Post on 21-Jan-2017
株式会社ノーザンシステムサービス中洞 友希
Cesium マニアックス
FOSS4G 2016 Hokkaido
自己紹介
氏名:中洞 友希会社: ( 株 ) ノーザンシステムサービス 入社 4 年目
地図やドローンを使ったりした可視化の研究開発をしています。
色々面白いものを置いてあるので、興味がある方は是非当社までお越しください!
はじめに
FOSS4G 2015 Hokkaido での発表後、 Cesium を使った案件のお仕事を頂く機会が増えました。
そこで本日は恩返しとして得た知見をアウトプットし、 Cesium の良さを知って頂こうと思います!
サーバーサイドではなくCesium のみで小地域の
地物を大量に表示したい!
こんな要望がありました。
※ 小地域・・・政府が国勢調査で調査する地物の最小単位
OpenLayers 等の 2D の地図ライブラリで大量の地物を表示しようとしたところ重すぎて OS ごと落ちてしまった
Cesium は上記のライブラリと異なりWebGL を使用しているため、簡単に実現できると思っていた。
( ・∀・ ) 楽勝だべノ
しかし!
Entity という地物を表示する API で読み込もうとしようとしたところ・・・
ここから Cesium との戦いが始まります。
表示できない
作戦1Primitive で表示してみる
Primitive は Cesiumで地物を表示する API 。Entity よりも軽量に動作するそうだが・・
重すぎて落ちる
作戦2D3.js で SVG 地図を作成して張り付けてみる
D3.js で SVG の地図を作成し、 Cesium のイメージレイヤーで地図上に描画する
解像度が悪く、ズームすると見た目が悪い
作戦3小地域の画像を 1 つ 1 つ作成して張り付ける
Mapnik で小地域の画像を 1 つ 1 つ作成し、地図上に張り付ける
重すぎて落ちる
500m 間隔でポイントをグリッド状に作成し地図上に表示
グリッドポイントの計算が遅すぎる
作戦4グリッドポイントで地物を表現する
しかし今回はクライアント側で完結する処理を追求したい。
色々探してみると・・
なんと希望の光が!!
サーバーを使わないでって言ったけどあらかじめ Mapnik でタイルを作成しておいて、それを表示するのが一番手っ取り早いのかも・・・
皆さんお馴染み藤村さんの Qiita で発見!
とりあえず実施せずにキープして
おくべき調査・開発作業
(http://qiita.com/handygeospatial/items/8f18d309a96ae7faf8c0)
geojson-vt
geojson-vt は Web ブラウザで GeoJSONを読み込み、タイルにしてくれるライブラリ。
Web Worker とChrome 64bitを使用し、geojson-vt でGeoJSON を読み込み canvas でタイルを表示する
表示出来た!!!
Web Worker とは並列処理が出来る HTML5 の機能。JavaScript の重い処理を並行して実行することでレスポンスが改善できる。
Chrome 64bit を使った理由64bit 版は Chrome のメモリのリミッターが解除され、制限無くメモリを使うことができる。そのため重い処理をしてもフリーズしたり落ちることは無くなった。
無事にタイルで表示出来たけど地物のクリックが出来ない。
Entity で表示できない原因として地物の頂点数の多さが問題なのか?
地物を簡素化して頂点数を減らせば表示できるかも?
地物の簡素化には PostGIS のトポロジを使用する。
トポロジ処理した地物を再び Entityで表示してみる
トポロジについては yellow_73 さんの記事が大変参考になります。(http://d.hatena.ne.jp/yellow_73/20120323)
表示出来た!!
【メリット】・ Web ブラウザ上でお手軽にタイルを作成できる
【デメリット】・選択&アニメーションができない
【メリット】・選択&アニメーションができる
【デメリット】・大量のデータを表示する時はトポロジ化が必須でちょっと手間がかかる
サーバーを使わず Cesium で大量の地物を表示するのに適した方法は2つ!
geojson-vt Entity
Cesium 上で北海道の小地域を表示する
デモ
geojson-vt verhttps://www.youtube.com/watch?v=7CyfJDY1lEY&feature=youtu.be
Entity verhttps://www.youtube.com/watch?v=BSVwcL3PRv8&feature=youtu.be
Cesium の地形データが重い。もっと軽くならないか?
一件落着。・・・と思いきや、再びこんな要望がありました。
Cesium は以下の2つの地形データのフォーマットをサポートしている。
・ quantized-mesh・ heightmap・
今まで heightmap を使用して地形を表示していたが、 quantized-mesh の方が高速で綺麗に表示できることが判明!
← heightmap(http://www.sunshineproject.eu/documents/publications/7.%20Heterogeneous-Resolution-and-Multi-Source-Terrain-Builder%20ICVAIV%202016.pdf)
quantized-mesh を作成できるライブラリを探してみるも、なかなか見つからない。あったとしても有償。
3d-forge というライブラリが見つかったが、S3 を使用する前提で作成されており環境が限定されてしまうため断念。
https://github.com/geoadmin/3d-forge
さらに探してみると、 3d-forge から派生したライブラリ quantized-mesh-tile を発見!早速試してみる。
http://quantized-mesh-tile.readthedocs.io/en/latest/index.html
今回は国土地理院の標高タイルを使用する。(http://maps.gsi.go.jp/development/demtile.html)
標高タイルから緯度経度高度を算出してquantized-mesh-tile で地形データのterrain ファイル作成する。
quantized-mesh-tile
標高タイル地形データ(.terrain)
terrain ファイルは正常にできたが、このままでは重くてもっさりする。
Cesium で公開している地形データは、 quantized-mesh を簡素化することで高速化を図っているっぽい。
簡素化前 簡素化後重 軽http://blog.thematicmapping.org/2014/10/3d-terrains-with-cesium.html
Cesium の quantized-mesh の簡素化はマイケル・ガーランドさんの論文を参考にしているようだ。
論文:https://cesiumjs.org/presentations/Rendering%20the%20Whole%20Wide%20World%20on%20the%20World%20Wide%20Web.pdf
マイケルさんは QSlim という簡素化のライブラリを公開しているので早速試してみる。
http://mgarland.org/software/qslim21.html
QSlim を使用して簡素化ができた!
Before
After
terrain をobj(smf)に変換
obj(smf) をterrain に変
換
全体の処理の流れ
quantized-mesh-tile
QSlimで簡素化
標高タイル
簡素化した quantized-mesh タイルの作
成は出来たが、 Cesium で表示する部分
はまだ奮闘中。
もし Cesium で表示することが出来たら、
国土地理院の地理院地図 Globe の高速化
や、ドローンや LiDAR で取得した 3Dデータも簡単に表示できるようになると
思う。
追記:Cesium Terrain Generator And Serverというライブラリを発見。 quantized-mesh の作成および簡素化をしてくれるかも…?
ソースはまだ公開されていないため、後で試してみようと思う。
https://github.com/Nymria/Cesium-Terrain-Generator-And-Server
観測データを時系列で3次元表示したい!
次に・・・
という要望も出てまいりました。
今回は震源のデータ (緯度・経度・深度 ) を時系列アニメーションで表示してみる。
震源のデータは IRIS の API から取得する。(http://www.iris.edu/hq/)
Cesium は時系列で地物の表示 / 非表示を制御する API「 Timeline 」が用意されている。
この Timeline を使用するには地物をEntity で表示する必要がある。
しかしこの Entity は数万ポイントしか表示できない。
表示するデータはもっと多い。さあどうしよう??
cesium-dev にて
『 Entity の代わりにPoint Primitive Collection を使えばパフォーマンスが向上するよ!』
https://groups.google.com/forum/#!searchin/cesiumdev/Memory$20leak$20advice/cesium-dev/HxDAJ96Ajnc/QSrY_zdmDgAJ
Point Primitive Collection を使用してみたところ、 80万ポイントを表示出来た!
しかし、この Point Primitive Collection は時系列アニメーションに対応していない。
そのため時系列アニメーションは自前で実装した。
それぞれのメリット・デメリット
【メリット】・お手軽に時系列アニメーションができる。・ポイントのスタイルを自由にいじれる。
【デメリット】・数万ポイントしか表示できない。
Point Primitive Collection
【メリット】・大量のポイントを表示できる。
【デメリット】・時系列アニメーションに対応していない。・ポイントのスタイルをあまりいじれない。
Entity
Cesium で 3次元震源データの時系列アニメーション
デモEntity
2011 年~https://www.youtube.com/watch?v=EUKj5oG3mEk&feature=youtu.be熊本地震https://www.youtube.com/watch?v=vdJ_aLzykoc&feature=youtu.be
Point Primitive Collection2000 年~https://www.youtube.com/watch?v=0fJ2GEk9wCQ&feature=youtu.be2000 年~ (時系列アニメーション )https://www.youtube.com/watch?v=fcdMRxyzyWY&feature=youtu.be
Cesium で物理演算をしてみた噴火や洪水で河川が決壊した際にどのように流出するのか?
リアルタイム物理演算がそもそも Cesium で可能なのか、またオブジェクト数はどの程度行けるのかを検証してみました。
・ Google summer of code のアイディアで oimo.js とか使った物理演算とか実装出来るとクール! とか書いてあったので、現時点では物理演算機能は実装されていないようだ。・ oimo.js ってそもそもなんだ?お芋?・元々は OimoPhysics という actionscript3 で実装された物理演算ライブラリを javascript に移植した軽量物理演算らしい。・とりあえず、物理演算だけを実装するには向いてそうなので採択。・ではこれをどうやって Cesium に組み込むか?・まず座標系を合わせなければいけない。・ Cesium では cartesian(カーテシアンと読みます。デカルト座標系=直交座標系)という地球楕円体の中心を原点とした座標系を採用している。・ oimo.js 等、物理演算系は大抵直交座標なので、 cartesian で渡してやればいけそう。
物理演算エンジンは何を使うか?
地面はどうする?・ oimo.js の地面はどうする?ここはお約束の地理院標高タイル。・標高タイルは 256*256 の行列なので、左上の原点を下に緯度経度標高を算出してからカーテシアン座標に変換する必要がある。
・ oimo.js では平面ポリゴンが存在しないため、球体オブジェクトを敷き詰めて地面の代わりとした。
レンダリングは three.js で・本来的には Cesium の primitive を動かしてやるのが早そうだけど、試したら遅かった。・ Cesium のレンダリングではなく、 oimo.js と相性が良いthree.js ではどうか?・幸い potree と言うポイントクラウド表示ライブラリで cesiumと three.js と potree を組み合わせたサンプルがあったので、こちらを拡張して作ってみた。・ three.js は基本的にレンダリング自体は Cesium より早いので大規模な点群やパーティクルなどを表示する場合は併用してもよいかもしれない。ちなみに potree は予め octree 化( Cesium で言うところの 3DTiles のようなもの)しておかないと使えないため、リアルタイム点群は表示できないようだ。この辺は調査中。
物理演算はやっぱWorker でしょ・ oimo.js とかの物理演算等の CPU バウンド処理は worker で別スレッドで実行させたい! Cesium でもオブジェクト作成時などにworker で処理しているようだ。・ホントは OpenCL など、 GPU を使った並列演算をしてみたかったが実装できるブラウザが現在ないため、今回は見送る。・シェーダー言語である GLSL を使えば簡単な演算であれば出来るらしいがマニアックになりすぎるので、今回は見送る。・ oimo.js は worker 版が用意されていたのでそちらで実装してみた。・ Step毎に worker 版 oimo で計算された位置及び回転情報をメインスレッドで受け取り、 three.js のオブジェクトに適用し、カメラ位置を Cesium と同期することで、あたかも Cesium で物理演算しているように表示することが出来た。・さしあたり 2万オブジェクトくらいまでは問題なく表示できている。・メモリはバカ食いするので、 64bit 版のブラウザが必要かも。
物理演算
デモ
Cesium with Three.js and oimo.jshttps://www.youtube.com/watch?v=-4-YWP0S45I
全体のまとめ
Cesium は 3次元や 4次元のデータを可視化するのに非常に適したプラットフォーム。
また、複数のライブラリを組み合わせることで幅広い表現手法が可能であることが分かった。
Cesium は開発が盛んで新しい機能がどんどん出てきているので今後の動向にも注目している。
Cesium バンザイ
\ (*^○^*) /
ちょっと宣伝YouTube で Cesium のデモ動画を多数公開しています。その動画を見た Cesium の開発者からお声をかけて頂き、 Cesium のショーケースにも掲載されました。
よかったらチェックしてみてくださいね☆
Cesium ショーケースhttps://cesiumjs.org/demos/LSDSLAM.htmlhttps://cesiumjs.org/demos/GridViz.htmlYouTubehttps://www.youtube.com/channel/UCClOP6BjCmgx4HUqFaW6QNA
ご清聴ありがとうございました。