38 votes

Le calcul de roulement entre les deux CLLocationCoordinate2Ds

Très "simple" problème: étant donnés deux CLLocationCoordinate2Ds, comment puis-je obtenir le roulement (comme radians) de la première à la seconde? J'ai fait beaucoup de recherche et d'étude sur ce, à la fois le problème général et Objective-C/Cocoa Touch/iOS spécifiquement.

Voici mon oeuvre:

- (float) getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
    float fLat = fromLoc.latitude;
    float fLng = fromLoc.longitude;
    float tLat = toLoc.latitude;
    float tLng = toLoc.longitude;

    return atan2(sin(fLng-tLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(fLng-tLng));         
}

Cependant, cette méthode n'est pas de retour consistante résultats pour moi. Si le roulement est à proximité au nord ou au sud, il semble bien, cependant, toute autre direction semble renvoyer incompatible données, par exemple:

De 50.405018, 8.437500

Pour 51.339802, 12.403340

Ma méthode retourne: 5.918441 radians

Devrait être 1.18660576 radians

(voir http://www.movable-type.co.uk/scripts/latlong.html et http://www.movable-type.co.uk/scripts/latlong-map.html?lat1=50.405018&long1=8.437500&lat2=51.339802&long2=12.403340)

J'ai le double et le triple vérifié la formule est correcte. J'ai également vérifiés au hasard un tas de valeurs comme l'exemple ci-dessus, une bonne, une mauvaise. J'ai joué avec les modulos ou de délimitation de la valeur de retour, aussi pas de chance.

Des idées? Est-il un problème avec mon code? Peut-être que j'ai mal compris quelque chose à propos de la façon dont les fonctions mathématiques de travail?

52voto

megabri Points 286

Voici le code modifié avec les modifications suggérées par Oren Trutner et de moi-même:

#define degreesToRadians(x) (M_PI * x / 180.0)
#define radiandsToDegrees(x) (x * 180.0 / M_PI)

- (float)getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc
{
    float fLat = degreesToRadians(fromLoc.latitude);
    float fLng = degreesToRadians(fromLoc.longitude);
    float tLat = degreesToRadians(toLoc.latitude);
    float tLng = degreesToRadians(toLoc.longitude);

    float degree = radiandsToDegrees(atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)));

    if (degree >= 0) {
        return degree;
    } else {
        return 360+degree;
    }
}

31voto

Oren Trutner Points 12125

Votre calcul est correct, avec les exceptions suivantes:

  1. Assurez-vous de convertir plat, fLon, tLat, et tLon en radians avant l'application de tout péché() ou cos() pour eux. Diviser par 180.0 et multiplier par PI.

  2. Entrez le delta entre tLng et fLng comme tLng-fLng, et non l'inverse. Notez que cette différence apparaît deux fois dans l'expression.

Avec ces changements, je suis 1.18660677830947 radians avec la double précision, les mathématiques et les valeurs dans la question.

-1voto

Trianto Kontri Points 1

vous pouvez utiliser mon code.. c'est travailler sur mon projet avec microcontrôleur qui utilisent le GPS pour les données.

#define d2r ((22/7.0)/180.0)
#define r2d (180.0/(22/7.0))

double get_heading1(double lat1, double long1, double lat2, double long2)  
{
    double diff_lat, diff_long;
    double degree;

    diff_long =(double) (((long2*1000000)-(long1*1000000))/1000000) * d2r;
    diff_lat = (double) (((lat2*1000000)-(lat1*1000000))/1000000) * d2r;     

    degree = r2d     (atan2(sin(diff_long)*cos(d2r*lat2),cos(d2r*lat1)*sin(d2r*lat2)-sin(d2r*lat1)*cos(d2r*lat2)    *cos(diff_long)));

    if (degree >= 0) {
        return degree;
    } else {
        return 360+degree;
    }                                                                 
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X