How to calculate the distance between two GPS coordinates without using Google Maps API?

25,042

Solution 1

Distance between two coordinates on earth is usually calculated using Haversine formula. This formula takes into consideration earth shape and radius. This is the code I use to calculate distance in meters.

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

Solution 2

You can use the geokit ruby gem. It does these calculations internally, but also supports resolving addresses via google and other services if you need it to.

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

You can also find out the bearing_to (direction expressed as a float in degrees between 0-360) and midpoint_to (returns an object you can run .latitude and .longitude methods on).

Solution 3

Just a little shorter & separated parameter version of @Lunivore's answer

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

Solution 4

I'm not sure of any prepackaged solution, but it seems a fairly straightforward calculation: http://www.movable-type.co.uk/scripts/latlong.html

Solution 5

You can use the loc gem like this :

require 'loc'

loc1 = Loc::Location[49.1, 2]
loc2 = Loc::Location[50, 3]

loc1.distance_to(loc2)
=> 123364.76538823603 # km
Share:
25,042
Chim Kan
Author by

Chim Kan

Worked for Google for 3 years (non-technical). MBA. Worked with VC. Decided to start his own company https://mibelo.com. Currently, he is in Toronto coding his product and doing business development.

Updated on June 25, 2020

Comments

  • Chim Kan
    Chim Kan almost 4 years

    I'm wondering if there's a way to calculate the distance of two GPS coordinates without relying on Google Maps API.

    My app may receive the coordinates in float or I would have to do reverse GEO on the addresses.

  • Oto Brglez
    Oto Brglez over 11 years
    Haversine formula is also used in Geocoder, see file calculations.rb.
  • joscas
    joscas over 10 years
    This method modifies the values of a and b which is unexpected. I guess there's no need to use .map! instead of .map or to reuse a again.
  • Lunivore
    Lunivore over 9 years
    Edited so that no longer happens.
  • James Adams
    James Adams almost 9 years
  • Ionut Popa
    Ionut Popa about 8 years
    like so Geocoder::Calculations.coordinates_present?
  • Oto Brglez
    Oto Brglez almost 5 years
    loc gem internally also uses exactly the same Haversine formula as described in the "accepted" answer above.