Пример #1
0
/* Make a new node and initialize to have all branch cells empty. */
struct RTree_Node *RTreeNewNode(struct RTree *t, int level)
{
    struct RTree_Node *n;

    n = (struct RTree_Node *)malloc((size_t) t->nodesize);
    assert(n);
    RTreeInitNode(n, NODETYPE(level, t->fd));
    return n;
}
Пример #2
0
/*
 * Add a branch to a node.  Split the node if necessary.
 * Returns 0 if node not split.  Old node updated.
 * Returns 1 if node split, sets *new_node to address of new node.
 * Old node updated, becomes one of two.
 * Returns 2 if branches were removed for forced reinsertion
 */
int RTreeAddBranch(struct RTree_Branch *b, struct RTree_Node *n,
		   struct RTree_Node **newnode, struct RTree_ListBranch **ee,
		   struct RTree_Rect *cover, int *overflow, struct RTree *t)
{
    int i, maxkids;

    maxkids = MAXKIDS((n)->level, t);

    if (n->count < maxkids) {	/* split won't be necessary */
	if ((n)->level > 0) {   /* internal node */
	    for (i = 0; i < maxkids; i++) {	/* find empty branch */
		if (!t->valid_child(&(n->branch[i].child))) {
		    n->branch[i] = *b;
		    n->count++;
		    break;
		}
	    }
	    return 0;
	}
	else if ((n)->level == 0) {   /* leaf */
	    for (i = 0; i < maxkids; i++) {	/* find empty branch */
		if (n->branch[i].child.id == 0) {
		    n->branch[i] = *b;
		    n->count++;
		    break;
		}
	    }
	    return 0;
	}
    }
    else {
	if (n->level < t->rootlevel && overflow[n->level]) {
	    /* R*-tree forced reinsert */
	    RTreeRemoveBranches(n, b, ee, cover, t);
	    overflow[n->level] = 0;
	    return 2;
	}
	else {
	    if (t->fd > -1)
		RTreeInitNode(*newnode, NODETYPE(n->level, t->fd));
	    else
		*newnode = RTreeNewNode(t, (n)->level);
	    RTreeSplitNode(n, b, *newnode, t);
	    return 1;
	}
    }

    /* should not be reached */
    assert(0);
    return -1;
}
Пример #3
0
/* 
 * Insert a data rectangle into an index structure.
 * RTreeInsertRect provides for splitting the root;
 * returns 1 if root was split, 0 if it was not.
 * The level argument specifies the number of steps up from the leaf
 * level to insert; e.g. a data rectangle goes in at level = 0.
 * RTreeInsertRect2 does the actual insertion.
 */
int RTreeInsertRectF(struct RTree_Rect *r, union RTree_Child child, int level,
                     struct RTree *t)
{
    struct RTree_ListBranch *reInsertList = NULL;
    struct RTree_ListBranch *e;
    int result;
    char overflow[MAXLEVEL];
    struct RTree_Branch *b = &(t->tmpb1);
    off_t newnode_pos = -1;

    struct RTree_Node *oldroot;
    static struct RTree_Node *newroot = NULL, *newnode = NULL;
    
    if (!newroot) {
	newroot = RTreeAllocNode(t, 1);
	newnode = RTreeAllocNode(t, 1);
    }

    /* R*-tree forced reinsertion: for each level only once */
    memset(overflow, t->overflow, MAXLEVEL);

    result = RTreeInsertRect2F(r, child, level, newnode, &newnode_pos,
			       t, &reInsertList, overflow);

    if (result == 1) {	/* root split */
	oldroot = RTreeGetNode(t->rootpos, t->rootlevel, t);
	/* grow a new root, & tree taller */
	t->rootlevel++;
	RTreeInitNode(t, newroot, NODETYPE(t->rootlevel, t->fd));
	newroot->level = t->rootlevel;
	/* branch for old root */
	RTreeNodeCover(oldroot, &(b->rect), t);
	b->child.pos = t->rootpos;
	RTreeAddBranch(b, newroot, NULL, NULL, NULL, NULL, t);
	/* branch for new node created by RTreeInsertRect2() */
	RTreeNodeCover(newnode, &(b->rect), t);
	b->child.pos = newnode_pos;  /* offset to new node as returned by RTreeInsertRect2F() */
	RTreeAddBranch(b, newroot, NULL, NULL, NULL, NULL, t);
	/* write new root node */
	t->rootpos = RTreeGetNodePos(t);
	RTreeWriteNode(newroot, t);
	t->n_nodes++;

	return result;
    }

