3
$\begingroup$

How can I use Mathematica (version 9) to plot an ellipse, given the coordinates of its two foci and the length of its semimajor axis, where the major axis is not necessarily parallel to either the $x$-axis or the $y$-axis? I also need the scales of the two axes to be equal.

For example, the foci might be at $(3,2)$ and $(5,1)$ and the semimajor axis might be $1.7$.

The following gives an ellipse of the right size, shape, and centre, but wrong orientation:

Graphics[Circle[{4, 1.5}, {1.7, Sqrt[1.64]}]]
$\endgroup$
  • 4
    $\begingroup$ Is this a Mathematica question ? How would you do it outside Mathematica ? $\endgroup$ – Lotus Aug 27 '18 at 13:00
  • $\begingroup$ Welcome to Mathematica.SE. Are you sure you are posting on the right site? There is nothing in your question making it clear that it is concerned with Mathematica software. $\endgroup$ – m_goldberg Aug 27 '18 at 14:13
  • $\begingroup$ Edited to make clear. $\endgroup$ – ruffle Aug 27 '18 at 15:21
4
$\begingroup$

You can find a geometric solution to this problem by using an implicit region definition directly based on the definition of an ellipse: sum of distances from foci equals twice the semimajor axis.

With[{foci = {{3, 2}, {5, 1}}, semimajoraxis = 3/2},
 Region[ImplicitRegion[
   Sum[EuclideanDistance[{x, y}, p], {p, foci}] == 
    2 semimajoraxis, {x, y}],
  Axes -> True, Epilog -> {Red, Point[foci]}]]

ellipse

Geometric regions functionality was introduced in Mathematica 10. Similar things can be accomplished using RegionPlot on earlier versions, but it requires explicit plot range, which complicates the approach (basically here I define the plot range to be $\pm \mathtt{semimajoraxis}$ on $x$ and $y$ axes).

With[{foci = {{3, 2}, {5, 1}}, semimajoraxis = 3/2},
 RegionPlot[
  Sum[EuclideanDistance[{x, y}, p], {p, foci}] < 2 semimajoraxis, 
  Evaluate[Sequence @@ 
    MapThread[{#1, #2 - semimajoraxis, #2 + semimajoraxis} &, {{x, y},
       Mean[foci]}]],
  AspectRatio -> Automatic, PlotStyle -> None, 
  Epilog -> {Red, Point[foci]}]]

ellipse

I hope this works for you, since my v9 seems to nag about need for legacy Java. Does it work?

$\endgroup$
  • $\begingroup$ Many thanks for this. It's just what I need, but can it be made to work for Mma v9? $\endgroup$ – ruffle Aug 27 '18 at 15:29
  • $\begingroup$ @ruffle Oh my. Geometric regions functionality was introduced in v10. I'll add a RegionPlot variant which should work in v9 in a moment. $\endgroup$ – kirma Aug 27 '18 at 15:34
  • $\begingroup$ @ruffle Try again, does it work? $\endgroup$ – kirma Aug 27 '18 at 15:53
  • 1
    $\begingroup$ Yes, this works perfectly. Many thanks! $\endgroup$ – ruffle Aug 27 '18 at 16:33
3
$\begingroup$

I came across this (not so recent) question, and it occurs to me that the following code is simpler - assuming all you want is the plot:

foci = {{3, 2}, {5, 1}}; semimajoraxis = 3/2; 
Graphics[{Rotate[Circle[Mean[foci], {3/2, 1}], 
   VectorAngle[{1, 0}, foci[[1]] - Mean[foci]]], 
   {Red, 
   Point /@ {foci, Mean[foci]}}}, Axes -> True, 
   AxesOrigin -> {2.5, 0}] 

Tomas Garza

$\endgroup$
2
$\begingroup$
foci = {{3, 2}, {5, 1}};
a = 3/2;

{{x1, y1}, {x2, y2}} = foci;
d = EuclideanDistance @@ foci;

{ContourPlot[Sum[EuclideanDistance[{x, y}, p], {p, foci}] == 2 a, 
{x, 2.5, 5.5}, {y, 0.3, 2.7}, AspectRatio -> Automatic], 

 ParametricPlot[{(x1 + x2)/2, (y1 + y2)/2} + 
  {a/d (x2 - x1) Cos[t] + Sqrt[a^2/d^2 - 1/4] (y1 - y2) Sin[t], 
   a/d (y2 - y1) Cos[t] + Sqrt[a^2/d^2 - 1/4] (x2 - x1) Sin[t]}, 
   {t, 0, 2 Pi}]
}

enter image description here

$\endgroup$
2
$\begingroup$

I will note that one can use Ellipsoid[] for this:

With[{f1 = {3, 2}, f2 = {5, 1}, a = 17/10},
     With[{r = RotationMatrix[{{1, 0}, f2 - f1}]},
          Graphics[{Directive[EdgeForm[ColorData[97, 1]], FaceForm[]], 
                    Ellipsoid[(f1 + f2)/2, 
                              r.DiagonalMatrix[{a^2, a^2 - Norm[f1 - f2]^2/4}].Transpose[r]]},
                   Frame -> True]]]

ellipse


If one is dissatisfied with Ellipsoid[] (like in this answer), one could also fall back on the NURBS representation. Here is a routine for making the BSplineCurve[] equivalent of Ellipsoid[]:

makeEllipse[p_?VectorQ, m_?MatrixQ] := Module[{aff, eig},
    eig = Eigensystem[N[m]];
    aff = AffineTransform[{Transpose[eig[[2]]].DiagonalMatrix[Sqrt[eig[[1]]]], p}];
    BSplineCurve[aff[{{1, 0}, {1, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {1, -1}, {1, 0}}],
                 SplineClosed -> True, SplineDegree -> 2, 
                 SplineKnots -> {0, 0, 0, 1/4, 1/2, 1/2, 3/4, 1, 1, 1}, 
                 SplineWeights -> {1, 1/2, 1/2, 1, 1/2, 1/2, 1}]]

and now one can use makeEllipse[] as a replacement for Ellipsoid[] in the code given above.

$\endgroup$
1
$\begingroup$

You can use the "SplineCircle" resource function to specify the semimajor axis direction:

Graphics[
    {
    ResourceFunction["SplineCircle"][{4,1.4}, {1.7,Sqrt[1.64]}, {2,-1}],
    Red, Point[{{3,2}, {5,1}}]
    },
    Axes->True
]

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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