You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MapBox绘制超25个途经点的环澳路线技术方案问询

解决方案:拆分请求是唯一可行的方案

很遗憾,单次调用MapBox Route Builder确实无法满足你的需求——因为你同时触发了两个API硬限制:

  • 途经点总数(含起点和终点)超过了25个的上限;
  • 路线总距离(12000公里)也突破了10000公里的限制。

MapBox的这些限制是API层面的硬性规则,没有官方绕过方法,所以你必须通过拆分请求来实现完整路线的绘制。下面是具体的实现思路和代码调整建议:

1. 拆分坐标与请求批次

首先把你的26个坐标点分成两个符合要求的批次:

  • 每个批次的总距离不超过10000公里;
  • 每个批次的点总数(起点+途经点+终点)不超过25个。

比如你可以将路线从中间位置拆分:

  • 第一批次:从起点到第13个坐标点(确保总距离≤10000公里,点数量≤25);
  • 第二批次:从第13个坐标点到最终终点(同样满足两个限制)。

如果后续坐标点继续增加,可以写一个通用的拆分逻辑,自动将所有点分成多个符合条件的批次。

2. 调整代码实现

你可以基于现有代码修改,实现多批次请求并合并路线:

// 示例:拆分坐标列表为两个批次
fun splitCheckPoints(checkPointList: List<YourPointType>): Pair<List<YourPointType>, List<YourPointType>> {
    val midIndex = checkPointList.size / 2
    val firstBatch = checkPointList.subList(0, midIndex + 1)
    val secondBatch = checkPointList.subList(midIndex, checkPointList.size)
    return Pair(firstBatch, secondBatch)
}

// 批量请求路线并合并
fun fetchAndDrawFullRoute(startPoint: Point, endPoint: Point, checkPointList: List<YourPointType>) {
    val (firstBatch, secondBatch) = splitCheckPoints(checkPointList)
    val allRoutes = mutableListOf<Route>()

    // 请求第一批次路线
    val firstRouteBuilder = NavigationRoute.builder(mContext)
        .accessToken(MapBoxUtils.MAP_KEY)
        .origin(startPoint)
        .destination(firstBatch.last().toPoint())
        .profile(DirectionsCriteria.PROFILE_CYCLING)
    
    for (point in firstBatch.subList(1, firstBatch.size - 1)) {
        firstRouteBuilder.addWaypoint(point.toPoint())
    }

    firstRouteBuilder.build().getRoute(object : Callback<DirectionsResponse> {
        override fun onFailure(call: Call<DirectionsResponse>, t: Throwable) {
            Timber.e("First batch error: ${t.message}")
        }

        override fun onResponse(call: Call<DirectionsResponse>, response: Response<DirectionsResponse>) {
            response.body()?.routes()?.firstOrNull()?.let { route ->
                allRoutes.add(route)
                // 请求第二批次路线
                fetchSecondBatch(secondBatch, endPoint, allRoutes)
            } ?: showToast("No route found for first batch")
        }
    })
}

fun fetchSecondBatch(batch: List<YourPointType>, endPoint: Point, allRoutes: MutableList<Route>) {
    val secondRouteBuilder = NavigationRoute.builder(mContext)
        .accessToken(MapBoxUtils.MAP_KEY)
        .origin(batch.first().toPoint())
        .destination(endPoint)
        .profile(DirectionsCriteria.PROFILE_CYCLING)
    
    for (point in batch.subList(1, batch.size - 1)) {
        secondRouteBuilder.addWaypoint(point.toPoint())
    }

    secondRouteBuilder.build().getRoute(object : Callback<DirectionsResponse> {
        override fun onFailure(call: Call<DirectionsResponse>, t: Throwable) {
            Timber.e("Second batch error: ${t.message}")
        }

        override fun onResponse(call: Call<DirectionsResponse>, response: Response<DirectionsResponse>) {
            response.body()?.routes()?.firstOrNull()?.let { route ->
                allRoutes.add(route)
                // 合并并绘制所有路线
                drawCombinedRoute(allRoutes)
            } ?: showToast("No route found for second batch")
        }
    })
}

fun drawCombinedRoute(routes: List<Route>) {
    // 合并所有路线的坐标点
    val combinedCoordinates = mutableListOf<Point>()
    routes.forEachIndexed { index, route ->
        val coords = route.geometry()?.coordinates() ?: return@forEachIndexed
        // 跳过重复的衔接点(除了第一个路线的起点)
        if (index > 0) {
            combinedCoordinates.addAll(coords.subList(1, coords.size))
        } else {
            combinedCoordinates.addAll(coords)
        }
    }
    // 这里执行绘制折线的逻辑
}

3. 额外优化建议

  • 距离校验:拆分批次前可以先计算每段的距离,确保每个批次的总距离不超过10000公里,避免请求失败;
  • 动态批次拆分:如果后续坐标点数量持续增加,可以写一个循环逻辑,自动将所有点分成N个符合条件的批次,而不是固定拆成两个;
  • 错误处理:增加批次请求失败后的重试逻辑,提升稳定性。

内容的提问来源于stack exchange,提问作者Sadda Hussain

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:44:33