判断一个点,是否在一个多边形区域内

package com.lxkj.project.location.utils;


import com.lxkj.project.location.domain.TCoordinatePoint;
import com.lxkj.project.location.domain.TLocationInfo;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 判断一个点,是否在一个多边形区域内
 */
public class MultiRectUtil {

    public static void main(String[] args) {

        double pyLng = 116.3383;
        double pxLat = 39.9147;

        ArrayList polygonYLng = new ArrayList();
        ArrayList polygonXLat = new ArrayList();

        polygonYLng.add(119.388572);
        polygonYLng.add(118.094802);
        polygonYLng.add(117.724194);
        polygonYLng.add(119.418956);
        polygonYLng.add(121.147316);
        polygonYLng.add(121.075774);
        polygonYLng.add(119.388572);

        polygonXLat.add(31.14423);
        polygonXLat.add(30.769938);
        polygonXLat.add(29.666748);
        polygonXLat.add(29.394196);
        polygonXLat.add(29.312862);
        polygonXLat.add(30.734536);
        polygonXLat.add(31.14423);

    }

    public static boolean isPointInPolygon(TLocationInfo locationInfo , List list) {
        double px = Double.parseDouble(locationInfo.getLatitude());
        double py = Double.parseDouble(locationInfo.getLongitude());
        return isPointInPolygon(px, py, list);
    }

    public static boolean isPointInPolygon(double px, double py, List pointList) {
        List>> districtList = new ArrayList>>();
        List polygonXLat = null;
        List polygonYLng = null;
        String startLat = null;
        String startLng = null;

        //获取区域列表
        for (TCoordinatePoint coordinatePoint : pointList) {

            //如果经度或纬度为空,则略过该点
            if (coordinatePoint.getLatitude() == null || coordinatePoint.getLatitude().trim().equals("") ||
                    coordinatePoint.getLongitude() == null || coordinatePoint.getLongitude().trim().equals("")) {
                continue;
            }

            //判断区域的起点和终点
            if (startLat == null || startLng == null) {
                startLat = coordinatePoint.getLatitude().trim();
                startLng = coordinatePoint.getLongitude().trim();
                polygonXLat = new ArrayList();
                polygonYLng = new ArrayList();
            } else if (startLat.equals(coordinatePoint.getLatitude().trim()) && startLng.equals(coordinatePoint.getLongitude().trim())) {
                startLat = null;
                startLng = null;
            }

            //新增区域点
            polygonXLat.add(Double.valueOf(coordinatePoint.getLatitude().trim()));
            polygonYLng.add(Double.valueOf(coordinatePoint.getLongitude().trim()));

            //如果到达终点,则判断为完整的区域
            if (startLat == null || startLng == null) {
                Map> districtPoint = new HashMap>();
                districtPoint.put("latitude", polygonXLat);
                districtPoint.put("longitude", polygonYLng);
                districtList.add(districtPoint);
            }
        }

        if (districtList.size() == 0 && polygonXLat != null && polygonYLng != null) {
            Map> districtPoint = new HashMap>();
            districtPoint.put("latitude", polygonXLat);
            districtPoint.put("longitude", polygonYLng);
            districtList.add(districtPoint);
        }

        //判断是否在区域中
        if (districtList.size() > 0) {
            for (Map> districtPoint : districtList) {
                boolean isInDistrict = isPointInPolygon(px, py, districtPoint.get("latitude"), districtPoint.get("longitude"));
                //只要这个点在某个区域中就判断为在区域中
                if (isInDistrict) return true;
            }
        }

        //返回不在区域中
        return false;
    }

//    public static boolean isPointInPolygon(double px, double py, List list) {
//        ArrayList polygonXLat = new ArrayList();
//        ArrayList polygonYLng = new ArrayList();
//        for (TCoordinatePoint coordinatePoint : list) {
//            polygonXLat.add(Double.valueOf(coordinatePoint.getLatitude().trim()));
//            polygonYLng.add(Double.valueOf(coordinatePoint.getLongitude().trim()));
//        }
//        //判断是否越界
//        boolean flag = isPointInPolygon(px, py, polygonXLat, polygonYLng);
//        /**
//         * 2021.10.29 应急处理:若越界,判断是否在允许误差范围内
//        if (!flag) {
//            //当判定越界时,与任意点的距离小于x米,均视为不越界
//            final double errorRange = 1000d;
//            flag = isWithinBoundaryErrorRange(px, py, polygonXLat, polygonYLng, errorRange);
//        }*/
//        return flag;
//    }

