TomP TomP - 4 years ago 170
Javascript Question

Decide if a point is on (or close enough to) a line segment

I want to decide whether a mouse click point lies on an SVG polyline. I found this Python code to determine whether a point lies between two other points, and reimplemented it in JavaScript.

function isOnLine(xp, yp, x1, y1, x2, y2){

var p = new Point(x, y);
var epsilon = 0.01;

var crossProduct = (yp - y1) * (x2 - x1) - (xp - x1) * (y2 - y1);
if(Math.abs(crossProduct) > epsilon)
return false;
var dotProduct = (xp - x1) * (x2 - x1) + (yp - y1)*(y2 - y1);
if(dotProduct < 0)
return false;
var squaredLengthBA = (x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1);
if(dotProduct > squaredLengthBA)
return false;

return true;
}


But it's not working the way I want, because I will never get the mouse pointer exactly on the line. So I need something like an "imaginary thick line" to get some margin of error:

enter image description here

Any ideas?

Answer Source

The cross product divided by the length of the line gives the distance of the point from the line. So just compare this to some threshold value:

function isOnLine (xp, yp, x1, y1, x2, y2, maxDistance) {
    var dxL = x2 - x1, dyL = y2 - y1;  // line: vector from (x1,y1) to (x2,y2)
    var dxP = xp - x1, dyP = yp - y1;  // point: vector from (x1,y1) to (xp,yp)

    var squareLen = dxL * dxL + dyL * dyL;  // squared length of line
    var dotProd   = dxP * dxL + dyP * dyL;  // squared distance of point from (x1,y1) along line
    var crossProd = dyP * dxL - dxP * dyL;  // area of parallelogram defined by line and point

    // perpendicular distance of point from line
    var distance = Math.abs(crossProd) / Math.sqrt(squareLen);

    return (distance <= maxDistance && dotProd >= 0 && dotProd <= squareLen);
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download