2
/****************************************************************************
6
* AUTHOR(S): Laura Toma, Bowdoin College - ltoma@bowdoin.edu
7
* Yi Zhuang - yzhuang@bowdoin.edu
9
* Ported to GRASS by William Richard -
10
* wkrichar@bowdoin.edu or willster3021@gmail.com
11
* Markus Metz: surface interpolation
15
* PURPOSE: To calculate the viewshed (the visible cells in the
16
* raster) for the given viewpoint (observer) location. The
17
* visibility model is the following: Two points in the raster are
18
* considered visible to each other if the cells where they belong are
19
* visible to each other. Two cells are visible to each other if the
20
* line-of-sight that connects their centers does not intersect the
21
* terrain. The terrain is NOT viewed as a tesselation of flat cells,
22
* i.e. if the line-of-sight does not pass through the cell center,
23
* elevation is determined using bilinear interpolation.
24
* The viewshed algorithm is efficient both in
25
* terms of CPU operations and I/O operations. It has worst-case
26
* complexity O(n lg n) in the RAM model and O(sort(n)) in the
27
* I/O-model. For the algorithm and all the other details see the
28
* paper: "Computing Visibility on * Terrains in External Memory" by
29
* Herman Haverkort, Laura Toma and Yi Zhuang.
31
* COPYRIGHT: (C) 2008 by the GRASS Development Team
33
* This program is free software under the GNU General Public License
34
* (>=v2). Read the file COPYING that comes with GRASS for details.
36
*****************************************************************************/
40
A R/B BST. Always call initNILnode() before using the tree.
44
Rewrote BST Deletion to improve efficiency
47
Bug fixed in deletion.
48
CLRS pseudocode forgot to make sure that x is not NIL before
49
calling rbDeleteFixup(root,x).
52
Some Cleanup. Separated the public portion and the
53
private porthion of the interface in the header
56
=================================
57
This is based on BST 1.0.4
60
find max is implemented in this version.
64
Major bug fix in deletion (when the node has two children,
65
one of them has a wrong parent pointer after the rotation in the deletion.)
78
#include <grass/gis.h>
79
#include <grass/glocale.h>
86
#define EPSILON 0.0000001
89
/*public:--------------------------------- */
90
RBTree *create_tree(TreeValue tv)
93
RBTree *rbt = (RBTree *) G_malloc(sizeof(RBTree));
94
TreeNode *root = (TreeNode *) G_malloc(sizeof(TreeNode));
97
rbt->root->value = tv;
98
rbt->root->left = NIL;
99
rbt->root->right = NIL;
100
rbt->root->parent = NIL;
101
rbt->root->color = RB_BLACK;
106
/*LT: not sure if this is correct */
107
int is_empty(RBTree * t)
110
return (t->root == NIL);
113
void delete_tree(RBTree * t)
115
destroy_sub_tree(t->root);
119
void destroy_sub_tree(TreeNode * node)
124
destroy_sub_tree(node->left);
125
destroy_sub_tree(node->right);
130
void insert_into(RBTree * rbt, TreeValue value)
132
insert_into_tree(&(rbt->root), value);
136
void delete_from(RBTree * rbt, double key)
138
delete_from_tree(&(rbt->root), key);
142
TreeNode *search_for_node_with_key(RBTree * rbt, double key)
144
return search_for_node(rbt->root, key);
147
/*------------The following is designed for viewshed's algorithm-------*/
148
double find_max_gradient_within_key(RBTree * rbt, double key, double angle, double gradient)
150
return find_max_value_within_key(rbt->root, key, angle, gradient);
153
/*<--------------------------------->
154
//Private below this line */
157
NIL = (TreeNode *) G_malloc(sizeof(TreeNode));
158
NIL->color = RB_BLACK;
159
NIL->value.angle[0] = 0;
160
NIL->value.angle[1] = 0;
161
NIL->value.angle[2] = 0;
162
NIL->value.gradient[0] = SMALLEST_GRADIENT;
163
NIL->value.gradient[1] = SMALLEST_GRADIENT;
164
NIL->value.gradient[2] = SMALLEST_GRADIENT;
165
NIL->value.maxGradient = SMALLEST_GRADIENT;
174
/*you can write change this compare function, depending on your TreeValue struct
175
//compare function used by findMaxValue
179
char compare_values(TreeValue * v1, TreeValue * v2)
181
if (v1->gradient[1] > v2->gradient[1])
183
if (v1->gradient[1] < v2->gradient[1])
190
/*a function used to compare two doubles */
194
char compare_double(double a, double b)
196
return (a < b ? -1 : (a > b));
201
/*create a tree node */
202
TreeNode *create_tree_node(TreeValue value)
206
ret = (TreeNode *) G_malloc(sizeof(TreeNode));
215
ret->value.maxGradient = SMALLEST_GRADIENT;
219
/*create node with its value set to the value given
220
//and insert the node into the tree
221
//rbInsertFixup may change the root pointer, so TreeNode** is passed in */
222
void insert_into_tree(TreeNode ** root, TreeValue value)
229
if (compare_double(value.key, curNode->value.key) == -1) {
230
nextNode = curNode->left;
233
nextNode = curNode->right;
237
while (nextNode != NIL) {
240
if (compare_double(value.key, curNode->value.key) == -1) {
241
nextNode = curNode->left;
244
nextNode = curNode->right;
249
//and place it at the right place
250
//created node is RED by default */
251
nextNode = create_tree_node(value);
253
nextNode->parent = curNode;
255
if (compare_double(value.key, curNode->value.key) == -1) {
256
curNode->left = nextNode;
259
curNode->right = nextNode;
262
TreeNode *inserted = nextNode;
264
/*update augmented maxGradient */
265
nextNode->value.maxGradient = find_value_min_value(&nextNode->value);
266
while (nextNode->parent != NIL) {
267
if (nextNode->parent->value.maxGradient < nextNode->value.maxGradient)
268
nextNode->parent->value.maxGradient = nextNode->value.maxGradient;
270
if (nextNode->parent->value.maxGradient > nextNode->value.maxGradient)
272
nextNode = nextNode->parent;
275
/*fix rb tree after insertion */
276
rb_insert_fixup(root, inserted);
281
void rb_insert_fixup(TreeNode ** root, TreeNode * z)
283
/*see pseudocode on page 281 in CLRS */
286
while (z->parent->color == RB_RED) {
287
if (z->parent == z->parent->parent->left) {
288
y = z->parent->parent->right;
289
if (y->color == RB_RED) { /*case 1 */
290
z->parent->color = RB_BLACK;
292
z->parent->parent->color = RB_RED;
293
z = z->parent->parent;
296
if (z == z->parent->right) { /*case 2 */
298
left_rotate(root, z); /*convert case 2 to case 3 */
300
z->parent->color = RB_BLACK; /*case 3 */
301
z->parent->parent->color = RB_RED;
302
right_rotate(root, z->parent->parent);
306
else { /*(z->parent == z->parent->parent->right) */
307
y = z->parent->parent->left;
308
if (y->color == RB_RED) { /*case 1 */
309
z->parent->color = RB_BLACK;
311
z->parent->parent->color = RB_RED;
312
z = z->parent->parent;
315
if (z == z->parent->left) { /*case 2 */
317
right_rotate(root, z); /*convert case 2 to case 3 */
319
z->parent->color = RB_BLACK; /*case 3 */
320
z->parent->parent->color = RB_RED;
321
left_rotate(root, z->parent->parent);
325
(*root)->color = RB_BLACK;
333
/*search for a node with the given key */
334
TreeNode *search_for_node(TreeNode * root, double key)
336
TreeNode *curNode = root;
338
while (curNode != NIL && compare_double(key, curNode->value.key) != 0) {
340
if (compare_double(key, curNode->value.key) == -1) {
341
curNode = curNode->left;
344
curNode = curNode->right;
352
/*function used by treeSuccessor */
353
TreeNode *tree_minimum(TreeNode * x)
355
while (x->left != NIL)
361
/*function used by deletion */
362
TreeNode *tree_successor(TreeNode * x)
365
return tree_minimum(x->right);
366
TreeNode *y = x->parent;
368
while (y != NIL && x == y->right) {
370
if (y->parent == NIL)
378
/*delete the node out of the tree */
379
void delete_from_tree(TreeNode ** root, double key)
387
z = search_for_node(*root, key);
390
/*node to delete is not found */
391
G_fatal_error(_("Attempt to delete node with key=%f failed"), key);
395
if (z->left == NIL || z->right == NIL)
398
y = tree_successor(z);
401
G_fatal_error(_("Successor node not found. Deletion fails."));
411
x->parent = y->parent;
414
if (y->parent == NIL) {
417
toFix = *root; /*augmentation to be fixed */
420
if (y == y->parent->left)
423
y->parent->right = x;
425
toFix = y->parent; /*augmentation to be fixed */
428
/*fix augmentation for removing y */
429
TreeNode *curNode = y;
432
while (curNode->parent != NIL) {
433
if (curNode->parent->value.maxGradient == find_value_min_value(&y->value)) {
434
left = find_max_value(curNode->parent->left);
435
right = find_max_value(curNode->parent->right);
438
curNode->parent->value.maxGradient = left;
440
curNode->parent->value.maxGradient = right;
442
if (find_value_min_value(&curNode->parent->value) >
443
curNode->parent->value.maxGradient)
444
curNode->parent->value.maxGradient =
445
find_value_min_value(&curNode->parent->value);
450
curNode = curNode->parent;
454
/*fix augmentation for x */
456
toFix->left->value.maxGradient >
457
toFix->right->value.maxGradient ? toFix->left->value.
458
maxGradient : toFix->right->value.maxGradient;
459
if (tmpMax > find_value_min_value(&toFix->value))
460
toFix->value.maxGradient = tmpMax;
462
toFix->value.maxGradient = find_value_min_value(&toFix->value);
465
if (y != NIL && y != z) {
466
double zGradient = find_value_min_value(&z->value);
468
z->value.key = y->value.key;
469
z->value.gradient[0] = y->value.gradient[0];
470
z->value.gradient[1] = y->value.gradient[1];
471
z->value.gradient[2] = y->value.gradient[2];
472
z->value.angle[0] = y->value.angle[0];
473
z->value.angle[1] = y->value.angle[1];
474
z->value.angle[2] = y->value.angle[2];
478
/*fix augmentation */
480
toFix->left->value.maxGradient >
481
toFix->right->value.maxGradient ? toFix->left->value.
482
maxGradient : toFix->right->value.maxGradient;
483
if (tmpMax > find_value_min_value(&toFix->value))
484
toFix->value.maxGradient = tmpMax;
486
toFix->value.maxGradient = find_value_min_value(&toFix->value);
488
while (z->parent != NIL) {
489
if (z->parent->value.maxGradient == zGradient) {
490
if (find_value_min_value(&z->parent->value) != zGradient &&
491
(!(z->parent->left->value.maxGradient == zGradient &&
492
z->parent->right->value.maxGradient == zGradient))) {
494
left = find_max_value(z->parent->left);
495
right = find_max_value(z->parent->right);
498
z->parent->value.maxGradient = left;
500
z->parent->value.maxGradient = right;
502
if (find_value_min_value(&z->parent->value) >
503
z->parent->value.maxGradient)
504
z->parent->value.maxGradient =
505
find_value_min_value(&z->parent->value);
511
if (z->value.maxGradient > z->parent->value.maxGradient)
512
z->parent->value.maxGradient = z->value.maxGradient;
520
if (y->color == RB_BLACK && x != NIL)
521
rb_delete_fixup(root, x);
529
/*fix the rb tree after deletion */
530
void rb_delete_fixup(TreeNode ** root, TreeNode * x)
534
while (x != *root && x->color == RB_BLACK) {
535
if (x == x->parent->left) {
536
w = x->parent->right;
537
if (w->color == RB_RED) {
539
x->parent->color = RB_RED;
540
left_rotate(root, x->parent);
541
w = x->parent->right;
549
if (w->left->color == RB_BLACK && w->right->color == RB_BLACK) {
554
if (w->right->color == RB_BLACK) {
555
w->left->color = RB_BLACK;
557
right_rotate(root, w);
558
w = x->parent->right;
561
w->color = x->parent->color;
562
x->parent->color = RB_BLACK;
563
w->right->color = RB_BLACK;
564
left_rotate(root, x->parent);
569
else { /*(x==x->parent->right) */
571
if (w->color == RB_RED) {
573
x->parent->color = RB_RED;
574
right_rotate(root, x->parent);
583
if (w->right->color == RB_BLACK && w->left->color == RB_BLACK) {
588
if (w->left->color == RB_BLACK) {
589
w->right->color = RB_BLACK;
591
left_rotate(root, w);
595
w->color = x->parent->color;
596
x->parent->color = RB_BLACK;
597
w->left->color = RB_BLACK;
598
right_rotate(root, x->parent);
609
/*find the min value in the given tree value */
610
double find_value_min_value(TreeValue * v)
612
if (v->gradient[0] < v->gradient[1]) {
613
if (v->gradient[0] < v->gradient[2])
614
return v->gradient[0];
616
return v->gradient[2];
619
if (v->gradient[1] < v->gradient[2])
620
return v->gradient[1];
622
return v->gradient[2];
624
return v->gradient[0];
627
/*find the max value in the given tree
628
//you need to provide a compare function to compare the nodes */
629
double find_max_value(TreeNode * root)
632
return SMALLEST_GRADIENT;
634
/*assert(root->value.maxGradient != SMALLEST_GRADIENT);
635
//LT: this shoudl be fixed
636
//if (root->value.maxGradient != SMALLEST_GRADIENT) */
637
return root->value.maxGradient;
642
/* find max within the max key */
643
double find_max_value_within_key(TreeNode * root, double maxKey, double angle, double gradient)
645
TreeNode *keyNode = search_for_node(root, maxKey);
647
if (keyNode == NIL) {
648
/*fprintf(stderr, "key node not found. error occurred!\n");
649
//there is no point in the structure with key < maxKey */
651
G_fatal_error(_("Attempt to find node with key=%f failed"), maxKey);
652
return SMALLEST_GRADIENT;
655
TreeNode *currNode = keyNode;
656
double max = SMALLEST_GRADIENT;
658
double curr_gradient;
660
while (currNode->parent != NIL) {
661
if (currNode == currNode->parent->right) { /*its the right node of its parent; */
662
tmpMax = find_max_value(currNode->parent->left);
665
if (find_value_min_value(&currNode->parent->value) > max)
666
max = find_value_min_value(&currNode->parent->value);
668
currNode = currNode->parent;
674
/* traverse all nodes with smaller distance */
675
max = SMALLEST_GRADIENT;
677
while (currNode != NIL) {
678
int checkme = (currNode->value.angle[0] <= angle &&
679
currNode->value.angle[2] >= angle);
681
if (!checkme && currNode->value.key > 0) {
682
G_warning(_("Angles outside angle %.4f"), angle);
683
G_warning(_("ENTER angle %.4f"), currNode->value.angle[0]);
684
G_warning(_("CENTER angle %.4f"), currNode->value.angle[1]);
685
G_warning(_("EXIT angle %.4f"), currNode->value.angle[2]);
686
G_warning(_("ENTER gradient %.4f"), currNode->value.gradient[0]);
687
G_warning(_("CENTER gradient %.4f"), currNode->value.gradient[1]);
688
G_warning(_("EXIT gradient %.4f"), currNode->value.gradient[2]);
691
if (currNode->value.key > maxKey) {
692
G_fatal_error(_("current dist too large %.4f > %.4f"), currNode->value.key, maxKey);
696
if (checkme && currNode != keyNode) {
697
if (angle < currNode->value.angle[1]) {
698
curr_gradient = currNode->value.gradient[1] +
699
(currNode->value.gradient[0] - currNode->value.gradient[1]) *
700
(currNode->value.angle[1] - angle) /
701
(currNode->value.angle[1] - currNode->value.angle[0]);
703
else if (angle > currNode->value.angle[1]) {
704
curr_gradient = currNode->value.gradient[1] +
705
(currNode->value.gradient[2] - currNode->value.gradient[1]) *
706
(angle - currNode->value.angle[1]) /
707
(currNode->value.angle[2] - currNode->value.angle[1]);
709
else /* angle == currNode->value.angle[1] */
710
curr_gradient = currNode->value.gradient[1];
712
if (curr_gradient > max)
718
/* get next smaller key */
719
if (currNode->left != NIL) {
720
currNode = currNode->left;
721
while (currNode->right != NIL)
722
currNode = currNode->right;
725
/* at smallest item in this branch, go back up */
730
currNode = currNode->parent;
731
} while (currNode != NIL && lastNode == currNode->left);
736
/* old code assuming flat cells */
737
while (keyNode->parent != NIL) {
738
if (keyNode == keyNode->parent->right) { /*its the right node of its parent; */
739
tmpMax = find_max_value(keyNode->parent->left);
742
if (keyNode->parent->value.gradient[1] > max)
743
max = keyNode->parent->value.gradient[1];
745
keyNode = keyNode->parent;
752
void left_rotate(TreeNode ** root, TreeNode * x)
758
/*maintain augmentation */
762
tmpMax = x->left->value.maxGradient > y->left->value.maxGradient ?
763
x->left->value.maxGradient : y->left->value.maxGradient;
765
if (tmpMax > find_value_min_value(&x->value))
766
x->value.maxGradient = tmpMax;
768
x->value.maxGradient = find_value_min_value(&x->value);
772
tmpMax = x->value.maxGradient > y->right->value.maxGradient ?
773
x->value.maxGradient : y->right->value.maxGradient;
775
if (tmpMax > find_value_min_value(&y->value))
776
y->value.maxGradient = tmpMax;
778
y->value.maxGradient = find_value_min_value(&y->value);
781
//see pseudocode on page 278 in CLRS */
783
x->right = y->left; /*turn y's left subtree into x's right subtree */
786
y->parent = x->parent; /*link x's parent to y */
788
if (x->parent == NIL) {
792
if (x == x->parent->left)
795
x->parent->right = y;
804
void right_rotate(TreeNode ** root, TreeNode * y)
810
/*maintain augmentation
814
tmpMax = x->right->value.maxGradient > y->right->value.maxGradient ?
815
x->right->value.maxGradient : y->right->value.maxGradient;
817
if (tmpMax > find_value_min_value(&y->value))
818
y->value.maxGradient = tmpMax;
820
y->value.maxGradient = find_value_min_value(&y->value);
823
tmpMax = x->left->value.maxGradient > y->value.maxGradient ?
824
x->left->value.maxGradient : y->value.maxGradient;
826
if (tmpMax > find_value_min_value(&x->value))
827
x->value.maxGradient = tmpMax;
829
x->value.maxGradient = find_value_min_value(&x->value);
833
x->right->parent = y;
835
x->parent = y->parent;
837
if (y->parent == NIL) {
841
if (y->parent->left == y)
844
y->parent->right = x;