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

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Nov 6 05:32:54 PST 2012


Author: mmetz
Date: 2012-11-06 05:32:54 -0800 (Tue, 06 Nov 2012)
New Revision: 53700

Modified:
   grass/trunk/lib/vector/Vlib/merge_lines.c
Log:
Vlib: improve Vect_merge_lines()

Modified: grass/trunk/lib/vector/Vlib/merge_lines.c
===================================================================
--- grass/trunk/lib/vector/Vlib/merge_lines.c	2012-11-06 13:32:16 UTC (rev 53699)
+++ grass/trunk/lib/vector/Vlib/merge_lines.c	2012-11-06 13:32:54 UTC (rev 53700)
@@ -20,6 +20,40 @@
 #include <grass/vector.h>
 #include <grass/glocale.h>
 
+/* compare category structures
+ * return 0 identical
+ * return 1 not identical
+ */
+static int compare_cats(struct line_cats *ACats, struct line_cats *BCats)
+{
+    int i, j;
+
+    if (ACats->n_cats == 0 && BCats->n_cats == 0)
+	return 0;
+
+    if (ACats->n_cats == 0 && BCats->n_cats > 0)
+	return 1;
+
+    if (ACats->n_cats > 0 && BCats->n_cats == 0)
+	return 1;
+
+    for (i = 0; i < ACats->n_cats; i++) {
+	int found = 0;
+
+	for (j = 0; j < BCats->n_cats; j++) {
+	    if (ACats->cat[i] == BCats->cat[j] &&
+	        ACats->field[i] == BCats->field[j]) {
+		found = 1;
+		break;
+	    }
+	}
+	if (!found)
+	    return 1;
+    }
+    
+    return 0;
+}
+
 /*!
    \brief Merge lines or boundaries in vector map.
 
@@ -42,22 +76,17 @@
 int Vect_merge_lines(struct Map_info *Map, int type, int *new_lines,
 		     struct Map_info *Err)
 {
-    int line, nlines, i, c, first, last, next_line, curr_line;
+    int line, nlines, i, first, last, next_line, curr_line;
     int merged = 0, newl = 0;
-    int next_node, direction, node_n_lines, same_type;
+    int next_node, direction, node_n_lines, ltype, lines_type;
     struct Plus_head *Plus;
     struct ilist *List;
     struct line_pnts *MPoints, *Points;
     struct line_cats *MCats, *Cats;
     struct P_line *Line;
 
-    if ((type & GV_BOUNDARY) && (type & GV_LINE)) {
+    if (!(type & GV_LINES)) {
 	G_warning
-	    ("Merging is done only with either lines or boundaries, not both types at the same time");
-	return 0;
-    }
-    if (!(type & GV_BOUNDARY) && !(type & GV_LINE)) {
-	G_warning
 	    ("Merging is done with lines or boundaries only, not with other types");
 	return 0;
     }
@@ -78,9 +107,12 @@
 	    continue;
 
 	Line = Plus->Line[line];
+	ltype = Line->type;
 
-	if (!(Line->type & type))
+	if (!(ltype & type))
 	    continue;
+	    
+	Vect_read_line(Map, NULL, MCats, line);
 
 	/* special cases:
 	 *  - loop back to start boundary via several other boundaries
@@ -91,48 +123,61 @@
 	/* go backward as long as there is only one other line/boundary at the current node */
 	G_debug(3, "go backward");
 	next_node = 0;
