问题
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.
回答1:
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;
}
回答2:
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);
}
回答3:
-(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);
}
回答4:
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);
}
来源:https://stackoverflow.com/questions/7173925/how-to-rotate-a-direction-arrow-to-particular-location