Exemple #1
0
        /// <summary>
        /// Performs the insertion algorithm.
        /// </summary>
        /// <param name="item">Item to insert</param>
        public void Insert(LeafRecord <T> item)
        {
            List <NodeRecord <T> > leafPath = new List <NodeRecord <T> >();

            // I1.
            // Track the nodes traversed to get to the point that we
            // want to add the node. This list of nodes will be used
            // to propagate changes up the tree.
            NodeRecord <T> insertNode = chooseLeaf(item, leafPath);
            NodeRecord <T> splitNode  = null;

            // I2.
            // Attempts to insert the item in the given node.
            // If it fails, we split the node. Store the new
            // node in splitNode, so it can be propagated up
            // later.
            if (!insertNode.TryInsert(item))
            {
                // Split.
                splitNode = insertNode.Split(item);
            }

            // I3.
            // Propagate resizing up the tree. Propagate split node
            // if necessary.
            if (adjustTree(leafPath, insertNode, ref splitNode))
            {
                // I4.
                // Create a new root if the root was split. This new root is not a leaf.
                NodeRecord <T> newRoot = new NodeRecord <T>()
                {
                    Node = new RTreeNode <T>(Leaf: false)
                };
                newRoot.TryInsert(root);
                newRoot.TryInsert(splitNode);
                root = newRoot;
            }
        }
Exemple #2
0
        /// <summary>
        /// Propagates resizing of the nodes upwards. Additionally, performs
        /// any splitting of nodes along the way if a node needed to split.
        /// Returns whether the root node was split.
        /// </summary>
        /// <param name="adjustPath">Path along which the nodes need be adjusted</param>
        /// <param name="node">Node above which needs to be adjusted</param>
        /// <param name="splitNode">Node that needs to be inserted.</param>
        /// <returns>True if the root node was split</returns>
        private bool adjustTree(List <NodeRecord <T> > adjustPath,
                                NodeRecord <T> node, ref NodeRecord <T> splitNode)
        {
            // AT1.
            NodeRecord <T> N  = node;
            NodeRecord <T> NN = splitNode;

            while (true)
            {
                // AT2.
                if (N == root)
                {
                    return(NN != null);
                }

                // AT3.
                N.ResizeBBox();

                // AT4.
                // Try to add the extra node to this parent node.
                // If the parent has no more room, split the parent,
                // and propagate the split node upwards to continue
                // looking for an insertion point.
                int            level = adjustPath.IndexOf(N);
                NodeRecord <T> P     = adjustPath[level - 1];

                if (NN != null)
                {
                    if (!P.TryInsert(NN))
                    {
                        NodeRecord <T> PP = P.Split(NN);
                        NN = PP;
                    }
                    else
                    {
                        NN = null;
                    }
                }

                N = P;
            }
        }
Exemple #3
0
        /// <summary>
        /// Utilizes the Quadradic split algorithm to determine where each
        /// of the records go - either to group one or group two.
        /// </summary>
        /// <param name="newItem"></param>
        /// <returns></returns>
        public NodeRecord <T> SplitQuadradic(IndexRecord <T> newItem)
        {
            List <IndexRecord <T> > itemsToBeAssigned = records;

            itemsToBeAssigned.Add(newItem);

            IndexRecord <T> A, B;

            // QS1.
            pickSeeds(itemsToBeAssigned, out A, out B);
            itemsToBeAssigned.Remove(A);
            itemsToBeAssigned.Remove(B);

            NodeRecord <T> groupOne = new NodeRecord <T>()
            {
                BBox = A.BBox, Node = new RTreeNode <T>(isLeaf)
            };
            NodeRecord <T> groupTwo = new NodeRecord <T>()
            {
                BBox = B.BBox, Node = new RTreeNode <T>(isLeaf)
            };

            groupOne.Node.TryInsert(A);
            groupTwo.Node.TryInsert(B);

            // QS2.
            while (itemsToBeAssigned.Count > 0)
            {
                // QS3.
                int d1, d2;
                var next = pickNext(itemsToBeAssigned, groupOne, groupTwo, out d1, out d2);
                if (d1 < d2)
                {
                    groupOne.TryInsert(next);
                }
                else if (d2 < d1)
                {
                    groupTwo.TryInsert(next);
                }
                else
                {
                    // Insert to whichever is smaller.
                    if (groupOne.Node.GetRecordCount() < groupTwo.Node.GetRecordCount())
                    {
                        groupOne.TryInsert(next);
                    }
                    else
                    {
                        groupTwo.TryInsert(next);
                    }
                }

                itemsToBeAssigned.Remove(next);

                // QS2.
                if (groupOne.Node.GetRecordCount() + itemsToBeAssigned.Count <= m)
                {
                    while (itemsToBeAssigned.Count > 0)
                    {
                        groupOne.TryInsert(itemsToBeAssigned.First());
                        itemsToBeAssigned.Remove(itemsToBeAssigned.First());
                    }
                }

                // QS2.
                if (groupTwo.Node.GetRecordCount() + itemsToBeAssigned.Count <= m)
                {
                    while (itemsToBeAssigned.Count > 0)
                    {
                        groupTwo.TryInsert(itemsToBeAssigned.First());
                        itemsToBeAssigned.Remove(itemsToBeAssigned.First());
                    }
                }
            }

            // Set this equal to group two.
            records = groupTwo.Node.records;
            return(groupOne);
        }