package pl.llp.aircasting.util.map;
import com.google.android.maps.GeoPoint;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
/**
* Created by IntelliJ IDEA.
* User: obrok
* Date: 2/27/12
* Time: 4:41 PM
*/
public class PathSmoother {
private static final double DIST_CUTOFF = 50;
private List<GeoPoint> points;
private boolean[] keep;
public List<GeoPoint> getSmoothed(List<GeoPoint> geoPoints) {
points = newArrayList(geoPoints);
keep = new boolean[this.points.size()];
ramerDouglasPeucke(0, keep.length - 1);
List<GeoPoint> result = newArrayList();
for (int i = 0; i < keep.length; i++) {
if (keep[i]) {
result.add(this.points.get(i));
}
}
return result;
}
private void ramerDouglasPeucke(int left, int right) {
if (right - left < 2) return;
keep[left] = keep[right] = true;
double best = perpendicularDist(points.get(left + 1), points.get(left), points.get(right));
int bestIndex = left + 1;
for (int i = left + 2; i < right; i++) {
double dist = perpendicularDist(points.get(i), points.get(left), points.get(right));
if (dist > best) {
best = dist;
bestIndex = i;
}
}
if (best > DIST_CUTOFF) {
ramerDouglasPeucke(left, bestIndex);
ramerDouglasPeucke(bestIndex, right);
}
}
private double perpendicularDist(GeoPoint from, GeoPoint to1, GeoPoint to2) {
double x1 = from.getLongitudeE6();
double y1 = from.getLatitudeE6();
double x2 = to1.getLongitudeE6();
double y2 = to1.getLatitudeE6();
double x3 = to2.getLongitudeE6();
double y3 = to2.getLatitudeE6();
// Line equation of a straight line going through (x2, y2) and (x3, y3):
// x(y3 - y2) + y(x2 - x3) - x2y3 + y2x3
double a = y3 - y2;
double b = x2 - x3;
double c = -x2 * y3 + y2 * x3;
// Perpendicular distance of (x1,y1) to L: ax + by + c = 0
return Math.abs(a * x1 + b * y1 + c) / Math.sqrt(a * a + b * b);
}
}