Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

There is no Circle or Disk object in 3D. I quickly found a way to use Cylinder (thin lines, no faces, very flat):

Module[{s},
Graphics3D[{EdgeForm[Thickness[Small]], FaceForm[None], 
  Cylinder[{s = {1/2, 1/2, 1/2}, s + {0, 1/1000, -2/1000}}, 1/2]}, 
  Axes -> True, AxesLabel -> {"x", "y", "z"}, 
  PlotRange -> {{0, 1}, {0, 1}, {0, 1}}]]

3D circle

But

  • orientation of the cylinder is tricky,
  • choice of coordinate shift is dependent on graphics size and magnification. I have to take into account the parameters of relative thickness,
  • it requires me to make a few auxiliary functions (without speaking for instance if I want to define a circle by center, radius and angles to the axis, or by three points)
  • I cannot only draw an arc between 2 angle positions nor make it elliptical.

If I want all this, am I forced to recreate the wheel and construct computationally a 3D polygon approximating an ellipse ?

share|improve this question
1  
I'm surprised Cylinder[] does not degenerate gracefully if the endpoints given to it are identical. For a circle arc in 3D, I don't think there's a built-in function for that. Note that you can use ScalingTransform[] on your circles to yield ellipses when needed. –  J. M. Jun 7 '12 at 16:05
1  
What would your preferred input for your arc be? There are many ways to parametrize... –  Yves Klett Jun 7 '12 at 17:20
1  
@Yves Klett : thanks for your concern and your interesting answer. In fact I asked the question mainly to know if it had been done before, if there was a standard package with this kind of things (an ellipse primitive in 3D). I am able to create the various required parametrizations myself in Mathematica. –  ogerard Jun 8 '12 at 5:29
1  
Highly relevant: mathematica.stackexchange.com/questions/10957/… –  Sjoerd C. de Vries Sep 14 '13 at 7:10
add comment

5 Answers

up vote 9 down vote accepted

One way to go about drawing a circular arc defined by three points (adjust for ellipses):

{a, b, m} = {{1, 0, 0}, {-1, 1, 2}, {1, 1, 1}};

{a, b, m} = {{1, 0, 0}, {-1, 1, 2}, {1, 1, 1}};

    Arc3D[{a_, b_, m_}, n_: 60, prim_: Line] := 
      Module[{\[Alpha], lab, axis, aarc, tm, alpha},
        lab = m + Norm[a - m]*Normalize[b - m];
        axis = (a - m)\[Cross](b - m);
        aarc = (VectorAngle[a - m, b - m]);
        tm = RotationMatrix[alpha, axis];
        prim@Table[m + tm.(a - m), {alpha, 0, aarc, aarc/n}]
        ]

    Graphics3D[{PointSize[Large], Line[{m, a}], Line[{m, b}], 
        Point[{a, b, m}], Arc3D[{a, b, m}, 20]}]

Mathematica graphics

This only draws arcs up to $\pi$. I´ll try to elaborate once your specs become a bit clearer (esp. what your preferred input would look like).

share|improve this answer
    
As a note: three points determine a circle, but one needs five points to determine an ellipse. –  J. M. Jun 7 '12 at 16:42
    
@J.M. thusly "circular arc"... never needed a 3D ellipse before ;-) –  Yves Klett Jun 7 '12 at 16:45
    
Sure. :) It's more of a general reminder for everybody than anything. –  J. M. Jun 7 '12 at 16:49
    
@J.M. : another reminder is that the five points must be coplanar :-) –  ogerard Jun 8 '12 at 5:34
    
@Yves Klett : as it is already, your code will be quite useful to me. –  ogerard Jun 8 '12 at 5:37
add comment

You may try

Graphics3D[{FaceForm[None], Cylinder[{{0, 0, 0}, {1, 1, 1}/1000}, 2]}]

for a circle. With a color instead of FaceForm you get a disk

Graphics3D[{Red, Cylinder[{{0, 0, 0}, {1, 1, 1}/1000}, 2]}]

Another way is to use e.g. ParametricPlot3D and applying some transformations as J.M. suggested in his comment.

share|improve this answer
add comment

Here is something I have used before to make plots of polarization states in vector fields. It uses the Cylinder primitve and does geometric transformations on it:

pacman[{θ1_, θ2_}, scale_, thickness_, capStyle_, 
  wedgeStyle_] := {{capStyle, 
   RevolutionPlot3D[
     thickness, {t, 0, scale}, {θ, θ1, θ2}, 
     Mesh -> False][[1]],
   RevolutionPlot3D[-thickness, {t, 0, 
      scale}, {θ, θ1, θ2}, Mesh -> False][[1]]},
  RevolutionPlot3D[{scale, t}, {t, -thickness, 
     thickness}, {θ, θ1, θ2}, Mesh -> False][[1]],
  {wedgeStyle, 
   Polygon[{{0, 0, -thickness}, {scale Cos[θ1], 
      scale Sin[θ1], -thickness}, {scale Cos[θ1], 
      scale Sin[θ1], thickness}, {0, 0, 
      thickness}, {scale Cos[θ2], scale Sin[θ2], 
      thickness}, {scale Cos[θ2], 
      scale Sin[θ2], -thickness}}]}}

