地球两点大圆距离计算算法 (经度纬度)

The great-circle distance or orthodromic distance is the shortest distance between two points on the surface of a sphere, measured along the surface of the sphere (as opposed to a straight line through the sphere’s interior). The distance between two points in Euclidean space is the length of a straight line between them, but on the sphere there are no straight lines. In spaces with curvature, straight lines are replaced by geodesics. Geodesics on the sphere are circles on the sphere whose centers coincide with the center of the sphere, and are called great circles. –wiki

大圆距离 (Great-circle distance) 是指从球面的一点到球面的另一点所经过的最短路径的长度。一般是连接这两个点较短的一条弧的长度。

地理位置两点之间的距离,就是这个大圆距离。想要计算这个大圆距离,并不能直接用类似在直角坐标系中通过勾股定理计算直线距离那样计算。地理位置信息一般采用经度和纬度,以弧度制度量。一般有两种算法来计算:

  • 如果将地球当作球体 (sphere)
    • 使用 半正矢公式 (Haversine formula)
  • 如果将地球当作椭球体 (ellipsoid)
    • 使用 Vincenty’s formulae

Vincenty’s formulae 由于将地球当作椭球体来计算,会有更高的精度, 但是计算效率会比Haversine formula略低。

Haversine formula (半正矢公式)

以下是一个通过 Haversine formula 用已知两点经度纬度的前提下,计算出大圆距离的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# python3
__author__ = 'Min'

import math

EARTH_RADUIS = 6378.137 # kilometre

def getDistance(lat1, long1, lat2, long2, decimal_digits=6):
'''
Function to get two-point distance by longtitude and latitude
average runtime for this function is about 0.000006 sec.

Eample:

>>> getDistance(-35.308228, 149.124358, -33.868883, 151.209301)
249.349728
>>> getDistance(-37.813971, 144.962921, -33.868883, 151.209301)
714.257887
>>> getDistance(-37.813971, 144.962921, 31.231981, 121.492631)
8063.801696
>>> getDistance(-37.813971, 144.962921, 31.231981, 121.492631, 3)
8063.802
'''
assert abs(lat1) <= 90 and abs(lat2) <= 90, "invalid latitude"
assert abs(long1) <= 180 and abs(long2) <= 180, "invalid longtigude"
rad_lat1 = math.radians(lat1)
rad_lat2 = math.radians(lat2)
rad_long1 = math.radians(long1)
rad_long2 = math.radians(long2)
a = rad_lat1 - rad_lat2
b = rad_long1 - rad_long2
s = (2 * math.asin(math.sqrt(math.pow(math.sin(a / 2), 2) +
math.cos(rad_lat1) * math.cos(rad_lat2) *
math.pow(math.sin(b / 2), 2))))
distance = s * EARTH_RADUIS
return round(distance,decimal_digits)

def _main():
# Canberra to Sydney
print(getDistance(-35.308228, 149.124358, -33.868883, 151.209301))

# Melbourne to Sydney
print(getDistance(-37.813971, 144.962921, -33.868883, 151.209301))

# Melbourne to Shanghai
print(getDistance(-37.813971, 144.962921, 31.231981, 121.492631))

if __name__ == '__main__':
import doctest
doctest.testmod()
_main()

通过测试数据得知:

From To Distance (km)
堪培拉 悉尼 249.349728
墨尔本 悉尼 714.257887
墨尔本 上海 8063.801696

还是比较精确的。 在不需要太精准的情况,可以使用Haversine formula (半正矢公式)来计算地球上两点之间的大圆距离。

Vincenty’s formulae

-TODO


Author: Min Gao

License: CC BY-NC-SA 4.0

如需转载或引用, 请标注出处。