[GRASS-SVN] r36395 - in grass/trunk/lib/vector: Vlib diglib

svn_grass at osgeo.org svn_grass at osgeo.org
Mon Mar 16 14:07:23 EDT 2009


Author: mmetz
Date: 2009-03-16 14:07:23 -0400 (Mon, 16 Mar 2009)
New Revision: 36395

Modified:
   grass/trunk/lib/vector/Vlib/build_nat.c
   grass/trunk/lib/vector/diglib/poly.c
Log:
faster topology building for areas

Modified: grass/trunk/lib/vector/Vlib/build_nat.c
===================================================================
--- grass/trunk/lib/vector/Vlib/build_nat.c	2009-03-16 18:07:05 UTC (rev 36394)
+++ grass/trunk/lib/vector/Vlib/build_nat.c	2009-03-16 18:07:23 UTC (rev 36395)
@@ -32,7 +32,7 @@
    \param iline line id
    \param side side (GV_LEFT or GV_RIGHT)
 
-   \return > 0 number of  area
+   \return > 0 number of area
    \return < 0 number of isle
    \return 0 not created (may also already exist)
  */
@@ -84,10 +84,15 @@
 	Vect_append_points(APoints, Points, direction);
     }
 
-    dig_find_area_poly(APoints, &area_size);
+    /* dig_find_area_poly(APoints, &area_size); */
+
+    Vect_line_prune(APoints);
+    area_size = dig_find_poly_orientation(APoints);
+    /* area_size is not real area size, we are only interested in the sign */
+
     G_debug(3, "  area/isle size = %f", area_size);
 
-    if (area_size > 0) {	/* area */
+    if (area_size > 0) {	/* CW: area */
 	/* add area structure to plus */
 	area = dig_add_area(plus, n_lines, lines);
 	if (area == -1) {	/* error */
@@ -97,7 +102,7 @@
 	G_debug(3, "  -> area %d", area);
 	return area;
     }
-    else if (area_size < 0) {	/* island */
+    else if (area_size < 0) {	/* CCW: island */
 	isle = dig_add_isle(plus, n_lines, lines);
 	if (isle == -1) {	/* error */
 	    Vect_close(Map);
@@ -191,7 +196,7 @@
 
 	/* Check box */
 	/* Note: If build is run on large files of areas imported from nontopo format (shapefile)
-	 * attaching of isles takes very  long time because each area is also isle and select by
+	 * attaching of isles takes very long time because each area is also isle and select by
 	 * box all overlapping areas selects all areas with box overlapping first node. 
 	 * Then reading coordinates for all those areas would take a long time -> check first 
 	 * if isle's box is completely within area box */

Modified: grass/trunk/lib/vector/diglib/poly.c
===================================================================
--- grass/trunk/lib/vector/diglib/poly.c	2009-03-16 18:07:05 UTC (rev 36394)
+++ grass/trunk/lib/vector/diglib/poly.c	2009-03-16 18:07:23 UTC (rev 36395)
@@ -24,8 +24,8 @@
 #endif
 
 /*
- **  fills BPoints (must be inited previously) by points from imput
- **  array LPoints. Each imput points must have at least 2 points.
+ **  fills BPoints (must be inited previously) by points from input
+ **  array LPoints. Each input LPoints[i] must have at least 2 points.
  **   
  **  returns number of points or -1 on error
  */
@@ -86,31 +86,72 @@
 }
 
 /*
- **  Calculate area size for polygon. 
+ **  Calculate signed area size for polygon. 
  **
- **  Total area is positive for clockwise and negative for counter clockwise ?
+ **  Total area is positive for clockwise and negative for counterclockwise
  */
 int dig_find_area_poly(struct line_pnts *Points, double *totalarea)
 {
-    int i;
+    int i, n = Points->n_points - 1;
     double *x, *y;
-    double tot_area, sum_area;
+    double tot_area;
 
-
-    *totalarea = 0.;
-
-    tot_area = 0.0;
-
     x = Points->x;
     y = Points->y;
 
-    sum_area = 0.0;
-    for (i = 1; i < Points->n_points; i++) {
-	sum_area += (x[i] - x[i - 1]) * (y[i] + y[i - 1]);
+    tot_area = 0.0;
+    for (i = 1; i < n; i++) {
+        tot_area += y[i] * (x[i + 1] - x[i - 1]);
     }
-    tot_area += sum_area;
+    /* add last point with i == Points->n_points - 1 */
+    tot_area += y[i] * (x[1] - x[i - 1]);
 
     *totalarea = 0.5 * tot_area;
 
     return (0);
 }
+
+/*
+ * find orientation of polygon
+ * faster than signed area
+ * 
+ * return value is positive for CW, negative for CCW, 0 for degenerate
+ *
+ * Points must be closed polygon
+ * only works with pruned lines (no consecutive duplicate vertices)
+ */
+double dig_find_poly_orientation(struct line_pnts *Points)
+{
+    unsigned int i, pcur = 0;
+    unsigned int n = Points->n_points -1; /* skip last point == first point */
+    double *x, *y;
+
+    /* first find leftmost highest vertex of the polygon */
+    /* could also be leftmost lowest, rightmost highest or rightmost lowest */
+
+    x = Points->x;
+    y = Points->y;
+
+    for (i = 1; i < n; i++) {
+	
+	if (y[i] < y[pcur])
+	    continue;
+	else if (y[i] == y[pcur]) {    /* just as high */
+	    if (x[i] < x[pcur])   	/* but to the right */
+		continue;
+	}
+	pcur = i;          /* a new leftmost highest vertex */
+    }
+
+    /* orientation at vertex pcur == signed area for triangle
+     * rather use robust determinant of Olivier Dilliers? */
+    if (pcur > 0) {
+	return (x[pcur + 1] - x[pcur - 1]) * (y[pcur] - y[pcur - 1])
+             - (x[pcur] - x[pcur - 1]) * (y[pcur + 1] - y[pcur - 1]);
+    }
+    else { 
+	n -= 1;
+	return (x[1] - x[n]) * (y[0] - y[n])
+             - (x[0] - x[n]) * (y[1] - y[n]);
+    }
+}



More information about the grass-commit mailing list