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 +
                '}';
    }

}

 

原文地址:http://www.cnblogs.com/mask-xiexie/p/16877712.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性