language-agnostic - 如何计算球体上一点到线段的距离?

标签 language-agnostic geometry gis geospatial distance

我在地球上有一条线段(大圆部分)。线段由其端点的坐标定义。显然,两个点定义了两条线段,所以假设我对较短的线段感兴趣。

我得到了第三个点,我正在寻找线和点之间的(最短)距离。

所有坐标均以经度\纬度 (WGS 84) 形式给出。

如何计算距离?

任何合理的编程语言的解决方案都可以。

最佳答案

这是我自己的解决方案,基于 ask Dr. Math 中的想法.我很高兴看到您的反馈。

首先免责声明。此解决方案适用于球体。地球不是球体,坐标系 (WGS 84) 也不假定它是球体。所以这只是一个近似值,我无法真正估计是错误的。此外,对于非常小的距离,也可能通过假设一切都是共面的来获得良好的近似值。同样,我不知道距离必须有多“小”。

现在开始做生意。我将线的末端称为 A、B 和第三点 C。基本上,算法是:

  1. 首先将坐标转换为笛卡尔坐标(原点在地球中心)- e.g. here .

  2. 使用以下 3 个向量积计算 T,即直线 AB 上最接近 C 的点:

    G = A x B

    F = C x G

    T = G x F

  3. 归一化 T 并乘以地球半径。

  4. 将 T 转换回经度\纬度。

  5. 计算 T 和 C 之间的距离 - e.g. here .

如果您正在寻找 C 与 A 和 B 定义的大圆之间的距离,这些步骤就足够了。如果您像我一样对 C 与较短线段之间的距离感兴趣,则需要采取额外的步骤验证 T 确实在该段上。如果不是,那么最近的点必然是 A 端或 B 端之一 - 最简单的方法是检查哪一个。

一般而言,三个向量积背后的思想如下。第一个 (G) 为我们提供了 A 和 B 的大圆所在的平面(因此包含 A、B 和原点的平面)。第二个 (F) 给出了穿过 C 并垂直于 G 的大圆。然后 T 是由 F 和 G 定义的大圆的交点,通过归一化和乘以 R 得到正确的长度。

这里有一些用于执行此操作的部分 Java 代码。

寻找大圆上的最近点。输入和输出是长度为 2 的数组。中间数组的长度为 3。

double[] nearestPointGreatCircle(double[] a, double[] b, double c[])
{
    double[] a_ = toCartsian(a);
    double[] b_ = toCartsian(b);
    double[] c_ = toCartsian(c);

    double[] G = vectorProduct(a_, b_);
    double[] F = vectorProduct(c_, G);
    double[] t = vectorProduct(G, F);
    normalize(t);
    multiplyByScalar(t, R_EARTH);
    return fromCartsian(t);
}

寻找线段上最近的点:

double[] nearestPointSegment (double[] a, double[] b, double[] c)
{
   double[] t= nearestPointGreatCircle(a,b,c);
   if (onSegment(a,b,t))
     return t;
   return (distance(a,c) < distance(b,c)) ? a : c;
} 

这是一种简单的测试方法,我们知道点 T 与 A 和 B 在同一个大圆上,是否在这个大圆的较短线段上。然而,有更有效的方法来做到这一点:

   boolean onSegment (double[] a, double[] b, double[] t)
   {
     // should be   return distance(a,t)+distance(b,t)==distance(a,b), 
     // but due to rounding errors, we use: 
     return Math.abs(distance(a,b)-distance(a,t)-distance(b,t)) < PRECISION;
   }    

关于language-agnostic - 如何计算球体上一点到线段的距离?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28521058/

相关文章:

algorithm - 在给定范围内查找随机数,排除某些可能的数字

math - float 学有问题吗?

performance - 获得 π 值的最快方法是什么?

android - 如何将 CircleImageView 与 Volley 的 NetworkImageView 一起使用?

gis - 在 GeoDataFrame 中有超过 1 个几何列是不好的做法吗?

iphone - 为 MapKit 转换 "world file"GIS?

language-agnostic - 如何确定错误的优先级?

java - 找到正方形中最近的边界点

geometry - 多边形三角剖分的反面是什么?

python - 如何使用 Shapely 获取 MultiPolygon 内每个点的列表