2009-02-20 20 views

Répondre

23

La méthode traditionnelle de calcul de la distance entre deux points (chaque paire de waypoints dans votre fichier GPX) est avec la formule de Haversine.

J'ai une fonction SQL Server qui implémente l'algorithme. Cela devrait être facile à traduire dans d'autres langues:

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([email protected])) 
    select @d = @R * @c 

    return @d 
end 

Ceci renvoie la distance en miles. Pour les kilomètres, remplacez le rayon de la terre par son équivalent en km.

Here est une explication plus en profondeur. Editer: Cette fonction est suffisamment rapide et précise pour effectuer des recherches de rayon avec une base de données de codes postaux. Il a fait un excellent travail sur this site pendant des années (mais il ne le fait plus, car le lien est cassé maintenant).

+0

Merci beaucoup. Je vais le porter à Java et le poster ici. Que signifie @DtoR? Distance au rayon? – guerda

+1

C'est le facteur qui convertit les degrés en radians, pi/180. – cdonner

+0

Merci pour le lien. Je posterai bientôt ma version Java – guerda

1

L'implémentation Delphi du Vincenty formulae peut être trouvée here.

+0

Avez-vous un lien mis à jour pour cela? –

+0

@Adam Carter: J'ai vérifié l'URL et c'est toujours OK. – menjaraz

1

Voici une implémentation de Scala.

3958.761 est le mean radius of the Earth en miles. Pour obtenir un résultat en km (ou une autre unité), modifiez simplement ce nombre.

// 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 
    } 
} 
0

Cette question est plutôt ancienne, mais je voudrais ajouter une option python pour l'exhaustivité. GeoPy a à la fois great-circle distance et Vincenty distance.