2012-10-19 38 views

回答

62

地球上兩個座標之間的距離通常使用Haversine formula來計算。該公式考慮了地球的形狀和半徑。這是我用來計算以米爲單位的距離的代碼。

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 
+6

Haversine公式也用於[Geocoder](http://rubygems.org/gems/geocoder),參見文件[calculate.rb](https: //github.com/alexreisner/geocoder/blob/master/lib/geocoder/calculations.rb#L72)。 –

+2

該方法修改了意想不到的'a'和'b'的值。我想沒有必要使用'.map!'而不是'.map'或者重新使用'a'。 – joscas

+1

已編輯,不再發生。 – Lunivore

2

看寶石Geocoderrailscast

如果您存儲座標分貝,它使用計算距離數據庫。但在其他情況下也很好。

+0

如何我可以訪問https://github.com/alexreisner/geocoder/blob/master/lib/geocoder/calculations.rb中的方法嗎? –

+0

like like'''Geocoder :: Calculations.coordinates_present?''' –

5

您可以使用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 

您也可以找到並midpoint_tobearing_to(表示爲度浮0-360之間方向)(返回一個對象,你可以在運行.latitude和.longitude方法)。

3

只是有點短&分離參數@ 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 
1

轉換接受的答案,以雨燕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 
} 
相關問題