parents.push(rootNodeId);
TIntStack parentsEntry = new TIntArrayStack();
parentsEntry.push(-1);
TIntArrayList savedValues = new TIntArrayList();
float savedPriority = 0;
// TODO: possible shortcut here - could test for intersection with the
// MBR of the root node. If no intersection, return immediately.
float furthestDistanceSq = furthestDistance * furthestDistance;
while (parents.size() > 0) {
Node n = getNode(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.
boolean near = false;
for (int i = startIndex; i < n.entryCount; i++) {
if (Rectangle.distanceSq(n.entriesMinX[i], n.entriesMinY[i],
n.entriesMaxX[i], n.entriesMaxY[i],
p.x, p.y) <= furthestDistanceSq) {
parents.push(n.ids[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++) {
float entryDistanceSq = Rectangle.distanceSq(n.entriesMinX[i], n.entriesMinY[i],
n.entriesMaxX[i], n.entriesMaxY[i],
p.x, p.y);
int entryId = n.ids[i];
if (entryDistanceSq <= furthestDistanceSq) {
distanceQueue.insert(entryId, entryDistanceSq);
while (distanceQueue.size() > count) {
// normal case - we can simply remove the lowest priority (highest distance) entry
int value = distanceQueue.getValue();
float distanceSq = distanceQueue.getPriority();
distanceQueue.pop();
// rare case - multiple items of the same priority (distance)
if (distanceSq == distanceQueue.getPriority()) {
savedValues.add(value);
savedPriority = distanceSq;
} else {
savedValues.reset();
}
}
// if the saved values have the same distance as the
// next one in the tree, add them back in.
if (savedValues.size() > 0 && savedPriority == distanceQueue.getPriority()) {
for (int svi = 0; svi < savedValues.size(); svi++) {
distanceQueue.insert(savedValues.get(svi), savedPriority);
}
savedValues.reset();
}
// narrow the search, if we have already found N items
if (distanceQueue.getPriority() < furthestDistanceSq && distanceQueue.size() >= count) {
furthestDistanceSq = distanceQueue.getPriority();