/* **************************************************************************** * * MODULE: Vector library * * AUTHOR(S): Original author CERL, probably Dave Gerdes. * Update to GRASS 5.7 Radim Blazek. * * PURPOSE: Lower level functions for reading/writing/manipulating vectors. * * COPYRIGHT: (C) 2001 by the GRASS Development Team * * This program is free software under the GNU General Public * License (>=v2). Read the file COPYING that comes with GRASS * for details. * *****************************************************************************/ #include /*************************************************************** * test_for_intersection (ax1,ay1,ax2,ay2,bx1,by1,bx2,by2) * double ax1,ax2,ay1,ay2; * double bx1,bx2,by1,by2; * * returns * 0 no intersection at all * 1 the line segments intersect at only one point * -1 the line segments intersect at many points, i.e., overlapping * segments from the same line * * find_intersection (ax1,ay1,ax2,ay2,bx1,by1,bx2,by2,x,y) * double ax1,ax2,ay1,ay2; * double bx1,bx2,by1,by2; * double *x,*y; * * returns * 0 no intersection * 1 x,y set to (unique) intersection * -1 lines overlap, no unique intersection * * Based on the following: * * (ax2-ax1)r1 - (bx2-bx1)r2 = ax2 - ax1 * (ay2-ay1)r1 - (by2-by1)r2 = ay2 - ay1 * * Solving for r1 and r2, if r1 and r2 are between 0 and 1, * then line segments (ax1,ay1)(ax2,ay2) and (bx1,by1)(bx2,by2) * intersect ****************************************************************/ #define D ((ax2-ax1)*(by1-by2) - (ay2-ay1)*(bx1-bx2)) #define D1 ((bx1-ax1)*(by1-by2) - (by1-ay1)*(bx1-bx2)) #define D2 ((ax2-ax1)*(by1-ay1) - (ay2-ay1)*(bx1-ax1)) int dig_test_for_intersection(double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2) { register double d, d1, d2; double t; int switched; if (ax1 > ax2 || (ax1 == ax2 && ay1 > ay2)) { t = ax1; ax1 = ax2; ax2 = t; t = ay1; ay1 = ay2; ay2 = t; } if (bx1 > bx2 || (bx1 == bx2 && by1 > by2)) { t = bx1; bx1 = bx2; bx2 = t; t = by1; by1 = by2; by2 = t; } switched = 0; if (bx1 < ax1) switched = 1; else if (bx1 == ax1) { if (bx2 < ax2) switched = 1; else if (bx2 == ax2) { if (by1 < ay1) switched = 1; else if (by1 == ay1) { if (by2 < ay2) switched = 1; } } } if (switched) { t = ax1; ax1 = bx1; bx1 = t; t = ax2; ax2 = bx2; bx2 = t; t = ay1; ay1 = by1; by1 = t; t = ay2; ay2 = by2; by2 = t; } d = D; d1 = D1; d2 = D2; if (d > 0) return (d1 >= 0 && d2 >= 0 && d >= d1 && d >= d2); if (d < 0) return (d1 <= 0 && d2 <= 0 && d <= d1 && d <= d2); /* lines are parallel */ if (d1 || d2) return 0; /* segments are colinear. check for overlap */ /* Collinear vertical */ if (ax1 == ax2) { if (ay1 > ay2) { t = ay1; ay1 = ay2; ay2 = t; } if (by1 > by2) { t = by1; by1 = by2; by2 = t; } if (ay1 > by2) return 0; if (ay2 < by1) return 0; /* there is overlap */ if (ay1 == by2 || ay2 == by1) return 1; /* endpoints only */ return -1; /* true overlap */ } else { if (ax1 > ax2) { t = ax1; ax1 = ax2; ax2 = t; } if (bx1 > bx2) { t = bx1; bx1 = bx2; bx2 = t; } if (ax1 > bx2) return 0; if (ax2 < bx1) return 0; /* there is overlap */ if (ax1 == bx2 || ax2 == bx1) return 1; /* endpoints only */ return -1; /* true overlap */ } return 0; /* should not be reached */ } int dig_find_intersection(double ax1, double ay1, double ax2, double ay2, double bx1, double by1, double bx2, double by2, double *x, double *y) { register double d, r1, r2; double t; int switched; if (ax1 > ax2 || (ax1 == ax2 && ay1 > ay2)) { t = ax1; ax1 = ax2; ax2 = t; t = ay1; ay1 = ay2; ay2 = t; } if (bx1 > bx2 || (bx1 == bx2 && by1 > by2)) { t = bx1; bx1 = bx2; bx2 = t; t = by1; by1 = by2; by2 = t; } switched = 0; if (bx1 < ax1) switched = 1; else if (bx1 == ax1) { if (bx2 < ax2) switched = 1; else if (bx2 == ax2) { if (by1 < ay1) switched = 1; else if (by1 == ay1) { if (by2 < ay2) switched = 1; } } } if (switched) { t = ax1; ax1 = bx1; bx1 = t; t = ax2; ax2 = bx2; bx2 = t; t = ay1; ay1 = by1; by1 = t; t = ay2; ay2 = by2; by2 = t; } d = D; if (d) { r1 = D1 / d; r2 = D2 / d; if (r1 < 0 || r1 > 1 || r2 < 0 || r2 > 1) { return 0; } *x = ax1 + r1 * (ax2 - ax1); *y = ay1 + r1 * (ay2 - ay1); return 1; } /* lines are parallel */ if (D1 || D2) { return 0; } /* segments are colinear. check for overlap */ /* Collinear vertical */ if (ax1 == ax2) { if (ay1 > by2) return 0; if (ay2 < by1) return 0; /* there is overlap */ if (ay1 == by2) { *x = ax1; *y = ay1; return 1; /* endpoints only */ } if (ay2 == by1) { *x = ax2; *y = ay2; return 1; /* endpoints only */ } /* overlap, no single intersection point */ if (ay1 > by1 && ay1 < by2) { *x = ax1; *y = ay1; } else { *x = ax2; *y = ay2; } return -1; } else { if (ax1 > bx2) return 0; if (ax2 < bx1) return 0; /* there is overlap */ if (ax1 == bx2) { *x = ax1; *y = ay1; return 1; /* endpoints only */ } if (ax2 == bx1) { *x = ax2; *y = ay2; return 1; /* endpoints only */ } /* overlap, no single intersection point */ if (ax1 > bx1 && ax1 < bx2) { *x = ax1; *y = ay1; } else { *x = ax2; *y = ay2; } return -1; } return 0; /* should not be reached */ }