【GAS】GoogleAppsScriptで2点間のルートと道中の標高を表示【GoogleMap】

## 概要
GASで地図上に線を引く際、経緯度を並べた配列をラインにエンコードする。ルートを表示する際も、エンコードされたラインを使う。
そのラインに対して標高を取得するメソッドがあるので遊んでみた。

**関連記事**
[GoogleAppsScriptで地図を扱うTips](https://qiita.com/YasumiYasumi/items/d772bfa5f77201009d94)
[GoogleAppsScriptで地図に線や円を描写する](https://qiita.com/YasumiYasumi/items/b5b24eadfe795b07a4e1)

## 直線の高低差をグラフ化
[Class ElevationSampler](https://developers.google.com/apps-script/reference/maps/elevation-sampler) で標高を取得できる。取得した標高を、折れ線グラフでスプレッドシートに出力することにした。

まずはシンプルに直線でお試し。
分かりやすく富士山をぶった切ってみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/f9245f46-cbb2-9ce7-3e74-b718b2d6a5c4.png)
身延駅～駿河小山駅で直線を引いて100ヶ所の標高を取得、グラフ化するとこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/c03b79d0-e4dd-9543-079b-a312e1f647c7.png)
富士山っぽい^^
西から東に切ったので静岡側から見た形になってる。正面がどっちだとかの議論に参加するつもりはないです。

コードがこちら
```javascript
function elevationchart() {

  //2点を決める
  var pointA = Maps.newGeocoder().setLanguage('ja').geocode('JR身延駅');
  var pointB = Maps.newGeocoder().setLanguage('ja').geocode('JR駿河小山駅');

  //2点それぞれの緯度と経度を取得
  var latA = pointA.results[0].geometry.location.lat;
  var lngA = pointA.results[0].geometry.location.lng;
  var latB = pointB.results[0].geometry.location.lat;
  var lngB = pointB.results[0].geometry.location.lng;

  //経緯度を並べてエンコード
  var line = [latA,lngA,latB,lngB];
  var polyline = Maps.encodePolyline(line);

  //線に沿って100ヶ所の標高を取得
  var sample = Maps.newElevationSampler().samplePath(polyline, 100);

  //取得した標高をグラフ化
  var data = Charts.newDataTable()
                   .addColumn(Charts.ColumnType.NUMBER, '')
                   .addColumn(Charts.ColumnType.NUMBER, '標高');

  for(var i=0; i<sample.results.length; i++){
    data.addRow([i+1, sample.results[i].elevation]);
  }

  var chart = Charts.newLineChart()
                    .setDataTable(data)
                    .setOption('width',500)
                    .setOption('height',300)
                    .build();

  //できたグラフを画像にしてスプレッドシートに貼り付け
  var image = Utilities.base64Encode(chart.getAs('image/png').getBytes());
  var url = "data:image/png;base64," + encodeURI(image);

  SpreadsheetApp.getActiveSheet().insertImage(url,1,1);
}
```
`Maps.newElevationSampler().samplePath(エンコードされたpolyline, 個数)`で、エンコードされた線に沿って、いくつかの標高を取得できる。

グラフの設定は雑^^;
`sample`には標高のほか位置情報などがJSONで100ヶ所分入ってるので、順番に標高だけ取り出している。横軸に1～100、縦軸に標高。

なにか間違えてるんだろうけど、`insertChart(chart)`でシートにグラフを貼り付けようとするとエラーになるので、深く考えず画像にして貼り付けることに・・・。

## ルート検索
GASでルートを検索し、ルートを描写した地図画像をスプレッドシートに表示させるコードがこちら
```javascript
function searchroute() {

  var route = Maps.newDirectionFinder()
                  .setLanguage('ja')
                  .setOrigin('出発')
                  .setDestination('到着')
                  .setMode(Maps.DirectionFinder.Mode.DRIVING)
                  .getDirections();

  var polyline = route.routes[0].overview_polyline.points

  var map = Maps.newStaticMap()
                .setSize(500, 300)
                .setLanguage('ja')
                .setPathStyle(5,Maps.StaticMap.Color.RED,null)
                .addPath(polyline);

  SpreadsheetApp.getActiveSheet().insertImage(map,1,1);
}
```
ルート検索して、エンコードして、地図に描写して、シートに貼り付けてる。
細かい説明は割愛。

このような、ルートをエンコードしたラインに対して標高を取得する。

## ルート検索＆高低差グラフ
コードがこちら
```javascript
function route_elevation() {

  var start = '出発';
  var goal  = '到着';

  //ルート地図
  var route = Maps.newDirectionFinder()
                  .setLanguage('ja')
                  .setOrigin(start)
                  .setDestination(goal)
                  .setMode(Maps.DirectionFinder.Mode.DRIVING)
                  .getDirections();

  var line = route.routes[0].overview_polyline.points;

  var map = Maps.newStaticMap()
                .setSize(500, 300)
                .setLanguage('ja')
                .setPathStyle(5,Maps.StaticMap.Color.RED,null)
                .addPath(line);

  //標高グラフ
  var sample = Maps.newElevationSampler().samplePath(line, 100);

  var data = Charts.newDataTable()
                   .addColumn(Charts.ColumnType.STRING, '')
                   .addColumn(Charts.ColumnType.NUMBER, '標高');
                                  
  for(var i=0; i<sample.results.length; i++){
    data.addRow(['',sample.results[i].elevation]);
  }

  var chart = Charts.newLineChart()
                    .setDataTable(data)
                    .setXAxisTitle(start+' - '+goal)
                    .setYAxisTitle('[m]')
                    .setOption('width',500)
                    .setOption('height',300)
                    .build();

  var image = Utilities.base64Encode(chart.getAs('image/png').getBytes());
  var url = "data:image/png;base64," + encodeURI(image);

  //それぞれスプレッドシートに貼り付け
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.insertImage(map,1,1);
  sheet.insertImage(url,6,1);
}
```
ほぼ、先の２つのコードを繋げただけ。
グラフは左から右に並ぶので、出発-到着は西から東にすると見やすい。
今回もグラフは雑だけど、縦軸と横軸に表題をつけてみた。横軸に振ってた1～100は無くてもいいやと空欄に。

実行してみるとこんな感じ。

**駒澤大学 - 霞が関**
窪んでる部分はそれぞれ目黒川、渋谷駅、西麻布、溜池あたりか？ 河川、暗渠、外堀跡が低くなってて、実際の地形と合ってそう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/affe01c5-2afd-48fd-709b-bb7ad1702e65.png)

**甲州街道**
甲府盆地が良くわかる。それにしても笹子峠がエグいｗ
ルートは笹子トンネルを通ってるから、道路の標高ではなく地面の標高を取得するのかも？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/cd7f4b65-86bc-33d7-e1ce-4df37999988f.png)

**富士山**
ルート検索の種類を徒歩に変えて富士山を登ってみた。
傾斜が一定になるようにルートが引かれてるのね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/d033a75d-bac3-6fc1-0da1-39f82f4404c1.png)
東側ルートは少しなだらか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/708687/32f280d2-5866-fea8-bfee-dc3a2b92e7ad.png)


### おしまい