/* 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; }
/* * 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; }