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
相关产品推荐
相关产品推荐

