condenseTree() private method

Used by delete(). Ensures that all nodes from the passed node up to the root have the minimum number of entries. Note that the parent and parentEntry stacks are expected to contain the nodeIds of all parents up to the root.
private condenseTree ( VelocityDb.Collection.Spatial.RTree rTree ) : void
rTree VelocityDb.Collection.Spatial.RTree
return void
Exemplo n.º 1
0
        /// <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);
        }