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); }
/*----------------------------------------------------------------------------- | Method #0 for choosing a partition: | As the seeds for the two groups, pick the two rects that would waste the | most area if covered by a single rectangle, i.e. evidently the worst pair | to have in the same group. | Of the remaining, one at a time is chosen to be put in one of the two groups. | The one chosen is the one with the greatest difference in area expansion | depending on which group - the rect most strongly attracted to one group | and repelled from the other. | If one group gets too full (more would force other group to violate min | fill requirement) then other group gets the rest. | These last are the ones that can go in either group most easily. -----------------------------------------------------------------------------*/ static void RTreeMethodZero(struct PartitionVars *p, int minfill) { register int i; RectReal biggestDiff; int group, chosen=0, betterGroup=0; assert(p); RTreeInitPVars(p, BranchCount, minfill); RTreePickSeeds(p); while (p->count[0] + p->count[1] < p->total && p->count[0] < p->total - p->minfill && p->count[1] < p->total - p->minfill) { biggestDiff = (RectReal)-1.; for (i=0; i<p->total; i++) { if (!p->taken[i]) { struct Rect *r, rect_0, rect_1; RectReal growth0, growth1, diff; r = &BranchBuf[i].rect; rect_0 = RTreeCombineRect(r, &p->cover[0]); rect_1 = RTreeCombineRect(r, &p->cover[1]); growth0 = RTreeRectSphericalVolume( &rect_0)-p->area[0]; growth1 = RTreeRectSphericalVolume( &rect_1)-p->area[1]; diff = growth1 - growth0; if (diff >= 0) group = 0; else { group = 1; diff = -diff; } if (diff > biggestDiff) { biggestDiff = diff; chosen = i; betterGroup = group; } else if (diff==biggestDiff && p->count[group]<p->count[betterGroup]) { chosen = i; betterGroup = group; } } } RTreeClassify(chosen, betterGroup, p); } /* if one group too full, put remaining rects in the other */ if (p->count[0] + p->count[1] < p->total) { if (p->count[0] >= p->total - p->minfill) group = 1; else group = 0; for (i=0; i<p->total; i++) { if (!p->taken[i]) RTreeClassify(i, group, p); } } assert(p->count[0] + p->count[1] == p->total); assert(p->count[0] >= p->minfill && p->count[1] >= p->minfill); }