Comment calculer la distance entre deux coordonnées GPS sans utiliser L'API Google Maps?
Je me demande s'il existe un moyen de calculer la distance de deux coordonnées GPS sans compter sur L'API Google Maps.
Mon application peut recevoir les coordonnées dans float ou je devrais faire une géo inversée sur les adresses.
7 réponses
La Distance entre deux coordonnées sur Terre est généralement calculée en utilisant la Formule Haversine . Cette formule prend en considération la forme et le rayon de la terre. C'est le code que j'utilise pour calculer la distance en mètres.
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
Vous pouvez utiliser la gemme geokit ruby . Il effectue ces calculs en interne, mais prend également en charge la résolution d'adresses via google et d'autres services Si vous en avez besoin.
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
Vous pouvez également trouver le bearing_to
(direction exprimée comme un flottant en degrés entre 0-360) et midpoint_to
(renvoie un objet que vous pouvez exécuter .la latitude et la .méthodes de longitude sur).
Je ne suis pas sûr d'une solution préemballée, mais cela semble un calcul assez simple: http://www.movable-type.co.uk/scripts/latlong.html
Juste une version de paramètre un peu plus courte et séparée de la réponse de @ 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
Converti la réponse acceptée à Swift 3.1 (fonctionne sur Xcode 8.3) , au cas où quelqu'un en aurait besoin:
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
}
Vous pouvez utiliser la gemme loc comme ceci:
require 'loc'
loc1 = Loc::Location[49.1, 2]
loc2 = Loc::Location[50, 3]
loc1.distance_to(loc2)
=> 123364.76538823603 # km