Contents
raw book

When describing a line-segment by two points \(\mathbf{A}=\left( \begin{array}{cc} A_x\\ A_y \end{array}\right)\) and \(\mathbf{B}=\left( \begin{array}{cc} B_x\\ B_y \end{array}\right)\), we can say that point \(\mathbf{P}=\left( \begin{array}{cc} x\\ y \end{array}\right)\) is somewhere on that line. The slope of the line \(\vec{\mathbf{AB}}\) and \(\vec{\mathbf{AP}}\) then is

\[\angle\vec{\mathbf{AB}} = \frac{A_y-B_y}{A_x-B_x}\]

\[\angle\vec{\mathbf{AP}} = \frac{y-A_y}{x-A_x}\]

Since the points \(\mathbf{A}, \mathbf{B}\) and \(\mathbf{P}\) are colinear, the slopes \(\angle\vec{\mathbf{AB}}\) and \(\angle\vec{\mathbf{AP}}\) are equal, and thus

\[\frac{A_y-B_y}{A_x-B_x}=\frac{y-A_y}{x-A_x}\]

which can then be rewritten to

\[\begin{array}{rrl} &(x-A_x)(A_y-B_y) &=(y-A_y)(A_x-B_x)\\ \Leftrightarrow& x(B_y-A_y)+y(A_x-B_x) &= A_x(B_y-A_y) + A_y(A_x-B_x)\\ \Leftrightarrow& \mathbf{v}\cdot \mathbf{P} &=d \end{array}\]

with the vector \(\mathbf{v}=(B_y-A_y, A_x-B_x)\).

On the other hand, a cubic Bezier curve with its control points \(\mathbf{C}_0, \mathbf{C}_1, \mathbf{C}_2\) and \(\mathbf{C}_3\) can be seen as

\[\mathbf{C}(t)= (1-t)^3\mathbf{C}_0+3(1-t)^2t\mathbf{C}_1+3(1-t)t^2\mathbf{C}_2+t^3\mathbf{C}_3 \;\forall t\in [0, 1]\]

Now substituting the line equation at our control points, yields

\[\mathbf{C}(t)= (1-t)^3(\mathbf{v}\cdot \mathbf{C}_0 - d)+3(1-t)^2t(\mathbf{v}\cdot \mathbf{C}_1 - d)+3(1-t)t^2(\mathbf{v}\cdot \mathbf{C}_2 - d)+t^3(\mathbf{v}\cdot \mathbf{C}_3 - d)\]

When rewriting the equation to a proper polynomial and setting the equation zero, we get

\[0= \mathbf{v}\cdot(-\mathbf{C}_0 + 3 \mathbf{C}_1 - 3 \mathbf{C}_2 + \mathbf{C}_3) t^3+ \mathbf{v}\cdot( 3 \mathbf{C}_0 - 6 \mathbf{C}_1 + 3 \mathbf{C}_2) t^2 + \mathbf{v}\cdot(- 3 \mathbf{C}_0 + 3 \mathbf{C}_1) t + \mathbf{v}\cdot\mathbf{C}_0 - d\]

This way the intersection problem becomes a root finding problem of a polynomial with degree 3.

Bezier Intersection JavaScript Implementation

Using Complex.js and the cubic root function, one can implement the line segment and bezier curve intersection like follows:

function lineBezier(A, B, C0, C1, C2, C3) {

    const res = [];

    const Ax = 3 * (C1.x - C2.x) + C3.x - C0.x;
    const Ay = 3 * (C1.y - C2.y) + C3.y - C0.y;
    
    const Bx = 3 * (C0.x - 2 * C1.x + C2.x);
    const By = 3 * (C0.y - 2 * C1.y + C2.y);
    
    const Cx = 3 * (C1.x - C0.x);
    const Cy = 3 * (C1.y - C0.y);

    const Dx = C0.x;
    const Dy = C0.y;

    const vx = B.y - A.y;
    const vy = A.x - B.x;

    const d = A.x * vx + A.y * vy;

    const roots = cubicRoots(
        vx * Ax + vy * Ay,
        vx * Bx + vy * By,
        vx * Cx + vy * Cy,
        vx * Dx + vy * Dy - d
    );

    for (let {re, im} of roots) {
        if (0 > re || re > 1 || Math.abs(im) > 1e-5) continue;
        res.push({
            x: ((Ax * re + Bx) * re + Cx) * re + Dx,
            y: ((Ay * re + By) * re + Cy) * re + Dy
        });
    }
    return res;
}