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

如何在Google Directions API中优化路线折线的平滑度?

提升Google Directions API折线平滑度的方法

问题描述

我需要在地图上显示更平滑的折线(当前折线存在尖锐拐点),注意到Routes Preferred API支持polylineQuality":"HIGH_QUALITY"参数,但Google Directions API没有这个选项,请问有什么办法可以提升折线的平滑度?

原有实现代码:

import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class Routing {
  Future<List<LatLng>> getPolylinePoints(
      LatLng source, LatLng destination) async {
    String apiKey = "API_KEY";
    String polylineQuality = "HIGH_QUALITY";
    String baseUrl = "https://maps.googleapis.com/maps/api/directions/json?";

    String url = "$baseUrl"
        "origin=${source.latitude},${source.longitude}&"
        "destination=${destination.latitude},${destination.longitude}&"
        "key=$apiKey&"
        "polylineQuality=$polylineQuality";

    var response = await http.get(Uri.parse(url));
    if (response.statusCode == 200) {
      var jsonData = jsonDecode(response.body);
      var points = jsonData['routes'][0]['overview_polyline']['points'];
      return decodePolyline(points);
    } else {
      throw Exception("Failed to load directions");
    }
  }

  List<LatLng> decodePolyline(String polyline) {
    List<LatLng> points = [];
    int index = 0;
    int len = polyline.length;
    int lat = 0;
    int lng = 0;

    while (index < len) {
      int b;
      int shift = 0;
      int result = 0;
      do {
        b = polyline.codeUnitAt(index++) - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
      } while (b >= 0x20);
      int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
      lat += dlat;

      shift = 0;
      result = 0;
      do {
        b = polyline.codeUnitAt(index++) - 63;
        result |= (b & 0x1f) << shift;
        shift += 5;
      } while (b >= 0x20);
      int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
      lng += dlng;

      LatLng p = LatLng((lat / 1E5).toDouble(), (lng / 1E5).toDouble());
      points.add(p);
    }

    return points;
  }
}

解决方案

方法一:改用Routes Preferred API

直接切换到支持polylineQuality参数的Routes Preferred API,该API返回的折线本身具备更高平滑度。修改代码如下:

Future<List<LatLng>> getPolylinePoints(
    LatLng source, LatLng destination) async {
  String apiKey = "API_KEY";
  String baseUrl = "https://routes.googleapis.com/directions/v2:computeRoutes";

  // 构造POST请求体
  var requestBody = jsonEncode({
    "origin": {
      "location": {
        "latLng": {
          "latitude": source.latitude,
          "longitude": source.longitude
        }
      }
    },
    "destination": {
      "location": {
        "latLng": {
          "latitude": destination.latitude,
          "longitude": destination.longitude
        }
      }
    },
    "travelMode": "DRIVE",
    "polylineQuality": "HIGH_QUALITY",
    "polylineEncoding": "ENCODED_POLYLINE"
  });

  var response = await http.post(
    Uri.parse(baseUrl),
    headers: {
      "Content-Type": "application/json",
      "X-Goog-Api-Key": apiKey,
      "X-Goog-FieldMask": "routes.polyline"
    },
    body: requestBody,
  );

  if (response.statusCode == 200) {
    var jsonData = jsonDecode(response.body);
    var points = jsonData['routes'][0]['polyline']['encodedPolyline'];
    return decodePolyline(points);
  } else {
    throw Exception("Failed to load directions: ${response.body}");
  }
}

注意:Routes Preferred API为付费服务,需确保API密钥已开通对应权限,请求方式为POST,需指定字段掩码。

方法二:客户端折线平滑处理

若不想切换API,可在客户端对Directions API返回的折线点做平滑处理,以下是简单的贝塞尔曲线平滑实现:
在Routing类中添加平滑函数:

List<LatLng> smoothPolyline(List<LatLng> points) {
  if (points.length < 3) return points;

  List<LatLng> smoothed = [];
  smoothed.add(points[0]);

  for (int i = 1; i < points.length - 1; i++) {
    LatLng p0 = points[i - 1];
    LatLng p1 = points[i];
    LatLng p2 = points[i + 1];

    // 计算中间控制点
    double midLat1 = (p0.latitude + p1.latitude) / 2;
    double midLng1 = (p0.longitude + p1.longitude) / 2;
    double midLat2 = (p1.latitude + p2.latitude) / 2;
    double midLng2 = (p1.longitude + p2.longitude) / 2;

    smoothed.add(LatLng(midLat1, midLng1));
    smoothed.add(LatLng(midLat2, midLng2));
  }

  smoothed.add(points.last);
  return smoothed;
}

在获取原始折线点后调用该函数:

// 在getPolylinePoints的返回逻辑中修改
List<LatLng> rawPoints = decodePolyline(points);
return smoothPolyline(rawPoints);

也可使用第三方库(如flutter_map_polyline_smoother)简化实现。

方法三:获取详细路径点

Directions API的overview_polyline是简化折线,而legs下的steps包含更密集的路径点,合并所有steps的polyline可提升视觉平滑度:
修改getPolylinePoints中的解析逻辑:

if (response.statusCode == 200) {
  var jsonData = jsonDecode(response.body);
  List<LatLng> allPoints = [];
  
  // 遍历所有legs和steps,合并路径点
  for (var leg in jsonData['routes'][0]['legs']) {
    for (var step in leg['steps']) {
      String stepPolyline = step['polyline']['points'];
      allPoints.addAll(decodePolyline(stepPolyline));
    }
  }
  
  return allPoints;
}

该方法得到的点集更密集,拐点更自然,可结合方法二进一步优化。


内容的提问来源于stack exchange,提问作者m.altinisik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 03:05:30