    if (result == 2) {	/* branches were removed */
	while (reInsertList) {
	    /* get next branch in list */
	    RTreeCopyBranch(b, &(reInsertList->b), t);
	    level = reInsertList->level;
	    e = reInsertList;
	    reInsertList = reInsertList->next;
	    RTreeFreeListBranch(e);
	    /* reinsert branches */
	    result =
		RTreeInsertRect2F(&(b->rect), b->child, level, newnode, &newnode_pos, t,
				 &reInsertList, overflow);

	    if (result == 1) {	/* root split */
		oldroot = RTreeGetNode(t->rootpos, t->rootlevel, t);
		/* grow a new root, & tree taller */
		t->rootlevel++;
		RTreeInitNode(t, newroot, NODETYPE(t->rootlevel, t->fd));
		newroot->level = t->rootlevel;
		/* branch for old root */
		RTreeNodeCover(oldroot, &(b->rect), t);
		b->child.pos = t->rootpos;
		RTreeAddBranch(b, newroot, NULL, NULL, NULL, NULL, t);
		/* branch for new node created by RTreeInsertRect2() */
		RTreeNodeCover(newnode, &(b->rect), t);
		b->child.pos = newnode_pos; 
		RTreeAddBranch(b, newroot, NULL, NULL, NULL, NULL, t);
		/* write new root node */
		t->rootpos = RTreeGetNodePos(t);
		RTreeWriteNode(newroot, t);
		t->n_nodes++;
	    }
	}
    }

    return result;
}
Пример #4
0
/*
 * Remove branches from a node. Select the 2 branches whose rectangle 
 * center is farthest away from node cover center.
 * Old node updated.
 */
static void RTreeRemoveBranches(struct RTree_Node *n, struct RTree_Branch *b,
				struct RTree_ListBranch **ee, struct RTree_Rect *cover,
				struct RTree *t)
{
    int i, j, maxkids, type;
    RectReal center_n[NUMDIMS], center_r, delta;
    struct RTree_Branch branchbuf[MAXCARD + 1];
    struct dist rdist[MAXCARD + 1];
    struct RTree_Rect new_cover;

    assert(cover);

    maxkids = MAXKIDS((n)->level, t);
    type = NODETYPE((n)->level, t->fd);
    
    assert(n->count == maxkids);	/* must be full */

    new_cover = RTreeCombineRect(cover, &(b->rect), t);

    /* center coords of node cover */
    for (j = 0; j < t->ndims; j++) {
	center_n[j] = (new_cover.boundary[j + NUMDIMS] + new_cover.boundary[j]) / 2;
    }

    /* compute distances of child rectangle centers to node cover center */
    for (i = 0; i < maxkids; i++) {
	branchbuf[i] = n->branch[i];
	rdist[i].distance = 0;
	rdist[i].id = i;
	for (j = 0; j < t->ndims; j++) {
	    center_r =
		(branchbuf[i].rect.boundary[j + NUMDIMS] +
		 branchbuf[i].rect.boundary[j]) / 2;
	    delta = center_n[j] - center_r;
	    rdist[i].distance += delta * delta;
	}

	RTreeInitBranch[type](&(n->branch[i]));
    }

    /* new branch */
    branchbuf[maxkids] = *b;
    rdist[maxkids].distance = 0;
    for (j = 0; j < t->ndims; j++) {
	center_r =
	    (b->rect.boundary[j + NUMDIMS] +
	     b->rect.boundary[j]) / 2;
	delta = center_n[j] - center_r;
	rdist[maxkids].distance += delta * delta;
    }
    rdist[maxkids].id = maxkids;

    /* quicksort dist */
    RTreeQuicksortDist(rdist, maxkids);

    /* put largest three in branch list, farthest from center first */
    for (i = 0; i < FORCECARD; i++) {
	RTreeReInsertBranch(branchbuf[rdist[maxkids - i].id], n->level, ee);
    }
    /* put remaining in node, closest to center first */
    for (i = 0; i < maxkids - FORCECARD + 1; i++) {
	n->branch[i] = branchbuf[rdist[i].id];
    }
    n->count = maxkids - FORCECARD + 1;
}