[GRASS-SVN] r70554 - grass/trunk/lib/vector/vedit

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Feb 13 22:55:56 PST 2017


Author: hcho
Date: 2017-02-13 22:55:56 -0800 (Mon, 13 Feb 2017)
New Revision: 70554

Modified:
   grass/trunk/lib/vector/vedit/break.c
Log:
vedit: Vedit_connect_lines handles two more cases properly by extending both
lines.

Since dist was not always the normal distance from line_from to line_to (cases
2 & 3), dist_p sometimes overestimated the distance of extension and resulted
in unexpected connections (e.g., case 2).

\                        \
 \             ->         \
      --                   \   ---
                            \/



Modified: grass/trunk/lib/vector/vedit/break.c
===================================================================
--- grass/trunk/lib/vector/vedit/break.c	2017-02-13 21:11:32 UTC (rev 70553)
+++ grass/trunk/lib/vector/vedit/break.c	2017-02-14 06:55:56 UTC (rev 70554)
@@ -16,6 +16,8 @@
 
 static int connect_lines(struct Map_info *, int, int, int,
 			 double, struct ilist *);
+static int find_extended_intersection(double, double, double, double, double,
+				      double, double *, double *);
 
 /*!
   \brief Split selected lines on given position
@@ -137,21 +139,39 @@
   \brief Connect lines in given threshold
   
   \code
-        \	             \
-   id1   \           ->	      \
-                               \
-   id2 ---------           -----+---
-   \endcode
+  1. Extend first line only
+          \                      \
+     id1   \             ->       \
+                                   \
+     id2 ----------            -----+----
 
-   If two lines are selected and <i>thresh</i> is -1, no limit is
-   applied.
 
-   \param Map pointer to Map_info
-   \param List list of selected lines
-   \param thresh threshold value
+  2. Extend both lines
+          \                      \
+     id1   \             ->       \
+                                   \
+     id2        ---                 +----
 
-   \return number of modified lines
-   \return -1 on error
+
+  3. Extend first line when both are on the same line
+     id1 ---    --- id2  ->    -----+----
+
+
+  4. Don't connect two lines that don't intersect
+     id1 ------                ------
+                         ->
+     id2     ------                ------
+  \endcode
+
+  If two lines are selected and <i>thresh</i> is -1, no limit is
+  applied.
+
+  \param Map pointer to Map_info
+  \param List list of selected lines
+  \param thresh threshold value
+
+  \return number of modified lines
+  \return -1 on error
  */
 int Vedit_connect_lines(struct Map_info *Map, struct ilist *List,
 			double thresh)
