読者です 読者をやめる 読者になる 読者になる

smellman's Broken Diary

クソみたいなもんです

OpenStreetMapのMapbox Vector Tileを作ってみた その2 、あとスタイルの編集とかフォントとか

OpenStreetMap タイル三兄弟 Mapbox Vector Tile

昨年12月にOpenStreetMapのMapbox Vector Tileを作ってみたというタイトルの記事を書きましたが、その時扱っていたosm2vectortilesが終了*1となり、現在はopenmaptilesという存在になりました。

openmaptiles自体はosm2vectortilesと同様にDockerを使ったタイルのビルド方法の提供などをしていますが、openmaptiles.comの方では非商用向けにフリーのタイル配信(githubなどからアクセストークンの取得が必要)や、月40ドルでのタイル配信サービスの提供していたり、iOS/Androidアプリのソースコードの販売などを行っています。

今回はopenmaptilesを使ってMapbox Vector Tileの作成と、Maputnikを使ったスタイルの編集や、既存のスタイルにM+とIPAの合成フォントを使ってみた例の紹介など、前回の記事よりもちょっと突っ込んだ内容となります。ただ、似たような説明の所はちょっと割愛してるので、そこだけ気をつけてください。

openmaptilesでMapbox Vector Tileの作成

さて、さっそくMapbox Vector Tileの作成をしていきます。

