protected NearestNeighborIterator(KdNode <T> treeRoot, double[] searchPoint, int maxPointsReturned, IDistanceFunction distanceFunction) { this.searchPoint = Arrays.copyOf(searchPoint, searchPoint.Length); this.pointsRemaining = Math.Min(maxPointsReturned, treeRoot.size()); this.distanceFunction = distanceFunction; this.pendingPaths = new BinaryHeap.Min <KdNode <T> >(); this.pendingPaths.offer(0, treeRoot); this.evaluatedPoints = new KDTreeRednaxela.IntervalHeap <T>(); }
protected static <T> nearestNeighborSearchStep( KDTreeRednaxela.MinHeap <KdNode <T> > pendingPaths, MaxHeap <T> evaluatedPoints, int desiredPoints, IDistanceFunction distanceFunction, double[] searchPoint) { // If there are pending paths possibly closer than the nearest evaluated point, check it out KdNode <T> cursor = pendingPaths.getMin(); pendingPaths.removeMin(); // Descend the tree, recording paths not taken while (!cursor.isLeaf()) { KdNode <T> pathNotTaken; if (searchPoint[cursor.splitDimension] > cursor.splitValue) { pathNotTaken = cursor.left; cursor = cursor.right; } else { pathNotTaken = cursor.right; cursor = cursor.left; } double otherDistance = distanceFunction.distanceToRect(searchPoint, pathNotTaken.minBound, pathNotTaken.maxBound); // Only add a path if we either need more points or it's closer than furthest point on list so far if (evaluatedPoints.size() < desiredPoints || otherDistance <= evaluatedPoints.getMaxKey()) { pendingPaths.offer(otherDistance, pathNotTaken); } } if (cursor.singlePoint) { double nodeDistance = distanceFunction.distance(cursor.points[0], searchPoint); // Only add a point if either need more points or it's closer than furthest on list so far if (evaluatedPoints.size() < desiredPoints || nodeDistance <= evaluatedPoints.getMaxKey()) { for (int i = 0; i < cursor.size(); i++) { T value = (T)cursor.data[i]; // If we don't need any more, replace max if (evaluatedPoints.size() == desiredPoints) { evaluatedPoints.replaceMax(nodeDistance, value); } else { evaluatedPoints.offer(nodeDistance, value); } } } } else { // Add the points at the cursor for (int i = 0; i < cursor.size(); i++) { double[] point = cursor.points[i]; T value = (T)cursor.data[i]; double distance = distanceFunction.distance(point, searchPoint); // Only add a point if either need more points or it's closer than furthest on list so far if (evaluatedPoints.size() < desiredPoints) { evaluatedPoints.offer(distance, value); } else if (distance < evaluatedPoints.getMaxKey()) { evaluatedPoints.replaceMax(distance, value); } } } }