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

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Dec 5 10:51:57 EST 2011


Author: mmetz
Date: 2011-12-05 07:51:57 -0800 (Mon, 05 Dec 2011)
New Revision: 49551

Modified:
   grass/trunk/lib/vector/Vlib/break_lines.c
   grass/trunk/lib/vector/Vlib/build.c
Log:
add new fns for topology check

Modified: grass/trunk/lib/vector/Vlib/break_lines.c
===================================================================
--- grass/trunk/lib/vector/Vlib/break_lines.c	2011-12-05 15:51:09 UTC (rev 49550)
+++ grass/trunk/lib/vector/Vlib/break_lines.c	2011-12-05 15:51:57 UTC (rev 49551)
@@ -17,6 +17,10 @@
 #include <grass/vector.h>
 #include <grass/glocale.h>
 
+static int break_lines(struct Map_info *, struct ilist *, struct ilist *,
+		       int, struct Map_info *, int);
+
+
 /*!
    \brief Break lines in vector map at each intersection.
 
@@ -32,7 +36,7 @@
 void
 Vect_break_lines(struct Map_info *Map, int type, struct Map_info *Err)
 {
-    Vect_break_lines_list(Map, NULL, NULL, type, Err);
+    break_lines(Map, NULL, NULL, type, Err, 0);
 
     return;
 }
@@ -61,8 +65,61 @@
 
 int
 Vect_break_lines_list(struct Map_info *Map, struct ilist *List_break,
-		      struct ilist *List_ref, int type, struct Map_info *Err)
+		      struct ilist *List_ref, int type,
+		      struct Map_info *Err)
 {
+    return break_lines(Map, List_break, List_ref, type, Err, 0);
+}
+
+/*!
+   \brief Check for and count intersecting lines, do not break.
+
+   For details see Vect_break_lines_list().
+
+   \param Map input vector map 
+   \param type feature type
+   \param[out] Err vector map where points at intersections will be written or NULL
+
+   \return
+ */
+
+int
+Vect_check_line_breaks(struct Map_info *Map, int type, struct Map_info *Err)
+{
+    return break_lines(Map, NULL, NULL, type, Err, 1);
+}
+
+/*!
+   \brief Check for and count intersecting lines, do not break.
+
+   If <i>List_break</i> is given, only lines in the list are checked for
+   intersections.
+
+   If reference lines are given (<i>List_ref</i>) break only lines
+   which intersect reference lines.
+
+   \param Map input vector map 
+   \param List_break list of lines (NULL for all lines in vector map)
+   \param List_ref list of reference lines or NULL
+   \param type feature type
+   \param[out] Err vector map where points at intersections will be written or NULL
+
+   \return number of intersections
+ */
+
+int
+Vect_check_line_breaks_list(struct Map_info *Map, struct ilist *List_break,
+		      struct ilist *List_ref, int type,
+		      struct Map_info *Err)
+{
+    return break_lines(Map, List_break, List_ref, type, Err, 1);
+}
+
+int
+break_lines(struct Map_info *Map, struct ilist *List_break,
+		      struct ilist *List_ref, int type,
+		      struct Map_info *Err, int check)
+{
     struct line_pnts *APoints, *BPoints, *Points;
     struct line_pnts **AXLines, **BXLines;
     struct line_cats *ACats, *BCats, *Cats;
@@ -177,7 +234,7 @@
 
 	    btype = Vect_read_line(Map, BPoints, BCats, bline);
 
-	    /* Check if thouch by end node only */
+	    /* Check if touch by end node only */
 	    if (!is3d) {
 		Vect_get_line_nodes(Map, aline, &anode1, &anode2);
 		Vect_get_line_nodes(Map, bline, &bnode1, &bnode2);
@@ -267,13 +324,16 @@
 	    }
 	    nx = 0;		/* number of intersections to be written to Err */
 	    if (naxlines > 0) {	/* intersection -> write out */
-		Vect_delete_line(Map, aline);
+		if (!check)
+		    Vect_delete_line(Map, aline);
 		for (k = 0; k < naxlines; k++) {
 		    /* Write new line segments */
 		    /* line may collapse, don't write zero length lines */
 		    Vect_line_prune(AXLines[k]);
 		    if ((atype & GV_POINTS) || AXLines[k]->n_points > 1) {
-			ret = Vect_write_line(Map, atype, AXLines[k], ACats);
+			if (!check)
+			    ret = Vect_write_line(Map, atype, AXLines[k],
+			                          ACats);
 			if (List_ref) {
 			    Vect_list_append(List_ref, ret);
 			}
@@ -302,15 +362,17 @@
 
 	    if (nbxlines > 0) {
 		if (aline != bline) {	/* Self intersection, do not write twice, TODO: is it OK? */
-		    Vect_delete_line(Map, bline);
+		    if (!check)
+			Vect_delete_line(Map, bline);
 		    for (k = 0; k < nbxlines; k++) {
 			/* Write new line segments */
 			/* line may collapse, don't write zero length lines */
 			Vect_line_prune(BXLines[k]);
 			if ((btype & GV_POINTS) || BXLines[k]->n_points > 1) {
-			    ret =
-				Vect_write_line(Map, btype, BXLines[k],
-						BCats);
+			    if (!check)
+				ret =
+				    Vect_write_line(Map, btype, BXLines[k],
+						    BCats);
 			    G_debug(5, "Line %d written", ret);
 			    if (List_break) {
 				Vect_list_append(List_break, ret);

Modified: grass/trunk/lib/vector/Vlib/build.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build.c	2011-12-05 15:51:09 UTC (rev 49550)
+++ grass/trunk/lib/vector/Vlib/build.c	2011-12-05 15:51:57 UTC (rev 49551)
@@ -487,6 +487,158 @@
 }
 
 /*!
+   \brief Extensive tests for correct topology
+
+   \param Map vector map
+   \param[out] Err vector map where errors will be written
+
+   \return 1 on success
+   \return 0 on error
+ */
+int Vect_topo_check(struct Map_info *Map, struct Map_info *Err)
+{
+    int line, nlines;
+    int nerrors, n_zero_lines, n_zero_boundaries;
+    struct line_pnts *Points;
+    struct line_cats *Cats;
+
+    if (Vect_get_built(Map) != GV_BUILD_ALL) {
+	Vect_build_partial(Map, GV_BUILD_NONE);
+	Vect_build(Map);
+    }
+
+    G_message(_("Checking for topological errors..."));
+
+    Points = Vect_new_line_struct();
+    Cats = Vect_new_cats_struct();
+
+    /* boundaries of zero length */
+    n_zero_lines = n_zero_boundaries = 0;
+    nlines = Vect_get_num_lines(Map);
+    for (line = 1; line <= nlines; line++) {
+	int type;
+	
+	if (!Vect_line_alive(Map, line))
+	    continue;
+	    
+	type = Vect_get_line_type(Map, line);
+
+	if (type & GV_LINES) {
+	    double len;
+	    
+	    Vect_read_line(Map, Points, Cats, line);
+	    len = Vect_line_length(Points);
+	    
+	    if (len == 0) {
+		if (type & GV_LINE)
+		    n_zero_lines++;
+		else if (type & GV_BOUNDARY)
+		    n_zero_boundaries++;
+		    
+		if (Err)
+		    Vect_write_line(Err, type, Points, Cats);
+	    }
+	}
+    }
+    if (n_zero_lines)
+	G_warning(_("Number of lines of length zero: %d"), n_zero_lines);
+    if (n_zero_boundaries)
+	G_warning(_("Number of boundaries of length zero: %d"), n_zero_boundaries);
+
+    /* remaining checks are for areas only */
+    if (Vect_get_num_primitives(Map, GV_BOUNDARY) == 0)
+	return 1;
+
+    /* intersecting boundaries -> overlapping areas */
+    nerrors = Vect_check_line_breaks(Map, GV_BOUNDARY, Err);
+    if (nerrors)
+	G_warning(_("Number of boundary intersections: %d"), nerrors);
+
+    /* areas without centroids that are not holes
+     * only makes sense if all boundaries are correct */
+    nerrors = 0;
+    for (line = 1; line <= nlines; line++) {
+	int type;
+	
+	if (!Vect_line_alive(Map, line))
+	    continue;
+	    
+	type = Vect_get_line_type(Map, line);
+
+	if (type == GV_BOUNDARY) {
+	    struct P_topo_b *topo = (struct P_topo_b *)Map->plus.Line[line]->topo;
+
+	    if (topo->left == 0 || topo->right == 0) {
+		G_debug(3, "line = %d left = %d right = %d", line, 
+			topo->left, topo->right);
+		nerrors++;
+	    }
+	}
+    }
+    if (nerrors)
+	G_warning(_("Skipping further checks because of incorrect boundaries"));
+    else {
+	int i, area, left, right, neighbour;
+	int nareas = Vect_get_num_areas(Map);
+	struct ilist *List = Vect_new_list();
+
+	nerrors = 0;
+	for (area = 1; area <= nareas; area++) {
+	    if (!Vect_area_alive(Map, area))
+		continue;
+	    line = Vect_get_area_centroid(Map, area);
+	    if (line != 0)
+		continue;   /* has centroid */
+
+	    Vect_get_area_boundaries(Map, area, List);
+	    for (i = 0; i < List->n_values; i++) {
+		line = List->value[i];
+		Vect_get_line_areas(Map, abs(line), &left, &right);
+		if (line > 0)
+		    neighbour = left;
+		else
+		    neighbour = right;
+		    
+		if (neighbour < 0) {
+		    neighbour = Vect_get_isle_area(Map, abs(neighbour));
+		    if (!neighbour) {
+			/* borders outer void */
+			nerrors++;
+			if (Err) {
+			    Vect_read_line(Map, Points, Cats, abs(line));
+			    Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
+			}
+		    }
+		    /* else neighbour is > 0, check below */
+		}
+		if (neighbour > 0) {
+		    if (Vect_get_area_centroid(Map, neighbour) == 0) {
+			/* neighbouring area does not have a centroid either */
+			nerrors++;
+			if (Err) {
+			    Vect_read_line(Map, Points, Cats, abs(line));
+			    Vect_write_line(Err, GV_BOUNDARY, Points, Cats);
+			}
+		    }
+		}
+	    }
+	}
+	Vect_destroy_list(List);
+
+	if (nerrors)
+	    G_warning(_("Number of redundant holes: %d"), 
+	              nerrors);
+    }
+
+    /* what else ? */
+
+    Vect_destroy_line_struct(Points);
+    Vect_destroy_cats_struct(Cats);
+
+    return 1;
+}
+
+/*!
    \brief Return current highest built level (part)
 
    \param Map vector map
@@ -642,20 +794,28 @@
 	G_message(_("Number of areas: %d"), plus->n_areas);
 	G_message(_("Number of isles: %d"), plus->n_isles);
 
+#if 0
+	/* not an error, message disabled to avoid confusion */
+	if (err_nocentr)
+	    G_message(_("Number of areas without centroid: %d"),
+		      err_nocentr);
+#endif
+
+	if (plus->n_clines > plus->n_areas)
+	    G_warning(_("Number of centroids exceeds number of areas: %d > %d"),
+		      plus->n_clines, plus->n_areas);
+
 	if (err_boundaries)
-	    G_message(_("Number of incorrect boundaries: %d"),
+	    G_warning(_("Number of incorrect boundaries: %d"),
 		      err_boundaries);
 
 	if (err_centr_out)
-	    G_message(_("Number of centroids outside area: %d"),
+	    G_warning(_("Number of centroids outside area: %d"),
 		      err_centr_out);
 
 	if (err_centr_dupl)
-	    G_message(_("Number of duplicate centroids: %d"), err_centr_dupl);
+	    G_warning(_("Number of duplicate centroids: %d"), err_centr_dupl);
 
-	if (err_nocentr)
-	    G_message(_("Number of areas without centroid: %d"), err_nocentr);
-
     }
     else if (build > GV_BUILD_NONE) {
 	G_message(_("Number of areas: -"));



More information about the grass-commit mailing list