internal NodeLeaf splitNode(RTree rTree, Rectangle r)
{
// [Pick first entry for each group] Apply algorithm pickSeeds to
// choose two entries to be the first elements of the groups. Assign
// each to a group.
// debug code
/*double initialArea = 0;
if (log.isDebugEnabled())
{
double unionMinX = Math.Min(n.mbrMinX, newRectMinX);
double unionMinY = Math.Min(n.mbrMinY, newRectMinY);
double unionMaxX = Math.Max(n.mbrMaxX, newRectMaxX);
double unionMaxY = Math.Max(n.mbrMaxY, newRectMaxY);
initialArea = (unionMaxX - unionMinX) * (unionMaxY - unionMinY);
}*/
System.Array.Copy(rTree.initialEntryStatus, 0, rTree.entryStatus, 0, rTree.maxNodeEntries);
Update();
NodeLeaf newNode = null;
newNode = new NodeLeaf(level, rTree.maxNodeEntries);
pickSeeds(rTree, ref r, newNode); // this also sets the entryCount to 1
// [Check if done] If all entries have been assigned, stop. If one group has so few entries that all the rest must be assigned to it in
// order for it to have the minimum number m, assign them and stop.
while (entryCount + newNode.entryCount < rTree.maxNodeEntries + 1)
{
if (rTree.maxNodeEntries + 1 - newNode.entryCount == rTree.minNodeEntries)
{
// assign all remaining entries to original node
for (int i = 0; i < rTree.maxNodeEntries; i++)
{
if (rTree.entryStatus[i] == ((byte)RTree.EntryStatus.unassigned))
{
rTree.entryStatus[i] = ((byte)RTree.EntryStatus.assigned);
if (entries[i].Value.MinX < minimumBoundingRectangle.MinX)
minimumBoundingRectangle.MinX = entries[i].Value.MinX;
if (entries[i].Value.MinY < minimumBoundingRectangle.MinY)
minimumBoundingRectangle.MinY = entries[i].Value.MinY;
if (entries[i].Value.MaxX > minimumBoundingRectangle.MaxX)
minimumBoundingRectangle.MaxX = entries[i].Value.MaxX;
if (entries[i].Value.MaxY > minimumBoundingRectangle.MaxY)
minimumBoundingRectangle.MaxY = entries[i].Value.MaxY;
entryCount++;
}
}
break;
}
if (rTree.maxNodeEntries + 1 - entryCount == rTree.minNodeEntries)
{
// assign all remaining entries to new node
for (int i = 0; i < rTree.maxNodeEntries; i++)
{
if (rTree.entryStatus[i] == ((byte)RTree.EntryStatus.unassigned))
{
rTree.entryStatus[i] = ((byte)RTree.EntryStatus.assigned);
Rectangle entryR = entries[i].Value;
newNode.addEntry(ref entryR);
entries[i] = null;
}
}
break;
}
// [Select entry to assign] Invoke algorithm pickNext to choose the next entry to assign. Add it to the group whose covering rectangle
// will have to be enlarged least to accommodate it. Resolve ties by adding the entry to the group with smaller area, then to the
// the one with fewer entries, then to either. Repeat from S2
pickNext(rTree, newNode);
}
reorganize(rTree);
// check that the MBR stored for each node is correct.
#if RtreeCheck
if (!this.minimumBoundingRectangle.Equals(calculateMBR()))
{
throw new UnexpectedException("Error: splitNode old node MBR wrong");
}
if (!newNode.minimumBoundingRectangle.Equals(newNode.calculateMBR()))
{
throw new UnexpectedException("Error: splitNode new node MBR wrong");
}
#endif
#if RtreeCheck
double newArea = minimumBoundingRectangle.Area + newNode.minimumBoundingRectangle.Area;
double percentageIncrease = (100 * (newArea - initialArea)) / initialArea;
Console.WriteLine("Node " + this + " split. New area increased by " + percentageIncrease + "%");
#endif
return newNode;
}
}