开发者

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