[GRASS-SVN] r54000 - grass/trunk/lib/vector/diglib

svn_grass at osgeo.org svn_grass at osgeo.org
Fri Nov 23 11:39:25 PST 2012


Author: mmetz
Date: 2012-11-23 11:39:23 -0800 (Fri, 23 Nov 2012)
New Revision: 54000

Modified:
   grass/trunk/lib/vector/diglib/spindex_rw.c
Log:
diglib: add buffer for searching spatial index

Modified: grass/trunk/lib/vector/diglib/spindex_rw.c
===================================================================
--- grass/trunk/lib/vector/diglib/spindex_rw.c	2012-11-23 19:37:28 UTC (rev 53999)
+++ grass/trunk/lib/vector/diglib/spindex_rw.c	2012-11-23 19:39:23 UTC (rev 54000)
@@ -715,6 +715,8 @@
     /* root node is written out last and its position returned */
 
     while (top >= 0) {
+	if (s[top].sn == NULL)
+	    G_fatal_error("NULL node ptr at top = %d", top);
 	n = s[top].sn;
 	writeout = 1;
 	/* this is an internal node in the RTree
@@ -1305,6 +1307,72 @@
     return 0;
 }
 
+/* read node from file */
+static void rtree_read_node(struct NodeBuffer *nb,
+                              off_t nodepos, struct RTree *t, struct Plus_head *Plus)
+{
+    int i, maxcard;
+    off_t pos;
+    struct gvfile *file = &(Plus->spidx_fp);
+
+    dig_fseek(file, nodepos, SEEK_SET);
+    /* read with dig__fread_port_* fns */
+    dig__fread_port_I(&(nb->n.count), 1, file);
+    dig__fread_port_I(&(nb->n.level), 1, file);
+    maxcard = nb->n.level ? t->nodecard : t->leafcard;
+    for (i = 0; i < maxcard; i++) {
+	dig__fread_port_D(nb->n.branch[i].rect.boundary, NUMSIDES,
+			  file);
+	dig__fread_port_O(&pos, 1, file,
+			  Plus->spidx_port.off_t_size);
+	/* leaf node: vector object IDs are stored in child.id */
+	if (nb->n.level == 0) {
+	    nb->n.branch[i].child.id = (int)pos;
+	}
+	else {
+	    nb->n.branch[i].child.pos = pos;
+	}
+    }
+}
+
+/* get node from buffer or file */
+static struct RTree_Node *rtree_get_node(off_t nodepos, int level,
+                                         struct RTree *t,
+					 struct Plus_head *Plus)
+{
+    int which, i = 0;
+
+    /* check mru first */
+    while (t->nb[level][t->used[level][i]].pos != nodepos &&
+           t->nb[level][t->used[level][i]].pos >= 0 &&
+	   i < NODE_BUFFER_SIZE - 1)
+	i++;
+
+    which = t->used[level][i];
+
+    if (t->nb[level][which].pos != nodepos) {
+	rtree_read_node(&(t->nb[level][which]), nodepos, t, Plus);
+	t->nb[level][which].pos = nodepos;
+    }
+    assert(t->nb[level][which].n.level == level);
+    /* make it mru */
+    if (i) { /* t->used[level][0] != which */
+#if 0
+	t->used[level][i] = t->used[level][0];
+	t->used[level][0] = which;
+#else
+	while (i) {
+	    t->used[level][i] = t->used[level][i - 1];
+	    i--;
+	}
+	t->used[level][0] = which;
+#endif
+    }
+
+    return &(t->nb[level][which].n);
+}
+
+
 /*!
    \brief Search spatial index file
    Can't use regular RTreeSearch() here because sidx must be read
@@ -1321,31 +1389,24 @@
 int rtree_search(struct RTree *t, struct RTree_Rect *r,
                  SearchHitCallback shcb, void *cbarg, struct Plus_head *Plus)
 {
-    int hitCount = 0, found, maxcard;
-    int i, j;
-    struct spidxstack *last;
-    static struct spidxstack s[MAXLEVEL];
-    static int stack_init = 0;
-    int top = 0;
+    int hitCount = 0, found;
+    /* int j, maxcard; */
+    int i;
+    struct spidxpstack s[MAXLEVEL];
+    int top = 0, level;
+    off_t lastpos;
 
     assert(r);
     assert(t);
 
-    if (!stack_init) {
-	for (i = 0; i < MAXLEVEL; i++) {
-	    for (j = 0; j < MAXCARD; j++) {
-		s[i].sn.branch[j].rect.boundary = G_malloc(6 * sizeof(RectReal));
-	    }
-	}
-	stack_init = 1;
-    }
-
     /* stack size of t->rootlevel + 1 is enough because of depth first search */
     /* only one node per level on stack at any given time */
 
     dig_set_cur_port(&(Plus->spidx_port));
 
     /* add root node position to stack */
+    s[top].sn = rtree_get_node(t->rootpos, t->rootlevel, t, Plus);
+#if 0
     dig_fseek(&(Plus->spidx_fp), t->rootpos, SEEK_SET);
     /* read with dig__fread_port_* fns */
     dig__fread_port_I(&(s[top].sn.count), 1, &(Plus->spidx_fp));
@@ -1364,18 +1425,23 @@
 	    s[top].sn.branch[j].child.pos = s[top].pos[j];
 	}
     }
+#endif
 
     s[top].branch_id = i = 0;
 
     while (top >= 0) {
-	last = &(s[top]);
-	if (s[top].sn.level > 0) {	/* this is an internal node in the tree */
+	level = s[top].sn->level;
+	if (level > 0) {	/* this is an internal node in the tree */
 	    found = 1;
 	    for (i = s[top].branch_id; i < t->nodecard; i++) {
-		if (s[top].pos[i] > 0 &&
-		    RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
+		lastpos = s[top].sn->branch[i].child.pos;
+		if (lastpos > 0 &&
+		    RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
 		    s[top++].branch_id = i + 1;
-		    dig_fseek(&(Plus->spidx_fp), last->pos[i], SEEK_SET);
+		    s[top].sn = rtree_get_node(lastpos, level - 1, t, Plus);
+		    
+#if 0
+		    dig_fseek(&(Plus->spidx_fp), lastpos, SEEK_SET);
 		    /* read with dig__fread_port_* fns */
 		    dig__fread_port_I(&(s[top].sn.count), 1,
 				      &(Plus->spidx_fp));
@@ -1395,7 +1461,7 @@
 			    s[top].sn.branch[j].child.pos = s[top].pos[j];
 			}
 		    }
-
+#endif
 		    s[top].branch_id = 0;
 		    found = 0;
 		    break;
@@ -1409,12 +1475,12 @@
 	}
 	else {			/* this is a leaf node */
 	    for (i = 0; i < t->leafcard; i++) {
-		if (s[top].sn.branch[i].child.id &&
-		    RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
+		if (s[top].sn->branch[i].child.id &&
+		    RTreeOverlap(r, &(s[top].sn->branch[i].rect), t)) {
 		    hitCount++;
 		    if (shcb) {	/* call the user-provided callback */
-			if (!shcb((int)s[top].sn.branch[i].child.id,
-				  &s[top].sn.branch[i].rect, cbarg)) {
+			if (!shcb((int)s[top].sn->branch[i].child.id,
+				  &s[top].sn->branch[i].rect, cbarg)) {
 			    /* callback wants to terminate search early */
 			    return hitCount;
 			}



More information about the grass-commit mailing list