simple dot product can do this easily ... so let consider we got line defined by two points p0,p1
. Any point p
on that line will have the same or negative slope to any of the endpoints so
|dot(p1-p0,p-p0)|/(|p1-p0|*|p-p0|) = 1.0
to make it more robust with floating point compare like this:
|dot(p1-p0,p-p0)|/(|p1-p0|*|p-p0|) >= 1.0-1e-10;
Where 1e-10
is small enough epsilon ... rewriten to code:
dx=x1-x0;
dy=y1-y0;
dz=z1-z0;
ex=x-x0;
ey=y-y0;
ez=z-z0;
q =dx*ex;
q+=dy*ey;
q+=dz*zy;
q*=q;
q/=(dx*dx+dy*dy+dz*dz);
q/=(ex*ex+ey*ey+ez*ez);
if (q>=1.0-1e-10) point p(x,y) is on the line
else p(x,y) is not on line
As you can see no need for the sqrt we can compare the power instead ...
However you should handle edge case when p==p0
then either use p1
or return true right away.
In case you want points only inside the line segment (not outside the edge points) then you need a slight change in code
0.0 <= dot(p1-p0,p-p0)/|p-p0| <= 1.0
So:
dx=x1-x0;
dy=y1-y0;
dz=z1-z0;
ex=x-x0;
ey=y-y0;
ez=z-z0;
q =dx*ex;
q+=dy*ey;
q+=dz*zy;
if (q<0.0) p(x,y) is not on line
q*=q;
q/=(ex*ex+ey*ey+ez*ez);
if (q<=1.0) point p(x,y) is on the line
else p(x,y) is not on line
btw the result of the dot product gives you ratio of one vector projected to another perpendicularly or cos of the angle between them (if they are normalized) so for parallel vectors the result is 100%
of length or 1.0
. If you tweak the 1e-10
value using goniometry and p-p0
you can convert this to detect points up to some perpendicular distance to line (which might get handy for thick lines and or mouse selecting).