I am trying to develop a compass for an appliation which has a set of annotations on a map. I would like to be able to choose an annotation and then have the compass point the user to the chosen location.
I have calculated the degress from the user's location to the location of the annotation and I have the magnetic heading and the true heading of the iPhone. Also I know how to rotate an image. But I can't figure out what the next step is.
The degrees between the user's location and the annotation location is calculated like this:
// get user location
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
CLLocation *location = [locationManager location];
CLLocationCoordinate2D coordinate = [location coordinate];
float x1 = coordinate.latitude;
float y1 = coordinate.longitude;
float x2 = [annLatitude floatValue];
float y2 = [annLongitude floatValue];
float dx = (x2 - x1);
float dy = (y2 - y1);
if (dx == 0) {
if (dy > 0) {
result = 90;
}
else {
result = 270;
}
}
else {
result = (atan(dy/dx)) * 180 / M_PI;
}
if (dx < 0) {
result = result + 180;
}
if (result < 0) {
result = result + 360;
}
The true and the magnetic heading is retrieved like this:
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
arrow.transform = CGAffineTransformMakeRotation(newHeading.magneticHeading);
// NSLog(@"magnetic heading: %f", newHeading.magneticHeading);
// NSLog(@"true heading: %f", newHeading.trueHeading);
}
Can anyone tell me what I should do now to make the arrow point to the location - even if the iPhone is rotated?
Place the straight edge of the compass's base along the line, and point its direction-of-travel arrow in the direction you want to go. Rotate the bezel until the orienting lines align with the grid lines running north to south on the map. The north marker on the compass' bezel should point north on the map.
I had time to play with this again.
This will do it:
- (void)viewDidLoad {
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
CLLocation *location = [locationManager location];
CLLocationCoordinate2D user = [location coordinate];
[self calculateUserAngle:user];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D here = newLocation.coordinate;
[self calculateUserAngle:here];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
compass.transform = CGAffineTransformMakeRotation(newHeading.magneticHeading * M_PI / 180);
needle.transform = CGAffineTransformMakeRotation((degrees - newHeading.magneticHeading) * M_PI / 180);
}
-(void) calculateUserAngle:(CLLocationCoordinate2D)user {
locLat = [[targetLocationDictionary objectForKey:@"latitude"] floatValue];
locLon = [[targetLocationDictionary objectForKey:@"longitude"] floatValue];
NSLog(@"%f ; %f", locLat, locLon);
float pLat;
float pLon;
if(locLat > user.latitude && locLon > user.longitude) {
// north east
pLat = user.latitude;
pLon = locLon;
degrees = 0;
}
else if(locLat > user.latitude && locLon < user.longitude) {
// south east
pLat = locLat;
pLon = user.longitude;
degrees = 45;
}
else if(locLat < user.latitude && locLon < user.longitude) {
// south west
pLat = locLat;
pLon = user.latitude;
degrees = 180;
}
else if(locLat < user.latitude && locLon > user.longitude) {
// north west
pLat = locLat;
pLon = user.longitude;
degrees = 225;
}
// Vector QP (from user to point)
float vQPlat = pLat - user.latitude;
float vQPlon = pLon - user.longitude;
// Vector QL (from user to location)
float vQLlat = locLat - user.latitude;
float vQLlon = locLon - user.longitude;
// degrees between QP and QL
float cosDegrees = (vQPlat * vQLlat + vQPlon * vQLlon) / sqrt((vQPlat*vQPlat + vQPlon*vQPlon) * (vQLlat*vQLlat + vQLlon*vQLlon));
degrees = degrees + acos(cosDegrees);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With