|
@@ -17,24 +17,39 @@
|
|
|
***************************************************************************/
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
+#include <grass/glocale.h>
|
|
|
+#include <grass/raster.h>
|
|
|
+#include <grass/btree.h>
|
|
|
#include "glob.h"
|
|
|
#include "local_proto.h"
|
|
|
-#include <grass/raster.h>
|
|
|
-#include <grass/glocale.h>
|
|
|
|
|
|
+static int compare(const void *aa, const void *bb)
|
|
|
+{
|
|
|
+ const CELL *a = aa;
|
|
|
+ const CELL *b = bb;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < nfiles; i++) {
|
|
|
+ if (a[i] > b[i])
|
|
|
+ return 1;
|
|
|
+ if (a[i] < b[i])
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
CELL cross(int fd[], int non_zero, int primary, int outfd)
|
|
|
{
|
|
|
+ BTREE btree;
|
|
|
CELL *cell[NFILES];
|
|
|
- CELL *result_cell, *rp;
|
|
|
- CELL cat[NFILES], cat0, cat1;
|
|
|
- register int i;
|
|
|
+ CELL *result_cell;
|
|
|
+ CELL cat[NFILES];
|
|
|
+ int row, col, i;
|
|
|
int zero;
|
|
|
- int row, col;
|
|
|
- register int p, q;
|
|
|
- int dir;
|
|
|
- NODE *pnode, *new_node;
|
|
|
CELL result;
|
|
|
+ int keysize = nfiles * sizeof(CELL);
|
|
|
+ void *ptr;
|
|
|
|
|
|
/* allocate i/o buffers for each raster map */
|
|
|
|
|
@@ -44,12 +59,9 @@ CELL cross(int fd[], int non_zero, int primary, int outfd)
|
|
|
|
|
|
/* initialize the reclass table */
|
|
|
result = 0;
|
|
|
- for (i = 0; i < nfiles; i++)
|
|
|
- cat[i] = 0;
|
|
|
- store_reclass(result, primary, cat);
|
|
|
|
|
|
/* here we go */
|
|
|
- plant_tree();
|
|
|
+ btree_create(&btree, compare, 1);
|
|
|
G_message(_("%s: STEP 1 ... "), G_program_name());
|
|
|
for (row = 0; row < nrows; row++) {
|
|
|
G_percent(row, nrows, 5);
|
|
@@ -65,7 +77,8 @@ CELL cross(int fd[], int non_zero, int primary, int outfd)
|
|
|
for (col = 0; col < ncols; col++) {
|
|
|
zero = 1;
|
|
|
for (i = 0; i < nfiles; i++) {
|
|
|
- if (cat[i] = cell[i][col])
|
|
|
+ cat[i] = cell[i][col];
|
|
|
+ if (!Rast_is_c_null_value(&cat[i]))
|
|
|
zero = 0;
|
|
|
else if (non_zero) {
|
|
|
zero = 1;
|
|
@@ -73,101 +86,18 @@ CELL cross(int fd[], int non_zero, int primary, int outfd)
|
|
|
}
|
|
|
}
|
|
|
if (zero) {
|
|
|
- result_cell[col] = 0;
|
|
|
+ Rast_set_c_null_value(&result_cell[col], 1);
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
/* search for this value in the tree */
|
|
|
- cat0 = cat[0];
|
|
|
- cat1 = cat0 - NCATS;
|
|
|
- q = 1;
|
|
|
- while (q > 0) {
|
|
|
- register CELL *t, *c;
|
|
|
- register CELL diff;
|
|
|
-
|
|
|
- pnode = &tree[p = q];
|
|
|
- t = pnode->cat;
|
|
|
-
|
|
|
- /* search the tree */
|
|
|
- dir = FOUND;
|
|
|
- if (*t > cat0)
|
|
|
- dir = LEFT;
|
|
|
- else if (*t++ <= cat1)
|
|
|
- dir = RIGHT;
|
|
|
- else {
|
|
|
- c = cat + 1;
|
|
|
- for (i = 1; i < nfiles; i++)
|
|
|
- if ((diff = (*t++ - *c++)) > 0) {
|
|
|
- dir = LEFT;
|
|
|
- break;
|
|
|
- }
|
|
|
- else if (diff < 0) {
|
|
|
- dir = RIGHT;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- switch (dir) {
|
|
|
- case FOUND:
|
|
|
- rp = &pnode->result[cat0 - pnode->cat[0]];
|
|
|
- if (*rp == 0) {
|
|
|
- *rp = ++result;
|
|
|
- store_reclass(result, primary, cat);
|
|
|
- }
|
|
|
- result_cell[col] = *rp;
|
|
|
- q = 0;
|
|
|
- break;
|
|
|
- case LEFT:
|
|
|
- q = pnode->left;
|
|
|
- break;
|
|
|
- case RIGHT:
|
|
|
- q = pnode->right;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (dir == FOUND)
|
|
|
- continue;
|
|
|
-
|
|
|
- /* add a new node to the tree and put this value into it */
|
|
|
- N++;
|
|
|
- /* grow the tree? */
|
|
|
- if (N >= tlen) {
|
|
|
- tree =
|
|
|
- (NODE *) G_realloc(tree, sizeof(NODE) * (tlen += INCR));
|
|
|
- pnode = &tree[p]; /* realloc moves tree, must reassign pnode */
|
|
|
- }
|
|
|
-
|
|
|
- new_node = &tree[N];
|
|
|
- new_node->cat = (CELL *) G_calloc(nfiles, sizeof(CELL));
|
|
|
- new_node->result = (CELL *) G_calloc(NCATS, sizeof(CELL));
|
|
|
-
|
|
|
- if (cat0 < 0)
|
|
|
- cat0 = -((-cat0) >> SHIFT) - 1;
|
|
|
- else
|
|
|
- cat0 = cat0 >> SHIFT;
|
|
|
-
|
|
|
- if (cat0 < 0)
|
|
|
- cat0 = -((-cat0) << SHIFT) + 1;
|
|
|
- else
|
|
|
- cat0 = cat0 << SHIFT;
|
|
|
- new_node->cat[0] = cat0;
|
|
|
-
|
|
|
- for (i = 1; i < nfiles; i++)
|
|
|
- new_node->cat[i] = cat[i];
|
|
|
-
|
|
|
- for (i = 0; i < NCATS; i++)
|
|
|
- new_node->result[i] = 0;
|
|
|
- result_cell[col] = new_node->result[cat[0] - cat0] = ++result;
|
|
|
- store_reclass(result, primary, cat);
|
|
|
-
|
|
|
- new_node->left = 0;
|
|
|
-
|
|
|
- if (dir == LEFT) {
|
|
|
- new_node->right = -p; /* create thread */
|
|
|
- pnode->left = N; /* insert left */
|
|
|
- }
|
|
|
+ if (btree_find(&btree, cat, &ptr))
|
|
|
+ result_cell[col] = *(CELL*)ptr;
|
|
|
else {
|
|
|
- new_node->right = pnode->right; /* copy right link/thread */
|
|
|
- pnode->right = N; /* add right */
|
|
|
+ btree_update(&btree, cat, keysize, &result, sizeof(CELL));
|
|
|
+ store_reclass(result, primary, cat);
|
|
|
+ result_cell[col] = result;
|
|
|
+ result++;
|
|
|
}
|
|
|
}
|
|
|
Rast_put_row(outfd, result_cell, CELL_TYPE);
|
|
@@ -175,8 +105,8 @@ CELL cross(int fd[], int non_zero, int primary, int outfd)
|
|
|
G_percent(nrows, nrows, 5);
|
|
|
|
|
|
/* free some memory */
|
|
|
- uproot_tree();
|
|
|
+ btree_free(&btree);
|
|
|
for (i = 0; i < nfiles; i++)
|
|
|
G_free(cell[i]);
|
|
|
- return result;
|
|
|
+ return result - 1;
|
|
|
}
|