iOS解决百度地图驾车导航画线不显示

背景:公司需要做驾车导航路径,选好起点、终点,然后把途经点选好,调用百度地图的规划api,得到所有的点,然后在地图上展示出来。页面上有个导航按钮,一点导航就开始导航了。

问题:基础版本的地图,请求驾车路径规划,路径也画到了地图上,然而将地图升级成导航地图,请求导航路径规划,却画线失败,无法展示路径,几经周折终于搞定了。

解决:通过两个版本的对比发现:

1、基础版本得到的点不是直接的经纬度,是比较大的两个数字,百度地图API的备注是“地理坐标点,用直角地理坐标表示”。

2、导航地图版本得到的是我们平时理解的经纬度。

结论:不同的数据列表初始化线路需要调用不同的函数。而我一直用地理坐标点数组初始化函数画线,这是画线不显示的主要问题。

3、还遇到了线路画偏的情况,进行坐标转后再画线就正常了。

下面是两个版本的大部分代码,希望给用的到同学有帮助。

 

A、基础版驾车线路规划请求


  lazy var routeSearch:BMKRouteSearch = {

        let search = BMKRouteSearch()

        search.delegate = self

        return search

  }()

func drivingSearchV1() {
        guard let staIt = startItem else {
            return
        }
        guard let endIt = endItem else {
            return
        }
        /*
         线路检索节点信息类,一个路线检索节点可以通过经纬度坐标或城市名加地名确定
         实例化线路检索节点信息类对象
         */
        let start = BMKPlanNode()
        //起点名称
        start.name = staIt.address
        start.pt = staIt.coordinate()
        // 途经点
        var plist = [BMKPlanNode]()
        for item in list {
            let start = BMKPlanNode()
            //起点名称
            start.name = item.nodeName
            //起点所在城市,注:cityName和cityID同时指定时,优先使用cityID
            start.pt = CLLocationCoordinate2D(latitude: item.latitude.doubleValue, longitude: item.longitude.doubleValue)
            plist.append(start)
        }
        
        //实例化线路检索节点信息类对象
        let end = BMKPlanNode()
        //终点名称
        end.name = endIt.address
        end.pt = endIt.coordinate()

        //初始化请求参数类BMKDrivingRoutePlanOption的实例
        let drivingRoutePlanOption = BMKDrivingRoutePlanOption()
        //检索的起点,可通过关键字、坐标两种方式指定。cityName和cityID同时指定时,优先使用cityID
        drivingRoutePlanOption.from = start
        //检索的终点,可通过关键字、坐标两种方式指定。cityName和cityID同时指定时,优先使用cityID
        drivingRoutePlanOption.to = end
        drivingRoutePlanOption.wayPointsArray = plist

        /**
         发起驾乘路线检索请求,异步函数,返回结果在BMKRouteSearchDelegate的onGetDrivingRouteResult中
         */
        let flag = routeSearch.drivingSearch(drivingRoutePlanOption)
        if flag {
            print("驾车检索成功")
            var points = [VmPointAnnotation]()
            for (k,item) in list.enumerated() {
                let coord = CLLocationCoordinate2D(latitude:item.latitude.doubleValue, longitude: item.longitude.doubleValue)
                if !CLLocationCoordinate2DIsValid(coord) || coord.longitude == 0 || coord.latitude == 0 {
                    continue
                }
                //初始化标注类BMKPointAnnotation的实例
                let annotation = VmPointAnnotation.init()
                //设置标注的经纬度坐标
                annotation.coordinate = coord
                //设置标注的标题
                annotation.title = item.vmCode
                //副标题
                annotation.subtitle = String(k + 1) + ":" + item.nodeName
                annotation.vm = item
                points.append(annotation)
            }

            let sta = StaEndPointAnnotation()
            sta.title = "起点"
            sta.tag = 0
            sta.coordinate = staIt.coordinate()
            mapView.addAnnotation(sta)

            let end = StaEndPointAnnotation()
            end.title = "终点"
            end.tag = 1
            end.coordinate = endIt.coordinate()
            mapView.addAnnotation(end)

            if !points.isEmpty {
                mapView.addAnnotations(points)
                mapView.showAnnotations(points, animated: true)
            }
        } else {
            print("驾车检索失败")
        }
    }

