Exemple #1
0
        void RemoveLeaf(IntervalNode <TData> leaf)
        {
            Debug.Assert(leaf.IsLeaf);

            var unbalancedNode = FindTopUnbalancedNode(leaf);

            if (unbalancedNode != null)
            {
                RebuildUnderNodeWithoutLeaf(unbalancedNode, leaf);
                UpdateParent(unbalancedNode);
            }
            else
            {
                //replace the parent with the sibling and update bounding boxes and counts
                var parent = leaf.Parent;
                if (parent == null)
                {
                    Debug.Assert(rootNode == leaf);
                    rootNode = new IntervalNode <TData>();
                }
                else
                {
                    TransferFromSibling(parent, leaf.IsLeftChild ? parent.Right : parent.Left);
                    UpdateParent(parent);
                }
            }
            Debug.Assert(TreeIsCorrect(RootNode));
        }
Exemple #2
0
        /// <summary>
        /// returns all leaf nodes for which the interval was hit and the delegate is happy with the object
        /// </summary>
        /// <param name="intervalPar"></param>
        /// <param name="hitTestAccept"></param>
        /// <returns></returns>
        public IEnumerable <TData> AllHitItems(Interval intervalPar, Func <TData, bool> hitTestAccept)
        {
            var stack = new Stack <IntervalNode <TData> >();

            stack.Push(this);
            while (stack.Count > 0)
            {
                IntervalNode <TData> node = stack.Pop();
                if (node.Interval.Intersects(intervalPar))
                {
                    if (node.IsLeaf)
                    {
                        if ((null == hitTestAccept) || hitTestAccept(node.UserData))
                        {
                            yield return(node.UserData);
                        }
                    }
                    else
                    {
                        stack.Push(node.left);
                        stack.Push(node.right);
                    }
                }
            }
        }
 internal static void CrossIntervalNodes <TA, TB>(IntervalNode <TA> a, IntervalNode <TB> b, Action <TA, TB> action)
 {
     if (!a.interval.Intersects(b.interval))
     {
         return;
     }
     if (a.Left == null)     //a is a leat
     {
         if (b.Left == null) //b is a leaf
         {
             action(a.UserData, b.UserData);
         }
         else
         {
             CrossIntervalNodes(a, b.Left, action);
             CrossIntervalNodes(a, b.Right, action);
         }
     }
     else     //a is not a leaf
     {
         if (b.Left != null)
         {
             CrossIntervalNodes(a.Left, b.Left, action);
             CrossIntervalNodes(a.Left, b.Right, action);
             CrossIntervalNodes(a.Right, b.Left, action);
             CrossIntervalNodes(a.Right, b.Right, action);
         }
         else     // b is a leaf
         {
             CrossIntervalNodes(a.Left, b, action);
             CrossIntervalNodes(a.Right, b, action);
         }
     }
 }
Exemple #4
0
 static void AddNodeToTreeRecursive(IntervalNode <TData> newNode, IntervalNode <TData> existingNode)
 {
     if (existingNode.IsLeaf)
     {
         existingNode.Left     = new IntervalNode <TData>(existingNode.UserData, existingNode.Interval);
         existingNode.Right    = newNode;
         existingNode.Count    = 2;
         existingNode.UserData = default(TData);
     }
     else
     {
         existingNode.Count++;
         Interval leftBox;
         Interval rightBox;
         if (2 * existingNode.Left.Count < existingNode.Right.Count)
         {
             //keep the balance
             AddNodeToTreeRecursive(newNode, existingNode.Left);
             existingNode.Left.Interval = new Interval(existingNode.Left.Interval, newNode.Interval);
         }
         else if (2 * existingNode.Right.Count < existingNode.Left.Count)
         {
             //keep the balance
             AddNodeToTreeRecursive(newNode, existingNode.Right);
             existingNode.Right.Interval = new Interval(existingNode.Right.Interval, newNode.Interval);
         }
         else     //decide basing on the boxes
         {
             leftBox = new Interval(existingNode.Left.Interval, newNode.Interval);
             var delLeft = leftBox.Length - existingNode.Left.Interval.Length;
             rightBox = new Interval(existingNode.Right.Interval, newNode.Interval);
             var delRight = rightBox.Length - existingNode.Right.Interval.Length;
             if (delLeft < delRight)
             {
                 AddNodeToTreeRecursive(newNode, existingNode.Left);
                 existingNode.Left.Interval = leftBox;
             }
             else if (delLeft > delRight)
             {
                 AddNodeToTreeRecursive(newNode, existingNode.Right);
                 existingNode.Right.Interval = rightBox;
             }
             else     //the deltas are the same; add to the smallest
             {
                 if (leftBox.Length < rightBox.Length)
                 {
                     AddNodeToTreeRecursive(newNode, existingNode.Left);
                     existingNode.Left.Interval = leftBox;
                 }
                 else
                 {
                     AddNodeToTreeRecursive(newNode, existingNode.Right);
                     existingNode.Right.Interval = rightBox;
                 }
             }
         }
     }
     existingNode.Interval = new Interval(existingNode.Left.Interval, existingNode.Right.Interval);
 }
