我正在尝试开发一个使用iPhone的GPS和指南针的应用程序,以便指向某个特定位置的指针(就像指南针总是指向北方)。位置是固定的,无论用户位于何处,我总是需要指针指向该特定位置。我有这个位置的Lat / Long坐标,但不知道如何使用指南针和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
^
|
|
|
:
|
*/
答案 0 :(得分: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相关的标准功能,它可以为您的目的地点所处的四个可能象限做正确的事情。
答案 1 :(得分: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);
你可能不得不调整它来编译,但想法就在那里!
答案 2 :(得分:1)
我之前做过这个,这里有两个不同的实现。第一个类似于你的方法,第二个是没有trig数学。第一个是我在我的应用程序中使用的,但第二个似乎也工作,虽然看起来并不干净。您还需要记住在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;
}
答案 3 :(得分: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));
}