/*----------------------------------------------------------------------------- | Load branch buffer with branches from full node plus the extra branch. -----------------------------------------------------------------------------*/ static void RTreeGetBranches(struct Node *n, struct Branch *b) { register int i; assert(n); assert(b); /* load the branch buffer */ for (i=0; i<MAXKIDS(n); i++) { assert(n->branch[i].child); /* n should have every entry full */ BranchBuf[i] = n->branch[i]; } BranchBuf[MAXKIDS(n)] = *b; BranchCount = MAXKIDS(n) + 1; /* calculate rect containing all in the set */ CoverSplit = BranchBuf[0].rect; for (i=1; i<MAXKIDS(n)+1; i++) { CoverSplit = RTreeCombineRect(&CoverSplit, &BranchBuf[i].rect); } CoverSplitArea = RTreeRectSphericalVolume(&CoverSplit); RTreeInitNode(n); }
/* 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; }
/* * 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; }
/* * 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; }