LoginSignup
9
1

MapLibre GL JSにdeck.glレイヤーを組み込む方法

Last updated at Posted at 2023-12-20

はじめに

この記事は MapLibre Advent Calendar 2023 20日目の記事です。

MapLibre GL JSは2.5次元のインタラクティブな地図を描画するライブラリですが、一方で、3Dのデータ表現が弱いというところがあります。そこで、便利な方法として、3Dのデータ表現に長けているdeck.glのレイヤーをMapLibre GL JSに組み込む方法を紹介したいと思います。具体には、3D都市モデルPLATEAU 3D Tiles3次元点群データをdeck.glのTile3DLayerを用いて、MapLibre GL JSにレイヤーとして組み込む方法について紹介します。

MapLibre GL JSにdeck.glレイヤーを組み込む方法

MapLibre GL JSにdeck.glレイヤーを組み込む方法には主に3つの方法があるようです。詳細については、下記の記事に詳しく書かれています。

1. MapboxOverlayを使ったオーバーレイ
2. MapboxOverlayを使ったインターリーブ
3. MapboxLayerを使ったインターリーブ

上記の記事の中で紹介されている、3つの方法におけるオーバーレイ、インターリーブの違いはこちらのページの図がわかりやすいです。

オーバーレイは、2つのライブラリが相互に独立してレンダリングする仕様のようで、2Dマップに適しているようです。一方で、インターリーブは、deck.glのレイヤーとMapLibre GL JSのレイヤーのオクルージョン(手前にある物体が後ろにある物体を隠す状態)が可能になるようで、3Dマップに適しているようです。

今回は、上記の記事で紹介されている方法のうち、deck.glのMapboxLayerを使ったインターリーブを使用して、MapLibre GL JSで3D都市モデルPLATEAU 3D Tilesや3次元点群データを表示します。

なお、3つの方法については、下記の記事でもGoogle Photorealistic 3D Tilesを用いて、MapLibre GL JSにdeck.glレイヤーを組み込む方法を試しているのであわせてご覧ください。

3D都市モデルPLATEAU 3D TilesをMapLibre GL JSで表示する

3D都市モデルPLATEAU 3D Tilesをdeck.glのTile3DLayerを用いて、MapLibre GL JSにレイヤーとして組み込みます。

デモサイト

image.png

東京駅周辺

ソースコードと解説

  • 全体のソースコードは、下記のGitHubから入手してください。

html
<html>

<head>
  <title>3D都市モデルPLATEAU(3D Tiles)</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.js"></script>
  <link href="https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.css" rel="stylesheet">
  <script src="https://unpkg.com/pmtiles@2.10.0/dist/index.js"></script>
  <script src="https://unpkg.com/deck.gl@8.9.0/dist.min.js"></script>
  <script src="https://unpkg.com/@loaders.gl/3d-tiles@^2.3.0/dist/dist.min.js"></script>
  • MapboxLayerで3D都市モデルPLATEAU 3D Tilesを定義します。
  • loaderTiles3DLoaderを指定します。
  • dataに3D都市モデルPLATEAU 3D TilesのURL(tileset.jsonのURL)を指定します。
  • 3D Tilesの配信URLは下記より確認できます。

今回、3D都市モデルPLATEAU 3D Tilesは2021年度末時点で公開されている3D Tilesデータを使用しています。今回の方法で最新の3D Tilesデータ(2022年度末時点)を使用すると3Dモデルが表示されませんでした。ちなみに、QGIS3.34で3D Tilesを読み込めるようになりましたが、最新の3D Tilesデータは表示できませんでした。現時点の最新の3D Tilesデータは下記になります。
https://github.com/Project-PLATEAU/plateau-streaming-tutorial/blob/main/3d-tiles/plateau-3dtiles-streaming.md

  • onTileLoad以下は、3Dモデルの高さをマップ平面に合うようにするための調整です。
  • 詳細については、下記の記事が詳しいです。

  • 最終的に、content.cartographicOrigin.zで建築物の基礎の標高に加えて東京駅付近のジオイド高 36.6641m を引いて、3Dモデルの高さをマップ平面に合うように調整しています。
  • map.addLayer(tile3dLayer)で3D都市モデルPLATEAU 3D Tilesレイヤを追加します。
