예제 #1
0
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);
}
예제 #2
0
/*-----------------------------------------------------------------------------
| 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);
}