VelocityDb.Collection.Spatial.NodeLeaf.condenseTree C# (CSharp) Method

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
    internal void condenseTree(RTree rTree)
    {
      // CT1 [Initialize] Set n=l. Set the list of eliminated nodes to be empty.
      NodeBase n = this;
      NodeInternal parent = null;
      int parentEntry = 0;
      Stack<NodeBase> eliminatedNodes = new Stack<NodeBase>();

      // CT2 [Find parent entry] If N is the root, go to CT6. Otherwise 
      // let P be the parent of N, and let En be N's entry in P  
      while (n.level != rTree.treeHeight)
      {
        parent = rTree.parents.Pop() as NodeInternal;
        parentEntry = rTree.parentsEntry.Pop();

        // CT3 [Eliminiate under-full node] If N has too few entries,
        // delete En from P and add N to the list of eliminated nodes
        if (n.entryCount < rTree.minNodeEntries)
        {
          parent.deleteEntry(parentEntry);
          eliminatedNodes.Push(n);
        }
        else
        {
          // CT4 [Adjust covering rectangle] If N has not been eliminated,
          // adjust EnI to tightly contain all entries in N
          if (n.minimumBoundingRectangle.MinX != parent.entries[parentEntry].Value.MinX || n.minimumBoundingRectangle.MinY != parent.entries[parentEntry].Value.MinY ||
              n.minimumBoundingRectangle.MaxX != parent.entries[parentEntry].Value.MaxX || n.minimumBoundingRectangle.MaxY != parent.entries[parentEntry].Value.MaxY)
          {
            Rectangle d = parent.entries[parentEntry].Value;
            parent.entries[parentEntry] = n.minimumBoundingRectangle;
            parent.recalculateMBRIfInfluencedBy(ref d);
          }
        }
        // CT5 [Move up one level in tree] Set N=P and repeat from CT2
        n = parent;
      }

      // CT6 [Reinsert orphaned entries] Reinsert all entries of nodes in set Q. Entries from eliminated leaf nodes are reinserted in tree leaves as in 
      // Insert(), but entries from higher level nodes must be placed higher in the tree, so that leaves of their dependent subtrees will be on the same
      // level as leaves of the main tree
      while (eliminatedNodes.Count > 0)
      {
        NodeBase e = eliminatedNodes.Pop();
        for (int j = 0; j < e.entryCount; j++)
        {
            if (e.level == 1)
              rTree.AddInternal(e.entries[j].Value);
            else
            {
              NodeInternal nInternal = e as NodeInternal;
              rTree.AddInternal(e.entries[j].Value, e.level, nInternal.childNodes[j]);
            }
        }
      }
    }

Usage Example

Esempio 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);
        }