如何在不使用Google Maps API的情况下计算两个GPS坐标之间的距离?

Chi*_*Kan 27 ruby google-maps

我想知道是否有办法计算两个GPS坐标的距离而不依赖于Google Maps API.

我的应用程序可能会收到float中的坐标,或者我必须在地址上执行反向GEO.

Oto*_*lez 73

地球上两个坐标之间的距离通常使用Haversine公式计算.该公式考虑了地球形状和半径.这是我用来计算以米为单位的距离的代码.

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
Run Code Online (Sandbox Code Playgroud)

  • 在[Geocoder](http://rubygems.org/gems/geocoder)中也使用了Haversine公式,参见文件[computation.rb](https://github.com/alexreisner/geocoder/blob/master/lib/geocoder /calculations.rb#L72). (7认同)
  • 此方法修改了意外的"a"和"b"的值.我想没有必要使用`.map!`代替`.map`或再次重用`a`. (2认同)

Ira*_*man 10

你可以使用geokit ruby​​ gem.它在内部进行这些计算,但如果需要,还支持通过谷歌和其他服务解析地址.

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
Run Code Online (Sandbox Code Playgroud)

您还可以找到bearing_to(以0-360之间的度数浮点表示的方向)和midpoint_to(返回可以运行.latitude和.longitude方法的对象).


Seb*_*Kim 5

@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
Run Code Online (Sandbox Code Playgroud)