Рассчитать расстояние между 2 GPS-координатами - PullRequest
323 голосов
/ 14 декабря 2008

Как рассчитать расстояние между двумя GPS-координатами (используя широту и долготу)?

Ответы [ 27 ]

2 голосов
/ 25 октября 2012

Мне нужно было реализовать это в PowerShell, надеюсь, это поможет кому-то еще. Некоторые заметки об этом методе

  1. Не разбивайте ни одну из линий, иначе расчет будет неправильным
  2. Для расчета в КМ уберите * 1000 в расчете на расстояние $
  3. Измените $ earthsRadius = 3963.19059 и удалите * 1000 в расчете $ distance для вычисления расстояния в милях
  4. Я использую Haversine, поскольку другие посты указывали, что формулы Винсенти намного точнее

    Function MetresDistanceBetweenTwoGPSCoordinates($latitude1, $longitude1, $latitude2, $longitude2)  
    {  
      $Rad = ([math]::PI / 180);  
    
      $earthsRadius = 6378.1370 # Earth's Radius in KM  
      $dLat = ($latitude2 - $latitude1) * $Rad  
      $dLon = ($longitude2 - $longitude1) * $Rad  
      $latitude1 = $latitude1 * $Rad  
      $latitude2 = $latitude2 * $Rad  
    
      $a = [math]::Sin($dLat / 2) * [math]::Sin($dLat / 2) + [math]::Sin($dLon / 2) * [math]::Sin($dLon / 2) * [math]::Cos($latitude1) * [math]::Cos($latitude2)  
      $c = 2 * [math]::ATan2([math]::Sqrt($a), [math]::Sqrt(1-$a))  
    
      $distance = [math]::Round($earthsRadius * $c * 1000, 0) #Multiple by 1000 to get metres  
    
      Return $distance  
    }
    
2 голосов
/ 22 августа 2011

Вы можете найти реализацию этого (с некоторым хорошим объяснением) в F # на fssnip

вот важные части:


let GreatCircleDistance&lt[&ltMeasure&gt] 'u&gt (R : float&lt'u&gt) (p1 : Location) (p2 : Location) =
    let degToRad (x : float&ltdeg&gt) = System.Math.PI * x / 180.0&ltdeg/rad&gt

    let sq x = x * x
    // take the sin of the half and square the result
    let sinSqHf (a : float&ltrad&gt) = (System.Math.Sin &gt&gt sq) (a / 2.0&ltrad&gt)
    let cos (a : float&ltdeg&gt) = System.Math.Cos (degToRad a / 1.0&ltrad&gt)

    let dLat = (p2.Latitude - p1.Latitude) |&gt degToRad
    let dLon = (p2.Longitude - p1.Longitude) |&gt degToRad

    let a = sinSqHf dLat + cos p1.Latitude * cos p2.Latitude * sinSqHf dLon
    let c = 2.0 * System.Math.Atan2(System.Math.Sqrt(a), System.Math.Sqrt(1.0-a))

    R * c
2 голосов
/ 14 декабря 2008

Полагаю, вы хотите это по искривлению Земли. Ваши две точки и центр Земли находятся на плоскости. Центр Земли является центром круга на этой плоскости, и две точки (примерно) находятся по периметру этого круга. Исходя из этого, вы можете рассчитать расстояние, выяснив, каков угол от одной точки к другой.

Если точки не одинаковы по высоте, или если вам нужно принять во внимание, что Земля не является идеальной сферой, становится немного сложнее.

2 голосов
/ 14 января 2018

я взял лучший ответ и использовал его в программе Scala

import java.lang.Math.{atan2, cos, sin, sqrt}

def latLonDistance(lat1: Double, lon1: Double)(lat2: Double, lon2: Double): Double = {
    val earthRadiusKm = 6371
    val dLat = (lat2 - lat1).toRadians
    val dLon = (lon2 - lon1).toRadians
    val latRad1 = lat1.toRadians
    val latRad2 = lat2.toRadians

    val a = sin(dLat / 2) * sin(dLat / 2) + sin(dLon / 2) * sin(dLon / 2) * cos(latRad1) * cos(latRad2)
    val c = 2 * atan2(sqrt(a), sqrt(1 - a))
    earthRadiusKm * c
}

Я вычеркнул функцию, чтобы можно было легко создавать функции, которые имеют одно из двух положений фиксированное и требуют только пару широт / долг для получения расстояния.

1 голос
/ 02 ноября 2018

Вот моя реализация в эликсире

defmodule Geo do
  @earth_radius_km 6371
  @earth_radius_sm 3958.748
  @earth_radius_nm 3440.065
  @feet_per_sm 5280

  @d2r :math.pi / 180

  def deg_to_rad(deg), do: deg * @d2r

  def great_circle_distance(p1, p2, :km), do: haversine(p1, p2) * @earth_radius_km
  def great_circle_distance(p1, p2, :sm), do: haversine(p1, p2) * @earth_radius_sm
  def great_circle_distance(p1, p2, :nm), do: haversine(p1, p2) * @earth_radius_nm
  def great_circle_distance(p1, p2, :m), do: great_circle_distance(p1, p2, :km) * 1000
  def great_circle_distance(p1, p2, :ft), do: great_circle_distance(p1, p2, :sm) * @feet_per_sm

  @doc """
  Calculate the [Haversine](https://en.wikipedia.org/wiki/Haversine_formula)
  distance between two coordinates. Result is in radians. This result can be
  multiplied by the sphere's radius in any unit to get the distance in that unit.
  For example, multiple the result of this function by the Earth's radius in
  kilometres and you get the distance between the two given points in kilometres.
  """
  def haversine({lat1, lon1}, {lat2, lon2}) do
    dlat = deg_to_rad(lat2 - lat1)
    dlon = deg_to_rad(lon2 - lon1)

    radlat1 = deg_to_rad(lat1)
    radlat2 = deg_to_rad(lat2)

    a = :math.pow(:math.sin(dlat / 2), 2) +
        :math.pow(:math.sin(dlon / 2), 2) *
        :math.cos(radlat1) * :math.cos(radlat2)

    2 * :math.atan2(:math.sqrt(a), :math.sqrt(1 - a))
  end
end
1 голос
/ 20 августа 2011

// Может быть, опечатка?
У нас есть неиспользуемая переменная dlon в GetDirection,
Я предполагаю

double y = Math.Sin(dlon) * Math.Cos(lat2);
// cannot use degrees in Cos ?

должно быть

double y = Math.Sin(dlon) * Math.Cos(dlat);
0 голосов
/ 07 июня 2019

Dart Version

Алгоритм Хаверсин.

import 'dart:math';

class GeoUtils {

  static double _degreesToRadians(degrees) {
    return degrees * pi / 180;
  }

  static double distanceInKmBetweenEarthCoordinates(lat1, lon1, lat2, lon2) {
    var earthRadiusKm = 6371;

    var dLat = _degreesToRadians(lat2-lat1);
    var dLon = _degreesToRadians(lon2-lon1);

    lat1 = _degreesToRadians(lat1);
    lat2 = _degreesToRadians(lat2);

    var a = sin(dLat/2) * sin(dLat/2) +
        sin(dLon/2) * sin(dLon/2) * cos(lat1) * cos(lat2);
    var c = 2 * atan2(sqrt(a), sqrt(1-a));
    return earthRadiusKm * c;
  }
}
...