2009-02-20 8 views

Antwort

23

Die traditionelle Methode zur Berechnung der Entfernung zwischen zwei Punkten (jedes Wegpunktpaar in Ihrer GPX-Datei) ist die Haversine-Formel.

Ich habe eine SQL Server-Funktion, die den Algorithmus implementiert. Dies sollte leicht in andere Sprachen übersetzt werden können:

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 

Dies gibt die Entfernung in Miles. Tauschen Sie den Erdradius kilometerweit aus.

Here ist eine tiefergehende Erklärung.

Bearbeiten: Diese Funktion ist schnell genug und genau genug, um Radiussuchen mit einer Postleitzahldatenbank durchzuführen. Es macht seit Jahren einen guten Job auf this site (aber es nicht mehr, da der Link jetzt unterbrochen ist).

+0

Vielen Dank. Ich werde es nach Java portieren und es hier posten. Was bedeutet @DtoR? Entfernung zum Radius? – guerda

+1

Das ist der Faktor, der Grad in Radiant konvertiert, pi/180. – cdonner

+0

Danke für den Link. Ich werde bald meine Java-Version veröffentlichen – guerda

1

Delphi-Implementierung der Vincenty formulae kann here gefunden werden.

+0

Haben Sie einen aktualisierten Link dafür? –

+0

@Adam Carter: Ich habe die URL überprüft und es ist immer noch OK. – menjaraz

1

Hier ist eine Scala-Implementierung.

3958.761 ist die mean radius of the Earth in Meilen. Um ein Ergebnis in km (oder einer anderen Einheit) zu erhalten, ändern Sie einfach diese Zahl.

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

Diese Frage ist ziemlich alt, aber ich möchte eine Python-Option für die Vollständigkeit hinzufügen. GeoPy hat sowohl great-circle distance als auch Vincenty distance.