iOS地图结构体数组坐标构造

使用地图API开发前前后后也有三年了吧,从使用高德转战腾讯,对这个地图坐标构造数组总是不太熟悉,每次遇到了就查资料粘贴复制,耽误时间,这里记录一下,方便未来查找。

1.腾讯地图3D配置方案https://lbs.qq.com/ios_v1/guide-3d.html

常规流程,
添加sdk,
添加bundle资源文件(这里最好添加上,否则第一次加载地图资源会出现各种意想不到的问题)
-ObjC,
添加各种依赖

2.0设置起点和终点的位置

    QPointAnnotation * startAnnotation;
    QPointAnnotation * endAnnotation;

    NSString * startLat = @"19.967205";
    NSString * startLon = @"110.410133";
    
    NSString * endLat = @"20.040722";
    NSString * endLon = @"110.231647";

    self.annotations = [NSMutableArray array];
    
    startAnnotation = [[QPointAnnotation alloc] init];
    startAnnotation.coordinate = CLLocationCoordinate2DMake([startLat doubleValue],[startLon doubleValue]);
    [self.annotations addObject:startAnnotation];
    
    endAnnotation = [[QPointAnnotation alloc] init];
    endAnnotation.coordinate = CLLocationCoordinate2DMake([endLat doubleValue],[endLon doubleValue]);
    [self.annotations addObject:endAnnotation];
    [self.mapView addAnnotations:self.annotations];

2.1设置起点和终点的UI

自定义一个CustomAnnotationView类

@interface CustomAnnotationView : QAnnotationView

自定义遮盖物子类基本代码实现

- (instancetype)initWithAnnotation:(id<QAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier])
    {
        
        self.bounds = CGRectMake(0, 0, 24, 38);
        [self setupLabelAndImage];
        self.centerOffset = CGPointMake(0, 0);
        self.backgroundColor = [UIColor clearColor];
    }
    
    return self;
}

-(void)setIconImageStr:(NSString *)iconImageStr
{
    _iconImageStr = iconImageStr;
    UIImage * image = [UIImage imageNamed:_iconImageStr];
    self.imageView = [[UIImageView alloc] initWithImage:image];
    self.imageView.frame = CGRectMake(0, 0, 24, 38);
    [self addSubview:self.imageView];
}

2.2地图添加遮盖物代理

- (QAnnotationView *)mapView:(QMapView *)mapView viewForAnnotation:(id<QAnnotation>)annotation
{
    if ([annotation isKindOfClass:[QPointAnnotation class]])
    {
        static NSString *pointReuseIndetifier = @"pointReuseIndetifier";
        CustomAnnotationView *annotationView = (CustomAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndetifier];
        
        if (annotationView == nil)
        {
            annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndetifier];
        }
        annotationView.canShowCallout   = NO;
        
        if (annotation == startAnnotation) {
            annotationView.iconImageStr = @"map_icon_origin";
        }else if(annotation == endAnnotation)
        {
            annotationView.iconImageStr = @"map_icon_destination";
        }else
        {
            annotationView.iconImageStr = @"order_icon_finish";
        }
        return annotationView;
    }
    return nil;
    
    
}

3.路线规划服务 https://lbs.qq.com/webservice_v1/guide-road.html

腾讯地图webserviceAPI提供的算路接口,通过get请求传入起点和终点坐标,可以规划出一条路线。返回的规划数据中,坐标点集polyline会有压缩。

4.0坐标解压服务

https://lbs.qq.com/webservice_v1/guide-road.html#link-seven
腾讯地图解压缩示例

var coors=[127.496637,50.243916,-345,-1828,19867,-26154];
for (var i = 2; i < coors.length ; I++)
{coors[i] = coors[i-2] + coors[i]/1000000}

iOS中解压缩的简单实现方案

self.arr = @[@"127.496637",@"50.243916",@"-345",@"-1828",@"19867",@"-26154"];
    NSUInteger count = self.arr.count;
    NSMutableArray * arra = [NSMutableArray arrayWithArray:self.arr];

//    解压缩坐标实现
        for (int i = 2 ; i < arra.count; i ++) {
            double v0 = [arra[i - 2] doubleValue];
            double v1 = [arra[i] doubleValue] / 1000000;
            double vTotal = v0 + v1;
            NSNumber * number = [NSNumber numberWithDouble:vTotal];
            NSMutableArray *newArray = [arra mutableCopy];
            [newArray replaceObjectAtIndex:i withObject:number];
            arra = newArray;
        }
    NSLog(@"%@",arra);

https://lbs.qq.com/ios_v1/guide-3d.html

//    构造结构体数组实现并且赋值
    int vCount = (int)count / 2;
    CLLocationCoordinate2D coordinateArry[vCount];
        for (int i = 0; i < count ;i += 2) {
            double vLat = [arra[i] doubleValue];
            double vLon = [arra[i + 1] doubleValue];
            int v = i / 2;
            coordinateArry[v].latitude = vLat;
            coordinateArry[v].longitude = vLon;
        }
//    展示折线到地图上
        QPolyline *walkPolyline = [QPolyline polylineWithCoordinates:coordinateArry count:vCount];
        [self.mapView addOverlay:walkPolyline];

5.1地图覆盖物代理

