Как рассчитать расстояние от файла GPX? - PullRequest
22 голосов
/ 20 февраля 2009

У меня есть файл GPX с треком GPS. Теперь я хочу вычислить расстояние, которое я преодолел с этой дорожкой.

Какой лучший способ рассчитать это?

Ответы [ 5 ]

24 голосов
/ 20 февраля 2009

Традиционный способ вычисления расстояния между двумя точками (каждая пара путевых точек в вашем файле GPX) - по формуле Хаверсайна.

У меня есть функция SQL Server, которая реализует алгоритм. Это должно быть легко перевести на другие языки:

create function dbo.udf_Haversine(@lat1 float, @long1 float, 
                   @lat2 float, @long2 float) returns float begin
    declare @dlon float, @dlat float, @rlat1 float, 
                 @rlat2 float, @rlong1 float, @rlong2 float, 
                 @a float, @c float, @R float, @d float, @DtoR float

    select @DtoR = 0.017453293
    select @R = 3959      -- Earth radius

    select 
        @rlat1 = @lat1 * @DtoR,
        @rlong1 = @long1 * @DtoR,
        @rlat2 = @lat2 * @DtoR,
        @rlong2 = @long2 * @DtoR

    select 
        @dlon = @rlong1 - @rlong2,
        @dlat = @rlat1 - @rlat2

    select @a = power(sin(@dlat/2), 2) + cos(@rlat1) * 
                     cos(@rlat2) * power(sin(@dlon/2), 2)
    select @c = 2 * atn2(sqrt(@a), sqrt(1-@a))
    select @d = @R * @c

    return @d 
end

Возвращает расстояние в милях. Для километров замените радиус Земли его эквивалентом в км.

Здесь - более подробное объяснение.

Редактировать: эта функция достаточно быстрая и точная для поиска по радиусу в базе данных по почтовому индексу. Он много лет работал на этом сайте (но теперь этого не происходит, так как ссылка теперь не работает).

1 голос
/ 28 октября 2013

Вот реализация Scala.

3958.761 - это средний радиус Земли в милях. Чтобы получить результат в км (или каком-либо другом блоке), просто измените это число.

// The Haversine formula
def haversineDistance(pointA: (Double, Double), pointB: (Double, Double)): Double = {
  val deltaLat = math.toRadians(pointB._1 - pointA._1)
  val deltaLong = math.toRadians(pointB._2 - pointA._2)
  val a = math.pow(math.sin(deltaLat / 2), 2) + math.cos(math.toRadians(pointA._1)) * math.cos(math.toRadians(pointB._1)) * math.pow(math.sin(deltaLong / 2), 2)
  val greatCircleDistance = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
  3958.761 * greatCircleDistance
}

// A sequence of gpx trackpoint lat,long pairs parsed from the track GPX data
val trkpts: Seq[(Double, Double)] = {
  val x = scala.xml.XML.loadString(track)
  (x \\ "trkpt").map(trkpt => ((trkpt \ "@lat").text.toDouble, (trkpt \ "@lon").text.toDouble))
}

// Distance of track in miles using Haversine formula
val trackDistance: Double = {
  trkpts match {
    case head :: tail => tail.foldLeft(head, 0.0)((accum, elem) => (elem, accum._2 + haversineDistance(accum._1, elem)))._2
    case Nil => 0.0
  }
}
1 голос
/ 04 декабря 2011

Delphi-реализация формул Винсента находится здесь здесь .

1 голос
/ 15 марта 2010

У Майка Гавагана есть алгоритм для расчета расстояния на его сайте. Существует C #, а также JAVA-версия кода.

0 голосов
/ 18 августа 2017

Этот вопрос довольно старый, но я бы хотел добавить опцию python для полноты. GeoPy имеет great-circle distance и Vincenty distance.

...