GooglemapAPI/Tips


ルート案内で出力される経路の座標を取得する

ルート案内を実行すると2地点が線の組み合わせによって結ばれるが、その線を結ぶための点の座標を取得するためのスクリプト。
スコープとか適当で説明しやすさ優先で書いてるのでそのへんはあんまり気にしないで下さい。
今回は東京から名古屋を経由して大阪に行く経路で出します。

まずHTMLをこんな感じで作ります。
<!DOCTYPE html>
<html>
<head>
  <title>Map</title>
  <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
  <meta charset="utf-8">
  <link rel="stylesheet" href="style.css" type="text/css" />
  <script type="text/javascript"
    src="http://maps.googleapis.com/maps/api/js?sensor=false">
  </script>
  <script type="text/javascript"
    src="zahyo.js">
  </script>
</head>
<body>
  <div id="display"></div>
  <div id="map_canvas"></div>
</body>
</html>

zahyo.jsをこんな感じで。
こちらは大雑把バージョンです。後で高精度バージョンも掲載します。
var map;

function initialize()
{
  var mapOptions =
  {
    center: new google.maps.LatLng( 35.689666, 139.691697 ),
    zoom: 6,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  };
  map = new google.maps.Map( document.getElementById( "map_canvas" ), mapOptions );

  calcRoute();
}

var directionsService = new google.maps.DirectionsService();
var directionResults = [];
var directionPaths = [];

function calcRoute()
{
  var places = [
    new google.maps.LatLng( 35.689666, 139.691697 ), // 東京
    new google.maps.LatLng( 35.181455, 136.906425 ), // 名古屋
    new google.maps.LatLng( 34.69385, 135.502106 ) // 大阪
  ];

  for( i = 0; i < places.length - 1; i++ )
  {
    var request = {
      origin: places[i],
      destination: places[i + 1],
      travelMode: google.maps.TravelMode.WALKING
    };
    
    directionsService.route( request, function( result, status )
    {
      if( status == google.maps.DirectionsStatus.OK )
      {
        myRoute = result.routes[0];
        directionResults.push( status );
        directionPaths.push( myRoute.overview_path ); // およそ座標取る用

        var result = true;
        for( j = 0; j < places.length - 1;  j++)
        {
          if( directionResults[j] != google.maps.DirectionsStatus.OK )
          {
            result = false;
          }
        }

        if( result == true )
        {
          latlngs = String( directionPaths ).replace( /\(|\)/g, "" ).split( "," );
          var display = document.getElementById( "display" );
          display.innerHTML = String( directionPaths ).replace( /\)\,\(/g, "<br>" ).replace( /\(|\)/g, "" ); // 座標表示する用

          var polylines = [];
          for( var k = 0; k < latlngs.length; k=k+2 )
          {
            polylines.push( new google.maps.LatLng( latlngs[k], latlngs[k+1] ) );
          }
  
          var flightPath = new google.maps.Polyline({
            path: polylines,
            strokeWeight: 2
          });
  
          flightPath.setMap(map); // polyline表示する用
        }
      }
    });
  }
}

google.maps.event.addDomListener(window, 'load', initialize);
これで実行すれば経路間の座標が出るのと、その座標を順番に結んだ線が表示されます。
表示した時に通過順序がおかしくなってしまうことがあるので、その時はページを更新してみて下さい。

では、順番に中身の説明です。HTMLの方は割愛します。
まずmap変数を宣言しているのとinitialize関数が宣言されてますが、これはよくある記述だと思うので詳しい説明は省きます。
なおinitialize関数の中でcalcRoute関数を呼んでますが、このcalcRoute関数が今回のメインです。

続けていくつかの変数を初期化しています。
var directionsService = new google.maps.DirectionsService();
var directionResults = [];
var directionPaths = [];
directionServiceは経路探索をするためのオブジェクトです。
後程このオブジェクトのrouteメソッドを使用して経路探索を行います。

directionResultsは地点間の経路探索が終了した時の結果(OKかNGか)を格納する配列です。
全ての経路探索が正常に完了したかどうかの判定に使用します。
今回で言えば東京⇔名古屋の結果と、名古屋⇔大阪の結果を格納します。

directionPathsは実際の地点間経路の座標群を格納する配列です。

