java 射线法 判断点和面的关系

package com.xx.common.core.utils.geography;

import com.alibaba.fastjson2.JSON;
import com.xx.common.core.baseweb.domain.Point;

import java.util.Arrays;
import java.util.List;

/**
 * @Description 射线法 判断点和面的关系
 * @Date 2022-11-04 15:55
 * @Author xie
 */
public class RayMethod {

    public static boolean ray(Point p, List<Point> poly) {
        double nx = p.getLon(); double ny = p.getLat();

        //计算射线穿过多边形的点的数目
        int cnt = 0;

        int len = poly.size();
        for (int i = 0, j = len - 1; i < len; j = i, ++i) {
            double bx = poly.get(i).getLon();
            double by = poly.get(i).getLat();
            double ux = poly.get(j).getLon();
            double uy = poly.get(j).getLat();

            //点与多边形顶点重合
            if ((nx == bx && ny == by) || (nx == ux && nx == uy)) {
                return true;
            }

            if ((by < ny && uy >= ny) || (by >= ny && uy < ny)) {
                //边上与点的坐标y相同的x坐标
                double x = bx + (ny - by) * (ux - bx) / (uy - by);

                //点在多边形的边上
                if (x == nx) {
                    return true;
                }

                if (x > nx) {
                    cnt += 1;
                }
            }
        }

        if (cnt % 2 == 1) {
            return true;
        } else {
            return false;
        }
    }


    public static boolean rayArrayPoint(double[] p, List<double[]> poly) {
        double nx = p[0]; double ny = p[1];

        //计算射线穿过多边形的点的数目
        int cnt = 0;

        int len = poly.size();
        for (int i = 0, j = len - 1; i < len; j = i, ++i) {
            double bx = poly.get(i)[0];
            double by = poly.get(i)[1];
            double ux = poly.get(j)[0];
            double uy = poly.get(j)[1];

            //点与多边形顶点重合
            if ((nx == bx && ny == by) || (nx == ux && nx == uy)) {
                return true;
            }

            if ((by < ny && uy >= ny) || (by >= ny && uy < ny)) {

                //边上与点的坐标y相同的x坐标
                double x = bx + (ny - by) * (ux - bx) / (uy - by);

                //点在多边形的边上
                if (x == nx) {
                    return true;
                }

                if (x > nx) {
                    cnt += 1;
                }
            }
        }

        if (cnt % 2 == 1) {
            return true;
        } else {
            return false;
        }
    }


    public static void main(String[] args) {

        Point p = new Point(116.756051906321, 43.084293983401146);

        Point pot1 = new Point(116.75602598549472, 43.084279337427155);
        Point pot2 = new Point(116.75603896966804, 43.08427934803498);
        Point pot3 = new Point(116.75603892382017, 43.08429398162957);
        Point pot4 = new Point(116.75602594131935, 43.084293979858);
        List<Point> poly = Arrays.asList(pot1, pot2, pot3, pot4);

        boolean flag = ray(p, poly);
        if (flag == true) {
            System.out.println("点在多边形内");
        } else {
            System.out.println("点不在多边形内");
        }

        double[] p1 = {116.756051906321, 43.084293983401146};
        String json = "[[116.75602598549472,43.084279337427155],[116.75603896966804,43.08427934803498],[116.75603892382017,43.08429398162957],[116.75602594131935,43.084293979858]]";
        List<double[]> poly1 = JSON.parseArray(json, double[].class);
        boolean flag1 = rayArrayPoint(p1, poly1);
        if (flag1 == true) {
            System.out.println("1点在多边形内");
        } else {
            System.out.println("1点不在多边形内");
        }
    }
}
package com.xx.common.core.baseweb.domain;

import lombok.Builder;
import lombok.Data;

/**
 * 内部类
 * 位置点(经纬度)
 * @author xie
 */
@Data
@Builder
public class Point {

    private static final long serialVersionUID = 1L;

    /**
     * 经度
     */
    double lon;
    /**
     * 纬度
     */
    double lat;

    public Point() {
    }

    public Point(double lon, double lat) {
        this.lon = lon;
        this.lat = lat;
    }

    @Override
    public String toString() {
        return "Point{" +
                "lon=" + lon +
                ", lat=" + lat +
                '}';
    }

}

 

posted @ 2022-11-10 17:08  xiexie0812  阅读(132)  评论(0编辑  收藏  举报