Contents
raw book

A line segment between points \(A\) and \(B\) can be defined as

\[L(t) = A + (B-A)t = \left[\begin{array}{c}x(t)\\y(t)\end{array}\right]\forall t\in[0,1]\]

On the other hand, an axis aligned ellipse with its radii \(r_x\) and \(r_y\) can be seen as

\[\frac{x^2}{r_x^2} + \frac{y^2}{r_y^2}=1\]

When substituting the \(x\) and \(y\) coordinates of the line into the equation of the ellipse, we get

\[\begin{array}{rrl} & \frac{x^2(t)}{r_x^2} + \frac{y^2(t)}{r_y^2}&=1\\ \Leftrightarrow & \frac{(A_x + (B_x-A_x)t)^2}{r_x^2} + \frac{(A_y + (B_y-A_y)t)^2}{r_y^2}&=1\\ \Leftrightarrow & r_x^2(A_y + (B_y-A_y)t)^2+ r_y^2(A_x + (B_x-A_x)t)^2 &=r_x^2r_y^2\\ \Leftrightarrow & \underbrace{(r_x^2(B_y-A_y)^2+r_y^2(B_x-A_x)^2)}_{=a}t^2 + \underbrace{(2r_x^2A_y(B_y-A_y)+2r_y^2A_x(B_x-A_x))}_{=b}t + \underbrace{r_x^2A_y^2 + r_y^2A_x^2 -r_x^2r_y^2}_{=c} &=0\\ \end{array}\]

Now this is a quadratic equation in \(t\), which we can solve using

\[t = \frac{-b\pm\sqrt{b^2-4ac}}{2a}\]

If the discriminant \(D=b^2-4ac\) in the square root becomes negative, we can conclude, there is no solution. For \(D=0\), it is clear that only one solution is possible and for \(D>0\), we get two solutions. Now The resulting points are

\[P = A+(B-A)t\]

For the general case, that an ellipse is positioned at point \(C\) and is rotated by \(\theta\), we can transform the line segment into the ellipses space, by assuming the anchor points \(A\) and \(B\) we used previously were originally transformed with

\[A = \text{Rot}(-\theta) (A'-C)\\B = \text{Rot}(-\theta) (B'-C)\]

And after all calculations, we transform the resulting points \(P\) back to the original space:

\[P' = \text{Rot}(\theta)P + C\]

JavaScript Implementation

function EllipseLine(A, B, C, rx, ry, phi) {

    A = Vector2(A).sub(C).rotate(-phi);
    B = Vector2(B).sub(C).rotate(-phi);

    rx *= rx;
    ry *= ry;

    const ret = [];

    const v = Vector2.fromPoints(A, B);

    const a = rx * v.y * v.y + ry * v.x * v.x;
    const b = 2 * (rx * A.y * v.y + ry * A.x * v.x);
    const c = rx * A.y * A.y + ry * A.x * A.x - rx * ry;

    const D = b * b - 4 * a * c; // Discriminant

    if (D >= 0) {

        const sqrtD = Math.sqrt(D);
        const t1 = (-b + sqrtD) / (2 * a);
        const t2 = (-b - sqrtD) / (2 * a);

        if (0 <= t1 && t1 <= 1)
            ret.push(v.scale(t1).add(A).rotate(phi).add(C));

        if (0 <= t2 && t2 <= 1 && Math.abs(t1 - t2) > 1e-16)
            ret.push(v.scale(t2).add(A).rotate(phi).add(C));
    }
    return ret;
}