@@ -194,6 +214,9 @@
 
 	    do {
 		/* find first nearest line */
+		/* thresh=-1 for Vect_find_line_list doesn't mean no limit
+		 * search => inconsistent behavior! Either this is a bug or the
+		 * function description is incorrect. */
 		found = Vect_find_line_list(Map, x, y, z,
 					    GV_LINES, thresh, WITHOUT_Z,
 					    List_exclude, List_found);
@@ -227,8 +250,8 @@
     int type_from, type_to;
     int n_points, seg, is;
     double x, y, px, py, x1, y1;
-    double dist, spdist, lpdist, length, dist_p;
-    double angle_t, angle_f, angle;
+    double dist, spdist, lpdist, length;
+    double angle_t, angle_f;
 
     struct line_pnts *Points_from, *Points_to, *Points_final;
     struct line_cats *Cats_from, *Cats_to;
@@ -247,12 +270,13 @@
 	line_new = -1;
 
     if (line_new > -1) {
+	n_points = Points_from->n_points - 1;
+
 	if (first) {
 	    x = Points_from->x[0];
 	    y = Points_from->y[0];
 	}
 	else {
-	    n_points = Points_from->n_points - 1;
 	    x = Points_from->x[n_points];
 	    y = Points_from->y[n_points];
 	}
@@ -271,22 +295,9 @@
 		if (Vect_point_on_line(Points_to, lpdist,
 				       NULL, NULL, NULL, &angle_t,
 				       NULL) > 0) {
-		    angle = angle_t - angle_f;
-		    dist_p = fabs(dist / sin(angle));
-		    
-		    if (first) {
-			if (angle_f < 0)
-			    angle_f -= M_PI;
-			else
-			    angle_f += M_PI;
-		    }
-
-		    x1 = x + dist_p * cos(angle_f);
-		    y1 = y + dist_p * sin(angle_f);
-
-		    length = Vect_line_length(Points_to);
-		    Vect_line_insert_point(Points_to, seg, x1, y1, 0.);
-		    if (fabs(Vect_line_length(Points_to) - length) < length * 1e-3) {
+		    /* extend both line_from & line_to and find intersection */
+		    if (find_extended_intersection(x, y, angle_f,
+						   px, py, angle_t, &x1, &y1)) {
 			/* lines connected -> split line_to */
 			/* update line_from */
 			if (first) {
@@ -302,31 +313,37 @@
 						     Points_from, Cats_from);
 			/* Vect_list_append(List, line_new); */
 			
-			/* update line_to  -- first part */
-			Vect_reset_line(Points_final);
-			for (is = 0; is < seg; is++) {
-			    Vect_append_point(Points_final, Points_to->x[is],
-					  Points_to->y[is],
-					      Points_to->z[is]);
-			}
-			Vect_append_point(Points_final, x1, y1, 0.0);
-			line_new = Vect_rewrite_line(Map, line_to, type_to,
-						     Points_final, Cats_to);
-			/* Vect_list_append(List, line_new); */
+			length = Vect_line_length(Points_to);
+			/* avoid adding duplicate nodes */
+			if (lpdist > 0 && lpdist < length) {
+			    /* update line_to  -- first part */
+			    Vect_reset_line(Points_final);
+			    for (is = 0; is < seg; is++) {
+				Vect_append_point(Points_final,
+						  Points_to->x[is],
+						  Points_to->y[is],
+						  Points_to->z[is]);
+			    }
+			    Vect_append_point(Points_final, x1, y1, 0.0);
+			    line_new = Vect_rewrite_line(Map, line_to, type_to,
+							 Points_final, Cats_to);
+			    /* Vect_list_append(List, line_new); */
 			
-			/* write second part */
-			Vect_reset_line(Points_final);
-			Vect_append_point(Points_final, x1, y1, 0.0);
-			for (is = seg; is < Points_to->n_points; is++) {
-			    Vect_append_point(Points_final, Points_to->x[is],
-					      Points_to->y[is],
-					      Points_to->z[is]);
+			    /* write second part */
+			    Vect_reset_line(Points_final);
+			    Vect_append_point(Points_final, x1, y1, 0.0);
+			    for (is = seg; is < Points_to->n_points; is++) {
+				Vect_append_point(Points_final,
+						  Points_to->x[is],
+						  Points_to->y[is],
+						  Points_to->z[is]);
+			    }
+			
+			    /* rewrite first part */
+			    line_new = Vect_write_line(Map, type_to,
+						       Points_final, Cats_to);
+			    /* Vect_list_append(List, line_new); */
 			}
-			
-			/* rewrite first part */
-			line_new = Vect_write_line(Map, type_to,
-						   Points_final, Cats_to);
-			/* Vect_list_append(List, line_new); */
 		    }
 		}
 	    }
@@ -341,3 +358,42 @@
 
     return line_new > 0 ? 1 : 0;
 }
+
+static int find_extended_intersection(double x1, double y1, double angle1,
+				      double x2, double y2, double angle2,
+				      double *x, double *y)
+{
+    double c1, s1, c2, s2, d, a;
+
+    if (fabs(sin(angle1 - angle2)) <= 1e-10) {
+	/* two lines are parallel */
+	double angle;
+
+	angle = atan2(y2 - y1, x2 - x1);
+	if (angle == angle1) {
+	    /* they are on the same line */
+	    *x = x2;
+	    *y = y2;
+
+	    return 1;
+	}
+
+	/* two lines don't intersect */
+	return 0;
+    }
+
+    c1 = cos(angle1);
+    s1 = sin(angle1);
+    c2 = cos(angle2);
+    s2 = sin(angle2);
+    d = -c1 * s2 + c2 * s1;
+    if (d == 0.0)
+	/* shouldn't happen again */
+	return 0;
+
+    a = (-s2 * (x2 - x1) + c2 * (y2 - y1)) / d;
+    *x = x1 + a * c1;
+    *y = y1 + a * s1;
+
+    return 1;
+}



More information about the grass-commit mailing list