示例中心
功能在线体验
menu 导航 closed 关闭

多路径展示

根据用户设置的驾车偏好,将规划出的多条路线按照实际的路况进行地图展示,同时展现路线的时间、距离、红绿灯数目以及路线的特征标签,帮助用户快速选择最优路线进行导航。
00:00 / 01:00
扫描二维码在手机端体验功能
体验移动端 扫码体验移动端

使用场景

出行类APP的路径选择。

用到产品

Android 导航 SDK

核心类/接口

接口

说明

版本

AMapNavi

strategyConvert(boolean congestion, boolean avoidspeed, boolean cost, boolean hightspeed, boolean multipleRoute)

进行算路策略转换,将传入的特定规则转换成PathPlanningStrategy的枚举值。

V1.8.0版本起


calculateDriveRoute(java.util.List from, java.util.List to, java.util.List wayPoints, int strategy)

计算驾车路径(包含起点)。

V1.0.0版本起


selectRouteId(int id)

选择路线ID。

V1.8.0版本起


startNavi(int naviType)

开始导航(GPS或模拟)。

V1.0.0版本起

AMapNaviListener

onCalculateMultipleRoutesSuccess

多路径驾车路径规划成功后的回调函数。

V1.0.0版本起

AMapNaviPath

getAllLength()

返回当前导航路线的总长度。

V1.0.0版本起


getAllTime()

返回当前导航路径所需的时间,单位:秒。

V1.0.0版本起


getTollCost()

获取导航段的花费金额,单位:元。

V1.0.0版本起

AMapNaviStep

getTrafficLightNumber()

返回当前导航路段的红绿灯数目。

V1.7.0版本起

RouteOverLay

addToMap()

将规划的路线添加到地图上。

V1.8.0版本起


setTrafficLine(java.lang.Boolean enabled)

是否开启交通线。

V1.8.0版本起


setTransparency(float value)

设置该routeOverlay的透明度。

V1.8.0版本起

核心难点

1、将规划出来的路线按照实际的交通路况进行显示。

RouteOverLay routeOverLay = new RouteOverLay(mAMap, path, this);
routeOverLay.setTrafficLine(true);
routeOverLay.addToMap();

2、地图上同时显示多条路线时,如何控制这些路线的层级。

规划出来的路线最多有3条,以选中第一条为例,介绍控制层级的逻辑,代码如下:

/**
 * 第一条路线是否focus
 *
 * @param focus focus为true 突出颜色显示,标示为选中状态,为false则标示非选中状态
 */
