I asked "How can I tell if a point belongs to a certain line?" before and I found a suitable answer so thank you very much.
Now, I would like to know how to tell if a certain point is close to my line.
I asked "How can I tell if a point belongs to a certain line?" before and I found a suitable answer so thank you very much.
Now, I would like to know how to tell if a certain point is close to my line.
You need to calculate the right angle distance to the line. Then you have to define what "close" is and test if it is within that distance.
The equation you want is:
@Alan Jackson's answer is almost perfect - but his first (and most up-voted) comment suggests that endpoints are not correctly handled. To ensure the point is on the segment, simply create a box where the segment is a diagonal, then check if the point is contained within. Here is the pseudo-code:
Given Line ab, comprised of points a and b, and Point p, in question:
int buffer = 25;//this is the distance that you would still consider the point nearby
Point topLeft = new Point(minimum(a.x, b.x), minimum(a.y, b.y));
Point bottomRight = new Point(maximum(a.x, b.x), maximum(a.y, b.y));
Rect box = new Rect(topLeft.x - buffer, topLeft.y - buffer, bottomRight.x + buffer, bottomRight.y + buffer);
if (box.contains(p))
{
//now run the test provided by Alan
if (test)
return true;
}
return false;
Google is your friend: Point-Line Distance (2-Dimensional). You can just use the equation at the bottom and there you go.
Basically, what you want to do it find the normal line — that is, a line perpendicular to your line — that intersects your point and the line, and then compute the distance along that line.
How close is near?
Some geometry will give you the answer you need, you just need to be aware of the following steps.
Assuming your like is of the form y=mx+b, the shortest distance to your point will be the line perpendicular to your starting line (m1=-1/m), intersecting your point in question.
From there you calculate the distance between the intersection point and the point in question.
Calculate the point on your line that is closest to that point.
Assuming the line segment is a and b, and the point is p.
float vAPx = p.x - a.x;
float vAPy = p.y - a.y;
float vABx = b.x - a.x;
float vABy = b.y - a.y;
float sqDistanceAB = a.distanceSq(b);
float ABAPproduct = vABx*vAPx + vABy*vAPy;
float amount = ABAPproduct / sqDistanceAB;
if (amount > 1) amount = 1;
if (amount < 0) amount = 0;
Which gives you 'amount', how far through the line segment you are between A and B (properly bounded).
float nx = (amount * (b.x - a.x)) + a.x;
float ny = (amount * (b.y - a.y)) + a.y;
Gives you point (nx,ny).
if (p.distance(nx,ny) > threshold) reject;
This will properly work beyond the end of the line segment, because it keeps 'amount' between 0 and 1.
If you don't want it a bounded line segment get rid of the bounds for amount. The rest of the code will still work, calculating positions beyond and before A and beyond B.
There was another question that claimed this question was a duplicate but, it's asking for a different thing hence my solution solves for the position of the point and then just solves the Euclidean distance (which actually solves both questions).
a.distanceSq(b) can also be done as vABxvABx + vAByvABy, since we already have those done.
Here's a python function which does the trick. It should work in 2 or 3 dimensions (or more) and handles vertical and horizontal lines without special cases. If you set clipToSegment
to true the returned point is clipped to the ends if the projected line extends beyond the supplied line segment.
def nearestPointOnLine(pt, r0, r1, clipToSegment = True):
r01 = r1 - r0 # vector from r0 to r1
d = np.linalg.norm(r01) # length of r01
r01u = r01 / d # unit vector from r0 to r1
r = pt - r0 # vector from r0 to pt
rid = np.dot(r, r01u) # projection (length) of r onto r01u
ri = r01u * rid # projection vector
lpt = r0 + ri # point on line
if clipToSegment: # if projection is not on line segment
if rid > d: # clip to endpoints if clipToSegment set
return r1
if rid < 0:
return r0
return lpt
Usage: (distance of point [4,5] from the line segment from [2,4] to [4,6])
r0 = np.array([2,4])
r1 = np.array([4,6])
rpt = np.array([4,5])
pt = nearestPointOnLine(rpt, r0, r1, True)
dist = np.linalg.norm(rpt-pt)
print('dist', dist)