raw math

Given a line segment from point A\mathbf{A} to point B\mathbf{B}, what is the shortest distance to a point P\mathbf{P}?

θ\theta
b\mathbf{b}
a\mathbf{a}
A\mathbf{A}
B\mathbf{B}
P\mathbf{P}
tt

Above the line itself, the shortest distance is the length from point P\mathbf{P} to the point orthogonal on the line, everywhere else the shortest distance is between point P\mathbf{P} and A\mathbf{A} or B\mathbf{B} respectively. Now the Scalar Projection tt from vector a=AP\mathbf{a} = \mathbf{AP} onto b=AB\mathbf{b} = \mathbf{AB} is

t=acosθ=aababcosθ=abbt = |\mathbf{a}|\cos\theta = |\mathbf{a}|\underbrace{\frac{\mathbf{a}\cdot\mathbf{b}}{|\mathbf{a}|\cdot|\mathbf{b}|}}_{\cos\theta}=\frac{\mathbf{a}\cdot\mathbf{b}}{|\mathbf{b}|}

Scaling the projected length tt by the length b|\mathbf{b}|, gives a ratio t^\hat{t} between 0 and 1 of the projection on the line AB\mathbf{AB}:

t^=tb=abbb=abb2=abbb\hat{t} = \frac{t}{|\mathbf{b}|} = \frac{\mathbf{a}\cdot\mathbf{b}}{|\mathbf{b}|\cdot |\mathbf{b}|} =\frac{\mathbf{a}\cdot\mathbf{b}}{|\mathbf{b}|^2}=\frac{\mathbf{a}\cdot\mathbf{b}}{\mathbf{b}\cdot\mathbf{b}}

Now R=A+t^(BA)=A+t^b\mathbf{R} = \mathbf{A} + \hat{t}(\mathbf{B} - \mathbf{A}) = \mathbf{A} + \hat{t}\mathbf{b} is the point on the line and by clamping t^\hat{t} strictly into the interval [0,1][0, 1], the final result is PR|\mathbf{P} - \mathbf{R}|.

Implemented in JavaScript this gives

function minLineDist(A, B, P) {
    const a = {
        x: P.x - A.x,
        y: P.y - A.y
    };
    const b = {
        x: B.x - A.x,
        y: B.y - A.y
    };
    const bb = b.x * b.x + b.y + b.y;

    if (0 === bb) {
        return Math.hypot(a.x, a.y);
    }

    const ab = a.x * b.x + a.y + b.y;
    const t = Math.max(0, Math.min(1, ab / bb));

    const R = {
        x: A.x + t * b.x,
        y: A.y + t * b.y
    };
    return Math.hypot(P.x - R.x, P.y - R.y);
}