ではいよいよcalcRouteの中身を説明します。
まずplaces配列に各地点の座標を順番に記述します。
var places = [
  new google.maps.LatLng( 35.689666, 139.691697 ), // 東京
  new google.maps.LatLng( 35.181455, 136.906425 ), // 名古屋
  new google.maps.LatLng( 34.69385, 135.502106 ) // 大阪
];
東京から名古屋を経由して大阪という順番ですね。
算出したい経路に合わせて変更して下さい。

次に各地点間の経路探索処理をさせるためのオブジェクトを作成してrequest変数に格納します。
for( i = 0; i < places.length - 1; i++ )
{
  var request = {
    origin: places[i],
    destination: places[i + 1],
    travelMode: google.maps.TravelMode.WALKING
  };

  ・・・
}    
先程作成したplaces配列を順番に処理し、開始点(origin)と終了点(destination)及び探索タイプ(travelMode)を定義したオブジェクトを作成してます。

次は探索処理の実行です。
directionsService.route( request, function( result, status )
{
  if( status == google.maps.DirectionsStatus.OK )
  {
    ・・・
  }
});
directionService変数に格納したgoogle.maps.DirectionsServiceオブジェクトのrouteメソッドを使用し、requestを渡して経路探索を実行します。
経路探索は非同期処理なので、第2引数には結果が返ってきた時に実行するcallback関数を定義してます。

callback関数では、探索結果がOKだった場合の処理が下記の様に記述されています。
myRoute = result.routes[0];
directionResults.push( status );
directionPaths.push( myRoute.overview_path ); // およそ座標取る用

var result = true;
for( j = 0; j < places.length - 1;  j++)
{
  if( directionResults[j] != google.maps.DirectionsStatus.OK )
  {
    result = false;
  }
}

if( result == true )
{
  ・・・
}
まず処理結果はDirectionsResultオブジェクトとしてcallback関数に渡され、経路情報はDirectionsResultオブジェクトのroutesプロパティ(中身は配列)の内、1番目の要素に格納されているのでこれを取り出してmyRoute変数に格納します。
次の行では処理結果がOKだったことを先だって宣言した配列変数に追加します。
次のdirectionPaths.push( myRoute.overview_path )ですが、overview_pathメソッドは経路探索結果に対するおおまかな座標群を返す物で、その結果を配列に格納しています。
経路探索結果は数千から数万の座標群で構成されることがありますが、overview_pathではせいぜい数百といったところなので、それほどの精度を求めない場合はこれで良いと思います。
高い精度が必要な場合については後述します。

その次のforループでは、全ての処理結果が正常に返ってきたかどうかをチェックし、チェックを通過したら座標群を整形して出力する処理に入ります。

出力処理はこちらです。
var latlngs = String( directionPaths ).replace( /\(|\)/g, "" ).split( "," );
var display = document.getElementById( "display" );
display.innerHTML = String( directionPaths ).replace( /\)\,\(/g, "<br>" ).replace( /\(|\)/g, "" ); // 座標表示する用

var polylines = [];
for( var i = 0; i < latlngs.length; i=i+2 )
{
  polylines.push( new google.maps.LatLng( latlngs[i], latlngs[i+1] ) );
}
  
var flightPath = new google.maps.Polyline({
  path: polylines,
  strokeWeight: 2
});
  
flightPath.setMap(map); // polyline表示する用
結果は配列で返ってくるので、String型にキャストして括弧などを除去しています。
座標の表示は3行目、経路の線の表示は最後の行なので、それぞれ出力を抑制したい場合はコメントして下さい。

そして最後にこれですね。
google.maps.event.addDomListener(window, 'load', initialize);
まあ、これも定番なので特に説明はしません。

さて、結果を表示すると経路の線が道路に正確には重なっていないと思います。
これはoverview_pathメソッドで得られるおおまかな座標を使って描いているからです。

これを正確に道路に重なる線(というか、実際に経路探索で出る線と同じ物)にするためには記述を以下の様に変更します。
directionPaths.push( myRoute.overview_path ); // およそ座標取る用

 ↓このように変更

// 正確な座標取る用
for( l = 0; l < myRoute.legs.length; l++ )
{
  for( m = 0; m < myRoute.legs[l].steps.length; m++ )
  {
    directionPaths.push( myRoute.legs[0].steps[m].path );
  }
}
これで全座標を取得することができますが、東京⇒名古屋⇒大阪の経路で全座標数が1万を超える程になるので、簡易的な方と必要に応じて使い分けて下さい。

  • 最終更新:2016-01-18 11:46:05

このWIKIを編集するにはパスワード入力が必要です

認証パスワード