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.

24
demandé sur Andrew Marshall 2012-10-19 06:44:33

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
66
répondu Oto Brglez 2015-01-31 14:38:35

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).

6
répondu Ira Herman 2016-04-14 22:49:59

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

4
répondu dantswain 2012-10-19 03:05:47

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
3
répondu Sebastian Kim 2017-04-25 15:00:04

Regardez gem géocodeur(railscast)

Si vous stockez vos coordonnées en db, il calcule la distance en utilisant la base de données. Mais fonctionne bien dans d'autres cas aussi.

2
répondu caulfield 2012-10-19 05:52:44

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
}
1
répondu bizz84 2017-04-28 14:47:30

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
1
répondu Hugo Barthelemy 2018-08-02 15:21:05