16
$\begingroup$

With Graphics3D[Sphere[{0, 0, 0}, 1]], I can render a uniform 3D sphere, but how can I render an ellipsoid? I would need to specify the rotation of the ellipsoid and the length of the main axes. The method should be reasonably fast to display around 100 of them at once.

$\endgroup$
4
  • $\begingroup$ related $\endgroup$
    – gpap
    Commented Oct 29, 2013 at 16:25
  • 2
    $\begingroup$ Look up GeometricTransformation $\endgroup$ Commented Oct 29, 2013 at 16:36
  • $\begingroup$ This uses ContourPlot3D: demonstrations.wolfram.com/Ellipsoid $\endgroup$
    – KAI
    Commented Oct 29, 2013 at 16:56
  • 1
    $\begingroup$ There is also an Ellipsoid function in the MultivariateStatistics package that I used here, but it acts cranky at times... $\endgroup$
    – rm -rf
    Commented Oct 29, 2013 at 23:12

5 Answers 5

16
$\begingroup$

You can modify this if you need to specify the rotation in different ways, etc. As Simon Woods has suggested, probably the best way is to use GeometricTransformation.

 ellipsoid[a_, b_, center_?VectorQ, rotation_, around_?VectorQ] := Fold[
           GeometricTransformation,
           Sphere[],
           {ScalingTransform[{a, b, b}],
            RotationTransform[rotation, around],
            TranslationTransform[center]}]

 ellipsoid @@@ Table[{x, x, 10 {x, x, x}, x, {x, x, x}} /. x :> RandomReal[]
                     , {111}] // Graphics3D // AbsoluteTiming
{0.347020,

enter image description here

$\endgroup$
5
  • 2
    $\begingroup$ I had a slight wtf moment at all the x's - nice way to generate the data. $\endgroup$ Commented Oct 29, 2013 at 21:15
  • $\begingroup$ @SimonWoods uff I was afraid I've missed something :) $\endgroup$
    – Kuba
    Commented Oct 29, 2013 at 21:21
  • 1
    $\begingroup$ You can compose the transforms with Dot instead of Fold: TranslationTransform[center].RotationTransform[rotation, around].ScalingTransform[{a, b, b}]. Very nice, +1! $\endgroup$
    – Michael E2
    Commented Oct 30, 2013 at 0:15
  • $\begingroup$ @MichaelE2 Thanks ;) and yes Dot looks clear and is about 3% faster than Fold on my pc. $\endgroup$
    – Kuba
    Commented Oct 30, 2013 at 3:17
  • $\begingroup$ Dot[] works, but Composition[] is the documented way to compose geometric transforms: GeometricTransformation[Sphere[], Composition[TranslationTransform[center], RotationTransform[rotation, around], ScalingTransform[{a, b, b}]]] $\endgroup$ Commented Jul 21, 2016 at 1:37
15
$\begingroup$

Using Sphere with Scale and Rotate works too:

Graphics3D[Rotate[Scale[Sphere[], {5, 4, 2}, {0, 0, 0}], 60 Degree, {1, 2, 1}]]

enter image description here

The first triple is the scaling in the x,y,and z coordinates, the second triple is the translation, and the third triple is the axis about which to rotate. To generate a number of random ellipses:

x := RandomReal[];
Show[Table[Graphics3D[Rotate[Scale[Sphere[], {x, x, x}, {x i/6, x i/6, x i/6}], 
                      x, {x, x, x}], Boxed -> False], {i, 25}]]

enter image description here

$\endgroup$
0
11
$\begingroup$

An alternative approach that generates explicit primitives instead of transformed ones uses the NURBS representation of a sphere, with all the appropriate transformations done to its control points to generate the ellipsoid:

