48 lines
1.9 KiB
Python
48 lines
1.9 KiB
Python
''' Rosetta Code task Distance_and_Bearing '''
|
|
|
|
from math import radians, degrees, sin, cos, asin, atan2, sqrt
|
|
from pandas import read_csv
|
|
|
|
|
|
EARTH_RADIUS_KM = 6372.8
|
|
TASK_CONVERT_NM = 0.0094174
|
|
AIRPORT_DATA_FILE = 'airports.dat.txt'
|
|
|
|
QUERY_LATITUDE, QUERY_LONGITUDE = 51.514669, 2.198581
|
|
|
|
|
|
def haversine(lat1, lon1, lat2, lon2):
|
|
'''
|
|
Given two latitude, longitude pairs in degrees for two points on the Earth,
|
|
get distance (nautical miles) and initial direction of travel (degrees)
|
|
for travel from lat1, lon1 to lat2, lon2
|
|
'''
|
|
rlat1, rlon1, rlat2, rlon2 = [radians(x) for x in [lat1, lon1, lat2, lon2]]
|
|
dlat = rlat2 - rlat1
|
|
dlon = rlon2 - rlon1
|
|
arc = sin(dlat / 2) ** 2 + cos(rlat1) * cos(rlat2) * sin(dlon / 2) ** 2
|
|
clen = 2.0 * degrees(asin(sqrt(arc)))
|
|
theta = atan2(sin(dlon) * cos(rlat2),
|
|
cos(rlat1) * sin(rlat2) - sin(rlat1) * cos(rlat2) * cos(dlon))
|
|
theta = (degrees(theta) + 360) % 360
|
|
return EARTH_RADIUS_KM * clen * TASK_CONVERT_NM, theta
|
|
|
|
|
|
def find_nearest_airports(latitude, longitude, wanted=20, csv=AIRPORT_DATA_FILE):
|
|
''' Given latitude and longitude, find `wanted` closest airports in database file csv. '''
|
|
airports = read_csv(csv, header=None, usecols=[1, 3, 5, 6, 7], names=[
|
|
'Name', 'Country', 'ICAO', 'Latitude', 'Longitude'])
|
|
airports['Distance'] = 0.0
|
|
airports['Bearing'] = 0
|
|
for (idx, row) in enumerate(airports.itertuples()):
|
|
distance, bearing = haversine(
|
|
latitude, longitude, row.Latitude, row.Longitude)
|
|
airports.at[idx, 'Distance'] = round(distance, ndigits=1)
|
|
airports.at[idx, 'Bearing'] = int(round(bearing))
|
|
|
|
airports.sort_values(by=['Distance'], ignore_index=True, inplace=True)
|
|
return airports.loc[0:wanted-1, ['Name', 'Country', 'ICAO', 'Distance', 'Bearing']]
|
|
|
|
|
|
print(find_nearest_airports(QUERY_LATITUDE, QUERY_LONGITUDE))
|