【整理之路二】百度地图的路径规划和调用本机地图导航

一、细说百度地图的路径规划

路径规划主要有这么几种
1.公交路径规划
1.1 市内公交规划(暂时不在这里说)
1.2 跨市/省公交规划

        // 导入头文件
        #import 
        #import 
        #import 
        
        #pragma mark: - 公交路线
        - (void)showBusSearch {
            //线路检索节点信息
            BMKPlanNode *start = [[BMKPlanNode alloc] init];
            start.pt = self.userLocation.location.coordinate;
            start.cityName = @"南宁";
            BMKPlanNode *end = [[BMKPlanNode alloc] init];
            // 108.296699,22.842406
            CLLocationCoordinate2D endCoordinate = CLLocationCoordinate2DMake(22.842406, 108.296699);
            end.pt = endCoordinate;
            end.cityName = @"南宁";
            BMKMassTransitRoutePlanOption *drivingRouteSearchOption = [[BMKMassTransitRoutePlanOption alloc] init];
            drivingRouteSearchOption.from = start;
            drivingRouteSearchOption.to = end;
            BOOL flag = [_routesearch massTransitSearch:drivingRouteSearchOption];
            if (flag) {
                NSLog(@"%s - 设置成功!",__func__);
            }else {
                debugLog(@"设置失败");
            }
        }
        
        /**
         *返回公共交通路线检索结果(new)回调方法
         *@param searcher 搜索对象
         *@param result 搜索结果,类型为BMKMassTransitRouteResult
         *@param error 错误号,@see BMKSearchErrorCode
         */
        - (void)onGetMassTransitRouteResult:(BMKRouteSearch*)searcher result:(BMKMassTransitRouteResult*)result errorCode:(BMKSearchErrorCode)error {
            debugLog(@"公交方案-%@",result.routes);
            if (error == BMK_SEARCH_NO_ERROR) {
                for (int i = 0; i < result.routes.count; i++ ) {
                    BMKMassTransitRouteLine *massTransitRouteLine = result.routes[i];
                    // 保存换乘说明
                    NSMutableArray *instructions = [NSMutableArray array];
                    // 换乘的交通工具
                    NSMutableArray *stepTypes = [NSMutableArray array];
                    // 价格信息
                    debugLog(@"价格-%f",massTransitRouteLine.price);
                    debugLog(@"时间分钟-%d",massTransitRouteLine.duration.minutes);
                    debugLog(@"起点-%@",massTransitRouteLine.starting.title);
                    debugLog(@"终点-%@",massTransitRouteLine.terminal.title);
                    debugLog(@"路段方案%@",massTransitRouteLine.steps);
                    // 所有路段的信息
                    for ( int j = 0; j < massTransitRouteLine.steps.count; j++) {
                        BMKMassTransitStep *step = massTransitRouteLine.steps[j];
                        debugLog(@"%@",step.steps);
                        for ( int k = 0; k< step.steps.count; k++) {
                            BMKMassTransitSubStep *subStep = step.steps[k];
                            debugLog(@"换乘说明-%@",subStep.instructions);
                            [instructions addObject:subStep.instructions];
                            debugLog(@"路段类型-%u",subStep.stepType);
                            if(subStep.stepType != 5) { // 5为步行
                                if (subStep.vehicleInfo.name) {
                                    [stepTypes addObject:subStep.vehicleInfo.name];
                                }
                            }
                            // 当路段为公交路段或地铁路段时,可以获取交通工具信息
                            debugLog(@"交通工具信息-%@",subStep.vehicleInfo.name);
                        }
                        
                    }
                    
                }
            }  
        }
        

2.驾车路径规划

