static bool NumberOfIntersectedIsLessThanBoundOnNode(RectangleNode <T, P> node, IRectangle <P> rect, ref int bound, Func <T, bool> conditionFunc) { Debug.Assert(bound > 0); if (!node.Rectangle.Intersects(rect)) { return(true); } if (node.IsLeaf) { if (conditionFunc(node.UserData)) { return((--bound) != 0); } return(true); } return(NumberOfIntersectedIsLessThanBoundOnNode(node.Left, rect, ref bound, conditionFunc) && NumberOfIntersectedIsLessThanBoundOnNode(node.Right, rect, ref bound, conditionFunc)); }
static public RectangleNode <T, P> CreateRectangleNodeOnListOfNodes(IList <RectangleNode <T, P> > 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].Rectangle; //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 <RectangleNode <T, P> >(); var gr1 = new List <RectangleNode <T, P> >(); gr0.Add(nodes[seed0]); gr1.Add(nodes[seed1]); var box0 = nodes[seed0].Rectangle; var box1 = nodes[seed1].Rectangle; //divide nodes on two groups DivideNodes(nodes, seed0, seed1, gr0, gr1, ref box0, ref box1, GroupSplitThreshold); var ret = new RectangleNode <T, P>(nodes.Count) { Rectangle = box0.Add(box1), Left = CreateRectangleNodeOnListOfNodes(gr0), Right = CreateRectangleNodeOnListOfNodes(gr1) }; return(ret); }
public IEnumerable <RectangleNode <TData> > GetLeafRectangleNodesIntersectingRectangle(Rectangle rectanglePar) { var stack = new Stack <RectangleNode <TData> >(); stack.Push(this); while (stack.Count > 0) { RectangleNode <TData> node = stack.Pop(); if (node.Rectangle.Intersects(rectanglePar)) { if (node.IsLeaf) { yield return(node); } else { stack.Push(node.left); stack.Push(node.right); } } } }
static HitTestBehavior VisitTreeStatic(RectangleNode <TData> rectangleNode, Func <TData, HitTestBehavior> hitTest, Rectangle hitRectangle) { if (rectangleNode.Rectangle.Intersects(hitRectangle)) { if (hitTest(rectangleNode.UserData) == HitTestBehavior.Continue) { if (rectangleNode.Left != null) { // If rectangleNode.Left is not null, rectangleNode.Right won't be either. if (VisitTreeStatic(rectangleNode.Left, hitTest, hitRectangle) == HitTestBehavior.Continue && VisitTreeStatic(rectangleNode.Right, hitTest, hitRectangle) == HitTestBehavior.Continue) { return(HitTestBehavior.Continue); } return(HitTestBehavior.Stop); } return(HitTestBehavior.Continue); } return(HitTestBehavior.Stop); } return(HitTestBehavior.Continue); }
internal static void CrossRectangleNodes <TA>(RectangleNode <TA> a, RectangleNode <TA> b, Action <TA, TA> action) { if (!a.rectangle.Intersects(b.rectangle)) { return; } if (Equals(a, b)) { HandleEquality(a, action); } else if (a.Left == null) { if (b.Left == null) { action(a.UserData, b.UserData); } else { CrossRectangleNodes <TA>(a, b.Left, action); CrossRectangleNodes <TA>(a, b.Right, action); } } else { if (b.Left != null) { CrossRectangleNodes <TA>(a.Left, b.Left, action); CrossRectangleNodes <TA>(a.Left, b.Right, action); CrossRectangleNodes <TA>(a.Right, b.Left, action); CrossRectangleNodes <TA>(a.Right, b.Right, action); } else { CrossRectangleNodes <TA>(a.Left, b, action); CrossRectangleNodes <TA>(a.Right, b, action); } } }
static internal bool TreeIsCorrect(RectangleNode <T, P> node) { if (node == null) { return(true); } bool ret = node.Left != null && node.Right != null || node.Left == null && node.Right == null; if (!ret) { return(false); } if (node.Left != null && node.Left.Parent != node) { return(false); } if (node.Right != null && node.Right.Parent != node) { return(false); } return(TreeIsCorrect(node.Left) && TreeIsCorrect(node.Right)); }
/// <summary> /// rebuild the whole tree /// </summary> public void Rebuild() { _rootNode = RectangleNode <TData> .CreateRectangleNodeOnEnumeration(_rootNode.GetAllLeafNodes()); }
/// <summary> /// Create a query tree for a given root node /// </summary> /// <param name="rootNode"></param> public RTree(RectangleNode <TData> rootNode) { this._rootNode = rootNode; }
static bool Balanced(RectangleNode <TData> rectangleNode) { return(2 * rectangleNode.Left.Count >= rectangleNode.Right.Count && 2 * rectangleNode.Right.Count >= rectangleNode.Left.Count); }
static void RebuildUnderNodeWithoutLeaf(RectangleNode <TData> nodeForRebuild, RectangleNode <TData> leaf) { Debug.Assert(leaf.IsLeaf); Debug.Assert(!nodeForRebuild.IsLeaf); var newNode = RectangleNode <TData> .CreateRectangleNodeOnEnumeration( nodeForRebuild.GetAllLeafNodes().Where(n => !(n.Equals(leaf)))); nodeForRebuild.Count = newNode.Count; nodeForRebuild.Left = newNode.Left; nodeForRebuild.Right = newNode.Right; nodeForRebuild.Rectangle = new Rectangle(newNode.Left.rectangle, newNode.Right.rectangle); }
public RTree(IEnumerable <KeyValuePair <Rectangle, TData> > rectsAndData) { _rootNode = RectangleNode <TData> .CreateRectangleNodeOnEnumeration(GetNodeRects(rectsAndData)); }
/// <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>(RectangleNode <TA> a, RectangleNode <TA> b, Func <TA, TA, bool> property) { if (!a.rectangle.Intersects(b.rectangle)) { 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); }
internal static void CrossRectangleNodes <TA, TB, P>(RectangleNode <TA, P> a, RectangleNode <TB, P> b, Action <TA, TB> action) { if (!a.rectangle.Intersects(b.rectangle)) { return; } if (a.Left == null) //a is a leat { if (b.Left == null) //b is a leaf { action(a.UserData, b.UserData); } else { CrossRectangleNodes(a, b.Left, action); CrossRectangleNodes(a, b.Right, action); } } else //a is not a leaf { if (b.Left != null) { CrossRectangleNodes(a.Left, b.Left, action); CrossRectangleNodes(a.Left, b.Right, action); CrossRectangleNodes(a.Right, b.Left, action); CrossRectangleNodes(a.Right, b.Right, action); } else // b is a leaf { CrossRectangleNodes(a.Left, b, action); CrossRectangleNodes(a.Right, b, action); } } }