【问题标题】:Is this the way to make a compass?这是制作指南针的方法吗?
【发布时间】:2011-06-05 17:09:02
【问题描述】:

我的一个 iPhone 应用程序的一部分需要显示一个指向某个位置的指南针。它不是北 - 它是一个位置(使用纬度和经度)。

我想出了下面的解决方案,但想问一下这是否是制作指南针应用程序的最佳方法,是否可以更精确,是否有什么我没有考虑到的?

我制作了这个示例应用程序来向您展示我的代码及其工作原理。 样本上传至http://codeinacup.com/pub/POICompass.tgz

这是源代码的中心:

- (void)viewDidLoad
{
    [super viewDidLoad];

    locationManager = [[CLLocationManager alloc] init];
    [locationManager setDelegate:self];
    [locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
    [locationManager setDistanceFilter:kCLDistanceFilterNone];
    [locationManager startUpdatingLocation];
    [locationManager startUpdatingHeading];

    // Getting the user's location
    CLLocation *location = [locationManager location];
    CLLocationCoordinate2D user = [location coordinate];

    [self calculateAngle:user];
}

- (void)calculateAngle:(CLLocationCoordinate2D)user {
    /*
     We imagine an x,y-coordinate system with the user as center (Q)
     At this point we do not know in which direction the user faces - we assume he faces north.
     The decided location (the Eiffel Tower in Paris for this example) is plotted into the coordinate system as L.
     A third point is made. This is called P. This must be on one of the axis and be perpendicular with the location (L)

     Now we decide if L is in the first (NE), second (SE), third (SW) or fourth (NW) quadrant.
     This is done by comparing the user's latitude (x) and longitude (y) with the latitude (x) and longitude (y) of the location.
     If P is in the first quadrant, we assume that the user is facing north.
     If P is in the second quadrant, we assume that the user is facing east.
     If P is in the third quadrant, we assume that the user is facing south.
     If P is in the fourth quadrant, we assume that the user is facing west.

     Now we can make two vectors: QP (from the user's location (Q) to the point (P)) and QL (from the user's location (Q) to the decided location (L))
     When having two vectors we can calculate the angle (V)

     Now we know the angle between one of the axis to the decided location (L).
     Whenever the iPhone rotates an amount of degrees, we rotate the needle the same amount of degrees in the other direction.

     Check ILLUSTRATION.PNG to see the above illustrated.
    */

    /*
     Q is the location of the user.
     L is the decided location (in this example, the Eiffel Tower)
     P is a point on the axis which is perpendicular with L.
    */

    /*
     (x, y) Coordinates
     x = latitude
     y = longitude
    */

    float locLat = 48.512972;
    float locLon = 2.174017;

    float pLat;
    float pLon;

    if(locLat > user.latitude && locLon > user.longitude) {
        /*
         L is in the first quadrant
         NE
        */

        pLat = user.latitude;
        pLon = locLon;

        degrees = 0;
    }
    else if(locLat > user.latitude && locLon < user.longitude) {
        /*
         L is in the second quadrant
         SE
        */

        pLat = locLat;
        pLon = user.longitude;

        degrees = 45;
    }
    else if(locLat < user.latitude && locLon < user.longitude) {
        /*
         L is in the third quadrant
         SW
        */

        pLat = locLat;
        pLon = user.latitude;

        degrees = 180;
    }
    else if(locLat < user.latitude && locLon > user.longitude) {
        /*
         L is in the fourth quadrant
         NW
        */

        pLat = locLat;
        pLon = user.longitude;

        degrees = 225;
    }
    else {
        NSLog(@"Failed locating.");
    }

    // Vector QP (from user's location to point)
    float vQPlat = pLat - user.latitude;
    float vQPlon = pLon - user.longitude;

    // Vector QL (from user's location to decided location)
    float vQLlat = locLat - user.latitude;
    float vQLlon = locLon - user.longitude;

    // Angle (V) between QP and QL
    float cosDegrees = (vQPlat * vQLlat + vQPlon * vQLlon) / sqrt((vQPlat * vQPlat + vQPlon*vQPlon) * (vQLlat * vQLlat + vQLlon * vQLlon));
    degrees = degrees + acos(cosDegrees);
}

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
    /*
     Everytime the user's location updates we need to call - (void)calculateAngle:user to calculate the degrees
     between the user (Q) and the decided location (L)
    */

    [self calculateAngle:newLocation.coordinate];
}

- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
    /*
     When the phone is rotated, the needle is rotated the same amount of degrees in the other direction
    */

    [needle setTransform:CGAffineTransformMakeRotation((degrees - newHeading.magneticHeading) * M_PI / 180)];
}

【问题讨论】:

    标签: iphone objective-c vector location compass-geolocation


    【解决方案1】:

    这不是办法。具体来说,您对两点之间角度的计算是不正确的,因为它忽略了许多关于纬度和经度的事情,并将其视为笛卡尔坐标系。而是使用very useful article 中的公式。另外,不要根据象限来假设方位,直接使用你从指南针得到的方位。

    【讨论】:

    • 非常感谢。我确实打算将其视为笛卡尔坐标系,但现在,在阅读了这篇文章后,我发现它是错误的。感谢您提供文章的链接。我很难找到与我想要的一样的东西,所以我试着自己做数学,但我发现结果是错误的:-)
    猜你喜欢
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    • 2016-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    相关资源
    最近更新 更多