2009-06-26 3 views
4

J'ai besoin d'obtenir la distance d'un point de latitude/longitude à une ligne. Bien sûr, il faut suivre le Grand Cercle.Distance de Point à Ligne fonction de grand cercle ne fonctionne pas bien.

J'ai trouvé un article sur ce sujet à http://www.movable-type.co.uk/scripts/latlong.html

mais le code ne fonctionne pas correctement. Soit je fais quelque chose de mal, soit il manque quelque chose. Voici la fonction en question. Voir le lien pour les autres fonctions si nécessaire.

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

Ce rapports 0,865 miles. La distance réelle est de 4.29905 miles.

Des indices sur la façon de résoudre ce problème? Je ne suis pas un mathématicien, juste un programmeur de longue date.

+0

Moi aussi j'ai quelques problèmes avec le calcul de la distance inter-piste. Je voudrais que vous utilisiez votre code comme exemple pour vérifier mes résultats mais j'ai du mal à comprendre vos coordonnées. Comment se fait-il que vous ayez des valeurs de latitude <-90 quand elle est seulement définie entre -90 et +90? – oschrenk

Répondre

4

La plupart des fonctions trigonométriques ont besoin de radians. Vos mesures angulaires sont-elles en degrés? Peut-être qu'ils doivent être convertis en utilisant la formule habituelle:

2 * π radians = 360 degrés

Si vous regardez sous la formule de formule Haversine, vous verrez ceci:

(Notez que les angles doivent être en radians pour passer aux fonctions trigonométriques).

+0

C'était bien ça! Je suis juste allé vide que la valeur de retour de la méthode de roulement était des degrés. Un slappeur de tête. Merci! –

0

est votre fonction de retour même valeur pour ces coordonnées:

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); 

Je pense qu'il devrait mais la mienne ne fonctionne pas. Le 3e point est toujours 0,1 au nord de l'équateur. seulement les changements de longitude qui ne devraient pas affecter le résultat. Comme cela semble le faire.

0

J'ai essayé pointlinedistancetest envoyer 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; 
} 
Questions connexes