-	if (type == GV_LINE) {
+	if (ltype == GV_LINE) {
 	    struct P_topo_l *topo = (struct P_topo_l *)Line->topo;
+
 	    next_node = topo->N1;
 	}
-	else if (type == GV_BOUNDARY) {
+	else if (ltype == GV_BOUNDARY) {
 	    struct P_topo_b *topo = (struct P_topo_b *)Line->topo;
+
 	    next_node = topo->N1;
 	}
 	first = -line;
 	while (1) {
 	    node_n_lines = Vect_get_node_n_lines(Map, next_node);
-	    same_type = 0;
+	    /* count lines/boundaries at this node */
+	    lines_type = 0;
 	    next_line = first;
 	    for (i = 0; i < node_n_lines; i++) {
 		curr_line = Vect_get_node_line(Map, next_node, i);
-		if ((Plus->Line[abs(curr_line)]->type & type)) {
-		    same_type++;
-		    if (abs(curr_line) != abs(first))
-			next_line = curr_line;
+		if ((Plus->Line[abs(curr_line)]->type & GV_LINES))
+		    lines_type++;
+		if ((Plus->Line[abs(curr_line)]->type == ltype)) {
+		    if (abs(curr_line) != abs(first)) {
+			Vect_read_line(Map, NULL, Cats, abs(curr_line));
+			
+			/* catgories must be identical */
+			if (compare_cats(MCats, Cats) == 0)
+			    next_line = curr_line;
+		    }
 		}
 	    }
-	    if (same_type == 2 && abs(next_line) != abs(first) &&
+	    if (lines_type == 2 && abs(next_line) != abs(first) &&
 		abs(next_line) != line) {
 		first = next_line;
 
 		if (first < 0) {
-		    if (type == GV_LINE) {
+		    if (ltype == GV_LINE) {
 			struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[-first]->topo;
+
 			next_node = topo->N1;
 		    }
-		    else if (type == GV_BOUNDARY) {
+		    else if (ltype == GV_BOUNDARY) {
 			struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[-first]->topo;
+
 			next_node = topo->N1;
 		    }
 		}
 		else {
-		    if (type == GV_LINE) {
+		    if (ltype == GV_LINE) {
 			struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[first]->topo;
+
 			next_node = topo->N2;
 		    }
-		    else if (type == GV_BOUNDARY) {
+		    else if (ltype == GV_BOUNDARY) {
 			struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[first]->topo;
+
 			next_node = topo->N2;
 		    }
 		}
@@ -148,62 +193,75 @@
 	last = -first;
 
 	if (last < 0) {
-	    if (type == GV_LINE) {
+	    if (ltype == GV_LINE) {
 		struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[-last]->topo;
+
 		next_node = topo->N1;
 	    }
-	    else if (type == GV_BOUNDARY) {
+	    else if (ltype == GV_BOUNDARY) {
 		struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[-last]->topo;
+
 		next_node = topo->N1;
 	    }
 	}
 	else {
-	    if (type == GV_LINE) {
+	    if (ltype == GV_LINE) {
 		struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[last]->topo;
+
 		next_node = topo->N2;
 	    }
-	    else if (type == GV_BOUNDARY) {
+	    else if (ltype == GV_BOUNDARY) {
 		struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[last]->topo;
+
 		next_node = topo->N2;
 	    }
 	}
 
 	Vect_reset_list(List);
 	while (1) {
-	    Vect_list_append(List, last);
+	    G_ilist_add(List, last);
 	    node_n_lines = Vect_get_node_n_lines(Map, next_node);
-	    same_type = 0;
+	    lines_type = 0;
 	    next_line = last;
 	    for (i = 0; i < node_n_lines; i++) {
 		curr_line = Vect_get_node_line(Map, next_node, i);
-		if ((Plus->Line[abs(curr_line)]->type & type)) {
-		    same_type++;
-		    if (abs(curr_line) != abs(last))
-			next_line = curr_line;
+		if ((Plus->Line[abs(curr_line)]->type & GV_LINES))
+		    lines_type++;
+		if ((Plus->Line[abs(curr_line)]->type == ltype)) {
+		    if (abs(curr_line) != abs(last)) {
+			Vect_read_line(Map, NULL, Cats, abs(curr_line));
+			
+			if (compare_cats(MCats, Cats) == 0)
+			    next_line = curr_line;
+		    }
 		}
 	    }
 
-	    if (same_type == 2 && abs(next_line) != abs(last) &&
+	    if (lines_type == 2 && abs(next_line) != abs(last) &&
 		abs(next_line) != abs(first)) {
 		last = next_line;
 
 		if (last < 0) {
-		    if (type == GV_LINE) {
+		    if (ltype == GV_LINE) {
 			struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[-last]->topo;
+
 			next_node = topo->N1;
 		    }
-		    else if (type == GV_BOUNDARY) {
+		    else if (ltype == GV_BOUNDARY) {
 			struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[-last]->topo;
+
 			next_node = topo->N1;
 		    }
 		}
 		else {
-		    if (type == GV_LINE) {
+		    if (ltype == GV_LINE) {
 			struct P_topo_l *topo = (struct P_topo_l *)Plus->Line[last]->topo;
+
 			next_node = topo->N2;
 		    }
-		    else if (type == GV_BOUNDARY) {
+		    else if (ltype == GV_BOUNDARY) {
 			struct P_topo_b *topo = (struct P_topo_b *)Plus->Line[last]->topo;
+
 			next_node = topo->N2;
 		    }
 		}
@@ -216,26 +274,21 @@
 	if (List->n_values > 1) {
 	    G_debug(3, "merge %d lines", List->n_values);
 	    Vect_reset_line(MPoints);
-	    Vect_reset_cats(MCats);
 
 	    for (i = 0; i < List->n_values; i++) {
 		Vect_reset_line(Points);
-		Vect_reset_cats(Cats);
 		Vect_read_line(Map, Points, Cats, abs(List->value[i]));
 		direction = (List->value[i] < 0 ? GV_BACKWARD : GV_FORWARD);
 		Vect_append_points(MPoints, Points, direction);
 		MPoints->n_points--;
-		for (c = 0; c < Cats->n_cats; c++) {
-		    Vect_cat_set(MCats, Cats->field[c], Cats->cat[c]);
-		}
 		if (Err) {
 		    /* write out lines/boundaries to be merged */
-		    Vect_write_line(Err, type, Points, Cats);
+		    Vect_write_line(Err, ltype, Points, Cats);
 		}
 		Vect_delete_line(Map, abs(List->value[i]));
 	    }
 	    MPoints->n_points++;
-	    Vect_write_line(Map, type, MPoints, MCats);
+	    Vect_write_line(Map, ltype, MPoints, MCats);
 	    merged += List->n_values;
 	    newl++;
 	}



More information about the grass-commit mailing list