Example #1
0
/* get node from buffer or file */
void RTreeGetNode(struct RTree_Node *n, off_t nodepos, int level, struct RTree *t)
{
    int which = (nodepos == t->nb[level][2].pos ? 2 : nodepos == t->nb[level][1].pos);

    if (t->nb[level][which].pos != nodepos) {
	/* replace least recently used (fastest method of lru, pseudo-lru, mru) */
	which = t->used[level][2];
	/* rewrite node in buffer */
	if (t->nb[level][which].dirty) {
	    RTreeRewriteNode(&(t->nb[level][which].n), t->nb[level][which].pos, t);
	    t->nb[level][which].dirty = 0;
	}
	RTreeReadNode(&(t->nb[level][which].n), nodepos, t);
	t->nb[level][which].pos = nodepos;
    }
    /* make it mru */
    if (t->used[level][2] == which) {
	t->used[level][2] = t->used[level][1];
	t->used[level][1] = t->used[level][0];
	t->used[level][0] = which; 
    }
    else if (t->used[level][1] == which) {
	t->used[level][1] = t->used[level][0];
	t->used[level][0] = which; 
    }
    *n = t->nb[level][which].n;
}
Example #2
0
/*!
   \brief Dump R-tree node from temp file to the file

   \param fp pointer to FILE
   \param pos position of Node in temp file
   \param with_z non-zero value for 3D vector data
   \param t RTree to dump

   \return 0
 */
int rtree_dump_node_file(FILE * fp, off_t pos, int with_z, struct RTree *t)
{
    int i;
    static struct RTree_Node *n = NULL;
    
    if (!n) {
	n = RTreeAllocNode(t, 1);
    }

    /* recursive nearly-but-a-bit-messy depth-first pre-order traversal
     * potentially filling up memory */
    /* TODO: change to non-recursive depth-first post-order traversal */
    /* left for comparison with GRASS6.x */

    RTreeReadNode(n, pos, t);
    fprintf(fp, "Node level=%d  count=%d\n", n->level, n->count);

    if (n->level > 0)
	for (i = 0; i < NODECARD; i++) {
	    if (n->branch[i].child.pos >= 0) {
		fprintf(fp, "  Branch %d", i);
		rtree_dump_branch_file(fp, &(n->branch[i]), with_z, n->level, t);
	    }
	}
    else
	for (i = 0; i < LEAFCARD; i++) {
	    if (n->branch[i].child.id) {
		fprintf(fp, "  Branch %d", i);
		rtree_dump_branch_file(fp, &(n->branch[i]), with_z, n->level, t);
	    }
	}

    return 0;
}
Example #3
0
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 RTree_Node *n;
    int i, j, writeout, maxcard;
    static struct spidxstack *s = NULL;
    int top = 0;
    
    if (!s) {
	s = G_malloc(MAXLEVEL * sizeof(struct spidxstack));
	for (i = 0; i < MAXLEVEL; i++) {
	    s[i].sn.branch = G_malloc(MAXCARD * sizeof(struct RTree_Branch));
	    for (j = 0; j < MAXCARD; j++) {
		s[i].sn.branch[j].rect.boundary = G_malloc(6 * sizeof(RectReal));
	    }
	}
    }

    /* 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] = 0;
		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("Unable to write spatial index. "
                              "Wrong node position (%"PRI_OFF_T") in file (should be %"PRI_OFF_T").",
                              G_ftell(fp->file), nextfreepos);
            
	    /* 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);
	    }
	}
    }
    
    close(t->fd);
    
    return nextfreepos;
}