# FOSS4G Niigata 2019: 国連と始めるベクトルタイル 日時 ~ 2019-09-13T15:00/18:00 (3時間) 講師 ~ 柴本 歩 この資料のために書き下ろした内容は CC0 です。 --- ## 国連と始めるベクトルタイル ### 会場 WiFi SSID ~ (現場合わせ) パスワード ~ (現場合わせ) --- ## 国連と始めるベクトルタイル ![](https://un-vector-tile-toolkit.github.io/signature/logo.png) --- #### 国連ベクトルタイルツールキットとは 1/2 - 既存のオープンソースソフトウェアを組み合わせて、ベクトルデータからベクトルタイルを生産してホストすることと、ベクトルタイルをスタイリングして最適化することを支援するツールキット。 - 国連オープン GIS イニシアティブのプロジェクトで、現在のところ、国連地理空間情報課、国連グローバルサービスセンター、国土地理院、農業環境変動研究センター、OSGeo 日本支部、Mapbox から技術者が参加している。 --- #### 国連ベクトルタイルツールキットとは 2/2 - 目下、ツールキット収録した Docker コンテナイメージ rasv を整備中 - rasv を活用したハンズオンマテリアル ango を開発している。 --- ##### 今回つくるもの: 自然災害伝承碑ベクトルタイルサイト <iframe width="100%" height="500px" src="https://un-vector-tile-toolkit.github.io/ango-static"></iframe> ズームインするとテキスト表示が切り替わります。Ctrl+ドラッグで斜め表示 --- # 作業開始 --- ## 会場 WiFi (再掲) SSID ~ (現場合わせ) パスワード ~ (現場合わせ) --- ## Docker イメージを動かそう ```console $ docker run -ti --rm unvt/ango root@09dc97356d7e:~# ``` * '09dc97356d7e' の部分は異なる ### うまくいかない場合 ```console $ curl -O http://ango.vectortiles.xyz/ango-amd64.tar.gz $ gunzip ango-amd64.tar.gz | docker load ``` * Raspberry Pi の場合 amd64 → armhf --- ## コマンドを動かしてみる ```console (# exit) # さっき試した docker run から抜ける $ docker run -ti --rm -p 3000:3000 -p 8888:8888 unvt/ango root@fef54f77bc33:~# tippecanoe -v tippecanoe v1.34.4 root@fef54f77bc33:~# node -v v10.15.2 ``` - バージョンの表示が出ない場合にはサポートを受けてください - 先に進んでおきたい場合: https://hackmd.io/@hfu/ango-slides --- ### 上級者向け: ホストボリュームマウント 作業データを保存したり、持ち込みデータを扱う場合はマウントすることをお勧めします。 ``` -v (ホスト側のディレクトリの絶対パス):/media ``` ```console $ # /Users/hfu を /media として触れるようにする $ docker run -ti --rm \ -v /Users/hfu/:/media \ -p 3000:3000 -p 8888:8888 unvt/ango ``` --- #### 収録されているコマンドの紹介 - 生産 ```console $ tippecanoe -v # ベクトルタイルを生産 tippecanoe v1.34.5 $ tile-join # ベクトルタイルを操作 Usage: tile-join [-f] [-i] [-pk] [-pC] [-c joins.csv] [-X] [-x exclude ...] -o new.mbtiles source.mbtiles ... $ ogr2ogr --version # データ変換 GDAL 2.4.2, released 2019/06/28 $ osmium --version # OpenStreetMap のデータ変換 osmium version 1.10.0 (v1.10.0-76-g26674e1) ... ``` --- #### 収録されているコマンドの紹介 - ホスト ```console $ node -v # サーバは Node.js で作ります v10.15.2 $ budo --version # 開発用サーバ budo v11.6.3 $ pm2 --version # サーバ 3.5.1 $ browserify --version # JavaScript 変換 16.5.0 ... ``` --- #### 収録されているコマンドの紹介 - スタイル ```console $ vi --version # スタイルを HJSON 形式で書く VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun 15 2019 16:41:15) ... $ hjson -v # HJSON を JSON に変換する Hjson.js 3.1.2 $ gl-style-validate # Mapbox Style を検証する usage: ... ``` --- #### 収録されているコマンドの紹介 - 最適化 ```console $ node ~/vt-optimizer/index.js --help # ベクトルタイルサイズ最適化 Vector Tile Weight Loser... ``` --- ## ハンズオン作業 1. 生産 2. ホスト 3. (スタイル) 4. (最適化) 今回のハンズオンでは、基礎編として 1., 2.。 3., 4. は進度に合わせたバリエーションルート。 --- ## (1) 生産 GeoJSONS をベクトルタイルに変換 ```console $ cd ango-produce $ rake tippecanoe --output=tiles.mbtiles --read-parallel --force --layer=ndm --minimum-zoom=7 --maximum-zoom=10 --prefilter='node prefilter.js' ../geojsons-natural-disaster-monuments/data.geojsons 255 features, 14316 bytes of geometry, 2 bytes of separate metadata, 109216 bytes of string pool 99.9% 10/900/404 tile-join --force --output-to-directory=zxy tiles.mbtiles --no-tile-compression ``` まずは実行してみてください --- ### 実行された内容 ```console $ cat Rakefile task :default do sh "tippecanoe --output=tiles.mbtiles\ --read-parallel --force --layer=ndm\ --minimum-zoom=7 --maximum-zoom=10\ --prefilter='node prefilter.js'\ ../geojsons-natural-disaster-monuments/data.geojsons" sh "tile-join --force\ --output-to-directory=zxy tiles.mbtiles\ --no-tile-compression" end ``` --- ### ソースデータ ```console # more ../geojsons-natural-disaster-monuments/data.geojsons {"geometry":{"type":"Point","coordinates":[128.042983,26.554941]},"type":"Feature","properties":{"ID":"47209-001","LoreName":"津波襲来の碑","LoreYear":"2012","Address":"沖縄県名護市字大浦","DisasterName":"津波<br>(1960年5月24日)","DisasterKind":"津波","DisasterInfo":"昭和35年(1960)5月南米チリでM8.5の地震が起き大津波が発生、津波は太平洋を横 断し日本近海を襲った。当地には数回に亘り襲来。津波高5mにも及び大浦橋が全壊、護岸も決壊した。","Image":"https://maps.gsi.go.jp/legend/disaster_lore/47209/47209-001.jpg","ImageWidth":"1200","ImageHeight":"900"}} ... ``` 一行ごとに GeoJSON Feature が書いてある [RFC 8142](https://tools.ietf.org/html/rfc8142): ogr2ogr は GeoJSONS と呼ぶ --- ### tippecanoe ```console tippecanoe --output=tiles.mbtiles\ --read-parallel --force --layer=ndm\ --minimum-zoom=7 --maximum-zoom=10\ --prefilter='node prefilter.js'\ ../geojsons-natural-disaster-monuments/data.geojsons ``` output ~ 出力するベクトルタイルパッケージのパス layer ~ レイヤ名 (protips: 複数レイヤを含む場合には、feature.tippecanoe.layer にセット) prefilter ~ タイルに切った後にかけるフィルタ --- #### プレフィルタ: 地物ごとの調整 ```javascript // prefilter.js: 標準入力の各行を `modify()` して出力 const modify = require('./modify.js') const readline = require('readline') const rl = readline.createInterface(process.stdin, {}) rl.on('line', (line) => { console.log(JSON.stringify(modify(JSON.parse(line)))) }) ``` ```javascript // modify.js: 与えられた地物を修正して返す module.exports = (f) => { for (k of [ 'DisasterKind', 'DisasterName', 'DisasterInfo', 'LoreName' ]) { // 余計な <br> タグをとる f.properties[k] = f.properties[k].replace(/<br>/g, " ") } return f } ``` --- #### tippecanoe で使用したその他のオプション read-parallel ~ 地物を並列に読む → 速くなる force ~ ベクトルタイルパッケージを上書きする minimum-zoom ~ 生産する最小ズーム (protips: 地物ごとなら feature.tippecanoe.minzoom にセット) maximum-zoom ~ 生産する最大ズーム (protips: 地物ごとなら feature.tippecanoe.maxzoom にセット) --- ### tile-join ```console tile-join --force\ --output-to-directory=zxy tiles.mbtiles\ --no-tile-compression ``` force ~ 出力フォルダを上書きする output-to-directory ~ 出力フォルダ no-tile-compression ~ ベクトルタイルを gzip 圧縮せず出力 --- #### 雑学: gzip 圧縮とベクトルタイルの関係 1. ウェブではベクトルタイルは __gzip 圧縮されて送られるのが普通__。そのときは content-encoding: gzip ヘッダをつけて送る。 3. このため、MBTiles にはもとから gzip 圧縮して格納するのがデフォルト。 4. プレインなウェブサーバでは content-encoding: gzip つきはデフォルトではなく、__非圧縮__ で送る。 5. よって「MBTiles の中では gzip 圧縮済み、ファイルシステムに展開する場合には gzip 圧縮しない」がグッドプラクティス --- ## (2) ホスト ベクトルタイルパッケージをブラウザで見ることができるようにする。 ```console $ cd ~/ango-host # ホストプログラムに移動 $ yarn # 必要なライブラリを導入 $ rake build # 地図サイトを構築 $ rake start # サーバをスタート ``` まずは実行してみてください。 → http://localhost:3000 --- <iframe width="100%" height="500px" src="https://un-vector-tile-toolkit.github.io/ango-static"></iframe> ```console $ rake stop      # サーバを止める ``` --- ## 解説: `rake build` ```ruby task :build do # サイトのファイルを作る sh "hjson -j htdocs/style.hjson > htdocs/style.json" sh "browserify -o htdocs/bundle.js -t " + "[ babelify --presets [ @babel/preset-env ] ] app.js" end ``` - htdocs/style.hjson → htdocs/style.json - app.js → htdocs/bundle.js --- ### `htdocs/style.hjson` ```hjson { version: 8 center: [135, 35] zoom: 7 sources: { v: { ... 255 ] text-halo-width: 1 } } ] } ``` [Mapbox Style](https://docs.mapbox.com/mapbox-gl-js/style-spec/) を簡明のため [HJSON](http://hjson.org) で書いたもの --- #### なぜスタイルを HJSON で手書きするのか - スタイルは意外と論理的なもの - Maputnik のような GUI エディタでは見通しが立てにくく、スタイル記述をコンパクトにしにくい - Maputnik は特有のメタデータを吐き、__[expressions](https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions)に対応していない__。 - より複雑なスタイルは今後 HOCON で書くかも --- ### `app.js` ```javascript const map = new mapboxgl.Map({ container: 'map', style: 'style.json', attributionControl: true, hash: true }) ``` 単なるウェブ地図起動の JavaScript だが、モダンに書きたいので browserify/babelify で変換している。 --- ## 解説: `rake start` ```ruby task :start do sh "pm2 start process.yml" end ``` --- ### `process.yml` ```yml apps: - script: index.js name: ango instances: 4 exec_mode: cluster ``` 4インスタンスのクラスタモードで起動 --- ## 解説: `rake stop` ```ruby task :stop do sh "pm2 stop ango; pm2 delete ango" end ``` --- ## 解説: `rake _mapbox` ```ruby task :_mapbox do sh "cp ../mapbox-gl-js/dist/mapbox-gl.js htdocs" sh "cp ../mapbox-gl-js/dist/mapbox-gl.js.map htdocs" sh "cp ../mapbox-gl-js/dist/mapbox-gl.css htdocs" end ``` 別途ビルドした Mapbox GL JS から必要ファイルをコピー --- # バリエーションルート --- - 別データに挑戦 - gh-pages を用いたホスティング (要 GitHub アカウント) - Vector Tile optimizer を用いた最適化 - Maputnik を用いたスタイル調整 --- ## まとめ - 成果紹介 - 国連ベクトルタイルツールキットのこれから - 全体を通しての質疑 - ラップアップ - 集合写真撮影 --- ## おわり --- # 参考 --- ![](https://optgeo.github.io/signature/optgeo-logo.png) オープンジオデータをベクトルタイルに変換する取り組みの[アンブレラ](https://github.com/optgeo/)です。
{"metaMigratedAt":"2023-06-14T22:56:45.550Z","metaMigratedFrom":"Content","title":"FOSS4G Niigata 2019: 国連と始めるベクトルタイル","breaks":true,"contributors":"[{\"id\":\"fc0f9ab3-2844-43fe-a29f-da028138304f\",\"add\":9817,\"del\":1396},{\"id\":\"370340a2-02b1-4368-b231-d79cd9de7109\",\"add\":2,\"del\":2}]"}
    3399 views