コード例 #1
0
        /// <summary>
        /// Reinserts or splits an overflown node.
        /// </summary>
        /// <param name="overflownNode">The overflown node.</param>
        /// <param name="canReinsert">Indicates whether the elements of the node can reinserted.</param>
        /// <param name="height">The height of the overflown node.</param>
        /// <returns></returns>
        private Boolean OverflowTreatment(RTreeNode overflownNode, Boolean canReinsert, Int32 height)
        {
            if (canReinsert) // reinsert
            {
                ReInsert(overflownNode, height);
                return(false);
            }
            else // split
            {
                RTreeNode first, second;
                SplitNode(overflownNode, out first, out second);

                if (overflownNode.Parent != null)
                {
                    overflownNode.Parent.RemoveChild(overflownNode);
                    overflownNode.Parent.AddChild(first);
                    overflownNode.Parent.AddChild(second);
                }
                else // case when the root is split
                {
                    _root = new RTreeNode(overflownNode.MaxChildren);
                    _root.AddChild(first);
                    _root.AddChild(second);
                    _height++;
                    return(false);
                }

                return(true);
            }
        }
コード例 #2
0
ファイル: RTree.cs プロジェクト: AegisSpatial/aegis-origin
        /// <summary>
        /// Splits a node into two nodes.
        /// </summary>
        /// <param name="overflownNode">The overflown node.</param>
        /// <param name="firstNode">The first produced node.</param>
        /// <param name="secondNode">The second produced node.</param>
        protected virtual void SplitNode(RTreeNode overflownNode, out RTreeNode firstNode, out RTreeNode secondNode)
        {
            RTreeNode firstSeed, secondSeed;

            PickSeeds(overflownNode.Children, out firstSeed, out secondSeed);

            firstNode  = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren);
            secondNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren);

            firstNode.AddChild(firstSeed);
            secondNode.AddChild(secondSeed);

            overflownNode.Children.Remove(firstSeed);
            overflownNode.Children.Remove(secondSeed);

            while (overflownNode.ChildrenCount > 0)
            {
                RTreeNode node = PickNext(overflownNode.Children);

                if (firstNode.ChildrenCount + overflownNode.ChildrenCount <= MinChildren)
                {
                    firstNode.AddChild(node);
                }
                else if (secondNode.ChildrenCount + overflownNode.ChildrenCount <= MinChildren)
                {
                    secondNode.AddChild(node);
                }
                else
                {
                    Double firstEnlargement  = firstNode.ComputeEnlargement(node.Envelope);
                    Double secondEnlargement = secondNode.ComputeEnlargement(node.Envelope);

                    if (firstEnlargement < secondEnlargement)
                    {
                        firstNode.AddChild(node);
                    }
                    else if (firstEnlargement > secondEnlargement)
                    {
                        secondNode.AddChild(node);
                    }
                    else
                    {
                        if (firstNode.Envelope.Surface < secondNode.Envelope.Surface)
                        {
                            firstNode.AddChild(node);
                        }
                        else
                        {
                            secondNode.AddChild(node);
                        }
                    }
                }
            }
        }
コード例 #3
0
ファイル: RTree.cs プロジェクト: AegisSpatial/aegis-origin
        /// <summary>
        /// Adjusts the tree after insertion, and corrects the bounding envelope of the nodes.
        /// </summary>
        /// <param name="node">The node where the adjustment starts.</param>
        /// <param name="splitted">The second part of the node if the original node was split.</param>
        /// <param name="nodeToRemove">The original node which should be removed if the original node was split.</param>
        protected void AdjustTree(RTreeNode node, RTreeNode splitted = null, RTreeNode nodeToRemove = null)
        {
            RTreeNode n  = node;
            RTreeNode nn = splitted;

            while (n.Parent != null)
            {
                RTreeNode parent = n.Parent;

                parent.CorrectBounding(n.Envelope);

                if (nn == null)
                {
                    n = parent;
                }
                else
                {
                    if (nodeToRemove != null)
                    {
                        parent.RemoveChild(nodeToRemove);
                        parent.AddChild(n);
                    }

                    if (!parent.IsFull)
                    {
                        parent.AddChild(nn);
                        n  = parent;
                        nn = null;
                    }
                    else
                    {
                        parent.AddChild(nn);
                        SplitNode(parent, out n, out nn);

                        nodeToRemove = parent;
                    }
                }
            }

            // create new root node if the root is split
            if (nn != null)
            {
                _root = new RTreeNode(n.MaxChildren);
                _root.AddChild(n);
                _root.AddChild(nn);

                _height++;
            }
        }
