Nearest Point To Polyline //JavaScript Repository
Description
Nearest point to a polyline, given a point out of the limits.
Created: 2005.08.20
Created: 2005.08.20
Code (Download)
//+ Jonas Raoni Soares Silva
//@ http://jsfromhell.com/math/closest-polyline-point [rev. #1]
closestPolyLinePoint = function(px, py, x0, y0, x1, y1, etc, etc, etc){
function dotLineLength(x, y, x0, y0, x1, y1, o){
function lineLength(x, y, x0, y0){
return Math.sqrt((x -= x0) * x + (y -= y0) * y);
}
if(o && !(o = function(x, y, x0, y0, x1, y1){
if(!(x1 - x0)) return {x: x0, y: y};
else if(!(y1 - y0)) return {x: x, y: y0};
var left, tg = -1 / ((y1 - y0) / (x1 - x0));
return {x: left = (x1 * (x * tg - y + y0) + x0 * (x * - tg + y - y1)) / (tg * (x1 - x0) + y0 - y1), y: tg * left - tg * x + y};
}(x, y, x0, y0, x1, y1), o.x >= Math.min(x0, x1) && o.x <= Math.max(x0, x1) && o.y >= Math.min(y0, y1) && o.y <= Math.max(y0, y1))){
var l1 = lineLength(x, y, x0, y0), l2 = lineLength(x, y, x1, y1);
return l1 > l2 ? l2 : l1;
}
else {
var a = y0 - y1, b = x1 - x0, c = x0 * y1 - y0 * x1;
return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b);
}
};
for(var args = [].slice.call(arguments, 0), lines = []; args.length > 4; lines[lines.length] = {y1: args.pop(), x1: args.pop(), y0: args.pop(), x0: args.pop()});
if(!lines.length)
return {x: px, y: py};
for(var l, i = lines.length - 1, o = lines[i],
lower = {i: i, l: dotLineLength(px, py, o.x0, o.y0, o.x1, o.y1, 1)};
i--; lower.l > (l = dotLineLength(px, py,
(o = lines[i]).x0, o.y0, o.x1, o.y1, 1)) && (lower = {i: i, l: l}));
py < Math.min((o = lines[lower.i]).y0, o.y1) ? py = Math.min(o.y0, o.y1)
: py > Math.max(o.y0, o.y1) && (py = Math.max(o.y0, o.y1));
px < Math.min(o.x0, o.x1) ? px = Math.min(o.x0, o.x1)
: px > Math.max(o.x0, o.x1) && (px = Math.max(o.x0, o.x1));
Math.abs(o.x0 - o.x1) < Math.abs(o.y0 - o.y1) ?
px = (py * (o.x0 - o.x1) - o.x0 * o.y1 + o.y0 * o.x1) / (o.y0 - o.y1)
: py = (px * (o.y0 - o.y1) - o.y0 * o.x1 + o.x0 * o.y1) / (o.x0 - o.x1);
return {x: px, y: py};
};
Example (Example)
<p>Mova o mouse fora da ?rea das linhas</p>
<div id="linhaA" style="position: absolute; 100px; border: solid 1px #000; font-size:1px; background: #000; width: 200px; height: 0px; left:200px; top: 200px;"></div>
<div id="linhaB" style="position: absolute; 100px; border: solid 1px #000; font-size:1px; background: #000; height: 200px; width: 0px; left:400px; top: 200px;"></div>
<div id="dot" style="position: absolute; border:1px solid #000; background: #fee; width: 20px; height: 20px;"></div>
<script type="text/javascript">
//<![CDATA[
var lineA = document.getElementById("linhaA"),
lineB = document.getElementById("linhaB");
box = document.getElementById("dot");
//http://www.jsfromhell.com/geral/event-listener
addEvent(document, "mousemove", function(e){
var p = closestPolyLinePoint(e.clientX, e.clientY,
lineA.offsetLeft, lineA.offsetTop, lineA.offsetLeft + lineA.offsetWidth, lineA.offsetTop + lineA.offsetHeight,
lineB.offsetLeft, lineB.offsetTop, lineB.offsetLeft + lineB.offsetWidth, lineB.offsetTop + lineB.offsetHeight
);
box.style.left = (p.x - box.offsetWidth / 2) + "px";
box.style.top = (p.y - box.offsetHeight / 2) + "px";
});
//]]>
</script>
Help
- closestPolyLinePoint( px: Integer, py: Integer, x0: Integer, y0: Integer, x1: Integer, y1: Integer, ...): Object
-
Returns an object containing two properties (x and y), that specifies the limit point of a set of lines in relation to a point.
- px
- point's x coord
- py
- point's y coord
- x0
- x coord of the line's A point
- y0
- y coord of the line's A point
- x1
- x coord of the line's B point
- y1
- y coord of the line's B point
- ...
- unlimited set of 2 points
Rank (Votes: 24)
3.96