123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- /****************************************************************************
- *
- * MODULE: r.cost
- *
- * AUTHOR(S): Antony Awaida - IESL - M.I.T.
- * James Westervelt - CERL
- * Pierre de Mouveaux <pmx audiovu com>
- * Eric G. Miller <egm2 jps net>
- *
- * min heap by Markus Metz
- *
- * PURPOSE: Outputs a raster map layer showing the cumulative cost
- * of moving between different geographic locations on an
- * input raster map layer whose cell category values
- * represent cost.
- *
- * COPYRIGHT: (C) 2006-2009 by the GRASS Development Team
- *
- * This program is free software under the GNU General Public
- * License (>=v2). Read the file COPYING that comes with GRASS
- * for details.
- *
- ***************************************************************************/
- /* These routines manage the list of grid-cell candidates for
- * visiting to calculate distances to surrounding cells.
- * A min-heap approach is used. Components are
- * sorted first by distance then by the order in which they were added.
- *
- * insert ()
- * inserts a new row-col with its distance value into the heap
- *
- * delete()
- * deletes a row-col entry in the heap
- *
- * get_lowest()
- * retrieves the entry with the smallest distance value
- */
- #include <grass/gis.h>
- #include <stdlib.h>
- #include <grass/glocale.h>
- #include "cost.h"
- #define GET_PARENT(c) (((c) - 2) / 3 + 1)
- #define GET_CHILD(p) (((p) * 3) - 1)
- static long next_point = 0;
- static long heap_size = 0;
- static long heap_alloced = 0;
- static struct cost **heap_index, *free_point;
- int init_heap(void)
- {
- next_point = 0;
- heap_size = 0;
- heap_alloced = 1000;
- heap_index = (struct cost **) G_malloc(heap_alloced * sizeof(struct cost *));
- free_point = NULL;
-
- return 0;
- }
- int free_heap(void)
- {
- if (heap_alloced)
- G_free(heap_index);
- if (free_point)
- G_free(free_point);
- return 0;
- }
- /* compare two costs
- * return 1 if a < b else 0 */
- int cmp_costs(struct cost *a, struct cost *b)
- {
- if (a->min_cost < b->min_cost)
- return 1;
- else if (a->min_cost == b->min_cost) {
- if (a->age < b->age)
- return 1;
- }
- return 0;
- }
- long sift_up(long start, struct cost * child_pnt)
- {
- register long parent, child;
- int r, c;
- r = child_pnt->row;
- c = child_pnt->col;
-
- child = start;
- while (child > 1) {
- parent = GET_PARENT(child);
- /* child is smaller */
- if (cmp_costs(child_pnt, heap_index[parent])) {
- /* push parent point down */
- heap_index[child] = heap_index[parent];
- child = parent;
- }
- else
- /* no more sifting up, found new slot for child */
- break;
- }
- /* put point in new slot */
- if (child < start) {
- heap_index[child] = child_pnt;
- }
- return child;
- }
- struct cost *insert(double min_cost, int row, int col)
- {
- struct cost *new_cell;
- if (free_point) {
- new_cell = free_point;
- free_point = NULL;
- }
- else
- new_cell = (struct cost *)(G_malloc(sizeof(struct cost)));
- new_cell->min_cost = min_cost;
- new_cell->age = next_point;
- new_cell->row = row;
- new_cell->col = col;
- next_point++;
- heap_size++;
- if (heap_size >= heap_alloced) {
- heap_alloced += 1000;
- heap_index = (struct cost **) G_realloc((void *)heap_index, heap_alloced * sizeof(struct cost *));
- }
- heap_index[heap_size] = new_cell;
- sift_up(heap_size, new_cell);
- return (new_cell);
- }
- struct cost *get_lowest(void)
- {
- struct cost *next_cell;
- register long parent, child, childr, i;
- if (heap_size == 0)
- return NULL;
-
- next_cell = heap_index[1];
- heap_index[0] = next_cell;
- if (heap_size == 1) {
- heap_size--;
- heap_index[1] = NULL;
- return next_cell;
- }
- /* start with root */
- parent = 1;
- /* sift down: move hole back towards bottom of heap */
- while ((child = GET_CHILD(parent)) <= heap_size) {
- /* select smallest child */
- if (child < heap_size) {
- childr = child + 1;
- i = child + 3;
- while (childr < i && childr <= heap_size) {
- /* get smallest child */
- if (cmp_costs(heap_index[childr], heap_index[child])) {
- child = childr;
- }
- childr++;
- }
- }
- /* move hole down */
- heap_index[parent] = heap_index[child];
- parent = child;
- }
- /* hole is in lowest layer, move to heap end */
- if (parent < heap_size) {
- heap_index[parent] = heap_index[heap_size];
- /* sift up last swapped point, only necessary if hole moved to heap end */
- sift_up(parent, heap_index[parent]);
- }
- /* the actual drop */
- heap_size--;
- return next_cell;
- }
- int delete(struct cost *delete_cell)
- {
- if (free_point)
- G_free(delete_cell);
- else
- free_point = delete_cell;
- return 0;
- }
|