[GRASS-SVN] r53417 - grass/trunk/vector/v.distance

svn_grass at osgeo.org svn_grass at osgeo.org
Tue Oct 16 00:48:36 PDT 2012


Author: mmetz
Date: 2012-10-16 00:48:35 -0700 (Tue, 16 Oct 2012)
New Revision: 53417

Modified:
   grass/trunk/vector/v.distance/distance.c
   grass/trunk/vector/v.distance/main.c
   grass/trunk/vector/v.distance/v.distance.html
Log:
v.distance update for areas to areas

Modified: grass/trunk/vector/v.distance/distance.c
===================================================================
--- grass/trunk/vector/v.distance/distance.c	2012-10-16 07:20:22 UTC (rev 53416)
+++ grass/trunk/vector/v.distance/distance.c	2012-10-16 07:48:35 UTC (rev 53417)
@@ -197,6 +197,7 @@
     int i, j;
     double tmp_dist;
     int isle, nisles;
+    int all_inside_outer, all_outside_outer, all_outside_inner;
     static struct line_pnts *aPoints = NULL;
     static struct line_pnts **iPoints = NULL;
     static struct bound_box *ibox = NULL;
@@ -237,6 +238,8 @@
     }
 
     /* inside area ? */
+    all_inside_outer = all_outside_outer = 1;
+    all_outside_inner = 1;
 
     for (i = 0; i < Points->n_points; i++) {
 	if (Vect_point_in_box(Points->x[i], Points->y[i],
@@ -246,6 +249,15 @@
 	    
 	    poly = Vect_point_in_poly(Points->x[i], Points->y[i], aPoints);
 	    
+	    if (poly > 0) {
+		/* inside outer ring */
+		all_outside_outer = 0;
+	    }
+	    else {
+		/* outside outer ring */
+		all_inside_outer = 0;
+	    }
+	    
 	    /* exactly on boundary */
 	    if (poly == 2) {
 		line2line(Points, type, aPoints, GV_BOUNDARY,
@@ -255,9 +267,9 @@
 		
 		return 1;
 	    }
-	    /* inside */
+	    /* inside outer ring */
 	    else if (poly == 1) {
-		int inside = 0;
+		int inside_isle = 0;
 
 		for (j = 0; j < nisles; j++) {
 		    if (Vect_point_in_box(Points->x[i], Points->y[i], Points->z[i], 
@@ -270,6 +282,8 @@
 			    double tmp_fx, tmp_fy, tmp_fz, tmp_fangle, tmp_falong;
 			    double tmp_tx, tmp_ty, tmp_tz, tmp_tangle, tmp_talong;
 
+			    /* pass all points of the line, 
+			     * this will catch an intersection */
 			    line2line(Points, type, iPoints[j], GV_BOUNDARY,
 				      &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
 				      &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
@@ -291,16 +305,17 @@
 				*tangle = tmp_tangle;
 			    }
 
-			    if (poly == 1)
-				inside = 1;
+			    if (poly == 1) /* excludes isle boundary */
+				inside_isle = 1;
 			    
 			}
 		    }
 		    if (*dist == 0)
 			break;
 		}
-		/* inside area (inside outer ring, outside inner rings) */
-		if (!inside) {
+		/* inside area (inside outer ring, outside inner rings
+		 * or exactly on one of the inner rings) */
+		if (!inside_isle) {
 		    *fx = Points->x[i];
 		    *fy = Points->y[i];
 		    *fz = Points->z[i];
@@ -313,18 +328,49 @@
 
 		    return 1;
 		}
-		/* inside one of the islands */
-		else
-		    return 2;
+		else {
+		    /* inside one of the islands */
+		    all_outside_inner = 0;
+		    if (*dist == 0) {
+			/* the line intersected with the isle boundary
+			 * -> line is partially inside the area */
+			return 1;
+		    }
+		    /* else continue with next point */
+		}
 	    } /* end inside outer ring */
 	}
-	/* not possible */
+	else {
+	    /* point not in box of outer ring */
+	    all_inside_outer = 0;
+	}
+	/* exactly on boundary */
 	if (*dist == 0)
 	    return 1;
     }
+    
+    /* if all points are inside the outer ring and inside inner rings,
+     * there could still be an intersection with one of the inner rings */
+     if (all_inside_outer) {
+	 if (all_outside_inner) {
+	     /* at least one point is really inside the area!
+	      * that should have been detected above */
+	     G_fatal_error(_("At least one point is really inside the area!"));
+	 }
+	 /* else all points are inside one of the area isles 
+	  * and we already have the minimum distance */
+	  return 2;
+     }
 
-    /* line is outside area */
+    /* if at least one point was found to be inside the outer ring, 
+     * but no point really inside the area,
+     * and at least one point outside,
+     * then there must be an intersection of the line with both 
+     * the outer ring and one of the isle boundaries */
 
+    /* if all line points are outside of the area,
+     * intersection is still possible */
+
     line2line(Points, type, aPoints, GV_BOUNDARY,
 	      fx, fy, fz, falong, fangle,
 	      tx, ty, tz, talong, tangle,

Modified: grass/trunk/vector/v.distance/main.c
===================================================================
--- grass/trunk/vector/v.distance/main.c	2012-10-16 07:20:22 UTC (rev 53416)
+++ grass/trunk/vector/v.distance/main.c	2012-10-16 07:48:35 UTC (rev 53417)
@@ -968,19 +968,21 @@
 		    int tmp_tcat, poly;
 
 		    tarea = aList->id[i];
-		    G_debug(4, "%d: area %d", i, tarea);
+		    G_debug(4, "%d: 'to' area id %d", i, tarea);
+
 		    Vect_get_area_points(&To, tarea, TPoints);
 		    
 		    ttype = GV_BOUNDARY;
 
-		    /* Find the distance to this area */
+		    /* Find the distance of the outer ring of 'to' area
+		     * to 'from' area */
 		    poly = line2area(&From, TPoints, ttype, area, &fbox,
 		              &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
 		              &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
 			      &tmp_dist, with_z, 0);
 
 		    if (poly == 3) {
-			/* 'to' area is outside 'from' area,
+			/* 'to' outer ring is outside 'from' area,
 			 * check if 'from' area is inside 'to' area */
 			poly = 0;
 			/* boxes must overlap */
@@ -996,6 +998,8 @@
 			if (poly) {
 			    /* 'from' area is (partially) inside 'to' area,
 			     * get distance to 'to' area */
+			    if (FPoints->n_points == 0)
+				Vect_get_area_points(&From, area, FPoints);
 			    poly = line2area(&To, FPoints, ttype, tarea, &aList->box[i],
 				      &tmp_fx, &tmp_fy, &tmp_fz, &tmp_falong, &tmp_fangle,
 				      &tmp_tx, &tmp_ty, &tmp_tz, &tmp_talong, &tmp_tangle,
@@ -1004,7 +1008,7 @@
 			    /* inside isle ? */
 			    poly = poly == 2;
 			}
-			if (poly) {
+			if (poly == 1) {
 			    double tmp2_tx, tmp2_ty, tmp2_tz, tmp2_talong, tmp2_tangle;
 			    double tmp2_fx, tmp2_fy, tmp2_fz, tmp2_falong, tmp2_fangle;
 			    double tmp2_dist;
@@ -1040,7 +1044,7 @@
 
 		    if (tmp_dist > max || tmp_dist < min)
 			continue;	/* not in threshold */
-		    Vect_get_area_cats(&To, area, TCats);
+		    Vect_get_area_cats(&To, tarea, TCats);
 		    tmp_tcat = -1;
 		    /* TODO: all cats of given field ? */
 		    for (j = 0; j < TCats->n_cats; j++) {

Modified: grass/trunk/vector/v.distance/v.distance.html
===================================================================
--- grass/trunk/vector/v.distance/v.distance.html	2012-10-16 07:20:22 UTC (rev 53416)
+++ grass/trunk/vector/v.distance/v.distance.html	2012-10-16 07:48:35 UTC (rev 53417)
@@ -8,6 +8,38 @@
 nearest points on features are written. <em>dmin</em> and/or 
 <em>dmax</em> can be used to limit the search radius.
 
+<p>
+For lines to lines, say line A to line B, <em>v.distance</em> calculates 
+the shortest distance of each vertex in A with each segment (not vertex) 
+in B. The module then calculates the shortest distance of each vertex in 
+B to each segment in A. The overall shortest distance of A points to B 
+segments and B points to A segments is used. Additionally, 
+<em>v.distance</em> checks for intersections. In case of intersections,
+the first intersection found is used and the distance set to zero.
+
+<p>
+For lines to areas, the distance is set to zero if a line is (partially) 
+inside an area. The first point of the line that is inside the area is 
+used as common point. The distance is also set to zero if the line 
+intersects with the outer ring or any of the inner rings (isles), in 
+which case the fist intersection is used as common point.
+
+<p>
+For areas to areas, the module checks first for overlap or if one area
+is (partially) inside the other area. This is computationally quite
+intensive. If the outer rings of the two areas do not overlap, the
+distance is calculated as above for lines to lines, treating the outer
+rings as two lines. Again, the first point encountered falling into an
+area is used as common point, or the first intersection point.
+
+<p>
+For anything else than points to lines, there can be several common
+locations with zero distance, and the common location would then be the 
+result of an overlay consisting of several points, lines, or areas.
+<em>v.distance</em> selects in these cases a single point, and does not 
+create an overlay like <em>v.overlay</em>.
+
+
 <h2>NOTES</h2>
 
 If a nearest feature does not have a category, the attribute column is 



More information about the grass-commit mailing list