2009-06-26 10 views
4

Ich muss den Abstand von einem lat/lng Punkt zu einer Linie bekommen. Natürlich muss der Große Kreis folgen.Entfernung von Punkt zu Linie Großkreisfunktion funktioniert nicht richtig.

fand ich einen großen Artikel zu diesem Thema bei http://www.movable-type.co.uk/scripts/latlong.html

aber der Code funktioniert nicht richtig. Entweder mache ich etwas falsch oder es fehlt etwas. Hier ist die Funktion in Frage. Siehe den Link für die anderen Funktionen, falls erforderlich.

var R = 3961.3 
    LatLon.crossTrack = function(lat1, lon1, lat2, lon2, lat3, lon3) { 
    var d13 = LatLon.distHaversine(lat1, lon1, lat3, lon3); 
    var brng12 = LatLon.bearing(lat1, lon1, lat2, lon2); 
    var brng13 = LatLon.bearing(lat1, lon1, lat3, lon3); 
    var dXt = Math.asin(Math.sin(d13/R)*Math.sin(brng13-brng12)) * R; 
    return dXt; 
    } 

lat/LON1 = -94,127592, 41,81762

lat/LON2 = -94,087257, 41,848202

lat/lon3 = -94,046875, 41,791057

Dies berichtet 0,865 Meilen. Die tatsächliche Entfernung beträgt 4,29905 Meilen.

Irgendwelche Hinweise, wie Sie das beheben können? Ich bin kein Mathematiker, nur ein langjähriger Programmierer.

+0

Auch ich habe einige Probleme mit der Berechnung der Cross-Track-Abstand zu senden. Ich möchte, dass Sie Ihren Code als Beispiel verwenden, um meine Ergebnisse zu überprüfen, aber ich habe Probleme, Ihre Koordinaten zu verstehen. Wie kommt es, dass Sie Breitengrade <-90 haben, wenn sie nur zwischen -90 und +90 definiert sind? – oschrenk

Antwort

4

Die meisten trigonometrischen Funktionen benötigen Radianten. Sind Ihre Winkelmaße in Grad? Vielleicht müssen sie mit der üblichen Formel umgewandelt werden:

2 * π Radiant = 360 Grad

Wenn Sie Haversine Formel unter der Formel anschauen, werden Sie sehen:

(Beachten Sie, dass Winkel im Bogenmaß sein müssen, um zu den Triggerfunktionen zu gelangen).

+0

Das war es tatsächlich! Ich habe einfach vergessen, dass der Rückgabewert der Lagermethode Grad ist. Ein Kopfslapper. Danke! –

0

Ist Ihre Funktion denselben Wert für diese Koordinaten Rückkehr:

crossTrack(0,0,0,1,0.1,0.5); 
crossTrack(0,0,0,1,0.1,0.6); 
crossTrack(0,0,0,1,0.1,0.4); 

Ich denke, es sollte aber mir tut es nicht. Der 3. Punkt liegt immer 0.1 km nördlich vom Äquator. nur der Längengrad ändert sich, was das Ergebnis nicht beeinflussen sollte. So wie es scheint.

0

habe ich versucht, diese pointlinedistancetest es aalatlon etc

private static final double _eQuatorialEarthRadius = 6378.1370D; 
private static final double _d2r = (Math.PI/180D); 
private static double PRECISION = 1; 





// Haversine Algorithm 
// source: http://stackoverflow.com/questions/365826/calculate-distance-between-2-gps-coordinates 

private static double HaversineInM(double lat1, double long1, double lat2, double long2) { 
    return (1000D * HaversineInKM(lat1, long1, lat2, long2)); 



} 

private static double HaversineInKM(double lat1, double long1, double lat2, double long2) { 
    double dlong = (long2 - long1) * _d2r; 
    double dlat = (lat2 - lat1) * _d2r; 
    double a = Math.pow(Math.sin(dlat/2D), 2D) + Math.cos(lat1 * _d2r) * Math.cos(lat2 * _d2r) 
      * Math.pow(Math.sin(dlong/2D), 2D); 
    double c = 2D * Math.atan2(Math.sqrt(a), Math.sqrt(1D - a)); 
    double d = _eQuatorialEarthRadius * c; 





    return d; 
} 

