# How to plot a quarter disk with specified height?

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. 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]

• Actually, I think using Cylinder would be better than doing it parameterically, I suppose. If I can do quarter cylinders.. – user129412 Jun 6 '15 at 14:07
• 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. – user129412 Jun 6 '15 at 14:43
• 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. – Jack LaVigne Jun 6 '15 at 14:53
• 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. – Jack LaVigne Jun 6 '15 at 14:57
• Ah, stupid, thanks. Still, it doesn't fill all the way to the origin sadly. – user129412 Jun 6 '15 at 15:00

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: 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]] ### 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]
] Unfortunately, this has the problem of being rather slow, so possibly something better with only Graphics3D can be realized.

• Very interesting, I'll have a look at this! – user129412 Jun 6 '15 at 14:51
• @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. – glS Jun 6 '15 at 14:57
• 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! – user129412 Jun 6 '15 at 14:58
• @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]] – glS Jun 6 '15 at 15:19
• @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. – glS Jun 7 '15 at 6:24
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}] ## 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] 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] 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] 