#pragma mark 驾车路线
-(void)showDriveSearch {
    //线路检索节点信息
    BMKPlanNode *start = [[BMKPlanNode alloc] init];
    start.pt = self.userLocation.location.coordinate;
    start.cityName = @"南宁";
    BMKPlanNode *end = [[BMKPlanNode alloc] init];
    CLLocationCoordinate2D endCoordinate = CLLocationCoordinate2DMake(22.842406, 108.296699);

    end.pt = endCoordinate;
    end.cityName = @"南宁";
    BMKDrivingRoutePlanOption *drivingRouteSearchOption = [[BMKDrivingRoutePlanOption alloc] init];
    drivingRouteSearchOption.from = start;
    drivingRouteSearchOption.to = end;
    BOOL flag = [_routesearch drivingSearch:drivingRouteSearchOption];
    if (flag) {
        NSLog(@"%s - 设置成功!",__func__);
    }else {
        debugLog(@"设置失败");
    }
}

#pragma mark 返回驾乘搜索结果
- (void)onGetDrivingRouteResult:(BMKRouteSearch*)searcher result:(BMKDrivingRouteResult*)result errorCode:(BMKSearchErrorCode)error {
    if (error == BMK_SEARCH_NO_ERROR) {
        for (int i = 0; i < result.routes.count; i++) {
            NSMutableArray *instruction = [NSMutableArray array];
            NSMutableArray *waypoints = [NSMutableArray array];
            //表示一条驾车路线
            BMKDrivingRouteLine *plan = result.routes[i];
            
            for (int k = 0; k < plan.wayPoints.count; k++) {
                BMKPlanNode *node = plan.wayPoints[k];
                [waypoints addObject:node.name];
            }
            
            for (int j = 0; j < plan.steps.count; j++) {
                //表示驾车路线中的一个路段
                BMKDrivingStep* transitStep = [plan.steps objectAtIndex:j];
                [instruction addObject:transitStep.instruction];
            }
            
        }
        
    }

}

3.步行路径规划

#pragma mark: - 步行
- (void)showWalkSearch {
    //线路检索节点信息
    BMKPlanNode *start = [[BMKPlanNode alloc] init];
    start.pt = self.userLocation.location.coordinate;
    start.cityName = @"南宁";
    BMKPlanNode *end = [[BMKPlanNode alloc] init];
    CLLocationCoordinate2D endCoordinate = CLLocationCoordinate2DMake(22.842406, 108.296699);
    end.pt = endCoordinate;
    end.cityName = @"南宁";
    BMKWalkingRoutePlanOption *drivingRouteSearchOption = [[BMKWalkingRoutePlanOption alloc] init];
    drivingRouteSearchOption.from = start;
    drivingRouteSearchOption.to = end;
    BOOL flag = [_routesearch walkingSearch:drivingRouteSearchOption];
    if (flag) {
        NSLog(@"%s - 设置成功!",__func__);
    }else {
        debugLog(@"设置失败");
    }
}

/**
 *返回步行搜索结果
 *@param searcher 搜索对象
 *@param result 搜索结果,类型为BMKWalkingRouteResult
 *@param error 错误号,@see BMKSearchErrorCode
 */
- (void)onGetWalkingRouteResult:(BMKRouteSearch*)searcher result:(BMKWalkingRouteResult*)result errorCode:(BMKSearchErrorCode)error {
    debugLog(@"步行方案--%@",result.routes);
    if (error == BMK_SEARCH_NO_ERROR) {
        for (int i = 0; i < result.routes.count; i++) {
            NSMutableArray *instructions = [NSMutableArray array];
            BMKWalkingRouteLine *walkingRouteLine = result.routes[i];
            //debugLog(@"途径 ---%@", walkingRouteLine.wayPointPoiList);
            debugLog(@"路线长度 -- %d", walkingRouteLine.distance);
            debugLog(@"需要花费的时间 %d",walkingRouteLine.duration.minutes);
            for (int j = 0; j < walkingRouteLine.steps.count; j++) {
                BMKWalkingStep *step = walkingRouteLine.steps[j];
                debugLog(@"入口信息 -- %@",step.entraceInstruction);
                debugLog(@"出口信息 -- %@",step.exitInstruction);
                debugLog(@"指示信息 -- %@",step.instruction);
                [instructions addObject:step.instruction];
            }
        }
    }
}


