В этой статье я собрал несколько примеров кода формулы Хаверсина в JS, Ruby и SQL.
Во-первых, позвольте мне объяснить формулу, известную как формула Хаверсина.
Хаверсинус позволяет вам вычислять расстояние между двумя наборами координат на сфере, что значительно отличается от вычисления расстояний на плоской плоскости: люди, работающие с плоской Землей, будут работать непосредственно с теоремой Пифагора, чтобы они могли щелкнуть здесь.
Лучшее объяснение, которое я видел лично, взято непосредственно из сообщения сообщества ESRI от постоянного участника SimonKettle¹:
The Haversine formula is perhaps the first equation to consider when understanding how to calculate distances on a sphere. The word "Haversine" comes from the function: haversine(θ) = sin²(θ/2) The following equation where φ is latitude, λ is longitude, R is earth’s radius (mean radius = 6,371km) is how we translate the above formula to include latitude and longitude coordinates. Note that angles need to be in radians to pass to trig functions: a = sin²(φB — φA/2) + cos φA * cos φB * sin²(λB — λA/2) c = 2 * atan2( √a, √(1−a) ) d = R ⋅ c
Формула гаверсинуса представляет собой переформулировку сферического закона косинусов, но формулировка в терминах гаверсинусов более полезна для малых углов и расстояний. — Саймон Кеттл
Автор также приводит пример на Python, который я подробно изложу в основе этой статьи.
Javascript — формула гаверсина
Пример использования: https://replit.com/@AbeFlansburg/haversine#index.js
Рубин — формула гаверсина
Пример использования: https://replit.com/@AbeFlansburg/haversine-1#main.rb
SQL — формула гаверсина
Имея в виду, что я не являюсь мастером SQL и что я работал с образцом набора данных, используя пример из StackOverflow²:
SELECT carrier.code, carrier.description, airport.lat, airport.long, ( 3959 * acos( cos( radians(airport.lat) ) * cos( radians( 61.2181 ) ) * cos( radians(149.9003) - radians(airport.long) ) + sin( radians(airport.lat) ) * sin( radians(61.2181)))) as distance_to_anchorage FROM carrier INNER JOIN airport ON airport.code=carrier.code WHERE airport.city LIKE '%AK' AND LOWER(carrier.description) LIKE '%inc%'
где это соответствующая строка кода:
( 3959 * acos( cos( radians(latitude1) ) * cos( radians( latitude2 ) ) * cos( radians(longitude2) - radians(longitude1) ) + sin( radians(latitude1) ) * sin( radians(latitude2))))
Питон — Хаверсин
Взято непосредственно с https://community.esri.com/t5/coordinate-reference-systems/distance-on-a-sphere-the-haversine-formula/ba-p/902128¹
'''
Calculate distance using the Haversine Formula
'''
def haversine(coord1: object, coord2: object):
import math
# Coordinates in decimal degrees (e.g. 2.89078, 12.79797)
lon1, lat1 = coord1
lon2, lat2 = coord2
R = 6371000 # radius of Earth in meters
phi_1 = math.radians(lat1)
phi_2 = math.radians(lat2)
delta_phi = math.radians(lat2 - lat1)
delta_lambda = math.radians(lon2 - lon1)
a = math.sin(delta_phi / 2.0) ** 2 + math.cos(phi_1) * math.cos(phi_2) * math.sin(delta_lambda / 2.0) ** 2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
meters = R * c # output distance in meters
km = meters / 1000.0 # output distance in kilometers
meters = round(meters, 3)
km = round(km, 3)
print(f"Distance: {meters} m")
print(f"Distance: {km} km")
Я надеюсь, что это может быть полезно для тех, кто хочет рассчитать расстояние по прямой с учетом двух наборов широты и долготы на сфере.
Источники
[1] Кеттл, Саймон (5 октября–2017 г.). Расстояние на сфере: формула Хаверсина.
https://community.esri.com/t5/coordinate-reference-systems/distance-on-a-sphere-the-haversine -формула/ба-п/902128
[2] Саадб (5 сентября–2016 г.). SQL-запрос формулы Хаверсина на SQL-сервере
https://stackoverflow.com/questions/39338167/sql-query-of-haversine-formula-in-sql-server