예제 #1
0
            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;
            }
예제 #2
0
            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);
                        }
                    }
                }
            }
예제 #3
0
 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);
                        }
                    }
                }
            }