• 13
• 15
• 27
• 9
• 9

# Point on a line

This topic is 4558 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hey guys, I've got a problem here. I have a line segment from (x0, y0) to (x1, y1). For example, (3,3) to (7,7) in 2d coords. I want to have certain actions happen based on whether a user clicks within 2 units of this line. I get the point they click on, but how can I detect if the point they click on is within that distance (d) from the line? Thanks.

##### Share on other sites
Convert the line into a long rectangle with the long side parrallel to the line.
Check to see if the point click was within this rectangle.

##### Share on other sites
But what if the line is diagonal? Will this still work? It seems like it would get anything within a rectangle with corners at (x0, y0) and (x1, y1).

##### Share on other sites
Basically what you do is..

- find the perpendicular vector to the line

- to calculate the four corners of the rectangle offset the end points of the line along the perp vector, first in one direction and then the other by 2 pixels.

- to detect if the mouse click is within this none-axis aligned rectangle you need to divide it into 2 triangles and use barycentric coords to determine if the mouse click was within either triangle.

I have the code for this somewhere at home but won't be able to get to it for about 6-7 hours.

##### Share on other sites
A slightly easier alternative might be to use a capsule. Basically, this just means finding the shortest distance from the point to the line segment and checking to see if it's within the desired range. Here's some pseudocode:
float DistancePointSegment(Vector3 p, Vector3 a, Vector3 b) {    Vector3 O = a;    Vector3 D = b-a;    Vector3 d = p-a;    float t = (d.Dot(D))/(D.Dot(D));    if (t < 0.0f) t = 0.0f;    else if (t > 1.0f) t = 1.0f;    Vector3 closest = O + t * D;    return (p - closest).Length();}bool SelectSegment(Vector3 p, Vector3 a, Vector3 b, float range) {    return DistancePointSegment(p, a, b) <= range;}
No guarantee that I got that all right, but if you have problems try googling for 'point line distance'. Also, you can substitute squared length for length to eliminate the square root.

##### Share on other sites
LineVec = LineP2 - LineP1;
PointLineVec = MousePoint - LineP1;

/* This will give you the distance along the vector where the mouse point would be nearest too.*/
DotValue = DotProduct(LineVec, PointLineVec);

/* Note: The point is behind the first point in the line. */
if (DotValue < 0) {
/* Cap it to an end point. */
DotValue = 0;
}
/* The point is behind the second point in the line. */
else if (DotValue > LineDist) {
/* Cap it to the other end point.
DotValue = LineDist;
}

LineVecNormed = Normalize(LineVec);
PointOnLine = Scale(LineVecNormed, DotValue) + LineP1;

PointDistance = Distance(MousePoint, PointOnLine);

if (PointDistance < tolerance) {
/* Mouse point is reasonably close to line vector or it's end points.*/
}

##### Share on other sites
Just to save the OP some time, the above solution is equivalent to the example I posted (in spirit at least - I think it may have a couple of errors). Although performance is probably of little concern here, it is also less efficient due to the (unnecessary) square root. To be fair, there are a few small optimizations that could be made to my version as well, but for illustrative purposes I opted for clarity.