web-dev-qa-db-fra.com

Calculer le roulement entre deux cllouerCoordinate2DS

Problème très "simple": donné deux cllouerCoordinated2DS, comment puis-je obtenir le roulement (comme radians) du premier à la seconde? J'ai fait beaucoup de recherches et d'étudier à la fois le problème général et l'objectif-c/cacao touch/iOS spécifiquement.

Voici ma mise en œuvre:

- (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 ne renvoie pas des résultats consistants pour moi. Si le roulement est proche du nord ou du sud du Sud, il semble que toute autre direction semble renvoyer des données incompatibles, par exemple:

À partir du 50.405018, 8.437500

Au 51.339802, 12.403340

Ma méthode renvoie: 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.40334 )

J'ai vérifié deux fois que la formule est correcte. J'ai aussi reporté que j'ai vérifié un tas de valeurs comme l'exemple ci-dessus, certains correct, certains faux. J'ai joué avec divers modulos ou délimitation de la valeur de retour, aussi pas de chance.

Des idées? Y a-t-il un problème avec mon code? Peut-être que j'ai mal compris quelque chose sur la façon dont les fonctions mathématiques fonctionnent?

38
James J

Votre calcul est correct, avec les exceptions suivantes:

  1. Assurez-vous de convertir plat, flon, tlat, et tlon aux radians avant d'appliquer tout ) ou COS () pour eux. Divisez de 180,0 et multiplié par PI.

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

Avec ces changements, je reçois 1.18660677830947 Radians avec des mathématiques à double précision et les valeurs de la question.

31
Oren Trutner

Ici, 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 radiansToDegrees(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 = radiansToDegrees(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;
    }
}
52
megabri

SWIFT 3:

extension CLLocationCoordinate2D {
    func bearing(to point: CLLocationCoordinate2D) -> Double {
        func degreesToRadians(_ degrees: Double) -> Double { return degrees * Double.pi / 180.0 }
        func radiansToDegrees(_ radians: Double) -> Double { return radians * 180.0 / Double.pi }

        let lat1 = degreesToRadians(latitude)
        let lon1 = degreesToRadians(longitude)

        let lat2 = degreesToRadians(point.latitude);
        let lon2 = degreesToRadians(point.longitude);

        let dLon = lon2 - lon1;

        let y = sin(dLon) * cos(lat2);
        let x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
        let radiansBearing = atan2(y, x);

        return radiansToDegrees(radiansBearing)
    }
}
10
Sahil Kapoor