4.骑车路径规划(暂时不总结)

5.根据路径规划划线

- (void)showCarRoutePlan {

    // 计算路线方案中的路段数目
    int size = (int)[self.drivingRouteLine.steps count];
    BMKDrivingRouteLine *plan = self.drivingRouteLine;
    int planPointCounts = 0;
    for (int i = 0; i < size; i++) {
        //表示驾车路线中的一个路段
        BMKDrivingStep* 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]; // 添加终点标注
        }
        //添加annotation节点
        RouteAnnotation* item = [[RouteAnnotation alloc]init];
        item.coordinate = transitStep.entrace.location;
        item.title = transitStep.entraceInstruction;
        item.degree = transitStep.direction * 30;
        item.type = 4;
        [_mapView addAnnotation:item];
        
        //轨迹点总数累计
        planPointCounts += transitStep.pointsCount;
    }
    // 添加途经点
    if (plan.wayPoints) {
        for (BMKPlanNode* tempNode in plan.wayPoints) {
            RouteAnnotation* item = [[RouteAnnotation alloc]init];
            item.coordinate = tempNode.pt;
            item.type = 5;
            item.title = tempNode.name;
            [_mapView addAnnotation:item];
        }
    }
    //轨迹点
    BMKMapPoint * temppoints = new BMKMapPoint[planPointCounts];
    int i = 0;
    for (int j = 0; j < size; j++) {
        BMKDrivingStep* transitStep = [plan.steps objectAtIndex:j];
        int k=0;
        for(k=0;k)annotation {
    if (![annotation isKindOfClass:[RouteAnnotation class]]) return nil;
    return [self getRouteAnnotationView:mapView viewForAnnotation:(RouteAnnotation *)annotation];
}

#pragma mark 获取路线的标注,显示到地图
- (BMKAnnotationView*)getRouteAnnotationView:(BMKMapView *)mapview viewForAnnotation:(RouteAnnotation*)routeAnnotation {
    
    BMKAnnotationView *view = nil;
    switch (routeAnnotation.type) {
            case 0:
        {
            view = [mapview dequeueReusableAnnotationViewWithIdentifier:@"start_node"];
            if (view == nil) {
                view = [[BMKAnnotationView alloc] initWithAnnotation:routeAnnotation reuseIdentifier:@"start_node"];
                view.image = [UIImage imageNamed:@"map_start"];
                //[UIImage imageWithContentsOfFile:[self getMyBundlePath1:@"images/icon_nav_start"]];
                view.centerOffset = CGPointMake(0, -(view.frame.size.height * 0.5));
                view.canShowCallout = true;
            }
            view.annotation = routeAnnotation;
        }
            break;
            case 1:
        {
            view = [mapview dequeueReusableAnnotationViewWithIdentifier:@"end_node"];
            if (view == nil) {
                view = [[BMKAnnotationView alloc] initWithAnnotation:routeAnnotation reuseIdentifier:@"end_node"];
                view.image = [UIImage imageNamed:@"map_end"];
                //[UIImage imageWithContentsOfFile:[self getMyBundlePath1:@"images/icon_nav_end"]];
                view.centerOffset = CGPointMake(0, -(view.frame.size.height * 0.5));
                view.canShowCallout = true;
            }
            view.annotation =routeAnnotation;
        }
            break;
            case 4:
        {
            view = [mapview dequeueReusableAnnotationViewWithIdentifier:@"route_node"];
            if (view == nil) {
                view = [[BMKAnnotationView alloc] initWithAnnotation:routeAnnotation reuseIdentifier:@"route_node"];
                view.canShowCallout = true;
            } else {
                [view setNeedsDisplay];
            }
            UIImage *image = [UIImage imageWithContentsOfFile:[self getMyBundlePath1:@"images/icon_direction"]];
            view.image = [image imageRotatedByDegrees:routeAnnotation.degree];
            view.annotation = routeAnnotation;
        }
            break;
        default:
            break;
    }
    return view;
}


#pragma mark 根据overlay生成对应的View
-(BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id)overlay {
    if ([overlay isKindOfClass:[BMKPolyline class]]) {
        BMKPolylineView* polylineView = [[BMKPolylineView alloc] initWithOverlay:overlay];
        polylineView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:1];
        polylineView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
        polylineView.lineWidth = 3.0;
        return polylineView;
    }
    return nil;
}