private void setLinelayoutOne(boolean focus) {
    if (mRouteLineLayoutOne.getVisibility() != View.VISIBLE) {
        return;
    }
    try {
        int routeID = (int) mRouteLineLayoutOne.getTag();
        RouteOverLay overlay = routeOverlays.get(routeID);
        if (focus) {
            mCalculateRouteOverView.setText(Utils.getRouteOverView(overlay.getAMapNaviPath()));
            mAMapNavi.selectRouteId(routeID);
            overlay.setTransparency(ROUTE_SELECTED_TRANSPARENCY);
            mRouteViewOne.setVisibility(View.VISIBLE);
            mRouteTextStrategyOne.setTextColor(getResources().getColor(R.color.colorBlue));
            mRouteTextTimeOne.setTextColor(getResources().getColor(R.color.colorBlue));
            mRouteTextDistanceOne.setTextColor(getResources().getColor(R.color.colorBlue));
        } else {
            overlay.setTransparency(ROUTE_UNSELECTED_TRANSPARENCY);
            mRouteViewOne.setVisibility(View.INVISIBLE);
            mRouteTextStrategyOne.setTextColor(getResources().getColor(R.color.colorDark));
            mRouteTextTimeOne.setTextColor(getResources().getColor(R.color.colorBlack));
            mRouteTextDistanceOne.setTextColor(getResources().getColor(R.color.colorDark));
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

3、路线的红绿灯数的计算。

获取每个路段上的红绿灯的数据,进行叠加,进而得到这条路线上的红绿灯的总数。

public static int getTrafficNumber(AMapNaviPath path) {
    int trafficLightNumber = 0;
    if (path == null) {
        return trafficLightNumber;
    }
    List<AMapNaviStep> steps = path.getSteps();
    for (AMapNaviStep step : steps) {
        trafficLightNumber += step.getTrafficLightNumber();
    }
    return trafficLightNumber;
}

 

00:00 / 01:00
扫描二维码在手机端体验功能
体验移动端 扫码体验移动端

使用场景

出行类APP的路径选择。

用到产品

iOS 导航 SDK

核心类/接口

接口

说明

版本

AMapNaviBaseManager

pausesLocationUpdatesAutomatically

指定定位是否会被系统自动暂停。默认为YES。

V2.0.0版本起


allowsBackgroundLocationUpdates

开始模拟导航。

V2.0.0版本起


startEmulatorNavi

是否允许后台定位。

V2.0.0版本起

AMapNaviDriveManager

calculateDriveRouteWithStartPoints:endPoints:wayPoints:drivingStrategy:

带起点的驾车路径规划。

V2.0.0版本起


selectNaviRouteWithRouteID:

多路径规划时选择路径。

V2.0.0版本起


getTrafficStatusesWithStartPosition:distance:

获取某一范围内的路况光柱信息。

V2.0.0版本起

AMapNaviRoute

routeLength

导航路径总长度(单位:米)。

V2.0.0版本起


routeTime

导航路径所需的时间(单位:秒)。

V2.0.0版本起


routeTollCost

导航路线的花费金额(单位:元)

V2.0.0版本起

AMapNaviDriveManagerDelegate

driveManagerOnCalculateRouteSuccess:

驾车路径规划成功后的回调函数

V2.0.0版本起

AMapNaviRoute

routeTrafficLightCount

获取整条线路的红绿灯数量

V2.0.0版本起

核心难点

1、显示规划路线的路况。

- (void)addRoutePolylineWithRouteID:(NSInteger)routeID
{
    //必须选中路线后,才可以通过driveManager获取实时交通路况
    if (![self.driveManager selectNaviRouteWithRouteID:routeID])
    {
        return;
    }
    
    NSArray <AMapNaviPoint *> *oriCoordinateArray = [self.driveManager.naviRoute.routeCoordinates copy];
    NSArray <AMapNaviTrafficStatus *> *trafficStatus = [self.driveManager getTrafficStatusesWithStartPosition:0 distance:(int)self.driveManager.naviRoute.routeLength];
    
    NSMutableArray <AMapNaviPoint *> *resultCoords = [[NSMutableArray alloc] init];
    NSMutableArray <NSNumber *> *coordIndexes = [[NSMutableArray alloc] init];
    NSMutableArray <UIColor *> *strokeColors = [[NSMutableArray alloc] init];
    [resultCoords addObject:[oriCoordinateArray objectAtIndex:0]];
    
    //依次计算每个路况的长度对应的polyline点的index
    unsigned int i = 1;
    NSInteger sumLength = 0;
    NSInteger statusesIndex = 0;
    NSInteger curTrafficLength = [[trafficStatus firstObject] length];
    
    for ( ; i < [oriCoordinateArray count]; i++)
    {
        double segDis = [self calcDistanceBetweenPoint:[oriCoordinateArray objectAtIndex:i-1]
                                              andPoint:[oriCoordinateArray objectAtIndex:i]];
        
        //两点间插入路况改变的点
        if (sumLength + segDis >= curTrafficLength)
        {
            if (sumLength + segDis == curTrafficLength)
            {
                [resultCoords addObject:[oriCoordinateArray objectAtIndex:i]];
                [coordIndexes addObject:[NSNumber numberWithInteger:((int)[resultCoords count]-1)]];
            }
            else
            {
                double rate = (segDis==0 ? 0 : ((curTrafficLength - sumLength) / segDis));
                AMapNaviPoint *extrnPoint = [self calcPointWithStartPoint:[oriCoordinateArray objectAtIndex:i-1]
                                                                 endPoint:[oriCoordinateArray objectAtIndex:i]
                                                                     rate:MAX(MIN(rate, 1.0), 0)];
                if (extrnPoint)
                {
                    [resultCoords addObject:extrnPoint];
                    [coordIndexes addObject:[NSNumber numberWithInteger:((int)[resultCoords count]-1)]];
                    [resultCoords addObject:[oriCoordinateArray objectAtIndex:i]];
                }
                else
                {
                    [resultCoords addObject:[oriCoordinateArray objectAtIndex:i]];
                    [coordIndexes addObject:[NSNumber numberWithInteger:((int)[resultCoords count]-1)]];
                }
            }
            
            //添加对应的strokeColors
            [strokeColors addObject:[self defaultColorForStatus:[[trafficStatus objectAtIndex:statusesIndex] status]]];
            
            sumLength = sumLength + segDis - curTrafficLength;
            
            if (++statusesIndex >= [trafficStatus count])
            {
                break;
            }
            curTrafficLength = [[trafficStatus objectAtIndex:statusesIndex] length];
        }
        else
        {
            [resultCoords addObject:[oriCoordinateArray objectAtIndex:i]];
            
            sumLength += segDis;
        }
    }
    
    //将最后一个点对齐到路径终点
    if (i < [oriCoordinateArray count])
    {
        while (i < [oriCoordinateArray count])
        {
            [resultCoords addObject:[oriCoordinateArray objectAtIndex:i]];
            i++;
        }
        
        [coordIndexes removeLastObject];
        [coordIndexes addObject:[NSNumber numberWithInteger:((int)[resultCoords count]-1)]];
    }
    else
    {
        while (((int)[coordIndexes count])-1 >= (int)[trafficStatus count])
        {
            [coordIndexes removeLastObject];
            [strokeColors removeLastObject];
        }
        
        [coordIndexes addObject:[NSNumber numberWithInteger:((int)[resultCoords count]-1)]];
        //需要修改textureImages的最后一个与trafficStatus最后一个一致
        [strokeColors addObject:[self defaultColorForStatus:[[trafficStatus lastObject] status]]];
    }
    
    //添加Polyline
    NSInteger coordCount = [resultCoords count];
    CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D *)malloc(coordCount * sizeof(CLLocationCoordinate2D));
    for (int k = 0; k < coordCount; k++)
    {
        AMapNaviPoint *aCoordinate = [resultCoords objectAtIndex:k];
        coordinates[k] = CLLocationCoordinate2DMake(aCoordinate.latitude, aCoordinate.longitude);
    }
    
    //创建SelectableTrafficOverlay
    SelectableTrafficOverlay *polyline = [SelectableTrafficOverlay polylineWithCoordinates:coordinates count:coordCount drawStyleIndexes:coordIndexes];
    polyline.routeID = routeID;
    polyline.selected = NO;
    polyline.polylineWidth = 10;
    polyline.polylineStrokeColors = strokeColors;
    
    if (coordinates != NULL)
    {
        free(coordinates);
    }
    
    [self.mapView addOverlay:polyline level:MAOverlayLevelAboveLabels];
}
func addRoutePolylineWithRouteID(_ routeID: Int) {
    //必须选中路线后,才可以通过driveManager获取实时交通路况
    if !driveManager.selectNaviRoute(withRouteID: routeID) {
        return
    }

    guard let aRoute = driveManager.naviRoute else {
        return
    }

    //获取路线坐标串
    guard let oriCoordinateArray = aRoute.routeCoordinates else {
        return
    }
    guard let trafficStatus = driveManager.getTrafficStatuses(withStartPosition: 0, distance: Int32(aRoute.routeLength)) else {
        return
    }

    //创建带路况信息的polyline,具体代码见Demo
    ......

    mapView.add(polyline, level: .aboveLabels)
}

2、地图上同时显示多条路线时,如何控制这些路线的层级。

- (void)selecteOverlayWithRouteID:(NSInteger)routeID
{
    [self.mapView.overlays enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id<MAOverlay> overlay, NSUInteger idx, BOOL *stop)
     {
         if ([overlay isKindOfClass:[SelectableTrafficOverlay class]])
         {
             SelectableTrafficOverlay *selectableOverlay = overlay;
             
             /* 获取overlay对应的renderer. */
             MAMultiColoredPolylineRenderer * overlayRenderer = (MAMultiColoredPolylineRenderer *)[self.mapView rendererForOverlay:selectableOverlay];
             
             if (selectableOverlay.routeID == routeID)
             {
                 /* 设置选中状态. */
                 selectableOverlay.selected = YES;
                 
                 /* 修改renderer选中颜色. */
                 NSMutableArray *strokeColors = [[NSMutableArray alloc] init];
                 for (UIColor *aColor in selectableOverlay.polylineStrokeColors)
                 {
                     [strokeColors addObject:[aColor colorWithAlphaComponent:1]];
                 }
                 selectableOverlay.polylineStrokeColors = strokeColors;
                 overlayRenderer.strokeColors = selectableOverlay.polylineStrokeColors;
                 
                 /* 修改overlay覆盖的顺序. */
                 [self.mapView exchangeOverlayAtIndex:idx withOverlayAtIndex:self.mapView.overlays.count - 1];
                 [self.mapView showOverlays:@[overlay] animated:YES];
             }
             else
             {
                 /* 设置选中状态. */
                 selectableOverlay.selected = NO;
                 
                 /* 修改renderer选中颜色. */
                 NSMutableArray *strokeColors = [[NSMutableArray alloc] init];
                 for (UIColor *aColor in selectableOverlay.polylineStrokeColors)
                 {
                     [strokeColors addObject:[aColor colorWithAlphaComponent:0.25]];
                 }
                 selectableOverlay.polylineStrokeColors = strokeColors;
                 overlayRenderer.strokeColors = selectableOverlay.polylineStrokeColors;
             }
             
             [overlayRenderer glRender];
         }
     }];
}
/* 选择对应的polyline,改变polyline的颜色. */
func selecteOverlayWithRouteID(routeID: Int) {
    guard let allOverlays = mapView.overlays else {
        return
    }

    for (index, aOverlay) in allOverlays.enumerated() {

        if let selectableOverlay = aOverlay as? SelectableTrafficOverlay {

            /* 获取overlay对应的renderer. */
            let overlayRenderer = mapView.renderer(for: selectableOverlay) as! MAMultiColoredPolylineRenderer

            if selectableOverlay.routeID == routeID {

                /* 设置选中状态. */
                selectableOverlay.selected = true

                /* 修改renderer选中颜色. */
                var strokeColors = Array<UIColor>()
                for aColor in selectableOverlay.polylineStrokeColors {
                    strokeColors.append(aColor.withAlphaComponent(1.0))
                }
                selectableOverlay.polylineStrokeColors = strokeColors
                overlayRenderer.strokeColors = selectableOverlay.polylineStrokeColors

                /* 修改overlay覆盖的顺序. */
                mapView.exchangeOverlay(at: UInt(index), withOverlayAt: UInt(mapView.overlays.count - 1))
                mapView.showOverlays([aOverlay], animated: true)
            }
            else {
                /* 设置选中状态. */
                selectableOverlay.selected = false

                /* 修改renderer选中颜色. */
                var strokeColors = Array<UIColor>()
                for aColor in selectableOverlay.polylineStrokeColors {
                    strokeColors.append(aColor.withAlphaComponent(0.25))
                }
                selectableOverlay.polylineStrokeColors = strokeColors
                overlayRenderer.strokeColors = selectableOverlay.polylineStrokeColors
            }

            overlayRenderer.glRender()
        }
    }
}

3、路线的红绿灯数的计算。

调用 AMapNaviRoute 类的 routeTrafficLightCount 获取整条线路的红绿灯数量即可。