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

如何在Android Studio中用Java解决Google Map多边形重叠问题

在Android Studio中用Java检测Google Map多边形重叠的方案

Google Maps Android SDK没有提供直接的多边形重叠检测接口,我们可以通过几何计算实现,核心思路是验证两个多边形是否存在顶点互斥在对方内部,或者边互相相交。以下是具体实现步骤和代码:

1. 坐标转换:经纬度转平面坐标

直接使用经纬度(球面坐标)计算几何关系会有误差,先将LatLng转换为墨卡托投影的平面坐标(单位:米),保证计算准确性:

// 将LatLng转换为墨卡托投影平面坐标
private PointF latLngToMercator(LatLng latLng) {
    double mercatorX = latLng.longitude * 20037508.34 / 180;
    double latRad = Math.toRadians(latLng.latitude);
    double mercatorY = Math.log(Math.tan((90 + latLng.latitude) * Math.PI / 360)) * 20037508.34 / Math.PI;
    return new PointF((float) mercatorX, (float) mercatorY);
}

2. 点在多边形内的判断(射线法)

用射线法判断一个点是否落在多边形内部,只要任意一个多边形的顶点在另一个多边形内,即可判定重叠:

// 射线法判断点是否在多边形内部
private boolean isPointInPolygon(PointF point, List<PointF> polygonPoints) {
    int intersectCount = 0;
    int vertexCount = polygonPoints.size();
    
    for (int i = 0; i < vertexCount; i++) {
        PointF p1 = polygonPoints.get(i);
        PointF p2 = polygonPoints.get((i + 1) % vertexCount);
        
        // 先判断点是否在多边形边上
        if (isPointOnSegment(point, p1, p2)) {
            return true;
        }
        
        // 检查射线与当前边是否相交
        if ((p1.y > point.y) != (p2.y > point.y)) {
            double xIntersect = (point.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
            if (point.x <= xIntersect) {
                intersectCount++;
            }
        }
    }
    // 交点数为奇数则在内部
    return intersectCount % 2 == 1;
}

// 判断点是否在线段上
private boolean isPointOnSegment(PointF point, PointF p1, PointF p2) {
    return point.x <= Math.max(p1.x, p2.x) && point.x >= Math.min(p1.x, p2.x)
            && point.y <= Math.max(p1.y, p2.y) && point.y >= Math.min(p1.y, p2.y)
            && crossProduct(p1, point, p2) == 0;
}

// 计算叉积,用于判断点与线段的位置关系
private float crossProduct(PointF a, PointF b, PointF c) {
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}

3. 线段相交判断

检查两个多边形的所有边是否存在相交情况,只要有一组边相交,即可判定重叠:

// 判断两条线段是否相交(包含端点在对方线段上的情况)
private boolean doSegmentsIntersect(PointF a1, PointF a2, PointF b1, PointF b2) {
    float cross1 = crossProduct(a1, a2, b1);
    float cross2 = crossProduct(a1, a2, b2);
    float cross3 = crossProduct(b1, b2, a1);
    float cross4 = crossProduct(b1, b2, a2);
    
    // 跨立实验:两条线段互相跨立对方
    boolean segmentsCross = (cross1 * cross2 < 0) && (cross3 * cross4 < 0);
    // 检查端点是否在对方线段上
    boolean pointOnSegment = isPointOnSegment(b1, a1, a2) || isPointOnSegment(b2, a1, a2)
            || isPointOnSegment(a1, b1, b2) || isPointOnSegment(a2, b1, b2);
    
    return segmentsCross || pointOnSegment;
}

4. 综合判断多边形重叠

整合上述方法,完成两个Google Map多边形的重叠检测:

// 对外暴露的方法:判断两个Polygon是否重叠
public boolean doPolygonsOverlap(Polygon polygon1, Polygon polygon2) {
    // 转换两个多边形的顶点为平面坐标
    List<PointF> poly1Points = new ArrayList<>();
    for (LatLng latLng : polygon1.getPoints()) {
        poly1Points.add(latLngToMercator(latLng));
    }
    
    List<PointF> poly2Points = new ArrayList<>();
    for (LatLng latLng : polygon2.getPoints()) {
        poly2Points.add(latLngToMercator(latLng));
    }
    
    // 检查多边形1的顶点是否在多边形2内
    for (PointF point : poly1Points) {
        if (isPointInPolygon(point, poly2Points)) {
            return true;
        }
    }
    
    // 检查多边形2的顶点是否在多边形1内
    for (PointF point : poly2Points) {
        if (isPointInPolygon(point, poly1Points)) {
            return true;
        }
    }
    
    // 检查两个多边形的边是否相交
    int poly1VertexCount = poly1Points.size();
    int poly2VertexCount = poly2Points.size();
    for (int i = 0; i < poly1VertexCount; i++) {
        PointF a1 = poly1Points.get(i);
        PointF a2 = poly1Points.get((i + 1) % poly1VertexCount);
        for (int j = 0; j < poly2VertexCount; j++) {
            PointF b1 = poly2Points.get(j);
            PointF b2 = poly2Points.get((j + 1) % poly2VertexCount);
            if (doSegmentsIntersect(a1, a2, b1, b2)) {
                return true;
            }
        }
    }
    
    // 所有检查都不满足则不重叠
    return false;
}

注意事项

  • 性能优化:如果需要批量检测多边形重叠,建议先通过getBounds()获取多边形的边界框,快速排除明显不重叠的多边形,再进行精确计算。
  • 凹多边形支持:上述算法对凸、凹多边形都有效,无需额外处理。
  • 边界场景:完全包含、共享边/顶点等场景都会被正确判定为重叠。

内容的提问来源于stack exchange,提问作者Pooja Wagh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 13:23:11