Instantly share code, notes, and snippets.

# mattdesl/point-to-line-2d.js

Created March 22, 2018 00:36
Star You must be signed in to star a gist
2D Point to Line Segment distance function
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 // 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 - w) + sqr(v - w); } // 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 - v) * (w - v) + (p - v) * (w - v)) / l2; t = Math.max(0, Math.min(1, t)); return dist2(p, [ v + t * (w - v), v + t * (w - v) ]); } // 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 commented Jan 22, 2020 • edited

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 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});`