[GRASS-SVN] r71952 - in grass/trunk/raster: r.cost r.walk
svn_grass at osgeo.org
svn_grass at osgeo.org
Mon Dec 18 14:20:24 PST 2017
Author: mmetz
Date: 2017-12-18 14:20:24 -0800 (Mon, 18 Dec 2017)
New Revision: 71952
Modified:
grass/trunk/raster/r.cost/main.c
grass/trunk/raster/r.cost/stash.h
grass/trunk/raster/r.walk/main.c
grass/trunk/raster/r.walk/stash.h
Log:
r.cost/r.walk: optimize stop points, sync modules
Modified: grass/trunk/raster/r.cost/main.c
===================================================================
--- grass/trunk/raster/r.cost/main.c 2017-12-18 22:19:38 UTC (rev 71951)
+++ grass/trunk/raster/r.cost/main.c 2017-12-18 22:20:24 UTC (rev 71952)
@@ -43,8 +43,9 @@
*
*********************************************************************/
-/* BUG 2005: r.cost probably hangs with negative costs.
- * Positive costs could be a condition for Dijkstra search? MM
+/* BUG 2005 - Markus Metz
+ * r.cost hangs with negative costs.
+ * Non-negative costs are a requirement for Dijkstra search
*
* 08 april 2000 - Pierre de Mouveaux. pmx at audiovu.com
* Updated to use the Grass 5.0 floating point raster cell format.
@@ -55,8 +56,6 @@
*/
/* TODO
- * use Vect_*() functions
- * use search tree for stop points
* re-organize and clean up code for better readability
* compartmentalize code, start with putting Dijkstra search into a separate function
*/
@@ -81,8 +80,27 @@
struct Cell_head window;
struct start_pt *head_start_pt = NULL;
-struct start_pt *head_end_pt = NULL;
+struct rc
+{
+ int r;
+ int c;
+};
+
+static struct rc *stop_pnts = NULL;
+static int n_stop_pnts = 0;
+static int stop_pnts_alloc = 0;
+
+int cmp_rc(struct rc *a, struct rc *b)
+{
+ if (a->r == b->r)
+ return (a->c - b->c);
+
+ return (a->r - b->r);
+}
+
+void add_stop_pnt(int r, int c);
+
int main(int argc, char *argv[])
{
const char *cum_cost_layer, *move_dir_layer, *nearest_layer;
@@ -103,7 +121,7 @@
int maxmem;
int segments_in_memory;
int cost_fd, cum_fd, dir_fd, nearest_fd;
- int have_stop_points = FALSE, dir = FALSE;
+ int dir = 0;
double my_cost, nearest;
double null_cost, dnullval;
int srows, scols;
@@ -119,7 +137,6 @@
struct Option *opt9, *opt10, *opt11, *opt12;
struct cost *pres_cell;
struct start_pt *pres_start_pt = NULL;
- struct start_pt *pres_stop_pt = NULL;
struct cc {
double cost_in, cost_out, nearest;
} costs;
@@ -297,13 +314,15 @@
G_fatal_error(_("Must specify exactly one of start_points, start_rast or coordinate"));
}
- if (opt3->answers)
- if (!process_answers(opt3->answers, &head_start_pt, &pres_start_pt))
+ if (opt3->answers) {
+ if (!process_start_coords(opt3->answers, &head_start_pt, &pres_start_pt))
G_fatal_error(_("No start points"));
+ }
- if (opt4->answers)
- have_stop_points =
- process_answers(opt4->answers, &head_end_pt, &pres_stop_pt);
+ if (opt4->answers) {
+ if (!process_stop_coords(opt4->answers))
+ G_fatal_error(_("No stop points"));
+ }
if (sscanf(opt5->answer, "%d", &maxcost) != 1 || maxcost < 0)
G_fatal_error(_("Inappropriate maximum cost: %d"), maxcost);
@@ -434,7 +453,7 @@
sizeof(struct cc), segments_in_memory) != 1)
G_fatal_error(_("Can not create temporary file"));
- if (dir == TRUE) {
+ if (dir == 1) {
if (Segment_open(&dir_seg, G_tempfile(), nrows, ncols, srows, scols,
sizeof(FCELL), segments_in_memory) != 1)
G_fatal_error(_("Can not create temporary file"));
@@ -444,7 +463,7 @@
G_message(_("Reading raster map <%s>, initializing output..."),
G_fully_qualified_name(cost_layer, cost_mapset));
{
- int i, skip_nulls;
+ int skip_nulls;
double p;
Rast_set_d_null_value(&dnullval, 1);
@@ -465,7 +484,7 @@
/* INPUT NULL VALUES: ??? */
ptr2 = cell;
- for (i = 0; i < ncols; i++) {
+ for (col = 0; col < ncols; col++) {
if (Rast_is_null_value(ptr2, data_type)) {
p = null_cost;
if (skip_nulls) {
@@ -488,11 +507,11 @@
if (p < 0) {
G_warning(_("Negative cell value found at row %d, col %d. "
"Setting negative value to null_cost value"),
- row, i);
+ row, col);
p = null_cost;
}
costs.cost_in = p;
- Segment_put(&cost_seg, &costs, row, i);
+ Segment_put(&cost_seg, &costs, row, col);
ptr2 = G_incr_void_ptr(ptr2, dsize);
}
}
@@ -500,7 +519,7 @@
G_percent(1, 1, 1);
}
- if (dir == TRUE) {
+ if (dir == 1) {
G_message(_("Initializing directional output..."));
for (row = 0; row < nrows; row++) {
G_percent(row, nrows, 2);
@@ -592,7 +611,6 @@
struct line_pnts *Points;
struct line_cats *Cats;
struct bound_box box;
- struct start_pt *new_start_pt;
int type;
G_message(_("Reading vector map <%s> with stop points..."), opt8->answer);
@@ -623,32 +641,16 @@
}
if (!Vect_point_in_box(Points->x[0], Points->y[0], 0, &box))
continue;
- have_stop_points = TRUE;
col = (int)Rast_easting_to_col(Points->x[0], &window);
row = (int)Rast_northing_to_row(Points->y[0], &window);
- new_start_pt =
- (struct start_pt *)(G_malloc(sizeof(struct start_pt)));
-
- new_start_pt->row = row;
- new_start_pt->col = col;
- new_start_pt->next = NULL;
-
- if (head_end_pt == NULL) {
- head_end_pt = new_start_pt;
- pres_stop_pt = new_start_pt;
- new_start_pt->next = NULL;
- }
- else {
- pres_stop_pt->next = new_start_pt;
- pres_stop_pt = new_start_pt;
- }
+ add_stop_pnt(row, col);
}
Vect_close(&In);
- if (!have_stop_points)
+ if (!stop_pnts)
G_fatal_error(_("No stop points found in vector <%s>"), opt8->answer);
}
@@ -712,8 +714,7 @@
G_fatal_error(_("No start points"));
}
- /* If the starting points are given on the command line start a linked
- * list of cells ordered by increasing costs
+ /* Insert start points into min heap
*/
if (head_start_pt) {
struct start_pt *top_start_pt = NULL;
@@ -736,6 +737,25 @@
}
}
+ if (n_stop_pnts > 1) {
+ int i, j;
+
+ /* prune stop points */
+ j = 1;
+ for (i = 1; i < n_stop_pnts; i++) {
+ if (stop_pnts[i].r != stop_pnts[j - 1].r ||
+ stop_pnts[i].c != stop_pnts[j - 1].c) {
+ stop_pnts[j].r = stop_pnts[i].r;
+ stop_pnts[j].c = stop_pnts[i].c;
+ j++;
+ }
+ }
+ if (n_stop_pnts > j) {
+ G_message(_("Number of duplicate stop points: %d"), n_stop_pnts - j);
+ n_stop_pnts = j;
+ }
+ }
+
/* Loop through the heap and perform at each cell the following:
* 1) If an adjacent cell has not already been assigned a value compute
* the min cost and assign it.
@@ -984,7 +1004,7 @@
costs.nearest = nearest;
Segment_put(&cost_seg, &costs, row, col);
insert(min_cost, row, col);
- if (dir == TRUE) {
+ if (dir == 1) {
Segment_put(&dir_seg, &cur_dir, row, col);
}
}
@@ -994,13 +1014,13 @@
costs.nearest = nearest;
Segment_put(&cost_seg, &costs, row, col);
insert(min_cost, row, col);
- if (dir == TRUE) {
+ if (dir == 1) {
Segment_put(&dir_seg, &cur_dir, row, col);
}
}
}
- if (have_stop_points && time_to_stop(pres_cell->row, pres_cell->col))
+ if (stop_pnts && time_to_stop(pres_cell->row, pres_cell->col))
break;
ct = pres_cell;
@@ -1121,7 +1141,7 @@
G_free(nearest_cell);
}
- if (dir == TRUE) {
+ if (dir == 1) {
void *p;
size_t dir_size = Rast_cell_size(dir_data_type);
@@ -1144,11 +1164,12 @@
}
Segment_close(&cost_seg); /* release memory */
- if (dir == TRUE)
+ if (dir == 1)
Segment_close(&dir_seg);
+
Rast_close(cost_fd);
Rast_close(cum_fd);
- if (dir == TRUE)
+ if (dir == 1)
Rast_close(dir_fd);
if (nearest_layer)
Rast_close(nearest_fd);
@@ -1158,7 +1179,7 @@
Rast_command_history(&history);
Rast_write_history(cum_cost_layer, &history);
- if (dir == TRUE) {
+ if (dir == 1) {
Rast_short_history(move_dir_layer, "raster", &history);
Rast_command_history(&history);
Rast_write_history(move_dir_layer, &history);
@@ -1200,13 +1221,12 @@
}
int
-process_answers(char **answers, struct start_pt **points,
+process_start_coords(char **answers, struct start_pt **points,
struct start_pt **top_start_pt)
{
int col, row;
double east, north;
struct start_pt *new_start_pt;
- int got_one = 0;
int point_no = 0;
*points = NULL;
@@ -1226,8 +1246,6 @@
east, north);
continue;
}
- else
- got_one = 1;
row = (window.north - north) / window.ns_res;
col = (east - window.west) / window.ew_res;
@@ -1249,27 +1267,85 @@
*top_start_pt = new_start_pt;
}
}
- return (got_one);
+ return (point_no > 0);
}
+int process_stop_coords(char **answers)
+{
+ int col, row;
+ double east, north;
+
+ if (!answers)
+ return 0;
+
+ for (; *answers != NULL; answers += 2) {
+ if (!G_scan_easting(*answers, &east, G_projection()))
+ G_fatal_error(_("Illegal x coordinate <%s>"), *answers);
+ if (!G_scan_northing(*(answers + 1), &north, G_projection()))
+ G_fatal_error(_("Illegal y coordinate <%s>"), *(answers + 1));
+
+ if (east < window.west || east > window.east ||
+ north < window.south || north > window.north) {
+ G_warning(_("Warning, ignoring point outside window: %g, %g"),
+ east, north);
+ continue;
+ }
+
+ row = (window.north - north) / window.ns_res;
+ col = (east - window.west) / window.ew_res;
+
+ add_stop_pnt(row, col);
+ }
+
+ return (stop_pnts != NULL);
+}
+
+void add_stop_pnt(int r, int c)
+{
+ int i;
+ struct rc sp;
+
+ if (n_stop_pnts == stop_pnts_alloc) {
+ stop_pnts_alloc += 100;
+ stop_pnts = (struct rc *)G_realloc(stop_pnts, stop_pnts_alloc * sizeof(struct rc));
+ }
+
+ sp.r = r;
+ sp.c = c;
+ i = n_stop_pnts;
+ while (i > 0 && cmp_rc(stop_pnts + i - 1, &sp) > 0) {
+ stop_pnts[i] = stop_pnts[i - 1];
+ i--;
+ }
+ stop_pnts[i] = sp;
+
+ n_stop_pnts++;
+}
+
int time_to_stop(int row, int col)
{
- static int total = 0;
+ int lo, mid, hi;
+ struct rc sp;
static int hits = 0;
- struct start_pt *points;
- if (total == 0) {
- for (points = head_end_pt;
- points != NULL; points = points->next, total++) ;
- }
+ sp.r = row;
+ sp.c = col;
- for (points = head_end_pt; points != NULL; points = points->next)
+ lo = 0;
+ hi = n_stop_pnts - 1;
- if (points->row == row && points->col == col) {
- hits++;
- if (hits == total)
- return (1);
- }
+ /* bsearch with deferred test for equality
+ * slightly more efficient for worst case: no match */
+ while (lo < hi) {
+ mid = lo + ((hi - lo) >> 1);
+ if (cmp_rc(stop_pnts + mid, &sp) < 0)
+ lo = mid + 1;
+ else
+ hi = mid;
+ }
+ if (cmp_rc(stop_pnts + lo, &sp) == 0) {
+ return (++hits == n_stop_pnts);
+ }
- return (0);
+ return 0;
}
Modified: grass/trunk/raster/r.cost/stash.h
===================================================================
--- grass/trunk/raster/r.cost/stash.h 2017-12-18 22:19:38 UTC (rev 71951)
+++ grass/trunk/raster/r.cost/stash.h 2017-12-18 22:20:24 UTC (rev 71952)
@@ -28,12 +28,8 @@
struct start_pt *next;
};
-extern char cum_cost_layer[], move_dir_layer[];
-extern char cost_layer[];
-extern struct start_pt *head_start_pt;
-extern struct start_pt *head_end_pt;
-
-int process_answers(char **, struct start_pt **, struct start_pt **);
+int process_start_coords(char **, struct start_pt **, struct start_pt **);
+int process_stop_coords(char **answers);
int time_to_stop(int, int);
#endif /* __STASH_H__ */
Modified: grass/trunk/raster/r.walk/main.c
===================================================================
--- grass/trunk/raster/r.walk/main.c 2017-12-18 22:19:38 UTC (rev 71951)
+++ grass/trunk/raster/r.walk/main.c 2017-12-18 22:20:24 UTC (rev 71952)
@@ -27,7 +27,7 @@
* Glynn Clements <glynn gclements.plus.com>, Soeren Gebbert <soeren.gebbert gmx.de>
* Updated for calculation errors and directional surface generation
* Colin Nielsen <colin.nielsen gmail com>
- * Updated for GRASS 7
+ * Use min heap instead of btree (faster, less memory)
* Markus Metz
* PURPOSE: anisotropic movements on cost surfaces
* COPYRIGHT: (C) 1999-2015 by the GRASS Development Team
@@ -114,8 +114,27 @@
struct Cell_head window;
struct start_pt *head_start_pt = NULL;
-struct start_pt *head_end_pt = NULL;
+struct rc
+{
+ int r;
+ int c;
+};
+
+static struct rc *stop_pnts = NULL;
+static int n_stop_pnts = 0;
+static int stop_pnts_alloc = 0;
+
+int cmp_rc(struct rc *a, struct rc *b)
+{
+ if (a->r == b->r)
+ return (a->c - b->c);
+
+ return (a->r - b->r);
+}
+
+void add_stop_pnt(int r, int c);
+
int main(int argc, char *argv[])
{
const char *cum_cost_layer, *move_dir_layer;
@@ -131,13 +150,13 @@
double min_cost, old_min_cost;
FCELL cur_dir;
double zero = 0.0;
- int col = 0, row = 0, nrows = 0, ncols = 0;
+ int col, row, nrows, ncols;
int maxcost, par_number;
int nseg;
int maxmem;
int segments_in_memory;
int cost_fd, cum_fd, dtm_fd, dir_fd;
- int have_stop_points = 0, dir = 0;
+ int dir = 0;
double my_dtm, my_cost, check_dtm;
double null_cost, dnullval;
double a, b, c, d, lambda, slope_factor;
@@ -154,7 +173,6 @@
struct Option *opt9, *opt10, *opt11, *opt12, *opt13, *opt14, *opt15;
struct cost *pres_cell;
struct start_pt *pres_start_pt = NULL;
- struct start_pt *pres_stop_pt = NULL;
struct cc {
double dtm; /* elevation model */
double cost_in; /* friction costs */
@@ -357,13 +375,15 @@
G_fatal_error(_("Must specify exactly one of start_points, start_rast or coordinate"));
}
- if (opt3->answers)
- if (!process_answers(opt3->answers, &head_start_pt, &pres_start_pt))
+ if (opt3->answers) {
+ if (!process_start_coords(opt3->answers, &head_start_pt, &pres_start_pt))
G_fatal_error(_("No start points"));
+ }
- if (opt4->answers)
- have_stop_points =
- process_answers(opt4->answers, &head_end_pt, &pres_stop_pt);
+ if (opt4->answers) {
+ if (!process_stop_coords(opt4->answers))
+ G_fatal_error(_("No stop points"));
+ }
if (sscanf(opt5->answer, "%d", &maxcost) != 1 || maxcost < 0)
G_fatal_error(_("Inappropriate maximum cost: %d"), maxcost);
@@ -420,10 +440,10 @@
keep_nulls = 0; /* handled automagically... */
}
- dtm_layer = opt12->answer;
+ cum_cost_layer = opt1->answer;
cost_layer = opt2->answer;
- cum_cost_layer = opt1->answer;
move_dir_layer = opt11->answer;
+ dtm_layer = opt12->answer;
/* Find number of rows and columns in window */
nrows = Rast_window_rows();
@@ -662,7 +682,7 @@
struct line_cats *Cats;
struct bound_box box;
struct start_pt *new_start_pt;
- int type, got_one = 0;
+ int cat, type, npoints = 0;
Points = Vect_new_line_struct();
Cats = Vect_new_cats_struct();
@@ -693,7 +713,7 @@
}
if (!Vect_point_in_box(Points->x[0], Points->y[0], 0, &box))
continue;
- got_one = 1;
+ npoints++;
col = (int)Rast_easting_to_col(Points->x[0], &window);
row = (int)Rast_northing_to_row(Points->y[0], &window);
@@ -703,6 +723,8 @@
new_start_pt->row = row;
new_start_pt->col = col;
+ Vect_cat_get(Cats, 1, &cat);
+ new_start_pt->value = cat;
new_start_pt->next = NULL;
if (head_start_pt == NULL) {
@@ -716,10 +738,12 @@
}
}
+ if (npoints < 1)
+ G_fatal_error(_("No start points found in vector map <%s>"), Vect_get_full_name(&In));
+ else
+ G_verbose_message(n_("%d point found", "%d points found", npoints), npoints);
+
Vect_close(&In);
-
- if (!got_one)
- G_fatal_error(_("No start points found in vector <%s>"), opt7->answer);
}
/* read vector with stop points */
@@ -728,7 +752,6 @@
struct line_pnts *Points;
struct line_cats *Cats;
struct bound_box box;
- struct start_pt *new_start_pt;
int type;
G_message(_("Reading vector map <%s> with stop points..."), opt8->answer);
@@ -759,32 +782,16 @@
}
if (!Vect_point_in_box(Points->x[0], Points->y[0], 0, &box))
continue;
- have_stop_points = 1;
col = (int)Rast_easting_to_col(Points->x[0], &window);
row = (int)Rast_northing_to_row(Points->y[0], &window);
- new_start_pt =
- (struct start_pt *)(G_malloc(sizeof(struct start_pt)));
-
- new_start_pt->row = row;
- new_start_pt->col = col;
- new_start_pt->next = NULL;
-
- if (head_end_pt == NULL) {
- head_end_pt = new_start_pt;
- pres_stop_pt = new_start_pt;
- new_start_pt->next = NULL;
- }
- else {
- pres_stop_pt->next = new_start_pt;
- pres_stop_pt = new_start_pt;
- }
+ add_stop_pnt(row, col);
}
Vect_close(&In);
- if (!have_stop_points)
+ if (!stop_pnts)
G_fatal_error(_("No stop points found in vector <%s>"), opt8->answer);
}
@@ -800,7 +807,7 @@
if (search_mapset == NULL)
G_fatal_error(_("Raster map <%s> not found"), opt9->answer);
- fd = Rast_open_old(opt9->answer, "");
+ fd = Rast_open_old(opt9->answer, search_mapset);
data_type2 = Rast_get_map_type(fd);
dsize2 = Rast_cell_size(data_type2);
cell2 = Rast_allocate_buf(data_type2);
@@ -845,8 +852,7 @@
G_fatal_error(_("No start points"));
}
- /* If the starting points are given on the command line start a linked
- * list of cells ordered by increasing costs
+ /* Insert start points into min heap
*/
if (head_start_pt) {
struct start_pt *top_start_pt = NULL;
@@ -867,6 +873,25 @@
}
}
+ if (n_stop_pnts > 1) {
+ int i, j;
+
+ /* prune stop points */
+ j = 1;
+ for (i = 1; i < n_stop_pnts; i++) {
+ if (stop_pnts[i].r != stop_pnts[j - 1].r ||
+ stop_pnts[i].c != stop_pnts[j - 1].c) {
+ stop_pnts[j].r = stop_pnts[i].r;
+ stop_pnts[j].c = stop_pnts[i].c;
+ j++;
+ }
+ }
+ if (n_stop_pnts > j) {
+ G_message(_("Number of duplicate stop points: %d"), n_stop_pnts - j);
+ n_stop_pnts = j;
+ }
+ }
+
/* Loop through the heap and perform at each cell the following:
* 1) If an adjacent cell has not already been assigned a value compute
* the min cost and assign it.
@@ -1320,6 +1345,7 @@
break;
}
+ /* skip if costs could not be calculated */
if (Rast_is_d_null_value(&min_cost))
continue;
@@ -1346,12 +1372,13 @@
}
}
- if (have_stop_points && time_to_stop(pres_cell->row, pres_cell->col))
+ if (stop_pnts && time_to_stop(pres_cell->row, pres_cell->col))
break;
ct = pres_cell;
delete(pres_cell);
pres_cell = get_lowest();
+
if (ct == pres_cell)
G_warning(_("Error, ct == pres_cell"));
}
@@ -1480,13 +1507,13 @@
}
int
-process_answers(char **answers, struct start_pt **points,
+process_start_coords(char **answers, struct start_pt **points,
struct start_pt **top_start_pt)
{
int col, row;
double east, north;
struct start_pt *new_start_pt;
- int got_one = 0;
+ int point_no = 0;
*points = NULL;
@@ -1505,8 +1532,6 @@
east, north);
continue;
}
- else
- got_one = 1;
row = (window.north - north) / window.ns_res;
col = (east - window.west) / window.ew_res;
@@ -1515,6 +1540,7 @@
new_start_pt->row = row;
new_start_pt->col = col;
+ new_start_pt->value = ++point_no;
new_start_pt->next = NULL;
if (*points == NULL) {
@@ -1527,27 +1553,85 @@
*top_start_pt = new_start_pt;
}
}
- return (got_one);
+ return (point_no > 0);
}
+int process_stop_coords(char **answers)
+{
+ int col, row;
+ double east, north;
+
+ if (!answers)
+ return 0;
+
+ for (; *answers != NULL; answers += 2) {
+ if (!G_scan_easting(*answers, &east, G_projection()))
+ G_fatal_error(_("Illegal x coordinate <%s>"), *answers);
+ if (!G_scan_northing(*(answers + 1), &north, G_projection()))
+ G_fatal_error(_("Illegal y coordinate <%s>"), *(answers + 1));
+
+ if (east < window.west || east > window.east ||
+ north < window.south || north > window.north) {
+ G_warning(_("Warning, ignoring point outside window: %g, %g"),
+ east, north);
+ continue;
+ }
+
+ row = (window.north - north) / window.ns_res;
+ col = (east - window.west) / window.ew_res;
+
+ add_stop_pnt(row, col);
+ }
+
+ return (stop_pnts != NULL);
+}
+
+void add_stop_pnt(int r, int c)
+{
+ int i;
+ struct rc sp;
+
+ if (n_stop_pnts == stop_pnts_alloc) {
+ stop_pnts_alloc += 100;
+ stop_pnts = (struct rc *)G_realloc(stop_pnts, stop_pnts_alloc * sizeof(struct rc));
+ }
+
+ sp.r = r;
+ sp.c = c;
+ i = n_stop_pnts;
+ while (i > 0 && cmp_rc(stop_pnts + i - 1, &sp) > 0) {
+ stop_pnts[i] = stop_pnts[i - 1];
+ i--;
+ }
+ stop_pnts[i] = sp;
+
+ n_stop_pnts++;
+}
+
int time_to_stop(int row, int col)
{
- static int total = 0;
+ int lo, mid, hi;
+ struct rc sp;
static int hits = 0;
- struct start_pt *points;
- if (total == 0) {
- for (points = head_end_pt;
- points != NULL; points = points->next, total++) ;
- }
+ sp.r = row;
+ sp.c = col;
- for (points = head_end_pt; points != NULL; points = points->next)
+ lo = 0;
+ hi = n_stop_pnts - 1;
- if (points->row == row && points->col == col) {
- hits++;
- if (hits == total)
- return (1);
- }
+ /* bsearch with deferred test for equality
+ * slightly more efficient for worst case: no match */
+ while (lo < hi) {
+ mid = lo + ((hi - lo) >> 1);
+ if (cmp_rc(stop_pnts + mid, &sp) < 0)
+ lo = mid + 1;
+ else
+ hi = mid;
+ }
+ if (cmp_rc(stop_pnts + lo, &sp) == 0) {
+ return (++hits == n_stop_pnts);
+ }
- return (0);
+ return 0;
}
Modified: grass/trunk/raster/r.walk/stash.h
===================================================================
--- grass/trunk/raster/r.walk/stash.h 2017-12-18 22:19:38 UTC (rev 71951)
+++ grass/trunk/raster/r.walk/stash.h 2017-12-18 22:20:24 UTC (rev 71952)
@@ -24,13 +24,12 @@
{
int row;
int col;
+ int value;
struct start_pt *next;
};
-extern struct start_pt *head_start_pt;
-extern struct start_pt *head_end_pt;
-
-int process_answers(char **, struct start_pt **, struct start_pt **);
+int process_start_coords(char **, struct start_pt **, struct start_pt **);
+int process_stop_coords(char **answers);
int time_to_stop(int, int);
#endif /* __STASH_H__ */
More information about the grass-commit
mailing list