You want to know if the point (x,y) is on the line (x1,y1) to (x2,y2)?
Whatever method you use (maybe comp.graphics.algorithms may be of help
here), and even with doubles, you may run into accuracy problems: how close
to the line or it's endpoints does (x,y) have to be, to be considered *on*
it?
The CGA FAQ won't help. This problem is considered too elementary for
a listing, I am sure.
If you imagine an XY plane with a fine grid corresponding to legal floating
point values (any X or Y only exists at an intersection), then a line drawn
from x1y1 to x2y2 quite likely will miss a lot of intersections on the way.
So you can't step smoothly along it, you can only follow the grid (and it
gets coarser away from 0,0).
It's the wrong way to solve it anyway.
A double will still have problems but won't show up as easily. Things are
still workable, just remember floating point is rarely exact.
Maybe something like this:
#include <float.h>
#include <math.h>
/* 'Close enough' comparison: */
int double_compare(double d1, double d2)
{
if (d1 > d2)
if ((d1 - d2) < fabs(d1 * DBL_EPSILON))
return 0;
else
return 1;
if (d1 < d2)
if ((d2 - d1) < fabs(d2 * DBL_EPSILON))
return 0;
else
return -1;
return 0;
}
/* Max between two doubles: */
double dmax(double a, double b)
{
if (a > b)
return a;
return b;
}
/* Min between two doubles: */
double dmin(double a, double b)
{
if (a < b)
return a;
return b;
}
/* Return 1 if point is on line segment, zero otherwise: */
int point_on_segment_2D(double x1, double y1, double x2, double y2,
double x, double y)
{
double x_1 = dmin(x1, x2);
double x_2 = dmax(x1, x2);
double y_1 = dmin(y1, y2);
double y_2 = dmax(y1, y2);
/* First, we check to see if the point is inside of the bounding
box: */
if ((x >= x_1) && (x <= x_2)) {
if ((y >= y_1) && (y <= y_2)) {
/* If the point is in the box, we check to see if it is on
the line: */
int result = double_compare(((x2 - x1) * (y - y1)), ((x -
x1) * (y2 - y1)));
return result == 0;
}
}
return 0;
}
#ifdef UNIT_TEST
#include <stdio.h>
int main(void)
{
double x1 = 0,
y1 = 0;
double x2 = 5,
y2 = 5;
double x,
y;
/* First, some points of which half are on the segment: */
for (x = -5, y = -5; x <= 5; x += 0.5, y += 0.5) {
if (point_on_segment_2D(x1, y1, x2, y2, x, y)) {
printf("(%g,%g) is on the segment\n", x, y);
}
}
/* Now, some points where half are close to, but NOT on the
segment: */
for (x = -5, y = -5; x <= 5; x += 0.5, y += 0.4999) {
if (point_on_segment_2D(x1, y1, x2, y2, x, y)) {
printf("(%g,%g) is on the segment\n", x, y);
}
}
return 0;
}
/* Possible output:
(0,0) is on the segment
(0.5,0.5) is on the segment
(1,1) is on the segment
(1.5,1.5) is on the segment
(2,2) is on the segment
(2.5,2.5) is on the segment
(3,3) is on the segment
(3.5,3.5) is on the segment
(4,4) is on the segment
(4.5,4.5) is on the segment
(5,5) is on the segment
*/
#endif