Преглед на файлове

new spatial index

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@44857 15284696-431f-4ddb-bdfa-cd5b030d7da7
Markus Metz преди 14 години
родител
ревизия
549dfa7f76
променени са 2 файла, в които са добавени 463 реда и са изтрити 127 реда
  1. 115 18
      lib/vector/diglib/spindex.c
  2. 348 109
      lib/vector/diglib/spindex_rw.c

+ 115 - 18
lib/vector/diglib/spindex.c

@@ -15,9 +15,11 @@
    \author Update to GRASS 7 Markus Metz
    \author Update to GRASS 7 Markus Metz
  */
  */
 
 
-#include <grass/config.h>
 #include <stdlib.h>
 #include <stdlib.h>
-#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include <string.h>
 #include <string.h>
 #include <grass/gis.h>
 #include <grass/gis.h>
 #include <grass/vector.h>
 #include <grass/vector.h>
@@ -37,14 +39,44 @@ int dig_spidx_init(struct Plus_head *Plus)
 
 
     ndims = (Plus->with_z != 0) ? 3 : 2;
     ndims = (Plus->with_z != 0) ? 3 : 2;
     Plus->spidx_with_z = (Plus->with_z != 0);
     Plus->spidx_with_z = (Plus->with_z != 0);
-
-    Plus->Node_spidx = RTreeNewIndex(ndims);
-    Plus->Line_spidx = RTreeNewIndex(ndims);
-    Plus->Area_spidx = RTreeNewIndex(ndims);
-    Plus->Isle_spidx = RTreeNewIndex(ndims);
-    Plus->Face_spidx = NULL;
-    Plus->Volume_spidx = NULL;
-    Plus->Hole_spidx = NULL;
+    
+    if (Plus->Spidx_file) {
+	int fd;
+	char *filename;
+	
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Node_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Line_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Area_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Isle_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+
+	Plus->Face_spidx = NULL;
+	Plus->Volume_spidx = NULL;
+	Plus->Hole_spidx = NULL;
+    }
+    else {
+	Plus->Node_spidx = RTreeNewIndex(-1, 0, ndims);
+	Plus->Line_spidx = RTreeNewIndex(-1, 0, ndims);
+	Plus->Area_spidx = RTreeNewIndex(-1, 0, ndims);
+	Plus->Isle_spidx = RTreeNewIndex(-1, 0, ndims);
+	Plus->Face_spidx = NULL;
+	Plus->Volume_spidx = NULL;
+	Plus->Hole_spidx = NULL;
+    }
 
 
     Plus->Node_spidx_offset = 0L;
     Plus->Node_spidx_offset = 0L;
     Plus->Line_spidx_offset = 0L;
     Plus->Line_spidx_offset = 0L;
@@ -71,8 +103,21 @@ void dig_spidx_free_nodes(struct Plus_head *Plus)
     ndims = Plus->with_z ? 3 : 2;
     ndims = Plus->with_z ? 3 : 2;
 
 
     /* Node spidx */
     /* Node spidx */
-    RTreeFreeIndex(Plus->Node_spidx);
-    Plus->Node_spidx = RTreeNewIndex(ndims);
+    if (Plus->Node_spidx->fd > -1) {
+	int fd;
+	char *filename;
+	
+	close(Plus->Node_spidx->fd);
+	RTreeFreeIndex(Plus->Node_spidx);
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Node_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+    }
+    else {
+	RTreeFreeIndex(Plus->Node_spidx);
+	Plus->Node_spidx = RTreeNewIndex(-1, 0, ndims);
+    }
 }
 }
 
 
 /*! 
 /*! 
@@ -87,8 +132,21 @@ void dig_spidx_free_lines(struct Plus_head *Plus)
     ndims = Plus->with_z ? 3 : 2;
     ndims = Plus->with_z ? 3 : 2;
 
 
     /* Line spidx */
     /* Line spidx */
-    RTreeFreeIndex(Plus->Line_spidx);
-    Plus->Line_spidx = RTreeNewIndex(ndims);
+    if (Plus->Line_spidx->fd > -1) {
+	int fd;
+	char *filename;
+	
+	close(Plus->Line_spidx->fd);
+	RTreeFreeIndex(Plus->Line_spidx);
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Line_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+    }
+    else {
+	RTreeFreeIndex(Plus->Line_spidx);
+	Plus->Line_spidx = RTreeNewIndex(-1, 0, ndims);
+    }
 }
 }
 
 
 /*! 
 /*! 
@@ -103,8 +161,21 @@ void dig_spidx_free_areas(struct Plus_head *Plus)
     ndims = Plus->with_z ? 3 : 2;
     ndims = Plus->with_z ? 3 : 2;
 
 
     /* Area spidx */
     /* Area spidx */
-    RTreeFreeIndex(Plus->Area_spidx);
-    Plus->Area_spidx = RTreeNewIndex(ndims);
+    if (Plus->Area_spidx->fd > -1) {
+	int fd;
+	char *filename;
+	
+	close(Plus->Area_spidx->fd);
+	RTreeFreeIndex(Plus->Area_spidx);
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Area_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+    }
+    else {
+	RTreeFreeIndex(Plus->Area_spidx);
+	Plus->Area_spidx = RTreeNewIndex(-1, 0, ndims);
+    }
 }
 }
 
 
 /*! 
 /*! 
@@ -119,8 +190,21 @@ void dig_spidx_free_isles(struct Plus_head *Plus)
     ndims = Plus->with_z ? 3 : 2;
     ndims = Plus->with_z ? 3 : 2;
 
 
     /* Isle spidx */
     /* Isle spidx */