A、基础版驾车线路规划绘制线

extension RoutePlanResultViewController: BMKRouteSearchDelegate {
    
    /**
     返回驾车路线检索结果
     
     @param searcher 检索对象
     @param result 检索结果,类型为BMKDrivingRouteResult
     @param error 错误码 @see BMKSearchErrorCode
     */
    func onGetDrivingRouteResult(_ searcher: BMKRouteSearch!, result: BMKDrivingRouteResult!, errorCode error: BMKSearchErrorCode) {
        if error == BMK_SEARCH_NO_ERROR {
            //成功获取结果
            let plan = result.routes.first
            var point = [BMKMapPoint]()
            var index = [NSNumber]()
            for item in plan?.steps ?? [] {
                if let a = item as? BMKDrivingStep {
                    for j in  0 ..< a.pointsCount {
                        var p = BMKMapPoint()
                        p.x = a.points[Int(j)].x;
                        p.y = a.points[Int(j)].y;
                        point.append(p)
                        DLog("111--->>>>p.x = ", p.x, "p.y = ", p.y)
                    }
                    if a.hasTrafficsInfo {
                        DLog("----存在路况")
                        for val in a.traffics {
                            index.append(val)
                            DLog("----加载路况===",val)
                        }
                    } else {
                        DLog("----不存在路况")
                        for _ in  0 ..< a.pointsCount {
                            index.append(NSNumber(value: 1))
                        }
                    }
                }
            }
            DLog("--->>>>point.count = ",point.count)
            if let polyline = BMKMultiPolyline(points: &point, count: UInt(point.count), drawIndexs: index) {
                mapView.add(polyline)
                mapViewFitPolyline(polyline)
            }
        } else {
            //检索失败
        }
    }
    

    func mapViewFitPolyline(_ polyline: BMKPolyline) {
        var leftTop_x: Double, leftTop_y: Double, rightBottom_x: Double, rightBottom_y: Double
        if polyline.pointCount < 1 {
            return
        }
        let pt = polyline.points[0]
        leftTop_x = pt.x
        leftTop_y = pt.y
        // 左上方的点leftTop坐标(leftTop_x,leftTop_y)
        rightBottom_x = pt.x
        rightBottom_y = pt.y
        // 右底部的点rightBottom坐标(rightBottom_x,rightBottom_y)
        for i in 1..<polyline.pointCount {
            let point = polyline.points[Int(i)]
            if point.x < leftTop_x {
                leftTop_x = point.x
            }
            if point.x > rightBottom_x {
                rightBottom_x = point.x
            }
            if point.y < leftTop_y {
                leftTop_y = point.y
            }
            if point.y > rightBottom_y {
                rightBottom_y = point.y
            }
        }
        let rect = BMKMapRect(origin: BMKMapPoint(x: leftTop_x, y: leftTop_y), size: BMKMapSize(width: rightBottom_x - leftTop_x, height: rightBottom_y - leftTop_y))
        let padding = UIEdgeInsets(top: 10, left: 10, bottom: k_safearea_bottom + 100, right: 10)
        mapView.fitVisibleMapRect(rect, edgePadding: padding, withAnimated: true)
    }

} 

 

共用地图线路渲染

extension RoutePlanResultViewController: BMKMapViewDelegate {
    