Exemple #5
0
 static void TransferFromSibling(IntervalNode <TData> parent, IntervalNode <TData> sibling)
 {
     parent.UserData = sibling.UserData;
     parent.Left     = sibling.Left;
     parent.Right    = sibling.Right;
     parent.Count--;
     parent.Interval = sibling.Interval;
 }
Exemple #6
0
 static void UpdateParent(IntervalNode <TData> parent)
 {
     for (var node = parent.Parent; node != null; node = node.Parent)
     {
         node.Count--;
         node.Interval = new Interval(node.Left.Interval, node.Right.Interval);
     }
 }
 static bool HandleEqualityCheck <TA>(IntervalNode <TA> a, Func <TA, TA, bool> func)
 {
     if (a.Left == null)
     {
         return(false);                //we don't do anything for two equal leafs
     }
     return(FindIntersectionWithProperty(a.Left, a.Left, func) ||
            FindIntersectionWithProperty(a.Left, a.Right, func) || FindIntersectionWithProperty(a.Right, a.Right, func));
 }
 /// <summary>
 /// we need to avoid calling action twice for the same pair
 /// </summary>
 /// <typeparam name="TA"></typeparam>
 /// <param name="a"></param>
 /// <param name="action"></param>
 static void HandleEquality <TA>(IntervalNode <TA> a, Action <TA, TA> action)
 {
     if (a.Left == null)
     {
         return;                 //we don't do anything for two equal leafs
     }
     CrossIntervalNodes <TA>(a.Left, a.Left, action);
     CrossIntervalNodes <TA>(a.Left, a.Right, action);
     CrossIntervalNodes <TA>(a.Right, a.Right, action);
 }
Exemple #9
0
 static IntervalNode <TData> FindTopUnbalancedNode(IntervalNode <TData> node)
 {
     for (var parent = node.Parent; parent != null; parent = parent.Parent)
     {
         if (!Balanced(parent))
         {
             return(parent);
         }
     }
     return(null);
 }
Exemple #10
0
        static void RebuildUnderNodeWithoutLeaf(IntervalNode <TData> nodeForRebuild, IntervalNode <TData> leaf)
        {
            Debug.Assert(leaf.IsLeaf);
            Debug.Assert(!nodeForRebuild.IsLeaf);
            var newNode =
                IntervalNode <TData> .CreateIntervalNodeOnEnumeration(
                    nodeForRebuild.GetAllLeafNodes().Where(n => !(n.Equals(leaf))));

            nodeForRebuild.Count    = newNode.Count;
            nodeForRebuild.Left     = newNode.Left;
            nodeForRebuild.Right    = newNode.Right;
            nodeForRebuild.Interval = new Interval(newNode.Left.interval, newNode.Right.interval);
        }
Exemple #11
0
 static public void TraverseHierarchy(IntervalNode <TData> node, Action <IntervalNode <TData> > visitor)
 {
     ValidateArg.IsNotNull(node, "node");
     ValidateArg.IsNotNull(visitor, "visitor");
     visitor(node);
     if (node.Left != null)
     {
         TraverseHierarchy(node.Left, visitor);
     }
     if (node.Right != null)
     {
         TraverseHierarchy(node.Right, visitor);
     }
 }
