Function Repository Resource:

RoundedAnnulus3D

Source Notebook

Represent a 3D annulus with rounded edges

Contributed by: Jaroslav Kysela

ResourceFunction["RoundedAnnulus3D"][{{x1,y1,z1},{x2,y2,z2}},{rinner,router}]

represents a 3D annulus around the line from {x1,y1,z1} to {x2,y2,z2} with rounded edges with inner radius rinner and outer radius router.

Details and Options

ResourceFunction["RoundedAnnulus3D"] can be used in Graphics3D.
Graphics rendering is affected by directives such as FaceForm, Specularity, Opacity and color.
ResourceFunction["RoundedAnnulus3D"][] is equivalent to ResourceFunction["RoundedAnnulus3D"][{{0,0,-1},{0,0,1}},{1/2,1}].
ResourceFunction["RoundedAnnulus3D"][r] is equivalent to ResourceFunction["RoundedAnnulus3D"][{{0,0,-1},{0,0,1}},{r/2,r}].
ResourceFunction["RoundedAnnulus3D"][{rinner,router}] is equivalent to ResourceFunction["RoundedAnnulus3D"][{{0,0,-1},{0,0,1}},{rinner,router}].
ResourceFunction["RoundedAnnulus3D"][{{x1,y1,z1},{x2,y2,z2}}] is equivalent to ResourceFunction["RoundedAnnulus3D"][{{x1,y1,z1},{x2,y2,z2}},{1/2,1}].
ResourceFunction["RoundedAnnulus3D"][{{x1,y1,z1},{x2,y2,z2}},r] is equivalent to ResourceFunction["RoundedAnnulus3D"][{{x1,y1,z1},{x2,y2,z2}},{r/2,r}].
The following options can be given:
RoundingRadius{0.1,0.1}the radii of rounded edges
The RoundingRadius setting can have the following forms:
ruse r for both the inner and the outer radius
{rin,rout}separate setting for both radii
ResourceFunction["RoundedAnnulus3D"] allows 0rinnerrouter.

Examples

Basic Examples (3) 

A unit radius and two units height 3D annulus:

In[1]:=
Graphics3D[ResourceFunction["RoundedAnnulus3D"][]]
Out[1]=

A 3D annulus from the origin to {1,-1,1} with inner radius 1/2:

In[2]:=
Graphics3D[
 ResourceFunction[
  "RoundedAnnulus3D"][{{0, 0, 0}, {1, -1, 1}}, {1/2, 1}]]
Out[2]=

Differently styled annuli:

In[3]:=
{Graphics3D[{Blue, ResourceFunction["RoundedAnnulus3D"][]}], Graphics3D[{Opacity[.5], ResourceFunction["RoundedAnnulus3D"][]}], Graphics3D[{Specularity[5], ResourceFunction["RoundedAnnulus3D"][]}]}
Out[3]=

Scope (10) 

Specification (5) 

Specify radii:

In[4]:=
Graphics3D[{Red, ResourceFunction["RoundedAnnulus3D"][1], Green, ResourceFunction["RoundedAnnulus3D"][3], Blue, ResourceFunction["RoundedAnnulus3D"][7]}]
Out[4]=

Specify centers:

In[5]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/197e9c08-bdc3-46e5-ba0e-99e8eb4c9c0a"]
Out[5]=

Annuli with different directions:

In[6]:=
Graphics3D[{ResourceFunction[
   "RoundedAnnulus3D"][{{0, 0, 0}, {1, 0, 0}}], ResourceFunction["RoundedAnnulus3D"][{{1, 1, 1}, {2, 3, 1}}]}]
Out[6]=

Specify position, direction, as well as inner and outer radii:

In[7]:=
Graphics3D[{ResourceFunction[
   "RoundedAnnulus3D"][{{-1, -2, 0}, {1, -1, 3}}, {0.5, 0.8}]}]
Out[7]=

Short form for a 3D annulus centered at the origin with a radius 1:

In[8]:=
Graphics3D[ResourceFunction["RoundedAnnulus3D"][], Axes -> True]
Out[8]=

Styling (5) 

Color directives specify the face color of each annulus:

In[9]:=
Table[Graphics3D[{c, ResourceFunction["RoundedAnnulus3D"][]}], {c, {Red, Green, Blue, Yellow}}]
Out[9]=

FaceForm can be used to specify the styles of the interiors as well as exteriors:

In[10]:=
Graphics3D[{FaceForm[Pink], ResourceFunction["RoundedAnnulus3D"][]}]
Out[10]=

Different properties can be specified for the front and back faces using FaceForm:

In[11]:=
Graphics3D[{FaceForm[Yellow, Blue], ResourceFunction["RoundedAnnulus3D"][]}, PlotRange -> {{-1, 1}, {-.8, 1}, {-1, 1}}]
Out[11]=

