HIT-2022春-软件构造 II 凸包算法

问题产生:

        问题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;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值