You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java 11中判断com.mapbox.geojson.Point是否在Polygon内?

判断Mapbox GeoJSON Point是否在Polygon内的Java 11实现

嘿,我刚好之前处理过类似的需求,用Java 11判断Mapbox的Point是否在Polygon范围内其实可以通过实现经典的射线法来搞定——毕竟Mapbox的GeoJSON库本身好像没直接提供这个判断方法。下面给你具体的实现步骤和可直接复用的代码:

核心逻辑:射线法(Ray Casting Algorithm)

射线法的原理很简单:从目标点向右发射一条水平射线,统计这条射线与多边形边的交点数量。如果交点数是奇数,说明点在多边形内部;如果是偶数,则在外部。同时我们额外处理了点刚好在多边形边上的情况,直接返回true。

完整工具类代码

首先导入需要的Mapbox GeoJSON类,然后实现工具类:

import com.mapbox.geojson.Point;
import com.mapbox.geojson.Polygon;
import com.mapbox.geojson.Position;
import java.util.List;

public class GeoUtils {

    // 判断点是否在多边形内(包含边界)
    public static boolean isPointInPolygon(Point point, Polygon polygon) {
        Position pointPos = point.coordinates();
        double pointX = pointPos.longitude();
        double pointY = pointPos.latitude();

        // 获取多边形的外环坐标(第一个List是外环,后续List是内环/洞)
        List<Position> outerRing = polygon.coordinates().get(0);
        int vertexCount = outerRing.size();
        boolean inside = false;

        // 遍历多边形的每条边(j是i的前一个顶点,形成边j->i)
        for (int i = 0, j = vertexCount - 1; i < vertexCount; j = i++) {
            Position posI = outerRing.get(i);
            Position posJ = outerRing.get(j);
            double xi = posI.longitude(), yi = posI.latitude();
            double xj = posJ.longitude(), yj = posJ.latitude();

            // 先判断点是否在当前边上,是则直接返回true
            if (isPointOnLineSegment(pointX, pointY, xi, yi, xj, yj)) {
                return true;
            }

            // 核心判断:射线与当前边是否相交
            boolean intersects = ((yi > pointY) != (yj > pointY))
                    && (pointX < (xj - xi) * (pointY - yi) / (yj - yi) + xi);
            if (intersects) {
                inside = !inside;
            }
        }

        // 如果有内环(洞),需要额外判断点是否不在任何内环内
        for (int k = 1; k < polygon.coordinates().size(); k++) {
            List<Position> innerRing = polygon.coordinates().get(k);
            if (isPointInRing(pointX, pointY, innerRing)) {
                return false; // 点在洞里,返回不在多边形内
            }
        }

        return inside;
    }

    // 判断点是否在单条环(外环/内环)内(无边界判断,用于内环检测)
    private static boolean isPointInRing(double px, double py, List<Position> ring) {
        int vertexCount = ring.size();
        boolean inside = false;
        for (int i = 0, j = vertexCount - 1; i < vertexCount; j = i++) {
            Position posI = ring.get(i);
            Position posJ = ring.get(j);
            double xi = posI.longitude(), yi = posI.latitude();
            double xj = posJ.longitude(), yj = posJ.latitude();

            boolean intersects = ((yi > py) != (yj > py))
                    && (px < (xj - xi) * (py - yi) / (yj - yi) + xi);
            if (intersects) {
                inside = !inside;
            }
        }
        return inside;
    }

    // 判断点是否在线段上(处理边界情况)
    private static boolean isPointOnLineSegment(double px, double py, double x1, double y1, double x2, double y2) {
        // 先判断点是否在线段的包围盒内
        boolean withinXBounds = Math.min(x1, x2) - 1e-8 <= px && px <= Math.max(x1, x2) + 1e-8;
        boolean withinYBounds = Math.min(y1, y2) - 1e-8 <= py && py <= Math.max(y1, y2) + 1e-8;
        if (!withinXBounds || !withinYBounds) {
            return false;
        }

        // 计算叉积,判断点是否在直线上(考虑浮点精度)
        double crossProduct = (px - x1) * (y2 - y1) - (py - y1) * (x2 - x1);
        return Math.abs(crossProduct) < 1e-8;
    }
}

示例使用代码

你可以这样调用工具类来测试你的五边形和目标点:

public class GeoTest {
    public static void main(String[] args) {
        // 创建你要判断的目标点
        Point targetPoint = Point.fromLngLat(你的点经度, 你的点纬度);

        // 创建你的五边形Polygon(注意最后一个点要和第一个点重合,保证多边形闭合)
        List<Position> polygonVertices = List.of(
                Position.fromLngLat(点1经度, 点1纬度),
                Position.fromLngLat(点2经度, 点2纬度),
                Position.fromLngLat(点3经度, 点3纬度),
                Position.fromLngLat(点4经度, 点4纬度),
                Position.fromLngLat(点5经度, 点5纬度),
                Position.fromLngLat(点1经度, 点1纬度) // 闭合多边形
        );
        Polygon testPolygon = Polygon.fromLngLats(List.of(polygonVertices));

        // 调用判断方法
        boolean isInside = GeoUtils.isPointInPolygon(targetPoint, testPolygon);
        System.out.println("目标点是否在多边形内:" + isInside);
    }
}

额外说明

  • 内环处理:如果你的Polygon包含内环(比如带洞的多边形),上面的代码已经处理了这种情况——只要点在任何一个内环里,就会返回false。
  • 浮点精度:代码中用了1e-8作为精度阈值,你可以根据业务需求调整这个值,避免因为浮点计算误差导致判断错误。
  • 适用范围:这个算法适用于所有简单多边形(不自交的多边形),你的五边形只要是正常的非自交形状就完全没问题。

内容的提问来源于stack exchange,提问作者Dyst.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 21:32:45