计算两个坐标之间的距离,考虑高度变化的短距离

Calculate distance between two Coordinates, with short distances considering altitude variation

我正在开发用于农业目的的 GPS 应用程序。我需要一种方法来精确计算两个坐标之间的距离和差值 (X, Y),使用纬度、经度和高度(高度以米为单位)。 这些点将彼此靠近,大约 10m 或更短,距离将用于其他计算,如面积,差值 (X, Y) 将用于渲染 2D 地图。

我的第一个想法是用直角三角形计算2D(X,Y),然后再计算3D距离

这是一个脚本(在 Javascript 中):

function xyDifference(lat1, lng1, lat2, lng2){
        var xdif = (lng1 - lng2)/0.00000898; //value to convert decimal degrees difference to meters
        var ydif = (lat1 - lat2)/0.00000898;
        return [xdif,ydif];
}

function distanceBetween2D(lat1,lng1,lat2,lng2) {
        var b = Math.abs(lat1 - lat2);
        var c = Math.abs(lng1 - lng2);
        var a = Math.sqrt(Math.pow(b,2) + Math.pow(c,2));
        var dst = a / 0.00000898; 
        return dst;
}

function distanceBetween3D(lat1,lng1,alt1,lat2,lng2,alt2){
        var dst = distanceBetween2D(lat1,lng1,lat2,lng2);
        a = Math.abs(alt1 - alt2);
        dst = Math.sqrt(Math.pow(dst,2) + Math.pow(a,2));
        return dst;
}

console.log(distanceBetween(-24.09234566666,-52.5289494999999,588,-24.09231633333,-52.5288795,589));

//It prints 8.51m
//Using Haversine formula with these values it gives something about 7.82m

我想知道这是不是一个好方法,或者有没有更好的方法。我看过 Haversine 公式,但我不知道如何将它用于海拔差异,以及如何获得 (X,Y) 差异来渲染地图。

建议使用大地测量库,特别是 https://www.movable-type.co.uk/scripts/geodesy-library.html。请注意,此库提供了许多大地测量模型供您选择(例如,球形与椭圆形)。在您的特定情况下,我选择了两个不同的模块来举例说明它们的用途...

  • "latlon-ellipsoidal-vincenty.js" 提供Lat/Lon距离计算功能,不支持带高度( altitude )的计算。
  • "latlon-ellipsoidal.js" 提供将纬度/经度转换为笛卡尔地心地球固定 (ECEF) 向量的函数,这些向量会影响高度。

<script type="module">

import LatLonE from 'https://cdn.jsdelivr.net/npm/geodesy@2/latlon-ellipsoidal-vincenty.js';
import LatLon, { Cartesian, Vector3d, Dms } from 'https://cdn.jsdelivr.net/npm/geodesy@2/latlon-ellipsoidal.js';

let latlon0 = new LatLonE( -24.09234566666, -52.5289494999999 );
let latlon1 = new LatLonE( -24.09231633333, -52.5288795 );
let latlonDistance = latlon0.distanceTo( latlon1 );

console.log( `Lat/Lon distance from ${latlon0.toString()} to ${latlon1.toString()} is ${latlonDistance}m` );

let cart0 = new LatLon( -24.09234566666, -52.5289494999999, 588 ).toCartesian();
let cart1 = new LatLon( -24.09231633333, -52.5288795, 589 ).toCartesian();
let cartDistance = Math.sqrt( ( cart1.x - cart0.x ) ** 2 + ( cart1.y - cart0.y ) ** 2 + ( cart1.z - cart0.z ) ** 2 );

console.log( `Cartesian distance from ${cart0.toString()} to ${cart1.toString()} is ${cartDistance}m` );

</script>

请注意,纬度/经度计算结果为您在 Haversine 公式中观察到的 7.824m。 (这也符合@Bergi 的评论,因为 Haversine 公式似乎没有考虑高度。)

转换为笛卡尔坐标并计算距离后,数值稍大一些,具体为 7.88836m,因为坐标之间存在 1m 的高差。直接向上计算边长为 7.824m 和 1m 的直角三角形的斜边,结果长度为 7.88765m,与库中的结果非常接近。请记住,1) 海拔越高,相同的纬度/经度变得越远,并且 2) 地球的椭圆体形状也会影响计算,那么库的结果是合理的...