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.效果图示:

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

8.一点思考和艰辛的曲折
如图:
图示:


腾讯地图有一个
+ (QPolyline *)polylineWithCoordinates:
(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
方法,这个方法实际的效果是将所有的点集合进行展示。
中间的CLLocationCoordinate2D参数,这个参数从最后一张图看起来是一个C的结构体,但奇怪的是,后面又跟了一个count参数,这个不是表示数组长度的么,嗯?
既然coords存储的是一个数组类型的参数,那就和CLLocationCoordinate2D这个类型是结构体相互矛盾。
这个就造成了我的困惑,饶了一大个弯路。
我一看是数组呀,好办,就写一个for 循环,用坐标来遍历坐标数组,构造CLLocationCoordinate2D类型的数据,放到一个最终的数组中,在向iOS数组中添加这个CLLocationCoordinate2D类型的对象时候,报错,
我一看,这个貌似是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

点击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,尴尬也不知道哪里来了印象,貌似是用下标来赋值的,尝试赋值。

下标值不是数组,指针,向量,难道结构体不是这样来取的吗,居然没我想要的struct。哼~快没辙了。
下班回家,不想了~~
最近一到下班时候就雷雨,不过每天有彩虹看~~~


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

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