この記事にあるosm2vectortilesは古いため、Dockerのインストール方法以外は新しい記事を参考にしてください。
OpenStreetMap Advent Calendar 2016 3日目の記事です。
今回はOpenStreetMapのデータを使ってMapbox Vector Tileを自分で作ってみることに挑戦してみました。
対象となる環境はUbuntu 16.10をインストールしているThinkpad X220です。スペックは以下の通りです。
なお、このマシンは本体と換装パーツ込で33000円ぐらいで揃えたものです*1
さて、余談はよいとして、Mapbox Vector Tileを作るに当たって、今回はosm2vectortilesのGenerate your own vector tilesを参考に行いました。
まず先にosm2vectortilesについて軽く紹介したいと思います。
このプロジェクトはOpenStreetMapをベースとしたMapbox Vector Tileの地図タイルを自由にダウンロードできるようにするもので、世界全域の地図タイル以外にもいろんな地域の地図タイルがmbtiles形式でホスティングされています。また、地図タイルの作成にdockerを活用しているのが特長です。また、地図タイルを長くやってる人にはMapTilerというプロダクトで有名なKlokan Technologiesがスポンサーをしていることも話題になりました。俺も久々にこのカンガルーの会社ロゴ見てびっくりした(汗
さて、さっそく作業をしていきます。まずはDockerとDocker-composeをインストールします。
sudo apt-get install docker docker-compose
sudo service docker start
sudo docker run hello-world
次に一般ユーザで作業をするためにdockerグループにユーザを追加します。
sudo usermod -aG docker $USER
これで一旦リブートをして再度ログインして、一般ユーザで動作するかを確認します。
docker run hello-world
dockerが一般ユーザで動くようになったら次にosm2vectortilesをgithubから落としてきます。
mkdir -p ~/develop/osm cd develop/osm git clone https://github.com/osm2vectortiles/osm2vectortiles.git cd osm2vectortiles
今回の作業パスは ~/develop/osm/osm2vectortiles とします。
まずは手順通りにdocker-composeでPostGISのコンテナを取得します。
docker-compose up -d postgis
ここで一旦別のディレクトリを作成して、そこに今回使うファイルをダウンロードします。
まずはテストということで、bbbikeから東京の範囲のpolyファイルとPBFファイルをダウンロードします。polyファイルは後でBBOXの範囲を計算するのに使います。
mkdir -p ~/tmp/osmdata cd ~/tmp/osmdata wget http://download.bbbike.org/osm/bbbike/Tokyo/Tokyo.poly wget http://download.bbbike.org/osm/bbbike/Tokyo/Tokyo.osm.pbf
次にPBFファイルをosm2vectortiles/importに配置します。
cp ~/tmp/osmdata/Tokyo.osm.pbf ~/develop/osm/osm2vectortiles/import/
次にまた別の作業ディレクトリを作成して、OpenStreetMapDataからwater-polygonsとsimplified-water-polygonsを、Natural Earthからnatural_earth_vectorのSQLiteのファイルをダウンロードします*2。
mkdir -p ~/tmp/osmpoly cd ~/tmp/osmpoly wget http://data.openstreetmapdata.com/water-polygons-split-3857.zip wget http://data.openstreetmapdata.com/simplified-water-polygons-complete-3857.zip wget http://naciscdn.org/naturalearth/packages/natural_earth_vector.sqlite.zip
これらを全てunzipしてから必要なファイルをosm2vectortiles/importにコピーします。
unzip water-polygons-split-3857.zip unzip simplified-water-polygons-complete-3857.zip unzip natural_earth_vector.sqlite.zip cp ~/tmp/osmpoly/water-polygons-split-3857/water_polygons.* ~/develop/osm/osm2vectortiles/import/ cp ~/tmp/osmpoly/simplified-water-polygons-complete-3857/simplified_water_polygons.* ~/develop/osm/osm2vectortiles/import/ cp ~/tmp/osmpoly/packages/natural_earth_vector.sqlite ~/develop/osm/osm2vectortiles/import/
最終的にosm2vectortiles/importディレクトリが以下のようになります。
% ls -l import 合計 1079640 -rw-r--r-- 1 btm btm 18088604 12月 3 15:11 Tokyo.osm.pbf -rw-r--r-- 1 btm btm 414519296 12月 3 15:16 natural_earth_vector.sqlite -rw-r--r-- 1 btm btm 6 12月 3 15:16 simplified_water_polygons.cpg -rw-r--r-- 1 btm btm 74837 12月 3 15:16 simplified_water_polygons.dbf -rw-r--r-- 1 btm btm 853 12月 3 15:16 simplified_water_polygons.prj -rw-r--r-- 1 btm btm 29614272 12月 3 15:16 simplified_water_polygons.shp -rw-r--r-- 1 btm btm 49948 12月 3 15:16 simplified_water_polygons.shx -rw-r--r-- 1 btm btm 6 12月 3 15:15 water_polygons.cpg -rw-r--r-- 1 btm btm 452789 12月 3 15:15 water_polygons.dbf -rw-r--r-- 1 btm btm 847 12月 3 15:15 water_polygons.prj -rw-r--r-- 1 btm btm 642308932 12月 3 15:15 water_polygons.shp -rw-r--r-- 1 btm btm 301916 12月 3 15:15 water_polygons.shx
では、またosm2vectortilesの作業ディレクトリに戻って手順書通りに作業を進めていきます。
docker-compose up import-external docker-compose up import-osm docker-compose up import-sql
ここまできたらあとはexportをするのみとなりますが、BBOX(範囲)のパラメータを与えないと世界中が対象となってしまうので、BBOXの値を計算します。
BBOX自体はwest,south,east,northの順にパラメータを与えます。
なので、経度180度線を気にしなければ、min(longitudes),min(latitudes),max(longitudes),max(latitudes)となります。
今回の東京の範囲のPOLYファイルをみると今回は単純な四角形なので値は簡単にわかります。
Tokyo 1 139.62 35.56 139.95 35.56 139.95 35.78 139.62 35.78 END END
これを読めば、BBOX=139.62,35.56,139.95,35.78という値がとれるので、それを使ってドキュメントに沿ってexportを実行します。今回はzoom 9からzoom 14までを作成してみます。
docker-compose run \ -e BBOX="139.62,35.56,139.95,35.78" \ -e MIN_ZOOM="9" \ -e MAX_ZOOM="14" \ export docker-compose up export
これらを実行するとexport以下にtiles.mbtilesというファイルができあがります*3。ただし、dockerで生成したためか所有者がrootのファイルになっているので、所有者の変更とあとでファイルを変更しても良いように別名でコピーをとっておきます。
sudo chown $USER:$USER ~/develop/osm/osm2vectortiles/export/tiles.mbtiles cp ~/develop/osm/osm2vectortiles/export/tiles.mbtiles ~/develop/osm/osm2vectortiles/export/tokyo.mbtiles
あとは実際に動作するかをチェックします。
これはGetting Startedではtileserver-gl-lightを使うようになっているのですが、tileserver-gl-light自体はすでに古く、tileserver-glが最新になっているのでそちらを使うようにします。
ただし、tileserver-glの方は現在npm installに失敗してしまいます*4。
なので、今回はtileserver-glのdockerを使って検証してみます。
cp ~/develop/osm/osm2vectortiles/export/tokyo.mbtiles /tmp/ cd /tmp docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl
これでサーバが動いているIPアドレスの 8080 port へアクセスします。
ここでBasicスタイルのVectorタイルを選択します。
初期状態でzoom 2なのですが、何も出ててきません。しかし、ズームアウトすると...
全球が出てきます。そこで東京の方に見ていきます
途中まではすごく雑です。
作成したズーム9からはちゃんと出てきます。
とりあえずズーム14までちゃんと作られたのが確認できます。
では、せっかくなのでズーム0〜ズーム8をマージしてみましょう。
マージはドキュメントにあるようにMapboxのmbutilにあるpatchというシェルスクリプトを使います。なお、sqlite3が入っている必要があります。また、ドキュメントにあるmbtilesのダウンロードはズームレベル5までのもの*5なので、ダウンロードページからPlanet from zoom level 0 to 8を選んでダウンロードします。
cd ~/develop/osm/osm2vectortiles/export wget https://osm2vectortiles-downloads.os.zhdk.cloud.switch.ch/v2.0/planet_2016-06-20_7088ce06a738dcb3104c769adc11ac2c_z0-z8.mbtiles wget https://raw.githubusercontent.com/mapbox/mbutil/master/patch chmod +x patch cp tokyo.mbtiles tokyo-and-planet.mbtiles ./patch planet_2016-06-20_7088ce06a738dcb3104c769adc11ac2c_z0-z8.mbtiles tokyo-and-planet.mbtiles
これも同様に動かしてみましょう。
rm /tmp/tokyo.mbtiles cp ~/develop/osm/osm2vectortiles/export/tokyo-and-planet.mbtiles /tmp cd /tmp docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl
最初から全球がレンダリングされていていい感じです。
日本の形もちゃんと出てきます。
ただし、zoom 8あたりで残念なマージになりました。
まぁ、ファイルを上書きしてしまってるのでしょうがないとはいえます。
とりあえずこれである程度の地図タイルが作れるようになりました。
では、せっかくなので日本全国の地図タイルを作ってみましょう。
まずはGeofebrikのOSMデータのミラーサイトから日本全体のデータをダウンロードします。
cd ~/tmp/osmdata
wget http://download.geofabrik.de/asia/japan.poly
wget http://download.geofabrik.de/asia/japan-161202.osm.pbf
次に、以前の作業に使ったpbfファイルの削除と、以前使ったdocker-composeを全て削除します。
docker-composeを削除するのはどうもpgdataを削除したぐらいでは何かが残ってしまっていてimposm3のmergeの処理が走ってしまうためです。
ただ、すでにイメージ自体はダウンロードしてるので再構築自体は高速です。
cd ~/develop/osm/osm2vectortiles rm import/Tokyo.osm.pbf docker-compose stop postgis docker-compose rm -f export docker-compose rm -f import-sql docker-compose rm -f import-osm docker-compose rm -f import-external docker-compose rm -f postgis docker-compose rm -f pgdata docker-compose rm -f cache
あとは以前の手順と同様に再構築を進めます。
cp ~/tmp/osmdata/japan-161202.osm.pbf import
docker-compose up -d postgis
docker-compose up import-external
docker-compose up import-osm
docker-compose up import-sql
次にBBOXを取り出したいのですが、日本の範囲として定義されているPOLYファイルはPOLYGONになっていてちょっと計算が面倒なので、とりあえずスクリプトをでっち上げたのでこれを使ってBBOXの値をゲットします。
cd ~/tmp/osmdata
wget https://gist.githubusercontent.com/smellman/a2770f3a6c4717315cc0a4538b985a1c/raw/1008b6d5f061fb7c0eeaddef86d8faf68f1a6d57/poly2bbox.py
% python poly2bbox.py japan.poly BBOX=122.5607,21.20992,153.8901,45.80245
こんな感じで取れるのでこれをBBOXのパラメータとして使います。
なお、今回はMAX_ZOOMを13としています。というのはどうもズーム9から14で試したら17時間ぐらい処理にかかるらしく、今日のAdvent Calendarに間に合わないので...*6
docker-compose run \ -e BBOX="122.5607,21.20992,153.8901,45.80245" \ -e MIN_ZOOM="9" \ -e MAX_ZOOM="13" \ export docker-compose up export
できあがったのはだいたい550MBぐらいのmbtilesで、 exportの処理時間はおよそ3時間ぐらい、importを含めてだいたい4時間ぐらいでいけました*7。
あとはバックアップを取ってからtileserver-glでチェックをしてみます。
rm /tmp/tokyo-and-planet.mbtiles sudo chown $USER:$USER ~/develop/osm/osm2vectortiles/export/tiles.mbtiles cp ~/develop/osm/osm2vectortiles/export/tiles.mbtiles ~/develop/osm/osm2vectortiles/export/japan.mbtiles cp ~/develop/osm/osm2vectortiles/export/japan.mbtiles /tmp cd /tmp docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl
東京周辺はこんな感じです。
三宅島も同様です。
やっぱりzoom 14の壁が厚いなーという印象ですね。
とりあえずzoom 14だけ足せるかこんなコマンド打って放置しておきます。
sudo chown root:root ~/develop/osm/osm2vectortiles/export/tiles.mbtiles docker-compose run \ -e BBOX="122.5607,21.20992,153.8901,45.80245" \ -e MIN_ZOOM="9" \ -e MAX_ZOOM="14" \ export
あと13時間後らしいので、お楽しみですね!!!!!1
*1:今日の小江戸LUGはこのネタをやる予定だったんだけど、この記事がニャオスだったので不参加にしました...
*2:なおドキュメントにはどのファイルを落とすのかが具体的に書いてないので注意してください、僕はソースコードを読んでダウンロードするファイルを判断しました
*3:最後のdocker-compose up exportが必要かどうかっていうとちょっと謎なんだけど、とりあえずドキュメント通りにやってる
*4:たしかMapboxの方のパッケージングでNode 4.xでバグがあるのが引っかかっているような気がします。なお、tileserver-gl-lightの方はUbuntu 16.10でnpm installができ、動作しています
*5:ちなみにこれURLが古くリンク切れしてる
*6:そもそも日本全域自体結構範囲がありますが、それ以外にもBBOXが四角形なので必要のない範囲のレンダリングも必要となってしまいます
*7:ズームレベルを1つ上げると単純に処理が4倍になりますが、データがほとんど無い範囲が多いとそれだけPostgreSQLから帰ってくるものが少なくなるはずなので時間は減るはずです