internal IEnumerable <Tuple <QuadNode, double> > GetNodesInside(Rect bounds) { double num = _bounds.Width / 2.0; double num2 = _bounds.Height / 2.0; Rect self = new Rect(_bounds.Left, _bounds.Top, num, num2); Rect self2 = new Rect(_bounds.Left + num, _bounds.Top, num, num2); Rect self3 = new Rect(_bounds.Left, _bounds.Top + num2, num, num2); Rect self4 = new Rect(_bounds.Left + num, _bounds.Top + num2, num, num2); var priorityQueue = new PriorityQueue <IEnumerator <Tuple <QuadNode, double> >, double>(true); if (_nodes != null) { priorityQueue.Enqueue(_nodes.GetNodesInside(bounds).GetEnumerator(), _nodes.Next.Priority); } if (_topLeft != null && self.Intersects(bounds)) { priorityQueue.Enqueue(_topLeft.GetNodesInside(bounds).GetEnumerator(), _topLeft._potential); } if (_topRight != null && self2.Intersects(bounds)) { priorityQueue.Enqueue(_topRight.GetNodesInside(bounds).GetEnumerator(), _topRight._potential); } if (_bottomLeft != null && self3.Intersects(bounds)) { priorityQueue.Enqueue(_bottomLeft.GetNodesInside(bounds).GetEnumerator(), _bottomLeft._potential); } if (_bottomRight != null && self4.Intersects(bounds)) { priorityQueue.Enqueue(_bottomRight.GetNodesInside(bounds).GetEnumerator(), _bottomRight._potential); } while (priorityQueue.Count > 0) { IEnumerator <Tuple <QuadNode, double> > key = priorityQueue.Dequeue().Key; if (key.MoveNext()) { Tuple <QuadNode, double> current = key.Current; QuadNode item = current.Item1; double item2 = current.Item2; double num3 = (priorityQueue.Count > 0) ? ((!item2.IsNaN()) ? Math.Max(item2, priorityQueue.Peek().Value) : priorityQueue.Peek().Value) : item2; if (num3 > item.Priority) { var enumerator = Enumerable.Repeat(Tuple.Create(item, double.NaN), 1) .GetEnumerator(); priorityQueue.Enqueue(enumerator, item.Priority); } else { yield return(Tuple.Create(item, num3)); } if (!item2.IsNaN()) { priorityQueue.Enqueue(key, item2); } } } yield break; }
internal IEnumerable <Tuple <QuadNode, double> > GetNodesInside(Rect bounds) { double w = _bounds.Width / 2.0; double h = _bounds.Height / 2.0; Rect topLeft = new Rect(_bounds.Left, _bounds.Top, w, h); Rect topRight = new Rect(_bounds.Left + w, _bounds.Top, w, h); Rect bottomLeft = new Rect(_bounds.Left, _bounds.Top + h, w, h); Rect bottomRight = new Rect(_bounds.Left + w, _bounds.Top + h, w, h); PriorityQueue <IEnumerator <Tuple <QuadNode, double> >, double> queue = new PriorityQueue <IEnumerator <Tuple <QuadNode, double> >, double>(invert: true); if (_nodes != null) { queue.Enqueue(_nodes.GetNodesInside(bounds).GetEnumerator(), _nodes.Next.Priority); } if (_topLeft != null && topLeft.Intersects(bounds)) { queue.Enqueue(_topLeft.GetNodesInside(bounds).GetEnumerator(), _topLeft._potential); } if (_topRight != null && topRight.Intersects(bounds)) { queue.Enqueue(_topRight.GetNodesInside(bounds).GetEnumerator(), _topRight._potential); } if (_bottomLeft != null && bottomLeft.Intersects(bounds)) { queue.Enqueue(_bottomLeft.GetNodesInside(bounds).GetEnumerator(), _bottomLeft._potential); } if (_bottomRight != null && bottomRight.Intersects(bounds)) { queue.Enqueue(_bottomRight.GetNodesInside(bounds).GetEnumerator(), _bottomRight._potential); } while (queue.Count > 0) { IEnumerator <Tuple <QuadNode, double> > enumerator = queue.Dequeue().Key; if (enumerator.MoveNext()) { Tuple <QuadNode, double> current = enumerator.Current; QuadNode node = current.Item1; double potential = current.Item2; double newPotential = (queue.Count <= 0) ? potential : ((!potential.IsNaN()) ? Math.Max(potential, queue.Peek().Value) : queue.Peek().Value); if (newPotential > node.Priority) { IEnumerator <Tuple <QuadNode, double> > enumerator2 = Enumerable.Repeat(Tuple.Create(node, double.NaN), 1).GetEnumerator(); queue.Enqueue(enumerator2, node.Priority); } else { yield return(Tuple.Create(node, newPotential)); } if (!potential.IsNaN()) { queue.Enqueue(enumerator, potential); } } } }
public IEnumerable <T> GetItemsInside(Rect bounds) { if (bounds.Top.IsNaN() || bounds.Left.IsNaN() || bounds.Width.IsNaN() || bounds.Height.IsNaN()) { throw new ArgumentOutOfRangeException(); } if (_root != null) { foreach (Tuple <QuadNode, double> node in _root.GetNodesInside(bounds)) { yield return(node.Item1.Node); } } }
/// <summary> /// Returns all nodes in this quadrant that are fully contained within the given bounds. /// The nodes are returned in order of descending priority. /// </summary> /// <param name="bounds">The bounds that contains the nodes you want returned.</param> /// <returns>A lazy list of nodes along with the new potential of this quadrant.</returns> internal IEnumerable <Tuple <QuadNode, double> > GetNodesInside(Rect bounds) { double w = _bounds.Width / 2; double h = _bounds.Height / 2; // assumption that the Rect struct is almost as fast as doing the operations // manually since Rect is a value type. Rect topLeft = new Rect(_bounds.Left, _bounds.Top, w, h); Rect topRight = new Rect(_bounds.Left + w, _bounds.Top, w, h); Rect bottomLeft = new Rect(_bounds.Left, _bounds.Top + h, w, h); Rect bottomRight = new Rect(_bounds.Left + w, _bounds.Top + h, w, h); // Create a priority queue based on the potential of our nodes and our quads. var queue = new PriorityQueue <IEnumerator <Tuple <QuadNode, double> >, double>(true); if (_nodes != null) { queue.Enqueue(_nodes.GetNodesInside(bounds).GetEnumerator(), _nodes.Next.Priority); } if (_topLeft != null && topLeft.Intersects(bounds)) { queue.Enqueue(_topLeft.GetNodesInside(bounds).GetEnumerator(), _topLeft._potential); } if (_topRight != null && topRight.Intersects(bounds)) { queue.Enqueue(_topRight.GetNodesInside(bounds).GetEnumerator(), _topRight._potential); } if (_bottomLeft != null && bottomLeft.Intersects(bounds)) { queue.Enqueue(_bottomLeft.GetNodesInside(bounds).GetEnumerator(), _bottomLeft._potential); } if (_bottomRight != null && bottomRight.Intersects(bounds)) { queue.Enqueue(_bottomRight.GetNodesInside(bounds).GetEnumerator(), _bottomRight._potential); } // Then just loop through the queue. while (queue.Count > 0) { // Grab the enumerator with the highest potential. var enumerator = queue.Dequeue().Key; if (enumerator.MoveNext()) { // Get the current node and its new potential from the enumerator. var current = enumerator.Current; var node = current.Item1; var potential = current.Item2; // Determine our new potential. var newPotential = queue.Count > 0 ? !potential.IsNaN() ? Math.Max(potential, queue.Peek().Value) : queue.Peek().Value : potential; // It might be the case that the actual intersecting node has less priority than our remaining potential. if (newPotential > node.Priority) { // Store it for later in a container containing only it with no further potential. var store = Enumerable.Repeat(Tuple.Create(node, double.NaN), 1).GetEnumerator(); // Enqueue the container at the correct position. queue.Enqueue(store, node.Priority); } else { // Return it to our parent along with our new potential. yield return(Tuple.Create(node, newPotential)); } // If this enumerator has some more potential then re-enqueue it. if (!potential.IsNaN()) { queue.Enqueue(enumerator, potential); } } } }