// Distance between a point and a line 

public static double pointLineDistanceTest(double[] aalatlng,double[] bblatlng,double[]cclatlng){ 



    double [] a = aalatlng; 
    double [] b = bblatlng; 
    double [] c = cclatlng; 




    double[] nearestNode = nearestPointGreatCircle(a, b, c); 
    //  System.out.println("nearest node: " + Double.toString(nearestNode[0]) 
    + ","+Double.toString(nearestNode[1])); 
    double result = HaversineInM(c[0], c[1], nearestNode[0], nearestNode[1]); 

     //  System.out.println("result: " + Double.toString(result)); 



      return (result); 






} 

// source: http://stackoverflow.com/questions/1299567/how-to-calculate-distance-from-a-point-to-a-line-segment-on-a-sphere 
private static double[] nearestPointGreatCircle(double[] a, double[] b, double c[]) 
{ 
    double[] a_ = toCartsian(a); 
    double[] b_ = toCartsian(b); 
    double[] c_ = toCartsian(c); 

    double[] G = vectorProduct(a_, b_); 
    double[] F = vectorProduct(c_, G); 
    double[] t = vectorProduct(G, F); 

    return fromCartsian(multiplyByScalar(normalize(t), _eQuatorialEarthRadius)); 
} 

@SuppressWarnings("unused") 
private static double[] nearestPointSegment (double[] a, double[] b, double[] c) 
{ 
    double[] t= nearestPointGreatCircle(a,b,c); 
    if (onSegment(a,b,t)) 
    return t; 

    return (HaversineInKM(a[0], a[1], c[0], c[1]) < HaversineInKM(b[0], b[1], c[0], c[1])) ? a : b; 
} 

private static boolean onSegment (double[] a, double[] b, double[] t) 
    { 
    // should be return distance(a,t)+distance(b,t)==distance(a,b), 
    // but due to rounding errors, we use: 
    return Math.abs(HaversineInKM(a[0], a[1], b[0], b[1])-HaversineInKM(a[0], a[1], t[0], t[1])-HaversineInKM(b[0], b[1], t[0], t[1])) < PRECISION; 
    } 


// source: http://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates 
private static double[] toCartsian(double[] coord) { 
    double[] result = new double[3]; 
    result[0] = _eQuatorialEarthRadius * Math.cos(Math.toRadians(coord[0])) * Math.cos(Math.toRadians(coord[1])); 
    result[1] = _eQuatorialEarthRadius * Math.cos(Math.toRadians(coord[0])) * Math.sin(Math.toRadians(coord[1])); 
    result[2] = _eQuatorialEarthRadius * Math.sin(Math.toRadians(coord[0])); 


    return result; 
} 

private static double[] fromCartsian(double[] coord){ 
    double[] result = new double[2]; 
    result[0] = Math.toDegrees(Math.asin(coord[2]/_eQuatorialEarthRadius)); 
    result[1] = Math.toDegrees(Math.atan2(coord[1], coord[0])); 

    return result; 
} 


// Basic functions 
private static double[] vectorProduct (double[] a, double[] b){ 
    double[] result = new double[3]; 
    result[0] = a[1] * b[2] - a[2] * b[1]; 
    result[1] = a[2] * b[0] - a[0] * b[2]; 
    result[2] = a[0] * b[1] - a[1] * b[0]; 

    return result; 
} 

private static double[] normalize(double[] t) { 
    double length = Math.sqrt((t[0] * t[0]) + (t[1] * t[1]) + (t[2] * t[2])); 
    double[] result = new double[3]; 
    result[0] = t[0]/length; 
    result[1] = t[1]/length; 
    result[2] = t[2]/length; 
    return result; 
} 

private static double[] multiplyByScalar(double[] normalize, double k) { 
    double[] result = new double[3]; 
    result[0] = normalize[0]*k; 
    result[1] = normalize[1]*k; 
    result[2] = normalize[2]*k; 
    return result; 
}