Подтвердить что ты не робот

Как рассчитать расстояние между двумя координатами GPS без использования API Карт Google?

Мне интересно, есть ли способ вычислить расстояние между двумя координатами GPS, не полагаясь на API Карт Google.

Мое приложение может получать координаты в float или мне придется делать обратную ГЕО по адресам.

4b9b3361

Ответ 1

Расстояние между двумя координатами на земле обычно рассчитывается с использованием формулы Хаверсина. Эта формула учитывает форму и радиус земли. Это код, который я использую для вычисления расстояния в метрах.

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

Ответ 2

Вы можете использовать geokit ruby ​​gem. Он выполняет эти вычисления внутренне, но также поддерживает разрешение адресов через google и другие службы, если вам это нужно.

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

Вы также можете узнать bearing_to (направление, выраженное как float в градусах между 0-360) и midpoint_to (возвращает объект, на который вы можете запустить методы .latitude и .longitude).

Ответ 4

Немного более короткая и разделенная версия параметра ответа @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

Ответ 5

Посмотрите на драгоценный камень Geocoder (railscast)

Если вы храните свои координаты в db, он вычисляет расстояние, используя базу данных. Но хорошо работает и в других случаях.

Ответ 6

Преобразовал принятый ответ в Swift 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
}