Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
2D Point to Line Segment distance function
// Taken From:
// https://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
function sqr (x) {
return x * x;
}
function dist2 (v, w) {
return sqr(v[0] - w[0]) + sqr(v[1] - w[1]);
}
// p - point
// v - start point of segment
// w - end point of segment
function distToSegmentSquared (p, v, w) {
var l2 = dist2(v, w);
if (l2 === 0) return dist2(p, v);
var t = ((p[0] - v[0]) * (w[0] - v[0]) + (p[1] - v[1]) * (w[1] - v[1])) / l2;
t = Math.max(0, Math.min(1, t));
return dist2(p, [ v[0] + t * (w[0] - v[0]), v[1] + t * (w[1] - v[1]) ]);
}
// p - point
// v - start point of segment
// w - end point of segment
function distToSegment (p, v, w) {
return Math.sqrt(distToSegmentSquared(p, v, w));
}
module.exports = distToSegment;
module.exports.squared = distToSegmentSquared;
@pjbaron
Copy link

pjbaron commented Jan 22, 2020

Handy snippet thanks!
Here's the same thing modified to reuse partial results and accept data structures instead of lists:

    function dist(point, x, y)
    {
        var dx = x - point.x;
        var dy = y - point.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
    // point - { x, y }
    // line - { sx, sy, ex, ey }
    function distToSegment(point, line)
    {
        var dx = line.ex - line.sx;
        var dy = line.ey - line.sy;
        var l2 = dx * dx + dy * dy;
        
        if (l2 == 0)
            return this.dist(point, line.sx, line.sy);

        var t = ((point.x - line.sx) * dx + (point.y - line.sy) * dy) / l2;
        t = Math.max(0, Math.min(1, t));

        return this.dist(point, line.sx + t * dx, line.sy + t * dy);
    }

@ashleedawg
Copy link

ashleedawg commented Feb 6, 2022

Handy snippet thanks!
Here's the same thing modified to reuse partial results and accept data structures instead of lists...

Handy modification thanks!
Here's the same thing, compressed:

function distToSegment(p,ln){var n=ln.ex-ln.sx,r=ln.ey-ln.sy,x=n*n+r*r;if(0==x)return this.pd(p,ln.sx,ln.sy);var y=((p.x-ln.sx)*n+(p.y-ln.sy)*r)/x;return y=Math.max(0,Math.min(1,y)),this.pd(p,ln.sx+y*n,ln.sy+y*r)}function pd(p,x,y){return Math.hypot(x-p.x,y-p.y)}

It's still used like ret=distToSegment({x:5,y:8},{sx:1,sy:1,ex:9,ey:7});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment