static int RTreeInsertNode (node_t n, int level, rect_t r, void *data, node_t *new_node) { int i; node_t n2; branch_t b; assert(n && new_node); assert(level >= 0 && level <= n->level); if (n->level > level) { i = RTreePickBranch(r,n); if (!RTreeInsertNode((node_t) n->branch[i].child, level, r, data,&n2)) /* not split */ { n->branch[i].mbr = RectCombine(r,n->branch[i].mbr); return FALSE; } else /* node split */ { n->branch[i].mbr = RTreeNodeCover(n->branch[i].child); b.child = n2; b.mbr = RTreeNodeCover(n2); return RTreeAddBranch(n, b, new_node); } } else /*insert level*/ { b.mbr = r; b.child = data; return RTreeAddBranch(n, b, new_node); } }
/* * Inserts a new data rectangle into the index structure. * Recursively descends tree, propagates splits back up. * Returns 0 if node was not split. Old node updated. * If node was split, returns 1 and sets the pointer pointed to by * new_node to point to the new node. Old node updated to become one of two. * 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. */ static int RTreeInsertRect2(struct Rect *r, long tid, struct Node *n, struct Node **new_node, int level) { /* register struct Rect *r = R; register long tid = Tid; register struct Node *n = N, **new_node = New_node; register int level = Level; */ register int i; struct Branch b; struct Node *n2; assert(r && n && new_node); assert(level >= 0 && level <= n->level); /* Still above level for insertion, go down tree recursively */ if (n->level > level) { i = RTreePickBranch(r, n); if (!RTreeInsertRect2(r, tid, n->branch[i].child, &n2, level)) { /* child was not split */ n->branch[i].rect = RTreeCombineRect(r,&(n->branch[i].rect)); return 0; } else /* child was split */ { n->branch[i].rect = RTreeNodeCover(n->branch[i].child); b.child = n2; b.rect = RTreeNodeCover(n2); return RTreeAddBranch(&b, n, new_node); } } /* Have reached level for insertion. Add rect, split if necessary */ else if (n->level == level) { b.rect = *r; b.child = (struct Node *) (tid); /* child field of leaves contains tid of data record */ return RTreeAddBranch(&b, n, new_node); } else { /* Not supposed to happen */ assert (FALSE); return 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 recursion. */ int RTreeInsertRect(struct Rect *R, long Tid, struct Node **Root, int Level) { register struct Rect *r = R; register long tid = Tid; register struct Node **root = Root; register int level = Level; register int i; register struct Node *newroot; struct Node *newnode; struct Branch b; int result; assert(r && root); assert(level >= 0 && level <= (*root)->level); for (i=0; i<NUMDIMS; i++) { assert(r->boundary[i] <= r->boundary[NUMDIMS+i]); } if (RTreeInsertRect2(r, tid, *root, &newnode, level)) /* root split */ { newroot = RTreeNewNode(); /* grow a new root, & tree taller */ newroot->level = (*root)->level + 1; rootID = newroot->id; if(newroot->level > maxLevel) maxLevel = newroot->level; b.rect = RTreeNodeCover(*root); b.child = *root; RTreeAddBranch(&b, newroot, NULL); b.rect = RTreeNodeCover(newnode); b.child = newnode; RTreeAddBranch(&b, newroot, NULL); *root = newroot; result = 1; } else result = 0; return result; }
void RTreeInsert (rtree_t *t, rect_t r, void *data) { node_t n2; node_t new_root; branch_t b; assert(t && *t); if (RTreeInsertNode(*t, 0, r, data, &n2)) /* deal with root split */ { new_root = RTreeNewNode(); new_root->level = (*t)->level + 1; b.mbr = RTreeNodeCover(*t); b.child = (void *) *t; RTreeAddBranch(new_root, b, NULL); b.mbr = RTreeNodeCover(n2); b.child = (void *) n2; RTreeAddBranch(new_root, b, NULL); *t = new_root; } }
/* * Delete a rectangle from non-root part of an index structure. * Called by RTreeDeleteRect. Descends tree recursively, * merges branches on the way back up. * Returns 1 if record not found, 0 if success. */ static int RTreeDeleteRect2(struct Rect *R, long Tid, struct Node *N, struct ListNode **Ee) { register struct Rect *r = R; register long tid = Tid; register struct Node *n = N; register struct ListNode **ee = Ee; register int i; assert(r && n && ee); assert(tid >= 0); assert(n->level >= 0); if (n->level > 0) /* not a leaf node */ { for (i = 0; i < NODECARD; i++) { if (n->branch[i].child && RTreeOverlap(r, &(n->branch[i].rect))) { if (!RTreeDeleteRect2(r, tid, n->branch[i].child, ee)) { if (n->branch[i].child->count >= MinNodeFill) { n->branch[i].rect = RTreeNodeCover( n->branch[i].child); } else { /* not enough entries in child, eliminate child node */ RTreeReInsert(n->branch[i].child, ee); RTreeDisconnectBranch(n, i); } return 0; } } } return 1; } else /* a leaf node */ { for (i = 0; i < LEAFCARD; i++) { if (n->branch[i].child && (struct Node *)(n->branch[i].child) == (struct Node *) tid) { RTreeDisconnectBranch(n, i); return 0; } } return 1; } }
/* * Delete a rectangle from non-root part of an index structure. * Called by RTreeDeleteRect. Descends tree non-recursively, * merges branches on the way back up. * Returns 1 if record not found, 0 if success. */ static int RTreeDeleteRect2F(struct RTree_Rect *r, union RTree_Child child, struct RTree *t, struct RTree_ListNode **ee) { int i, notfound = 1, currlevel; struct RTree_Node *n; int top = 0, down = 0; int minfill; struct nstack *s = t->ns; struct RTree_Rect *nr = &(t->orect); /* add root node position to stack */ currlevel = t->rootlevel; s[top].pos = t->rootpos; s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); s[top].branch_id = 0; while (notfound && top >= 0) { /* go down to level 0, remember path */ if (s[top].sn->level > 0) { n = s[top].sn; currlevel = s[top].sn->level - 1; for (i = s[top].branch_id; i < t->nodecard; i++) { if (n->branch[i].child.pos > -1 && RTreeOverlap(r, &(n->branch[i].rect), t)) { s[top++].branch_id = i + 1; /* add next node to stack */ s[top].pos = n->branch[i].child.pos; s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); s[top].branch_id = 0; notfound = 0; break; } } if (notfound) { /* nothing else found, go back up */ s[top].branch_id = t->nodecard; top--; } else /* found a way down but not yet the item */ notfound = 1; } else { for (i = 0; i < t->leafcard; i++) { if (s[top].sn->branch[i].child.id && s[top].sn->branch[i].child.id == child.id) { /* found item */ RTreeDisconnectBranch(s[top].sn, i, t); RTreeNodeChanged(s[top].sn, s[top].pos, t); t->n_leafs--; notfound = 0; break; } } if (notfound) /* continue searching */ top--; } } if (notfound) { return notfound; } /* go back up */ while (top) { down = top; top--; i = s[top].branch_id - 1; minfill = (s[down].sn->level ? t->min_node_fill : t->min_leaf_fill); if (s[down].sn->count >= minfill) { /* just update node cover */ RTreeNodeCover(s[down].sn, nr, t); /* rewrite rect */ if (!RTreeCompareRect(nr, &(s[top].sn->branch[i].rect), t)) { RTreeCopyRect(&(s[top].sn->branch[i].rect), nr, t); RTreeNodeChanged(s[top].sn, s[top].pos, t); } } else { /* not enough entries in child, eliminate child node */ n = RTreeAllocNode(t, s[down].sn->level); /* copy node */ RTreeCopyNode(n, s[down].sn, t); RTreeAddNodePos(s[down].pos, s[down].sn->level, t); RTreeReInsertNode(n, ee); RTreeDisconnectBranch(s[top].sn, i, t); RTreeNodeChanged(s[top].sn, s[top].pos, t); } } return notfound; }
/* * 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; }
/* * Inserts a new data rectangle into the index structure. * Non-recursively descends tree, propagates splits back up. * Returns 0 if node was not split. Old node updated. * If node was split, returns 1 and sets the pointer pointed to by * new_node to point to the new node. Old node updated to become one of two. * 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. */ static int RTreeInsertRect2F(struct RTree_Rect *r, union RTree_Child child, int level, struct RTree_Node *newnode, off_t *newnode_pos, struct RTree *t, struct RTree_ListBranch **ee, char *overflow) { int i, currlevel; struct RTree_Node *n, *n2; struct RTree_Rect *cover; int top = 0, down = 0; int result; struct RTree_Branch *b = &(t->tmpb2); struct nstack *s = t->ns; struct RTree_Rect *nr = &(t->orect); n2 = newnode; /* add root node position to stack */ currlevel = t->rootlevel; s[top].pos = t->rootpos; s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); /* go down to level of insertion */ while (s[top].sn->level > level) { n = s[top].sn; currlevel = s[top].sn->level - 1; i = RTreePickBranch(r, n, t); s[top++].branch_id = i; /* add next node to stack */ s[top].pos = n->branch[i].child.pos; s[top].sn = RTreeGetNode(s[top].pos, currlevel, t); } /* Have reached level for insertion. Add rect, split if necessary */ RTreeCopyRect(&(b->rect), r, t); /* child field of leaves contains tid of data record */ b->child = child; /* add branch, may split node or remove branches */ cover = NULL; if (top) cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect); result = RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t); /* update node */ RTreeNodeChanged(s[top].sn, s[top].pos, t); /* write out new node if node was split */ if (result == 1) { *newnode_pos = RTreeGetNodePos(t); RTreeWriteNode(n2, t); t->n_nodes++; } /* go back up */ while (top) { down = top--; i = s[top].branch_id; if (result == 0) { /* branch was added */ if (RTreeExpandRect(&(s[top].sn->branch[i].rect), r, t)) { RTreeNodeChanged(s[top].sn, s[top].pos, t); } } else if (result == 2) { /* branches were removed */ /* get node cover of previous node */ RTreeNodeCover(s[down].sn, nr, t); /* rewrite rect */ if (!RTreeCompareRect(nr, &(s[top].sn->branch[i].rect), t)) { RTreeCopyRect(&(s[top].sn->branch[i].rect), nr, t); RTreeNodeChanged(s[top].sn, s[top].pos, t); } } else if (result == 1) { /* node was split */ /* get node cover of previous node */ RTreeNodeCover(s[down].sn, &(s[top].sn->branch[i].rect), t); /* add new branch for new node previously added by RTreeAddBranch() */ b->child.pos = *newnode_pos; RTreeNodeCover(n2, &(b->rect), t); /* add branch, may split node or remove branches */ cover = NULL; if (top) cover = &(s[top - 1].sn->branch[s[top - 1].branch_id].rect); result = RTreeAddBranch(b, s[top].sn, &n2, ee, cover, overflow, t); /* update node */ RTreeNodeChanged(s[top].sn, s[top].pos, t); /* write out new node if node was split */ if (result == 1) { *newnode_pos = RTreeGetNodePos(t); RTreeWriteNode(n2, t); t->n_nodes++; } } } return result; }