package com.sqx.modules.utils;


import com.sqx.common.entity.WMPoint;

import java.util.List;

public class GeoFenceUtil {

    /**
     * 判断点是否在多边形内
     * @param point 测试点
     * @param pts   多边形的点
     * @return boolean true:在多边形内, false:在多边形外
     */
    public static boolean isInPolygon(WMPoint point, List<WMPoint> pts) {
        int N = pts.size();
        int intersectCount = 0;//交叉点数量
        double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
        WMPoint p1, p2;//临近顶点
        p1 = pts.get(0);
        for (int i = 1; i <= N; ++i) {
            if (point.equals(p1)) {
                return true;
            }

            p2 = pts.get(i % N);
            if (point.getLng() < Math.min(p1.getLng(), p2.getLng()) || point.getLng() > Math.max(p1.getLng(), p2.getLng())) {
                p1 = p2;
                continue;
            }

            //射线穿过算法
            if (point.getLng() > Math.min(p1.getLng(), p2.getLng()) && point.getLng() < Math.max(p1.getLng(), p2.getLng())) {
                if (point.getLat() <= Math.max(p1.getLat(), p2.getLat())) {
                    if (p1.getLng() == p2.getLng() && point.getLat() >= Math.min(p1.getLat(), p2.getLat())) {
                        return true;
                    }

                    if (p1.getLat() == p2.getLat()) {
                        if (p1.getLat() == point.getLat()) {
                            return true;
                        } else {
                            ++intersectCount;
                        }
                    } else {
                        double xinters = (point.getLng() - p1.getLng()) * (p2.getLat() - p1.getLat()) / (p2.getLng() - p1.getLng()) + p1.getLat();
                        if (Math.abs(point.getLat() - xinters) < precision) {
                            return true;
                        }

                        if (point.getLat() < xinters) {
                            ++intersectCount;
                        }
                    }
                }
            } else {
                if (point.getLng() == p2.getLng() && point.getLat() <= p2.getLat()) {
                    WMPoint p3 = pts.get((i + 1) % N);
                    if (point.getLng() >= Math.min(p1.getLng(), p3.getLng()) && point.getLng() <= Math.max(p1.getLng(), p3.getLng())) {
                        ++intersectCount;
                    } else {
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2;
        }
        return intersectCount % 2 != 0;
    }
}
