こんにちは!
デバイスソフトウエア開発部の米森です。最近業務でGoogle MapのRoutes APIを使う機会がありました。Routes APIとは、Google Mapで経路検索をした時に表示されるあのルートを簡単に描画できるAPIです。しかし、便利な反面、痒いところに手が届かないという部分もあったので、今回はそのあたりを共有させてください!
Routes APIの概要
APIの概要は、公式ドキュメントにて分かりやすく整理されているので、そちらに譲ります。
今回の記事に関わる部分だけかいつまんで説明すると、Routes APIとは、道路にそったルートを描画するために必要なプロットを補完してくれる機能です。
例えば、車が↓のようなルートで道路を走り、3点の緯度経度プロットを取得できたと仮定します。
これら3点のプロットだけで車の走行軌跡を再現しようとすると、①から②へ行く部分で建物を横切ってしまいます。
この3点をRoutes APIに渡すと、Google Mapの道路に沿うルートに変換し、足りないプロットを補完してくれます。これで、建物を横切ることなく、道路に沿った軌跡を地図上で再現できます。
サンプル実演
実際にAPIを実行してみましょう。弊社オフィスから、JR札幌駅までのルートを取得するというケースを考えます。
2地点の位置関係と緯度経度は下記の通り。
こちらの公式ページに、サンプルPOSTリクエストがあるので、それをもとにHTTPリクエストを投げてみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
curl -X POST -d '{ "origin":{ "location":{ "latLng":{ "latitude": 43.06336507676069, // 弊社オフィス緯度 "longitude": 141.3571428420565 // 弊社オフィス経度 } } }, "destination":{ "location":{ "latLng":{ "latitude": 43.068750409171145, // JR札幌駅緯度 "longitude": 141.35075529917603 // JR札幌駅経度 } } }, "travelMode": "DRIVE", "routingPreference": "TRAFFIC_AWARE", "computeAlternativeRoutes": false, "routeModifiers": { "avoidTolls": false, "avoidHighways": false, "avoidFerries": false }, "languageCode": "en-US", "units": "IMPERIAL" }' \ -H 'Content-Type: application/json' -H 'X-Goog-Api-Key: <YOUR_API_KEY>' \ // 自身のAPIキー -H 'X-Goog-FieldMask: routes.duration,routes.distanceMeters,routes.polyline.encodedPolyline' \ 'https://routes.googleapis.com/directions/v2:computeRoutes' |
サンプルからの変更点は下記の3つだけです。
origin
: 出発点destination
: 到着点Google Maps API KEY
: APIキー
これをPOSTすると…
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "routes": [ { "distanceMeters": 1363, "duration": "418s", "polyline": { "encodedPolyline": "mxyeG{vw}YfB[g@sHo\\lFbBnU_G|@Dz@`@|D`@hF" } } ] } |
レスポンスが返却されました。レスポンスデータはそれぞれ下記の通りです。
distanceMeters
: 道のり距離duration
: 所要時間polyline
:encodedPolyline
: エンコードされた緯度経度配列
encodedPolyline
というのが今回の肝で、このデータの実態はエンコードされた「緯度経度配列」です。こちらの公式ページにエンコードアルゴリズムの仕様があるので、それをリバースすれば、エンコード前の緯度経度配列が取得できる(はず)です。が、さすがに大変なので、Googleさんが用意してくれているWebデコーダーを使ってみましょう。
こちらにencodedPolyline
を入力すると、それをデコードしてくれ、さらにGoogle Maps上にルートを描画してくれます。
できました!
APIには「弊社オフィス」と「JR札幌駅」のプロット2点しか渡していませんが、APIがそれを補完してそれっぽいルートが描画されています。
ちなみに、デコード用のライブラリ・メソッド(google.maps.geometry.encoding.decodePath
)も用意されているので、下記のようなフローでローカルの地図上でも上記のようなルートを描画できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// getRoute()で、上記のHTTP POSTを実行する想定 getRoute(origin, destination) .then((res) => { // レスポンスから、エンコードされた緯度経度配列を取得 const encodedPolyline = res.data.routes[0].polyline.encodedPolyline; // ライブラリを使用してデコード const decodedPath = google.maps.geometry.encoding.decodePath(encodedPolyline); // ポリラインインスタンスを生成 // ※ポリライン = Google Map上のお絵描きオブジェクト const polyline = new google.maps.Polyline({ path: decodedPath, // 緯度経度配列 strokeColor: 'red', // 色 strokeWeight: 20, // 線の太さ }); マップインスタンスにポリラインをセット polyline.setMap(map); }) // 以降エラーハンドリング |
こんな感じで描画されます。
Google Maps APIを使用した基本的な実装方法については、下記の記事をご参照ください!
便利な反面、挙動制御が難しいことも…
緯度経度の配列さえ渡せばそれを一筆書きしてもらえるのですが、その反面、点と点の間をどう結ぶのかはAPI依存になってしまいます。ほとんどの場合、生成されるルートに問題はないのですが、ある特定の条件下では想定外のルートが描画されてしまいます。
例えば、中央分離帯がある道路の片側車線をずっとまっすぐ走行していたのに、ある一点だけ緯度経度プロットが反対車線側にずれてしまったと仮定します。この状況では、APIに「反対車線に移動した」と判定され、その地点までの迂回路をサジェストされてしまいます。
以下のようなプロットを考えます。車は常に北(上)側の車線を走っているのですが、③の地点で緯度経度が下(南)側に少しずれてしまいました。
この緯度経度配列をAPIに渡すと、以下のようなルートが描画されてしまいます。
大分遠回りさせられましたね… これはいただけません。
方角を指定してあげてルートを制御
この問題、いろいろと解決策はありそうですが、本記事ではプロットの方角を使用したものを紹介します。
先ほどの迂回路のケースは、車は東向きに走っているのに、③のプロットは西向きに走っているとRoutes APIに判断されてしまったことが原因です。
なので、Routes APIに対して「③のプロットの方角は東!」と明示的に教えてあげれば上手くいくかもしれません。そしてなんと、Routes APIのリクエストパラメータにはheading
というプロットの方角を指定できるものがあります(公式ドキュメント)。
0~359で方角を指定できるとのことなので、3点のプロットに "heading": 90
(真東)を指定してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
curl -X POST -d '{ "origin":{ "location":{ "latLng":{ "latitude": 43.06184383295933, "longitude": 141.34954550117448 }, "heading": 90 // 追加 } }, "destination":{ "location":{ "latLng":{ "latitude": 43.0619054927957, "longitude": 141.35118917920653 }, "heading": 90 // 追加 } }, "intermediates":[ { "location":{ "latLng":{ "latitude": 43.061952471676996, "longitude": 141.35035729325875 }, "heading": 90 // 追加 } } ], // 以下省略 |
レスポンスをもとに、ルートを描画してみると…
想定通りのプロットができました!
緯度経度情報に加えて、方角情報も保持している場合に限られますが、これを活用すれば想定外のルート描画の可能性を少しは減らせそうです!
まとめ
Routes APIの概要と、ちょっとしたtipを紹介させていただきました。今回は言及しませんでしたが、車両タイプ、高速道路の有無、渋滞の考慮など、こちらから設定できる項目は他にも色々あるので、ぜひ公式ドキュメントをご参照ください。簡単にルートを描画できるので、とてもおもしろいです!
エコモットでは一緒にモノづくりをしていく仲間を随時募集しています。弊社に少しでも興味がある方はぜひ下記の採用ページをご覧ください!