-    RTreeFreeIndex(Plus->Isle_spidx);
-    Plus->Isle_spidx = RTreeNewIndex(ndims);
+    if (Plus->Isle_spidx->fd > -1) {
+	int fd;
+	char *filename;
+	
+	close(Plus->Isle_spidx->fd);
+	RTreeFreeIndex(Plus->Isle_spidx);
+	filename = G_tempfile();
+	fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+	Plus->Isle_spidx = RTreeNewIndex(fd, 0, ndims);
+	remove(filename);
+    }
+    else {
+	RTreeFreeIndex(Plus->Isle_spidx);
+	Plus->Isle_spidx = RTreeNewIndex(-1, 0, ndims);
+    }
 }
 }
 
 
 /*! 
 /*! 
@@ -131,16 +215,29 @@ void dig_spidx_free_isles(struct Plus_head *Plus)
 void dig_spidx_free(struct Plus_head *Plus)
 void dig_spidx_free(struct Plus_head *Plus)
 {
 {
     /* Node spidx */
     /* Node spidx */
+    if (Plus->Node_spidx->fd > -1)
+	close(Plus->Node_spidx->fd);
     RTreeFreeIndex(Plus->Node_spidx);
     RTreeFreeIndex(Plus->Node_spidx);
 
 
     /* Line spidx */
     /* Line spidx */
+    if (Plus->Line_spidx->fd > -1)
+	close(Plus->Line_spidx->fd);
     RTreeFreeIndex(Plus->Line_spidx);
     RTreeFreeIndex(Plus->Line_spidx);
 
 
     /* Area spidx */
     /* Area spidx */
+    if (Plus->Area_spidx->fd > -1)
+	close(Plus->Area_spidx->fd);
     RTreeFreeIndex(Plus->Area_spidx);
     RTreeFreeIndex(Plus->Area_spidx);
 
 
     /* Isle spidx */
     /* Isle spidx */
+    if (Plus->Isle_spidx->fd > -1)
+	close(Plus->Isle_spidx->fd);
     RTreeFreeIndex(Plus->Isle_spidx);
     RTreeFreeIndex(Plus->Isle_spidx);
+
+    /* 3D future : */
+    /* Face spidx */
+    /* Volume spidx */
+    /* Hole spidx */
 }
 }
 
 
 /*!
 /*!

+ 348 - 109
lib/vector/diglib/spindex_rw.c

@@ -24,21 +24,6 @@
 #include <grass/vector.h>
 #include <grass/vector.h>
 #include <grass/glocale.h>
 #include <grass/glocale.h>
 
 
-
-struct FBranch			/* branch for file based index */
-{
-    struct Rect rect;
-    off_t child;		/* position of child node in file */
-};
-
-struct FNode			/* node for file based index */
-{
-    int count;			/* number of branches */
-    int level;			/* 0 is leaf, others positive */
-    struct FBranch branch[MAXCARD];
-};
-
-
 /*!
 /*!
    \brief Write spatial index header to file
    \brief Write spatial index header to file
 
 
@@ -115,10 +100,10 @@ int dig_Wr_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* identical for all spatial indices: */
     /* identical for all spatial indices: */
     t = ptr->Node_spidx;
     t = ptr->Node_spidx;
     /* byte 12 : n dimensions */
     /* byte 12 : n dimensions */
-    if (0 >= dig__fwrite_port_C(&(t->ndims), 1, fp))
+    if (0 >= dig__fwrite_port_C((const char *)&(t->ndims), 1, fp))
 	return (-1);
 	return (-1);
     /* byte 13 : n sides */
     /* byte 13 : n sides */
