How to rotate a Direction Arrow to particular location
In my app I have a latitude-longitude of 1 fix location. Now user with iPhone device can move anywhere 开发者_开发百科and even he rotate his device, the arrow (some uiimageview) should point to that fix location so User will get direction to that location every time. I tried as follows.
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D here = newLocation.coordinate;
[self calculateUserAngle:here];
}
-(void) calculateUserAngle:(CLLocationCoordinate2D)user {
NSLog(@"my destination is %f ; %f", fixlocLat, fixlocLon);
degrees = degrees + atan2(sin(fixlocLon-user.longitude)*cos(fixlocLat),cos(user.latitude)*sin(fixlocLat) - sin(user.latitude)*cos(fixlocLat)*cos(fixlocLon-user.longitude));
//get angle between user location and fix location
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
arrow.transform = CGAffineTransformMakeRotation((degrees-newHeading.trueHeading) * M_PI / 180);
}
but the code above will always rotate arrow to approx. 2-3 degree north for every location.
My question looks similar to this Stack Overflow question.but using code from this link I am getting wrong direction. please help me on this.
and also if any idea using accelerometer or gyrodata will be helpful for me.
thanx in advance.
This works for me: to rotate a Direction Arrow to particular location
-(void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
}
-(void) calculateUserAngle:(CLLocationCoordinate2D)current {
double x = 0, y = 0 , deg = 0,delLon = 0;
delLon = fixLon - current.longitude;
y = sin(delLon) * cos(fixLat);
x = cos(current.latitude) * sin(fixLat) - sin(current.latitude) * cos(fixLat) * cos(delLon);
deg = RADIANS_TO_DEGREES(atan2(y, x));
if(deg<0){
deg = -deg;
} else {
deg = 360 - deg;
}
degrees = deg;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
CLLocationCoordinate2D here = newLocation.coordinate;
[self calculateUserAngle:here];
}
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
arrow.transform = CGAffineTransformMakeRotation((degrees-newHeading.trueHeading) * M_PI / 180);
}
this code may help you
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
// Use the true heading if it is valid.
CLLocationDirection direction = newHeading.magneticHeading;
CGFloat radians = -direction / 180.0 * M_PI;
self.strAccuracy = [NSString stringWithFormat:@"%.1fmi",newHeading.headingAccuracy];
[lblAccuracy setText:self.strAccuracy];
//Rotate Bearing View
[self rotateBearingView:bearingView radians:radians];
//For Rotate Niddle
CGFloat angle = RadiansToDegrees(radians);
[self setLatLonForDistanceAndAngle];
[self rotateArrowView:arrowView degrees:(angle + fltAngle)];
}
-(void)rotateArrowView:(UIView *)view degrees:(CGFloat)degrees
{
CGAffineTransform transform = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
view.transform = transform;
}
-(void)setLatLonForDistanceAndAngle
{
dblLat1 = DegreesToRadians(appDelegate.dblLatitude);
dblLon1 = DegreesToRadians(appDelegate.dblLongitude);
dblLat2 = DegreesToRadians(objClsProductSearch.dblLatitude);
dblLon2 = DegreesToRadians(objClsProductSearch.dblLongitude);
fltLat = dblLat2 - dblLat1;
fltLon = dblLon2 - dblLon1;
}
-(float)getAngleFromLatLon
{
//Calculate angle between two points taken from http://www.movable-type.co.uk/scripts /latlong.html
double y = sin(fltLon) * cos(dblLat2);
double x = cos(dblLat1) * sin(dblLat2) - sin(dblLat1) * cos(dblLat2) * cos(dblLon2);
CGFloat angle = RadiansToDegrees(atan2(y, x));
return angle;
}
-(void)viewDidLoad
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
locationManager.distanceFilter = kCLDistanceFilterNone;
[locationManager startUpdatingLocation];
[locationManager startUpdatingHeading];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
GeoAngle = [self setLatLonForDistanceAndAngle:newLocation];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations
{
CLLocation *location=[locations lastObject];
GeoAngle = [self setLatLonForDistanceAndAngle:location];
}
-(float)setLatLonForDistanceAndAngle:(CLLocation *)userlocation
{
float lat1 = DegreesToRadians(userlocation.coordinate.latitude);
float lon1 = DegreesToRadians(userlocation.coordinate.longitude);
float lat2 = DegreesToRadians(Destination lattitude);
float lon2 = DegreesToRadians(Destination Longitude);
float dLon = lon2 - lon1;
float y = sin(dLon) * cos(lat2);
float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
float radiansBearing = atan2(y, x);
if(radiansBearing < 0.0)
{
radiansBearing += 2*M_PI;
}
return radiansBearing;
}
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
float direction = -newHeading.trueHeading;
arrow.transform=CGAffineTransformMakeRotation((direction* M_PI / 180)+ GeoAngle);
}
Try this example. Its in C# Xamarin tho :) "double heading" is the CLHeading.MagneticHeading from the eventobject in CLLocationManager.UpdatedHeading.
void UpdateCompass(Location origin, Location target, double heading)
{
var angle1 = GetAngleBetweenPoints(origin, target);
var angle2 = GetAngleFromHeading(heading);
var radian = Math.PI * (angle1 + angle2) / 180.0;
CompassArrow.Transform = CGAffineTransform.MakeRotation((nfloat)radian);
}
double GetAngleBetweenPoints(Location origin, Location target)
{
var n = 270 - (Math.Atan2(origin.Latitude - target.Latitude, origin.Longitude - target.Longitude)) * 180 / Math.PI;
return n % 360;
}
double GetAngleFromHeading(double heading)
{
var radians = -heading / 180.0 * Math.PI;
return radians * (180.0 / Math.PI);
}
精彩评论