RosettaCodeData/Task/Distance-and-Bearing/Python/distance-and-bearing.py

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))