最近要做个类似这样的地图效果。在这里不得不吐槽下iOS百度地图开发文档,内容远没有安卓版的详细。。。。
要实现这种效果,这就得用到百度地图的路径规划了。开发文档上是这样写的
路径规划
百度地图iOS SDK为开发者提供了公交换乘、驾车和步行三种类型的线路规划方案,同时根据不同的方案还可以选择“时间最短”、“距离最短”等策略来完成最终的线路规划。开发者可根据自己实际的业务需求来自由使用。公交换乘的线路规范实现方式如下:
-(void)viewDidLoad { //初始化检索对象 _searcher = [[BMKRouteSearch alloc]init]; _searcher.delegate = self; //发起检索 BMKPlanNode* start = [[[BMKPlanNode alloc]init] autorelease]; start.name = @"龙泽"; BMKPlanNode* end = [[[BMKPlanNode alloc]init] autorelease]; end.name = "西单"; BMKTransitRoutePlanOption *transitRouteSearchOption = [[BMKTransitRoutePlanOption alloc]init]; transitRouteSearchOption.city= @"北京市"; transitRouteSearchOption.startNode = start; transitRouteSearchOption.endNode = end; BOOL flag = [_searcher transitSearch:transitRouteSearchOption]; [transitRouteSearchOption release]; if(flag) { NSLog(@"bus检索发送成功"); } else { NSLog(@"bus检索发送失败"); } } //实现Deleage处理回调结果 -(void)onGetTransitRouteResult:(BMKRouteSearch*)searcher result: (BMKTransitRouteResult*)result errorCode:(BMKSearchErrorCode)error { if (error == BMK_SEARCH_NO_ERROR) { //在此处理正常结果 } else if (error == BMK_SEARCH_AMBIGUOUS_ROURE_ADDR){ //当路线起终点有歧义时通,获取建议检索起终点 //result.routeAddrResult } else { NSLog(@"抱歉,未找到结果"); } } //不使用时将delegate设置为 nil -(void)viewWillDisappear:(BOOL)animated { _searcher.delegate = nil; }
但是,我们从字面上理解根本不知道返回的字段是什么,文档上也没说。。。。。
此时,我们就该利用到百度地图开发demo了,在demo上它是这样写的
- (void)onGetTransitRouteResult:(BMKRouteSearch*)searcher result:(BMKTransitRouteResult*)result errorCode:(BMKSearchErrorCode)error { NSArray* array = [NSArray arrayWithArray:_mapView.annotations]; [_mapView removeAnnotations:array]; array = [NSArray arrayWithArray:_mapView.overlays]; [_mapView removeOverlays:array]; if (error == BMK_SEARCH_NO_ERROR) { BMKTransitRouteLine* plan = (BMKTransitRouteLine*)[result.routes objectAtIndex:0]; // 计算路线方案中的路段数目 int size = [plan.steps count]; int planPointCounts = 0; for (int i = 0; i < size; i++) { BMKTransitStep* transitStep = [plan.steps objectAtIndex:i]; if(i==0){ RouteAnnotation* item = [[RouteAnnotation alloc]init]; item.coordinate = plan.starting.location; item.title = @"起点"; item.type = 0; [_mapView addAnnotation:item]; // 添加起点标注 }else if(i==size-1){ RouteAnnotation* item = [[RouteAnnotation alloc]init]; item.coordinate = plan.terminal.location; item.title = @"终点"; item.type = 1; [_mapView addAnnotation:item]; // 添加起点标注 } RouteAnnotation* item = [[RouteAnnotation alloc]init]; item.coordinate = transitStep.entrace.location; item.title = transitStep.instruction; item.type = 3; [_mapView addAnnotation:item]; //轨迹点总数累计 planPointCounts += transitStep.pointsCount; } //轨迹点 BMKMapPoint * temppoints = new BMKMapPoint[planPointCounts]; int i = 0; for (int j = 0; j < size; j++) { BMKTransitStep* transitStep = [plan.steps objectAtIndex:j]; int k=0; for(k=0;k<transitStep.pointsCount;k++) { temppoints[i].x = transitStep.points[k].x; temppoints[i].y = transitStep.points[k].y; i++; } } // 通过points构建BMKPolyline BMKPolyline* polyLine = [BMKPolyline polylineWithPoints:temppoints count:planPointCounts]; [_mapView addOverlay:polyLine]; // 添加路线overlay delete []temppoints; } }
按照它的逻辑,似乎好像这个BMKTransitRouteLine对象就是我们想要的结果呢。
为什么这么说呢,因为这句话。
BMKTransitRouteLine* plan = (BMKTransitRouteLine*)[result.routes objectAtIndex:0];
它是取数组中的第一个元素,然后在这个对象中取得路径点,最后开始绘图。为证明没有猜错,我们在去百度地图头文件中看看这个对象到底是什么。
在文件BMKRouteSearchType.h中,我们可以看到
///此类表示一个换乘路线,换乘路线将根据既定策略调配多种交通工具 @interface BMKTransitRouteLine : BMKRouteLine @end
在往下看,我们还可以看到
@interface BMKTransitRouteResult : NSObject{ BMKTaxiInfo* _taxiInfo; BMKSuggestAddrInfo* _suggestAddrResult; NSArray* _routes; } ///该路线打车信息 @property (nonatomic, strong) BMKTaxiInfo* taxiInfo; ///返回起点或终点的地址信息结果 @property (nonatomic, strong) BMKSuggestAddrInfo* suggestAddrResult; ///方案数组,成员类型为BMKTransitRouteLine @property (nonatomic, strong) NSArray* routes; @end
这就证明我们的想法是没错。
找到了我们所需要的对象,那怎么具体把它解析出来了?不急,再慢慢往下看
BMKTransitRouteLine对象继承BMKRouteLine对象,那我们就得看BMKRouteLine对象了,
///此类表示路线数据结构的基类,表示一条路线,路线可能包括:路线规划中的换乘/驾车/步行路线 ///此类为路线数据结构的基类,一般关注其子类对象即可,无需直接生成该类对象 @interface BMKRouteLine : NSObject{ int _distance; BMKTime* _duration; BMKRouteNode* _starting; BMKRouteNode* _terminal; NSString* _title; NSArray* _steps; } ///路线长度 单位: 米 @property (nonatomic) int distance; ///路线耗时 单位: 秒 @property (nonatomic, strong) BMKTime* duration; ///路线起点信息 @property (nonatomic, strong) BMKRouteNode* starting; ///路线终点信息 @property (nonatomic, strong) BMKRouteNode* terminal; ///路线名称(预留字段,现为空) @property (nonatomic, strong) NSString* title; ///路线中的所有路段,成员类型为BMKWalkingStep,BMKDrivingStep,BMKTransitStep @property (nonatomic, strong) NSArray* steps; @end
在这,我们可以很肯定的知道我们所需的信息一定在数组steps中(不要问为什么,如果这都看不出的话,那你面壁去)。
在例子中,我们要检索公交,那么应该是steps由BMKTransitStep对象组成的数组,
查看BMKTransitStep对象
///此类表示公交换乘路线中的一个路段 @interface BMKTransitStep : BMKRouteStep{ BMKRouteNode* _entrace; BMKRouteNode* _exit; NSString* _instruction; BMKTransitStepType _stepType; BMKVehicleInfo* _vehicleInfo; } ///路段入口信息 @property (nonatomic, retain) BMKRouteNode* entrace; ///路段出口信息 @property (nonatomic, retain) BMKRouteNode* exit; ///路段换乘说明 @property (nonatomic, retain) NSString* instruction; ///路段类型 @property (nonatomic) BMKTransitStepType stepType; ///当路段为公交路段或地铁路段时,可以获取交通工具信息 @property (nonatomic, retain) BMKVehicleInfo* vehicleInfo; @end
可以确定,我们最终所需要的信息就在对象BMKVehicleInfo中了,为保险点,我们在看下对象BMKVehicleInfo
///路线换乘方案里的交通工具信息类 @interface BMKVehicleInfo : NSObject{ NSString* _uid; NSString* _title; int _passStationNum; int _totalPrice; int _zonePrice; } ///该交通路线的标识 @property (nonatomic, retain) NSString* uid; ///该交通路线的名称 @property (nonatomic, retain) NSString* title; ///该交通路线的所乘站数 @property (nonatomic) int passStationNum; ///该交通路线的全程价格 @property (nonatomic) int totalPrice; ///该交通路线的所乘区间的区间价格 @property (nonatomic) int zonePrice; @end
在这已经很明显了,title就是我们所需的信息了。