はじめに
今回は、deck.gl がサポートしている OGC の I3S を使用した例を紹介したいと思います。
以前に紹介した記事「ArcGIS API for JavaScript で deck.gl を利用してみる」の中で、deck.gl が提供している Tile3DLayer に OGC の I3S がサポートされたことに触れました。今回は、I3S の紹介と deck.gl がサポートしている I3S についてサンプルアプリとともに紹介したいと思います。
作成したサンプルアプリでは東京駅周辺の建物を表示しました。
使用したデータは、ESRI ジャパンが配信している以下のデータを使用しました。
https://www.arcgis.com/home/item.html?id=88d4fe21ea5f431d995eb8f45dd2e93cwww.arcgis.com
使用したサンプルアプリは以下の GitHub にも公開しています。 github.com
ソースは、Git でクローンして
npm install npm start
で使用することができます。
また、
npm run build
でビルドすることもできます。
i3S とは
オープンスタンダートの Open Geospatial Consortium(OGC) にも準拠しており、3D GIS データを扱うための各種フォーマットをシーン サービスと呼ばれる I3S 形式で提供しています。
3D GIS で扱うデータは、2D で扱うデータとは違い、特殊なデータ形式が多く、Web などの各ブラウザやモバイルなどで配信する場合に最適化する必要があります。この I3S 形式を使用することで、データが最適化され、高パフォーマンスで配信することができます。
Esri が提供している I3S のデータ形式は、目的に応じてさまざまな形式で提供しています。
- 3D オブジェクト (3D objects)(例:建物の外観など、GISデータや様々なフォーマットの 3D モデルから作成)
- 統合メッシュ (Integrated mesh)(例:衛星画像、航空画像、ドローンで撮影した画像などを使用し、写真測量ソフトウェアなどを用いて統合メッシュを作成します。統合メッシュは、建物の壁面、樹木、渓谷、崖など、建造物と自然の 3D フィーチャを現実的なテクスチャで表現し、標高の情報を挿入することができます。
- ポイント (Point)(例:病院、学校、樹木、街路樹、標識)
- 点群 (Point cloud)(例:LiDARによる大規模なポイントデータ)
- ビルディング シーンレイヤー (Building scene layer)(例:建物コンポーネントを含む総合的な建物モデル)
また、indexed 3D scene layer (I3S) の仕様と、シーン サービスの REST エンドポイントとして I3S リソースにアクセスするための仕様について、オープンフォーマットとして説明しています。
deck.gl の tile-3d-layer を使用
deck.gl で I3S が使用できるレイヤークラスは、Tile3DLayer で、その中で、実際にデータを呼び出している部分のライブラリとして、i3s-loader を使用しています。
i3s-loader の API リファレンスを見ると「The I3SLoader is experimental. Currently only support I3S MeshPyramids data format.」とあり、残念ながらすべての I3S の形式をサポートしているわけではなく、I3S MeshPyramids data format のみをサポートしているとのことです。今のバージョンが v2.1 なので、今後のバージョンアップでサポートされるフォーマットが増えることを期待したいです。
ちなみに、MeshPyramids は、I3S のプロファイルで、サポートしているデータタイプとして、3D オブジェクト (3D objects) と 統合メッシュ (Integrated mesh) になります。今回使用したデータは、3D オブジェクト (3D objects) になります。
以下の表に、I3S Profile、I3Sコミュニティ仕様、OGC コミュニティ標準のそれぞれの関係図を示しています。
I3S Profile | Supported Layer Types | I3S community specification | OGC I3S community standard |
---|---|---|---|
MeshPyramids | 3D Object and Integrated Mesh | 1.6 | 1.0 |
Points | Point | 1.6 | 1.0 |
PointClouds | Point Cloud | 2.0 | 1.1 (under adoption process) |
詳細は、An OGC Community Standard も参照していただければと思います。
サンプルアプリの作成
サンプルアプリは、i3s-loader にも記載例をそのまま参考にしています。今回は、React を使用しました。
Tile3DLayer クラスを使用し、プロパティの data には、シーンサービスの REST のエンドポイントを指定し、loader には、i3s-loader を指定します。Callbacks 関数として、onTilesetLoadを指定します。こちらは、タイルがロードされた時に呼び出される関数です。
import React, {Component} from 'react'; import {render} from 'react-dom'; import {StaticMap} from 'react-map-gl'; import DeckGL from '@deck.gl/react'; import {MapController} from '@deck.gl/core'; import {Tile3DLayer} from '@deck.gl/geo-layers'; import {I3SLoader} from '@loaders.gl/i3s'; // How to get mapbox token https://docs.mapbox.com/help/how-mapbox-works/access-tokens/ const MAPBOX_TOKEN = 'pk.eyJ1IjoidmFsdWVjcmVhdGlvbiIsImEiOiJjanM0Z21xamQwNHRrM3lueXZrOHBxZmNmIn0.oF6cKsx1z4NzUNiJ7RTXNQ'; // add your Mapbox token here const INITIAL_VIEW_STATE = { longitude: -120, latitude: 34, height: 600, width: 800, pitch: 45, maxPitch: 85, bearing: 0, minZoom: 2, maxZoom: 30, zoom: 14.5 }; export default class App extends Component { constructor(props) { super(props); this.state = {viewState: INITIAL_VIEW_STATE}; } _onTilesetLoad(tileset) { // update viewport to the tileset center const {zoom, cartographicCenter} = tileset; const [longitude, latitude] = cartographicCenter; const viewState = { ...this.state.viewState, zoom: zoom + 2.5, longitude, latitude }; this.setState({viewState}); } render() { const {viewState} = this.state; // construct Tile3DLayer to render I3S tileset const layer = new Tile3DLayer({ id: 'tile-3d-layer', // Tileset entry point: Indexed 3D layer file url data: 'https://services.arcgis.com/wlVTGRSYTzAbjjiC/ArcGIS/rest/services/Tokyo_Building_MP/SceneServer/layers/0?f=pjson', loader: I3SLoader, onTilesetLoad: this._onTilesetLoad.bind(this) }); return ( <DeckGL layers={[layer]} viewState={viewState} controller={{type: MapController}} onViewStateChange={({viewState}) => { // update viewState when interacting with map this.setState({viewState}); }} > <StaticMap mapStyle={'mapbox://styles/mapbox/streets-v11'} mapboxApiAccessToken={MAPBOX_TOKEN} preventStyleDiffing /> </DeckGL> ); } } export function renderToDOM(container) { render(<App />, container); }
さいごに
今回は、前回紹介した「ArcGIS API for JavaScript で deck.gl を利用してみる」に続いて、deck.gl で Esri のサービスとして OGC にも準拠している I3S を使用した例について紹介しました。deck.gl で使用できる I3S のデータは幾つか公開されており、今回使用したデータ以外で確認したところ、うまく表示されないデータもあったりと、まだまだ不安定な状況みたいです。今後のバージョンアップに期待したいです。