Hirosaji Tech Blog 🍙

Web開発の記事が多め。絵師支援の記事も少し。

MapboxとTurf.jsでポイントデータの3D地図を作る

ポイントデータの3D地図表現が、Mapboxにあるようで無かったので作りました。

どんな時に使うの

棒グラフ地理情報を付けたい時に使えます。

例えば、「全国の展望台付きタワーの高さ」を比較する場合。

全国の主要な展望台付きタワーの高さ(棒グラフ)


↓ 比較する各地を、地図上に載せる時に使えます。

全国の主要な展望台付きタワーの高さ(地図)

実装例

今回はシンプルに、1層の棒グラフを地図に載せる方法を紹介します。

シンプル表現

デモとソースコード

デモとソースコードは、こちらのリンク先に掲載しています。

bl.ocks.org

要点の解説

今回の要点は、ポイントデータから3Dポリゴンデータを作る点です。
Mapboxにはポイントを直接3Dで表現するメソッドは無いのですが、3Dポリゴンを描画するメソッド自体はあります。
そこで、3Dポリゴンデータを作って描画しよう、という考えです。

なお、MapboxはGeoJSON形式であれば大概のデータをビジュアライズできるので、今回はGeoJSONで用意しました。

上記リンクに載せたソースコード内で該当するのは、次の部分です。

const qfs = mapObj.queryRenderedFeatures({
  layers: ['tower_points']
});
const data = {
  "type": "FeatureCollection",
  "features": []
};
const radiusPX = 3;

qfs.forEach(function (object) {

  const center = object.geometry.coordinates;

  let xy = mapObj.project(center);
  xy.x += radiusPX;

  let LL = mapObj.unproject(xy);
  LL = turf.point([LL.lng, LL.lat]);

  const radius = turf.distance(center, LL, {
    units: 'meters'
  }) + 0.00000001;

  object.properties.height = object.properties.full_value * 600;
  object.properties.base = 0;

  const options = {
    steps: 16,
    units: 'meters',
    properties: object.properties
  };

  data.features.push(turf.circle(center, radius, options));
})

ざっくり言うと、ポイントデータで作った circle レイヤーの円から円柱ポリゴンデータを作り、その円柱ポリゴンデータをGeoJSON形式にまとめる、という手順のコードです。
半径の計算や円柱の生成は、Turf.jsが担っています。

ここ以外のコードについては、大体 Mapboxの公式ドキュメント に載っているので、適宜調べてみてください。
もちろん、この記事への質問やコメントも歓迎です。

応用例

積み上げ表現

記事の初めにも載せた、積み上げ棒グラフ的な表現です。

積み上げ表現
Mapbox - Extruding circles (stacked) - bl.ocks.org

作りは単純で、色別にレイヤー分けした円柱を積み重ねて表示させています。

塗り分け表現

高さに合わせて、色を塗り分けた表現です。

塗り分け表現
Mapbox - Extruding circles (choropleth) - bl.ocks.org

d3.jsのカラースケールを使えば、簡単に高さに合わせた色を計算することができるのでオススメです。

グラデーション表現

円柱の縦方向にグラデーションをかける表現です。

グラデーション表現
Mapbox - Extruding circles (gradient) - bl.ocks.org

ただし、想定したグラデーション表現がMapboxの仕様になかった(参考)ため、これは円柱を多層に重ねた擬似グラデーション表現です。多層にしすぎると重くなるので注意です。

参考リンク