CLLocation Category for Calculating Bearing w/ Haversine function
Your code seems fine to me. Nothing wrong with the calculous. You don't specify how far off your results are, but you might try tweaking your radian/degrees converters to this:
double DegreesToRadians(double degrees) {return degrees * M_PI / 180.0;};
double RadiansToDegrees(double radians) {return radians * 180.0/M_PI;};
If you are getting negative bearings, add 2*M_PI
to the final result in radiansBearing (or 360 if you do it after converting to degrees). atan2 returns the result in the range -M_PI
to M_PI
(-180 to 180 degrees), so you might want to convert it to compass bearings, using something like the following code
if(radiansBearing < 0.0)
radiansBearing += 2*M_PI;
This is a porting in Swift of the Category at the beginning:
import Foundation
import CoreLocation
public extension CLLocation{
func DegreesToRadians(_ degrees: Double ) -> Double {
return degrees * M_PI / 180
}
func RadiansToDegrees(_ radians: Double) -> Double {
return radians * 180 / M_PI
}
func bearingToLocationRadian(_ destinationLocation:CLLocation) -> Double {
let lat1 = DegreesToRadians(self.coordinate.latitude)
let lon1 = DegreesToRadians(self.coordinate.longitude)
let lat2 = DegreesToRadians(destinationLocation.coordinate.latitude);
let lon2 = DegreesToRadians(destinationLocation.coordinate.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 radiansBearing
}
func bearingToLocationDegrees(destinationLocation:CLLocation) -> Double{
return RadiansToDegrees(bearingToLocationRadian(destinationLocation))
}
}