- (QOverlayView *)mapView:(QMapView *)mapView viewForOverlay:(id<QOverlay>)overlay
{
    QPolylineView *polylineView = [[QPolylineView alloc] initWithPolyline:overlay];
    polylineView.lineWidth = 8;
    polylineView.lineDashPattern = nil;
    polylineView.strokeColor = [UIColor greenColor];
    return polylineView;
}

6.效果图示:

2261629-4d1a0fbd1d7f2822.png
Simulator Screen Shot - iPhone 7 - 2019-05-31 at 15.59.09.png

7.代码地址https://github.com/xgkp/TencentMapDrawLine.git

备注:由于腾讯地图的sdk大于100M,所以上传代码时候我将有一个文件目录/Vender添加到了gitignore文件里去了,如果要运行代码,请自行添加。目录图示:

2261629-20b683d1fccbbea4.png
zz.png

8.一点思考和艰辛的曲折

如图:
图示:


2261629-70c09d653c29ca0f.png
zzz.png
2261629-f47689b1bdfd1728.png
zc.png

腾讯地图有一个

+ (QPolyline *)polylineWithCoordinates:
(CLLocationCoordinate2D *)coords count:(NSUInteger)count;

方法,这个方法实际的效果是将所有的点集合进行展示。

中间的CLLocationCoordinate2D参数,这个参数从最后一张图看起来是一个C的结构体,但奇怪的是,后面又跟了一个count参数,这个不是表示数组长度的么,嗯?

既然coords存储的是一个数组类型的参数,那就和CLLocationCoordinate2D这个类型是结构体相互矛盾。

这个就造成了我的困惑,饶了一大个弯路。

我一看是数组呀,好办,就写一个for 循环,用坐标来遍历坐标数组,构造CLLocationCoordinate2D类型的数据,放到一个最终的数组中,在向iOS数组中添加这个CLLocationCoordinate2D类型的对象时候,报错,
2261629-deab8f3148a75f9f.png
zcc.png

我一看,这个貌似是OC中的数组不能存储这个结构体类型,需要转成其他类型才能存吧。
这里,又赶快去找了OC下可以存结构体的方法:

 NSValue包装对象指针,CGRect结构体等
 一个NSValue对象是用来存储一个C或者Objective-C
数据的简单容器,它可以保存任意类型的数据.
比如int , float , char ,当然也可以是指pointers,structures, 
and object ids .
NSValue类的目标就是允许以上数据类型的数据结构能够被添加到集合里,
例如那些需要其元素是对象的数据结构,
如NSArray 或者NSSet的实例.
需要注意的是NSValue对象一直是不可枚举的

直接上代码


    NSMutableArray * arraaa = [NSMutableArray arrayWithCapacity:0];
    CLLocationCoordinate2D coor = CLLocationCoordinate2DMake(19.000000, 110.000000);
//    [arraaa addObject:coor];
    NSValue *va = [NSValue valueWithBytes:&coor objCType: @encode(CLLocationCoordinate2D)];
    [arraaa addObject:va];

    }

这样写居然不报错,我猜,这个应该搞定了吧。

接着下一步emm


2261629-6f1975c7a12b7b6d.png
z2.png

点击Fix,哇塞,居然不报错了,看到曙光了

   for (int i = 0; i < arra.count; i += 2) {
        double vLat = [arra[i] doubleValue];
        double vLng = [arra[i + 1] doubleValue];
        CLLocationCoordinate2D coor = CLLocationCoordinate2DMake(vLat, vLng);
        NSValue *va = [NSValue valueWithBytes:&coor objCType: @encode(CLLocationCoordinate2D)];
          [arraaa addObject:va];
    }
    
    
    QPolyline *Polyline1 = [QPolyline polylineWithCoordinates:(__bridge CLLocationCoordinate2D *)(arraaa) count:vCount];
    [self.mapView addOverlay:Polyline1];

运行一下,emm没显示,空白一片。到此感觉到了应该是用bridge将OC数组直接强转成坐标格式的结构体数组还是有问题的,到现在也没明白。

于是转换思路,既然要的是结构体,那只能从一开始就创建成结构体数组该有的样子才行。

    CLLocationCoordinate2D coordinateArry[vCount];

这个创建好了,但是没有set方法,没有addObject方法,又卡住了!!!emmm,尴尬也不知道哪里来了印象,貌似是用下标来赋值的,尝试赋值。


2261629-5a284d609b0e3e2f.png
z22.png

下标值不是数组,指针,向量,难道结构体不是这样来取的吗,居然没我想要的struct。哼~快没辙了。
下班回家,不想了~~

最近一到下班时候就雷雨,不过每天有彩虹看~~~

2261629-662b711cc4cece0d.jpeg
zzzz.jpeg
2261629-b4ecdf744620e34e.png
zzzzzz.png

回去还是不甘心,就翻开腾讯地图的iOS3D地图的api介绍,突然想到貌似demo中有写多边形和折线的画法,看下那个数据是怎么构造的,或许有解决办法。

最后居然看到了令我惊奇的一幕~~~


2261629-428d76dc5bba4d5c.png
z1.png

真想给自己一嘴巴子,耽误那么久,居然这里有现成的!!!
总是想着用下标来取,却没注意结构体是要直接调出属性一样的来赋值....

跌宕起伏~~~~~~~

转载于:https://www.jianshu.com/p/329f75f17432

猜你喜欢

转载自blog.csdn.net/weixin_34175509/article/details/91150358