48 lines
1.3 KiB
Ruby
48 lines
1.3 KiB
Ruby
require 'open-uri'
|
|
require 'csv'
|
|
include Math
|
|
|
|
RADIUS = 6372.8 # rough radius of the Earth, in kilometers
|
|
|
|
def spherical_distance(start_coords, end_coords)
|
|
lat1, long1 = deg2rad(*start_coords)
|
|
lat2, long2 = deg2rad(*end_coords)
|
|
2 * RADIUS * asin(sqrt(sin((lat2-lat1)/2)**2 + cos(lat1) * cos(lat2) * sin((long2 - long1)/2)**2))
|
|
end
|
|
|
|
def bearing(start_coords, end_coords)
|
|
lat1, long1 = deg2rad(*start_coords)
|
|
lat2, long2 = deg2rad(*end_coords)
|
|
dlon = long2 - long1
|
|
atan2(sin(dlon) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dlon))
|
|
end
|
|
|
|
def deg2rad(lat, long)
|
|
[lat * PI / 180, long * PI / 180]
|
|
end
|
|
|
|
uri = "https://raw.githubusercontent.com/jpatokal/openflights/master/data/airports.dat"
|
|
headers = %i(airportID
|
|
name
|
|
city
|
|
country
|
|
iata
|
|
icao
|
|
latitude
|
|
longitude
|
|
altitude
|
|
timezone
|
|
dst
|
|
tzOlson
|
|
type
|
|
source)
|
|
data = CSV.parse(URI.open(uri), headers: headers, converters: :numeric)
|
|
|
|
position = [51.514669, 2.198581]
|
|
|
|
data.each{|r| r[:dist] = (spherical_distance(position, [r[:latitude], r[:longitude]])/1.852).round(1)}
|
|
closest = data.min_by(20){|row| row[:dist] }
|
|
closest.each do |r|
|
|
bearing = (bearing(position,[r[:latitude], r[:longitude]])*180/PI).round % 360
|
|
puts "%-40s %-25s %-6s %12.1f %15.0f" % (r.values_at(:name, :country, :ICAO, :dist) << bearing)
|
|
end
|