ellipse3D[abrList_, wedgeList_: {{0, 2 π}}, scale_: .1, 
  thickness_: .01, capStyle_: {}, wedgeStyle_: {}] :=
 {EdgeForm[],
  MapThread[GeometricTransformation[{
      pacman[#2, scale, thickness, capStyle, wedgeStyle]
      },
     AffineTransform[{
       Transpose[
        Append[Most[#], Normalize[Cross @@ Most[#]]]], Last[#]}
      ]] &,
   {abrList, PadRight[wedgeList, Length[abrList], Last[wedgeList]]}]}

Edit

In the above code, I added the ability to draw a filled "arc" of an ellipse, more commonly known as a squished Pacman. The examples below stay the same if you don't specify a pair of angles for the wedge in the ellipse. I'll add an example with a wedge opening below.

Graphics3D[{
  Red,
  ellipse3D[{
    {
     (* Axes a, b, position r: *)
     {1, 0, 0}, {0, .5, 0}, {0, 0, 0}
     }
    }
   ]
  }]

ellipse3d

The function ellipse3D takes a list of points as its argument, so that I can plot more than a single ellipse at a time. Each element of the list consists of a three entries:

{a, b, r}

where a and b are three-dimensional vectors pointing in the direction of the semi-major and semi-minor axes. Their length determines the eccentricity of the ellipse. If a and b aren't perpendicular to each other, you can also produce a skewed ellipse. The third vector r is the position at which the ellipse is centered.

The optional arguments scale and thickness determine the overall size of the object. The lengths given by a and b are multiplied by scale before plotting, and the z height of the cylinder which represents the ellipse in 3D is given by thickness.

Here is another example that shows how to apply it with a list of ellipses:

Graphics3D[{
  Magenta,
  ellipse3D[{
    {
     (* First ellipse; axes a, b, 
     position r: *)
     {1/Sqrt[2], 1/Sqrt[2], 0}, {0, .5, 0}, {0, 0,
       0}
     },
    {
     (* Second ellipse; axes a, b, 
     position r: *)
     {.5, 1, .5}, {.25, .25, .5}, {1, 1, 1}
     },
    {
     (* Third ellipse; axes a, b, 
     position r: *)
     {-.5, .1, 1/Sqrt[2]}, {0, .5, 0}, {0, 1, 
      0.5}
     },
    {
     (* Circle: *)
     {1, 0, 1}, {0, 1, 0}, {.5, 1, 0}
     }
    }]
  }, ViewPoint -> Top]

more ellipses

Here is an ellipse with a wedge:

Graphics3D[{
  Red,
  ellipse3D[{
    {
     (* Axes a, b, position r: *)
     {1, 0, 0}, {0, .5, 0}, {0, 0, 0}
     }
    }
   , {{0, 5}}
   ]
  }]

wedge

The second argument (wedgeList) of ellipse3D now was specified as a list of angle pairs - one for each ellipse to be drawn. If there is only a single element, all subsequent ellipses specified by the first argument (abrList) are drawn with the same angle spans.

Edit 2

In order to also be able to draw open ellipse arcs I added two further arguments to the function, specifying the style in which the different faces of the ellipse are rendered. For the top and bottom faces, the style is in the variable capStyle (with the default value capStyle = {} cap style is taken from the enclosing graphics). The sides of the wedge can be styled with the last argument, wedgeStyle. To suppress any of these, use FaceForm[].

For example, here is a hollow pacman:

Graphics3D[{
  Red,
  ellipse3D[{
    {
     (* Axes a, b, position r: *)
     {1, 0, 0}, {0, .5, 0}, {0, 0, 0}
     }
    }
   , {{0, 5}}, .1, .01, FaceForm[], Directive[Opacity[.5], Blue]
   ]
  }]

hollowpacman

As an application example, I'll just show a more complicated plot made with this kind of function. It requires too many additional definitions to put into this answer, but you can get a better impression of how 3D ellipses can be really useful:

sphericalHarmonic

share|improve this answer
add comment

What about using the graphics primitive that can be extracted from ParametricPlot?

arc = ParametricPlot[{2 Cos[t], Sin[t]}, {t, 0, Pi}, 
    Axes -> None][[1, 1, 3, 2, 1]];

We then add a constant value for the third dimension:

zeros = Table[0, {Length[arc]}];
arc3D = Partition[Flatten[Transpose[{arc, zeros}]], 3];

We can then use this as a 3D graphics primitive:

Graphics3D[
 GeometricTransformation[
  Line[arc3D], {RotationMatrix[45 Degree, {1, 0, 0}], {0, 0, 1}}], 
 AspectRatio -> 1, SphericalRegion -> True, 
 PlotRange -> {{-3, 3}, {-3, 3}, {-3, 3}}]

arc

share|improve this answer
    
Nice reuse of existing Mathematica functions that can be applied to many other things. But indeed, the simplest would perhaps be to use ParametricPlot3D directly? –  ogerard Jun 8 '12 at 5:32
add comment

Another way to plot 3D ellipse would be

Scale[Cylinder[{{x, y, 0}, {x, y, 0.1}}, 1], {wx, wy, 1}]

where x, y gives the location and wx, wy give the length of major and minor axis.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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