java - 计算两点之间地理距离的更快方法

标签 java optimization geolocation gps gis

我从互联网上的某个地方借用了以下方法(不记得在哪里)。但它做的是一个直接的过程,找到两个 gps 点之间的距离。它工作得很好,除了它可能有点慢,因为我在数百万个点上运行它。 我想知道是否有人知道一种计算成本更低的方法。

准确度需要在“正确”的一般范围内,但不需要 100% 准确。

private double distFrom(double lat1, double lng1, double lat2, double lng2) {
    double earthRadius = 3958.75;
    double dLat = Math.toRadians(lat2-lat1);
    double dLng = Math.toRadians(lng2-lng1);
    double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
           Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
           Math.sin(dLng/2) * Math.sin(dLng/2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    return   earthRadius * c;
  }
}

P.s 我确实发现了许多其他相关问题,但它们并没有真正关注我的速度问题。

最佳答案

如果您不介意忽略地球的轻微扁率(并且您发布的 Haversine 代码无论如何都会这样做)考虑将所有球面(纬度/经度)坐标预先转换为 3D 单位长度 首先是笛卡尔坐标,per:

http://en.wikipedia.org/wiki/Spherical_coordinate_system

那么笛卡尔坐标 p1p2 之间的球面距离就是:

r * acos(p1 . p2)

由于 p1p2 将具有单位长度,因此每对减少为四次乘法、两次加法和一次反三角运算。

另请注意,点积的计算是优化的理想选择,例如通过 GPU、MMX 扩展、 vector 库等。

此外,如果您的意图是按距离排序对,可能会忽略更远的对,您可以推迟等式中昂贵的 r*acos() 部分通过仅根据点积值对列表进行排序,因为对于所有有效输入(即范围 [-1, 1]),它保证:

acos(x) < acos(y) if x > y

然后您只需获取您实际感兴趣的值的 acos()

回复:使用 acos() 的潜在错误,只有在您使用单精度 float 变量时,这些错误才真正重要。使用具有 16 位有效数字的 double 可以使您的距离精确到一米或更小。

关于java - 计算两点之间地理距离的更快方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6409035/

相关文章:

java - Spring MVC传入参数 @RequestParam String requestURL

java - proguard:无法读取 [C:\Program Files\AdoptOpenJDK\jdk-11.0.6.10-hotspot\lib\rt.jar]

java - 在 GPS 上绘制到位置的轨迹

javascript - 如何在没有警报消息(iOS)的情况下获得 webview 中的地理定位权限?

iphone - 从坐标中获取位置名称?

java - 从 rfcomm0 读取数据

JAVAFX - 标签字段未在操作事件处理程序上更新

java - 多线程遍历二叉树

ios - EAGLContext_presentRenderBuffer 在 OpenGLES 压力测试中占用了大部分时间

sql - 查询内联与扁平化