コード例 #4
0
ファイル: RTree.cs プロジェクト: AegisSpatial/aegis-origin
        /// <summary>
        /// Adds a node into the tree on a specified height.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="height">The height where the node should be inserted.</param>
        protected virtual void AddNode(RTreeNode node, Int32 height = -1)
        {
            RTreeNode nodeToInsert = ChooseNodeToAdd(node.Envelope, height);

            if (!nodeToInsert.IsFull)
            {
                if (nodeToInsert == _root && nodeToInsert.ChildrenCount == 0)
                {
                    _height = 1;
                }

                nodeToInsert.AddChild(node);
                AdjustTree(nodeToInsert);
            }
            else
            {
                nodeToInsert.AddChild(node);

                RTreeNode firstNode, secondNode;
                SplitNode(nodeToInsert, out firstNode, out secondNode);
                AdjustTree(firstNode, secondNode, nodeToInsert);
            }
        }
コード例 #5
0
        /// <summary>
        /// Splits a node into two nodes.
        /// </summary>
        /// <param name="overflownNode">The overflown node.</param>
        /// <param name="firstNode">The first produced node.</param>
        /// <param name="secondNode">The second produced node.</param>
        protected override void SplitNode(RTreeNode overflownNode, out RTreeNode firstNode, out RTreeNode secondNode)
        {
            List <RTreeNode> alongChosenAxis = ChooseSplitAxis(overflownNode);

            Int32  minIndex   = MinChildren;
            Double minOverlap = ComputeOverlap(Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, MinChildren).Select(x => x.Envelope)),
                                               Envelope.FromEnvelopes(alongChosenAxis.GetRange(MinChildren, alongChosenAxis.Count - MinChildren).Select(x => x.Envelope)));

            // ChooseSplitIndex

            for (Int32 i = MinChildren + 1; i <= MaxChildren - MinChildren + 1; i++)
            {
                Double actOverlap = ComputeOverlap(Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, i).Select(x => x.Envelope)),
                                                   Envelope.FromEnvelopes(alongChosenAxis.GetRange(i, alongChosenAxis.Count - i).Select(x => x.Envelope)));
                if (minOverlap > actOverlap)
                {
                    minOverlap = actOverlap;
                    minIndex   = i;
                }
                else if (minOverlap == actOverlap)
                {
                    Double minArea = Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, minIndex).Select(x => x.Envelope)).Surface +
                                     Envelope.FromEnvelopes(alongChosenAxis.GetRange(minIndex, alongChosenAxis.Count - minIndex).Select(x => x.Envelope)).Surface;

                    Double actArea = Envelope.FromEnvelopes(alongChosenAxis.GetRange(0, i).Select(x => x.Envelope)).Surface +
                                     Envelope.FromEnvelopes(alongChosenAxis.GetRange(i, alongChosenAxis.Count - i).Select(x => x.Envelope)).Surface;

                    if (minArea > actArea)
                    {
                        minIndex = i;
                    }
                }
            }

            firstNode  = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren);
            secondNode = (overflownNode.Parent != null) ? new RTreeNode(overflownNode.Parent) : new RTreeNode(overflownNode.MaxChildren);

            foreach (RTreeNode node in alongChosenAxis.GetRange(0, minIndex))
            {
                firstNode.AddChild(node);
            }

            foreach (RTreeNode node in alongChosenAxis.GetRange(minIndex, alongChosenAxis.Count - minIndex))
            {
                secondNode.AddChild(node);
            }
        }
コード例 #6
0
        /// <summary>
        /// Inserts a node into the tree on a specified height.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <param name="height">The height where the node should be inserted.</param>
        /// <param name="startHeight">If the tree was grown during the reinsert, then the original height of the tree.</param>
        private void InsertInSpecifiedHeight(RTreeNode node, Int32 height, Int32 startHeight)
        {
            RTreeNode nodeToInsert = ChooseNodeToAdd(node.Envelope, height);

            if (nodeToInsert == _root && nodeToInsert.ChildrenCount == 0)
            {
                _height = 1;
            }

            if (height == -1)
            {
                height      = Height - 1;
                startHeight = height;
            }

            nodeToInsert.AddChild(node);

            if (nodeToInsert.IsOverflown)
            {
                Boolean canReInsert;
                Boolean splitted;

                do
                {
                    canReInsert = startHeight > 0 && !_visitedLevels[startHeight];
                    _visitedLevels[startHeight] = true;

                    splitted = OverflowTreatment(nodeToInsert, canReInsert, height) &&
                               nodeToInsert.Parent.IsOverflown;

                    nodeToInsert = nodeToInsert.Parent;
                    height--;
                } while (splitted);
            }

            if (nodeToInsert != null)
            {
                AdjustTree(nodeToInsert);
            }
        }