    //MARK:BMKMapViewDelegate
    /**
     根据overlay生成对应的BMKOverlayView
     */
    func mapView(_ mapView: BMKMapView, viewFor overlay: BMKOverlay) -> BMKOverlayView? {
        if overlay.isKind(of: BMKMultiPolyline.self) {
            let mulTexturePolylineView = BMKMultiTexturePolylineView(multiPolyline: overlay as! BMKMultiPolyline)
            mulTexturePolylineView?.lineWidth = 8.0
            // 构建纹理数组
            let images: [UIImage] = [UIImage(named: "icon_road_blue")!,
                                     UIImage(named: "icon_road_green")!,
                                     UIImage(named: "icon_road_yellow")!,
                                     UIImage(named: "icon_road_red")!]
            mulTexturePolylineView?.textureImages = images
//            LineJoinType,默认是kBMKLineJoinBevel(不支持虚线)
            // 拐角处圆角衔接
            mulTexturePolylineView?.lineJoinType = kBMKLineJoinRound
//            // 拐角处平角衔接
//            mulTexturePolylineView?.lineJoinType = kBMKLineJoinBevel;
//            // 拐角处尖角衔接,ps尖角连接(尖角过长(大于线宽)按平角处理)
//            mulTexturePolylineView?.lineJoinType = kBMKLineJoinMiter;
            return mulTexturePolylineView
        }
        if let over = overlay as? BMKPolyline {
            //初始化一个overlay并返回相应的BMKPolylineView的实例
            let polylineView = BMKPolylineView(polyline: over)

                //设置polylineView的画笔颜色为蓝色
                polylineView?.strokeColor = UIColor(red: 19 / 255.0, green: 107/255.0, blue: 251/255.0, alpha: 1.0)
                //设置polylineView的画笔宽度为16
                polylineView?.lineWidth = 5
                //圆点虚线,V5.0.0新增
                //polylineView?.lineDashType = kBMKLineDashTypeDot
                //方块虚线,V5.0.0新增
                //polylineView?.lineDashType = kBMKLineDashTypeSquare
            return polylineView
        }
        return nil
    }
    
    //MARK:BMKMapViewDelegate
    /**
     根据anntation生成对应的annotationView
     @param mapView 地图View
     @param annotation 指定的标注
     @return 生成的标注View
     */
    func mapView(_ mapView: BMKMapView, viewFor annotation: BMKAnnotation) -> BMKAnnotationView? {
        if annotation is VmPointAnnotation {
            /**
             根据指定标识查找一个可被复用的标注,用此方法来代替新创建一个标注,返回可被复用的标注
             */
            var annotationView: BMKPinAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: annotationViewIdentifier1) as? BMKPinAnnotationView
            if annotationView == nil {
                /**
                 初始化并返回一个annotationView
                 @param annotation 关联的annotation对象
                 @param reuseIdentifier 如果要重用view,传入一个字符串,否则设为nil,建议重用view
                 @return 初始化成功则返回annotationView,否则返回nil
                 */
                annotationView = BMKPinAnnotationView.init(annotation: annotation, reuseIdentifier: annotationViewIdentifier1)
            }
            return annotationView
        }
        if let an = annotation as? StaEndPointAnnotation {
            /**
             根据指定标识查找一个可被复用的标注,用此方法来代替新创建一个标注,返回可被复用的标注
             */
            var annotationView: BMKPinAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: annotationViewIdentifier2) as? BMKPinAnnotationView
            if annotationView == nil {
                /**
                 初始化并返回一个annotationView
                 @param annotation 关联的annotation对象
                 @param reuseIdentifier 如果要重用view,传入一个字符串,否则设为nil,建议重用view
                 @return 初始化成功则返回annotationView,否则返回nil
                 */
                annotationView = BMKPinAnnotationView.init(annotation: annotation, reuseIdentifier: annotationViewIdentifier2)
            }
            if an.tag == 0 {
                annotationView?.image = UIImage(named: "icon_start")
            } else {
                annotationView?.image = UIImage(named: "icon_end")
            }
            return annotationView
        }
        return nil
    }
}

  

