[GRASS-SVN] r32284 - grass/branches/develbranch_6/lib/vector/vedit

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Jul 25 06:24:37 EDT 2008


Author: martinl
Date: 2008-07-25 06:24:37 -0400 (Fri, 25 Jul 2008)
New Revision: 32284

Modified:
   grass/branches/develbranch_6/lib/vector/vedit/break.c
Log:
veditlib: connect_lines() rewritten (merged from trunk, r32283)

Modified: grass/branches/develbranch_6/lib/vector/vedit/break.c
===================================================================
--- grass/branches/develbranch_6/lib/vector/vedit/break.c	2008-07-25 10:23:18 UTC (rev 32283)
+++ grass/branches/develbranch_6/lib/vector/vedit/break.c	2008-07-25 10:24:37 UTC (rev 32284)
@@ -1,29 +1,31 @@
 /**
-   \file break.c
+   \file vector/vedit/break.c
 
-   \brief Vedit library - split/break lines
+   \brief Vedit library - split / break lines
 
-   This program is free software under the
-   GNU General Public License (>=v2).
-   Read the file COPYING that comes with GRASS
-   for details.
+   (C) 2007-2008 by the GRASS Development Team
 
-   \author (C) 2007-2008 by the GRASS Development Team
-   Martin Landa <landa.martin gmail.com>
+   This program is free software under the GNU General Public License
+   (>=v2).  Read the file COPYING that comes with GRASS for details.
 
+   \author Martin Landa <landa.martin gmail.com>
+
    \date 2007-2008
 */
 
 #include <math.h>
 #include <grass/vedit.h>
 
+static int connect_lines(struct Map_info *, int, int, int,
+			 double, struct ilist *);
+
 /**
    \brief Split selected lines on given position
    
-   \param[in] Map vector map
-   \param[in] List list of selected lines
-   \param[in] coord points location
-   \param[in] List_updated list of rewritten features (or NULL)
+   \param Map vector map
+   \param List list of selected lines
+   \param coord points location
+   \param[out] List_updated list of rewritten features (or NULL)
 
    \return number of modified lines
    \return -1 on error
@@ -132,206 +134,193 @@
 }
 
 /**
-   \brief Connect *two* lines
+   \brief Connect lines in given threshold
  
-   The first line from the list is connected to the second one
-   if necessary the second line is broken
- 
-   \			     \
-   id1  \           ->	      \
+   <pre>
+        \         	     \
+   id1   \           ->	      \
                                \
-   id2 ---------           ---------
- 
-   \param[in] Map vector map
-   \param[in] List list of selected lines
-   \param[in] thresh threshold value for connect
+   id2 ---------           -----+---
+   </pre>
 
-   \return  1 lines connected
-   \return  0 lines not connected
+   \param Map vector map
+   \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)
 {
-    int nlines_modified, newline, intersection, linep, nlines_to_modify;
-    int i, idx, pnt_idx[2];
-    int line[2], type[2], seg[2];
-    double px[2], py[2], pz[2], dist[2], spdist[2], lpdist[2];
-    double nx[2], ny[2], nz[2];
-    char   n_on_line[2], connected;
-    double angle, dseg, dist_connect;
-
-    struct ilist *List_break, *List_updated;
-
-    struct line_pnts *Points[2];
-    struct line_cats *Cats[2];
-
+    int nlines_modified;
+    int i, j, node[2], n_nodes;
+    int line, found;
+    double x, y, z;
+    
     nlines_modified  = 0;
-    nlines_to_modify = 2; /* modify *two* lines at the time */
 