-    if (0 >= dig__fwrite_port_C(&(t->nsides), 1, fp))
+    if (0 >= dig__fwrite_port_C((const char *)&(t->nsides), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 14 - 17 : nodesize */
     /* bytes 14 - 17 : nodesize */
     if (0 >= dig__fwrite_port_I(&(t->nodesize), 1, fp))
     if (0 >= dig__fwrite_port_I(&(t->nodesize), 1, fp))
@@ -140,13 +125,13 @@ int dig_Wr_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
 
 
     /* Node spatial index */
     /* Node spatial index */
     /* bytes 34 - 37 : n nodes */
     /* bytes 34 - 37 : n nodes */
-    if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 38 - 41 : n leafs */
     /* bytes 38 - 41 : n leafs */
-    if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 42 - 45 : n levels */
     /* bytes 42 - 45 : n levels */
-    if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fwrite_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 46 - 49 (LFS 53) : root node offset */
     /* bytes 46 - 49 (LFS 53) : root node offset */
     if (0 >=
     if (0 >=
@@ -157,13 +142,13 @@ int dig_Wr_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* Line spatial index */
     /* Line spatial index */
     t = ptr->Line_spidx;
     t = ptr->Line_spidx;
     /* bytes 50 - 53 (LFS 54 - 57) : n nodes */
     /* bytes 50 - 53 (LFS 54 - 57) : n nodes */
-    if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 54 - 57 (LFS 58 - 61) : n leafs */
     /* bytes 54 - 57 (LFS 58 - 61) : n leafs */
-    if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 58 - 61 (LFS 62 - 65) : n levels */
     /* bytes 58 - 61 (LFS 62 - 65) : n levels */
-    if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fwrite_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 62 - 65 (LFS 66 - 73) : root node offset */
     /* bytes 62 - 65 (LFS 66 - 73) : root node offset */
     if (0 >=
     if (0 >=
@@ -174,13 +159,13 @@ int dig_Wr_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* Area spatial index */
     /* Area spatial index */
     t = ptr->Area_spidx;
     t = ptr->Area_spidx;
     /* bytes 66 - 69 (LFS 74 - 77) : n nodes */
     /* bytes 66 - 69 (LFS 74 - 77) : n nodes */
-    if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 70 - 73 (LFS 78 - 81) : n leafs */
     /* bytes 70 - 73 (LFS 78 - 81) : n leafs */
-    if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 74 - 77 (LFS 82 - 85) : n levels */
     /* bytes 74 - 77 (LFS 82 - 85) : n levels */
-    if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fwrite_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 78 - 81 (LFS 86 - 93) : root node offset */
     /* bytes 78 - 81 (LFS 86 - 93) : root node offset */
     if (0 >=
     if (0 >=
@@ -191,13 +176,13 @@ int dig_Wr_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* Isle spatial index */
     /* Isle spatial index */
     t = ptr->Isle_spidx;
     t = ptr->Isle_spidx;
     /* bytes 82 - 85 (LFS 94 - 97) : n nodes */
     /* bytes 82 - 85 (LFS 94 - 97) : n nodes */
-    if (0 >= dig__fwrite_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 86 - 89 (LFS 98 - 101) : n leafs */
     /* bytes 86 - 89 (LFS 98 - 101) : n leafs */
-    if (0 >= dig__fwrite_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fwrite_port_I((const int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 90 - 93 (LFS 102 - 105) : n levels */
     /* bytes 90 - 93 (LFS 102 - 105) : n levels */
-    if (0 >= dig__fwrite_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fwrite_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 94 - 97 (LFS 106 - 113) : root node offset */
     /* bytes 94 - 97 (LFS 106 - 113) : root node offset */
     if (0 >=
     if (0 >=
@@ -338,14 +323,14 @@ int dig_Rd_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* identical for all spatial indices: */
     /* identical for all spatial indices: */
     t = ptr->Node_spidx;
     t = ptr->Node_spidx;
     /* byte 12 : n dimensions */
     /* byte 12 : n dimensions */
-    if (0 >= dig__fread_port_C(&(t->ndims), 1, fp))
+    if (0 >= dig__fread_port_C((char *)&(t->ndims), 1, fp))
 	return (-1);
 	return (-1);
     ptr->Line_spidx->ndims = t->ndims;
     ptr->Line_spidx->ndims = t->ndims;
     ptr->Area_spidx->ndims = t->ndims;
     ptr->Area_spidx->ndims = t->ndims;
     ptr->Isle_spidx->ndims = t->ndims;
     ptr->Isle_spidx->ndims = t->ndims;
 
 
     /* byte 13 : n sides */
     /* byte 13 : n sides */
-    if (0 >= dig__fread_port_C(&(t->nsides), 1, fp))
+    if (0 >= dig__fread_port_C((char *)&(t->nsides), 1, fp))
 	return (-1);
 	return (-1);
     ptr->Line_spidx->nsides = t->nsides;
     ptr->Line_spidx->nsides = t->nsides;
     ptr->Area_spidx->nsides = t->nsides;
     ptr->Area_spidx->nsides = t->nsides;
@@ -390,13 +375,13 @@ int dig_Rd_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
 
 
     /* Node spatial index */
     /* Node spatial index */
     /* bytes 34 - 37 : n nodes */
     /* bytes 34 - 37 : n nodes */
-    if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 38 - 41 : n leafs */
     /* bytes 38 - 41 : n leafs */
-    if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 42 - 45 : n levels */
     /* bytes 42 - 45 : n levels */
-    if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fread_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 46 - 49 (LFS 53) : root node offset */
     /* bytes 46 - 49 (LFS 53) : root node offset */
     if (0 >=
     if (0 >=
@@ -408,13 +393,13 @@ int dig_Rd_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* Line spatial index */
     /* Line spatial index */
     t = ptr->Line_spidx;
     t = ptr->Line_spidx;
     /* bytes 50 - 53 (LFS 54 - 57) : n nodes */
     /* bytes 50 - 53 (LFS 54 - 57) : n nodes */
-    if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 54 - 57 (LFS 58 - 61) : n leafs */
     /* bytes 54 - 57 (LFS 58 - 61) : n leafs */
-    if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 58 - 61 (LFS 62 - 65) : n levels */
     /* bytes 58 - 61 (LFS 62 - 65) : n levels */
-    if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fread_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 62 - 65 (LFS 66 - 73) : root node offset */
     /* bytes 62 - 65 (LFS 66 - 73) : root node offset */
     if (0 >=
     if (0 >=
@@ -426,13 +411,13 @@ int dig_Rd_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* Area spatial index */
     /* Area spatial index */
     t = ptr->Area_spidx;
     t = ptr->Area_spidx;
     /* bytes 66 - 69 (LFS 74 - 77) : n nodes */
     /* bytes 66 - 69 (LFS 74 - 77) : n nodes */
-    if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 70 - 73 (LFS 78 - 81) : n leafs */
     /* bytes 70 - 73 (LFS 78 - 81) : n leafs */
-    if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 74 - 77 (LFS 82 - 85) : n levels */
     /* bytes 74 - 77 (LFS 82 - 85) : n levels */
-    if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fread_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 78 - 81 (LFS 86 - 93) : root node offset */
     /* bytes 78 - 81 (LFS 86 - 93) : root node offset */
     if (0 >=
     if (0 >=
@@ -444,13 +429,13 @@ int dig_Rd_spidx_head(struct gvfile * fp, struct Plus_head *ptr)
     /* Isle spatial index */
     /* Isle spatial index */
     t = ptr->Isle_spidx;
     t = ptr->Isle_spidx;
     /* bytes 82 - 85 (LFS 94 - 97) : n nodes */
     /* bytes 82 - 85 (LFS 94 - 97) : n nodes */
-    if (0 >= dig__fread_port_I(&(t->n_nodes), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_nodes), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 86 - 89 (LFS 98 - 101) : n leafs */
     /* bytes 86 - 89 (LFS 98 - 101) : n leafs */
-    if (0 >= dig__fread_port_I(&(t->n_leafs), 1, fp))
+    if (0 >= dig__fread_port_I((int *)&(t->n_leafs), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 90 - 93 (LFS 102 - 105) : n levels */
     /* bytes 90 - 93 (LFS 102 - 105) : n levels */
-    if (0 >= dig__fread_port_I(&(t->n_levels), 1, fp))
+    if (0 >= dig__fread_port_I(&(t->rootlevel), 1, fp))
 	return (-1);
 	return (-1);
     /* bytes 94 - 97 (LFS 106 - 113) : root node offset */
     /* bytes 94 - 97 (LFS 106 - 113) : root node offset */
     if (0 >=
     if (0 >=
@@ -598,13 +583,13 @@ int rtree_dump_node(FILE * fp, struct Node *n, int with_z)
    \return offset to root node on success
    \return offset to root node on success
  */
  */
 
 
-static off_t rtree_write_to_sidx(struct gvfile * fp, off_t startpos,
+static off_t rtree_write_from_memory(struct gvfile *fp, off_t startpos,
 				 struct RTree *t, int off_t_size)
 				 struct RTree *t, int off_t_size)
 {
 {
     off_t nextfreepos = startpos;
     off_t nextfreepos = startpos;
-    int sidx_nodesize;
+    int sidx_nodesize, sidx_leafsize;
     struct Node *n;
     struct Node *n;
-    int i, j, writeout;
+    int i, j, writeout, maxcard;
     struct spidxstack
     struct spidxstack
     {
     {
 	off_t pos[MAXCARD];	/* file position of child node, object ID on level 0 */
 	off_t pos[MAXCARD];	/* file position of child node, object ID on level 0 */
@@ -615,9 +600,11 @@ static off_t rtree_write_to_sidx(struct gvfile * fp, off_t startpos,
 
 
     /* should be foolproof */
     /* should be foolproof */
     sidx_nodesize =
     sidx_nodesize =
-	(int)(2 * PORT_INT + MAXCARD * (off_t_size + NUMSIDES * PORT_DOUBLE));
+	(int)(2 * PORT_INT + t->nodecard * (off_t_size + NUMSIDES * PORT_DOUBLE));
+    sidx_leafsize =
+	(int)(2 * PORT_INT + t->leafcard * (off_t_size + NUMSIDES * PORT_DOUBLE));
 
 
-    /* stack size of t->n_levels + 1 would be enough because of
+    /* stack size of t->rootlevel + 1 would be enough because of
      * depth-first post-order traversal:
      * depth-first post-order traversal:
      * only one node per level on stack at any given time */
      * only one node per level on stack at any given time */
 
 
@@ -661,7 +648,8 @@ static off_t rtree_write_to_sidx(struct gvfile * fp, off_t startpos,
 	    /* write with dig__fwrite_port_* fns */
 	    /* write with dig__fwrite_port_* fns */
 	    dig__fwrite_port_I(&(s[top].sn->count), 1, fp);
 	    dig__fwrite_port_I(&(s[top].sn->count), 1, fp);
 	    dig__fwrite_port_I(&(s[top].sn->level), 1, fp);
 	    dig__fwrite_port_I(&(s[top].sn->level), 1, fp);
-	    for (j = 0; j < MAXCARD; j++) {
+	    maxcard = s[top].sn->level ? t->nodecard : t->leafcard;
+	    for (j = 0; j < maxcard; j++) {
 		dig__fwrite_port_D(s[top].sn->branch[j].rect.boundary,
 		dig__fwrite_port_D(s[top].sn->branch[j].rect.boundary,
 				   NUMSIDES, fp);
 				   NUMSIDES, fp);
 		/* leaf node: vector object IDs are stored in child.id */
 		/* leaf node: vector object IDs are stored in child.id */
@@ -678,7 +666,7 @@ static off_t rtree_write_to_sidx(struct gvfile * fp, off_t startpos,
 	     * they hold the position in file of the next nodes down the tree */
 	     * they hold the position in file of the next nodes down the tree */
 	    if (top >= 0) {
 	    if (top >= 0) {
 		s[top].pos[s[top].branch_id - 1] = nextfreepos;
 		s[top].pos[s[top].branch_id - 1] = nextfreepos;
-		nextfreepos += sidx_nodesize;
+		nextfreepos += (s[top + 1].sn->level ? sidx_nodesize : sidx_leafsize);
 	    }
 	    }
 	}
 	}
     }
     }
@@ -688,6 +676,123 @@ static off_t rtree_write_to_sidx(struct gvfile * fp, off_t startpos,
 
 
 
 
 /*!
 /*!
+   \brief Write RTree body from temporary file to sidx file
+   Must be called when new or updated vector is closed
+
+   \param[out] fp pointer to struct gvfile
+   \param startpos offset to struct gvfile where to start writing out
+   \param t pointer to RTree
+   \param off_t_size size of off_t used to write struct gvfile
+
+   \return -1 on error
+   \return offset to root node on success
+ */
+
+static off_t rtree_write_from_file(struct gvfile *fp, off_t startpos,
+				 struct RTree *t, int off_t_size)
+{
+    off_t nextfreepos = startpos;
+    int sidx_nodesize, sidx_leafsize;
+    struct Node *n;
+    int i, j, writeout, maxcard;
+    struct spidxstack
+    {
+	off_t pos[MAXCARD];	/* file position of child node, object ID on level 0 */
+	struct Node sn;		/* stack node */
+	int branch_id;		/* branch no to follow down */
+    } s[MAXLEVEL];
+    int top = 0;
+    
+    /* write pending changes to file */
+    RTreeFlushBuffer(t);
+
+    /* should be foolproof */
+    sidx_nodesize =
+	(int)(2 * PORT_INT + t->nodecard * (off_t_size + NUMSIDES * PORT_DOUBLE));
+    sidx_leafsize =
+	(int)(2 * PORT_INT + t->leafcard * (off_t_size + NUMSIDES * PORT_DOUBLE));
+
+    /* stack size of t->rootlevel + 1 would be enough because of
+     * depth-first post-order traversal:
+     * only one node per level on stack at any given time */
+
+    /* add root node position to stack */
+    s[top].branch_id = i = 0;
+    RTreeReadNode(&s[top].sn, t->rootpos, t);
+
+    /* depth-first postorder traversal 
+     * all children of a node are visitied and written out first
+     * when a child is written out, its position in file is stored in pos[] for
+     * the parent node and written out with the parent node */
+    /* root node is written out last and its position returned */
+
+    while (top >= 0) {
+	n = &(s[top].sn);
+	writeout = 1;
+	/* this is an internal node in the RTree
+	 * all its children are processed first,
+	 * before it is written out to the sidx file */
+	if (s[top].sn.level > 0) {
+	    for (i = s[top].branch_id; i < t->nodecard; i++) {
+		s[top].pos[i] = -1;
+		if (n->branch[i].child.pos >= 0) {
+		    s[top++].branch_id = i + 1;
+		    RTreeReadNode(&s[top].sn, n->branch[i].child.pos, t);
+		    s[top].branch_id = 0;
+		    writeout = 0;
+		    break;
+		}
+	    }
+	    if (writeout) {
+		/* nothing else found, ready to write out */
+		s[top].branch_id = t->nodecard;
+	    }
+	}
+	if (writeout) {
+	    /* write node to sidx file */
+	    if (G_ftell(fp->file) != nextfreepos)
+		G_fatal_error(_("Writing sidx: wrong node position in file"));
+
+	    /* write with dig__fwrite_port_* fns */
+	    dig__fwrite_port_I(&(s[top].sn.count), 1, fp);
+	    dig__fwrite_port_I(&(s[top].sn.level), 1, fp);
+	    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
+	    for (j = 0; j < maxcard; j++) {
+		dig__fwrite_port_D(s[top].sn.branch[j].rect.boundary,
+				   NUMSIDES, fp);
+		/* leaf node: vector object IDs are stored in child.id */
+		if (s[top].sn.level == 0)
+		    s[top].pos[j] = (off_t) s[top].sn.branch[j].child.id;
+		dig__fwrite_port_O(&(s[top].pos[j]), 1, fp, off_t_size);
+	    }
+
+	    top--;
+	    /* update corresponding child position of parent node
+	     * this node is only updated if its level is > 0, i.e.
+	     * this is an internal node
+	     * children of internal nodes do not have an ID, instead
+	     * they hold the position in file of the next nodes down the tree */
+	    if (top >= 0) {
+		s[top].pos[s[top].branch_id - 1] = nextfreepos;
+		nextfreepos += (s[top + 1].sn.level ? sidx_nodesize : sidx_leafsize);
+	    }
+	}
+    }
+    
+    return nextfreepos;
+}
+
+/* write RTree body to sidx file */
+static off_t rtree_write_to_sidx(struct gvfile *fp, off_t startpos,
+				 struct RTree *t, int off_t_size)
+{
+    if (t->fd > -1)
+	return rtree_write_from_file(fp, startpos, t, off_t_size);
+    else
+	return rtree_write_from_memory(fp, startpos, t, off_t_size);
+}
+
+/*!
    \brief Load RTree body from sidx file to memory
    \brief Load RTree body from sidx file to memory
    Must be called when old vector is opened in update mode
    Must be called when old vector is opened in update mode
 
 
@@ -699,21 +804,20 @@ static off_t rtree_write_to_sidx(struct gvfile * fp, off_t startpos,
    \return pointer to root node on success
    \return pointer to root node on success
  */
  */
 
 
-struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
+static void rtree_load_to_memory(struct gvfile *fp, off_t rootpos,
 				  struct RTree *t, int off_t_size)
 				  struct RTree *t, int off_t_size)
 {
 {
     struct Node *newnode = NULL;
     struct Node *newnode = NULL;
-    int i, j, loadnode;
+    int i, j, loadnode, maxcard;
     struct spidxstack
     struct spidxstack
     {
     {
-	off_t childpos[MAXCARD];
-	off_t pos;		/* file position of child node */
+	off_t pos[MAXCARD];	/* file position of child node, object ID on level 0 */
 	struct Node sn;		/* stack node */
 	struct Node sn;		/* stack node */
 	int branch_id;		/* branch no to follow down */
 	int branch_id;		/* branch no to follow down */
     } s[50], *last;
     } s[50], *last;
     int top = 0;
     int top = 0;
 
 
-    /* stack size of t->n_levels + 1 would be enough because of
+    /* stack size of t->rootlevel + 1 would be enough because of
      * depth-first postorder traversal:
      * depth-first postorder traversal:
      * only one node per level on stack at any given time */
      * only one node per level on stack at any given time */
 
 
@@ -723,17 +827,13 @@ struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
     /* read with dig__fread_port_* fns */
     /* read with dig__fread_port_* fns */
     dig__fread_port_I(&(s[top].sn.count), 1, fp);
     dig__fread_port_I(&(s[top].sn.count), 1, fp);
     dig__fread_port_I(&(s[top].sn.level), 1, fp);
     dig__fread_port_I(&(s[top].sn.level), 1, fp);
-    for (j = 0; j < MAXCARD; j++) {
+    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
+    for (j = 0; j < maxcard; j++) {
 	dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES, fp);
 	dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES, fp);
-	dig__fread_port_O(&(s[top].childpos[j]), 1, fp, off_t_size);
+	dig__fread_port_O(&(s[top].pos[j]), 1, fp, off_t_size);
 	/* leaf node: vector object IDs are stored in child.id */
 	/* leaf node: vector object IDs are stored in child.id */
 	if (s[top].sn.level == 0) {
 	if (s[top].sn.level == 0) {
-	    if (s[top].childpos[j]) {
-	    s[top].sn.branch[j].child.id =
-		(int)s[top].childpos[j];
-	    }
-	    else
-		s[top].sn.branch[j].child.id = 0;
+	    s[top].sn.branch[j].child.id = (int)s[top].pos[j];
 	}
 	}
 	else {
 	else {
 	    s[top].sn.branch[j].child.ptr = NULL;
 	    s[top].sn.branch[j].child.ptr = NULL;
@@ -753,29 +853,25 @@ struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
 	 * before it is transfered to the RTree in memory */
 	 * before it is transfered to the RTree in memory */
 	if (s[top].sn.level > 0) {
 	if (s[top].sn.level > 0) {
 	    for (i = s[top].branch_id; i < t->nodecard; i++) {
 	    for (i = s[top].branch_id; i < t->nodecard; i++) {
-		if (s[top].childpos[i] > 0) {
+		if (s[top].pos[i] > 0) {
 		    s[top++].branch_id = i + 1;
 		    s[top++].branch_id = i + 1;
-		    s[top].pos = last->childpos[i];
-		    G_fseek(fp->file, s[top].pos, SEEK_SET);
+		    G_fseek(fp->file, last->pos[i], SEEK_SET);
 		    /* read with dig__fread_port_* fns */
 		    /* read with dig__fread_port_* fns */
 		    dig__fread_port_I(&(s[top].sn.count), 1, fp);
 		    dig__fread_port_I(&(s[top].sn.count), 1, fp);
 		    dig__fread_port_I(&(s[top].sn.level), 1, fp);
 		    dig__fread_port_I(&(s[top].sn.level), 1, fp);
-		    for (j = 0; j < MAXCARD; j++) {
+		    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
+		    for (j = 0; j < maxcard; j++) {
 			dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
 			dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
 					  NUMSIDES, fp);
 					  NUMSIDES, fp);
-			dig__fread_port_O(&(s[top].childpos[j]), 1, fp,
+			dig__fread_port_O(&(s[top].pos[j]), 1, fp,
 					  off_t_size);
 					  off_t_size);
 			/* leaf node
 			/* leaf node
 			 * vector object IDs are stored in file as
 			 * vector object IDs are stored in file as
 			 * off_t but always fit into an int, see dig_structs.h
 			 * off_t but always fit into an int, see dig_structs.h
 			 * vector object IDs are transfered to child.id */
 			 * vector object IDs are transfered to child.id */
 			if (s[top].sn.level == 0) {
 			if (s[top].sn.level == 0) {
-			    if (s[top].childpos[j]) {
-				s[top].sn.branch[j].child.id =
-				    (int)s[top].childpos[j];
-			    }
-			    else
-				s[top].sn.branch[j].child.id = 0;
+			    s[top].sn.branch[j].child.id =
+				(int)s[top].pos[j];
 			}
 			}
 			else {
 			else {
 			    s[top].sn.branch[j].child.ptr = NULL;
 			    s[top].sn.branch[j].child.ptr = NULL;
@@ -785,7 +881,7 @@ struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
 		    loadnode = 0;
 		    loadnode = 0;
 		    break;
 		    break;
 		}
 		}
-		else if (last->childpos[i] < 0)
+		else if (last->pos[i] < 0)
 		    G_fatal_error("corrupt spatial index");
 		    G_fatal_error("corrupt spatial index");
 	    }
 	    }
 	    if (loadnode) {
 	    if (loadnode) {
@@ -800,7 +896,8 @@ struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
 	    /* copy from stack node */
 	    /* copy from stack node */
 	    newnode->level = s[top].sn.level;
 	    newnode->level = s[top].sn.level;
 	    newnode->count = s[top].sn.count;
 	    newnode->count = s[top].sn.count;
-	    for (j = 0; j < MAXCARD; j++) {
+	    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
+	    for (j = 0; j < maxcard; j++) {
 		newnode->branch[j].rect = s[top].sn.branch[j].rect;
 		newnode->branch[j].rect = s[top].sn.branch[j].rect;
 		newnode->branch[j].child = s[top].sn.branch[j].child;
 		newnode->branch[j].child = s[top].sn.branch[j].child;
 	    }
 	    }
@@ -816,8 +913,144 @@ struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
 	    }
 	    }
 	}
 	}
     }
     }
+    
+    t->root = newnode;
+}
+
+/*!
+   \brief Load RTree body from sidx file to temporary file
+   Must be called when old vector is opened in update mode
+
+   \param fp pointer to struct gvfile
+   \param rootpos position of root node in file
+   \param t pointer to RTree
+   \param off_t_size size of off_t used to read struct gvfile
 
 
-    return newnode;
+   \return offset to root node
+ */
+
+static void rtree_load_to_file(struct gvfile *fp, off_t rootpos,
+				  struct RTree *t, int off_t_size)
+{
+    struct Node newnode;
+    off_t newnode_pos = -1;
+    int i, j, loadnode, maxcard;
+    struct spidxstack
+    {
+	off_t pos[MAXCARD];	/* file position of child node, object ID on level 0 */
+	struct Node sn;		/* stack node */
+	int branch_id;		/* branch no to follow down */
+    } s[MAXLEVEL], *last;
+    int top = 0;
+
+    /* stack size of t->rootlevel + 1 would be enough because of
+     * depth-first postorder traversal:
+     * only one node per level on stack at any given time */
+
+    /* add root node position to stack */
+    last = &(s[top]);
+    G_fseek(fp->file, rootpos, SEEK_SET);
+    /* read with dig__fread_port_* fns */
+    dig__fread_port_I(&(s[top].sn.count), 1, fp);
+    dig__fread_port_I(&(s[top].sn.level), 1, fp);
+    maxcard = t->rootlevel ? t->nodecard : t->leafcard;
+    for (j = 0; j < maxcard; j++) {
+	dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES, fp);
+	dig__fread_port_O(&(s[top].pos[j]), 1, fp, off_t_size);
+	/* leaf node: vector object IDs are stored in child.id */
+	if (s[top].sn.level == 0) {
+	    s[top].sn.branch[j].child.id = (int)s[top].pos[j];
+	}
+	else {
+	    s[top].sn.branch[j].child.pos = -1;
+	}
+    }
+
+    s[top].branch_id = i = 0;
+
+    /* depth-first postorder traversal */
+    /* root node is loaded last and returned */
+
+    while (top >= 0) {
+	last = &(s[top]);
+	loadnode = 1;
+	/* this is an internal node in the RTree
+	 * all its children are read first,
+	 * before it is transfered to the RTree in memory */
+	if (s[top].sn.level > 0) {
+	    for (i = s[top].branch_id; i < t->nodecard; i++) {
+		if (s[top].pos[i] > 0) {
+		    s[top++].branch_id = i + 1;
+		    G_fseek(fp->file, last->pos[i], SEEK_SET);
+		    /* read with dig__fread_port_* fns */
+		    dig__fread_port_I(&(s[top].sn.count), 1, fp);
+		    dig__fread_port_I(&(s[top].sn.level), 1, fp);
+		    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
+		    for (j = 0; j < maxcard; j++) {
+			dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
+					  NUMSIDES, fp);
+			dig__fread_port_O(&(s[top].pos[j]), 1, fp,
+					  off_t_size);
+			/* leaf node
+			 * vector object IDs are stored in file as
+			 * off_t but always fit into an int, see dig_structs.h
+			 * vector object IDs are transfered to child.id */
+			if (s[top].sn.level == 0) {
+			    s[top].sn.branch[j].child.id =
+				    (int)s[top].pos[j];
+			}
+			else {
+			    s[top].sn.branch[j].child.pos = -1;
+			}
+		    }
+		    s[top].branch_id = 0;
+		    loadnode = 0;
+		    break;
+		}
+		else if (last->pos[i] < 0)
+		    G_fatal_error("corrupt spatial index");
+	    }
+	    if (loadnode) {
+		/* nothing else found, ready to load */
+		s[top].branch_id = t->nodecard;
+	    }
+	}
+	if (loadnode) {
+	    /* ready to load node and write to temp file */
+
+	    /* copy from stack node */
+	    newnode.level = s[top].sn.level;
+	    newnode.count = s[top].sn.count;
+	    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
+	    for (j = 0; j < maxcard; j++) {
+		newnode.branch[j].rect = s[top].sn.branch[j].rect;
+		newnode.branch[j].child = s[top].sn.branch[j].child;
+	    }
+	    newnode_pos = RTreeGetNodePos(t);
+	    RTreeWriteNode(&newnode, t);
+
+	    top--;
+	    /* update child of parent node
+	     * this node is only updated if its level is > 0, i.e.
+	     * this is an internal node
+	     * children of internal nodes do not have an ID, instead
+	     * they point to the next nodes down the tree */
+	    if (top >= 0) {
+		s[top].sn.branch[s[top].branch_id - 1].child.pos = newnode_pos;
+	    }
+	}
+    }
+    
+    t->rootpos = newnode_pos;
+}
+
+static void rtree_load_from_sidx(struct gvfile *fp, off_t rootpos,
+				  struct RTree *t, int off_t_size)
+{
+    if (t->fd > -1)
+	return rtree_load_to_file(fp, rootpos, t, off_t_size);
+    else
+	return rtree_load_to_memory(fp, rootpos, t, off_t_size);
 }
 }
 
 
 /*!
 /*!
@@ -828,7 +1061,7 @@ struct Node *rtree_load_from_sidx(struct gvfile * fp, off_t rootpos,
 
 
    \return 0
    \return 0
  */
  */
-int dig_Wr_spidx(struct gvfile * fp, struct Plus_head *Plus)
+int dig_Wr_spidx(struct gvfile *fp, struct Plus_head *Plus)
 {
 {
     G_debug(1, "dig_Wr_spidx()");
     G_debug(1, "dig_Wr_spidx()");
 
 
@@ -891,24 +1124,20 @@ int dig_Rd_spidx(struct gvfile * fp, struct Plus_head *Plus)
     dig_set_cur_port(&(Plus->spidx_port));
     dig_set_cur_port(&(Plus->spidx_port));
 
 
     /* Nodes */
     /* Nodes */
-    Plus->Node_spidx->root =
-	rtree_load_from_sidx(fp, Plus->Node_spidx_offset,
-			     Plus->Node_spidx, Plus->spidx_port.off_t_size);
+    rtree_load_from_sidx(fp, Plus->Node_spidx_offset,
+			 Plus->Node_spidx, Plus->spidx_port.off_t_size);
 
 
     /* Lines */
     /* Lines */
-    Plus->Line_spidx->root =
-	rtree_load_from_sidx(fp, Plus->Line_spidx_offset,
-			     Plus->Line_spidx, Plus->spidx_port.off_t_size);
+    rtree_load_from_sidx(fp, Plus->Line_spidx_offset,
+			 Plus->Line_spidx, Plus->spidx_port.off_t_size);
 
 
     /* Areas */
     /* Areas */
-    Plus->Area_spidx->root =
-	rtree_load_from_sidx(fp, Plus->Area_spidx_offset,
-			     Plus->Area_spidx, Plus->spidx_port.off_t_size);
+    rtree_load_from_sidx(fp, Plus->Area_spidx_offset,
+			 Plus->Area_spidx, Plus->spidx_port.off_t_size);
 
 
     /* Isles */
     /* Isles */
-    Plus->Isle_spidx->root =
-	rtree_load_from_sidx(fp, Plus->Isle_spidx_offset,
-			     Plus->Isle_spidx, Plus->spidx_port.off_t_size);
+    rtree_load_from_sidx(fp, Plus->Isle_spidx_offset,
+			 Plus->Isle_spidx, Plus->spidx_port.off_t_size);
 
 
     /* 3D future : */
     /* 3D future : */
     /* Faces */
     /* Faces */
@@ -959,21 +1188,20 @@ int dig_dump_spidx(FILE * fp, const struct Plus_head *Plus)
 int rtree_search(struct RTree *t, struct Rect *r, SearchHitCallback shcb,
 int rtree_search(struct RTree *t, struct Rect *r, SearchHitCallback shcb,
 		 void *cbarg, struct Plus_head *Plus)
 		 void *cbarg, struct Plus_head *Plus)
 {
 {
-    struct FNode *n;
-    int hitCount = 0, found;
+    int hitCount = 0, found, maxcard;
     int i, j;
     int i, j;
     struct spidxstack
     struct spidxstack
     {
     {
-	off_t pos;		/* file position of stack node */
-	struct FNode sn;	/* stack node */
+	off_t pos[MAXCARD];	/* file position of child node, object ID on level 0 */
+	struct Node sn;	        /* stack node */
 	int branch_id;		/* branch no to follow down */
 	int branch_id;		/* branch no to follow down */
-    } s[50];
+    } s[50], *last;
     int top = 0;
     int top = 0;
 
 
     assert(r);
     assert(r);
     assert(t);
     assert(t);
 
 
-    /* stack size of t->n_levels + 1 is enough because of depth first search */
+    /* stack size of t->rootlevel + 1 is enough because of depth first search */
     /* only one node per level on stack at any given time */
     /* only one node per level on stack at any given time */
 
 
     dig_set_cur_port(&(Plus->spidx_port));
     dig_set_cur_port(&(Plus->spidx_port));
@@ -983,39 +1211,50 @@ int rtree_search(struct RTree *t, struct Rect *r, SearchHitCallback shcb,
     /* read with dig__fread_port_* fns */
     /* read with dig__fread_port_* fns */
     dig__fread_port_I(&(s[top].sn.count), 1, &(Plus->spidx_fp));
     dig__fread_port_I(&(s[top].sn.count), 1, &(Plus->spidx_fp));
     dig__fread_port_I(&(s[top].sn.level), 1, &(Plus->spidx_fp));
     dig__fread_port_I(&(s[top].sn.level), 1, &(Plus->spidx_fp));
-    for (j = 0; j < MAXCARD; j++) {
+    maxcard = t->rootlevel ? t->nodecard : t->leafcard;
+    for (j = 0; j < maxcard; j++) {
 	dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES,
 	dig__fread_port_D(s[top].sn.branch[j].rect.boundary, NUMSIDES,
 			  &(Plus->spidx_fp));
 			  &(Plus->spidx_fp));
-	dig__fread_port_O(&(s[top].sn.branch[j].child), 1, &(Plus->spidx_fp),
+	dig__fread_port_O(&(s[top].pos[j]), 1, &(Plus->spidx_fp),
 			  Plus->spidx_port.off_t_size);
 			  Plus->spidx_port.off_t_size);
+	/* leaf node: vector object IDs are stored in child.id */
+	if (s[top].sn.level == 0) {
+	    s[top].sn.branch[j].child.id = (int)s[top].pos[j];
+	}
+	else {
+	    s[top].sn.branch[j].child.pos = s[top].pos[j];
+	}
     }
     }
 
 
-    s[top].pos = t->rootpos;
     s[top].branch_id = i = 0;
     s[top].branch_id = i = 0;
-    n = &(s[top].sn);
 
 
     while (top >= 0) {
     while (top >= 0) {
-	n = &(s[top].sn);
+	last = &(s[top]);
 	if (s[top].sn.level > 0) {	/* this is an internal node in the tree */
 	if (s[top].sn.level > 0) {	/* this is an internal node in the tree */
 	    found = 1;
 	    found = 1;
 	    for (i = s[top].branch_id; i < t->nodecard; i++) {
 	    for (i = s[top].branch_id; i < t->nodecard; i++) {
-		if (s[top].sn.branch[i].child &&
+		if (s[top].pos[i] > 0 &&
 		    RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
 		    RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
 		    s[top++].branch_id = i + 1;
 		    s[top++].branch_id = i + 1;
-		    s[top].pos = n->branch[i].child;
-
-		    dig_fseek(&(Plus->spidx_fp), s[top].pos, SEEK_SET);
+		    dig_fseek(&(Plus->spidx_fp), last->pos[i], SEEK_SET);
 		    /* read with dig__fread_port_* fns */
 		    /* read with dig__fread_port_* fns */
 		    dig__fread_port_I(&(s[top].sn.count), 1,
 		    dig__fread_port_I(&(s[top].sn.count), 1,
 				      &(Plus->spidx_fp));
 				      &(Plus->spidx_fp));
 		    dig__fread_port_I(&(s[top].sn.level), 1,
 		    dig__fread_port_I(&(s[top].sn.level), 1,
 				      &(Plus->spidx_fp));
 				      &(Plus->spidx_fp));
-		    for (j = 0; j < MAXCARD; j++) {
+		    maxcard = s[top].sn.level ? t->nodecard : t->leafcard;
+		    for (j = 0; j < maxcard; j++) {
 			dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
 			dig__fread_port_D(s[top].sn.branch[j].rect.boundary,
 					  NUMSIDES, &(Plus->spidx_fp));
 					  NUMSIDES, &(Plus->spidx_fp));
-			dig__fread_port_O(&(s[top].sn.branch[j].child), 1,
+			dig__fread_port_O(&(s[top].pos[j]), 1,
 					  &(Plus->spidx_fp),
 					  &(Plus->spidx_fp),
 					  Plus->spidx_port.off_t_size);
 					  Plus->spidx_port.off_t_size);
+			if (s[top].sn.level == 0) {
+			    s[top].sn.branch[j].child.id = (int)s[top].pos[j];
+			}
+			else {
+			    s[top].sn.branch[j].child.pos = s[top].pos[j];
+			}
 		    }
 		    }
 
 
 		    s[top].branch_id = 0;
 		    s[top].branch_id = 0;
@@ -1031,11 +1270,11 @@ int rtree_search(struct RTree *t, struct Rect *r, SearchHitCallback shcb,
 	}
 	}
 	else {			/* this is a leaf node */
 	else {			/* this is a leaf node */
 	    for (i = 0; i < t->leafcard; i++) {
 	    for (i = 0; i < t->leafcard; i++) {
-		if (s[top].sn.branch[i].child &&
+		if (s[top].sn.branch[i].child.id &&
 		    RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
 		    RTreeOverlap(r, &(s[top].sn.branch[i].rect), t)) {
 		    hitCount++;
 		    hitCount++;
 		    if (shcb) {	/* call the user-provided callback */
 		    if (shcb) {	/* call the user-provided callback */
-			if (!shcb((int)s[top].sn.branch[i].child, cbarg)) {
+			if (!shcb((int)s[top].sn.branch[i].child.id, cbarg)) {
 			    /* callback wants to terminate search early */
 			    /* callback wants to terminate search early */
 			    return hitCount;
 			    return hitCount;
 			}
 			}