package com.interview.basics.model.geometry; import com.interview.utils.FloatAssertion; import java.util.ArrayList; import java.util.List; /** * Created_By: stefanie * Date: 15-1-5 * Time: 上午9:25 */ public class ConvexHull { /** * If onEdge is true, use as many points as possible for * the convex hull, otherwise as few as possible. * * when crossProduct == 0, both N and X are in the same direction. * If onEdge is true, pick the closest one, otherwise pick the farthest one. */ public List<float[]> find(float[][] points, boolean onEdge){ List<float[]> convexHull = new ArrayList(); boolean[] used = new boolean[points.length]; int leftMost = leftMost(points); convexHull.add(points[leftMost]); used[leftMost] = true; int start = leftMost; float dist = onEdge? Integer.MAX_VALUE : 0; do{ int next = -1; for(int i = 0; i < points.length; i++){ if(used[i]) continue; float d = new Vector(points[start], points[i]).length(); if(next == -1) { next = i; dist = d; } else { float cross = new Vector(points[start], points[i]).cross(new Vector(points[start], points[next])); int cmp = FloatAssertion.compareTo(cross, 0.0); if(cmp < 0) { next = i; dist = d; } else if(cmp == 0){ if(onEdge && d < dist){ next = i; dist = d; }else if(!onEdge && d > dist){ next = i; dist = d; } } } convexHull.add(points[next]); start = next; } } while(start != leftMost); return convexHull; } public int leftMost(float[][] points){ int leftMost = 0; for(int i = 1; i < points.length; i++){ if(points[i][0] < points[leftMost][0] || (points[i][0] == points[leftMost][0] && points[i][1] > points[leftMost][1])) leftMost = i; } return leftMost; } }