Skip to content

Commit 2e405f3

Browse files
Created geodesy section with one algorithm (#1757)
* implemented haversine * updated docstring Only calculate distance * added type hints * added type hints * improved docstring and math usage * f"{haversine_distance(*SAN_FRANCISCO, *YOSEMITE):0,.0f} meters" Co-authored-by: Christian Clauss <[email protected]>
1 parent 53042f0 commit 2e405f3

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

‎geodesy/haversine_distance.py‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
frommathimportasin, atan, cos, radians, sin, sqrt, tan
2+
3+
4+
defhaversine_distance(lat1: float, lon1: float, lat2: float, lon2: float) ->float:
5+
"""
6+
Calculate great circle distance between two points in a sphere,
7+
given longitudes and latitudes https://en.wikipedia.org/wiki/Haversine_formula
8+
9+
We know that the globe is "sort of" spherical, so a path between two points
10+
isn't exactly a straight line. We need to account for the Earth's curvature
11+
when calculating distance from point A to B. This effect is negligible for
12+
small distances but adds up as distance increases. The Haversine method treats
13+
the earth as a sphere which allows us to "project" the two points A and B
14+
onto the surface of that sphere and approximate the spherical distance between
15+
them. Since the Earth is not a perfect sphere, other methods which model the
16+
Earth's ellipsoidal nature are more accurate but a quick and modifiable
17+
computation like Haversine can be handy for shorter range distances.
18+
19+
Args:
20+
lat1, lon1: latitude and longitude of coordinate 1
21+
lat2, lon2: latitude and longitude of coordinate 2
22+
Returns:
23+
geographical distance between two points in metres
24+
>>> from collections import namedtuple
25+
>>> point_2d = namedtuple("point_2d", "lat lon")
26+
>>> SAN_FRANCISCO = point_2d(37.774856, -122.424227)
27+
>>> YOSEMITE = point_2d(37.864742, -119.537521)
28+
>>> f"{haversine_distance(*SAN_FRANCISCO, *YOSEMITE):0,.0f} meters"
29+
'254,352 meters'
30+
"""
31+
# CONSTANTS per WGS84 https://en.wikipedia.org/wiki/World_Geodetic_System
32+
# Distance in metres(m)
33+
AXIS_A=6378137.0
34+
AXIS_B=6356752.314245
35+
RADIUS=6378137
36+
# Equation parameters
37+
# Equation https://en.wikipedia.org/wiki/Haversine_formula#Formulation
38+
flattening= (AXIS_A-AXIS_B) /AXIS_A
39+
phi_1=atan((1-flattening) *tan(radians(lat1)))
40+
phi_2=atan((1-flattening) *tan(radians(lat2)))
41+
lambda_1=radians(lon1)
42+
lambda_2=radians(lon2)
43+
# Equation
44+
sin_sq_phi=sin((phi_2-phi_1) /2)
45+
sin_sq_lambda=sin((lambda_2-lambda_1) /2)
46+
# Square both values
47+
sin_sq_phi*=sin_sq_phi
48+
sin_sq_lambda*=sin_sq_lambda
49+
h_value=sqrt(sin_sq_phi+ (cos(phi_1) *cos(phi_2) *sin_sq_lambda))
50+
return2*RADIUS*asin(h_value)
51+
52+
53+
if__name__=="__main__":
54+
importdoctest
55+
56+
doctest.testmod()

0 commit comments

Comments
(0)