3

iPhone の GPS とコンパスを使用して、ある種のポインターを特定の場所に向けるアプリケーションを開発しようとしています (コンパスが常に北を指すように)。場所は固定されており、ユーザーがどこにいても、その特定の場所を指すポインターが常に必要です。私はこの場所の緯度/経度座標を持っていますが、コンパスと GPS を使用してその場所を指す方法がわかりません... http://www.youtube.com/watch?v=iC0Xn8hY80wこのリンク 1 のように: 20'

私はいくつかのコードを書いていますが、正しい方向に回転することはできません。

-(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

        ^
        |
        | 
        |
        :
        |
    */
4

4 に答える 4

5

使用できる標準の「見出し」または「方位」方程式があります。緯度 1、経度 1 にあり、関心のあるポイントが緯度 2、経度 2 にある場合、方程式は次のようになります。

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

これにより方位がラジアンになり、180/π を掛けることで度に変換できます。値は -180 度から 180 度の間であるため、標準的なコンパスの方位を取得するには、負の回答に 360 を追加します。

atan2 は、arctan に関連する標準関数であり、現在の場所と比較して目的地が存在する可能性のある 4 つの象限に対して正しいことを行います。

于 2010-11-02T09:14:20.467 に答える
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);

コンパイルするにはそれを微調整する必要があるかもしれませんが、アイデアはそこにあります!

于 2010-10-13T13:30:34.790 に答える
1

私はこれを少し前に行いました。ここに 2 つの異なる実装があります。1つ目はあなたのアプローチに似ています.2つ目は三角関数なしです. 1 つ目は私がアプリで使用したものですが、2 つ目も同様に機能しているように見えましたが、それほどクリーンではないようです。また、UI で北に基づいてこの方位をオフセットすることも忘れないでください。

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

そして2番目。

// 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;

}

于 2010-11-09T06:34:44.617 に答える
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));         
}
于 2010-11-05T17:45:49.143 に答える