-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeomath.py
148 lines (118 loc) · 3.67 KB
/
geomath.py
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#
# geomath.py
#
# some geo coordinate math that I found on the internet
#
# kevinabrandon@gmail.com
#
import math
def HeadingStr(heading):
"""
Gives a heading string given the heading float
"""
headstr = "?"
if heading is not None:
if heading < 22.5 or heading >= 337.5:
headstr = "N"
elif heading >= 22.5 and heading < 67.5:
headstr = "NE"
elif heading >= 67.5 and heading < 112.5:
headstr = "E"
elif heading >= 112.5 and heading < 157.5:
headstr = "SE"
elif heading >= 157.5 and heading < 202.5:
headstr = "S"
elif heading >= 202.5 and heading < 247.5:
headstr = "SW"
elif heading >= 247.5 and heading < 292.5:
headstr = "W"
elif heading >= 292.5 and heading < 337.5:
headstr = "NW"
return headstr
def knot2mph(k):
"""
Converts knots to miles per hour.
"""
if k is None:
return None
return k * 1.15078
def mach2mph(ma):
"""
Converts mach to miles per hour
"""
if ma is None:
return None
return ma * 767.27
def mi2km(mi):
"""
Converts to miles to kilometers.
"""
if mi is None:
return None
return mi * 1.60934
def mi2nm(mi):
"""
Converts miles to nautical miles
"""
if mi is None:
return None
return mi * 0.868976
def ft2m(ft):
"""
Converts feet to meters.
"""
if ft is None:
return None
return ft * 0.3048
def distance(pointA, pointB):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
http://stackoverflow.com/questions/15736995/how-can-i-quickly-estimate-the-distance-between-two-latitude-longitude-points
"""
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(
math.radians, [pointA[1], pointA[0], pointB[1], pointB[0]]
)
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = (
math.sin(dlat / 2) ** 2 + math.cos(lat1) * math.cos(lat2) * math.sin(dlon / 2) ** 2
)
c = 2 * math.asin(math.sqrt(a))
r = 3956 # Radius of earth in miles. Use 6371 for kilometers
return c * r
def bearing(pointA, pointB):
"""
Calculates the bearing between two points.
Found here: https://gist.github.com/jeromer/2005586
The formulae used is the following:
θ = atan2(sin(Δlong).cos(lat2),
cos(lat1).sin(lat2) − sin(lat1).cos(lat2).cos(Δlong))
:Parameters:
- `pointA: The tuple representing the latitude/longitude for the
first point. Latitude and longitude must be in decimal degrees
- `pointB: The tuple representing the latitude/longitude for the
second point. Latitude and longitude must be in decimal degrees
:Returns:
The bearing in degrees
:Returns Type:
float
"""
if (type(pointA) is not tuple) or (type(pointB) is not tuple):
raise TypeError("Only tuples are supported as arguments")
lat1 = math.radians(pointA[0])
lat2 = math.radians(pointB[0])
diffLong = math.radians(pointB[1] - pointA[1])
x = math.sin(diffLong) * math.cos(lat2)
y = math.cos(lat1) * math.sin(lat2) - (
math.sin(lat1) * math.cos(lat2) * math.cos(diffLong)
)
initial_bearing = math.atan2(x, y)
# Now we have the initial bearing but math.atan2 return values
# from -180° to + 180° which is not what we want for a compass bearing
# The solution is to normalize the initial bearing as shown below
initial_bearing = math.degrees(initial_bearing)
compass_bearing = (initial_bearing + 360) % 360
return compass_bearing