[GRASS-SVN] r39724 - grass/trunk/raster/r.watershed/seg

svn_grass at osgeo.org svn_grass at osgeo.org
Sat Nov 14 06:19:59 EST 2009


Author: mmetz
Date: 2009-11-14 06:19:58 -0500 (Sat, 14 Nov 2009)
New Revision: 39724

Modified:
   grass/trunk/raster/r.watershed/seg/do_astar.c
Log:
fix for ticket #807

Modified: grass/trunk/raster/r.watershed/seg/do_astar.c
===================================================================
--- grass/trunk/raster/r.watershed/seg/do_astar.c	2009-11-14 11:08:42 UTC (rev 39723)
+++ grass/trunk/raster/r.watershed/seg/do_astar.c	2009-11-14 11:19:58 UTC (rev 39724)
@@ -3,17 +3,43 @@
 #include "Gwater.h"
 #include "do_astar.h"
 
+double get_slope2(CELL, CELL, double);
+
 int do_astar(void)
 {
     int doer, count;
     SHORT upr, upc, r = -1, c = -1, ct_dir;
-    CELL alt_val, alt_up;
+    CELL alt_val, alt_nbr[8], alt_up;
     CELL asp_val;
-    char flag_value; 
+    char flag_value, is_in_list, is_worked; 
     HEAP_PNT heap_p;
+    /* sides
+     * |7|1|4|
+     * |2| |3|
+     * |5|0|6|
+     */
+    int nbr_ew[8] = { 0, 1, 2, 3, 1, 0, 0, 1};
+    int nbr_ns[8] = { 0, 1, 2, 3, 3, 2, 3, 2};
+    double dx, dy, dist_to_nbr[8], ew_res, ns_res;
+    double slope[8];
 
     G_message(_("SECTION 2: A* Search."));
 
+    for (ct_dir = 0; ct_dir < sides; ct_dir++) {
+	/* get r, c (r_nbr, c_nbr) for neighbours */
+	upr = nextdr[ct_dir];
+	upc = nextdc[ct_dir];
+	/* account for rare cases when ns_res != ew_res */
+	dy = ABS(upr) * window.ns_res;
+	dx = ABS(upc) * window.ew_res;
+	if (ct_dir < 4)
+	    dist_to_nbr[ct_dir] = dx + dy;
+	else
+	    dist_to_nbr[ct_dir] = sqrt(dx * dx + dy * dy);
+    }
+    ew_res = window.ew_res;
+    ns_res = window.ns_res;
+
     if (heap_size == 0)
 	G_fatal_error(_("No seeds for A* Search"));
 	
@@ -43,11 +69,34 @@
 	    /* get r, c (upr, upc) for this neighbour */
 	    upr = r + nextdr[ct_dir];
 	    upc = c + nextdc[ct_dir];
+	    slope[ct_dir] = alt_nbr[ct_dir] = 0;
 	    /* check that upr, upc are within region */
 	    if (upr >= 0 && upr < nrows && upc >= 0 && upc < ncols) {
+		/* slope */
+		bseg_get(&bitflags, &flag_value, upr, upc);
+		is_in_list = FLAG_GET(flag_value, INLISTFLAG);
+		is_worked = FLAG_GET(flag_value, WORKEDFLAG);
+		if (!is_worked) {
+		    cseg_get(&alt, &alt_up, upr, upc);
+		    alt_nbr[ct_dir] = alt_up;
+		    slope[ct_dir] = get_slope2(alt_val, alt_nbr[ct_dir], dist_to_nbr[ct_dir]);
+		    /* avoid diagonal flow direction bias */
+		    if (ct_dir > 3) {
+			if (slope[nbr_ew[ct_dir]]) {
+			    /* slope to ew nbr > slope to center */
+			    if (slope[ct_dir] <= get_slope2(alt_nbr[nbr_ew[ct_dir]], alt_nbr[ct_dir], ew_res))
+				is_in_list = 1;
+			}
+			if (!is_in_list && slope[nbr_ns[ct_dir]]) {
+			    /* slope to ns nbr > slope to center */
+			    if (slope[ct_dir] <= get_slope2(alt_nbr[nbr_ns[ct_dir]], alt_nbr[ct_dir], ns_res))
+				is_in_list = 1;
+			}
+		    }
+		}
 		/* put neighbour in search list if not yet in */
 		bseg_get(&bitflags, &flag_value, upr, upc);
-		if (!FLAG_GET(flag_value, INLISTFLAG)) {
+		if (is_in_list == 0) {
 		    cseg_get(&alt, &alt_up, upr, upc);
 		    /* flow direction is set here */
 		    asp_val = drain[upr - r + 1][upc - c + 1];
@@ -73,6 +122,7 @@
 	bseg_get(&bitflags, &flag_value, r, c);
 	FLAG_SET(flag_value, WORKEDFLAG);
 	bseg_put(&bitflags, &flag_value, r, c);
+
     }
     if (doer != -1)
 	G_fatal_error(_("bug in A* Search: doer %d heap size %d count %d"), doer, heap_size, count);
@@ -223,3 +273,11 @@
 	return (MIN_SLOPE);
     return (slope);
 }
+
+double get_slope2(CELL ele, CELL up_ele, double dist)
+{
+    if (ele == up_ele)
+	return 0.5 / dist;
+    else
+	return (double) (up_ele - ele) / dist;
+}



More information about the grass-commit mailing list