滴滴打车车辆转弯的,历史轨迹运动可能都需要这个功能吧.
头几天偶然看见了这个https://www.douban.com/group/topic/38478506/?author=1&start=0,作为程序员都身同感受吧,但是可惜没找到下文,所以今天我们来完成这个功能
让我指向像你
这是他的图片不想看我墨迹一些没营养的下面有地址demo~~
实现思路
- 1 不管手机怎么移动,我的红心手将指向你,所以这应该是一个指南针
- 2 但是我不想指向北方,所以我们之间和北极应该有个角度,找到这个角度,我就找到你了
- 3 应该还有个距离. 这个百度代码很多~~~
好的,我们首先先做个指南针.
1.导入头文件 #import <CoreLocation/CoreLocation.h>
这个框架
签好协议<CLLocationManagerDelegate>
和私有属性@property (nonatomic, strong) CLLocationManager *locationM;
2.然后懒加载
#pragma mark - 懒加载
- (CLLocationManager *)mgr
{
if (!_mgr) {
_mgr = [[CLLocationManager alloc] init];
}
return _mgr;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.mgr startUpdatingHeading];
}
3.实现协议
// 当获取到用户方向时就会调用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
/*
magneticHeading 设备与磁北的相对角度
trueHeading 设置与真北的相对角度, 必须和定位一起使用, iOS需要设置的位置来计算真北
真北始终指向地理北极点
*/
// 1.将获取到的角度转为弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 2.旋转图片
/*
顺时针 正
逆时针 负数
*/
// 因为如果没有动画的话旋转的时候回出现卡顿的现象,为了更流畅,我们给它加个动画
[UIView animateWithDuration:0.1 animations:^{
// 旋转图片
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
}];
}
这个协议方法是一直调用的,不信你打印一下试试,所以最好不要在这里写任何耗时的事,self.compasspointer
是一个图片,这里为了减少资源损耗就不画圆了,用图片是一样的.
- 这样就是一个正经八经的指南针了.下面只要求出来我们之间的角度,就完成了.
好的,我们找角度
1.根据百度的坐标提取系统我们可以知道任意两个点之间的坐标
//我在大连的
float lat1 = 38.927431;
float lng1 = 121.650592;
// 这是北京(假设就是北京)往下一点 116.650592,38.927431
float lat2 = 38.927431;
float lng2 = 116.650592;
2. 求出两个经纬度之间的角度
//两个经纬度之间的角度
-(double)getBearingWithLat1:(double)lat1 whitLng1:(double)lng1 whitLat2:(double)lat2 whitLng2:(double)lng2{
double d = 0;
double radLat1 = [self radian:lat1];
double radLat2 = [self radian:lat2];
double radLng1 = [self radian:lng1];
double radLng2 = [self radian:lng2];
d = sin(radLat1)*sin(radLat2)+cos(radLat1)*cos(radLat2)*cos(radLng2-radLng1);
d = sqrt(1-d*d);
d = cos(radLat2)*sin(radLng2-radLng1)/d;
d = [self angle:asin(d)];
return d;
}
//根据角度计算弧度
-(double)radian:(double)d{
return d * M_PI/180.0;
}
//根据弧度计算角度
-(double)angle:(double)r{
return r * 180/M_PI;
}
我们纬度是一样的,根据上面的公式求出 北京 大连 北极之间的角度
角度3 why? 口算都算出来了,应该是九十度啊?这怎么事八十八度?还是负数?后来我百度了一下真北,磁北,坐标北 ,我就不管这点误差了,当然这是可以处理的.
负数的问题,取个绝对值就好了,先不管这多为啥是负数 5231524215272_.pic.jpg好了,变正数了,正数也可以一个人一个做法,不要吐槽我~
4 接下来为了验证正确性,我们把坐标改成山东东营,
// 获取地理位置坐标的代码就不贴了,我在大连中山广场, 这是我的坐标 121.650592,38.927431
float lat1 = 38.927431;
float lng1 = 121.650592;
// 山东 东营
float lat2 = 37.588364;
float lng2 = 118.593547;
按地图上来看角度应该是一百多度吧,但是打印出来的结果是
2018-04-20 17:14:06.029517+0800 angle[3667:1273780] -61.798896
2018-04-20 17:14:06.029610+0800 angle[3667:1273780] 61.798896
所以我又写了两行代码
if(lat2 < lat1){
s = 180-s;
}
这回打印结果
2018-04-20 17:14:06.029637+0800 angle[3667:1273780] 118.201104
好像对上
但是旋转图片的
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
-a 是根据弧度计算的,值是0 到 2*π, 这个"我指向你的角度"就是 a弧度减去我求出来的角度
//宏定义
#define DEGREES_TO_RADIANS(angle) ( M_PI / 180 * (angle))
self.f = DEGREES_TO_RADIANS(s);
if (lng2 < lng1) {
_f = (M_PI*2 - _f);
}
打印出来2018-04-20 17:14:06.029687+0800 angle[3667:1273780] 4.220187
最后
// 当获取到用户方向时就会调用
- (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
/*
magneticHeading 设备与磁北的相对角度
trueHeading 设置与真北的相对角度, 必须和定位一起使用, iOS需要设置的位置来计算真北
真北始终指向地理北极点
*/
// 1.将获取到的角度转为弧度 = (角度 * π) / 180;
CGFloat angle = newHeading.magneticHeading * M_PI / 180;
// 2.旋转图片
/*
顺时针 正
逆时针 负数
*/
CGFloat a = 0;
a = angle - _f;
// 因为如果没有动画的话旋转的时候回出现卡顿的现象,为了更流畅,我们给它加个动画
[UIView animateWithDuration:0.1 animations:^{
// 旋转图片
self.compasspointer.transform = CGAffineTransformMakeRotation(-a);
}];
}
效果图
正北 北京墨迹完了,我也不知道我做的对不对,有问题一起探讨
下面是项目地址
demo (记得用真机)
Xcode9.3 以下打开会有问题???
网友评论