B、导航版驾车线路规划请求

    func drivingSearchV2() {
        guard let staIt = startItem else {
            return
        }
        guard let endIt = endItem else {
            return
        }
        var naviNodes = [BNRoutePlanNode]()
        
        let starNode =  BNRoutePlanNode()
        let position = BNPosition()
        position.x = staIt.longitude?.doubleValue ?? 0
        position.y = staIt.latitude?.doubleValue ?? 0
        starNode.pos = position
        starNode.pos.eType = BNCoordinate_BaiduMapSDK
        naviNodes.append(starNode)
        
        for item in list {
            let node =  BNRoutePlanNode()
            let pos = BNPosition()
            pos.x = item.longitude.doubleValue
            pos.y = item.latitude.doubleValue
            node.pos = pos
            node.pos.eType = BNCoordinate_BaiduMapSDK
            naviNodes.append(node)
        }
        
        let endNode =  BNRoutePlanNode()
        let endPosition = BNPosition()
        endPosition.x = endIt.longitude?.doubleValue ?? 0
        endPosition.y = endIt.latitude?.doubleValue ?? 0
        endNode.pos = endPosition
        endNode.pos.eType = BNCoordinate_BaiduMapSDK
        naviNodes.append(endNode)

        let routeManager = BNaviService.getInstance()?.routePlanManager()
        routeManager?.startNaviRoutePlan(BNRoutePlanMode_Recommend, naviNodes: naviNodes, time: nil, delegete: self, userInfo:[BNaviTripTypeKey:BN_NaviTypeReal.rawValue])
    }
    

  

B、基础版驾车线路规划绘制线

extension RoutePlanningResultViewController: BNNaviRoutePlanDelegate {
    
    /**
     *  算路成功回调
     *  @param userInfo 用户信息
     */
    func routePlanDidFinished(_ userInfo: [AnyHashable : Any]!) {
        if let route = BNaviService.getInstance().driveRouteManager().getCurrentCarRouteData() {
            let plan = route.carRoutes.firstObject as? BNCarOneRouteModel
            var point = [CLLocationCoordinate2D]()
            var index = [NSNumber]()
            for item in plan?.stepList ?? [] {
                if let a = item as? BNCarRouteStepModel {
                    for l in a.coordinates {
                        // 国测局坐标类型的原始坐标
                        let gcj02Coord = CLLocationCoordinate2DMake(l.y, l.x)
                        // 转为百度经纬度类型的坐标
                        let bd09Coord = BMKCoordTrans(gcj02Coord, BMK_COORD_TYPE.COORDTYPE_COMMON, BMK_COORD_TYPE.COORDTYPE_BD09LL)
                        point.append(bd09Coord)
                    }
                }
            }
            // 带纹理线
            if let polyline = BMKMultiPolyline(coordinates: &point, count: UInt(point.count),drawIndexs: index) {
                mapView.add(polyline)
                mapViewFitPolyline(polyline)
            }
            // 不带纹理
//            if let polyline = BMKPolyline.init(coordinates: &point, count: UInt(point.count)) {
//                mapView.add(polyline)
//                mapViewFitPolyline(polyline)
//            }
        }
        
        var points = [VmPointAnnotation]()
        for (k,item) in list.enumerated() {
            let coord = CLLocationCoordinate2D(latitude:item.latitude.doubleValue, longitude: item.longitude.doubleValue)
            if !CLLocationCoordinate2DIsValid(coord) || coord.longitude == 0 || coord.latitude == 0 {
                continue
            }
            //初始化标注类BMKPointAnnotation的实例
            let annotation = VmPointAnnotation.init()
            //设置标注的经纬度坐标
            annotation.coordinate = coord
            //设置标注的标题
            annotation.title = item.vmCode
            //副标题
            annotation.subtitle = String(k + 1) + ":" + item.nodeName
            annotation.vm = item
            points.append(annotation)
        }
        if !points.isEmpty {
            mapView.addAnnotations(points)
            mapView.showAnnotations(points, animated: true)
        }
     // 开启导航 // BNaviService.getInstance().uiManager().showPage(BNaviUI_NormalNavi, delegate: self, extParams:[BNaviUI_NormalNavi_TypeKey:BN_NaviTypeReal.rawValue]) } func routePlanDidFailedWithError(_ error: Error!, andUserInfo userInfo: [AnyHashable : Any]! = [:]) { } func routePlanDidUserCanceled(_ userInfo: [AnyHashable : Any]!) { } }

  

posted @ 2023-11-22 13:27  東玖零  阅读(103)  评论(0编辑  收藏  举报