package com.interview.basics.model.geometry;
import com.interview.utils.FloatAssertion;
import com.interview.utils.GeoUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* Created_By: stefanie
* Date: 15-1-12
* Time: 下午3:48
*/
public class ConvexHull_SweepLine {
static Comparator<float[]> COMPARATOR = new Comparator<float[]>() {
@Override
public int compare(float[] o1, float[] o2) {
if(FloatAssertion.equals(o1[0], o2[0])){
return FloatAssertion.compareTo(o1[1], o2[1]);
} else return FloatAssertion.compareTo(o1[0], o2[0]);
}
};
public List<float[]> find(float[][] points){
Arrays.sort(points, COMPARATOR);
List<float[]> upper = new ArrayList();
List<float[]> lower = new ArrayList();
float[] leftMost = points[0];
for(int i = 1; i < points.length; i++){
if(points[i][1] >= leftMost[1]) upper.add(points[i]);
else lower.add(points[i]);
}
List<float[]> upperConvexHull = buildConvexHull(leftMost, upper, true);
List<float[]> lowerConvexHull = buildConvexHull(leftMost, lower, false);
for(int i = lower.size() - 1; i >= 0; i--){
upperConvexHull.add(lowerConvexHull.get(i));
}
return upperConvexHull;
}
private List<float[]> buildConvexHull(float[] leftMost, List<float[]> points, boolean isUpper) {
List<float[]> convexHull = new ArrayList();
convexHull.add(leftMost);
for(int i = 0; i < points.size(); i++){
if(i == 0) convexHull.add(points.get(i));
else {
while(convexHull.size() >= 2){
float cross = GeoUtil.crossProduct(convexHull.get(convexHull.size() - 2),
convexHull.get(convexHull.size() - 1), points.get(i));
if((isUpper && FloatAssertion.compareTo(cross, 0.0) >= 0)
|| (!isUpper && FloatAssertion.compareTo(cross, 0.0) <= 0)){
convexHull.remove(convexHull.size() - 1);
} else {
break;
}
}
convexHull.add(points.get(i));
}
}
return convexHull;
}
}