/* Make a new index, empty. Consists of a single node. */ struct Node * RTreeNewIndex(void) { struct Node *x; nodeCount = 0; maxLevel = 0; rootID = 0; /* The tree traversal logic fails if there is */ /* "pointer" to node 0. For real memory this */ /* cannot happen but for our memory mapped files */ /* it can and does. To avoid this, we will */ /* allocate a dummy node which will never be */ /* used as part of the tree. A bit of a kludge */ /* but better than mucking around with index */ /* offsets all over the place. */ x = RTreeNewNode(); /* This is the real "first" node */ x = RTreeNewNode(); x->level = 0; /* leaf */ return x; }
rtree_t RTreeNew (void) { rtree_t t; t = RTreeNewNode(); t->level = 0; /*leaf*/ return t; }
static void RTreeSplitNode (node_t n, branch_t b, node_t *new_node) { partition_t p; int level; int i; assert(n); assert(new_node); p = PartitionNew(); for (i = 0; i < MAXCARD; i ++) PartitionPush(p,n->branch[i]); PartitionPush(p,b); level = n->level; RTreeNodeInit(n); n->level = level; *new_node = RTreeNewNode(); (*new_node)->level = level; RTreePickSeeds(p, n, *new_node); while (p->n) if (n->count + p->n <= MINCARD) /* first group (n) needs all entries */ RTreeNodeAddBranch(&(p->cover[0]), n, PartitionPop(p)); else if ((*new_node)->count + p->n <= MINCARD) /* second group (new_node) needs all entries */ RTreeNodeAddBranch(&(p->cover[1]), *new_node, PartitionPop(p)); else RTreePickNext(p, n, *new_node); }
/*----------------------------------------------------------------------------- | Split a node. | Divides the nodes branches and the extra one between two nodes. | Old node is one of the new ones, and one really new one is created. | Tries more than one method for choosing a partition, uses best result. -----------------------------------------------------------------------------*/ extern void RTreeSplitNode(struct Node *n, struct Branch *b, struct Node **nn) { register struct PartitionVars *p; register int level; assert(n); assert(b); /* load all the branches into a buffer, initialize old node */ level = n->level; RTreeGetBranches(n, b); /* find partition */ p = &Partitions[0]; /* Note: can't use MINFILL(n) below since n was cleared by GetBranches() */ RTreeMethodZero(p, level>0 ? MinNodeFill : MinLeafFill); /* * put branches from buffer into 2 nodes * according to chosen partition */ *nn = RTreeNewNode(); (*nn)->level = n->level = level; RTreeLoadNodes(n, *nn, p); assert(n->count+(*nn)->count == p->total); }
/* Make a new index, empty. Consists of a single node. */ Node_t *RTreeNewIndex(RTree_t * rtp) { Node_t *x; x = RTreeNewNode(rtp); x->level = 0; /* leaf */ rtp->LeafCount++; return x; }
int RTreeInsert(RTree_t * rtp, Rect_t * r, void *data, Node_t ** n, int level) { /* RTreeInsert(RTree_t*rtp, Rect_t*r, int data, Node_t**n, int level) { */ register int i; register Node_t *newroot; Node_t *newnode=0; Branch_t b; int result = 0; assert(r && n); assert(level >= 0 && level <= (*n)->level); for (i = 0; i < NUMDIMS; i++) assert(r->boundary[i] <= r->boundary[NUMDIMS + i]); # ifdef RTDEBUG fprintf(stderr, "RTreeInsert level=%d\n", level); # endif if (rtp->StatFlag) { if (rtp->Deleting) rtp->ReInsertCount++; else rtp->InsertCount++; } if (!rtp->Deleting) rtp->RectCount++; if (RTreeInsert2(rtp, r, data, *n, &newnode, level)) { /* root was split */ if (rtp->StatFlag) { if (rtp->Deleting) rtp->DeTouchCount++; else rtp->InTouchCount++; } newroot = RTreeNewNode(rtp); /* grow a new root, make tree taller */ rtp->NonLeafCount++; newroot->level = (*n)->level + 1; b.rect = NodeCover(*n); b.child = *n; AddBranch(rtp, &b, newroot, NULL); b.rect = NodeCover(newnode); b.child = newnode; AddBranch(rtp, &b, newroot, NULL); *n = newroot; // rtp->root = newroot; rtp->EntryCount += 2; result = 1; } return result; }
/* * 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 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; } }