[GRASS-SVN] r70792 - grass/trunk/lib/vector/Vlib

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Mar 22 13:35:11 PDT 2017


Author: mmetz
Date: 2017-03-22 13:35:11 -0700 (Wed, 22 Mar 2017)
New Revision: 70792

Modified:
   grass/trunk/lib/vector/Vlib/intersect2.c
Log:
vectorlib: improve Vect_line_intersection2(), Vect_line_check_intersection2()

Modified: grass/trunk/lib/vector/Vlib/intersect2.c
===================================================================
--- grass/trunk/lib/vector/Vlib/intersect2.c	2017-03-22 20:31:58 UTC (rev 70791)
+++ grass/trunk/lib/vector/Vlib/intersect2.c	2017-03-22 20:35:11 UTC (rev 70792)
@@ -85,8 +85,8 @@
 #if 0
 static int ident(double x1, double y1, double x2, double y2, double thresh);
 #endif
-static int cross_seg(int i, int j);
-static int find_cross(int i, int j);
+static int cross_seg(int i, int j, int b);
+static int find_cross(int i, int j, int b);
 
 
 typedef struct
@@ -179,7 +179,7 @@
 static struct line_pnts *APnts, *BPnts, *ABPnts[2], *IPnts;
 
 /* break segments */
-static int cross_seg(int i, int j)
+static int cross_seg(int i, int j, int b)
 {
     double x1, y1, z1, x2, y2, z2;
     double y1min, y1max, y2min, y2max;
@@ -202,12 +202,28 @@
     if (y1min > y2max || y1max < y2min)
 	return 0;
 
-    ret = Vect_segment_intersection(APnts->x[i], APnts->y[i], APnts->z[i],
-				    APnts->x[i + 1], APnts->y[i + 1],
-				    APnts->z[i + 1], BPnts->x[j], BPnts->y[j],
-				    BPnts->z[j], BPnts->x[j + 1],
-				    BPnts->y[j + 1], BPnts->z[j + 1], &x1,
-				    &y1, &z1, &x2, &y2, &z2, 0);
+    if (b) {
+	ret = Vect_segment_intersection(APnts->x[i], APnts->y[i],
+	                                APnts->z[i],
+					APnts->x[i + 1], APnts->y[i + 1],
+					APnts->z[i + 1],
+					BPnts->x[j], BPnts->y[j], 
+					BPnts->z[j],
+					BPnts->x[j + 1], BPnts->y[j + 1],
+					BPnts->z[j + 1],
+					&x1, &y1, &z1, &x2, &y2, &z2, 0);
+    }
+    else {
+	ret = Vect_segment_intersection(BPnts->x[j], BPnts->y[j],
+					BPnts->z[j],
+					BPnts->x[j + 1], BPnts->y[j + 1],
+					BPnts->z[j + 1], 
+					APnts->x[i], APnts->y[i],
+					APnts->z[i],
+					APnts->x[i + 1], APnts->y[i + 1],
+					APnts->z[i + 1],
+					&x1, &y1, &z1, &x2, &y2, &z2, 0);
+    }
 
     /* add ALL (including end points and duplicates), clean later */
     if (ret > 0) {
@@ -727,7 +743,7 @@
 		/* test for intersection of s with all segments in T */
 		rbtree_init_trav(&bo_t_trav, bo_tb);
 		while ((found = rbtree_traverse(&bo_t_trav))) {
-		    cross_seg(qi.s, found->s);
+		    cross_seg(qi.s, found->s, 0);
 		}
 		
 		/* insert s in T */
@@ -737,7 +753,7 @@
 		/* test for intersection of s with all segments in T */
 		rbtree_init_trav(&bo_t_trav, bo_ta);
 		while ((found = rbtree_traverse(&bo_t_trav))) {
-		    cross_seg(found->s, qi.s);
+		    cross_seg(found->s, qi.s, 1);
 		}
 		
 		/* insert s in T */
@@ -1126,8 +1142,8 @@
 
 static int cross_found;		/* set by find_cross() */
 
-/* break segments */
-static int find_cross(int i, int j)
+/* find segment intersection, used by Vect_line_check_intersection2 */
+static int find_cross(int i, int j, int b)
 {
     double x1, y1, z1, x2, y2, z2;
     double y1min, y1max, y2min, y2max;
@@ -1150,16 +1166,33 @@
     if (y1min > y2max || y1max < y2min)
 	return 0;
 
-    ret = Vect_segment_intersection(APnts->x[i], APnts->y[i], APnts->z[i],
-				    APnts->x[i + 1], APnts->y[i + 1],
-				    APnts->z[i + 1], BPnts->x[j], BPnts->y[j],
-				    BPnts->z[j], BPnts->x[j + 1],
-				    BPnts->y[j + 1], BPnts->z[j + 1], &x1,
-				    &y1, &z1, &x2, &y2, &z2, 0);
+    if (b) {
+	ret = Vect_segment_intersection(APnts->x[i], APnts->y[i],
+	                                APnts->z[i],
+					APnts->x[i + 1], APnts->y[i + 1],
+					APnts->z[i + 1],
+					BPnts->x[j], BPnts->y[j], 
+					BPnts->z[j],
+					BPnts->x[j + 1], BPnts->y[j + 1],
+					BPnts->z[j + 1],
+					&x1, &y1, &z1, &x2, &y2, &z2, 0);
+    }
+    else {
+	ret = Vect_segment_intersection(BPnts->x[j], BPnts->y[j],
+					BPnts->z[j],
+					BPnts->x[j + 1], BPnts->y[j + 1],
+					BPnts->z[j + 1], 
+					APnts->x[i], APnts->y[i],
+					APnts->z[i],
+					APnts->x[i + 1], APnts->y[i + 1],
+					APnts->z[i + 1],
+					&x1, &y1, &z1, &x2, &y2, &z2, 0);
+    }
 
     if (!IPnts)
 	IPnts = Vect_new_line_struct();
 
+    /* add ALL (including end points and duplicates), clean later */
     switch (ret) {
     case 0:
     case 5:
@@ -1177,12 +1210,8 @@
 	    G_warning(_("Error while adding point to array. Out of memory"));
 	break;
     }
-    /* add ALL (including end points and duplicates), clean later */
-    if (ret > 0) {
-	cross_found = 1;
-	return 0;
-    }
-    return 1;			/* keep going */
+
+    return ret;
 }
 
 /*!
@@ -1195,7 +1224,8 @@
  * \param with_z 3D, not supported (only if one or both are points)!
  *
  * \return 0 no intersection 
- * \return 1 intersection found
+ * \return 1 intersection
+ * \return 2 end points only
  */
 int
 Vect_line_check_intersection2(struct line_pnts *APoints,
@@ -1207,6 +1237,8 @@
     struct qitem qi, *found;
     struct RB_TREE *bo_ta, *bo_tb;
     struct RB_TRAV bo_t_trav;
+    int ret, intersect;
+    double xa1, ya1, xa2, ya2, xb1, yb1, xb2, yb2, xi, yi;
 
     APnts = APoints;
     BPnts = BPoints;
@@ -1218,6 +1250,7 @@
 
     if (!IPnts)
 	IPnts = Vect_new_line_struct();
+    Vect_reset_line(IPnts);
 
     /* If one or both are point (Points->n_points == 1) */
     if (APoints->n_points == 1 && BPoints->n_points == 1) {
@@ -1333,7 +1366,15 @@
     bo_tb = rbtree_create(cmp_t_y, sizeof(struct qitem));
 
     /* find intersection */
-    cross_found = 0;
+    xa1 = APnts->x[0];
+    ya1 = APnts->y[0];
+    xa2 = APnts->x[APnts->n_points - 1];
+    ya2 = APnts->y[APnts->n_points - 1];
+    xb1 = BPnts->x[0];
+    yb1 = BPnts->y[0];
+    xb2 = BPnts->x[BPnts->n_points - 1];
+    yb2 = BPnts->y[BPnts->n_points - 1];
+    intersect = 0;
     while (boq_drop(&bo_queue, &qi)) {
 
 	if (qi.e == QEVT_IN) {
@@ -1342,9 +1383,33 @@
 		/* test for intersection of s with all segments in T */
 		rbtree_init_trav(&bo_t_trav, bo_tb);
 		while ((found = rbtree_traverse(&bo_t_trav))) {
-		    find_cross(qi.s, found->s);
+		    ret = find_cross(qi.s, found->s, 0);
 
-		    if (cross_found) {
+		    if (ret > 0) {
+			if (ret != 1) {
+			    intersect = 1;
+			}
+			/* intersect at one point */
+			else if (intersect != 1) {
+			    intersect = 1;
+			    xi = IPnts->x[IPnts->n_points - 1];
+			    yi = IPnts->y[IPnts->n_points - 1];
+			    if (xi == xa1 && yi == ya1) {
+				if ((xi == xb1 && yi == yb1) ||
+				    (xi == xb2 && yi == yb2)) {
+				    intersect = 2;
+				}
+			    }
+			    else if (xi == xa2 && yi == ya2) {
+				if ((xi == xb1 && yi == yb1) ||
+				    (xi == xb2 && yi == yb2)) {
+				    intersect = 2;
+				}
+			    }
+			}
+		    }
+
+		    if (intersect == 1) {
 			break;
 		    }
 		}
@@ -1356,9 +1421,33 @@
 		/* test for intersection of s with all segments in T */
 		rbtree_init_trav(&bo_t_trav, bo_ta);
 		while ((found = rbtree_traverse(&bo_t_trav))) {
-		    find_cross(found->s, qi.s);
+		    ret = find_cross(found->s, qi.s, 1);
 
-		    if (cross_found) {
+		    if (ret > 0) {
+			if (ret != 1) {
+			    intersect = 1;
+			}
+			/* intersect at one point */
+			else if (intersect != 1) {
+			    intersect = 1;
+			    xi = IPnts->x[IPnts->n_points - 1];
+			    yi = IPnts->y[IPnts->n_points - 1];
+			    if (xi == xa1 && yi == ya1) {
+				if ((xi == xb1 && yi == yb1) ||
+				    (xi == xb2 && yi == yb2)) {
+				    intersect = 2;
+				}
+			    }
+			    else if (xi == xa2 && yi == ya2) {
+				if ((xi == xb1 && yi == yb1) ||
+				    (xi == xb2 && yi == yb2)) {
+				    intersect = 2;
+				}
+			    }
+			}
+		    }
+
+		    if (intersect == 1) {
 			break;
 		    }
 		}
@@ -1385,7 +1474,7 @@
 		    G_fatal_error("RB tree error!");
 	    }
 	}
-	if (cross_found) {
+	if (intersect == 1) {
 	    break;
 	}
     }
@@ -1393,7 +1482,7 @@
     rbtree_destroy(bo_ta);
     rbtree_destroy(bo_tb);
 
-    return cross_found;
+    return intersect;
 }
 
 /*!



More information about the grass-commit mailing list