美文网首页程序员
iOS 根据两个经纬度计算与地理北极夹角

iOS 根据两个经纬度计算与地理北极夹角

作者: 卖女孩的小match | 来源:发表于2018-04-20 17:28 被阅读36次

    滴滴打车车辆转弯的,历史轨迹运动可能都需要这个功能吧.

    头几天偶然看见了这个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. 这样就是一个正经八经的指南针了.下面只要求出来我们之间的角度,就完成了.

    好的,我们找角度

    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 以下打开会有问题???

    相关文章

      网友评论

        本文标题:iOS 根据两个经纬度计算与地理北极夹角

        本文链接:https://www.haomeiwen.com/subject/csqzkftx.html