package com.ssyf.common.core.util;

import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 经纬度点位工具
 *
 * @author Administrator
 * @date 2019/8/13
 * 电子围栏计算
 */
public class MapRangeUtil {
    /**
     * 地球平均半径（单位：米）
     */
    private static final double EARTH_AVG_RADIUS = 6371000;

    /**
     * 经纬度转化为弧度(rad)
     *
     * @param d 经度/纬度
     */
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 方法三：（基于googleMap中的算法得到两经纬度之间的距离,计算精度与谷歌地图的距离精度差不多。）
     *
     * @param longitude1 第一点的经度
     * @param latitude1  第一点的纬度
     * @param longitude2 第二点的经度
     * @param latitude2  第二点的纬度
     * @return 返回的距离，单位m
     */
    public static double calculateHaversine(double longitude1, double latitude1, double longitude2, double latitude2) {
        double radLat1 = rad(latitude1);
        double radLat2 = rad(latitude2);
        double a = radLat1 - radLat2;
        double b = rad(longitude1) - rad(longitude2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_AVG_RADIUS;
        s = Math.round(s * 10000d) / 10000d;
        return s;
    }

    /**
     * 判断点是否坐落于多边形内
     * 注意：：： 多边形的坐标点必须依次顺序传入
     *
     * @param point
     * @param polygonPoints
     * @return
     */
    public static boolean isInPolygon(Point2D.Double point, Point2D.Double[] polygonPoints) {
        List<Point2D.Double> polygonPointList = new ArrayList<>();
        for (int i = 0; i < polygonPoints.length; ++i) {
            polygonPointList.add(polygonPoints[i]);
        }
        return isInPolygon(point, polygonPointList);
    }

    public static boolean isInPolygon(Point2D.Double point, List<Point2D.Double> polygonPointList) {
        if (polygonPointList.size() < 3) {
            return false;
        }
        List<Double> xs = new ArrayList<>(polygonPointList.size());
        List<Double> ys = new ArrayList<>(polygonPointList.size());
        for (int i = 0; i < polygonPointList.size(); ++i) {
            xs.add(polygonPointList.get(i).getX());
            ys.add(polygonPointList.get(i).getY());
        }
        //排序
        Collections.sort(xs);
        Collections.sort(ys);

        if (point.getX() < xs.get(0).doubleValue() || point.getX() > xs.get(xs.size() - 1).doubleValue()) {
            return false;
        }
        if (point.getY() < ys.get(0).doubleValue() || point.getY() > ys.get(ys.size() - 1).doubleValue()) {
            return false;
        }
        int i, j;
        boolean c = false;
        for (i = 0, j = polygonPointList.size() - 1; i < polygonPointList.size(); j = i++) {
            if ((polygonPointList.get(i).getY() >= point.getY()) != (polygonPointList.get(j).getY() >= point.getY()) &&
                    (point.getX() <= (polygonPointList.get(j).getX() - polygonPointList.get(i).getX()) * (point.getY() - polygonPointList.get(i).getY()) / (polygonPointList.get(j).getY() - polygonPointList.get(i).getY()) + polygonPointList.get(i).getX())) {
                c = !c;
            }
        }
        return c;
    }

}