Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/44.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
iPhone罗盘GPS方向_Iphone_Gps_Location_Compass Geolocation - Fatal编程技术网

iPhone罗盘GPS方向

iPhone罗盘GPS方向,iphone,gps,location,compass-geolocation,Iphone,Gps,Location,Compass Geolocation,我正在尝试开发一个应用程序,它使用iPhone的GPS和指南针来指向某个特定的位置(比如指南针总是指向北方)。位置是固定的,无论用户位于何处,我始终需要指向该特定位置的指针。我有这个位置的纵横坐标,但不确定如何使用指南针和GPS指向那个位置。。。就像这个链接1:20' 我写了一些代码,但是,它不能向正确的方向旋转 -(float) angleToRadians:(double) a { return ((a/180)*M_PI); } -(void)updateArrow {

我正在尝试开发一个应用程序,它使用iPhone的GPS和指南针来指向某个特定的位置(比如指南针总是指向北方)。位置是固定的,无论用户位于何处,我始终需要指向该特定位置的指针。我有这个位置的纵横坐标,但不确定如何使用指南针和GPS指向那个位置。。。就像这个链接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

        ^
        |
        | 
        |
        :
        |
    */
1) 获取您当前的位置(从GPS)

2) 获取纬度和经度的差异

3) 使用atan2方法获取角度

i、 e.(警告:未测试代码)

CLLocation*targetLocation=[CLLocation alloc]initWithLatitude:1经度:2];
CLLocation*sourceLocation=
双dx=[targetLocation坐标].纬度-[sourceLocation坐标].纬度;
双dy=[targetLocation坐标].经度-[sourceLocation坐标].经度;
双角度=atan2(dx,dy);
你可能需要调整它来编译它,但是想法就在那里

您可以使用一个标准的“航向”或“方位”方程式-如果您在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相关的标准函数,它对目标点可能位于的四个象限与您所在的位置进行了比较。请使用此函数。您必须从getHeadingForDirection的结果中减去实际的罗盘航向,以确定正确的相对航向。返回值以弧度表示


我不久前做过这件事,这里有两种不同的实现。第一种方法与您的方法类似,第二种方法没有三角数学。第一个是我在我的应用程序中使用的,但第二个似乎也能工作,尽管看起来没有那么干净。您还需要记住在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)];
}
第二个

// 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;
//从一些论坛获得此代码并对其进行了修改,感谢您在coullis发布此代码!这里主要是为了参考如何做到这一点没有罪恶和原因。
-(CLLocationDegrees)AltCalcBearingwithLattitude:(CLLocationDegrees)纬度源
纬度:(CLLocationDegrees)最晚
经度:(CLLocationDegrees)lonSrc
经度:(CLLocationDegrees)最远
{
CLLocationDegrees结果;
//首先计算增量距离。
float dx=lonSrc-latSource;
浮动dy=最长-最晚;
//如果x part为0,我们可以进入零问题除法,但在这种情况下,结果只能是90或270:
如果(dx==0)
{
如果(dy>0)
结果=90;
其他的
结果=270;
}
其他的
{
结果=[自回归:atan(dy/dx)];
}
//这只对两个象限(坐标系的右侧)有效,所以在必要时修改结果。。。
if(dx<0)
结果=结果+180;
//如果所有数字都为正数(0到360范围),效果会更好
如果(结果<0)
结果=结果+360;
//返回我们的结果。
返回结果;

}

在我得到角度后。如何使用当前航向通过罗盘实现。我只使用当前航向-角度。然后旋转箭头(当前航向-角度),但我不能得到正确的答案?我希望这对某人有所帮助,在做任何其他事情之前,您必须先将纬度/经度转换为弧度。这里有一个非常有用的链接:
- (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;