-    Points[0] = Points[1] = NULL;
-    Cats[0]   = Cats[1]   = NULL;
+    /* collect lines to be modified */
+    for (i = 0; i < List->n_values; i++) {
+	line = List->value[i];
 
-    List_break = Vect_new_list ();
-    List_updated = Vect_new_list();
+	if (!Vect_line_alive(Map, line))
+	    continue;
 
-    for (linep = 0; linep < List -> n_values; linep += 2) {
-	connected = 0;
-	/* read the lines */
-	for (i = 0; i < nlines_to_modify; i++) {
-	    line[i] = List -> value[linep + i];
+	node[0] = node[1] = -1;
 
-	    if (!Vect_line_alive (Map, line[i])) {
-		line[i] = -1;
-		break;
-	    }
-	    if (!Points[i])
-		Points[i] = Vect_new_line_struct();
-	    if (!Cats[i])
-		Cats[i] = Vect_new_cats_struct();
+	Vect_get_line_nodes(Map, line, &(node[0]), &(node[1]));
+	if (node[0] < 0 || node[1] < 0)
+	    continue;
 
-	    type[i] = Vect_read_line(Map, Points[i], Cats[i], line[i]);
-
-	    if (!(type[i] & GV_LINES)) {
-		line[i] = -1;
-		break;
+	n_nodes = 2;
+	for (j = 0; j < n_nodes; j++) {
+	    /* for each line node find lines in threshold */
+	    Vect_get_node_coor(Map, node[j], &x, &y, &z);
+	    found = Vect_find_line(Map, x, y, z,
+				   GV_LINES, thresh, WITHOUT_Z,
+				   line);
+	    
+	    if (found > 0 && Vect_line_alive(Map, found)) {
+		/* try to connect lines (given node) */
+		G_debug(3, "Vedit_connect_lines(): lines=%d,%d",
+			line, found);
+		if (connect_lines(Map, !j, line, found, thresh, List)) {
+		    G_debug(3, "    -> connected");
+		    nlines_modified += 2;
+		    break;
+		}
 	    }
 	}
+    }
 
-	if (line[0] == -1 || line[1] == -1)
-	    continue;
+    return nlines_modified;
+}
 
-	/* check lines intersection 
-	   if (Vect_line_check_intersection (Points[0], Points[1], WITHOUT_Z))
-	   return 0;
-	*/
+int connect_lines(struct Map_info *Map, int first, int line_from, int line_to,
+		  double thresh, struct ilist *List)
+{
+    int line_new;
+    int type_from, type_to;
+    int n_points, seg, is;
+    double x, y, px, py, fx, fy, x1, y1;
+    double dist, spdist, lpdist, length, dist_p, dist_1, dist_2, dist_3;
+    double angle_p, angle_n, angle;
 
-	/* find node to connect */
-	for (i = 0; i < nlines_to_modify; i++) {
-	    if (i == 0)
-		idx = 0;
-	    else
-		idx = Points[0] -> n_points - 1;
+    struct line_pnts *Points_from, *Points_to, *Points_final;
+    struct line_cats *Cats_from, *Cats_to;
 
-	    seg[i] = Vect_line_distance (Points[1], Points[0]->x[idx], Points[0]->y[idx], Points[0]->z[idx],
-					 WITHOUT_Z,
-					 &px[i], &py[i], &pz[i],
-					 &dist[i], &spdist[i], &lpdist[i]);
-	}
+    Points_from = Vect_new_line_struct();
+    Points_to = Vect_new_line_struct();
+    Points_final = Vect_new_line_struct();
+    Cats_from = Vect_new_cats_struct();
+    Cats_to = Vect_new_cats_struct();
 
-	idx        = (dist[0] <= dist[1]) ? 0 : 1;
-	pnt_idx[0] = (idx == 0) ? 0 : Points[0] -> n_points - 1; /* which node to connect */
+    type_from = Vect_read_line(Map, Points_from, Cats_from, line_from);
+    type_to = Vect_read_line(Map, Points_to, Cats_to, line_to);
 
-	angle =
-	    M_PI / 2 -
-	    acos (fabs (Points[0] -> x[0] - Points[0] -> x[Points[0] -> n_points - 1]) /
-		  Vect_line_length (Points[0])) -
-	    asin (fabs (Points[1] -> y[seg[idx] - 1] - py[idx]) / spdist[idx]);
-	
-	dseg = dist[idx] * tan (angle);
+    line_new = 0;
+    if (!(type_from & GV_LINES) || !(type_to & GV_LINES))
+	line_new = -1;
 
-	/* compute connect points */
-	for (i = 0; i < nlines_to_modify; i++) {
-	    if (0 == Vect_point_on_line (Points[1], lpdist[idx] + dseg, &nx[i], &ny[i], &nz[i], NULL, NULL)) {
-		n_on_line[i] = 0;
-	    }
-	    else {
-		n_on_line[i] = 1;
-	    }
-	    dseg *= -1.0;
+    if (line_new > -1) {
+	/* get node (line_from/node) */
+	if (first) {
+	    x = Points_from->x[0];
+	    y = Points_from->y[0];
+	    x1 = Points_from->x[1];
+	    y1 = Points_from->y[1];
 	}
-    
-	if (!n_on_line[0] || !n_on_line[1]) {
-	    G_warning (_("Unable to connect lines %d,%d"), line[0], line[1]);
-	    continue;
+	else {
+	    n_points = Points_from->n_points - 1;
+	    x = Points_from->x[n_points];
+	    y = Points_from->y[n_points];
+	    x1 = Points_from->x[n_points-1];
+	    y1 = Points_from->y[n_points-1];
 	}
+	Vect_line_distance(Points_to, x, y, 0.0, WITHOUT_Z,
+			   &px, &py, NULL, &dist, &spdist, &lpdist);
+	if (dist > 0.0 && dist <= thresh) {
+	    /* lines in threshold */
+	    if (first)
+		length = 0;
+	    else
+		length = Vect_line_length(Points_from);
 
-	/* choose connect point */
-	if (idx == 0)
-	    pnt_idx[1] = Points[0] -> n_points - 1;
-	else
-	    pnt_idx[1] = 0;
-	
-	if (Vect_points_distance (nx[0], ny[0], nz[0],
-				  Points[0] -> x[pnt_idx[1]], Points[0] -> y[pnt_idx[1]],
-				  Points[0] -> z[pnt_idx[1]],
-				  WITHOUT_Z) >
-	    Vect_points_distance (nx[1], ny[1], nz[1],
-				  Points[0] -> x[pnt_idx[1]], Points[0] -> y[pnt_idx[1]],
-				  Points[0] -> z[pnt_idx[1]],
-				  WITHOUT_Z))
-	    pnt_idx[1] = 0;
-	else
-	    pnt_idx[1] = 1;
-	
-	dist_connect = Vect_points_distance (nx[pnt_idx[1]], ny[pnt_idx[1]], nz[pnt_idx[1]],
-					     Points[0] -> x[pnt_idx[0]], Points[0] -> y[pnt_idx[0]],
-					     Points[0] -> z[pnt_idx[0]],
-					     WITHOUT_Z);
+	    if (Vect_point_on_line(Points_from, length,
+				   NULL, NULL, NULL, &angle_n, NULL) > 0) {
+		if (Vect_point_on_line(Points_to, lpdist,
+				       NULL, NULL, NULL, &angle_p, NULL) > 0) {
+		    angle = angle_p - angle_n;
+		    dist_p = dist / tan(angle);
 
-	G_debug (3, "Vedit_connect_lines(): dist=%f/%f -> pnt_idx=%d -> "
-		 "x=%f, y=%f / dist_connect=%f (thresh=%f)",
-		 dist[0], dist[1], pnt_idx[0], nx[pnt_idx[1]], ny[pnt_idx[1]], dist_connect, thresh);
+		    seg = Vect_point_on_line(Points_to, lpdist + dist_p,
+					     &fx, &fy, NULL, NULL, NULL);
+		    dist_1 = Vect_points_distance(x, y, 0.0,
+						  fx, fy, 0.0, WITHOUT_Z);
+		    dist_2 = Vect_points_distance(x1, y1, 0.0,
+						  x, y, 0.0, WITHOUT_Z);
+		    dist_3 = Vect_points_distance(x1, x1, 0.0,
+						  fx, fy, 0.0, WITHOUT_Z);
 
-	if (thresh >= 0.0 && dist_connect > thresh) {
-	    continue;
-	}
-    
-	/* modify the first line */
-	Vect_reset_list (List_updated);
-	intersection = Vect_line_check_intersection (Points[0], Points[1], WITHOUT_Z);
+		    if (dist_3 < dist_1 + dist_2) {
+			seg = Vect_point_on_line(Points_to, lpdist - dist_p,
+						 &fx, &fy, NULL, NULL, NULL);
+		    }
 
-	if (!intersection) {
-	    if (pnt_idx[0] == 0)
-		Vect_line_insert_point (Points[0], 0, nx[pnt_idx[1]], ny[pnt_idx[1]], 0.0);
-	    else
-		Vect_append_point (Points[0], nx[pnt_idx[1]], ny[pnt_idx[1]], 0.0);
-	    
-	    /* rewrite the first line */
-	    newline = Vect_rewrite_line (Map, line[0], type[0], Points[0], Cats[0]);
-	    if (newline < 0) {
-		return -1;
+		    if(seg > 0) {
+			/* lines connected -> split line_to */
+			/* update line_from */
+			if (first) {
+			    Points_from->x[0] = fx;
+			    Points_from->y[0] = fy;
+			    Points_from->z[0] = 0.0;
+			}
+			else {
+			    n_points = Points_from->n_points - 1;
+			    Points_from->x[n_points] = fx;
+			    Points_from->y[n_points] = fy;
+			    Points_from->z[n_points] = 0.0;
+			}
+			line_new = Vect_rewrite_line(Map, line_from, type_from,
+						     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, fx, fy, 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, fx, fy, 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);
+		
+		    }
+		}
 	    }
-	    Vect_list_append (List_updated, newline);
-	    connected = 1;
 	}
-	else
-	    Vect_list_append (List_updated, line[0]);
-	
-	/* break the second line */
-	Vect_reset_list (List_break);
-	if (!intersection ||
-	    (intersection &&
-	     Vect_points_distance (nx[pnt_idx[1]], ny[pnt_idx[1]], nz[pnt_idx[1]],
-				   Points[0] -> x[pnt_idx[0]], Points[0] -> y[pnt_idx[0]],
-				   Points[0] -> z[pnt_idx[0]],
-				   WITHOUT_Z) <= 0.0)) {
-	    Vect_list_append (List_break, line[1]);
-	    struct line_pnts *coord = Vect_new_line_struct();
-	    Vect_append_point(coord, nx[pnt_idx[1]], ny[pnt_idx[1]], nz[pnt_idx[1]]);
-	    Vedit_split_lines(Map, List_break, 
-			      coord, 1e-1, 
-			      List_updated);
-	    Vect_destroy_line_struct(coord);
-	    /* snap lines */
-	    Vect_snap_lines_list (Map, List_updated, 1e-1, NULL, NULL);
-	    connected = 1;
-	}
-	
-	if (connected)
-	    nlines_modified += 2;
-
-    } /* for each line pair */
-
-    /* destroy structures */
-    for (i = 0; i < nlines_to_modify; i++) {
-	if (Points[i])
-	    Vect_destroy_line_struct(Points[i]);
-	if (Cats[i])
-	    Vect_destroy_cats_struct(Cats[i]);
     }
-    Vect_destroy_list (List_break);
-    Vect_destroy_list (List_updated);
 
-    return nlines_modified == 2 ? 1 : 0;
+    Vect_destroy_line_struct(Points_from);
+    Vect_destroy_line_struct(Points_to);
+    Vect_destroy_line_struct(Points_final);
+    Vect_destroy_cats_struct(Cats_from);
+    Vect_destroy_cats_struct(Cats_to);
+
+    return line_new > 0 ? 1 : 0;
 }



More information about the grass-commit mailing list