Turf.jsの使い方 ～地図の表示から実際に使用するまで～

## はじめに
今回は、Turf.jsで使われる機会が多いと思われる距離計算、面積計算、ポリゴン内の位置を返す機能を実際に試してみることにします。

## Turf.jsとは
空間解析に使用されるオープンソースのJavaScriptライブラリです。空間演算、GeoJSONデータ作成用のヘルパー関数、データ分類・統計ツールなどが含まれています。

https://turfjs.org/

## 準備

### 地図を表示する
Turf.jsを使う前に準備として地図を表示します。
地図はMapLibre GL JSを使ってOpenStreetMapを表示します。
ソースコードは以下となります。

```index.html
<!DOCTYPE html>
<html>
<head>
    <link href="https://unpkg.com/maplibre-gl@4.1.3/dist/maplibre-gl.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/maplibre-gl@4.1.3/dist/maplibre-gl.js"></script>
    <style>
        #map { position: absolute; top: 0; bottom: 0; width: 100%; }
    </style>
</head>
<body>
    <div id="map"></div>
    <script>
      const map = new maplibregl.Map({
        container: 'map', // container id
        style: {
          // MapLibre-Style
          version: 8,
          sources: {
            osm: {
              type: 'raster', 
              tiles: [
                'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
              ],
              tileSize: 256, 
              maxzoom: 18,
              attribution:'&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
            }
          },
          layers: [{
            id: 'osm-layer',
            source: 'osm', 
            type: 'raster', 
          }],
        },
        center: [139.66735, 35.67299], // starting position
        zoom: 13 // starting zoom
      });
    </script>
</body>
</html>
```

地図が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/8aabaf7c-954b-da7a-1ca8-d29b923bc3c8.png)

> 参考情報
> [MapLibre GL JS](https://maplibre.org/maplibre-gl-js/docs/)
> [OpenStreetMap](https://openstreetmap.jp/node/762)

## スクリプトを取り込む
今回は試しに使用するだけなのでTurf.jsのすべての機能を取り込みます。
全て取り込むデメリットとしてはサイズが大きくなることです。
必要な機能だけ取り込むことでサイズを小さくすることができます。

以下のコードを追加します。

```index.html
<script src='https://unpkg.com/@turf/turf@6.5.0/turf.min.js'></script>
```

## Turf.jsの機能を使用する

### 直線距離を計算する
直線距離を計算する場合はdistanceを使用します。
新宿駅から渋谷駅までの直線距離を計算してコンソールに表示するようにします。

以下のコードを追加します。
```js:index.html
map.on("load", (event) => {
  // 新宿駅の座標
  const shinjukuStationPoint = [139.70056, 35.69002];
  // 渋谷駅の座標
  const shibuyaStationPoint = [139.70162, 35.65812];
  // 2点間の距離を計算
  const dist = turf.distance(shinjukuStationPoint, shibuyaStationPoint);
  console.log("2点間の距離は:", dist, "kmです");
});
```
コンソールに約3.5kmと表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/1b6f7d50-bfb6-8dfc-acd8-90eb74fc8324.png)

> 参考情報
> [distance](https://turfjs.org/docs/#distance)

### 面積を計算する
面積を計算する場合はareaを使用します。
単位は平方メートルになります。

先ほど追加した直線距離の計算のコードを削除し、以下のコードを追加します。
ポリゴンは初期表示画面に表示される適当なポリゴンを用意しました。

```js:index.html
map.on("load", () => {
    // ポリゴンデータ
    const polygon = turf.polygon([[
        [139.67236757278442, 35.669927984288854],
        [139.6694188117981, 35.65839192329736],
        [139.67695236206054, 35.65839192329736],
        [139.67236757278442, 35.669927984288854]
    ]]);

    // 面積を計算して表示する
    const area = turf.area(polygon);
    console.log("ポリゴンの面積は:", area, "平方メートルです");

    map.addSource(`polygon`, {
        type: "geojson",
        data: polygon,
    });

    // ポリゴンの背景色を設定します
    map.addLayer({
        id: `polygon`,
        type: "fill",
        source: `polygon`,
        layout: {},
        paint: {
            "fill-color": "#1c1c1c",
            "fill-opacity": 0.5,
        },
    }); 

    // ポリゴンの枠線を設定します
    map.addLayer({
        id: `outline`,
        type: "line",
        source: `polygon`,
        layout: {},
        paint: {
            "line-color": "#1c1c1c",
            "line-width": 2,
        },
    });
});

```
コンソールに約437487平方メートルと表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/b1f6209d-3a65-8215-0623-e5adddf4afd1.png)

> 参考情報
> [area](https://turfjs.org/docs/#area)

### ポリゴン内の位置を返す
ポリゴン内の位置を返す機能は複数存在します。中心を返すcenter、重心を返すcentroid、他にもcenterOfMassやpointOnFeatureがあります。
今回はcentroidを使用して地図にポリゴンの重心を表示するようにします。

先ほど追加した面積計算のコードを削除し、以下のコードを追加します。
```js:index.html
map.on("load", () => {
    // ポリゴンデータ
    const polygon = turf.polygon([[
        [139.67236757278442, 35.669927984288854],
        [139.6694188117981, 35.65839192329736],
        [139.67695236206054, 35.65839192329736],
        [139.67236757278442, 35.669927984288854]
    ]]);

    // 面積を計算して表示する
    const area = turf.area(polygon);
    console.log("ポリゴンの面積は:", area, "平方メートルです");

    map.addSource(`polygon`, {
        type: "geojson",
        data: polygon,
    });

    // ポリゴンの背景色を設定します
    map.addLayer({
        id: `polygon`,
        type: "fill",
        source: `polygon`,
        layout: {},
        paint: {
            "fill-color": "#1c1c1c",
            "fill-opacity": 0.5,
        },
    }); 

    // ポリゴンの枠線を設定します
    map.addLayer({
        id: `outline`,
        type: "line",
        source: `polygon`,
        layout: {},
        paint: {
            "line-color": "#1c1c1c",
            "line-width": 2,
        },
    });
    const centroid = turf.centroid(polygon);
    // 重心を表示
    map.addSource("point", {
      type: "geojson",
      data: centroid
    });
    // 重心を表示するレイヤーを追加
    map.addLayer({
      id: "centroid",
      type: "circle",
      source: "point",
      paint: {
        "circle-radius": 5, // マーカーの半径
        "circle-color": "#FFFF00" // マーカーの色
      }
    });
});


```
予め用意したポリゴンに重心が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2916977/cbfbc0fe-ba22-7f9a-471c-48a4c4405d82.png)

> 参考情報
> [center](https://turfjs.org/docs/#center)
> [centroid](https://turfjs.org/docs/#centroid)
> [centerOfMassr](https://turfjs.org/docs/#centerOfMassr)
> [centerOfMass](https://turfjs.org/docs/#centerOfMass)

## おわりに
Turf.jsの機能を3つ使用してみました。他の機能に関しても実際に使う機会があると思います。様々な機能があるのでご興味のある方は試してみてください。