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]!) {
}
}

浙公网安备 33010602011771号