Exemple #12
0
        static bool TreeIsCorrect(IntervalNode <TData> node)
        {
            if (node == null)
            {
                return(true);
            }
            bool ret = node.Left != null && node.Right != null ||
                       node.Left == null && node.Right == null;

            if (!ret)
            {
                return(false);
            }
            return(TreeIsCorrect(node.Left) && TreeIsCorrect(node.Right));
        }
Exemple #13
0
 internal void Add(IntervalNode <TData> node)
 {
     if (rootNode == null)
     {
         rootNode = node;
     }
     else if (Count <= 2)
     {
         rootNode = IntervalNode <TData> .CreateIntervalNodeOnEnumeration(rootNode.GetAllLeafNodes().Concat(new[] { node }));
     }
     else
     {
         AddNodeToTreeRecursive(node, rootNode);
     }
 }
Exemple #14
0
        /// <summary>
        ///
        /// </summary>
        /// <returns></returns>
        public IntervalNode <TData> Clone()
        {
            var ret = new IntervalNode <TData>(Count)
            {
                UserData = UserData, Interval = Interval
            };

            if (Left != null)
            {
                ret.Left = Left.Clone();
            }
            if (Right != null)
            {
                ret.Right = Right.Clone();
            }
            return(ret);
        }
Exemple #15
0
        static public IntervalNode <TData> CreateIntervalNodeOnListOfNodes(IList <IntervalNode <TData> > nodes)
        {
            ValidateArg.IsNotNull(nodes, "nodes");
            if (nodes.Count == 0)
            {
                return(null);
            }

            if (nodes.Count == 1)
            {
                return(nodes[0]);
            }

            //Finding the seeds
            var b0 = nodes[0].Interval;

            //the first seed
            int seed0 = 1;

            int seed1 = ChooseSeeds(nodes, ref b0, ref seed0);

            //We have two seeds at hand. Build two groups.
            var gr0 = new List <IntervalNode <TData> >();
            var gr1 = new List <IntervalNode <TData> >();

            gr0.Add(nodes[seed0]);
            gr1.Add(nodes[seed1]);

            var box0 = nodes[seed0].Interval;
            var box1 = nodes[seed1].Interval;

            //divide nodes on two groups
            DivideNodes(nodes, seed0, seed1, gr0, gr1, ref box0, ref box1, GroupSplitThreshold);

            var ret = new IntervalNode <TData>(nodes.Count)
            {
                Interval = new Interval(box0, box1),
                Left     = CreateIntervalNodeOnListOfNodes(gr0),
                Right    = CreateIntervalNodeOnListOfNodes(gr1)
            };

            return(ret);
        }
Exemple #16
0
 static HitTestBehavior VisitTreeStatic(IntervalNode <TData> intervalNode, Func <TData, HitTestBehavior> hitTest, Interval hitInterval)
 {
     if (intervalNode.Interval.Intersects(hitInterval))
     {
         if (hitTest(intervalNode.UserData) == HitTestBehavior.Continue)
         {
             if (intervalNode.Left != null)
             {
                 // If intervalNode.Left is not null, intervalNode.Right won't be either.
                 if (VisitTreeStatic(intervalNode.Left, hitTest, hitInterval) == HitTestBehavior.Continue &&
                     VisitTreeStatic(intervalNode.Right, hitTest, hitInterval) == HitTestBehavior.Continue)
                 {
                     return(HitTestBehavior.Continue);
                 }
                 return(HitTestBehavior.Stop);
             }
             return(HitTestBehavior.Continue);
         }
         return(HitTestBehavior.Stop);
     }
     return(HitTestBehavior.Continue);
 }
