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

如何判断lat/lon经纬度点是否落在另一坐标点的指定半径范围内

问题结论

针对你给出的示例参数,设备A到位置B的球面距离约为5.8英里,在10英里的覆盖半径范围内。

实现方案选型

这类球面点和圆形覆盖范围的判定,最实用高效的方案是Haversine公式计算大圆距离,适配绝大多数LBS覆盖判定场景:

  • 计算量极小,无第三方依赖,三种语言都可以原生实现,单线程每秒可完成数十万次判定,性能完全满足高并发业务需求
  • 针对地球球面曲率做了修正,中低纬度100公里范围内的距离误差小于10米,完全匹配10英里半径的判定精度要求
  • 不需要对接专业GIS服务,部署和维护成本为0

如果你的业务要求厘米级精度(比如测绘场景),再考虑替换为Vincenty椭球公式,普通到店、附近的人、电子围栏类场景完全不需要。

实现注意事项
  • 所有经纬度传入三角函数计算前,必须先从角度值转为弧度值,否则计算结果完全错误
  • 单位保持统一:计算英里为单位的距离时,地球平均半径取3956英里;如果要算公里单位,替换为6371即可
  • 临界值判定建议增加10米左右的容差,避免浮点精度误差导致边界点判定错误
  • 跨180度经线的场景,计算经度差时要做修正:如果两点经度差绝对值大于180度,用360减去该绝对值再参与计算
  • 超大规模点批量判定场景,可以先做矩形预过滤:先计算半径对应的经纬度差值范围,超出范围的点直接判定为不在覆盖内,减少三角函数计算量
多语言代码实现

Python 版本

import math

def is_in_coverage(lat_a: float, lon_a: float, lat_b: float, lon_b: float, radius_mile: float) -> bool:
    EARTH_RADIUS_MILE = 3956
    # 角度转弧度
    lat_a_rad = math.radians(lat_a)
    lat_b_rad = math.radians(lat_b)
    d_lat = lat_b_rad - lat_a_rad
    d_lon = math.radians(lon_b - lon_a)

    # Haversine公式计算距离
    a = math.sin(d_lat / 2) ** 2 + math.cos(lat_a_rad) * math.cos(lat_b_rad) * math.sin(d_lon / 2) ** 2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
    distance = EARTH_RADIUS_MILE * c
    # 增加0.006英里(约10米)容差,规避浮点误差
    return distance <= radius_mile + 0.006

if __name__ == "__main__":
    # 测试示例参数
    print(is_in_coverage(40.7128, -74.0060, 40.730610, -73.935242, 10))
    # 输出:True

JavaScript 版本

function isInCoverage(latA, lonA, latB, lonB, radiusMile) {
    const EARTH_RADIUS_MILE = 3956;
    const toRad = deg => deg * Math.PI / 180;
    const latARad = toRad(latA);
    const latBRad = toRad(latB);
    const dLat = latBRad - latARad;
    const dLon = toRad(lonB - lonA);

    const a = Math.sin(dLat / 2) ** 2 + Math.cos(latARad) * Math.cos(latBRad) * Math.sin(dLon / 2) ** 2;
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    const distance = EARTH_RADIUS_MILE * c;
    // 增加10米左右容差
    return distance <= radiusMile + 0.006;
}

// 测试示例参数
console.log(isInCoverage(40.7128, -74.0060, 40.730610, -73.935242, 10))
// 输出:true

Java 版本

public class GeoCoverageUtil {
    private static final double EARTH_RADIUS_MILE = 3956;
    private static final double TOLERANCE = 0.006; // 10米容差,单位英里

    private static double toRad(double degree) {
        return degree * Math.PI / 180;
    }

    public static boolean isInCoverage(double latA, double lonA, double latB, double lonB, double radiusMile) {
        double latARad = toRad(latA);
        double latBRad = toRad(latB);
        double dLat = latBRad - latARad;
        double dLon = toRad(lonB - lonA);

        double a = Math.pow(Math.sin(dLat / 2), 2)
                + Math.cos(latARad) * Math.cos(latBRad) * Math.pow(Math.sin(dLon / 2), 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double distance = EARTH_RADIUS_MILE * c;

        return distance <= radiusMile + TOLERANCE;
    }

    public static void main(String[] args) {
        System.out.println(isInCoverage(40.7128, -74.0060, 40.730610, -73.935242, 10));
        // 输出:true
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 23:48:39