private void runDeleteAllEntries(int minNodeEntries, int maxNodeEntries, int numRects) { RTree rtree = new RTree(minNodeEntries, maxNodeEntries); for (int i = 0; i <= numRects; i += 100) { // add some entries for (int j = 0; j < i; j++) { rtree.Add(rects[j]); } Assert.True(rtree.checkConsistency()); // now delete them all for (int j = 0; j < i; j++) { rtree.Remove(rects[j]); } Assert.True(rtree.Count == 0); Assert.True(rtree.checkConsistency()); // check that we can make queries on an empty rtree without error. Rectangle testRect = new Rectangle(1, 2, 3, 4); Point testPoint = new Point(1, 2); Counter counter = new Counter(); rtree.Intersects(testRect, counter.execute); Assert.True(counter.count == 0); PriorityQueueRTree priorityQue = rtree.Nearest(testPoint, float.MaxValue); Assert.True(priorityQue.Count == 0); priorityQue = rtree.NearestN(testPoint, 10, float.MaxValue); Assert.True(priorityQue.Count == 0); rtree.Contains(testRect, counter.execute); Assert.True(counter.count == 0); } }
private PriorityQueueRTree createNearestNDistanceQueue(Point p, UInt32 count, double furthestDistance) { PriorityQueueRTree distanceQueue = new PriorityQueueRTree(); // return immediately if given an invalid "count" parameter if (count == 0) return distanceQueue; parents.Clear(); parents.Push(rootNode); parentsEntry.Clear(); parentsEntry.Push(-1); // TODO: possible shortcut here - could test for intersection with the MBR of the root node. If no intersection, return immediately. double furthestDistanceSq = furthestDistance * furthestDistance; while (parents.Count > 0) { NodeBase n = parents.Peek(); int startIndex = parentsEntry.Peek() + 1; if (!n.IsLeaf) { // go through every entry in the index node to check if it could contain an entry closer than the farthest entry currently stored. bool near = false; NodeInternal nodeInternal = n as NodeInternal; for (int i = startIndex; i < n.entryCount; i++) { if (n.entries[i].Value.distanceSq(p.x, p.y) <= furthestDistanceSq) { parents.Push(nodeInternal.childNodes[i]); parentsEntry.Pop(); parentsEntry.Push(i); // this becomes the start index when the child has been searched parentsEntry.Push(-1); near = true; break; // ie go to next iteration of while() } } if (near) continue; } else { // go through every entry in the leaf to check if it is currently one of the nearest N entries. for (int i = 0; i < n.entryCount; i++) { double entryDistanceSq = n.entries[i].Value.distanceSq(p.x, p.y); if (entryDistanceSq <= furthestDistanceSq) { distanceQueue.Insert(n.entries[i].Value, entryDistanceSq); while (distanceQueue.Count > count) { // normal case - we can simply remove the lowest priority (highest distance) entry Rectangle value = distanceQueue.ValuePeek; double distanceSq = distanceQueue.PriorityPeek; distanceQueue.Pop(); // rare case - multiple items of the same priority (distance) if (distanceSq == distanceQueue.PriorityPeek) { savedValues.Add(value); savedPriority = distanceSq; } else savedValues.Clear(); } // if the saved values have the same distance as the next one in the tree, add them back in. if (savedValues.Count > 0 && savedPriority == distanceQueue.PriorityPeek) { for (int svi = 0; svi < savedValues.Count; svi++) distanceQueue.Insert(savedValues[svi], savedPriority); savedValues.Clear(); } // narrow the search, if we have already found N items if (distanceQueue.PriorityPeek < furthestDistanceSq && distanceQueue.Count >= count) furthestDistanceSq = distanceQueue.PriorityPeek; } } } parents.Pop(); parentsEntry.Pop(); } return distanceQueue; }
/// <summary> /// Finds the nearest rectangles to the passed point. If multiple rectangles are equally near, they will all be returned. /// </summary> /// <param name="p">the point we are looking for</param> /// <param name="furthestDistance">The furthest distance away from the rectangle to search. Rectangles further than this will not be found.</param> /// <returns>a PriorityQue containing the found recatngles and their priorities (distances from point)</returns> public PriorityQueueRTree Nearest(Point p, double furthestDistance) { PriorityQueueRTree distanceQueue = new PriorityQueueRTree(); double furthestDistanceSq = furthestDistance * furthestDistance; rootNode.Nearest(p, this, furthestDistanceSq, distanceQueue); return distanceQueue; }
internal override double Nearest(Point p, RTree rTree, double furthestDistanceSq, PriorityQueueRTree nearestRectangles) { for (int i = 0; i < entryCount; i++) { double tempDistanceSq = entries[i].Value.distanceSq(p.x, p.y); if (tempDistanceSq < furthestDistanceSq) { furthestDistanceSq = tempDistanceSq; nearestRectangles.Clear(); } if (tempDistanceSq <= furthestDistanceSq) nearestRectangles.Insert(entries[i].Value, tempDistanceSq); } return furthestDistanceSq; }
internal override double Nearest(Point p, RTree rTree, double furthestDistanceSq, PriorityQueueRTree nearestRectangles) { for (int i = 0; i < entryCount; i++) { double tempDistanceSq = entries[i].Value.distanceSq(p.x, p.y); // a rectangle nearer than actualNearest if (tempDistanceSq <= furthestDistanceSq) { NodeBase node = childNodes[i]; // search the child node furthestDistanceSq = node.Nearest(p, rTree, furthestDistanceSq, nearestRectangles); } } return furthestDistanceSq; }
internal abstract double Nearest(Point p, RTree rTree, double furthestDistanceSq, PriorityQueueRTree nearestRectangles);