Algorithm 地球上点到线的距离

Algorithm 地球上点到线的距离,algorithm,gps,geometry,latitude-longitude,intersection,Algorithm,Gps,Geometry,Latitude Longitude,Intersection,我需要一些简单的 但这适用于Lon/Lat。我以前没有使用过Lon/Lat,但是。。 我会创建一个坐标系。地球的中心是原点。 将lon/lat位置转换为坐标系 做你的计算 转换回lon/lat我们将从一些假设开始: 我们将模型化为一个 我们所说的“线”是指a的小弧 我们正在寻找一个高度精确的解决方案(针对建议的模型) 那么,重新表述你的问题: 给定三个地球表面点——p0、p1和p2, 在p1和p2定义的大圆的小弧上找到一个地球表面点,该点最接近p0。 作为解决方案的基础架构,我们需要:

我需要一些简单的


但这适用于Lon/Lat。

我以前没有使用过Lon/Lat,但是。。 我会创建一个坐标系。地球的中心是原点。 将lon/lat位置转换为坐标系 做你的计算
转换回lon/lat

我们将从一些假设开始:

  • 我们将模型化为一个
  • 我们所说的“线”是指a的小弧
  • 我们正在寻找一个高度精确的解决方案(针对建议的模型)
那么,重新表述你的问题:

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

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

  • 基于初始点、初始方位角和距离查找目标点的精确函数
  • 测量两点之间距离的精确函数
我建议分别使用的正函数和反函数,这是我所知道的最准确的实现

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

作为第一步,我们将尝试了解一个图形,其中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)我将使用几何(而不是分析)方法详细阐述Lior Kogan的优秀答案

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


    现在,我们正在寻找与现有平面正交的平面,通过p0。这很容易计算,该平面与球体的交点应该(警告:我有点匆忙,不确定这一步在数学上是否合理)是与“线”正交的大圆。圆弧的交点应该是您要查找的点,可以计算为两个平面(与每个平面正交的向量的叉积)和球体的公共线的截取。

    谢谢您试图教我,但我要求的是一个简单实用的解决方案。不是数学课

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

    看这里:

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


    就是这样。我们用几行代码完成。没有迭代。没有额外的libs。Lean和mean。

    你有一条穿过地球表面点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;
    }
    
    计算两点之间距离的算法是众所周知的。有很多实现。其中一个(如前面的答案所示)可以在那里找到

    对于计算三角形面积,您可以使用一些依赖于线长度的算法

    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;
    }
    

    Ilya Golota的答案是正确的,但事实证明,即使距离直线2米的点,它也会返回一个非常大的数字,如“3.0355243098445522e12”。我这样做是为了计算三角形面积:

    double d0 = computeDistanceBetween(p0, p1);
    double d1 = computeDistanceBetween(p1, p2);
    double d2 = computeDistanceBetween(p2, p0);
    
    (使用Heron公式)

    然后在这里插入面积值

    double distanceToLine = 2*area/computeDistanceBetween(line.startPoint, line.endPoint)
    

    <>这对于我来说是很好的,并且返回了从点到线的垂直距离。

    这是不考虑的,除此之外,地球上的距离通常不是直线计算的,而是在地球表面上延伸的弧,也可以从大地测量(LAT/Lon)转换为地球中心,地球固定。(ECEF)很容易。从ECEF转换为大地测量并不容易。一个快速的草图似乎可以确认这应该在不进行迭代的情况下产生正确的结果。我想在一个点上可能会出现一些问题,其中大地水准面与通过该点和原点的向量不垂直。我可以请您分享一些代码如何计算吗?我已经完成了在尝试创建正常工作的内容时损失了大约一周。我将不胜感激。这是堆栈溢出的工作原理:提供答案,而不是链接。欢迎提供指向解决方案的链接,但请确保您的答案在没有它的情况下是有用的:这样您的其他用户将了解它是什么以及为什么存在,然后引用最相关的部分在目标页面不可用的情况下,你链接到的页面的曲率。这没有考虑地球的曲率。距离越长,它就越不准确。
    double distanceToLine = 2*area/computeDistanceBetween(line.startPoint, line.endPoint)