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

svn_grass at osgeo.org svn_grass at osgeo.org
Wed Feb 18 14:05:44 PST 2015


Author: mmetz
Date: 2015-02-18 14:05:44 -0800 (Wed, 18 Feb 2015)
New Revision: 64680

Modified:
   grass/trunk/lib/btree2/kdtree.c
   grass/trunk/lib/btree2/kdtree.h
Log:
btree2lib: add range (box) search to kdtree

Modified: grass/trunk/lib/btree2/kdtree.c
===================================================================
--- grass/trunk/lib/btree2/kdtree.c	2015-02-18 21:11:58 UTC (rev 64679)
+++ grass/trunk/lib/btree2/kdtree.c	2015-02-18 22:05:44 UTC (rev 64680)
@@ -606,6 +606,104 @@
     return found;
 }
 
+/* find all nearest neighbors within range aka box search
+ * the range is specified with min and max for each dimension as
+ * (min1, min2, ..., minn, max1, max2, ..., maxn)
+ * results are stored in puid (uids)
+ * memory is allocated as needed, the calling fn must free the memory
+ * optionally an uid to be skipped can be given */
+int kdtree_rnn(struct kdtree *t, double *c, int **puid, int *skip)
+{
+    int i, k, found, inside;
+    struct kdnode sn, *n;
+    struct kdstack {
+	struct kdnode *n;
+	int dir;
+	char v;
+    } s[256];
+    int dir;
+    int top;
+    int *uid;
+
+    if (!t->root)
+	return 0;
+
+    sn.c = c;
+    sn.uid = (int)0x80000000;
+    if (skip)
+	sn.uid = *skip;
+
+    *puid = NULL;
+
+    k = 0;
+    uid = NULL;
+
+    found = 0;
+
+    /* go down */
+    top = 0;
+    s[top].n = t->root;
+    while (s[top].n) {
+	n = s[top].n;
+	dir = cmp(&sn, n, n->dim) > 0;
+	s[top].dir = dir;
+	s[top].v = 0;
+	top++;
+	s[top].n = n->child[dir];
+    }
+    
+    /* go back up */
+    while (top) {
+	top--;
+	
+	if (!s[top].v) {
+	    s[top].v = 1;
+	    n = s[top].n;
+
+	    if (n->uid != sn.uid) {
+		inside = 1;
+		for (i = 0; i < t->ndims; i++) {
+		    if (n->c[i] < sn.c[i] || n->c[i] > sn.c[i + t->ndims]) {
+			inside = 0;
+			break;
+		    }
+		}
+
+		if (inside) {
+		    if (found + 1 >= k) {
+			k = found + 10;
+			uid = G_realloc(uid, k * sizeof(int));
+		    }
+		    i = found;
+		    uid[i] = n->uid;
+		    found++;
+		}
+	    }
+
+	    /* look on the other side ? */
+	    dir = s[top].dir;
+	    if (n->c[(int)n->dim] >= sn.c[(int)n->dim] && 
+	        n->c[(int)n->dim] <= sn.c[(int)n->dim + t->ndims]) {
+		/* go down the other side */
+		top++;
+		s[top].n = n->child[!dir];
+		while (s[top].n) {
+		    n = s[top].n;
+		    dir = cmp(&sn, n, n->dim) > 0;
+		    s[top].dir = dir;
+		    s[top].v = 0;
+		    top++;
+		    s[top].n = n->child[dir];
+		}
+	    }
+	}
+    }
+
+    *puid = uid;
+
+    return found;
+}
+
 /* initialize tree traversal
  * (re-)sets trav structure
  * returns 0

Modified: grass/trunk/lib/btree2/kdtree.h
===================================================================
--- grass/trunk/lib/btree2/kdtree.h	2015-02-18 21:11:58 UTC (rev 64679)
+++ grass/trunk/lib/btree2/kdtree.h	2015-02-18 22:05:44 UTC (rev 64680)
@@ -123,6 +123,17 @@
 	       double maxdist,			/* radius to search around the given coordinates */
 	       int *skip);			/* unique id to skip */
 
+/* find all nearest neighbors within range aka box search
+ * the range is specified with min and max for each dimension as
+ * (min1, min2, ..., minn, max1, max2, ..., maxn)
+ * results are stored in puid (uids) and pd (squared distances)
+ * memory is allocated as needed, the calling fn must free the memory
+ * optionally an uid to be skipped can be given */
+int kdtree_rnn(struct kdtree *t,		/* k-d tree */
+               double *c,			/* coordinates for range */
+	       int **puid,			/* unique ids of the neighbors */
+	       int *skip);			/* unique id to skip */
+
 /* k-d tree optimization, only useful if the tree will be heavily used
  * (more searches than items in the tree)
  * level 0 = a bit, 1 = more, 2 = a lot */



More information about the grass-commit mailing list