今回は前回同様Ubuntu 16.10をインストールしたThinkpad X220での解説に加え、OS X El Capitan上でのやり方を追加で解説します。ただ、OS X上でのやり方はあくまで追加となり、Dockerに慣れてない人は適当にがんばってください(何

まず、今回必要な環境は以下のものとなります。

  • Docker 1.10.0以上
  • Docker Compose 1.6.0以上*2

DockerをUbuntu 16.10で動かす方法については前回の記事を参照にしてください。

Docker ComposeについてはUbuntu 16.10ではパッケージのバージョンが古いため、別途インストールが必要となります。

sudo su -
curl -L https://github.com/docker/compose/releases/download/1.10.1/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
exit

このあと新しいターミナルウィンドウを開くなりすればdocker-composeの新しいバージョンが動きます。

あとは公式ドキュメントに沿って作業をします。

git clone https://github.com/openmaptiles/openmaptiles.git
cd ./openmaptiles
docker-compose pull
./quickstart.sh

quickstart.shはデフォルトではアルバニア*3のpbfファイルをgeofabrikからダウンロードしてMapbox Vector Tilesの作成とmbtiles形式(SQLite)への格納を行います。

この後、一旦tileserver-glを動かして検証をします。

make start-tileserver

あとは http://localhost:8080 へアクセスします。

f:id:smellman:20170204023959p:plain

f:id:smellman:20170204024014p:plain

さて、quickstart.shでは主に以下のことを行います。

  1. 生成する国を指定
  2. 以前のDocker imagesのクリーンアップ
  3. 必要なら新たにgeofabrikから対象となる国のpbfファイルのダウンロード
  4. 必要ならdocker-composeに渡す設定ファイルを作成
  5. Mapbox Vector Tileに必要なdocker-composeのタスクを順次実行

また、実際のタスク自体はMakefileの方に何をするかが書かれています。

では、次に日本のタイルを作成します。

これは非常に簡単です。

./quickstart.sh japan

以上です。

ですが、動かしてもズームレベル7までしかないので微妙なので、ズームレベルを0から14*4まで生成してみますが、一度quickstart.shを実行した後にやっかいなことがあります。

  1. docker-compose の一部タスクで利用される ./data/docker-compose-config.yml はgeofabrikからpbfをダウンロードするタイミングで作成される
  2. 1. のタスク自体の設定がレポジトリにある .env ファイルを参照している
  3. geofabrikからダウンロードしていたpbfがあると geofabrik からpbfをダウンロードするステップは省略されてしまう

公式ドキュメントなどにはズームレベルを変更する場合は .env ファイルを編集しろとあるのですが、実際には .env ファイルを変更したあとに再度 ./quickstart.sh を実行しても ./data/docker-compose-config.yml が変更されないため、結局のところズームレベル7までしか作成されないということになります。

なので、以下のいずれかの方法を取る必要があります。

  • .env ファイルを編集したあとに ./data 以下にある一度ダウンロードした pbf を削除してから再度実行
  • .env ファイルを編集したあとに ./data/docker-compose-config.yml も編集してから再度実行

ただし、 ./data/docker-compose-config.yml を生成する処理自体も docker によって実行されるので、 ./data/docker-compose-config.yml を編集する場合はroot権限が必要になります。

sudo vim ./data/docker-compose-config.yml

さて、この妙な所を説明したところで、 .env ファイルと ./data/docker-compose-config.yml の説明をします。

まずは .env ファイルです。

POSTGRES_DB=openmaptiles
POSTGRES_USER=openmaptiles
POSTGRES_PASSWORD=openmaptiles
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
QUICKSTART_MIN_ZOOM=0
QUICKSTART_MAX_ZOOM=7
DIFF_MODE=false

このような設定がありますが、基本的には QUICKSTART_MAX_ZOOM を作成したい MAX ZOOM に設定してあげればよいです。

個人的にはなぜこのファイルがレポジトリに突っ込んであるのか微妙ですが...

次に、 ./data/docker-compose-config.yml です。

version: "2"
services:
  generate-vectortiles:
    environment:
      BBOX: " 121.8236704, 23.7651400, 152.1180000, 46.9388859"
      OSM_MAX_TIMESTAMP : "2017-02-01T21:10:42Z"
      OSM_AREA_NAME: "japan"
      MIN_ZOOM: "0"
      MAX_ZOOM: "7"

ここにはズームレベルの他に ./quickstart.sh の引数として指定したエリアの名前とダウンロードしたPBFファイルのタイムスタンプ、そしてPBFファイルから算出したBounding Boxの値*5が格納されます。

ここもMAX_ZOOMを14にしてあげればよいということになります。

あとは、前回同様作成すればOKです。流れとしてはこんな感じです。

vim .env
sudo vim ./data/docker-compose-config.yml
./quickstart.sh japan

ちなみに./quickstart.shで国名を間違えるとPBFファイルが消されるので気をつけてください...

この後は make start-tileserver でタイルサーバを実行してもよいのですが、バックアップの意味も込めて別のところにコピーして動かしてみましょう。

mkdir ~/tiles
cp data/tiles.mbtiles ~/tiles/japan.mbtiles
cd ~/tiles
docker pull klokantech/tileserver-gl
docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl

これでlocalhost:8080にアクセスすればtileserver-glを通してMapbox Vector Tileへアクセスが可能となります。

さて、OSXの方ですが、quickstart.shでdateコマンドが GNU date でしか使われていないオプションがあり止まってしまいます。そのため、dateコマンドのオプションを変更する必要があります。Pull Requestは出して置いたのでそれを参考にしてください。

あとはgawkコマンドとmd5sumコマンドが無かったのでそれをHomebrewとかで入れます。

brew install gawk
brew install md5sha1sum

他にも足りないものがあるかもしれませんが、まぁそこは適当に調べてください。

スタイルの編集とフォントの追加

さて、今回は前回ノータッチだったスタイルエディタ周りについても紹介します。

Mapbox Vector Tileのスタイルの編集はいくつか方法がありますが、今回はlocal環境のみで完結できるMaputnikを紹介します。

Maputnikはオンライン、オフライン問わず利用できるMapbox Vector Tileのスタイル編集ソフトウェアです。ES6やReactを使って開発をされていて、また開発資金をkickstarterで募集したことも有名です。

Maputnikはオンラインで利用ができ、styleのjsonファイルをアップロードして編集することが可能なので非常に便利ですが、当然タイルのアクセスにはSSLが必要なのでlocal環境で構築したものの編集にはオンラインモードは使うことができません。

ですが、local環境で動かせばSSL無しで動作可能というわけでやってみます。

先に tileserver-gl を8080ポートで動いているということが前提とします。

次にmaputnikをダウンロードして起動します*6

git clone git@github.com:maputnik/editor.git
cd editor
npm install
npm start

あとは http://localhost:8888 にアクセスします*7

f:id:smellman:20170204024811p:plain

次にヘッダにあるOpenから元ネタとなるスタイルを選択します。今回はアップロードせずにKlokantech Basicを選びます。

f:id:smellman:20170204025033p:plain

次に、まず行方不明にならないよう日本付近を表示させておきます。

そして、Sourcesを選び、TileJSON URLを http://localhost:8080/data/v3.json に変更します。

f:id:smellman:20170204025525p:plain

そしてwaterのレイヤーのPaint Propertiesをいじっておもむろに海を血の海にしてやります*8

f:id:smellman:20170204030105p:plain

さて、血の海ごっこに飽きたところで次にフォントをMigMixに変えてみたいと思います。今回はroad_major_labelのみを対象としてみます。

まず最初にMapbox GLにフォントを対応させるためにMapbox GL用にglyphを作成します。

これには openmaptilesのfontsというレポジトリを利用します。

先に適当なディレクトリにmix-mplus-ipaのフォントを展開しておき、以下のようにします。

git clone git@github.com:openmaptiles/fonts.git
cd fonts
cp ../font/mix-mplus-ipa/*/*.ttf mix-mplus-ipa
npm install genfontgl
./generate.sh

これで _deploy というディレクトリにmix-mplus-ipa を含むフォントのディレクトリが作成されます。

次にこのディレクトリでhttpサーバを立ち上げます。今回は serve というnodeのパッケージを使います。

npm install -g serve
cd _deploy
serve -C -p 18888

今回は適当にCORS対応でかつ18888ポートで立ち上げておきます。

次に、MaputnikのStyle SettingsからGlyphs URLを http://localhost:18888/{fontstack}/{range}.pbf に変更します。

f:id:smellman:20170204030356p:plain

すると日本語どころか全ての文字が消えてしまいます。

URLを見ると、

http://localhost:18888/Klokantech%20Noto%20Sans%20Regular,Klokantech%20Noto%20Sans%20CJK%20Regular/36096-36351.pbf

となっていて、fontstackに対してKlokantech Noto Sans RegularとKlokantech Noto Sans CJK Regularの2つが与えられていることがわかります。

すくなくともMapbox Vector Tileでサーバ側のフォントの扱いがややこしいのがわかりましたが、とりあえずスタイルを編集してこれを回避します。

まず、 road_major_label のスタイルを開きます。

ここで、フォントを編集したいのですが、現行のMaputnikでは2つ以上のフォントがある場合GUIでの編集が上手くいかないという問題があります。

なので、下の方のJSON EditorでKlokantech Noto Sans Regularを削除しちゃいます。

f:id:smellman:20170204030656p:plain

これでちゃんと日本語の表示が出てくるようになりました。

ではこの表示のフォントをmigmix1p-boldに変更してみます。

f:id:smellman:20170204030836p:plain

これでフォントが変更されます。

f:id:smellman:20170204030946p:plain

他の所も同じように変更していけばよいという感じになります。

まとめ

Mapbox Vector Tileに関するものはスタイルの編集などを含めるとかなり敷居が高かったんですが、Mapuntikの出現で一気に敷居が下がりました。

また、openmaptilesでは以前よりもより簡単にタイルの構築が行えるようになっていてこちらも敷居が下がってよかったという感じです。

まだまだサーバ周りでは調査は必要ですが、だいぶこなれてきたと思います。

みなさんもぜひタイル作成にチャレンジしてみましょう。

あ、MacでビルドしてたプロセスどころかDockerの全プロセスが飛んだ...orz

*1:no longer maintainedなんで終了だと思ってる

*2:docker-compose.ymlにversion "2"と書いてある

*3:イタリアのかかとの裏とおぼえました

*4:なお、openmaptilesではズームレベル14までは取り込む内容がズームレベルごとに変わりますが、ズームレベル14以上は特にタイルの内容に変更がないのと十分な情報量があるのでズームレベル14までとしています。詳しいことはlayersフォルダの中にあるSQLを参考にしてください

*5:実際にはosmconvert --out-statisticsを使っていて、その出力ファイルが./data/osmstat.txtとして残る

*6:Maputnik CLIという便利そうなものがあるらしいがそれはインストール方法が良くわからなかったので割愛します

*7:この場合だと2つ以上のブラウザでアクセスすると死ぬっぽいので注意

*8:毎回なんで俺こんな遊びやるんだろう...