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); }
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); }