    /**
     *
     * @param px 纬度 lat
     * @param py 经度 lng
     * @param polygonXA 纬度 lat
     * @param polygonYA 经度 lng
     * @return
     */
    public static boolean isPointInPolygon(double px, double py, List polygonXA, List polygonYA) {
        if(polygonYA.size() > 0){//注意:必须把第一个点加入到尾部组成闭合
            if(polygonYA.get(polygonYA.size()-1).equals(polygonYA.get(0)) &&
                    polygonXA.get(polygonXA.size()-1).equals(polygonXA.get(0))){
                //已经是闭包
            }else{
                polygonYA.add(polygonYA.get(0));
                polygonXA.add(polygonXA.get(0));
            }
        }

        boolean isInside = false;
        double ESP = 1e-9;
        int count = 0;
        double linePoint1x;
        double linePoint1y;
        double linePoint2x = 180;
        double linePoint2y;

        linePoint1x = px;
        linePoint1y = py;
        linePoint2y = py;

        for (int i = 0; i < polygonXA.size() - 1; i++) {
            double cx1 = polygonXA.get(i);
            double cy1 = polygonYA.get(i);
            double cx2 = polygonXA.get(i + 1);
            double cy2 = polygonYA.get(i + 1);
            if (PointUtil.isPointOnLine(px, py, cx1, cy1, cx2, cy2)) {
                return true;
            }
            if (Math.abs(cy2 - cy1) < ESP) {
                continue;
            }

            if (PointUtil.isPointOnLine(cx1, cy1, linePoint1x, linePoint1y, linePoint2x, linePoint2y)) {
                if (cy1 > cy2)
                    count++;
            } else if (PointUtil.isPointOnLine(cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y)) {
                if (cy2 > cy1)
                    count++;
            } else if (PointUtil.isIntersect(cx1, cy1, cx2, cy2, linePoint1x, linePoint1y, linePoint2x, linePoint2y)) {
                count++;
            }
        }
        //System.out.println(count);
        if (count % 2 == 1) {
            isInside = true;
        }
        //System.out.println("判断点是否在区域里面:"+py+"--"+px+",结果:"+isInside);
        return isInside;
    }

    /**
     * 点距离区域边界最近距离是否在指定误差范围内
     * 要结合区域范围内外判断使用
     *
     * @param lat0
     * @param lng0
     * @param polygonLat
     * @param polygonLng
     * @param errorRange 米
     * @return
     */
    public static boolean isWithinBoundaryErrorRange(double lat0, double lng0, ArrayList polygonLat, ArrayList polygonLng, double errorRange) {
        if (errorRange < 0) {
            return false;
        }
        if (polygonLng.size() > 0) {//注意:必须把第一个点加入到尾部组成闭合
            if (polygonLng.get(polygonLng.size() - 1).equals(polygonLng.get(0)) && polygonLat.get(polygonLat.size() - 1).equals(polygonLat.get(0))) {
                //已经是闭包
            } else {
                polygonLng.add(polygonLng.get(0));
                polygonLat.add(polygonLat.get(0));
            }
        }
        boolean flag = false;
        for (int i = 0; i < polygonLat.size() - 1; i++) {
            double lat1 = polygonLat.get(i);
            double lng1 = polygonLng.get(i);
            double lat2 = polygonLat.get(i + 1);
            double lng2 = polygonLng.get(i + 1);

            double distance = PointUtil.getNearestDistance(lng0, lat0, lng1, lat1, lng2, lat2);
            if (Math.abs(distance) <= errorRange) {
                flag = true;
                break;
            }
        }
        return flag;
    }

}

你可能感兴趣的:(windows,java)