/**
* KDNearestSearch.java
*/
package rampancy_old.util.kdTree;
import java.util.*;
/**
* @author Matthew Chun-Lum
*
*/
public class KDNearestSearch<T> {
public T target;
public int k;
public List<T> nearestNeighbors;
public double furthestDistance;
public KDDistanceFunction<T> distanceFunction;
public KDNearestSearch(T target, int k, KDDistanceFunction<T> distanceFunction) {
this.k = k;
this.target = target;
nearestNeighbors = new ArrayList<T>();
furthestDistance = -1;
this.distanceFunction = distanceFunction;
}
/**
* Attempts to add the candidate point to the nearest neighbor list
* @param candidate
* @return {@code true} if the candidate was added
*/
public boolean attemptToAdd(T candidate) {
if(nearestNeighbors.size() < k) {
nearestNeighbors.add(candidate);
furthestDistance = Math.max(distanceFunction.distance(candidate, target), furthestDistance);
return true;
} else if(distanceFunction.distance(candidate, target) <= furthestDistance) {
nearestNeighbors.add(candidate);
return true;
}
return false;
}
/**
* @param candidate
* @return {@code true} if the candidate could be added to the neighbors list
*/
public boolean canTraverse(T candidate) {
return (nearestNeighbors.size() < k || distance(candidate) <= furthestDistance);
}
/**
* @param point
* @return using the distance function, compute the distance to the point
*/
public double distance(T point) {
return distanceFunction.distance(target, point);
}
/**
* @return Return only the K nearest neighbors
*/
public List<T> getNearestNeighbors() {
sortNeighbors();
return nearestNeighbors.subList(0, Math.min(nearestNeighbors.size(), k));
}
// ------------ Private ------------- //
/**
* Sort the nearest neighbors
*/
private void sortNeighbors() {
Collections.sort(nearestNeighbors, new Comparator<T>() {
public int compare(T o1, T o2) {
if(distanceFunction.distance(o1, target) == distanceFunction.distance(o2, target))
return 0;
else if(distanceFunction.distance(o1, target) < distanceFunction.distance(o2, target))
return -1;
else
return 1;
}
});
}
}