# How to render a 3D ellipsoid with Graphics3D?

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.

-
related – gpap Oct 29 '13 at 16:25
Look up GeometricTransformation – Simon Woods Oct 29 '13 at 16:36
This uses ContourPlot3D: demonstrations.wolfram.com/Ellipsoid – KAI Oct 29 '13 at 16:56
There is also an Ellipsoid function in the MultivariateStatistics package that I used here, but it acts cranky at times... – R. M. Oct 29 '13 at 23:12

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,

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

Using Sphere with Scale and Rotate works too:

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

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

-

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

-

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

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

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

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

-
Its only limitation is that it can only generate axis-aligned ellipsoids; Rotate[] is still needed for the arbitrary orientation. – J. M. Nov 17 '15 at 14:51
@J.M. What about Graphics3D[Ellipsoid[{0, 0, 0}, {{5, 2, 3}, {2, 3, 2}, {3, 2, 5}}]]? :) – ybeltukov Nov 17 '15 at 14:54
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}]]. – J. M. Nov 17 '15 at 15:09
@J.M. Sure, it is just a habit because it is faster for big matrices. – ybeltukov Nov 17 '15 at 15:31
That's funny… maybe it's worth a question? – J. M. Nov 17 '15 at 15:33

Thought I would add after looking at this quite a bit later. The numbers you use to generate the random ellipsoid orientation is 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.

-