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

adjustTree() private method

private adjustTree ( VelocityDb.Collection.Spatial.RTree rTree, NodeLeaf nn ) : NodeBase
rTree VelocityDb.Collection.Spatial.RTree
nn NodeLeaf
return NodeBase
    internal NodeBase adjustTree(RTree rTree, NodeLeaf nn)
    {
      // AT1 [Initialize] Set N=L. If L was split previously, set NN to be the resulting second node.

      // AT2 [Check if done] If N is the root, stop
      while (level != rTree.treeHeight)
      {
        // AT3 [Adjust covering rectangle in parent entry] Let P be the parent node of N, and let En be N's entry in P. Adjust EnI so that it tightly encloses all entry rectangles in N.
        NodeInternal parent = rTree.parents.Pop() as NodeInternal;
        int entry = rTree.parentsEntry.Pop();

        if (parent.childNodes[entry] != this)
          throw new UnexpectedException("Error: entry " + entry + " in node " + parent + " should point to node " + this + "; actually points to node " + parent.childNodes[entry]);
        if (parent.entries[entry].Value.MinX != minimumBoundingRectangle.MinX || parent.entries[entry].Value.MinY != minimumBoundingRectangle.MinY ||
            parent.entries[entry].Value.MaxX != minimumBoundingRectangle.MaxX || parent.entries[entry].Value.MaxY != minimumBoundingRectangle.MaxY)
        {
          parent.entries[entry] = minimumBoundingRectangle;
          parent.recalculateMBR();
        }

        // AT4 [Propagate node split upward] If N has a partner NN resulting from an earlier split, create a new entry Enn with Ennp pointing to NN and 
        // Enni enclosing all rectangles in NN. Add Enn to P if there is room. Otherwise, invoke splitNode to produce P and PP containing Enn and all P's old entries.
        NodeInternal newNode = null;
        if (nn != null)
        {
          if (parent.entryCount < rTree.maxNodeEntries)
            parent.addEntry(ref nn.minimumBoundingRectangle, nn);
          else
            newNode = parent.splitNode(rTree, ref nn.minimumBoundingRectangle, nn);
        }
        // AT5 [Move up to next level] Set N = P and set NN = PP if a split occurred. Repeat from AT2
        return parent.adjustTree(rTree, newNode);
      }
      return nn;
    }

Usage Example

Esempio n. 1
0
        /// <summary>
        /// Adds a new entry at a specified level in the tree
        /// </summary>
        /// <param name="r">the rectangle added</param>
        internal void AddInternal(Rectangle r)
        {
            // I1 [Find position for new record] Invoke ChooseLeaf to select a leaf node L in which to place r
            NodeLeaf n       = (NodeLeaf)chooseNode(r, 1);
            NodeLeaf newLeaf = null;

            // I2 [Add record to leaf node] If L has room for another entry, install E. Otherwise invoke SplitNode to obtain L and LL containing E and all the old entries of L
            if (n.entryCount < maxNodeEntries)
            {
                n.addEntry(ref r);
            }
            else
            {
                newLeaf = n.splitNode(this, r);
            }

            // I3 [Propagate changes upwards] Invoke AdjustTree on L, also passing LL if a split was performed
            NodeBase newNode = n.adjustTree(this, newLeaf);

            // I4 [Grow tree taller] If node split propagation caused the root to split, create a new root whose children are the two resulting nodes.
            if (newNode != null)
            {
                NodeBase     oldRoot = rootNode;
                NodeInternal root    = new NodeInternal(++treeHeight, maxNodeEntries);
                rootNode = root;
                root.addEntry(ref newNode.minimumBoundingRectangle, newNode);
                root.addEntry(ref oldRoot.minimumBoundingRectangle, oldRoot);
            }
        }