[GRASS-SVN] r73001 - in grass/trunk/raster: r.cost r.walk
svn_grass at osgeo.org
svn_grass at osgeo.org
Sat Jul 21 02:32:16 PDT 2018
Author: mmetz
Date: 2018-07-21 02:32:15 -0700 (Sat, 21 Jul 2018)
New Revision: 73001
Added:
grass/trunk/raster/r.cost/flag.c
grass/trunk/raster/r.cost/flag.h
grass/trunk/raster/r.walk/flag.c
grass/trunk/raster/r.walk/flag.h
Modified:
grass/trunk/raster/r.cost/main.c
grass/trunk/raster/r.walk/main.c
Log:
r.cost,r.walk: avoid circular paths when using solver
Added: grass/trunk/raster/r.cost/flag.c
===================================================================
--- grass/trunk/raster/r.cost/flag.c (rev 0)
+++ grass/trunk/raster/r.cost/flag.c 2018-07-21 09:32:15 UTC (rev 73001)
@@ -0,0 +1,60 @@
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "flag.h"
+
+FLAG *flag_create(int nrows, int ncols)
+{
+ unsigned char *temp;
+
+ FLAG *new_flag;
+
+ register int i;
+
+ new_flag = (FLAG *) G_malloc(sizeof(FLAG));
+ new_flag->nrows = nrows;
+ new_flag->ncols = ncols;
+ new_flag->leng = (ncols + 7) / 8;
+ new_flag->array =
+ (unsigned char **)G_malloc(nrows * sizeof(unsigned char *));
+
+ if (!new_flag->array)
+ G_fatal_error(_("Out of memory!"));
+
+ temp =
+ (unsigned char *)G_malloc(nrows * new_flag->leng *
+ sizeof(unsigned char));
+
+ if (!temp)
+ G_fatal_error(_("Out of memory!"));
+
+ for (i = 0; i < nrows; i++) {
+ new_flag->array[i] = temp;
+ temp += new_flag->leng;
+ }
+
+ flag_clear_all(new_flag);
+
+ return (new_flag);
+}
+
+int flag_destroy(FLAG * flags)
+{
+ G_free(flags->array[0]);
+ G_free(flags->array);
+ G_free(flags);
+
+ return 0;
+}
+
+int flag_clear_all(FLAG * flags)
+{
+ register int r, c;
+
+ for (r = 0; r < flags->nrows; r++) {
+ for (c = 0; c < flags->leng; c++) {
+ flags->array[r][c] = 0;
+ }
+ }
+
+ return 0;
+}
Property changes on: grass/trunk/raster/r.cost/flag.c
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-csrc
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: grass/trunk/raster/r.cost/flag.h
===================================================================
--- grass/trunk/raster/r.cost/flag.h (rev 0)
+++ grass/trunk/raster/r.cost/flag.h 2018-07-21 09:32:15 UTC (rev 73001)
@@ -0,0 +1,64 @@
+#ifndef __FLAG_H__
+#define __FLAG_H__
+
+
+/* flag.[ch] is a set of routines which will set up an array of bits
+ ** that allow the programmer to "flag" cells in a raster map.
+ **
+ ** FLAG *
+ ** flag_create(nrows,ncols)
+ ** int nrows, ncols;
+ ** opens the structure flag.
+ ** The flag structure will be a two dimensional array of bits the
+ ** size of nrows by ncols. Will initalize flags to zero (unset).
+ **
+ ** flag_destroy(flags)
+ ** FLAG *flags;
+ ** closes flags and gives the memory back to the system.
+ **
+ ** flag_clear_all(flags)
+ ** FLAG *flags;
+ ** sets all values in flags to zero.
+ **
+ ** flag_unset(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ ** sets the value of (row, col) in flags to zero.
+ **
+ ** flag_set(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ ** will set the value of (row, col) in flags to one.
+ **
+ ** int
+ ** flag_get(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ ** returns the value in flags that is at (row, col).
+ **
+ ** idea by Michael Shapiro
+ ** code by Chuck Ehlschlaeger
+ ** April 03, 1989
+ */
+#define FLAG struct _flagsss_
+FLAG {
+ int nrows, ncols, leng;
+ unsigned char **array;
+};
+
+#define FLAG_UNSET(flags,row,col) \
+ (flags)->array[(row)][(col)>>3] &= ~(1<<((col) & 7))
+
+#define FLAG_SET(flags,row,col) \
+ (flags)->array[(row)][(col)>>3] |= (1<<((col) & 7))
+
+#define FLAG_GET(flags,row,col) \
+ (flags)->array[(row)][(col)>>3] & (1<<((col) & 7))
+
+/* flag.c */
+FLAG *flag_create(int, int);
+int flag_destroy(FLAG *);
+int flag_clear_all(FLAG *);
+
+
+#endif /* __FLAG_H__ */
Property changes on: grass/trunk/raster/r.cost/flag.h
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-chdr
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: grass/trunk/raster/r.cost/main.c
===================================================================
--- grass/trunk/raster/r.cost/main.c 2018-07-20 12:58:54 UTC (rev 73000)
+++ grass/trunk/raster/r.cost/main.c 2018-07-21 09:32:15 UTC (rev 73001)
@@ -11,6 +11,8 @@
* Updated for calculation errors and directional surface generation
* Colin Nielsen <colin.nielsen gmail com>
* Use min heap instead of btree (faster, less memory)
+ * multiple directions with bitmask encoding
+ * avoid circular paths
* Markus Metz
*
* PURPOSE: Outputs a raster map layer showing the cumulative cost
@@ -74,6 +76,7 @@
#include <grass/glocale.h>
#include "cost.h"
#include "stash.h"
+#include "flag.h"
#define SEGCOLSIZE 64
@@ -140,6 +143,7 @@
struct cc {
double cost_in, cost_out, nearest;
} costs;
+ FLAG *visited;
void *ptr2;
RASTER_MAP_TYPE data_type, /* input cost type */
@@ -806,6 +810,7 @@
G_debug(1, "nrows x ncols: %d", nrows * ncols);
G_message(_("Finding cost path..."));
n_processed = 0;
+ visited = flag_create(nrows, ncols);
pres_cell = get_lowest();
while (pres_cell != NULL) {
@@ -830,6 +835,12 @@
continue;
}
}
+ if (FLAG_GET(visited, pres_cell->row, pres_cell->col)) {
+ delete(pres_cell);
+ pres_cell = get_lowest();
+ continue;
+ }
+ FLAG_SET(visited, pres_cell->row, pres_cell->col);
if (have_solver)
Segment_get(&solve_seg, mysolvedir, pres_cell->row, pres_cell->col);
@@ -1006,6 +1017,8 @@
if (col < 0 || col >= ncols)
continue;
+ /* skip already processed neighbors here ? */
+
min_cost = dnullval;
Segment_get(&cost_seg, &costs, row, col);
@@ -1133,12 +1146,17 @@
Segment_put(&solve_seg, solvedir, row, col);
}
}
- else if (old_min_cost == min_cost && (dir_bin || have_solver)) {
+ else if (old_min_cost == min_cost &&
+ (dir_bin || have_solver) &&
+ !(FLAG_GET(visited, row, col))) {
FCELL old_dir;
int dir_inv[16] = { 4, 5, 6, 7, 0, 1, 2, 3,
12, 13, 14, 15, 8, 9, 10, 11 };
int dir_fwd;
int equal = 1;
+
+ /* only update neighbors that have not yet been processed,
+ * otherwise we might get circular paths */
if (have_solver) {
Segment_get(&solve_seg, solvedir, row, col);
@@ -1187,6 +1205,7 @@
/* free heap */
free_heap();
+ flag_destroy(visited);
if (have_solver) {
Segment_close(&solve_seg);
Added: grass/trunk/raster/r.walk/flag.c
===================================================================
--- grass/trunk/raster/r.walk/flag.c (rev 0)
+++ grass/trunk/raster/r.walk/flag.c 2018-07-21 09:32:15 UTC (rev 73001)
@@ -0,0 +1,60 @@
+#include <grass/gis.h>
+#include <grass/glocale.h>
+#include "flag.h"
+
+FLAG *flag_create(int nrows, int ncols)
+{
+ unsigned char *temp;
+
+ FLAG *new_flag;
+
+ register int i;
+
+ new_flag = (FLAG *) G_malloc(sizeof(FLAG));
+ new_flag->nrows = nrows;
+ new_flag->ncols = ncols;
+ new_flag->leng = (ncols + 7) / 8;
+ new_flag->array =
+ (unsigned char **)G_malloc(nrows * sizeof(unsigned char *));
+
+ if (!new_flag->array)
+ G_fatal_error(_("Out of memory!"));
+
+ temp =
+ (unsigned char *)G_malloc(nrows * new_flag->leng *
+ sizeof(unsigned char));
+
+ if (!temp)
+ G_fatal_error(_("Out of memory!"));
+
+ for (i = 0; i < nrows; i++) {
+ new_flag->array[i] = temp;
+ temp += new_flag->leng;
+ }
+
+ flag_clear_all(new_flag);
+
+ return (new_flag);
+}
+
+int flag_destroy(FLAG * flags)
+{
+ G_free(flags->array[0]);
+ G_free(flags->array);
+ G_free(flags);
+
+ return 0;
+}
+
+int flag_clear_all(FLAG * flags)
+{
+ register int r, c;
+
+ for (r = 0; r < flags->nrows; r++) {
+ for (c = 0; c < flags->leng; c++) {
+ flags->array[r][c] = 0;
+ }
+ }
+
+ return 0;
+}
Property changes on: grass/trunk/raster/r.walk/flag.c
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-csrc
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: grass/trunk/raster/r.walk/flag.h
===================================================================
--- grass/trunk/raster/r.walk/flag.h (rev 0)
+++ grass/trunk/raster/r.walk/flag.h 2018-07-21 09:32:15 UTC (rev 73001)
@@ -0,0 +1,64 @@
+#ifndef __FLAG_H__
+#define __FLAG_H__
+
+
+/* flag.[ch] is a set of routines which will set up an array of bits
+ ** that allow the programmer to "flag" cells in a raster map.
+ **
+ ** FLAG *
+ ** flag_create(nrows,ncols)
+ ** int nrows, ncols;
+ ** opens the structure flag.
+ ** The flag structure will be a two dimensional array of bits the
+ ** size of nrows by ncols. Will initalize flags to zero (unset).
+ **
+ ** flag_destroy(flags)
+ ** FLAG *flags;
+ ** closes flags and gives the memory back to the system.
+ **
+ ** flag_clear_all(flags)
+ ** FLAG *flags;
+ ** sets all values in flags to zero.
+ **
+ ** flag_unset(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ ** sets the value of (row, col) in flags to zero.
+ **
+ ** flag_set(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ ** will set the value of (row, col) in flags to one.
+ **
+ ** int
+ ** flag_get(flags, row, col)
+ ** FLAG *flags;
+ ** int row, col;
+ ** returns the value in flags that is at (row, col).
+ **
+ ** idea by Michael Shapiro
+ ** code by Chuck Ehlschlaeger
+ ** April 03, 1989
+ */
+#define FLAG struct _flagsss_
+FLAG {
+ int nrows, ncols, leng;
+ unsigned char **array;
+};
+
+#define FLAG_UNSET(flags,row,col) \
+ (flags)->array[(row)][(col)>>3] &= ~(1<<((col) & 7))
+
+#define FLAG_SET(flags,row,col) \
+ (flags)->array[(row)][(col)>>3] |= (1<<((col) & 7))
+
+#define FLAG_GET(flags,row,col) \
+ (flags)->array[(row)][(col)>>3] & (1<<((col) & 7))
+
+/* flag.c */
+FLAG *flag_create(int, int);
+int flag_destroy(FLAG *);
+int flag_clear_all(FLAG *);
+
+
+#endif /* __FLAG_H__ */
Property changes on: grass/trunk/raster/r.walk/flag.h
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+text/x-chdr
\ No newline at end of property
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: grass/trunk/raster/r.walk/main.c
===================================================================
--- grass/trunk/raster/r.walk/main.c 2018-07-20 12:58:54 UTC (rev 73000)
+++ grass/trunk/raster/r.walk/main.c 2018-07-21 09:32:15 UTC (rev 73001)
@@ -28,6 +28,8 @@
* Updated for calculation errors and directional surface generation
* Colin Nielsen <colin.nielsen gmail com>
* Use min heap instead of btree (faster, less memory)
+ * multiple directions with bitmask encoding
+ * avoid circular paths
* Markus Metz
* PURPOSE: anisotropic movements on cost surfaces
* COPYRIGHT: (C) 1999-2015 by the GRASS Development Team
@@ -108,6 +110,7 @@
#include <grass/glocale.h>
#include "cost.h"
#include "stash.h"
+#include "flag.h"
#define SEGCOLSIZE 64
@@ -179,6 +182,7 @@
double cost_in; /* friction costs */
double cost_out; /* cumulative costs */
} costs;
+ FLAG *visited;
void *ptr1, *ptr2;
RASTER_MAP_TYPE dtm_data_type, cost_data_type, cum_data_type =
@@ -941,6 +945,7 @@
G_debug(1, "nrows x ncols: %d", nrows * ncols);
G_message(_("Finding cost path..."));
n_processed = 0;
+ visited = flag_create(nrows, ncols);
pres_cell = get_lowest();
while (pres_cell != NULL) {
@@ -973,7 +978,6 @@
continue;
}
}
-
my_dtm = costs.dtm;
if (Rast_is_d_null_value(&my_dtm)) {
delete(pres_cell);
@@ -986,6 +990,12 @@
pres_cell = get_lowest();
continue;
}
+ if (FLAG_GET(visited, pres_cell->row, pres_cell->col)) {
+ delete(pres_cell);
+ pres_cell = get_lowest();
+ continue;
+ }
+ FLAG_SET(visited, pres_cell->row, pres_cell->col);
if (have_solver)
Segment_get(&solve_seg, mysolvedir, pres_cell->row, pres_cell->col);
@@ -1159,6 +1169,8 @@
if (col < 0 || col >= ncols)
continue;
+ /* skip already processed neighbors here ? */
+
min_cost = dnullval;
Segment_get(&cost_seg, &costs, row, col);
@@ -1484,12 +1496,17 @@
Segment_put(&solve_seg, solvedir, row, col);
}
}
- else if (dir && dir_bin && old_min_cost == min_cost) {
+ else if (old_min_cost == min_cost &&
+ (dir_bin || have_solver) &&
+ !(FLAG_GET(visited, row, col))) {
FCELL old_dir;
int dir_inv[16] = { 4, 5, 6, 7, 0, 1, 2, 3,
12, 13, 14, 15, 8, 9, 10, 11 };
int dir_fwd;
int equal = 1;
+
+ /* only update neighbors that have not yet been processed,
+ * otherwise we might get circular paths */
if (have_solver) {
Segment_get(&solve_seg, solvedir, row, col);
@@ -1508,7 +1525,7 @@
}
}
- if (equal) {
+ if (dir_bin && equal) {
/* this can create circular paths:
* set only if current cell does not point to neighbor
* does not avoid longer circular paths */
@@ -1537,6 +1554,7 @@
/* free heap */
free_heap();
+ flag_destroy(visited);
if (have_solver) {
Segment_close(&solve_seg);
More information about the grass-commit
mailing list