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

splitNode() private method

private splitNode ( VelocityDb.Collection.Spatial.RTree rTree, Rectangle r ) : NodeLeaf
rTree VelocityDb.Collection.Spatial.RTree
r Rectangle
return NodeLeaf
    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;
    }
  }

Usage Example

コード例 #1
0
ファイル: RTree.cs プロジェクト: timotrob/VelocityDB
        /// <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);
            }
        }