myEllipsoid[dims : {_?Positive, _?Positive, _?Positive} : {1, 1, 1}, 
            center : (_?VectorQ) : {0, 0, 0}, 
            rot : {_, _?VectorQ} : {0, {1, 0, 0}}] := Block[{ctrlpts},
  ctrlpts = Composition[TranslationTransform[center], 
                        RotationTransform[Sequence @@ rot],
                        ScalingTransform[dims]] /@ 
            Outer[Append[#2 #1[[1]], #1[[2]]] &,
                  {{0, -1}, {1, -1}, {1, 1}, {0, 1}},
                  {{1, 0}, {1, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {1, -1}, {1, 0}}, 1];
            BSplineSurface[ctrlpts, SplineClosed -> True, SplineDegree -> 2, 
                           SplineKnots -> {{0, 0, 0, 1/2, 1, 1, 1},
                                           {0, 0, 0, 1/4, 1/2, 1/2, 3/4, 1, 1, 1}}, 
                           SplineWeights -> Outer[Times, {1, 1/2, 1/2, 1},
                                                  {1, 1/2, 1/2, 1, 1/2, 1/2, 1}]]]

Here's an example:

randomEllipsoid := myEllipsoid[RandomReal[1, 3], RandomReal[{-2, 2}, 3],
                               {RandomReal[{-π, π}], 
                                Normalize[RandomVariate[NormalDistribution[], 3]]}]

BlockRandom[SeedRandom[42, Method -> "Legacy"]; 
            Graphics3D[Table[{ColorData[61, RandomInteger[{1, 9}]], randomEllipsoid},
                             {50}], Boxed -> False, Lighting -> "Neutral"]]

some ellipsoids

$\endgroup$
9
$\begingroup$

Starting from version 10 there is documented Ellipsoid which is reasonably fast

Graphics3D[Ellipsoid @@@ RandomReal[1, {100, 2, 3}]]

enter image description here

For an arbitrary orientation you specify the weight matrix Σ as a second argument

randomEllipsoid[] := Module[{ℛ, \[ScriptCapitalS], p},
  ℛ = First@QRDecomposition@RandomReal[NormalDistribution[], {3, 3}];
  \[ScriptCapitalS] = DiagonalMatrix@RandomReal[1, 3];
  p = RandomReal[10, 3];
  Ellipsoid[p, ℛ\[Transpose].\[ScriptCapitalS].ℛ]]

Graphics3D[Table[randomEllipsoid[], {100}]]

enter image description here

Here and \[ScriptCapitalS] are random rotation matrix and random scale matrix respectively.

$\endgroup$
7
  • $\begingroup$ Its only limitation is that it can only generate axis-aligned ellipsoids; Rotate[] is still needed for the arbitrary orientation. $\endgroup$ Commented Nov 17, 2015 at 14:51
  • $\begingroup$ @J.M. What about Graphics3D[Ellipsoid[{0, 0, 0}, {{5, 2, 3}, {2, 3, 2}, {3, 2, 5}}]]? :) $\endgroup$
    – ybeltukov
    Commented Nov 17, 2015 at 14:54
  • $\begingroup$ Ah, missed that. :D One still has to recognize the SVD for this. Anyway: First @ QRDecomposition @ RandomReal[NormalDistribution[], {3, 3}] is more compactly done as Orthogonalize[RandomReal[NormalDistribution[], {3, 3}]]. $\endgroup$ Commented Nov 17, 2015 at 15:09
  • $\begingroup$ @J.M. Sure, it is just a habit because it is faster for big matrices. $\endgroup$
    – ybeltukov
    Commented Nov 17, 2015 at 15:31
  • $\begingroup$ That's funny… maybe it's worth a question? $\endgroup$ Commented Nov 17, 2015 at 15:33
0
$\begingroup$

Thought I would add after looking at this quite a bit later. The numbers you use to generate the random ellipsoid orientation are not truly random. You are missing a factor of $\pi/2$ in the 4th argument in the table.

When generating the table, use this instead to get truly random ellipsoids:

 ellipsoid @@@ Table[{x, x, 10 {x, x, x}, pi/2*x, {x, x, x}} /. x :> RandomReal[]
                     , {111}] // Graphics3D // AbsoluteTiming

All I added was a factor of $\pi$ in the 4th argument of ellipsoid in the table being generated. This will give you random radian values from $0$ to $\pi/2$.

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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