海龟绘图
凸包计算 convexHull()
什么是凸包
凸包(Convex Hull)是一个计算几何(图形学)中的概念。在一个实数向量空间V中,对于给定集合X,所有包含X的凸集的交集S被称为X的凸包。X的凸包可以用X内所有点(X1,...Xn)的凸组合来构造.在二维欧几里得空间中,凸包可想象为一条刚好包著所有点的橡皮圈。用不严谨的话来讲,给定二维平面上的点集,凸包就是将最外层的点连接起来构成的凸多边形,它能包含点集中所有的点。

如何计算凸包
1.判断点集内元素的个数
若点集内元素的个数少于三个,那么凸包就是该点集。

若点集内元素的个数多于三个,那么就有可能有的点不在凸包的点集内。

2.当多于三个点,寻找起始点
起始点一般为最为左下角或右下角或左上角或右上角的点(其中一个)(后文都以左下角的点)

for(Point point : points) {//blPoint为左下角的点
if(blPoint == null){
blPoint = point;
continue;
}
if(blPoint.x() > point.x())
blPoint = point;
else if(blPoint.x() == point.x())
{
if(point.y() < blPoint.y())
blPoint = point;
}
}
turnPoint.add(blPoint); //最左下角点一定为凸包点集内的点,加入集合
nowPoint = blPoint;
angle = 0.0; //起始角度
点集遍历,按顺时针找到凸包点集的点






while(true)
{
nextangle = 360;
nextLength = Double.MAX_VALUE;
for(Point point : points)
{
if(point.equals(nowPoint))
continue;
nowangle = calculateBearingToPoint(angle,(int)nowPoint.x(),(int)nowPoint.y(),(int)point.x(),(int)point.y());
if(nowangle<0){//**nowangle为负数是要转换成正数**要不然会出现死循环
nowangle=360.0+nowangle;
}
if(nextangle == nowangle){//角度相等时 比较长度 选取较长的
if(nextLength < ((point.x()-nowPoint.x())*(point.x()-nowPoint.x())+(point.y()-nowPoint.y())*(point.y()-nowPoint.y()))
{
nextLength = (point.x()-nowPoint.x())*(point.x()-nowPoint.x())+(point.y()-nowPoint.y())*(point.y()-nowPoint.y());
nextPoint = point;
}
}
else if(nextangle > nowangle) {//角度不同时 选取角度较小的
nextLength = (point.x()-nowPoint.x())*(point.x()-nowPoint.x())+(point.y()-nowPoint.y())*(point.y()-nowPoint.y());
nextangle = nowangle;
nextPoint = point;
}
}
if(blPoint.equals(nextPoint))//当循环回到左下角的点时说明结束了
{
break;
}
nowPoint = nextPoint;
angle += nextangle;
angle =angle%360;//防止大于360度,但好像没用
turnPoint.add(nextPoint);
}
4.calculateBearingToPoint函数
这个函数是为了求出两点间角度偏向
写的较为繁琐...

public static double calculateBearingToPoint(double currentBearing, int currentX, int currentY,
int targetX, int targetY) {//计算两点旋转角度角度
if(currentX==targetX&¤tY==targetY){
System.out.println("是同一个点");
return 0.0;
}
double sum=0.0;
if(currentX<targetX¤tY<targetY){
double angle;
double b=targetY-currentY;
double c=targetX-currentX;
double a=Math.sqrt(c*c+b*b);
angle = Math.toDegrees(Math.acos((a * a + b * b - c * c) / (2 * a * b)));
sum = angle - currentBearing;
} else if (currentX>targetX¤tY<targetY) {
double angle;
double b=targetY-currentY;
double c=currentX-targetX;
double a=Math.sqrt(c*c+b*b);
angle = Math.toDegrees(Math.acos((a * a + b * b - c * c) / (2 * a * b)));
sum = 360.0 - currentBearing - angle;
} else if (currentX<targetX¤tY>targetY) {
double angle;
double b=currentY-targetY;
double c=targetX-currentX;
double a=Math.sqrt(c*c+b*b);
angle = Math.toDegrees(Math.acos((a * a + b * b - c * c) / (2 * a * b)));
sum = 180.0 - angle - currentBearing;
} else if (currentX>targetX & currentY>targetY) {
double angle;
double b=currentY-targetY;
double c=currentX-targetX;
double a=Math.sqrt(c*c+b*b);
angle = Math.toDegrees(Math.acos((a * a + b * b - c * c) / (2 * a * b)));
sum = 180 - currentBearing + angle;
}else if (targetX==currentX&targetY>currentY) {
sum=360.0-currentBearing;
} else if (targetX==currentX&targetY<currentY) {
sum=180-currentBearing;
} else if (targetX<currentX&targetY==currentY) {
sum=270-currentBearing;
} else if (targetX>currentX&targetY==currentY) {
sum=90-currentBearing;
}
if(sum%360==0.0){
sum=0.0;
}
return sum;
//throw new RuntimeException("implement me!");
}
返回数据
return turnlPoint;
测试类
@Test
public void convexHullTest() {
Set<Point> points = new HashSet<Point>();
Set<Point> convexHull = new HashSet<Point>();
assertEquals(convexHull, TurtleSoup.convexHull(points));
Point p11 = new Point(1, 1);
Point p1010 = new Point(10, 10);
Point p110 = new Point(1, 10);
Point p12 = new Point(1, 2);
Point p23 = new Point(2, 3);
Point p32 = new Point(3, 2);
points.add(p11);
convexHull.add(p11);
assertEquals(convexHull, TurtleSoup.convexHull(points));
points.add(p1010);
convexHull.add(p1010);
assertEquals(convexHull, TurtleSoup.convexHull(points));
points.add(p110);
convexHull.add(p110);
assertEquals(convexHull, TurtleSoup.convexHull(points));
points.add(p12);
assertEquals(convexHull, TurtleSoup.convexHull(points));
points.add(p23);
assertEquals(convexHull, TurtleSoup.convexHull(points));
points.add(p32);
convexHull.add(p32);
assertEquals(convexHull, TurtleSoup.convexHull(points));
}