(译)计算距离、方位和更多经纬度之间的点

本文介绍了如何计算地球上两点之间的距离、方位、中点等信息,基于球面模型,包括haversine公式、余弦球面定律、等矩形近似值等方法。内容涵盖多种计算公式和代码片段,适合地图应用开发者参考。
摘要由CSDN通过智能技术生成

译)计算距离、方位和更多经纬度之间的点

计算距离、方位和更多经纬度之间的点。最近在研究预测未来坐标和速度、时间之间的关系,希望这篇文章对地图应用有所帮助。

作者:狐狸家的鱼

本文链接:计算距离、方位和更多经纬度之间的点

原文链接:Calculate distance, bearing and more between Latitude/Longitude points

GitHub:sueRimn

该页面介绍了对经纬度点的各种计算,以及实现它们的公式和代码片段。

所有这些公式都是基于球形地球的计算(忽略椭球效应) - 大多数情况下都是准确的(事实上,地球是非常略微椭圆形的, 使用球形模型的误差通常高达0.3%1 - 有关详细信息,请参阅注释)。

1、距离

这使用' hasrsine '公式1来计算两点之间的大圆弧距离 - 即地球表面上的最短距离 - 给出点之间的最短距离。

                                  hasrsine:     a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)

            公式:      c = 2 ⋅ atan2( √a, √(1−a) )

d = R ⋅ c

其中φ为纬度,λ为经度,R为地球半径(平均半径= 6,371km)。注意角度必须是弧度才能传递给三角函数!

JavaScript:    
var R = 6371e3; // metres
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();

var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
        Math.cos(φ1) * Math.cos(φ2) *
        Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

var d = R * c;

在这些脚本中,我通常用 lat/lon 表示度,以 φ/λ 表示的距离/长度。发现混合度和半径是经常让人抓耳挠腮的问题。

即使在很小的距离条件下,“haversine”公式也可以很好的进行不同于基于余弦球面定律的数值计算。

以上使用的"(重新)正矢"是 1−cosθ ,以及 “半正矢”是 (1−cosθ)/2 或者 sin²(θ/2)。曾被航海家广泛使用,罗杰·辛诺特于1984年在《天空与望远镜》杂志上对其进行了描述:辛诺特解释说,大熊星座中Mizar(大熊星座中的一个恒星)和Alcor(北斗七星中的第五等星)之间的角间距(0°11’49.69”)可以通过使用haversine在TRS-80上精确计算出来。

奇怪的是,c是弧度的角距离,a是两点弦长一半的平方。

如果 atan2 不可用, c 可以从 2 ⋅ asin( min(1, √a) ) 计算得出(包括防止四舍五入误差)。

在中等核的i5个人电脑上使用Chrome,距离计算大约需要2 - 5微秒(因此大约每秒200,000 - 500,000次)。通过公因子分解几乎没有用,因为JIT编译器可能会对它们进行优化。

2、余弦球面定律

事实上,JavaScript(以及大多数现代计算机和语言)使用提供了15个重要的精度数字的 “IEEE 754” 64位浮点数。据我估计,在简单余弦公式球面定律(cos c = cos a cos b + sin a sin b cos C)的精度下给出了良好的结果,距离小到地球表面几米。(注意,余弦定律的大地测量形式是规范重新排列的,这样就可以直接使用纬度,而不是用余纬)。

这使得简单余弦定理可以在许多大地测量目的(如果不是天文学)中作为 haversine 公式的另一个选择。这种选择可能是由编程语言、处理器、编码上下文、可用地三角函数(在不同语言中)等驱动的,并且,在非常小地距离中。等矩形的近似值可能更合适。

余弦定理 :d = acos( sin φ1 ⋅ sin φ2 + cos φ1 ⋅ cos φ2 ⋅ cos Δλ ) ⋅ R

JavaScript:    
var φ1 = lat1.toRadians(), φ2 = lat2.toRadians(), Δλ = (lon2-lon1).toRadians(), R = 6371e3; // gives d in metres
var d = Math.acos( Math.sin(φ1)*Math.sin(φ2) + Math.cos(φ1)*Math.cos(φ2) * Math.cos(Δλ) ) * R;
Excel:  
=ACOS( SIN(lat1)*SIN(lat2) + COS(lat1)*COS(lat2)*COS(lon2-lon1) ) * 6371000

(or with lat/lon in degrees): 
=ACOS( SIN(lat1*PI()/180)*SIN(lat2*PI()/180) + COS(lat1*PI()/180)
  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值