#pragma mark  根据polyline设置地图范围
- (void)mapViewFitPolyLine:(BMKPolyline *) polyLine {
    CGFloat ltX, ltY, rbX, rbY;
    
    if (polyLine.pointCount < 1) return;
    BMKMapPoint pt = polyLine.points[0];
    ltX = pt.x, ltY = pt.y;
    rbX = pt.x, rbY = pt.y;
    
    for (int i = 0; i < polyLine.pointCount; i++) {
        BMKMapPoint pt = polyLine.points[i];
        if (pt.x < ltX) {
            ltX = pt.x;
        }
        if (pt.x > rbX) {
            rbX = pt.x;
        }
        if (pt.y > ltY) {
            ltY = pt.y;
        }
        if (pt.y < rbY) {
            rbY = pt.y;
        }
    }
    BMKMapRect rect;
    rect.origin = BMKMapPointMake(ltX , ltY);
    rect.size = BMKMapSizeMake(rbX - ltX, rbY - ltY);
    [_mapView setVisibleMapRect:rect];
    _mapView.zoomLevel = _mapView.zoomLevel - 0.3;
}


    // RouteAnnotation 自定义的类
    /** 路线的标注*/
    @interface RouteAnnotation : BMKPointAnnotation
    
    @property (nonatomic) int type; ///<0:起点 1:终点 2:公交 3:地铁 4:驾乘 5:途经点
    @property (nonatomic) int degree;
    @end
    
    @implementation RouteAnnotation
    
    @end

二、使用本机的地图导航

通常自己的手机都会安装有百度地图、高德地图、腾讯等等
1.实现步骤
1.1 添加应用白名单

        baidumap
        iosamap
        comgooglemaps
        qqmap

1.2 info.plist添加对应的url schemes

百度地图: baidumap://
腾讯地图: qqmap://
谷歌地图: comgooglemaps://
高德地图: iosamap://

1.3 使用的第三方框架

    pod 'LCActionSheet'   // 弹窗选择
    pod 'JZLocationConverter' // 经纬度转换(主要解决百度地图和谷歌地图用的不是同一种标准的问题)

1.4 具体实现代码

// 引入头文件
#import 
#import 

