Skip to content

Instantly share code, notes, and snippets.

@mattdesl
Created March 22, 2018 00:36
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattdesl/47412d930dcd8cd765c871a65532ffac to your computer and use it in GitHub Desktop.
Save mattdesl/47412d930dcd8cd765c871a65532ffac to your computer and use it in GitHub Desktop.
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

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