[GRASS-SVN] r63951 - grass/trunk/lib/btree2

svn_grass at osgeo.org svn_grass at osgeo.org
Sun Jan 4 11:32:25 PST 2015


Author: mmetz
Date: 2015-01-04 11:32:25 -0800 (Sun, 04 Jan 2015)
New Revision: 63951

Modified:
   grass/trunk/lib/btree2/kdtree.c
   grass/trunk/lib/btree2/kdtree.h
Log:
btree2lib: add kdtree traversal

Modified: grass/trunk/lib/btree2/kdtree.c
===================================================================
--- grass/trunk/lib/btree2/kdtree.c	2015-01-03 22:50:11 UTC (rev 63950)
+++ grass/trunk/lib/btree2/kdtree.c	2015-01-04 19:32:25 UTC (rev 63951)
@@ -35,6 +35,8 @@
                                  struct kdnode *, int, int);
 static int kdtree_replace(struct kdtree *, struct kdnode *);
 static int kdtree_balance(struct kdtree *, struct kdnode *);
+static int kdtree_first(struct kdtrav *, double *, int *);
+static int kdtree_next(struct kdtrav *, double *, int *);
 
 static int cmp(struct kdnode *a, struct kdnode *b, int p)
 {
@@ -417,14 +419,15 @@
 	    n = s[top].n;
 
 	    if (n->uid != sn.uid) {
-		dist = 0;
-		for (i = 0; i < t->ndims; i++) {
-		    diff = sn.c[i] - n->c[i];
-		    dist += diff * diff;
-		    if (found == k && dist > maxdist)
-			break;
-		}
 		if (found < k) {
+		    dist = 0.0;
+		    i = t->ndims - 1;
+		    do {
+			diff = sn.c[i] - n->c[i];
+			dist += diff * diff;
+			
+		    } while (i--);
+
 		    i = found;
 		    while (i > 0 && d[i - 1] > dist) {
 			d[i] = d[i - 1];
@@ -438,19 +441,29 @@
 		    maxdist = d[found];
 		    found++;
 		}
-		else if (dist < maxdist) {
-		    i = k - 1;
-		    while (i > 0 && d[i - 1] > dist) {
-			d[i] = d[i - 1];
-			uid[i] = uid[i - 1];
-			i--;
+		else {
+		    dist = 0.0;
+		    i = t->ndims - 1;
+		    do {
+			diff = sn.c[i] - n->c[i];
+			dist += diff * diff;
+			
+		    } while (i-- && dist <= maxdist);
+
+		    if (dist < maxdist) {
+			i = k - 1;
+			while (i > 0 && d[i - 1] > dist) {
+			    d[i] = d[i - 1];
+			    uid[i] = uid[i - 1];
+			    i--;
+			}
+			if (d[i] == dist && uid[i] == n->uid)
+			    G_fatal_error("knn: inserting duplicate");
+			d[i] = dist;
+			uid[i] = n->uid;
+
+			maxdist = d[k - 1];
 		    }
-		    if (d[i] == dist && uid[i] == n->uid)
-			G_fatal_error("knn: inserting duplicate");
-		    d[i] = dist;
-		    uid[i] = n->uid;
-
-		    maxdist = d[k - 1];
 		}
 		if (found == k && maxdist == 0.0)
 		    break;
@@ -540,15 +553,16 @@
 
 	    if (n->uid != sn.uid) {
 		dist = 0;
-		for (i = 0; i < t->ndims; i++) {
+		i = t->ndims - 1;
+		do {
 		    diff = sn.c[i] - n->c[i];
 		    dist += diff * diff;
-		    if (dist > maxdistsq)
-			break;
-		}
+		    
+		} while (i-- && dist <= maxdistsq);
+
 		if (dist <= maxdistsq) {
 		    if (found + 1 >= k) {
-			k += 10;
+			k = found + 10;
 			uid = G_realloc(uid, k * sizeof(int));
 			d = G_realloc(d, k * sizeof(double));
 		    }
@@ -592,7 +606,45 @@
     return found;
 }
 
+/* initialize tree traversal
+ * (re-)sets trav structure
+ * returns 0
+ */
+int kdtree_init_trav(struct kdtrav *trav, struct kdtree *tree)
+{
+    trav->tree = tree;
+    trav->curr_node = tree->root;
+    trav->first = 1;
+    trav->top = 0;
 
+    return 0;
+}
+
+/* traverse the tree
+ * useful to get all items in the tree non-recursively
+ * struct kdtrav *trav needs to be initialized first
+ * returns 1, 0 when finished
+ */
+int kdtree_traverse(struct kdtrav *trav, double *c, int *uid)
+{
+    if (trav->curr_node == NULL) {
+	if (trav->first)
+	    G_debug(1, "k-d tree: empty tree");
+	else
+	    G_debug(1, "k-d tree: finished traversing");
+
+	return 0;
+    }
+
+    if (trav->first) {
+	trav->first = 0;
+	return kdtree_first(trav, c, uid);
+    }
+
+    return kdtree_next(trav, c, uid);
+}
+
+
 /**********************************************/
 /*            internal functions              */
 /**********************************************/
@@ -1038,3 +1090,60 @@
 
     return r;
 }
+
+/* start traversing the tree
+ * returns pointer to first item
+ */
+static int kdtree_first(struct kdtrav *trav, double *c, int *uid)
+{
+    /* get smallest item */
+    while (trav->curr_node->child[0] != NULL) {
+	trav->up[trav->top++] = trav->curr_node;
+	trav->curr_node = trav->curr_node->child[0];
+    }
+
+    memcpy(c, trav->curr_node->c, trav->tree->csize);
+    *uid = trav->curr_node->uid;
+
+    return 1;
+}
+
+/* continue traversing the tree in ascending order
+ * returns pointer to data item, NULL when finished
+ */
+static int kdtree_next(struct kdtrav *trav, double *c, int *uid)
+{
+    if (trav->curr_node->child[1] != NULL) {
+	/* something on the right side: larger item */
+	trav->up[trav->top++] = trav->curr_node;
+	trav->curr_node = trav->curr_node->child[1];
+
+	/* go down, find smallest item in this branch */
+	while (trav->curr_node->child[0] != NULL) {
+	    trav->up[trav->top++] = trav->curr_node;
+	    trav->curr_node = trav->curr_node->child[0];
+	}
+    }
+    else {
+	/* at smallest item in this branch, go back up */
+	struct kdnode *last;
+
+	do {
+	    if (trav->top == 0) {
+		trav->curr_node = NULL;
+		break;
+	    }
+	    last = trav->curr_node;
+	    trav->curr_node = trav->up[--trav->top];
+	} while (last == trav->curr_node->child[1]);
+    }
+
+    if (trav->curr_node != NULL) {
+	memcpy(c, trav->curr_node->c, trav->tree->csize);
+	*uid = trav->curr_node->uid;
+
+	return 1;
+    }
+
+    return 0;		/* finished traversing */
+}

Modified: grass/trunk/lib/btree2/kdtree.h
===================================================================
--- grass/trunk/lib/btree2/kdtree.h	2015-01-03 22:50:11 UTC (rev 63950)
+++ grass/trunk/lib/btree2/kdtree.h	2015-01-04 19:32:25 UTC (rev 63951)
@@ -68,6 +68,15 @@
     struct kdnode *root;	/* tree root */
 };
 
+struct kdtrav
+{
+    struct kdtree *tree;	/* tree being traversed */
+    struct kdnode *curr_node;	/* current node */
+    struct kdnode *up[256];	/* stack of parent nodes */
+    int top;			/* index for stack */
+    int first;			/* little helper flag */
+};
+
 /* creae a new k-d tree */
 struct kdtree *kdtree_create(char ndims,	/* number of dimensions */
                              int *btol);	/* optional balancing tolerance */
@@ -119,3 +128,16 @@
  * level 0 = a bit, 1 = more, 2 = a lot */
 void kdtree_optimize(struct kdtree *t,		/* k-d tree */
                      int level);		/* optimization level */
+
+/* initialize tree traversal
+ * (re-)sets trav structure
+ * returns 0
+ */
+int kdtree_init_trav(struct kdtrav *trav, struct kdtree *tree);
+
+/* traverse the tree
+ * useful to get all items in the tree non-recursively
+ * struct kdtrav *trav needs to be initialized first
+ * returns 1, 0 when finished
+ */
+int kdtree_traverse(struct kdtrav *trav, double *c, int *uid);



More information about the grass-commit mailing list