// 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 Xastir_RTreeInsertRect2(struct Rect *r, void *tid, struct Node *n, struct Node **new_node, int level) { /* register struct Rect *r = R; register int 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 = Xastir_RTreePickBranch(r, n); if (!Xastir_RTreeInsertRect2(r, tid, n->branch[i].child, &n2, level)) { // child was not split // n->branch[i].rect = Xastir_RTreeCombineRect(r,&(n->branch[i].rect)); return 0; } else // child was split { n->branch[i].rect = Xastir_RTreeNodeCover(n->branch[i].child); b.child = n2; b.rect = Xastir_RTreeNodeCover(n2); return Xastir_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 Xastir_RTreeAddBranch(&b, n, new_node); } else { /* Not supposed to happen */ assert (FALSE); return 0; } }
// Find the smallest rectangle that includes all rectangles in // branches of a node. // struct Rect Xastir_RTreeNodeCover(struct Node *N) { register struct Node *n = N; register int i, first_time=1; struct Rect r; assert(n); Xastir_RTreeInitRect(&r); for (i = 0; i < MAXKIDS(n); i++) if (n->branch[i].child) { if (first_time) { r = n->branch[i].rect; first_time = 0; } else r = Xastir_RTreeCombineRect(&r, &(n->branch[i].rect)); } return r; }
// Pick a branch. Pick the one that will need the smallest increase // in area to accomodate the new rectangle. This will result in the // least total area for the covering rectangles in the current node. // In case of a tie, pick the one which was smaller before, to get // the best resolution when searching. // int Xastir_RTreePickBranch(struct Rect *R, struct Node *N) { register struct Rect *r = R; register struct Node *n = N; register struct Rect *rr; register int i, first_time=1; // Although it is impossible for bestArea and best to be used // unininitialized the way the code is structured, gcc complains // about possible uninitialized usage. Let's keep it happy. // Original superliminal.com had no initializers here. RectReal increase, bestIncr=(RectReal)-1, area, bestArea=0.0; int best=0; struct Rect tmp_rect; assert(r && n); for (i=0; i<MAXKIDS(n); i++) { if (n->branch[i].child) { rr = &n->branch[i].rect; area = Xastir_RTreeRectSphericalVolume(rr); tmp_rect = Xastir_RTreeCombineRect(r, rr); increase = Xastir_RTreeRectSphericalVolume(&tmp_rect) - area; if (increase < bestIncr || first_time) { best = i; bestArea = area; bestIncr = increase; first_time = 0; } else if (increase == bestIncr && area < bestArea) { best = i; bestArea = area; bestIncr = increase; } } } return best; }