凸包是一个计算几何(图形学)中的概念。
在一个实数向量空间V中,对于给定的集合X,所有包含X的凸集的交集S被称为X的凸包。
X的凸包可以用X内所有点(X1,...Xn)的线性组合来构造.
在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。
用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边型,它能包含点集中所有的点。如下图所示:
一个比较简单的实现方法如下:
首先将所有点放在平面直角坐标系中,然后找到最左(横坐标相等则取纵坐标更小的)的点,这个点加入凸包集合。然后寻找与该点相对角度最小的点并加入。(起始角度为零且所有角度都是相对y轴正方向,顺时针旋转)。实现代码如下:
public static Set<P2.turtle.Point> convexHull(Set<P2.turtle.Point> points) { //throw new RuntimeException("implement me!"); //首先处理点的坐标 //点的个数小于等于3时,所有点都在凸包内 if (points.size() <= 3) return points; Set<Point> convexHullPoints = new HashSet<Point>(); Point a = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); //先找出在平面上最左下角的点 for(Point i : points){ if(i.x() < a.x() || (i.x() == a.x() && i.y() < a.y())) a = i; } convexHullPoints.add(a); Point curpoint = a, nextpoint = null; double angle = 0, mintheta = 360, theta = 0, distance = 0; while(nextpoint != a) { for(Point i : points) {//类似calculateBearingToPoint的方法,找出使得旋转角度最小的点 //运用反三角函数计算目标点与当前点所成斜线与x轴正向的夹角 double angle1 = Math.atan2(i.y() - curpoint.y(), i.x() - curpoint.x()) * 180.0 / Math.PI; //角度为负的,调整为正值 if(angle1 < 0) angle1 += 360.0; //计算斜线与y轴正向之间的夹角(y轴为始边,顺时针方向为正向),再减去当前偏移角度 double bearing = (360 - angle1 + 90 >= 360 ? 90 - angle1 : 360 - angle1 + 90) - angle; //最后调整为0-360°之间 if(bearing < 0) theta = 360.0 + bearing; else theta = bearing; //查找使得旋转角度最小的角 if((!convexHullPoints.contains(i) || (i == a && curpoint != a)) && theta < mintheta) { mintheta = theta; nextpoint = i; distance = Math.sqrt((i.y() - curpoint.y())*(i.y() - curpoint.y())+(i.x() - curpoint.x())*(i.x() - curpoint.x())); } //当旋转角度相同时,选择距离当前点更远的点 if((!convexHullPoints.contains(i) || (i == a && curpoint != a)) && theta == mintheta) { if(Math.sqrt((i.y() - curpoint.y())*(i.y() - curpoint.y())+(i.x() - curpoint.x())*(i.x() - curpoint.x())) > distance) { nextpoint = i; distance = Math.sqrt((i.y() - curpoint.y())*(i.y() - curpoint.y())+(i.x() - curpoint.x())*(i.x() - curpoint.x())); } } } convexHullPoints.add(nextpoint); curpoint = nextpoint; angle += mintheta; if(angle > 360) angle -= 360; mintheta = 360; } return convexHullPoints; }