12

在我的应用程序中,我有1个固定位置的经度 - 纬度。现在,使用iPhone设备的用户可以在任何地方移动,甚至他可以旋转他的设备,箭头(某些uiimageview)应该指向该修复位置,以便用户每次都可以获取指向该位置的路线。我尝试如下。如何将方向箭头旋转到特定位置

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

,但上面的代码将永远旋转箭头约。每个位置向北2-3度。

我的问题与this Stack Overflow question类似,但使用此链接中的代码我得到错误的方向。 请帮助我。

以及使用加速度计或gyrodata的任何想法对我都有帮助。

thanx提前。

+0

位置有多远?如果距离很远,则可能需要[大圆距离](http://en.wikipedia.org/wiki/Great-circle_distance)计算。 – RabinDev

+0

我们如何使用xcode(物镜c)中的大圆距离计算和距离可以远远大约。千公里。 – Dhawal

+0

距离是可变的,它会随着用户移动而更新,但范围大约在0到1000km之间。 – Dhawal

回答

10

这段代码可以帮助你

-(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; 
} 
+0

thanx为答案和只是1查询;这个方法怎么样 - [self rotateBearingView:bearingView radians:radians];这个方法是什么? – Dhawal

+0

我刚刚在产品位置的方向上旋转了一个车速表种类图像 – NIKHIL

+4

您在哪里使用getAngleFromLatLon? –

15

这对我的作品:以箭头的方向旋转到特定位置

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

我最近实现了这一点,但是当箭头直接指向相反的方向时,它一直有偶然的问题。这就像箭头被镜像。你有什么想法,为什么会发生? – Chris

+1

什么是“fixLon”和“fixLat”?在代码中找不到任何定义或声明 –

+2

@chiragshah这些是您希望箭头指向的固定位置的坐标 – SteBra

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

也许是说明它的作用以及OP出错的位置? –

+0

尝试这一个它会帮助你。 – ShigaSuresh

+0

这对iOS 8来说非常适合我!谢谢。 –

0

试试这个例子。它在C#Xamarin tho :) “双标题”是来自CLLocationManager.UpdatedHeading中eventobject的CLHeading.MagneticHeading。

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