随机二维坐标顺时针排序

思想就是取最小的x,当x一样取最小的y,取每个点与当前比对点的正切值从大到小排序得到顺时针的顺序

package com.test.utils;

import java.util.*;
/**
 * @version 1.0.0
 * @author: gongchao
 * @date: 2019/3/8 11:36
 * 离散二维坐标的顺时针方向排序工具类
 */
public  class PositionUtils {
    //二维坐标
    static class Position{
        Double x;
        Double y;
        public Position(Double x,Double y){
        this.x=x;
        this.y=y;
        }
        @Override
        public String toString() {
            return "x="+x+"y="+y;
        }
    }
    public static void  main(String[] aa){
        //255,459 511,459 1495,1050 310,1050
        List<Position> list = new ArrayList<>();
        list.add(new Position(255d,459d));
        list.add(new Position( 511d,459d));
        list.add(new Position(1495d,1050d));
        list.add(new Position(310d,1050d));
      //  list.add(new Position(1069d,496d));
     //   list.add(new Position(1500d,1075d));
     //   list.add(new Position(434d,1075d));
     //   list.forEach((x)-> System.out.println((x.x/917+","+x.y/518)));
       list.forEach((x)-> System.out.println((x.x/1920+","+x.y/1080)));
      //  list.add(new Position(0.2077,0.2698));
      //  list.add(new Position(0.0321,0.293));
      //  list.add(new Position(0.1435,0.4209));

       // list.add(new Position(0.0514,0.5));

        List<Position> positions = null;
        try {
            positions = PositionUtils.sortPosition(list);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    /**
     *输入离散点得到顺时针的二维做标集合
     * @param list
     * @throws Exception
     */
    public static List<Position> sortPosition(List<Position> list)throws Exception{
        //保存X轴坐标一样的无限小正切的集合点,按x轴从小到大
        List<Position> minTanXList=new ArrayList<>();
        //保存Y轴坐标一样的为零正切的集合点,y轴从小到大
        List<Position> zeroTanYList=new ArrayList<>();
        //排序后的二维坐标
        List<Position> afterSort=new ArrayList<>();
        //将各个点到最小的tan值和坐标保存起来
        Map<Double,Position> tanMap=new HashMap<>();
        //将各个点到最小的tan值保存起来
        List<Double> tanLists=new ArrayList<>();
        //根据X轴坐标从小到大排序
        List<Position> leftPosition = getLeftPosition(list);
        //获取最左边且靠近原点的点
        Position leftPostion = leftPosition.get(0);
        //原点
        afterSort.add(leftPostion);
        //排除最小的点从1开始获取每个点到最小点的正切
        for (int i=1;i<list.size();i++){
            Position nextPostion = list.get(i);
            //获取tan值的分子和分母
            Double tanFenmu=nextPostion.x-leftPostion.x;
            Double tanFenzi=nextPostion.y-leftPostion.y;
            //考虑到多个点与参照点同一个X坐标导致正切无限小
            if(tanFenmu.equals(0d)){
                minTanXList.add(nextPostion);
            }else if(tanFenzi.equals(0d)){
                //y轴一样正切为0
                zeroTanYList.add(nextPostion);
            }else{
                Double  tan=(tanFenzi)/(tanFenmu);
                tanMap.put(tan,nextPostion);
                tanLists.add(tan);
            }
        }
        //tan的值从大到小排列,相当于顺时针
        tanLists.sort(Comparator.reverseOrder());
        //正切无限大
        if(!minTanXList.isEmpty()){
            Collections.sort(minTanXList,( p1, p2)->p1.y.compareTo(p2.y));
            afterSort.addAll(minTanXList);
        }
      //  tanLists.forEach((tan)-> System.out.println(tan));
        Boolean flag=Boolean.TRUE;
        for (int i=0;i<tanLists.size();i++){
            Double tan = tanLists.get(i);
            //将排序后的从map取出来
            //添加正切为零的数据
            if(tan<0d&&flag){
                if(!zeroTanYList.isEmpty()){
                    afterSort.addAll(zeroTanYList);
                }
                flag=Boolean.FALSE;
                afterSort.add(tanMap.get(tan));
            }else{
                afterSort.add(tanMap.get(tan));
                if(tanLists.size()==1){
                    afterSort.addAll(zeroTanYList);
                }
                if(tan>0&&i==tanLists.size()-1){
                    afterSort.addAll(zeroTanYList);
                }
            }
        }
       // afterSort.sort();
        afterSort.forEach((x)-> System.out.println(x.x+","+x.y));
       // afterSort.forEach((x)-> System.out.println(x.x*1920+","+x.y*1080));
        return afterSort;
    }
    /**
     * 根据X轴坐标从小到大排序
     * @param list 随机离散点集合
     * @return
     * @throws Exception
     */
    public static List<Position> getLeftPosition(List<Position> list)throws Exception{
        if (list.size()<3){
            throw  new Exception("必须多余四个点");
        }
        // 取x最小的点,相同x取y小的点
        Collections.sort(list,(Position o1, Position o2)->{
            if(o1.x.equals(o2.x)){
                return o1.y.compareTo(o2.y);
            }else{
                return o1.x.compareTo(o2.x);
            }
        });
        return list;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值