Geometry Libraryを使ってPathをエンコード/デコードする方法

今回は、緯度/経度の配列である「MVCArray」型をエンコードして、文字列に変換する方法、そして、そのエンコード文字列からデコードして「MVCArray」型のデータを取得する方法を紹介します。

なお、Google Maps関連の記事についてはこちらにまとめてありますので、ご覧ください。

Geometry Libraryを使ってPathをエンコード/デコードする方法

Geometry Libraryとは、Google Mapsで使うオブジェクトを利用した計算や判定、変換する関数群を提供するライブラリになっています。

Pathをエンコード/デコードするには「google.maps.geometry.encoding」を利用します。

Geometry Libraryを利用するには

Geometry Libraryを利用するには、Google Maps APIをロードする際に、Geometry Libraryを利用できるようなパラメータを設定しなければなりません。以下のようなコードが必要になります。

 <script src="https://maps.googleapis.com/maps/api/js?key=(APIキー)&libraries=geometry">

PolylineのPath(緯度/経度の集合体)をエンコードする/エンコード文字列からPolylineを描画する

サンプル

マップを複数回、クリックし、PolyLineを描画してください。




手順1

まず、マップを複数回数クリックし、Polylineを描画してください。

手順2

「↓エンコードする」ボタンを押して、Polylineの各緯度/経度情報をエンコードしてください。

手順3

「線を消す」ボタンを押して、Polylineやマーカーを削除させてみてください。

手順4

「↑デコードする」ボタンを押してみてください。エンコード文字列をもとに、消す前に描画させていた、Polylineとマーカーを再描画させています。

HTMLコード

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
   <title>Sample Map</title>
   <script defer
       src="https://maps.googleapis.com/maps/api/js?key=(APIキー)&callback=initMap&libraries=geometry" >
   </script>
   <style type="text/css">
      #map_canvas {
         width: 100%;
         height:70%;
      }
      html,
      body {
         height: 100%;
         margin: 0;
         padding: 0;
      }
   </style>
   <script type="text/javascript">
      var map;
      var clickedLines;
      var marker;
      function initMap() {
         var myLatlng = new google.maps.LatLng(35.68517826190777,139.7528236934712);
         var mapOptions = {
           zoom: 15,
           center: myLatlng
         }
         map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
         clickedLines = new google.maps.Polyline({
            geodesic: true,
            strokeColor: "#3333FF",
            strokeOpacity: 1.0,
            strokeWeight: 3
         });
         // マップにクリックイベントを設定
         google.maps.event.addListener(map, 'click', function(event) {
            // クリック時の位置を渡す
            drawOneLine(event.latLng);
         });
      }
      function drawOneLine(latLng) {
         var path = clickedLines.getPath();
         if ( path.length == 0 ) {
            createMarker(latLng);
            document.getElementById('txtLatLng').value = latLng;
         } else {
            document.getElementById('txtLatLng').value = document.getElementById('txtLatLng').value + "\n" + latLng;
         }
         path.push(latLng);
      
         clickedLines.setMap(map);
      }

      function createMarker(latLng) {
         marker = new google.maps.Marker({
            position: latLng,
            map: map,
            title: '最初の位置'
         });
      }

      function deleteAllLines() {
         var path = clickedLines.getPath();
         if ( path != undefined ) {
            if ( path.length >= 0 ){
               do {
                  if ( path.length == 0 ) break;
                  path.pop();
               } while(1);
            }
            
         }
         document.getElementById('txtLatLng').value = "";
         if ( marker != undefined ) {
            marker.setMap(null);
         }
         if ( clickedLines != undefined ) {
            clickedLines.setMap(null);
         }
      }
      function encodePath() {
         var path = clickedLines.getPath();
         var encodedPath = google.maps.geometry.encoding.encodePath(path);
         document.getElementById('txtEncoded').value = encodedPath;
      }
      function decodePath() {
         var sEncodedPath = document.getElementById('txtEncoded').value;
         if ( sEncodedPath.length > 0 ) {
            deleteAllLines();
            var path = google.maps.geometry.encoding.decodePath(sEncodedPath);
            document.getElementById('txtLatLng').value = path[0];
            marker.setPosition(path[0]);
            marker.setMap(map);
            for ( var i=1 ; i < path.length; i++ ) {
               document.getElementById('txtLatLng').value = document.getElementById('txtLatLng').value + "\n" + path[i];
            }
            clickedLines.setPath(path);
            clickedLines.setMap(map);
            
         }
      }
   </script>
</head>
<body>
   <div id="map_canvas"></div>
   <br />
   <textarea style="height:50px;width:80%;margin-left:20px;margin-bottom:10px;" id="txtLatLng"></textarea>
   <br />
   <input type="button" value="線を消す"  onclick="deleteAllLines();" style="margin-left:20px;"/>
   <input type="button" value="↓エンコードする"  onclick="encodePath();" style="margin-left:20px;"/><input type="button" value="↑デコードする"  onclick="decodePath();" style="margin-left:20px;"/>
   <br />
   <textarea style="height:50px;width:80%;margin-left:20px;margin-top:10px;" id="txtEncoded"></textarea>
</body>
</html>

デモ

エンコード/デコードする

エンコードする

「↓エンコードする」ボタンを押すと、エンコード処理が呼び出されます。

      function encodePath() {
         var path = clickedLines.getPath();
         var encodedPath = google.maps.geometry.encoding.encodePath(path);
         document.getElementById('txtEncoded').value = encodedPath;
      }

まず、PolylineオブジェクトのgetPath()メソッドを実行することで、描画されているPolylineの位置情報(path)を取得します。そのpathは「MVCArray<LatLng>」型で、位置情報を複数配列で保持している型になります。

その「MVCArray<LatLng>」型、または、「Array<LatLng>」型の値をencodePathメソッド渡すことで、位置情報の配列をエンコードし、文字列に変換することができます。

デコードする

「↑デコードする」ボタンを押すと、エンコード文字列から、デコードし、位置情報の配列を取得します。それをもとにマーカーを設定し、Polylineを描画するようにしてあります。

      function decodePath() {
         var sEncodedPath = document.getElementById('txtEncoded').value;
         if ( sEncodedPath.length > 0 ) {
            deleteAllLines();
            var path = google.maps.geometry.encoding.decodePath(sEncodedPath);
            document.getElementById('txtLatLng').value = path[0];
            marker.setPosition(path[0]);
            marker.setMap(map);
            for ( var i=1 ; i < path.length; i++ ) {
               document.getElementById('txtLatLng').value = document.getElementById('txtLatLng').value + "\n" + path[i];
            }
            clickedLines.setPath(path);
            clickedLines.setMap(map);
            
         }
      }

まず、「deleteAllLines()」ですべての線(Polylineとマーカー)をいったん削除します。その後、decodePath()にエンコード文字列を渡すことで、緯度/経度の配列型「MVCArray<LatLng>」型の変数に変換します。

配列の一つ目の緯度/経度にマーカーを設定、その後、テキストボックスに緯度/経度の配列文字列を設定し、PolylineのsetPath()メソッドに緯度/経度の配列型変数を渡すことで、Polylineを描画させることができます。最後にsetMap()でMapオブジェクトと紐づけて描画終了です。

ご参考

関連ページ