🔖

FlutterMapで経路検索

2025/02/01に公開

FlutterMapと経路計算アルゴリズム

FlutterMapパッケージとをopenstreetmapしようしてマップを実装する方法は以下の記事参考
経路計算アルゴリズムはOSRMをしようします
https://www.openstreetmap.org/#map=5/35.59/134.38
https://project-osrm.org/
https://qiita.com/wdtkr/items/d06822b97654372385f0

経路計算の実装

以下のようにすることでurlを参照し、経路計算ができます。
startPointとgoalPointはそれぞれ座標を初期値として緯度経度どちらも含めた値を用意してください。

final url =
      "http://router.project-osrm.org/route/v1/driving/${startPoint.longitude},${startPoint.latitude};${goalPoint.longitude},${goalPoint.latitude}?geometries=geojson";
final response = await http.get(Uri.parse(url));

あとはif文などで通常のAPIでのエラーハンドリングなどを行いstatusCodeが200の場合以下を実行します。

final data = json.decode(response.body);

    // GeoJSON形式の座標データを取得
final List<dynamic> coordinates =
        data['routes'][0]['geometry']['coordinates'];

    // 緯度経度形式に変換
final RoutePoints =
        coordinates.map((coord) => LatLng(coord[1], coord[0])).toList();

関数化してRoutePointsreturnすれば経路計算のロジックは完成です

コード全体

Future<List<LatLng>> fetchRoute(startPoint, goalPoint) async {
  final url =
      "http://router.project-osrm.org/route/v1/driving/${startPoint.longitude},${startPoint.latitude};${goalPoint.longitude},${goalPoint.latitude}?geometries=geojson";

  final response = await http.get(Uri.parse(url));
  if (response.statusCode == 200) {
    final data = json.decode(response.body);

    // GeoJSON形式の座標データを取得
    final List<dynamic> coordinates =
        data['routes'][0]['geometry']['coordinates'];

    // 緯度経度形式に変換
    final RoutePoints =
        coordinates.map((coord) => LatLng(coord[1], coord[0])).toList();


    return RoutePoints;
  } else {
    throw Exception("経路データを取得できませんでした");
  }
}

マップ側の実装

map側のコードはHooksで実装しました。statefullの場合はそれに合わせてかきなおしてください。
<List<LatLng>>を格納するためのListを作成し、そこにさっきのロジックのreturnされた値を代入することで計算されたルートが表示されます。

///map.dart
final routePoints = useState<List<LatLng>>([]);
useEffect(() {
      // 非同期でルートを取得
      Future<void> loadRoute() async {
        try {
          final fetchedRoutePoints = await fetchRoute(
            start,
            goal,
          );
          routePoints.value = fetchedRoutePoints;
        } catch (e) {
          debugPrint("ルート取得エラー: $e");
        }
      }

      loadRoute();
      return null;
    }, []);
//~~~~省略~~~~
body: FlutterMap(
//~~~~省略~~~~
children:[
//~~~~省略~~~~
if (routePoints.value.isNotEmpty)
            PolylineLayer(
              polylines: [
                Polyline(
                  points: routePoints.value,
                  strokeWidth: 3.0,
                  color: Colors.blue,
                ),
              ],
            ),
    ],
),

感想

今回はGooglMapAPIを取得するのが面倒だったのでこれらの方法で実装しました。今回の方法だと曲がり角が雑だったり最短経路(高速道路使用)といった制限が多いので経路にオプションをつけたり正確なルートが必要な場合はGooglMapAPIを取得して計算したほうが良いと感じる実装になりました。

Discussion