Opacity specifies the face opacity:

In[12]:=
Table[Graphics3D[{Opacity[o], ResourceFunction["RoundedAnnulus3D"][]}], {o, {0.3, 0.5, 0.9}}]
Out[12]=

Decompose the annulus into its components and apply different styling to each:

In[13]:=
{baseL, baseH, circumIn, circumOut, bevelLOut, bevelHOut, bevelLIn, bevelHIn} = Rest@ResourceFunction[
    "RoundedAnnulus3D"][{{0, 0, 0}, {0, 0, 1}}, {0.5, 1.1}, RoundingRadius -> .1];
In[14]:=
Graphics3D[{EdgeForm[], {Opacity[.7, Orange], baseL, baseH}, {Opacity[.7, Purple], circumOut}, Green, circumIn, Yellow, bevelLOut, bevelHOut, bevelLIn, bevelHIn}]
Out[14]=

Options (2) 

RoundingRadius (2) 

Adjust how rounded the edges are:

In[15]:=
Graphics3D[
   ResourceFunction[
    "RoundedAnnulus3D"][{{0, 0, 0}, {0, 5, 0}}, {1/2, 3}, RoundingRadius -> #], Boxed -> False] & /@ {.1, .5, 1}
Out[15]=

Adjust the inner and outer edges independently:

In[16]:=
{Graphics3D[
  ResourceFunction[
   "RoundedAnnulus3D"][{{0, 0, 0}, {0, 5, 0}}, {1/2, 3}, RoundingRadius -> {0.1, 1.7}], Boxed -> False], Graphics3D[
  ResourceFunction[
   "RoundedAnnulus3D"][{{0, 0, 0}, {0, 5, 0}}, {1/2, 3}, RoundingRadius -> {1.7, 0.1}], Boxed -> False]}
Out[16]=

Applications (2) 

Create a model of a wheel:

In[17]:=
(* Evaluate this cell to get the example input *) CloudGet["https://www.wolframcloud.com/obj/e39205d0-8429-4b9d-8fb7-8324478cf52e"]
Out[19]=

Use it to create a model of a chassis:

In[20]:=
wheelbase = 5;
track = 4;
pts = With[{wba = 0.4 wheelbase/2, wbb = 0.6 wheelbase/2, wbc = 1.2 wheelbase/2, tra = track/2, trb = 0.6 track/2, dz = 0.3,
     zpos = -.4},
   {{{-wba, -tra, zpos}, {wba, -tra, zpos}, {wba, tra, zpos}, {-wba, tra, zpos}}, {{wbb, -trb, dz + zpos}, {wbc, -trb, dz + zpos}, {wbc, trb, dz + zpos}, {wbb, trb, dz + zpos}}, {{wba, -tra, zpos}, {wbb, -trb, dz + zpos}, {wbb, trb, dz + zpos}, {wba, tra, zpos}}, {{-wba, tra, zpos}, {-wbb, trb, dz + zpos}, {-wbb, -trb, dz + zpos}, {-wba, -tra, zpos}}, {{-wbb, trb, dz + zpos}, {-wbc, trb, dz + zpos}, {-wbc, -trb, dz + zpos}, {-wbb, -trb, dz + zpos}}}];
chassis = Table[GraphicsComplex[
    Join[p, TranslationTransform[{0, 0, 0.3}] /@ p], {Polyhedron[{{4, 3, 2, 1}, {5, 6, 7, 8}, {1, 2, 6, 5}, {2, 3, 7, 6}, {3, 4, 8, 7}, {5, 8, 4, 1}}]}], {p, pts}];
axles = Translate[
   Cylinder[{{0, -1.25 track/2, 0}, {0, 1.25 track/2, 0}}, 0.1], {{-wheelbase/2, 0, 0}, {wheelbase/2, 0, 0}}];
wheels = Translate[
   wheel, {{-wheelbase/2, -track/2, 0}, {-wheelbase/2, track/2, 0}, {wheelbase/2, -track/2, 0}, {wheelbase/2, track/2, 0}}];
Graphics3D[{EdgeForm[], Brown, chassis, axles, wheels}, Lighting -> "Neutral", ImageSize -> Large]
Out[26]=

Properties and Relations (4) 

RoundedAnnulus3D is a 3D generalization of Annulus in 2D:

In[27]:=
Graphics[Annulus[]]
Out[27]=

The resource function RoundedCylinder effectively corresponds to RoundedAnnulus3D with zero inner radius:

In[28]:=
Graphics3D[ResourceFunction["RoundedCylinder"][]]
Out[28]=

PieChart3D or SectorChart3D can be used to create 3D rounded annuli:

In[29]:=
PieChart3D[{1}, ChartElementFunction -> ChartElementDataFunction["ProfileSector3D", "Profile" -> 8], SectorOrigin -> {{0, 1}, 0.7}]
Out[29]=

Get the graphical primitive from PieChart3D:

In[30]:=
ann3D[{zposLow_, zposHigh_}, {rIn_, rOut_}, prof_] := ChartElementDataFunction["ProfileSector3D", "Profile" -> prof][{{0, 2 Pi}, {rIn, rOut}, {zposLow, zposHigh}}, 1]
In[31]:=
Graphics3D[{EdgeForm[], ann3D[{0, 1}, {0.5, 1.1}, 4]}, Axes -> True]
Out[31]=

Compare with RoundedAnnulus3D:

In[32]:=
Graphics3D[
 ResourceFunction[
  "RoundedAnnulus3D"][{{0, 0, 0}, {0, 0, 1}}, {0.5, 1.1}, RoundingRadius -> .1], Axes -> True]
Out[32]=

Despite being seemingly the same, the two annuli have a very different internal structure:

In[33]:=
{
 Graphics3D[{EdgeForm[Thick], ann3D[{0, 1}, {0.5, 1.1}, 5]}, Axes -> True, ImageSize -> Medium],
 Graphics3D[
  ResourceFunction[
    "RoundedAnnulus3D"][{{0, 0, 0}, {0, 0, 1}}, {0.5, 1.1}, RoundingRadius -> .1] /. x_EdgeForm :> EdgeForm[Thick], Axes -> True, ImageSize -> Medium]
 }
Out[33]=

Possible Issues (5) 

When the two endpoints coincide, no annulus is created:

In[34]:=
Graphics3D[
 ResourceFunction["RoundedAnnulus3D"][{{0, 0, 0}, {0, 0, 0}}]]
Out[34]=

Radii are assumed to be non-negative real numbers:

In[35]:=
Graphics3D[
 ResourceFunction["RoundedAnnulus3D"][{{0, 0, 0}, {1, 0, 0}}, {r, 1}]]
Out[35]=

When the inner radius exceeds the outer one, a warning is issued and artifacts appear:

In[36]:=
Graphics3D[
 ResourceFunction[
  "RoundedAnnulus3D"][{{0, 0, 0}, {1, 0, 0}}, {.2, .1}]]
Out[36]=

When rounding radii exceed the height of the annulus, a warning is issued and artifacts appear:

In[37]:=
Graphics3D[
 ResourceFunction["RoundedAnnulus3D"][{{0, 0, 0}, {1, 0, 0}}, {1, 3}, RoundingRadius -> {1, 1}]]
Out[37]=

When the sum of rounding radii exceeds the thickness of the annulus, a warning is issued and artifacts appear:

In[38]:=
Graphics3D[
 ResourceFunction["RoundedAnnulus3D"][{{0, 0, 0}, {2, 0, 0}}, {1, 2}, RoundingRadius -> {1, 1}]]
Out[38]=

Neat Examples (4) 

Random unit annuli:

In[39]:=
Graphics3D[
 Table[{EdgeForm[Opacity[.3]], Hue[RandomReal[]], ResourceFunction["RoundedAnnulus3D"][
    RandomReal[10, {2, 3}], {1/2, 1}]}, {20}]]
Out[39]=

Concentric annuli:

In[40]:=
Graphics3D[{Table[{Hue[RandomReal[]], ResourceFunction["RoundedAnnulus3D"][6 + {z , z + 3}, RoundingRadius -> 1]}, {z, 1, 20, 5}]}]
Out[40]=

Use the degenerate radius specification to create a spool-like object:

In[41]:=
Graphics3D[{Orange, Quiet@ResourceFunction[
    "RoundedAnnulus3D"][{{0, 0, 0}, {2, 0, 0}}, {1.1, 1}, RoundingRadius -> .15]}]
Out[41]=

Create a model of a Roman amphitheater:

In[42]:=
stadium = Table[ResourceFunction["RoundedAnnulus3D"][{{0, 0, 0}, {0, 0, z}}, 5 + {1 z + 1 , 1 z + 4}], {z, Subdivide[0.2, 3, 8]}];
Graphics3D[{Lighter@Gray, Scale[stadium, {0.8, 1, 1}]}, ImageSize -> Large, Lighting -> "Neutral", Boxed -> False]
Out[4]=

Publisher

Jaroslav Kysela

Version History

  • 1.0.0 – 11 January 2022

Related Resources

Author Notes

Currently, no annulus sectors defined by start and end angles (akin to Annulus functionality) are implemented. The same is true for the support of Scaled.

License Information