地球上点到线的距离

时间:2011-10-18 05:56:57

标签: algorithm gps geometry latitude-longitude intersection

我需要像

这样简单的东西

"Subject 1.02: How do I find the distance from a point to a line?"

但这适用于Lon / Lat。

6 个答案:

答案 0 :(得分:8)

我们将从一些假设开始:

所以,重新提出你的问题:

给定三个地表点 - p0,p1和p2, 在由p1和p2定义的大圆的小弧上找到一个地球表面点,它与p0最接近。

作为解决方案的基础架构,我们需要:

  • 基于初始点,初始方位角和距离找到目标点的精确函数。
  • 测量两点之间距离的准确函数。

我建议分别使用GeographicLib的直接和反向函数,这是我所知道的最准确的实现。

由于扁球体计算中涉及的数学是高度非线性的,我们将构建一个迭代解决方案。

作为第一步,我们将尝试理解X轴是由p1和p2定义的大圆的次弧上的点的图形,Y轴是从p0到该点的距离 - 可能看起来像:

这样的图形可能有几种选择:函数可能单调递增或单调递减。它也可能包含单个点,其一阶导数可能为0.它可能是最小值(非常微不足道),但也可能是最大值(例如 - 如果Lat(p0)= 0,则Lat(p1)= 100和Lat(p2)= - 100)。但是,在所有情况下,导数变化都有0或1个点。

理解这一点,我们现在可以构建一个迭代算法。在每次迭代中:

我们将计算dist(p0,p1),dist(p0,p2)以及dist(p0,pM),其中M是p1和p2之间的中点,位于由大圆定义的小圆弧上p1和p2。现在。我们会检查:

  • if(dist(p0,p1)< = dist(p0,pM))&& (dist(p0,pM)< = dist(p0,p2)) - p0比p2更接近p1
  • if(dist(p0,p2)< = dist(p0,pM))&& (dist(p0,pM)< = dist(p0,p1)) - p0比p1更接近p2
  • if(dist(p0,p1)< = dist(p0,p2))&& (dist(p0,p2)< = dist(p0,pM)) - p0是p1
  • if(dist(p0,p2)< = dist(p0,p1))&& (dist(p0,p1)< = dist(p0,pM)) - p0是p2

否则,我们无法确定最小值是否接近p1或p2,因此我们将再使用两个点进行检查:我们将pL定义为p1和pM之间的中点,pN为pM和p2之间的中点。现在,

  • if(dist(p0,pL)< = dist(p0,pM)) - p0更接近p1
  • if(dist(p0,pN)< = dist(p0,pM)) - p0更接近p2

否则 - p0在pL和pN之间。

因此,在每次迭代中,我们将寻找解决方案的弧长减半。

使用这种方法,我们可以在不到30次迭代中获得1 cm的精度。

答案 1 :(得分:4)

我将通过使用几何(而非分析)方法详细阐述Lior Kogan的优秀答案。

包含“线”的大圆位于穿过球体中心的平面上。该平面与作为通过原点的矢量和p1和p2的交叉积得到的矢量正交。

现在,我们正在寻找与我们所拥有的平面正交的平面,通过p0。这可以很容易地计算出来,并且这个平面与球体的交点应该是(警告:我有点匆忙,我不确定这一步是数学上的声音)是大圆正交到了“线”。弧的交点应该是您要寻找的点,并且可以计算为截取两个平面共有的线(与每个平面正交的矢量的交叉积)和球体。

答案 2 :(得分:1)

谢谢你试图教我,但我已经要求一个简单实用的解决方案。不是数学教学:)

无论如何,这是一个简单的答案:

请看这里:http://www.movable-type.co.uk/scripts/latlong.html

计算“方位”(从线的起点到每个我想知道的点距离)+“串扰距离”。

就是这样。我们完成了几行代码。没有迭代。没有附加的libs。精益和卑鄙

答案 3 :(得分:-1)

我之前没有和lon / lat合作过但是.. 我会创建一个坐标系。地球的中心是起源。 将lon / lat位置转换为坐标系 做你的计算 转换回lon / lat

答案 4 :(得分:-1)

你有一条通过地球表面A和B的线以及一个你想要计算距离的点C.

您可以计算三角形ABC的面积,将其除以A和B之间的距离,然后乘以2.

function computeDistanceToLine(p, line) {
    var length = computeDistanceBetween(line.startPoint, line.endPoint);
    var triangleArea = computeTriangleArea(p, line.startPoint, line.endPoint);
    return 2 * triangleArea / length;
}

计算两点之间距离的算法是众所周知的。有很多实现。其中一个(如前面的答案中所述)可以在http://www.movable-type.co.uk/scripts/latlong.html

找到

对于计算三角形区域,您可以使用某些依赖于线长度的算法。例如

function computeTriangleArea(p0, p1, p2) {
    var r = 6378137;

    var d0 = computeDistanceBetween(p0, p1);
    var d1 = computeDistanceBetween(p1, p2);
    var d2 = computeDistanceBetween(p2, p0);

    var halfPerimeter = (d0 + d1 + d2) * 0.5;

    var t = Math.tan(halfPerimeter) *
        Math.tan((halfPerimeter - d0) * 0.5) *
        Math.tan((halfPerimeter - d1) * 0.5) *
        Math.tan((halfPerimeter - d2) * 0.5);

    return 4 * Math.atan(Math.sqrt(Math.abs(t))) * r * r;
}

答案 5 :(得分:-1)

Ilya Golota的答案是正确的方法,但事实证明它总会返回一个非常大的数字,如" 3.0355243098445522e12"即使是距离线路2米的点。我这样做是为了计算三角形区域:

@media (max-width: 768px) and (orientation: landscape) {
    #container-div {
        width: 100vh;
    }
}

(使用Heron&#39的公式)

double d0 = computeDistanceBetween(p0, p1);
double d1 = computeDistanceBetween(p1, p2);
double d2 = computeDistanceBetween(p2, p0);

然后插入区域值

double area = Math.sqrt(halfP*(halfP-d0)*(halfP-d1)*(halfP-d2));

这适用于我,并返回从点到线的垂直距离(以米为单位)。