Frage

Ich brauche den Abstand von einem lat / lng Punkt auf eine Linie zu bekommen. Natürlich braucht der Great Circle zu folgen.

Ich fand einen großen Artikel über diese unter http: //www.movable -type.co.uk/scripts/latlong.html

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

    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

Das berichtet 0,865 Meilen. Der tatsächliche Abstand ist 4,29905 Meilen.

Jede Hinweise darauf, wie dieses Problem beheben? Ich bin kein Mathematiker, nur einen in die Jahre gekommenen Programmierer.

War es hilfreich?

Lösung

Die meisten trigonometrischen Funktionen benötigen Radiant. Sind Ihre Winkel Maßnahmen in Grad? Vielleicht müssen sie mit der üblichen Formel umgewandelt werden:

  

2 * π Radiant = 360 Grad

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

  

(Beachten Sie, dass Winkel in Radiant sein müssen passieren Funktionen trig).

Andere Tipps

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 dritte Punkt ist immer 0,1 im Norden von Äquator. nur die Längenänderungen, die das Ergebnis nicht beeinflussen sollte. Wie es scheint, es tut.

Ich habe versucht, diese pointlinedistancetest sendet 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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top