6
3

3D都市モデルPLATEAU 3DTiles+GeoJSONで3D主題図を作る

Last updated at Posted at 2023-12-12

はじめに

この記事は 3D都市モデル Project PLATEAU Advent Calendar 2023 2日目の記事です。

3D都市モデル PLATEAU LT 05@_shimizuさんが発表されていた、deck.glのTerrainExtensionを用いた事例を参考にさせていただきながら、3D都市モデルPLATEAU 3DTiles+GeoJSONで3D主題図を作成してみました。具体には、3D都市モデルPLATEAU 3DTiles国土数値情報の用途地域データ(2019年)を組み合わせて、用途地域名で色分けした3D主題図を作成してみました。

アウトプットイメージ

deck.glとは

  • オープンソースの地図ライブラリーです。
  • WebGLによる可視化フレームワークで、大規模なデータセットをサポートしており、2Dおよび3Dデータの可視化を行えます。
  • もともとはUber社が開発していましたが、現在はUrban Computing Foundationに移管されています。
  • 可視化のための様々なレイヤーが用意されています。

Tile3DLayer

  • 3Dタイルデータ(3DTilesなど)を読み込み、地図上に表示するレイヤです。
  • 3D都市モデルPLATEAU 3DTilesを表示するために使用します。

GeoJsonLayer

  • GeoJSONデータを読み込み、地図上に表示するレイヤです。
  • 国土数値情報の用途地域データを表示するために使用します。

2D主題図と3D主題図の比較

  • 通常、3D都市モデルPLATEAU 3DTilesと国土数値情報の用途地域データ(2019年)の2つのレイヤをdeck.glで重ねて表示すると下図のようになり、用途地域の2Dデータの一部が建物の3Dモデルに隠れてしまいます。

2D主題図
image.png

  • 一方で、deck.glのTerrainExtensionを用いると、用途地域の2Dのデータが建物の3Dモデルのサーフェイスに沿ってレンダリングされ、3Dモデルのサーフェイスに2Dのデータがオーバレイされます。

3D主題図
image.png

ただし、TerrainExtensionは、現時点では実験的な位置付けの機能です。また、負荷が高く、巨大なGeoJSONをオーバレイすると固まります。

デモサイト

ソースコードと解説

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

Tile3DLayer

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

  • operation: 'terrain+draw'とすることで、deck.glのTerrainExtensionが機能します。
javascript
                // PLATEAU-3DTiles
                new deck.Tile3DLayer({
                    id: "tile3dlayer",
                    data: 'https://plateau.geospatial.jp/main/data/3d-tiles/bldg/13100_tokyo/13104_shinjuku-ku/low_resolution/tileset.json', // 新宿区
                    loader: Tiles3DLoader,
                    opacity: 1,
                    pickable: false,
                    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.9702 + zMins[Math.floor(len / 2)];
                    },
                    operation: 'terrain+draw'
                }),

GeoJsonLayer

  • getFillColor 国土数値情報の用途地域データの属性「用途地域コード(A29_004)」をもとに、色分けを行っています。
  • 用途地域コード(A29_004)のコード表は下記を参照してください。

  • extensions: [new deck._TerrainExtension()]とすることで、deck.glのTerrainExtensionが機能します。
javascript
                // 用途地域(TerrainExtension)
                new deck.GeoJsonLayer({
                    id: 'youtochiiki-1',
                    data: data,
                    stroked: false,
                    filled: true,
                    getFillColor: ({ properties }) => {
                        const { A29_004 } = properties;
                        if (A29_004 == 1)
                            return [0, 178, 133]
                        else if (A29_004 == 2)
                            return [145, 207, 185]
                        else if (A29_004 == 3)
                            return [120, 206, 63]
                        else if (A29_004 == 4)
                            return [173, 223, 33]
                        else if (A29_004 == 5)
                            return [235, 238, 94]
                        else if (A29_004 == 6)
                            return [255, 210, 182]
                        else if (A29_004 == 7)
                            return [255, 166, 56]
                        else if (A29_004 == 8)
                            return [255, 176, 195]
                        else if (A29_004 == 9)
                            return [255, 89, 61]
                        else if (A29_004 == 10)
                            return [167, 148, 197]
                        else if (A29_004 == 11)
                            return [185, 234, 255]
                        else if (A29_004 == 12)
                            return [95, 197, 251]
                        else if (A29_004 == 21)
                            return [196, 215, 155]
                    },
                    opacity: 0.5,
                    extensions: [new deck._TerrainExtension()]
                }),

おわりに

deck.glのTerrainExtensionを用いて、3D都市モデルPLATEAU 3DTiles+GeoJSONで3D主題図を作成してみました。deck.glのTerrainExtensionを使用すると、主題図と3Dモデルを組み合わせて、様々な表現が可能です。例えば、国土数値情報の用途地域データには、用途地域名のほかに容積率などの属性を持っていますので、3D都市モデルPLATEAU 3DTilesと組み合わせて、容積率マップを作ってみるなど、面白そうな試みができそうです。容積率マップは、にゃんこそば(@ShinagawaJP)さんの書籍で紹介されていました。

6
3
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
6
3