#pragma mark - 导航方法
- (NSArray *)getInstalledMapApp
{
    NSArray *locationArray = [self.poiMD.address_x_y componentsSeparatedByString:@","];
    // lat lng
    CLLocationCoordinate2D endLocation = CLLocationCoordinate2DMake([locationArray.lastObject floatValue], [locationArray.firstObject floatValue]);
    
    NSMutableArray *maps = [NSMutableArray array];
    
    //苹果地图
    NSMutableDictionary *iosMapDic = [NSMutableDictionary dictionary];
    iosMapDic[@"title"] = @"苹果地图";
    [maps addObject:iosMapDic];
    
    //百度地图
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"baidumap://"]]) {
        NSMutableDictionary *baiduMapDic = [NSMutableDictionary dictionary];
        baiduMapDic[@"title"] = @"百度地图";
        NSString *urlString = [[NSString stringWithFormat:@"baidumap://map/direction?origin={{我的位置}}&destination=latlng:%f,%f|name=北京&mode=driving&coord_type=gcj02",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        baiduMapDic[@"url"] = urlString;
        [maps addObject:baiduMapDic];
    }
    
    //高德地图
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"iosamap://"]]) {
        NSMutableDictionary *gaodeMapDic = [NSMutableDictionary dictionary];
        gaodeMapDic[@"title"] = @"高德地图";
        NSString *urlString = [[NSString stringWithFormat:@"iosamap://navi?sourceApplication=%@&backScheme=%@&lat=%f&lon=%f&dev=0&style=2",@"导航功能",@"nav123456",endLocation.latitude,endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        gaodeMapDic[@"url"] = urlString;
        [maps addObject:gaodeMapDic];
    }
    
    //谷歌地图
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"comgooglemaps://"]]) {
        NSMutableDictionary *googleMapDic = [NSMutableDictionary dictionary];
        googleMapDic[@"title"] = @"谷歌地图";
        NSString *urlString = [[NSString stringWithFormat:@"comgooglemaps://?x-source=%@&x-success=%@&saddr=&daddr=%f,%f&directionsmode=driving",@"导航测试",@"nav123456",endLocation.latitude, endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        googleMapDic[@"url"] = urlString;
        [maps addObject:googleMapDic];
    }
    
    //腾讯地图
    if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"qqmap://"]]) {
        NSMutableDictionary *qqMapDic = [NSMutableDictionary dictionary];
        qqMapDic[@"title"] = @"腾讯地图";
        NSString *urlString = [[NSString stringWithFormat:@"qqmap://map/routeplan?from=我的位置&type=drive&tocoord=%f,%f&to=终点&coord_type=1&policy=0",endLocation.latitude, endLocation.longitude] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        qqMapDic[@"url"] = urlString;
        [maps addObject:qqMapDic];
    }
    
    return maps;
}

- (void)showLCActionSheet {
    
    NSArray *maps = [self getInstalledMapApp];
    NSMutableArray *mapsA = [NSMutableArray array];
    for (NSDictionary *dict in maps) {
        [mapsA addObject:dict[@"title"]];
    }
    
    LCActionSheet *actionSheet =  [LCActionSheet sheetWithTitle:@"请选择" cancelButtonTitle:@"取消" clicked:^(LCActionSheet * _Nonnull actionSheet, NSUInteger buttonIndex) {
        debugLog(@"当前选择 --- %d",buttonIndex);
        if (buttonIndex == 0) { // 当前选择了取消
            return ;
        }
        if ((buttonIndex - 1) == 0) { // 苹果地图无论如何都是有的
            [self navAppleMap];
            return;
        }
        NSDictionary *dic = [self getInstalledMapApp][buttonIndex - 1];
        NSString *urlString = dic[@"url"];
        [[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
    } otherButtonTitleArray:mapsA];
    
    actionSheet.blurEffectStyle = UIBlurEffectStyleLight;
    actionSheet.scrolling          = YES;
    actionSheet.visibleButtonCount = 3.6f;
    [actionSheet show];
}

// 苹果地图
- (void)navAppleMap
{
    NSArray *locationArray = [self.poiMD.address_x_y componentsSeparatedByString:@","];
    // lat lng
    CLLocationCoordinate2D endLocation = CLLocationCoordinate2DMake([locationArray.lastObject floatValue], [locationArray.firstObject floatValue]);
    CLLocationCoordinate2D gps = [JZLocationConverter bd09ToWgs84:endLocation];
    
    MKMapItem *currentLoc = [MKMapItem mapItemForCurrentLocation];
    MKMapItem *toLocation = [[MKMapItem alloc] initWithPlacemark:[[MKPlacemark alloc] initWithCoordinate:gps addressDictionary:nil]];
    NSArray *items = @[currentLoc,toLocation];
    NSDictionary *dic = @{
                          MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
                          MKLaunchOptionsMapTypeKey : @(MKMapTypeStandard),
                          MKLaunchOptionsShowsTrafficKey : @(YES)
                          };
    
    [MKMapItem openMapsWithItems:items launchOptions:dic];
}

你可能感兴趣的:(【整理之路二】百度地图的路径规划和调用本机地图导航)