/// <summary>
/// Removes a rectangle from the Rtree
/// </summary>
/// <param name="r">the rectangle to delete</param>
/// <returns>true if rectangle deleted otherwise false</returns>
public bool Remove(Rectangle r)
{
// FindLeaf algorithm inlined here. Note the "official" algorithm searches all overlapping entries. This seems inefficient,
// as an entry is only worth searching if it contains (NOT overlaps) the rectangle we are searching for.
// FL1 [Search subtrees] If root is not a leaf, check each entry to determine if it contains r. For each entry found, invoke
// findLeaf on the node pointed to by the entry, until r is found or all entries have been checked.
parents.Clear();
parents.Push(rootNode);
parentsEntry.Clear();
parentsEntry.Push(-1);
NodeBase n = null;
int foundIndex = -1; // index of entry to be deleted in leaf
while (foundIndex == -1 && parents.Count > 0)
{
n = parents.Peek();
int startIndex = parentsEntry.Peek() + 1;
if (!n.IsLeaf)
{
NodeInternal internalNode = n as NodeInternal;
bool Contains = false;
for (int i = startIndex; i < n.entryCount; i++)
{
if (n.entries[i].Value.Contains(r))
{
parents.Push(internalNode.childNodes[i]);
parentsEntry.Pop();
parentsEntry.Push(i); // this becomes the start index when the child has been searched
parentsEntry.Push(-1);
Contains = true;
break; // ie go to next iteration of while()
}
}
if (Contains)
{
continue;
}
}
else
{
NodeLeaf leaf = n as NodeLeaf;
foundIndex = leaf.findEntry(ref r);
}
parents.Pop();
parentsEntry.Pop();
} // while not found
if (foundIndex != -1)
{
NodeLeaf leaf = n as NodeLeaf;
leaf.deleteEntry(foundIndex);
leaf.condenseTree(this);
size--;
}
// shrink the tree if possible (i.e. if root node has exactly one entry, and that entry is not a leaf node, delete the root (it's entry becomes the new root)
NodeBase root = rootNode;
while (root.entryCount == 1 && treeHeight > 1)
{
NodeInternal rootInternal = root as NodeInternal;
root.entryCount = 0;
rootNode = rootInternal.childNodes[0];
treeHeight--;
}
// if the tree is now empty, then set the MBR of the root node back to it's original state (this is only needed when the tree is empty,
// as this is the only state where an empty node is not eliminated)
if (size == 0)
{
rootNode.minimumBoundingRectangle = new Rectangle(true);
}
#if RtreeCheck
checkConsistency();
#endif
return(foundIndex != -1);
}