generated from mwc/lab_weather
96 lines
2.6 KiB
Python
96 lines
2.6 KiB
Python
#!/usr/bin/python
|
|
# coding: utf8
|
|
|
|
from __future__ import absolute_import
|
|
from math import radians, cos, sin, asin, sqrt
|
|
from geocoder.location import Location
|
|
|
|
AVG_EARTH_RADIUS = 6371 # in km
|
|
|
|
|
|
def Distance(*args, **kwargs):
|
|
total = 0.0
|
|
last = None
|
|
|
|
if len(args) == 1 and isinstance(args, (list, tuple)):
|
|
args = args[0]
|
|
|
|
if len(args) <= 1:
|
|
raise ValueError("Distance needs at least two locations")
|
|
|
|
for location in args:
|
|
if last:
|
|
distance = haversine(Location(last), Location(location), **kwargs)
|
|
if distance:
|
|
total += distance
|
|
last = location
|
|
|
|
return total
|
|
|
|
|
|
def haversine(point1, point2, **kwargs):
|
|
""" Calculate the great-circle distance bewteen two points on the Earth surface.
|
|
|
|
:input: two 2-tuples, containing the latitude and longitude of each point
|
|
in decimal degrees.
|
|
|
|
Example: haversine((45.7597, 4.8422), (48.8567, 2.3508))
|
|
|
|
:output: Returns the distance bewteen the two points.
|
|
The default unit is kilometers. Miles can be returned
|
|
if the ``miles`` parameter is set to True.
|
|
|
|
"""
|
|
|
|
lookup_units = {
|
|
'miles': 'miles',
|
|
'mile': 'miles',
|
|
'mi': 'miles',
|
|
'ml': 'miles',
|
|
'kilometers': 'kilometers',
|
|
'kilometres': 'kilometers',
|
|
'kilometer': 'kilometers',
|
|
'kilometre': 'kilometers',
|
|
'km': 'kilometers',
|
|
'meters': 'meters',
|
|
'metres': 'meters',
|
|
'meter': 'meters',
|
|
'metre': 'meters',
|
|
'm': 'meters',
|
|
'feet': 'feet',
|
|
'f': 'feet',
|
|
'ft': 'feet',
|
|
}
|
|
|
|
if point1.ok and point2.ok:
|
|
# convert all latitudes/longitudes from decimal degrees to radians
|
|
lat1, lng1, lat2, lng2 = list(map(radians, point1.latlng + point2.latlng))
|
|
|
|
# calculate haversine
|
|
lat = lat2 - lat1
|
|
lng = lng2 - lng1
|
|
d = sin(lat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(lng / 2) ** 2
|
|
h = 2 * AVG_EARTH_RADIUS * asin(sqrt(d))
|
|
|
|
# Measurements
|
|
units = kwargs.get('units', 'kilometers').lower()
|
|
units_calculation = {
|
|
'miles': h * 0.621371,
|
|
'feet': h * 0.621371 * 5280,
|
|
'meters': h * 1000,
|
|
'kilometers': h,
|
|
}
|
|
|
|
if units in lookup_units:
|
|
return units_calculation[lookup_units[units]]
|
|
else:
|
|
raise ValueError("Unknown units of measurement")
|
|
|
|
else:
|
|
print(u'[WARNING] Error calculating the following two locations.\n'
|
|
'Points: {0} to {1}'.format(point1.location, point2.location))
|
|
|
|
if __name__ == '__main__':
|
|
d = Distance('Ottawa, ON', 'Toronto, ON', 'Montreal, QC')
|
|
print(d)
|