package com.ruoyi.dataprocess.common;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description: 高德地图计算工具类
 * @ClassName: AmapUtils
 * @Author  : xins
 * @Date    :2023-09-02  11:13
 * @Version :1.0
 */
public class AmapUtils {

    public static class Poi{
        private Double lat;
        private Double lng;
        public Poi(Double lng,Double lat){
            this.lat = lat;
            this.lng = lng;
        }

    }

    /**
     * 计算经纬度围成的实际面积（平方公里）
     * @return
     */
    public static BigDecimal getArea(List<Poi> ring){
        double sJ = 6378137;
        double Hq = 0.017453292519943295;
        double c = sJ *Hq;
        double d = 0;

        if (3 > ring.size()) {
            return new BigDecimal( 0);
        }

        for (int i = 0; i < ring.size() - 1; i ++){
            Poi h = ring.get(i);
            Poi k = ring.get(i + 1);
            double u = h.lng * c * Math.cos(h.lat * Hq);
            double hhh = h.lat * c;
            double v = k.lng * c * Math.cos(k.lat *Hq);
            d = d + (u * k.lat * c - v * hhh);
        }
        Poi g1 = ring.get(ring.size()-1);
        Poi point = ring.get(0);
        double eee = g1.lng * c * Math.cos(g1.lat * Hq);
        double g2 = g1.lat * c;
        double k = point.lng * c * Math.cos(point.lat * Hq);
        d += eee * point.lat * c - k * g2;
        return new BigDecimal( 0.5*Math.abs(d)).divide(new BigDecimal(1000000));
    }
    public static void main(String[] args) {
        List<Poi> poiList = new ArrayList<Poi>();
        //林和西地铁站
        poiList.add(new Poi(113.323947,23.141525));
        //五羊邨地铁站
        poiList.add(new Poi(113.314119,23.119977));
        //体育中心南地铁站
        poiList.add(new Poi(113.324247,23.134501));
        //猎德地铁站
        poiList.add(new Poi(113.331972,23.118477));

        BigDecimal area =  getArea(poiList);
        System.out.println( "面积:"+ area + "平方米" );

        //天河体育馆
        Poi inPoi = new Poi(113.323239,23.135428);
        //天河路
        Poi inPoi2 = new Poi(113.321522,23.13381);
        //黄埔大道
        Poi outPoi = new Poi(113.324462,23.127002);
        // 大剧院
        Poi outPoi2 = new Poi(113.324247,23.116188);
        // 天河中学
        Poi outPoi3 = new Poi(113.319773,23.121664);
        // 杨箕地铁站
        Poi outPoi4 = new Poi(113.307757,23.127249);

        System.out.println("inPoi是否在圈内:" + IsPtInPoly(inPoi.lng,inPoi.lat,poiList) );
        System.out.println("inPoi2是否在圈内:" + IsPtInPoly(inPoi2.lng,inPoi2.lat,poiList) );

        System.out.println("outPoi是否在圈内:" + IsPtInPoly(outPoi.lng,outPoi.lat,poiList) );
        System.out.println("outPoi2是否在圈内:" + IsPtInPoly(outPoi2.lng,outPoi2.lat,poiList) );
        System.out.println("outPoi3是否在圈内:" + IsPtInPoly(outPoi3.lng,outPoi3.lat,poiList) );
        System.out.println("outPoi4是否在圈内:" + IsPtInPoly(outPoi4.lng,outPoi4.lat,poiList) );
    }




    public static boolean IsPtInPoly(double ALon, double ALat, List<Poi> APoints)
    {
        int iSum = 0, iCount;
        double dLon1, dLon2, dLat1, dLat2, dLon;
        if (APoints.size() < 3)
            return false;
        iCount = APoints.size();
        for (int i = 0; i < iCount - 1; i++)
        {
            if (i == iCount - 1)
            {
                dLon1 = APoints.get(i).lng;
                dLat1 = APoints.get(i).lat;
                dLon2 = APoints.get(0).lng;
                dLat2 = APoints.get(0).lat;
            }
            else
            {
                dLon1 = APoints.get(i).lng;
                dLat1 = APoints.get(i).lat;
                dLon2 = APoints.get(i+1).lng;
                dLat2 = APoints.get(i+1).lat;
            }
            //以下语句判断A点是否在边的两端点的水平平行线之间，在则可能有交点，开始判断交点是否在左射线上
            if (((ALat >= dLat1) && (ALat < dLat2)) || ((ALat >= dLat2) && (ALat < dLat1)))
            {
                if (Math.abs(dLat1 - dLat2) > 0)
                {
                    //得到 A点向左射线与边的交点的x坐标：
                    dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - ALat)) / (dLat1 - dLat2);

                    // 如果交点在A点左侧（说明是做射线与边的交点），则射线与边的全部交点数加一：
                    if (dLon < ALon)
                        iSum++;
                }
            }
        }
        if (iSum % 2 != 0)
            return true;
        return false;
    }
}
