Prechádzať zdrojové kódy

libgis: fix G_intersect_line_segments() (sync to trunk)

git-svn-id: https://svn.osgeo.org/grass/grass/branches/releasebranch_7_0@61936 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Neteler 10 rokov pred
rodič
commit
066481a50a
1 zmenil súbory, kde vykonal 88 pridanie a 23 odobranie
  1. 88 23
      lib/gis/intersect.c

+ 88 - 23
lib/gis/intersect.c

@@ -75,7 +75,7 @@
 #define D1 ((bx1-ax1)*(by1-by2) - (by1-ay1)*(bx1-bx2))
 #define D2 ((ax2-ax1)*(by1-ay1) - (ay2-ay1)*(bx1-ax1))
 
-#define SWAP(x,y) {int t; t=x; x=y; y=t;}
+#define SWAP(x,y) {double t; t=x; x=y; y=t;}
 
 int G_intersect_line_segments(double ax1, double ay1, double ax2, double ay2,
 			      double bx1, double by1, double bx2, double by2,
@@ -83,6 +83,16 @@ int G_intersect_line_segments(double ax1, double ay1, double ax2, double ay2,
 {
     double d;
 
+    if (ax1 > ax2 || (ax1 == ax2 && ay1 > ay2)) {
+	SWAP(ax1, ax2)
+	SWAP(ay1, ay2)
+    }
+
+    if (bx1 > bx2 || (bx1 == bx2 && by1 > by2)) {
+	SWAP(bx1, bx2)
+	SWAP(by1, by2)
+    }
+
     d = D;
 
     if (d) {			/* lines are not parallel */
@@ -94,31 +104,86 @@ int G_intersect_line_segments(double ax1, double ay1, double ax2, double ay2,
 	return (*ra >= 0.0 && *ra <= 1.0 && *rb >= 0.0 && *rb <= 1.0);
     }
 
-    if (D1 || D2)
-	return -1;		/* lines are parallel, not colinear */
-
-    if (ax1 > ax2) {
-	SWAP(ax1, ax2)
-    }
-    if (bx1 > bx2) {
-	SWAP(bx1, bx2)
-    }
-    if (ax1 > bx2)
-	return -1;
-    if (ax2 < bx1)
+    /* lines are parallel */
+    if (D1 || D2) {
 	return -1;
+    }
+
+    /* segments are colinear. check for overlap */
+
+    /* Collinear vertical */
+    if (ax1 == ax2) {
+	if (ay1 > by2) {
+	    *x = ax1;
+	    *y = ay1;
+	    return 0;		/* extensions overlap */
+	}
+	if (ay2 < by1) {
+	    *x = ax2;
+	    *y = ay2;
+	    return 0;		/* extensions overlap */
+	}
 
-    /* there is overlap */
-    if (ax1 == bx2) {
-	*x = ax1;
-	*y = ay1;
-	return 1;		/* at endpoints only */
+	/* 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 2;
     }
-    if (ax2 == bx1) {
-	*x = ax2;
-	*y = ay2;
-	return 1;		/* at endpoints only */
+    else {
+	if (ax1 > bx2) {
+	    *x = ax1;
+	    *y = ay1;
+	    return 0;		/* extensions overlap */
+	}
+	if (ax2 < bx1) {
+	    *x = ax2;
+	    *y = ay2;
+	    return 0;		/* extensions overlap */
+	}
+
+	/* 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 2;
     }
 
-    return 2;			/* colinear with overlap on an interval, not just a single point */
+    return 0; /* should not be reached */
 }