Exemple #17
0
        public IEnumerable <IntervalNode <TData> > GetLeafIntervalNodesIntersectingInterval(Interval intervalPar)
        {
            var stack = new Stack <IntervalNode <TData> >();

            stack.Push(this);
            while (stack.Count > 0)
            {
                IntervalNode <TData> node = stack.Pop();
                if (node.Interval.Intersects(intervalPar))
                {
                    if (node.IsLeaf)
                    {
                        yield return(node);
                    }
                    else
                    {
                        stack.Push(node.left);
                        stack.Push(node.right);
                    }
                }
            }
        }
 internal static void CrossIntervalNodes <TA>(IntervalNode <TA> a, IntervalNode <TA> b, Action <TA, TA> action)
 {
     if (!a.interval.Intersects(b.interval))
     {
         return;
     }
     if (Equals(a, b))
     {
         HandleEquality(a, action);
     }
     else if (a.Left == null)
     {
         if (b.Left == null)
         {
             action(a.UserData, b.UserData);
         }
         else
         {
             CrossIntervalNodes <TA>(a, b.Left, action);
             CrossIntervalNodes <TA>(a, b.Right, action);
         }
     }
     else
     {
         if (b.Left != null)
         {
             CrossIntervalNodes <TA>(a.Left, b.Left, action);
             CrossIntervalNodes <TA>(a.Left, b.Right, action);
             CrossIntervalNodes <TA>(a.Right, b.Left, action);
             CrossIntervalNodes <TA>(a.Right, b.Right, action);
         }
         else
         {
             CrossIntervalNodes <TA>(a.Left, b, action);
             CrossIntervalNodes <TA>(a.Right, b, action);
         }
     }
 }
Exemple #19
0
 /// <summary>
 /// rebuild the whole tree
 /// </summary>
 public void Rebuild()
 {
     rootNode = IntervalNode <TData> .CreateIntervalNodeOnEnumeration(rootNode.GetAllLeafNodes());
 }
Exemple #20
0
 /// <summary>
 /// Create a query tree for a given root node
 /// </summary>
 /// <param name="rootNode"></param>
 public IntervalRTree(IntervalNode <TData> rootNode)
 {
     this.rootNode = rootNode;
 }
Exemple #21
0
 static bool Balanced(IntervalNode <TData> rectangleNode)
 {
     return(2 * rectangleNode.Left.Count >= rectangleNode.Right.Count &&
            2 * rectangleNode.Right.Count >= rectangleNode.Left.Count);
 }
        /// <summary>
        /// returns true if "property" holds for some pair
        /// </summary>
        /// <typeparam name="TA"></typeparam>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        internal static bool FindIntersectionWithProperty <TA>(IntervalNode <TA> a, IntervalNode <TA> b, Func <TA, TA, bool> property)
        {
            if (!a.interval.Intersects(b.interval))
            {
                return(false);
            }
            if (Equals(a, b))
            {
                return(HandleEqualityCheck(a, property));
            }

            if (a.Left == null)
            {
                if (b.Left == null)
                {
                    return(property(a.UserData, b.UserData));
                }

                if (FindIntersectionWithProperty(a, b.Left, property))
                {
                    return(true);
                }
                if (FindIntersectionWithProperty(a, b.Right, property))
                {
                    return(true);
                }
            }
            else
            {
                if (b.Left != null)
                {
                    if (FindIntersectionWithProperty(a.Left, b.Left, property))
                    {
                        return(true);
                    }
                    if (FindIntersectionWithProperty(a.Left, b.Right, property))
                    {
                        return(true);
                    }
                    if (FindIntersectionWithProperty(a.Right, b.Left, property))
                    {
                        return(true);
                    }
                    if (FindIntersectionWithProperty(a.Right, b.Right, property))
                    {
                        return(true);
                    }
                }
                else
                {
                    if (FindIntersectionWithProperty(a.Left, b, property))
                    {
                        return(true);
                    }
                    if (FindIntersectionWithProperty(a.Right, b, property))
                    {
                        return(true);
                    }
                }
            }
            return(false);
        }
Exemple #23
0
 public IntervalRTree(IEnumerable <KeyValuePair <Interval, TData> > rectsAndData)
 {
     rootNode = IntervalNode <TData> .CreateIntervalNodeOnEnumeration(GetNodeRects(rectsAndData));
 }