JAVA判断某一点是否在任意多边形内(亲测)

一:原理及方法

1、先将横纵坐标数组的横坐标最大最小值,纵坐标的最大最小值,求出来,需要判断的一点大于横纵坐标的最大值或者小于横纵坐标的最小值,也就是粗略的计算一下,如果这个条件不满足的话,就不用往下计算了,直接不在指定的区域里面。
JAVA判断某一点是否在任意多边形内(亲测)_第1张图片
如果通过了上面的判断,可以进行接下来的算法判断了

/**
     * 判断该地理坐标是否在最大范围区域内
     * 
     * @param pointLon
     *            要判断的点的纵坐标
     * @param pointLat
     *            要判断的点的横坐标
     * @param lon
     *            指定区域的纵坐标组成的数组
     * @param lat
     *            指定区域的横坐标组成的数组
     * @return
     */
    private static boolean isInMaxArea(double pointLon, double pointLat, double[] lon,
            double[] lat) {
 
        // 获取区域横纵坐标最大值和最小值
        double temp = 0.0;
        for (int i = 0; i < lon.length; i++) {
            for (int j = 0; j < lon.length - i - 1; j++) {
                if (lon[j] > lon[j + 1]) {
                    temp = lon[j];
                    lon[j] = lon[j + 1];
                    lon[j + 1] = temp;
                }
            }
        }
        for (int i = 0; i < lat.length; i++) {
            for (int j = 0; j < lat.length - i - 1; j++) {
                if (lat[j] > lat[j + 1]) {
                    temp = lat[j];
                    lat[j] = lat[j + 1];
                    lat[j + 1] = temp;
                }
            }
        }
 
        // 如果在最值组成的区域外,那肯定不在重点区域内
        return (pointLon < lon[0] || pointLon > lon[lon.length - 1] || pointLat < lat[0]
                || pointLat > lat[lat.length - 1]);
    }

2、通过一点,画一条线,这条线与多边形相交,如果相交点数位奇数,就在区域内,如果为偶数,就不在区域内。这也是一种比较简单实用的方法(亲测)

  *java实现方法*如下:
             
     /**
     * 判断点是否在多边形内
     * @param point 检测点
     * @param pts   多边形的顶点
     * @return      点在多边形内返回true,否则返回false
     */
    public static boolean IsPtInPoly(Point2D.Double point, List<Point2D.Double> pts){

        int N = pts.size();
        boolean boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
        int intersectCount = 0;//cross points count of x
        double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
        Point2D.Double p1, p2;//neighbour bound vertices
        Point2D.Double p = point; //当前点

        p1 = pts.get(0);//left vertex
        for(int i = 1; i <= N; ++i){//check all rays
            if(p.equals(p1)){
                return boundOrVertex;//p is an vertex
            }

            p2 = pts.get(i % N);//right vertex
            if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){//ray is outside of our interests
                p1 = p2;
                continue;//next ray left point
            }

            if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){//ray is crossing over by the algorithm (common part of)
                if(p.y <= Math.max(p1.y, p2.y)){//x is before of ray
                    if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){//overlies on a horizontal ray
                        return boundOrVertex;
                    }

                    if(p1.y == p2.y){//ray is vertical
                        if(p1.y == p.y){//overlies on a vertical ray
                            return boundOrVertex;
                        }else{//before ray
                            ++intersectCount;
                        }
                    }else{//cross point on the left side
                        double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;//cross point of y
                        if(Math.abs(p.y - xinters) < precision){//overlies on a ray
                            return boundOrVertex;
                        }
                        if(p.y < xinters){//before ray
                            ++intersectCount;
                        }
                    }
                }
            }else{//special case when ray is crossing through the vertex
                if(p.x == p2.x && p.y <= p2.y){//p crossing over p2
                    Point2D.Double p3 = pts.get((i+1) % N); //next vertex
                    if(p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)){//p.x lies between p1.x & p3.x
                        ++intersectCount;
                    }else{
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2;//next ray left point
        }

        if(intersectCount % 2 == 0){//偶数在多边形外
            return false;
        } else { //奇数在多边形内
            return true;
        }

    }

测试实例如下:


```java
  public static void main(String[] args) {
        Point2D.Double point = new Point2D.Double(119.245584,39.068196);//测试点位坐标
        // 多边形关键点位
        String Coordinates="17.24432,39.076508,119.24402,39.058515;113.24402,37.0717652,178.2653,39.256876// 此处要注意数据的类型问题(如果不存在类型问题请忽略)
       // Coordinates= Coordinates.replace(";","[]");
        String Coordinateslist[] = Coordinates.split(",");
        List<Point2D.Double> pts = new ArrayList<Point2D.Double>();
        // 遍历填入值
        if(Coordinateslist.length%2==0){
            for (int i = 0;i<Coordinateslist.length/2;i++){
                int min  = i*2;
                int max  =i*2+1;
                pts.add(new Point2D.Double(Double.parseDouble(Coordinateslist[min]), Double.parseDouble(Coordinateslist[max])));
            }
        }
 
        if(IsPtInPoly(point, pts)){
            System.out.println("测试坐标在多边形里面");
        }else{
            System.out.println("测试坐标在多边形外面");
        }
    }

你可能感兴趣的:(java,算法,开发语言)