地域メッシュコードから緯度経度を取得してMapboxにポリゴンを描画

# できたもの
地域メッシュコード、例えば`53392425123`を与えてやるとその地域をポリゴンで表示してくれます。今回は8分の１メッシュコードまでを対応しています。
![スクリーンショット 2019-08-02 13.12.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290902/48dff8fd-e87a-0baf-8b7d-86c16838833a.png)

## ソース
細かい計算もあるので少し長くなってますがこの様になっています。

```html
<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8' />
    <title>sample</title>
    <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
    <script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.js'></script>
    <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.2.0/mapbox-gl.css' rel='stylesheet' />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id='map'></div>

<script>
mapboxgl.accessToken = 'Mapboxのアクセスキーをここに貼り付けてください';
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v11',
    center: [139.5664063, 35.51822917],
    zoom: 15
});

map.on('load', function () {
    var geojson = {
        'id': 'hogehoge',
        'type': 'fill',
        'source': {
            'type': 'geojson'
        },
        'layout': {},
        'paint': {
            'fill-color': '#088',
            'fill-opacity': 0.8
        }
    }

    // ここからメッシュコードの計算
    var mesh_code = "53392425123";

    let first_coordinate = first(mesh_code);
    let second_coordinate = second(mesh_code);
    let third_coordinate = third(mesh_code);
    let forth_coordinate = forth(mesh_code);
    let fifth_coordinate = fifth(mesh_code);
    let sixth_coordinate = sixth(mesh_code);
    lat = (first_coordinate[1] + second_coordinate[1] + third_coordinate[1] + forth_coordinate[1] + fifth_coordinate[1] + sixth_coordinate[1]) / 3600;
    lon = (first_coordinate[0] + second_coordinate[0] + third_coordinate[0] + forth_coordinate[0] + fifth_coordinate[0] + sixth_coordinate[0]) / 3600;

    var upper_lat = lat + 3.75/3600;
    var right_log = lon + 5.625/3600;

    geojson['source']['data']  = {
      'type': 'Feature',
      'geometry': {
        'type': 'Polygon',
        'coordinates': [[
          [lon,lat],
          [lon,upper_lat],
          [right_log,upper_lat],
          [right_log,lat],
        ]]
      }
    };

    map.addLayer(geojson);
});
</script>

<script>
// それぞれの計算を定義
function first(mesh_code) {
  var lat = mesh_code.slice(0, 2);
  var lon = mesh_code.slice(2, 4);
  return [(parseInt(lon) + 100) * 3600, lat / 1.5 * 3600] // 3600をかけて秒に直す
}

function second(mesh_code) {
  var lat = mesh_code.slice(4, 5);
  var lon = mesh_code.slice(5, 6);
  return [lon * 7.5 * 60, lat * 5 * 60] // 60をかけて秒に直す
}

function third(mesh_code) {
  var lat = mesh_code.slice(6, 7);
  var lon = mesh_code.slice(7, 8);
  return [lon * 45, lat * 30]
}

function forth(mesh_code) {
  let forth = mesh_code.slice(8, 9);
  let lat;
  let lon;
  if (is_south(forth)) {
    lat = 0
  } else {
    lat = 15
  }

  if (is_west(forth)) {
    lon = 0;
  } else {
    lon = 22.5;
  }

  return [lon, lat];
}

function fifth(mesh_code) {
  let fifth = mesh_code.slice(9, 10);
  let lat;
  let lon;
  if (is_south(fifth)) {
    lat = 0
  } else {
    lat = 7.5
  }

  if (is_west(fifth)) {
    lon = 0;
  } else {
    lon = 11.25;
  }

  return [lon, lat];
}

function sixth(mesh_code) {
  let sixth = mesh_code.slice(10, 11);
  let lat;
  let lon;
  if (is_south(sixth)) {
    lat = 0
  } else {
    lat = 3.75
  }

  if (is_west(sixth)) {
    lon = 0;
  } else {
    lon = 5.625;
  }

  return [lon, lat];
}

function is_south(code) {
  if (code == 1 || code == 2) {
    return true
  }
  return false
}

function is_west(code) {
  if (code == 1 || code == 3) {
    return true;
  }
  return false;
}
</script>
</body>
</html>
```

