Calcul du relèvement entre deux CLLocationCoordinate2Ds

Problème très "simple": étant donné deux CLLocationCoordinate2Ds, comment puis-je get le relèvement (en radians) du premier au second? J'ai fait beaucoup de search et d'étude à ce sujet, à la fois le problème général et Objective-C / Cocoa 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 returnne pas des résultats constants pour moi. Si le relèvement est proche du nord ou du sud, il semble que tout va bien, mais toute autre direction semble renvoyer des données inconsistantes, par exemple:

De 50.405018, 8.437500

À 51.339802, 12.403340

Ma méthode returnne: 5.918441 radians

Doit ê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 double et sortingple vérifié la formule est correcte. J'ai également vérifié un tas de valeurs comme l'exemple ci-dessus, certains corrects, certains faux. J'ai joué avec divers modulos ou la limite de la valeur de return, 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 le fonctionnement des fonctions mathématiques?

Votre calcul est correct, avec les exceptions suivantes:

  1. Assurez-vous de convertir fLat , fLon , tLat et tLon en radians avant d'y appliquer sin () ou cos () . 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, j'obtiens 1.18660677830947 radians avec les maths de double précision et les valeurs dans la question.

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

Swift 3:

 func getBearing(toPoint point: CLLocationCoordinate2D) -> Double { func degreesToRadians(degrees: Double) -> Double { return degrees * M_PI / 180.0 } func radiansToDegrees(radians: Double) -> Double { return radians * 180.0 / M_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) } 

vous pouvez utiliser mon code .. c'est un travail sur mon projet avec un microcontroller qui utilise le GPS pour datatables.

 #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; } }