Мне интересно, есть ли способ вычислить расстояние между двумя координатами GPS, не полагаясь на API Карт Google.
Мое приложение может получать координаты в float или мне придется делать обратную ГЕО по адресам.
Мне интересно, есть ли способ вычислить расстояние между двумя координатами GPS, не полагаясь на API Карт Google.
Мое приложение может получать координаты в float или мне придется делать обратную ГЕО по адресам.
Расстояние между двумя координатами на земле обычно рассчитывается с использованием формулы Хаверсина. Эта формула учитывает форму и радиус земли. Это код, который я использую для вычисления расстояния в метрах.
def distance loc1, loc2
rad_per_deg = Math::PI/180 # PI / 180
rkm = 6371 # Earth radius in kilometers
rm = rkm * 1000 # Radius in meters
dlat_rad = (loc2[0]-loc1[0]) * rad_per_deg # Delta, converted to rad
dlon_rad = (loc2[1]-loc1[1]) * rad_per_deg
lat1_rad, lon1_rad = loc1.map {|i| i * rad_per_deg }
lat2_rad, lon2_rad = loc2.map {|i| i * rad_per_deg }
a = Math.sin(dlat_rad/2)**2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin(dlon_rad/2)**2
c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1-a))
rm * c # Delta in meters
end
puts distance [46.3625, 15.114444],[46.055556, 14.508333]
# => 57794.35510874037
Вы можете использовать geokit ruby gem. Он выполняет эти вычисления внутренне, но также поддерживает разрешение адресов через google и другие службы, если вам это нужно.
require 'geokit'
current_location = Geokit::LatLng.new(37.79363,-122.396116)
destination = "37.786217,-122.41619"
current_location.distance_to(destination)
# Returns distance in miles: 1.211200074136264
Вы также можете узнать bearing_to
(направление, выраженное как float в градусах между 0-360) и midpoint_to
(возвращает объект, на который вы можете запустить методы .latitude и .longitude).
Я не уверен в каком-либо заранее упакованном решении, но это выглядит довольно просто: http://www.movable-type.co.uk/scripts/latlong.html
Немного более короткая и разделенная версия параметра ответа @Lunivore
RAD_PER_DEG = Math::PI / 180
RM = 6371000 # Earth radius in meters
def distance_between(lat1, lon1, lat2, lon2)
lat1_rad, lat2_rad = lat1 * RAD_PER_DEG, lat2 * RAD_PER_DEG
lon1_rad, lon2_rad = lon1 * RAD_PER_DEG, lon2 * RAD_PER_DEG
a = Math.sin((lat2_rad - lat1_rad) / 2) ** 2 + Math.cos(lat1_rad) * Math.cos(lat2_rad) * Math.sin((lon2_rad - lon1_rad) / 2) ** 2
c = 2 * Math::atan2(Math::sqrt(a), Math::sqrt(1 - a))
RM * c # Delta in meters
end
Посмотрите на драгоценный камень Geocoder (railscast)
Если вы храните свои координаты в db, он вычисляет расстояние, используя базу данных. Но хорошо работает и в других случаях.
Преобразовал принятый ответ в Swift 3.1 (работает на Xcode 8.3), если кому-то это понадобится:
public static func calculateDistanceMeters(departure: CLLocationCoordinate2D, arrival: CLLocationCoordinate2D) -> Double {
let rad_per_deg = Double.pi / 180.0 // PI / 180
let rkm = 6371.0 // Earth radius in kilometers
let rm = rkm * 1000.0 // Radius in meters
let dlat_rad = (arrival.latitude - departure.latitude) * rad_per_deg // Delta, converted to rad
let dlon_rad = (arrival.longitude - departure.longitude) * rad_per_deg
let lat1_rad = departure.latitude * rad_per_deg
let lat2_rad = arrival.latitude * rad_per_deg
let sinDlat = sin(dlat_rad/2)
let sinDlon = sin(dlon_rad/2)
let a = sinDlat * sinDlat + cos(lat1_rad) * cos(lat2_rad) * sinDlon * sinDlon
let c = 2.0 * atan2(sqrt(a), sqrt(1-a))
return rm * c
}