答案 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。现在。我们会检查:
否则,我们无法确定最小值是否接近p1或p2,因此我们将再使用两个点进行检查:我们将pL定义为p1和pM之间的中点,pN为pM和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));
这适用于我,并返回从点到线的垂直距离(以米为单位)。