package com.github.davidmoten.rtree.internal;
import java.util.Comparator;
import java.util.List;
import com.github.davidmoten.rtree.Entry;
import com.github.davidmoten.rtree.Selector;
import com.github.davidmoten.rtree.Splitter;
import com.github.davidmoten.rtree.geometry.Geometry;
import com.github.davidmoten.rtree.geometry.HasGeometry;
import com.github.davidmoten.rtree.geometry.Rectangle;
/**
* Utility functions asociated with {@link Comparator}s, especially for use with
* {@link Selector}s and {@link Splitter}s.
*
*/
public final class Comparators {
private Comparators() {
// prevent instantiation
}
public static <T extends HasGeometry> Comparator<HasGeometry> overlapAreaThenAreaIncreaseThenAreaComparator(
final Rectangle r, final List<T> list) {
return new Comparator<HasGeometry>() {
@Override
public int compare(HasGeometry g1, HasGeometry g2) {
int value = Float.compare(overlapArea(r, list, g1), overlapArea(r, list, g2));
if (value == 0) {
value = Float.compare(areaIncrease(r, g1), areaIncrease(r, g2));
if (value == 0) {
value = Float.compare(area(r, g1), area(r, g2));
}
}
return value;
}
};
}
private static float area(final Rectangle r, HasGeometry g1) {
return g1.geometry().mbr().add(r).area();
}
public static <T extends HasGeometry> Comparator<HasGeometry> areaIncreaseThenAreaComparator(
final Rectangle r) {
return new Comparator<HasGeometry>() {
@Override
public int compare(HasGeometry g1, HasGeometry g2) {
int value = Float.compare(areaIncrease(r, g1), areaIncrease(r, g2));
if (value == 0) {
value = Float.compare(area(r, g1), area(r, g2));
}
return value;
}
};
}
private static float overlapArea(Rectangle r, List<? extends HasGeometry> list,
HasGeometry g) {
Rectangle gPlusR = g.geometry().mbr().add(r);
float m = 0;
for (HasGeometry other : list) {
if (other != g) {
m += gPlusR.intersectionArea(other.geometry().mbr());
}
}
return m;
}
private static float areaIncrease(Rectangle r, HasGeometry g) {
Rectangle gPlusR = g.geometry().mbr().add(r);
return gPlusR.area() - g.geometry().mbr().area();
}
/**
* <p>
* Returns a comparator that can be used to sort entries returned by search
* methods. For example:
* </p>
* <p>
* <code>search(100).toSortedList(ascendingDistance(r))</code>
* </p>
*
* @param <T>
* the value type
* @param <S>
* the entry type
* @param r
* rectangle to measure distance to
* @return a comparator to sort by ascending distance from the rectangle
*/
public static <T, S extends Geometry> Comparator<Entry<T, S>> ascendingDistance(
final Rectangle r) {
return new Comparator<Entry<T, S>>() {
@Override
public int compare(Entry<T, S> e1, Entry<T, S> e2) {
return Double.compare(e1.geometry().distance(r), e2.geometry().distance(r));
}
};
}
}