javascript
    map.on('load', () => {
      // MapboxLayerを使ったインターリーブ
      const tile3dLayer = new deck.MapboxLayer({
        id: '13101_chiyoda-ku',
        type: deck.Tile3DLayer,
        // 3D都市モデルPLATEAU 3DTilesソース
        data: 'https://plateau.geospatial.jp/main/data/3d-tiles/bldg/13100_tokyo/13101_chiyoda-ku/low_resolution/tileset.json', // 千代田区
        loader: Tiles3DLoader,
        opacity: 1,
        // 【参考】https://nagix.hatenablog.com/entry/2022/12/27/203825
        onTileLoad: d => {
          const { content } = d;
          const buffer = content.batchTableBinary.buffer;
          const key = content.batchTableJson;
          const len = key._gml_id.length;
          const zMinView = new DataView(buffer, key._zmin.byteOffset, len * 8);
          const zMins = [];

          for (let i = 0; i < len; i++) {
            zMins.push(zMinView.getFloat64(i * 8, true));
          }
          zMins.sort((a, b) => a - b);
          content.cartographicOrigin.z -= 36.6641 + zMins[Math.floor(len / 2)];
        }
      });

      // 3D都市モデルPLATEAU 3DTilesレイヤ
      map.addLayer(tile3dLayer);

    })

3次元点群データ(3D Tiles)をMapLibre GL JSで表示する

3次元点群データをdeck.glのTile3DLayerを用いて、MapLibre GL JSにレイヤーとして組み込みます。

長崎県がオープンデータとして公開している3次元点群データ(LAS形式)から3D Tilesを生成して、MapLibre GL JS+deck.glで表示しています。3次元点群データから3D Tilesを生成する方法については、Zennで記事を書いていますので、あわせてご覧ください。

デモサイト

image.png

長崎駅周辺

ソースコードと解説

  • 全体のソースコードは、下記のGitHubから入手してください。

html
<html>

<head>
  <title>長崎県 3次元点群データ(3DTiles)</title>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src='https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.js'></script>
  <link href='https://unpkg.com/maplibre-gl@3.6.2/dist/maplibre-gl.css' rel='stylesheet' />
  <script src="https://unpkg.com/pmtiles@2.10.0/dist/index.js"></script>
  <script src="https://unpkg.com/deck.gl@8.9.0/dist.min.js"></script>
  <script src="https://unpkg.com/@loaders.gl/3d-tiles@^2.3.0/dist/dist.min.js"></script>
  • MapboxLayerで3次元点群データ(3D Tiles)を定義します。
  • dataに3次元点群データ(3D Tiles)のURL(tileset.jsonのURL)を指定します。
  • loaderTiles3DLoaderを指定します。
  • map.addLayer(tile3dLayer)でレイヤを追加します。
javascript
    map.on('load', () => {
      // MapboxLayerを使ったインターリーブ
      const tile3dLayer = new deck.MapboxLayer({
        id: "nagasaki-station",
        type: deck.Tile3DLayer,
        pointSize: 2,
        // 3次元点群データ(3DTiles)ソース
        data: 'https://xs489works.xsrv.jp/3dtiles/open_nagasaki/nagasaki_station/tileset.json',
        loader: Tiles3DLoader
      });

      // 3次元点群データ(3DTiles)レイヤ
      map.addLayer(tile3dLayer);

    })

参考文献

おわりに

MapLibre GL JSにdeck.glのレイヤーを組み込む方法についてご紹介しました。deck.glのTile3DLayerをMapLibre GL JSにレイヤとして組み込むことで、MapLibre GL JSで3D都市モデルPLATEAU 3D Tilesや3次元点群データ(3D Tiles)を表示することができます。deck.glには、Tile3DLayer以外にも可視化のための様々なレイヤーが用意されています。例えば、地点間の繋がりを3Dの弧で表現できるArcLayerやデータをヘキサゴン(六角形)で集約してヒートマップとして表現できるHexagonLayerなど表現力の高いレイヤーを利用することもできます。

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1