Ellipse

An ellipse is a specific instance of a conic section.

class conics.Ellipse(center, major_minor, alpha)[source]

Initializes the ellipse using its geometric representation.

Parameters:
  • center (array_like, (2, )) – The center of the ellipse.

  • major_minor (array_like, (2, )) – The size of the semi-major and semi-minor axes.

  • alpha (float) – The orientation angle in radians.

property area

Compute the area of this ellipse.

contact(pts)[source]

Computes the orthogonal points on the ellipse given some 2-D points.

Orthogonal (contact) points are points on the ellipse closest to those passed.

Parameters:

pts (array_like) – The 2-D points whose closest (orthogonal) points on the ellipse should be determined.

Returns:

contact_pts – The orthogonal points on the ellipse.

Return type:

numpy.ndarray

static from_conic(C)[source]

Constructs an ellipse from the specified conic.

refine(pts)[source]

Refine the ellipse non-linearly by minimizing the orthogonal distances.

The method uses the approach introduced by Ahn et al. [ARW01].

The analytic Jacobian used by the underlying least-squares solve is cross-checked symbolically and numerically in scripts/derive_refine_jacobian.py.

Parameters:

pts (array_like) – The 2-D points whose closest (orthogonal) points on the ellipse should be determined.

Returns:

The refine ellipse.

Return type:

Ellipse

segment_area(line)[source]

Computes the area of the region obtained as a result of intersecting the ellipse with a line.

This ellipse’s normalized homogeneous conic \(C\) (see to_conic()) evaluates to exactly \(-1\) at its own center in homogeneous coordinates, \(\vec c=(c_x,c_y,1)^\top\), i.e. \(\vec c^\top C \vec c=-1\), and is negative everywhere else inside the ellipse. Writing points in homogeneous coordinates as \(\vec p=(x,y,1)^\top\) as well, this function computes the area of the set \(\{ \vec p : \vec p^\top \vec l < 0 \land \vec p^\top C \vec p < 0 \}\).

If the line does not intersect or is tangent to the ellipse, then either zero or the full ellipse area is returned. If the line is degenerate, having no direction (\(\vec l=(0,0,d)^\top\)), the sign of \(d\) alone decides between the same two outcomes.

The area is computed by mapping the ellipse to the unit circle through the affine transform that rotates into the ellipse-local frame and scales each axis by the corresponding semi-axis length. This transform has constant Jacobian determinant \(\text{major} \cdot\text{minor}\), so any area computed in the transformed (unit circle) space scales back to the ellipse by that factor. The line maps to another line under this transform, at some perpendicular distance \(h\) from the origin (in units of the unit circle’s radius).

For \(h<1\) the cap it cuts off on the side not containing the origin can be rotated, without changing its area, so that the cutting line becomes the vertical line \(x=h\). The cap area then follows by integrating the circle’s cross-sectional width over \(x\in[h,1]\):

\[\int_h^1 2\sqrt{1-x^2}\,dx = \arccos h-h\sqrt{1-h^2} \enspace,\]

from which the requested half-plane area follows directly depending on which side of the line the origin (the ellipse center) falls on.

\(\arccos h\) is evaluated as \(\operatorname{atan2}(s, h)\) with \(s=\sqrt{1-h^2}\), and \(s\) itself is computed from the factored product \((1-h)(1+h)\) rather than \(1-h^2\). Squaring \(h\) first and then subtracting from 1 cancels leading digits once \(h\) approaches 1 (a near-tangent line), and can even drive the argument of the square root slightly negative. The factored form halves that cancellation and stays nonnegative.

The integral derivation above, the \(\operatorname{atan2}\) rewrite, and the affine scaling by \(\text{major}\cdot\text{minor}\) are all cross-checked symbolically and numerically in scripts/derive_segment_area.py.

Parameters:

line (array_like (3,)) – A homogeneous line cutting the ellipse into the two regions this method chooses between.

Returns:

area – The area of the intersection of the interior of this ellipse and the negative half plane of line. This value is nonnegative and bounded by the total ellipse area.

Return type:

float

to_conic()[source]

Constructs a Conic from the current Ellipse instance.