问题产生:
问题2中的TurtleSoup类中要求我们完成点集的凸包(Convex Hull )算法。凸包-百度百科https://baike.baidu.com/item/%E5%87%B8%E5%8C%85/179150?fr=aladdin
算法实现:
不严谨地讲,凸包就是在二维点集中,一群能够包围其余所有点的数量最少的点集。
在本任务中,推荐使用了Gift-Wrapping算法实现。
此算法的基本思想是:
①首先找到点集中横坐标的点(在横坐标相同时,选择纵坐标较大的点)。
②在当前点时,选择未遍历的点中,与当前点所成角度最小的(以 y 轴正向为 0 度角,若有角度相同大小的,则选择距离较大的),并将其作为当前点。
③不断循环直至回到起始点,循环结束。
代码实现:
public static Set<Point> convexHull(Set<Point> points) {
List<Point> list = new ArrayList<Point>();
List<Point> result = new ArrayList<Point>();
Set<Point> Result = new HashSet<Point>();
list.addAll(points);
int pos = 0;
if(points.size() <= 3) {
return points;
}
double xMin = list.get(0).x();
double yMax = list.get(0).y();
for( int i = 1;i < list.size(); i++) {
if((list.get(i).x() < xMin) || (list.get(i).x() == xMin && list.get(i).y() > yMax)) {
xMin = list.get(i).x() ; yMax = list.get(i).y() ; pos = i;
}
}
Point first = list.get(pos);
Point temp = first;
result.add(first);
Point target = first;
double angleSet = 360;
double distanceSet = -1;
while(true) {
for(Point i : list) {
if((i != temp)) {
double angle = TurtleSoup.calculateBearingToPointDouble(0,temp.x(),temp.y(),i.x(),i.y());
if(angle < angleSet || (angle == angleSet) && (TurtleSoup.calculateDistance(temp.x(),temp.y(),i.x(),i.y()) > distanceSet)) {
angleSet = angle;
distanceSet = TurtleSoup.calculateDistance(temp.x(),temp.y(),i.x(),i.y());
target = i;
}
}
else continue;
}
if((target.x() == first.x()) && (target.y() == first.y()))
break;
else {
result.add(target);
temp = target;
angleSet = 360;
distanceSet = -1;
if(!target.equals(first)) {
list.remove(target);
}
}
}
Result.addAll(result);
return Result;
}