Reputation: 999
To get another point (r
) on the line that passes through point p
in the direction v
we can use the following formula, and substitute any value for a
:
To test if r
is on the line, we must only find a value for a
that satisfies. In my current implementation, I check if a
is the same for each component of the vectors by reorganizing the equation for r
to:
In code terms, this looks like the following:
boolean isPointOnLine(Vector2f r, Vector2f p, Vector2f v) {
return (p.x - r.x) / v.x == (p.y - r.y) / v.y;
}
However, this method does not work: If any component of v
is 0
, the fraction will evaluate to infinity. Hence we get an incorrect result.
How do I check if r
is on the line correctly?
Upvotes: 4
Views: 6504
Reputation: 29244
In 3D you do the following:
If a point r=(x,y,z)
is on the line with p=(px,py,pz)
another point on the line and v=(vx,vy,vz)
the direction calculate the following
CROSS(v,r-p)=0
or by component
(py-ry)*vz - (pz-rz)*vy==0
(pz-rz)*vx - (px-rx)*vz==0
(px-rx)*vy - (py-ry)*vx==0
For the 2D version, make all z-components zero
(px-rx)*vy - (py-ry)*vx == 0
No division needed, no edge cases and simple fast multiplication.
Of course due to round-off the result will be never be exactly zero. So what you need is a formula for the minimum distance, and a check if the distance is within some tolerance
d = abs((px-rx)*vy-(py-ry)*vx)/sqrt(vx*vx+vy*vy) <= tol
Upvotes: 5
Reputation: 999
It turns out that the equation I had was in fact correct, the division by 0 is just an edge case that must be handled beforehand. The final function looks like this:
boolean isPointOnLine(Vector2f r, Vector2f p, Vector2f v) {
if (v.x == 0) {
return r.x == p.x;
}
if (v.y == 0) {
return r.y == p.y;
}
return (p.x - r.x) / v.x == (p.y - r.y) / v.y;
}
Upvotes: 1