RosettaCodeData/Task/Distance-and-Bearing/Ruby/distance-and-bearing.rb
2023-07-01 13:44:08 -04:00

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