使用纬度、经度和高程(海拔)计算两点之间的距离

3

我正在尝试使用纬度、经度和高度(海拔)计算两点之间的距离。

为了得出距离,我使用了欧几里得公式:

D=√((Long1-Long2)²+(Lat1-Lat2)²+(Alt1-Alt2)²)

我的点是地理坐标,当然高度是我距海面的高度。我只有纬度和经度,我正在使用GOOGLE API Elevation来获取我的高度。
我正在开发一个应用程序,计算我滑雪时行驶的距离。我使用过的每个应用程序都会获取包括高度在内的行驶距离。例如#Endomondo或#Garmin,我无法在2D空间中获取我的距离,因为真实距离将与我返回的距离不同。
哪种公式最适合计算我的距离?当然要包括高度。
我正在使用Python和PostGis编写我的应用程序。

2
为什么不将坐标存储在Postgis中并使用ST_distance函数呢? - Tom-db
有几篇文章质疑Garmin和其他公司在计算中使用海拔高度的说法。http://www.trailhunger.com/info/articles/garmin-distance-calculation 。在你提供的方程式中,你将度数和米数结合在一起。 - e4c5
嘿,@sebb,你找到任何有用的答案了吗? - John Moutafis
3个回答

4

您可以使用 geopy 软件包或 Vincenty的公式,直接粘贴坐标,计算平面坐标之间的距离(以米为单位)。 假设结果为 d 米,则旅行的总距离为 sqrt(d ** 2 + h ** 2),其中 h 是以米为单位的高度变化。


3
我使用了John Moutafis提供的解决方案,但没有得到正确的答案。该公式需要做些修正。您可以在http://electron9.phys.utk.edu/vectors/3dcoordinates.htm上获取从极坐标到笛卡尔坐标(x、y、z)的转换。 使用以上公式将球面坐标(极坐标)转换为笛卡尔坐标,并计算欧几里得距离。 我在控制台应用程序中使用了以下C#代码。 考虑以下虚拟纬度和经度。
       double lat_1 = 18.457793 * (Math.PI / 180);
       double lon_1 = 73.3951930277778 *(Math.PI/180);
       double alt_1 = 270.146;

       double lat_2 = 18.4581253333333 * (Math.PI / 180);
       double lon_2 = 73.3963755277778 * (Math.PI / 180);
       double alt_2 = 317.473;

       const Double r = 6376.5 *1000; // Radius of Earth in metres

       double x_1 = r * Math.Sin(lon_1) * Math.Cos(lat_1);
       double y_1 = r * Math.Sin(lon_1) * Math.Sin(lat_1);
       double z_1 = r * Math.Cos(lon_1);

       double x_2 = r * Math.Sin(lon_2) * Math.Cos(lat_2);
       double y_2 = r * Math.Sin(lon_2) * Math.Sin(lat_2);
       double z_2 = r * Math.Cos(lon_2);

       double dist = Math.Sqrt((x_2 - x_1) * (x_2 - x_1) + (y_2 - y_1) *    
                               (y_2 - y_1) + (z_2 - z_1) * (z_2 - z_1));

这似乎只考虑了地球半径 r,但应该还包括每个点相对于地球表面的高度,例如,对于点1和点2,r1 = r + alt1r2 = r + alt2。通过这种修改,这个答案似乎比 @John Moutafis 的答案更直观(因为这个答案假设地球是一个球体,最直接可比较到 Haversine 计算),尽管它们可能在数学上都是正确的。 - emigre459

3

编辑于2019年: 自从这个答案发布以来,我撰写了一个问答式的示例来回答类似的问题(包括本问题作为一个例子): 如何在GeoDjango中计算两点之间的3D距离(包括高度)

简而言之:

我们需要使用大圆距离公式或Vincenty公式来计算两点之间的2D距离,然后结合两点之间的高度差(delta)来计算它们之间的欧几里得距离。具体如下:

dist = sqrt(great_circle((lat_1, lon_1), (lat_2, lon_2)).m**2, (alt_1 - alt_2)**2)

该解决方案假设海拔以米为单位,并将great_circle的结果转换为米。
你可以通过将坐标从 极坐标 (经度,纬度,高度) 转换为 笛卡尔坐标系 (x,y,z) 来获得正确的计算结果:
  • Let:
    polar_point_1 = (long_1, lat_1, alt_1)
    and
    polar_point_2 = (long_2, lat_2, alt_2)
  • Translate each point to it's Cartesian equivalent by utilizing this formula:

    x = alt * cos(lat) * sin(long)
    y = alt * sin(lat)
    z = alt * cos(lat) * cos(long)
    

    and you will have p_1 = (x_1, y_1, z_1) and p_2 = (x_2, y_2, z_2) points respectively.

  • Finally use the Euclidean formula:

    dist = sqrt((x_2-x_1)**2 + (y_2-y_1)**2 + (z_2-z_1)**2)
    


这个距离的度量单位是什么?你怎样将其转换回米? - AngryDuck
@AngryDuck 因为我们正在使用 Google 海拔 API,所以 alt 是以米为单位的,因此 dist 也将以米为单位。 - John Moutafis
好的,很酷,只要我的高度单位是米,我就可以直接取dist的值,它就是以米为单位的吗? - AngryDuck
@AngryDuck 是的,情况就是这样(你将拥有与你的 alt 变量相同的单位)! - John Moutafis
在将高度转换为笛卡尔坐标时,难道不应该修改高度以考虑地球半径吗?即,在转换方程中使用alt + earth_radius? - ja.ro
@ja.ro 自从最初的回答以来,我已经更好地研究了并提出了更好的解决方案。请查看编辑后的答案和链接的问答。 - John Moutafis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接