3
$\begingroup$

Kind of important: the solution posted does work, and answers the question in that sense. However, it is very slow, so a faster option would be much appreciated.

I'm trying to create the following image in Mathematica. enter image description here

I apologize for my terrible paint skills. The idea is that I have a certain vector, say $({0,-\sqrt{0.25},\sqrt{0.5},-\sqrt0.25})$ (it's a unit vector, apart from that the components can take any real value). Now, what I want is to plot a disk, where each quarter section corresponds to a value of the vector. So in the image I drew, the first component is 0, so that quarter is just a quarter circle in the z = 0 plane. Then the second component would have height $\sqrt{0.25}$ in the second quarter section of the disk, in the negative z direction, et cetera.

Now, to be honest, I'm not sure where to start. I first thought I could possible use ParametricPlot3D, for example like

ParametricPlot3D[{ Cos[u], Sin[u], v}, {u, 0, 2 Pi/4}, {v, -0.5, 0}, 
 Mesh -> None] 

However, this only draws the outer shell, and I'm not sure to fill it up. Nor am I sure that I can combine this with another 3 commands in order to get a full disk, but perhaps that is not too difficult. In any case, I was wondering if someone had an idea of how to do this, and if I'm taking the right approach.

To extend a little on this, I tried combining them like this but it doesn't seem to work

p1 = ParametricPlot3D[{ Cos[u], Sin[u], v}, {u, 0, 2 Pi/4}, {v, -0.5, 
    0}, Mesh -> None, PlotStyle -> Opacity[.5]];
p2 = ParametricPlot3D[{ Cos[u], Sin[u], v}, {u, 2 Pi/4, 2 Pi/2}, {v, 
    0, Sqrt[0.5]}, Mesh -> None, PlotStyle -> LightBlue];
Show[p1, p2]

I can however do it in 2D, with circles. If only here was an easy way to plot sections of cylinders.

p1 = Graphics[{Blue, Disk[{0, 0}, 0, {0, 2 Pi/4}]}];
p2 = Graphics[{Red, Disk[{0, 0}, Sqrt[0.5], {2 Pi/4, 2 Pi/2}]}];
p3 = Graphics[{Blue, Disk[{0, 0}, 0.5, {Pi, 3/2*Pi}]}];
p4 = Graphics[{Red, Disk[{0, 0}, Sqrt[0.5], {3/2*Pi, 2 Pi/1}]}];
Show[p1, p2, p3, p4]
$\endgroup$
  • $\begingroup$ Actually, I think using Cylinder would be better than doing it parameterically, I suppose. If I can do quarter cylinders.. $\endgroup$ – user129412 Jun 6 '15 at 14:07
  • $\begingroup$ Also, I should note that I'm not looking at the option for just 4 cuboids arranged into a larger cuboid; I need to be able to do this for 3 or 5 components as well, so something with a variable angle is really needed. $\endgroup$ – user129412 Jun 6 '15 at 14:43
  • $\begingroup$ I thought Cylinder would be the way to go as well. But when I looked at the documentation I found that although Disk has a list of angles as an optional argument enabling one to plot a sector, Cylinder did not appear to have that option. $\endgroup$ – Jack LaVigne Jun 6 '15 at 14:53
  • 1
    $\begingroup$ Your example with Show[p1,p1] will work. You need to specify the PlotRange so that it all can be seen. Without an explicit PlotRange Show takes on the range of the first plot. Show[p1, p2, PlotRange -> {{-1, 1}, {-1, 1}, {-1, 1}} ] works fine. $\endgroup$ – Jack LaVigne Jun 6 '15 at 14:57
  • $\begingroup$ Ah, stupid, thanks. Still, it doesn't fill all the way to the origin sadly. $\endgroup$ – user129412 Jun 6 '15 at 15:00
4
$\begingroup$

You can create a rather fast function to create a section of a cylinder of a given height combining some ParametricPlot3D using the following code:

cylinderSection[h_, \[Theta]0_, \[Theta]1_, 
  OptionsPattern[plotStyle -> Green]] := With[{r = 1},
  Show[
   ParametricPlot3D[
    {{\[Rho] Cos[\[Theta]], \[Rho] Sin[\[Theta]], 0},
     {\[Rho] Cos[\[Theta]], \[Rho] Sin[\[Theta]], h}},
    {\[Rho], 0, r},
    {\[Theta], \[Theta]0, \[Theta]1},
    Mesh -> None,
    PlotStyle -> OptionValue@plotStyle
    ],
   ParametricPlot3D[
    {Cos[\[Theta]], Sin[\[Theta]], z},
    {\[Theta], \[Theta]0, \[Theta]1},
    {z, 0, h},
    Mesh -> None,
    PlotStyle -> OptionValue@plotStyle
    ],
   ParametricPlot3D[
    {{t Cos[\[Theta]0], t Sin[\[Theta]0], z},
     {t Cos[\[Theta]1], t Sin[\[Theta]1], z}},
    {t, 0, 1},
    {z, 0, h},
    Mesh -> None,
    PlotStyle -> OptionValue@plotStyle
    ],
   PlotRange -> All,
   RotationAction -> "Clip",
   ImageSize -> Large
   ]
  ]

This is called in exactly the same way as the solution with RegionPlot3D (see below):

Show[
 cylinderSection[0.001, 0, Pi/2, plotStyle -> Blue],
 cylinderSection[-Sqrt[0.25], Pi/2, Pi, plotStyle -> Green],
 cylinderSection[Sqrt[0.5], -Pi, -Pi/2, plotStyle -> Orange],
 cylinderSection[-Sqrt[0.25], -Pi/2, 0, plotStyle -> Red]
 ]

And this is the output:

enter image description here

You want the whole thing generated by only giving as input heights, angles and colors? Do it with the function makePie:

makePie[hh_List, angles_List, plotStyles_List] := Show[
  Append[
   Table[
    cylinderSection[hh[[i]] /. (0 -> 0.001), angles[[i]], 
     angles[[i + 1]], plotStyle -> plotStyles[[i]]],
    {i, Length@hh - 1}
    ],
   cylinderSection[hh[[Length@hh]] /. (0 -> 0.001), 
    angles[[Length@hh]], 2 Pi, plotStyle -> plotStyles[[Length@hh]]]
   ]
  ]

You can now generate the above pie with the following:

makePie[{0, -Sqrt[0.25], Sqrt[0.5], -Sqrt[0.25]}, {0, Pi/2, Pi, 
  3 Pi/2}, {Blue, Green, Orange, Red}]

But you can use it to generate pies with an arbitrary number of partitions, not just four. For fun, you can try this:

With[{n = RandomInteger@{3, 20}}, 
 makePie[RandomReal[{-2, 2}, n], Sort@RandomReal[{0, 2 Pi}, n], 
  RandomColor@n]]

enter image description here

The (slow) solution I originally found, using RegionPlot3D:

First create a function drawing an arbitrary section of a cylinder with

cylinderSection[h_, \[Theta]1_, \[Theta]2_, 
  OptionsPattern[plotStyle -> Red]] := RegionPlot3D[
  x^2 + y^2 < 1 &&
   \[Theta]1 < ArcTan[x, y] < \[Theta]2,
  {x, -1, 1},
  {y, -1, 1},
  {z, 0, h},
  Mesh -> None,
  PlotRange -> All,
  RotationAction -> "Clip",
  PlotStyle -> OptionValue@plotStyle,
  PlotPoints -> 100,
  ImageSize -> Large
  ]

Then combine it with Show to obtain the desired result.

Show[
 cylinderSection[0.001, 0, Pi/2, plotStyle -> Blue],
 cylinderSection[-Sqrt[0.25], Pi/2, Pi, plotStyle -> Green],
 cylinderSection[Sqrt[0.5], -Pi, -Pi/2, plotStyle -> Orange],
 cylinderSection[-Sqrt[0.25], -Pi/2, 0, plotStyle -> Red]
 ]

enter image description here

Unfortunately, this has the problem of being rather slow, so possibly something better with only Graphics3D can be realized.

$\endgroup$
  • $\begingroup$ Very interesting, I'll have a look at this! $\endgroup$ – user129412 Jun 6 '15 at 14:51
  • $\begingroup$ @user129412 I edited the code, the colors should work now. For the slowness you can lower the value of PlotPoints, but at the cost of output quality. $\endgroup$ – glS Jun 6 '15 at 14:57
  • $\begingroup$ I haven't tested it yet, but is there a specific reason for not making the empty quarter with your function too? As it seems to create some strange overlay effects with the other ones. I have to admit it does look quite good! $\endgroup$ – user129412 Jun 6 '15 at 14:58
  • 1
    $\begingroup$ @user129412 the opacity settings can be included in the PlotStyle option. The way I defined cylinderSection you can pass to PlotStyle whatever you want through plotStyle. For example to have the green region opaque you can use cylinderSection[-Sqrt[0.25], Pi/2, Pi, plotStyle -> Directive[Opacity[0.5], Green]] $\endgroup$ – glS Jun 6 '15 at 15:19
  • 1
    $\begingroup$ @user129412 I'm not sure how to fix that I'm afraid. But you could maybe ask how to fix that problem on a separate question, as it seems interesting enough. $\endgroup$ – glS Jun 7 '15 at 6:24
2
$\begingroup$
seg[{a_, b_}, {g_, h_}, col_, op_] := 
 Show[ParametricPlot3D[{Cos[t], Sin[t], z}, {t, a, b}, {z, g, h}, 
   Mesh -> False, PlotStyle -> {col, Opacity[op]}, 
   BoundaryStyle -> {Black, Thick}], 
  ParametricPlot3D[{u Cos[t], u Sin[t], g}, {t, a, b}, {u, 0, 1}, 
   Mesh -> False, PlotStyle -> {col, Opacity[op]}], 
  ParametricPlot3D[{u Cos[t], u Sin[t], h}, {t, a, b}, {u, 0, 1}, 
   Mesh -> False, PlotStyle -> {col, Opacity[op]}], 
  Graphics3D[{col, Opacity[op], EdgeForm[{Black, Thick}], 
      Polygon[{{0, 0, g}, {0, 0, h}, {Cos[#], Sin[#], h}, {Cos[#], 
         Sin[#], g}}]} & /@ {a, b}]]

Visualizing:

Manipulate[
 Show[seg[{0 + a, Pi/2}, {0, 1}, Red, opacity], 
  seg[{-Pi/2, Pi + a}, {-1, 0}, Blue, opacity],
  seg[{Pi + a, 3 Pi/2}, {-.01, 0}, Gray, opacity],
  PlotRange -> Table[{-2, 2}, {3}], Boxed -> False, Axes -> False, 
  Background -> White], {opacity, 0.3, 1}, {{a, 0}, -1, 1}]

enter image description here

$\endgroup$
0
$\begingroup$

ChartElementData["CylindricalSector3D"]

The built-in function ChartElementData["CylindricalSector3D"] takes two or more arguments. The first argument, {{angle0_, angle1_}, {radius0_, radius1_}, {height0_, height1_}} specifies the angles, radii and heights needed to specify a cylindrical sector. The second argument needs to be specified but can be anything for our application. We use this function to generate the graphics primitives in the following function:

cylindricalSectors[styles : {__}, specs : {__}, opts : OptionsPattern[]] := 
 Graphics3D[{#, EdgeForm[], ChartElementData["CylindricalSector3D"][#2, {}]} & @@@ 
   Transpose[{styles, specs}], opts, Axes -> False, Boxed -> False, Lighting -> "Neutral"]

Examples:

cylindricalSectors[{Red}, {{{Pi/2, Pi}, {0, 1}, {0, 1/2}}},  Axes -> True]

enter image description here

specs = {{{0, Pi/2}, {0, 2}, {0, 1}}, {{Pi/2, Pi}, {0, 2}, {0,  1}},
 {{Pi, 3 Pi/2}, {0, 2}, {0, 1}}, {{3 Pi/2, 2 Pi}, {0, 2}, {1, 1}}, 
 {{Pi/2, Pi}, {0, 2}, {1, 2}}};
colors = ColorData[54, "ColorList"][[;; 5]];

cylindricalSectors[colors, specs]

enter image description here

random = Transpose[{Sort /@ RandomReal[{0, 2 Pi}, {7, 2}],
     {0, #} & /@ RandomReal[{1, 3}, 7], Sort /@ RandomReal[{0, 10}, {7, 2}]}];
colors = ColorData["Rainbow"] /@ Range[1/7, 1, 1/7];
cylindricalSectors[Opacity[.7, #] & /@ colors, random]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.