## 解説
計算方法は[Wikipedia](https://ja.wikipedia.org/wiki/%E5%9C%B0%E5%9F%9F%E3%83%A1%E3%83%83%E3%82%B7%E3%83%A5)を参照しています。ちなみにメッシュから割り出している緯度経度はメッシュの南西端（左下の端っこ）を指しています。

#### 1次メッシュコード
> 4桁の数字で、上2桁が緯度（1.5倍して分以下を切り上げたもの）、下2桁が経度（下2桁）を表す。1次メッシュコードはメッシュの南西端の緯度経度を用いて次式で算出される：緯度をlat[度]、経度をlon[度]とすると、 {\displaystyle (lat\times 1.5\times 100)+(lon-100)} {\displaystyle (lat\times 1.5\times 100)+(lon-100)}。

つまり…
経度は先頭二桁に100を足す。
緯度は3~4桁目を1.5で割ってあげれば良い

```javascript
function first(mesh_code) {
  var lat = mesh_code.slice(0, 2);
  var lon = mesh_code.slice(2, 4);
  return [(parseInt(lon) + 100) * 3600, lat / 1.5 * 3600] // 3600をかけて秒に直す
}
```

#### 2次メッシュコード
> 第2次メッシュ（二次メッシュ、正式名称は第2次地域区画）は第1次メッシュを緯線方向及び経線方向に8等分してできる区域で、2万5千分の1地形図の1図葉の区画に対応する。緯度差は5分、経度差は7分30秒で、1辺の長さは約10kmである。
2次メッシュコード
2桁の数字で、上1桁が緯度方向、下1桁が経度方向を表す。これに1次メッシュコードを合せて5339-23のように表す。

つまり...
経度は7.5をかける
緯度は5をかける

```javascript
function second(mesh_code) {
  var lat = mesh_code.slice(4, 5);
  var lon = mesh_code.slice(5, 6);
  return [lon * 7.5 * 60, lat * 5 * 60] // 60をかけて秒に直す
}
```

#### 3次メッシュコード
>第3次メッシュ（三次メッシュ、正式名称は基準地域メッシュないし第3次地域区画）は第2次メッシュを緯線方向及び経線方向に10等分してできる区域である。緯度差は30秒、経度差は45秒で、1辺の長さは約1kmである。
3次メッシュコード
2次メッシュコードと同様に2桁の数字で、上1桁が緯度方向、下1桁が経度方向を表す。これに1次・2次メッシュコードを合せて5339-23-43のように表す。

つまり…
経度は45をかける
緯度は30をかける

```javascript
function third(mesh_code) {
  var lat = mesh_code.slice(6, 7);
  var lon = mesh_code.slice(7, 8);
  return [lon * 45, lat * 30]
}
```

#### 2分の1地域メッシュ（4次と呼ばれていることもある）
>2分の1地域メッシュ
基準地域メッシュより細かな地域区分として2分の1地域メッシュがある。2分の1地域メッシュは基準地域メッシュを縦横に2等分したものである。緯度差は15秒、経度差は22.5秒で、1辺の長さは約500mである。南西側のメッシュを1、南東を2、北西を3、北東を4として、5339-23-43-1のように表す。

ここから計算方法が変わります。3次メッシュで割り出したメッシュを4分割していきそれぞれ`南西、南東、北西、北東`の順に`1,2,3,4`と割り振っていきます。なのでメッシュコードはここから1~4の数値しか現れません。その数値に合わせて経度・緯度を足していきます。

```javascript
function forth(mesh_code) {
  let forth = mesh_code.slice(8, 9);
  let lat;
  let lon;
  if (is_south(forth)) {
    lat = 0
  } else {
    lat = 15
  }

  if (is_west(forth)) {
    lon = 0;
  } else {
    lon = 22.5;
  }

  return [lon, lat];
}
```

2分の1では緯度が15秒、経度は22.5秒の決まりでそこから4分の１、８分の１まではそれぞれ値を半分にすればよいです。
4分の１、８分の１は上記コードの通りで数値を変えるだけなので特に解説は入れません。

緯度経度が割り出せたら最後はメッシュコード分の秒数を足します。今回は8分の１に対応した秒数を足しています。

```javascript
var upper_lat = lat + 3.75/3600;
var right_log = lon + 5.625/3600;
```

あとはgeojsonに割り出した緯度経度を渡してあげて描画させてあげると画像のようなものが現れます。
このあたりはMapboxのドキュメントにあるとおりです。
メッシュコードについて知識がなかったのでまとめてみました。
間違っている部分ありましたらご指摘お願いします。