2010-11-09 53 views
3

我試圖開發使用GPS和iPhone的指南針,以點某種指針到一個特定的位置(如羅盤始終指向北)的應用程序。該位置是固定的,我總是需要指針指向該特定位置,而不管用戶位於何處。我有這個位置的緯度/經度座標,但不知道如何使用指南針和GPS指向那個位置...就像http://www.youtube.com/watch?v=iC0Xn8hY80w這個鏈接1:20'iPhone北斗GPS方向

我寫了一些代碼,但是,它不能正確旋轉。

-(float) angleToRadians:(double) a { 
    return ((a/180)*M_PI); 
} 

-(void)updateArrow {  
    double alon=[longi doubleValue];//source 
    double alat=[lati doubleValue];//source 
    double blon=[pointlongi doubleValue];//destination 
    double blat=[pointlati doubleValue];//destination 

    float fLat = [self angleToRadians:alat]; 
    float fLng = [self angleToRadians:alon]; 
    float tLat = [self angleToRadians:blat]; 
    float tLng = [self angleToRadians:blon]; 

    float temp = atan2(sin(tLng-fLng)*cos(tLat), 
     cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng)); 
    double temp2= previousHeading; 

    double temp1=temp-[self angleToRadians:temp2]; 

    /*I using this,but it can't rotate by :point even i change the coordinate 
     in CGPointMake */ 
    Compass2.layer.anchorPoint=CGPointMake(0, 0.5); 

    [Compass2 setTransform:CGAffineTransformMakeRotation(temp1)]; 
    /* Compass2 is a UIImageView like below picture I want to rotate it around 
    : point in image 

     ^
     | 
     | 
     | 
     : 
     | 
    */ 

回答

1

1)獲取您的當前位置(從GPS)

2)獲取的緯度和經度

3)使用ATAN2方法來獲得角度

即差異(警告:未經測試的代碼)

CLLocation *targetLocation = [CLLocation alloc] initWithLatitude:1 longitude:2]; 
CLLocation *sourceLocation = <get from GPS> 

double dx = [targetLocation coordinate].latitude - [sourceLocation coordinate].latitude; 
double dy = [targetLocation coordinate].longitude - [sourceLocation coordinate].longitude; 

double angle = atan2(dx, dy); 

您可能需要調整以獲得它編譯但這個想法在那裏!

+0

後,我得到的角度。我如何使用指南針實現的當前航向。 – Jessesiu 2010-10-25 16:09:47

+0

我只是使用當前的標題 - 角度。然後旋轉箭頭(當前標題-angle),但我無法得到正確的答案? – Jessesiu 2010-10-25 16:11:28

5

有一個標準的「標題」或「軸承」方程,你可以使用 - 如果你是在LAT1,lon1,你感興趣的是,在LAT2點,lon2,則公式爲:

heading = atan2(sin(lon2-lon1)*cos(lat2), cos(lat1)*sin(lat2) - sin(lat1)*cos(lat2)*cos(lon2-lon1)) 

這給你以弧度,你可以通過180 /π乘以轉換爲角度的軸承。該值然後在-180和180度之間,因此要獲得標準指南針方位,請在任何負面答案中加上360。

atan2是一個與arctan相關的標準函數,它可以爲您的目標點與您所在的位置相比較,確定四個可能的象限。

+0

我希望這可以幫助某人,在做任何事情之前,您必須首先將經緯度轉換爲弧度。這是一個非常有用的鏈接:http://www.movable-type.co.uk/scripts/latlong.html – Mirkules 2011-04-06 22:24:39

0

使用此。您將不得不從getHeadingForDirection的結果中減去實際的羅盤標題以確定適當的相對標題。返回值爲弧度

-(float) angleToRadians:(float) a { 
    return ((a/180)*M_PI); 
} 


- (float) getHeadingForDirectionFromCoordinate:(CLLocationCoordinate2D)fromLoc toCoordinate:(CLLocationCoordinate2D)toLoc 
{ 

    float fLat = [self angleToRadians:fromLoc.latitude]; 
    float fLng = [self angleToRadians:fromLoc.longitude]; 
    float tLat = [self angleToRadians:toLoc.latitude]; 
    float tLng = [self angleToRadians:toLoc.longitude]; 

    return atan2(sin(tLng-fLng)*cos(tLat), cos(fLat)*sin(tLat)-sin(fLat)*cos(tLat)*cos(tLng-fLng));   
} 
1

我之前做過這個,這裏有兩個不同的實現。第一個和你的方法類似,第二個沒有trig數學。第一個是我在我的應用程序中使用的,但第二個似乎也工作得很好,雖然看起來沒有那麼幹淨。您還需要記住在您的用戶界面中根據北向來抵消這種方位。

- (double) toRadian: (double) val 
{ 
    return val * (M_PI/180); 
} 

// Convert to degrees from radians 
- (double) toDegrees: (double) val 
{ 
    return val * 180/M_PI; 
} 

// convert from a radian to a 360 degree format. 
- (double) toBearing: (double) val 
{ 
    return ((int)([self toDegrees: val]) + 360) % 360;  // use mod to get the degrees 
} 

// Calculate the bearing based off of the passed coordinates and destination. 
// 
- (double) calcBearingWithLatitude:(CLLocationDegrees)latSource 
          latitude:(CLLocationDegrees)latDest 
          longitude:(CLLocationDegrees)lonSrc 
          longitude:(CLLocationDegrees)lonDest 
{ 
    double lat1 = [self toRadian:latSource]; 
    double lat2 = [self toRadian:latDest]; 
    double dLon = [self toRadian:(lonDest - lonSrc)]; 

    double y = sin(dLon) * cos(lat2); 
    double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon); 
    return [self toBearing:atan2(y, x)]; 
} 

而第二個。

// got this code from some forums and modified it, thanks for posting it coullis! Mostly here for reference on how to do this without sin and cos. 
- (CLLocationDegrees) altCalcBearingWithLatitude:(CLLocationDegrees)latSource 
             latitude:(CLLocationDegrees)latDest 
             longitude:(CLLocationDegrees)lonSrc 
             longitude:(CLLocationDegrees)lonDest 

{ 
    CLLocationDegrees result; 


// First You calculate Delta distances. 
float dx = lonSrc - latSource; 
float dy = lonDest - latDest; 

// If x part is 0 we could get into division by zero problems, but in that case result can only be 90 or 270: 
if (dx==0) 
{ 
    if (dy > 0) 
     result = 90; 
    else 
     result = 270; 
} 
else 
{ 
    result = [self toDegrees: atan(dy/dx)]; 
} 

// This is only valid for two quadrants (for right side of the coordinate system) so modify result if necessary... 
if (dx < 0) 
    result = result + 180; 

// looks better if all numbers are positive (0 to 360 range) 
if (result < 0) 
    result = result + 360; 

// return our result. 
return result; 

}