• 根据坐标点显示地图显示范围(高德地图)


    对于以下问题系统方法有实现:

    过滤不合理点   CLLocationCoordinate2DIsValid 就可以搞定。。。。0.0

    ====================分割线啊分割线===以下活脱重新造了把轮子============================

    /**

     *  过滤不合理点

     *

     *  @param locations locations description

     *

     *  @return return value description

     */

    -(NSMutableArray *)getShowAnnotationArr:(NSArray *)locations{

        CGFloat minLon = -90;

        CGFloat maxLon = 90;

        //解决跨国际日期变更线时 跨度计算错误

        NSMutableArray *nArr = [NSMutableArray arrayWithCapacity:0];//东经 

        NSMutableArray *wArr = [NSMutableArray arrayWithCapacity:0];//西经 

        

        //把坐标点按东经  西经 分组

        [locations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

            CLLocation * annotation = locations[idx];

            if (fmin(0.0, annotation.coordinate.longitude) == 0) {

                [nArr addObject:annotation];

            }else{

                [wArr addObject:annotation];

            }

        }];

        //最终转换后,可以显示在地图上得点

        NSMutableArray *showArr = nil;

        //判断 按(东、西)经度的两个分组, 最少的转成最多的(比如东经少于西经,那么将东经转成西经表示)

        if ([nArr count] != [wArr count] && [wArr count]>0 && [nArr count]>0) {

            NSMutableArray *rangInArr = [NSMutableArray arrayWithCapacity:0];//  -90 <=lon<=90 范围内的点

            NSMutableArray *rangOutArr = [NSMutableArray arrayWithCapacity:0];//  lon <=-90 && lon >=90 范围内的点

            

            //将所有坐标点按 上面范围分组

            [locations enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

                CLLocation * annotation = locations[idx];

                if (annotation.coordinate.longitude >=minLon && annotation.coordinate.longitude <=maxLon) {

                    [rangInArr addObject:annotation];

                }else{

                    [rangOutArr addObject:annotation];

                }

                

            }];

            // 将最少的一组剔除,保留最多的一组。即可以正常显示的点

            if ([rangOutArr count]<[rangInArr count]) {

                showArr = [rangInArr mutableCopy];

            }else{

                showArr = [rangOutArr mutableCopy];

            }

            //清空第一次分组后东西经分组。

            [wArr removeAllObjects];

            [nArr removeAllObjects];

            //重新装入数据(这时是已经过滤了的数据,再次分组按东、西经)

            [showArr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

                CLLocation * annotation = showArr[idx];

                if (fmin(0.0, annotation.coordinate.longitude) == 0) {

                    [nArr addObject:annotation];

                }else{

                    [wArr addObject:annotation];

                }

            }];

            [showArr removeAllObjects];

            

            if ([wArr count] > [nArr count]) {

                //将东经 转换为 西经

                [nArr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

                    CLLocation * annotation = nArr[idx];

                    

                    CGFloat tunrnNLon = 0.0;

                    if (annotation.coordinate.longitude >=90  && annotation.coordinate.longitude<= 180) {

                        tunrnNLon =  -180+(annotation.coordinate.longitude - 180);

                    }else{

                        tunrnNLon = annotation.coordinate.longitude;

                    }

                    

                    CLLocation *newLoctaion = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:tunrnNLon];

                    

                    [wArr addObject:newLoctaion];

                }];

                showArr = wArr;

            }else{

                //将西经 转换为东经

                [wArr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {

                    CLLocation * annotation = wArr[idx];

                    

                    CGFloat tunrnWLon = 0.0;

                    /**

                     *  转换规则

                     *  如果 西经在 w<=0 && w>=-90 则东经一定在 0<= n <=90 则不需要处理。

                     *  相反  -90<= w <=-180  时,则东经一定在   90<= n <= 180 需要处理,把西经转换为东经。

                     *  因为如果不转换在 算经度跨度  maxW - minW*系数  >= 180。则地图显示不出,会崩掉。

                     */

                    if (annotation.coordinate.longitude <=0 && annotation.coordinate.longitude>=-90) {//

                        tunrnWLon = annotation.coordinate.longitude;

                    }else{

                        tunrnWLon = 180 +(180 +annotation.coordinate.longitude);

                    }

                    CLLocation *newLoctaion = [[CLLocation alloc] initWithLatitude:annotation.coordinate.latitude longitude:tunrnWLon];

                    [nArr addObject:newLoctaion];

                }];

                //转换后的点(都是以东经表示的电,即都是正数)

                showArr = nArr;

            }

            

            

        }else{

            showArr = [NSMutableArray arrayWithArray:locations] ;

        }

        return showArr;

    }

     

    说明:

           该算法原型 http://stackoverflow.com/questions/10222308/zoom-mapview-to-a-region-where-pins-are-dropped

     原算法在大部分情况下效果不错。但有个bug .

      

    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; 
    
        // Add a little extra space on the sides 
        region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; 

    这段代码如果在计算的数组里包含  西经-175 东经175的情况下就会奔溃。原因是地图只能显示 经度跨度小于或等于180的区域。参与计算后结果会大于180.

        region = [mapView regionThatFits:region];

     执行后也依然如此。

    纬度则不会出现这种情况。北纬90 到 南纬-90 怎么也不会出现大于180 的纬度跨度出现。

    即如果数组里有跨国际日期变更线 的坐标点存在时。就会出现这种情况。如新西兰 就是个跨国际日期变更线的国家

    国际日期变更线(西经-180 和 东经180 重合的那条线 ),可以理解地球被 经度0 和国际日期变更线所绕的”圆“ 切成东西半球。

    我得解决办法是 将数组安 东经(+)和 西经(-)分组。比较count 。如果东经 的坐标点 大于西经。则转换 西经为 ”东经“(一个正数)。

    如: 西经 -176  转东经 为 180+(180+(-176))。是的,按照东经的增长顺序  将西经转换成一个大于180的 正数。然后参与计算。并平均出来。

    东经转西经也是同样道理。

    改进后对于大多数 情况下新算法 显示正常。即使是跨国际日期变更线。但是 依然有些情况下会超出 180在最后计算出得经度跨度值。

    例如:

    一个 西经-40 的点  和  东经176 的点。

    计算出来 经度跨度依然会大于 180.

    郁闷了一段时间,发现了个规律。

     就是显示的区域要么在

    -90 ~0~90

    -180 ~0

    0~180

    想象一个球,你均匀的切两刀(竖着切没有切开)变成4瓣。旋转这个球每次旋转90度。就会出现上面的假设。

    在遵循上面假设的前提下,如果你要看 东经 90到180这个跨度里的任一点,和 西经 -90到0这个跨度里的任一点。即 连个不是相邻的连个瓣你需要”透视眼“。没办法在平面上显现在。

    所有根据这个原理,我把不属于-90 ~0~90的点和 属于这个区域的点分开。

    剔除不属于这个区域的点,就是最后可以正常显示在地图上且经度跨度不会超过180 。

    ....貌似有点稀里糊涂。希望有地理帝 给指点一二,说说其中原理。和这个算法的正确与否。

    目前项目中这个算法运行良好,有不同建议欢迎讨论。

  • 相关阅读:
    令Django 视图有默认 login_required
    sql语句 case
    java进制转换
    倒水问题
    全排列
    数据库范式
    操作系统——磁盘设备管理
    Windows系统安装MySQL
    Java题库——Chapter16 JavaFX UI组件和多媒体
    Java题库——Chapter15 事件驱动编程和动画
  • 原文地址:https://www.cnblogs.com/DamonTang/p/4505769.html
Copyright © 2020-2023  润新知