smellman's Broken Diary

クソみたいなもんです

Georepublicに入社して7年目になりました。

smellman.hatenablog.com

本日で無事7年目に突入しました。
なんだかんだでGISの専門家っぽくなってきました。
使う方のGISはまだまだ慣れないのですが...

笑い話としては、俺はGIS上級者資格を持ってないのだけど、俺の講義を受けるとGIS上級者資格が取れるポイントが付くらしいんですよ。
俺にもくれって思いますね(何
いや、持ってても何に使うのかわからないのですががが

仕事は相変わらずRuby on RailsだったりReact Nativeだったり、コンサルティングやったりVector Tileだったりで、節操がない感じでGISをやっています。
最近はVisual Basicで書かれたASPなWeb GISRuby on Railsに移植してたりとか地獄のような仕事をしています。Dimとかすっかり忘れて変なコード規約だなーとか思ってました(何
コミュニティ活動は日本UNIXユーザー会、OpenStreetMap Foundation Japan、OSGeo財団日本支部などで活動をしていますが、いずれも楽しくやれているので比較的コミュニティ活動が充実しています。たまにはMozillaの方にも顔を出してますが、最近レアキャラになりつつあります。元組長ピンチ。

まぁ、そんなこんなで7年目も引き続き弊社をよろしくお願いいたします。
安全な案件を9月ぐらいにください。

schemaspyでRailsのDBの概要の資料を作成する

schemaspyを使ってRailsのDBの資料が簡単に作れたのでネタにしてみます。

github.com

用意するもの docker-compose 環境なんですが、これは Mac上で Graphviz が落ちるというのを回避するためにやっています。

まず docker-compose.yml を用意

version: '3'
volumes:
  pgdata:
services:
  db:
    image: "mdillon/postgis:9.6"
    volumes:
      - pgdata:/var/lib/postgresql/data
      - .:/mydata
    ports:
      - "5432:5432"
  schemaspy:
    image: "schemaspy/schemaspy:snapshot"
    volumes:
      - ./schemaspy:/output
    depends_on:
      - db

自分の場合だいたいpostgisを使っているのでimageはpostgisです。

事前準備はこんな感じ。

pg_dump -Fp -O hogehoge > hogehoge.sql
docker-compose pull
docker-compose up -d db

postgresqlが立ち上がったのでimportします。

docker-compose exec db /bin/bash
su - postgres
createuser -s foo
createdb -O foo bar
psql -U foo bar < /mydata/hogehoge.sql

インポートするときは /mydata にデータがあるようにしてるので注意してください。

あとは schemaspy の volumes に schemaspy というディレクトリを指定してるので、先に作ってから出力します。
ちなみに現状の schemaspy:snapshot は -o オプションが指定されてるので変更はできません。

mkdir schemaspy
docker-compose run schemaspy -t pgsql -host db -db qq -schemas "public" -u qq -charset utf-8 -rails -I "spatial_ref_sys|geography_columns|geometry_columns|raster_columns|raster_overviews"

これで schemaspy/index.html を開けばOK。
なかでは relation の項目でこんな図ができたりします。

f:id:smellman:20171230161522p:plain

オプションの -railsspam_id を spams などにリレーションを貼ってくれるようになります。
あと、 -I オプションで除外できるテーブルを指定できるので postgis のやつらを除外すれば rails のみの構成になります。

注意としては schemaspy は github で開発が継続されてから公式ドキュメントが追いついてないのでソースコード読んだほうが機能が見つけやすいです(ぉ
あと、schemaspy で検索すると sourceforge の方がまっさきに出てくるので渋い気持ちになります。

おまけ

snapshot ではなく schemaspy 6.0.0rc2 を動かしてみたいと思って試しに作った Dockerfile も置いておきますね。

FROM openjdk:8-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
                graphviz \
&& rm -rf /var/lib/apt/lists/*

RUN mkdir /usr/src/app

COPY postgresql-42.1.4.jar /usr/src/app
COPY schemaspy-6.0.0-rc2.jar /usr/src/app

jar は各自拾ってきましょう。

OpenMapTiles/Tileserver-GL/MaputnikによるMapbox Vector TileのOSS実装環境のまとめ

本記事はOpenStreetMap Advent Calendar 2017の12月10日付けの記事となります。

昨年からosm2vectortilesを検証しだし、今年はOpenMapTilesによる検証及び実運用を進めていたので、とりあえずこの界隈をまとめようと思います。
ただ、主な内容はOpenStreetMapのMapbox Vector Tileを作ってみた その2 、あとスタイルの編集とかフォントとかからあまり変わっては居ません。

まず、今回取り扱うプログラムの簡単な説明をしたいと思います。

OpenMapTiles
OpenStreetMapのデータからMapbox Vector Tileを生成するためのプログラム群
Tileserver-GL
Mapbox Vector Tileの配信用サーバ兼レンダリングサーバ
Maputnik
Mapbox-GL Styleのエディタ

一般的なワークフローとしては、まずOpenMapTilesでMapbox Vector Tileを作成し、Tileserver-GLでMapbox Vector Tileを配信させ、MaputnikでMapbox-GL Styleを作成して、Tileserver-GLで作成したMapbox-GL Styleを配信させるという流れになります。

ここでややこしいのがTileserver-GLがタイルとスタイルを両方配信する役目を持っているということです。実際、タイルとスタイルがないとMapbox GL上で地図がレンダリングできないため、これがセットで配信できるという風に理解していただきたいです。

なお、Mapbox社は上記に該当するものを全てサービスとして提供をしていますが、使ったことがないのでわかりません(汗
なので、少なくとも本記事ではMapbox社のサービス自体と比較するというものではありません。

では、それぞれのプログラムの解説及び今年一年で変わった部分などを解説していきます。

OpenMapTiles

OpenMapTilesは前述通りOpenStreetMapのデータからMapbox Vector Tileを生成するプログラム群というものになります。
各処理をDockerコンテナで行うことで処理毎に開発、メンテナンスがされているという特長があります。

今年大きく変わったところは以下のものが挙げられます。

  • Multi Languageサポート(v3.6): デフォルトで35言語のインポートを可能にしていて、対応言語の変更も可能です。これはMapbox GL JSなどで動的に表示言語を変更するのに役に立ちます。
  • Wikidataのインポートをサポート(v3.7): これはOSMのデータよりもWikidataの方が多言語対応のデータを多く含んでいるということから、上記のMulti Languageサポートをより強力にするために取り込みをおこないます。
  • postserveの提供: 今年追加されたdockerコンテナで、ST_AsMVTを利用してPostgisのデータから直接Mapbox Vector Tileを出力するというものです。

他にもレイヤーの追加や、インポート対象のデータの更新や対象のズームレベルの変更など様々な変更が入っています。

また、この一年でインポートにかかる時間が増えました。
Thinkpad X220 (Core i5 4core, SSD 256GB, Memory 16GB)のマシンで計測したところZ14でたしか夜間ぐらいで終わっていたものが計測したところ16時間ぐらいかかるようになっています。
しかしながら、取り込みのスピードとしてはそこまで問題にならないかと思います。

また、postserveが提供されているため、OSMのデータをインポート後に直接postserveで運用するという手もあります。
実際のところpostserveの開発者はvarnishと組み合わせて配信をしているようです*1

では、とりあえずOpenMapTilesの作成手順を簡単にまとめましょう。

まず用意するのは docker-compose が動作する環境です。Ubuntu 17.10であれば、以下のようにします。

sudo apt-get install docker.io
sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo usermod -aG docker $USER
sudo reboot
docker run hello-world # 一般ユーザで動作確認
docker-compose -v

以上でセットアップが完了です。

あとはOpenMapTilesを取得して構築を行います。

git clone https://github.com/openmaptiles/openmaptiles.git
cd openmaptiles
git checkout -b origin/v3.7 v3.7
vim .env # QUICKSTART_MAX_ZOOM=14に変更
./quickstart.sh japan

最終的なアウトプットは data/tiles.mbtiles になります。
ここらへんは今年の初めあたりからはほぼ変わっていません。

では、続いてTileserver-GLの話をします。

Tileserver-GL

Tileserver-GLはMapbox Vector Tileの配信用サーバ兼レンダリングサーバとなります。
こちらもDockerによる運用が簡単なのがポイントです。
弊社でも現在二件ほどTileserver-GL+Dockerで運用を行っています。

大きな変更点は今年にかけてエントリーポイントのURLが変更になったことです。
詳しい情報はAvailable Endpointを参考にしてください。
このため、以前から運用中のものはURLなどの変更が必要になるのに注意が必要です。

動作方法はいろいろありますが、実運用として使うのであればdocker-composeとVarnish cacheによる運用をおすすめします。
実際にこの運用の構築手順を見ていきましょう。

まず最初に tileserver-gl を動作させるところまで持っていきます。
最初に運用をするサーバにmbtilesをコピーします。

scp data/tiles.mbtiles example.com:/tmp/japan.mbtiles

次にtileserver-glが起動をするかどうかを確認します。

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

これでアクセスできたら成功です。

次に、config.jsonファイルを作成します。
現段階では最小限のファイルだけ作成します。

vim config.json
{
  "data": {
    "japan-vector": {
      "mbtiles": "japan.mbtiles"
    }
  }
}
docker run -it -v $(pwd):/data -p 8080:80 klokantech/tileserver-gl
curl http://localhost:8080/data/japan-vector.json

なお、この状態ではスタイルの配信を行っていない状態になります。

では、もう少し踏み込んでセットアップをしていきます。
今度はMapbox GL Styleが参照する font と sprite 、および style のディレクトリの用意をします。
今回は解説が面倒なのでフォントはgithubにアップロードしているものを取ってきます。

wget https://github.com/openmaptiles/fonts/releases/download/v1.1/v1.1.zip
mkdir fonts
cd fonts
unzip ../v1.1.zip
cd ..
mkdir sprites
mkdir styles

この段階で以下のような構成になっているはずです。

.
├── config.json
├── fonts
├── japan.mbtiles
├── sprites
└── styles

では、上記ディレクトリ構成をconfig.jsonに反映させます。

vim config.json
{
  "options": {
    "paths": {
      "root": "",
      "fonts": "fonts",
      "sprites": "sprites",
      "styles": "styles",
      "mbtiles": ""
    }
  },
  "styles": {
  },
  "data": {
    "japan-vector": {
      "mbtiles": "japan.mbtiles"
    }
  }
}

スタイルは後述するMaputnikで扱うので、次にこれをdocker-composeで動かせるようにしましょう。

vim docker-compose.yaml
version: '2'
services:
  varnish:
    image: eeacms/varnish
    ports:
    - "6081:6081"
    depends_on:
    - raster-tileserver
    environment:
      BACKENDS: "raster-tileserver"
      BACKENDS_PORT: "80"
      BACKENDS_PROBE_INTERVAL: "10s"
      BACKENDS_PROBE_TIMEOUT: "2s"
      DNS_ENABLED: "true"
    restart: always
  vector-tileserver:
    image: klokantech/tileserver-gl
    ports:
    - "8080:80"
    volumes:
    - .:/data
    restart: always
  raster-tileserver:
    image: klokantech/tileserver-gl
    volumes:
    - .:/data
    restart: always

上記のdocker-compose.yamlで行っているのは vector tile と raster tile の配信をわけ、raster tileの配信を Varnish Cache でまとめるというものです*2
なお、向き先の変更についてはnginxなどで行っています。
実運用の環境では以下のようにしています。

  location / {
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://localhost:8080;
  }

  location ~ ^/.*\.png {
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_pass http://localhost:6081;
  }

また、実運用時にはdocker-compose scaleを使って処理が重たい raster tile のサーバの台数を変更することで効率よくCPUを利用するようにしています。

docker-compose up -d
docker-compose scale raster-tileserver=3

では、最後にMaputnikについてお話します。

Maputnik

これも今年はじめの記事から対してあまり変わっていないというか、むしろ maputnik.com のドメイン更新を怠ったので大変なことになりました(汗

Maputnikは現在のMapbox社のエディタのクローンとして誕生したものです。
実装には React を使っていて、現在は github.io にホスティングされているものか、もしくはローカル環境で起動したものが利用できます。
今回は localhost 上で一度スタイルの設定をしたいので、 docker 環境を作ってしまいましょう*3

git clone git@github.com:maputnik/editor.git
cd editor
docker build -t maputnik:latest .
docker run -it -p 8888:8888 maputnik

あとは http://localhost:8888 にアクセスをして Open からベースとなるスタイルを選択して Export から Download を選択して JSON ファイルを保存します。

次にこのjsonファイルをtileserver-glのstylesにコピーをします。

scp ~/Downloads/ciwhogehoge.json example.com:~/tiles/styles/mydesign.json

次にサーバ上で mydesign.json を編集し、以下の場所を書き換えます。

sources.openmaptiles.url
"mbtiles:{japan-vector}"
glyphs
"{fontstack}/{range}.pbf"
sprite
"スプライト画像のpath"

なお、spriteは必要に応じて変更してください。
というのも、sprite画像自体は元々提供されているデザインと対になってデザインされているケースが多いので、その場合は必要に応じてwgetなどで取得してください。

cd sprites
wget https://raw.githubusercontent.com/lukasmartinelli/osm-liberty/gh-pages/sprites/osm-liberty.json
wget https://raw.githubusercontent.com/lukasmartinelli/osm-liberty/gh-pages/sprites/osm-liberty.png
wget https://raw.githubusercontent.com/lukasmartinelli/osm-liberty/gh-pages/sprites/osm-liberty%402x.json
wget https://raw.githubusercontent.com/lukasmartinelli/osm-liberty/gh-pages/sprites/osm-liberty%402x.png

このようにした場合は sprite の値は "osm-liberty" となります。

では、今回は osm-liberty をベースに処理をしてみます。

vim styles/mydesign.json #sources.openmaptiles.url, glyphs, spriteを編集
vim config.json
{
  "options": {
    "paths": {
      "root": "",
      "fonts": "fonts",
      "sprites": "sprites",
      "styles": "styles",
      "mbtiles": ""
    }
  },
  "styles": {
    "mydesign": {
      "style": "mydesign.json"
    }
  },
  "data": {
    "japan-vector": {
      "mbtiles": "japan.mbtiles"
    }
  }
}

これでdocker-composeを再起動するとデザインが追加され、Viewerからアクセスが可能になります。
あとはnginxなどをセットアップすれば完成です。

なお、この後デザインを変更する場合はGL Styleのリンクをダウンロードしてmaputnikで編集をすればOKです。
また、一旦httpsでアクセス可能になれば maputnik をローカルで立ち上げずに作業することができるので、デプロイは面倒ですが共同編集のようなことが可能になります。

OpenMapTiles Map Server

ここまで3つのOSSをベースに話をしてきましたが、OpenMapTiles自体に大きな動きがあり、OpenMapTilesを運営しているKlokanTechが簡単に OpenMapTiles のホスティングまでを可能にするサービスを開始しました。

それが、 OpenMapTile Map Server です。

OpenMapTiles Map Server

これは Docker のインスタンス1つでOpenMapTilesがホスティングしてるMapbox Vector Tileのダウンロードや展開を可能にする物で、 MacWindowsであれば Kitematic を使って簡単に動かすことが可能です。
詳しいことは以前雑にまとめたので適当にみてください。

speakerdeck.com

というわけでOpenMapTiles周りは商業まわりも頑張っているようです。

来年に向けてのトピック

さて、今年の分のおさらいをしたのですが、来年に向けて1つホットな話題があります。
それが、Mapbox Vector Tileを使ったNative Clientの台頭です。

まず、大きなポイントとしては Mapbox GL の React Native 対応が安定してきました。

github.com

先日、React Native Mapbox GL を使って簡単なクライアントを作成してみたのですが、期待通りの動きをしてくれました。
ただ、Mapbox GL の Native 版については起動制限などがあるのではないかという話があり、どのように回避していくのかが気になるところです。
今のところは "pk.NO_ACCESS_TOKEN" とかいうTokenを入れておくとザルなのと、そもそもTokenのチェックの仕方がandroidの方が厳しいというよくわからない実装になっているので、具体的なところはよくわかっていません。

また、Native対応という点では Mapzen の Tangram ES という OpenGL ES を使ったライブラリもあります。

github.com

これは Tangram *4という Leaflet JS 上で WebGL を使ったレンダリングをするためのライブラリの Native 版という存在です。
Mapbox GL Styleとは違い、シーンの表現に yaml を採用したものとなっていて、また対応しているベクトルタイルの種類が豊富という利点もあります。

これらのライブラリが台頭してくることにより、よりOpenMapTilesを使ったサービス展開などが望めるかもしれません。

資料など

今年はOpenMapTilesについていろいろと喋りましたので、その資料とか貼っておきます。

State of the Map 2017 発表資料(えせ英語)と動画(えせ英語)

speakerdeck.com


State of the Map 2017 - Friday Room 1 10:30 to 13:00

(やばい、State of the Mapの動画編集まだ終わってないorz)

FOSS4G Tokyo 2017 ハンズオンデイ資料

speakerdeck.com

FOSS4G Tokyo 2017 コアデイ資料

speakerdeck.com

(やばい、FOSS4G Tokyo 2017 コアデイの動画編集まだ終わってないorz)

*1:ただし、postserveは直接gzip圧縮したファイルを出力していないのに注意してください

*2:実際には png 画像だけ raster tile の方に振り分けています

*3:現在リリースされているバージョンは古いのですが、静的なWebアプリケーションなのでPythonやNodeでWebサーバを立てるだけでローカルでも動きます

*4:Tangram JSと言ったほうが良いのかもしれないが、正式にはTangramのはず

夏のイベント「ITコミュニティの運営を考える」、「State of the Map 2017」、「FOSS4G Tokyo 2017」の告知など

今月から再来月ぐらいにかけてスタッフをやっているイベントのラッシュが始まっていて、完全にバタバタしていますがもろもろ告知をしておきます。

jus勉強会「ITコミュニティの運営を考える」

まず、7月22日(土曜日)に僕が理事を努めている日本UNIXユーザー会(jus)主催の「ITコミュニティの運営を考える」という勉強会をサイボウズ株式会社 東京オフィスで開催します。

techplay.jp

「ITコミュニティの運営を考える」はちょうど二年前のjus総会併設勉強会でスタートした企画で、現在はjus研究会で各地のOSCでいろんな講師の方に出ていただいてコミュニティ運営について発表やディスカッションを行ったり、jusのコミュニティソムリエ(何)によるグループディスカッションの場になっていたりしていて、今回は久々に勉強会として開催することになりました。

登壇者は以下の六名です。

  • 岡田良太郎(OWASP) @okdt
  • 白石俊平(TechFeed/元html5jリーダー) @Shumpei
  • 須藤功平(OSS Gate) @ktou
  • 関治之(Code for Japan) @hal_sk
  • 日高正博(DroidKaigi/techbooster) @mhidaka
  • 宮原徹(OSC事務局) @tmiyahar

今回は特に幅広いジャンル(セキュリティ、Web、OSS入門、Civic Tech、Android、文化祭)の方々に声を掛けた所、掛けた人ほぼOKを貰いかなりすごいメンバーが集結することになります。
かなり濃いメンバーなので面白いディスカッションとなると思います。
ぜひとも皆さん来てください。

ちなみに、jusでは毎年総会をやったあとに同じ会場で勉強会をやっていますが、今回も2017年度の総会のあとの勉強会となります。
特にjusの会員である必要はありませんので、日本橋散策ついでに来てくれたら*1よいかなと思います。

State of the Map 2017

次に8月18日(金曜日)から20日(日曜日)にかけて三日間、 State of the Map 2017 という OpenStreetMap の国際イベントを会津若松で開催します。

2017.stateofthemap.org

こちらは国際イベントとありますが、昨年の State of the Map Japan 2016 とは違い地域イベントではなく OpenStreetMap Foundation が主催するメインのイベントとなっています。
また、国際イベントというだけあって、英語によるプレゼンテーションやディスカッションが大半で、翻訳は特にありません(ぉ
ただし、日本人による日本語での発表もあります。

僕は今回はこのイベントでローカルチームのメンバーとして、準備を円滑に進めるための調整や、当日配布されるガイドブックの作成*2などをやっています。

また、僕自身も発表者として、まさかのトップバッターで発表することになっています。
発表内容は神戸市にあるしあわせの村*3という施設の公式アプリ、「だれでもナビ」の実装について語ります。

だれでもナビ

だれでもナビ

  • KOBESHIMIN FUKUSHI SHINKO KYOKAI
  • Navigation
  • Free

内容としては、 openmaptiles + tileserver-gl による OpenStreetMap のデータを Mapbox Vector Tile の配信する方法とReact Native+WebViewでの活用方法、pgRouting と 現段階では未リリースのバージョンの osm2pgrouting *4 によるルーティングAPIの作り方などの解説などをします。
問題点としては僕はこれから英語をしっかりやらないといけないのですが、準備で忙しくて手遅れ感がすでにあるということですね!

Early Birdは締め切ってしまいましたが、まだまだ参加者募集していますので、お早めに参加登録をお願いいたします!

FOSS4G 2017 Tokyo

最後に、9月15日(金曜日)と9月16日(土曜日)の二日間、都内某所(まだアナウンスできない)でFOSS4G 2017 Tokyoを開催が決定しました!

[OSGeoJapan-discuss] FOSS4G Tokyo 2017【第一報】

こちらの主催は OSGeo財団日本支部 となります。

まだアナウンスページが無いのはこれから作らないといけないからなのでいろいろお察ししていただきつつ、すでに発表者募集が始まっていますので、発表ネタがあるよ!って人は是非ご応募を、また、地図系の知識を深めたいっていう人は是非日程を開けておいてください。



なお、今年は三宅島には行きません(汗

*1:真横にコレド日本橋があるのでショッピングなども良いかと。ちなみにコレド日本橋の地下のスーパーみたいなところの近くでたむろしないようにかモスキート音ならしてるところがあって辛かった

*2:去年の元データが無くなってしまったようなのでInDesignを一から勉強して作成しています

*3:今年のCode for Japan Summitの開催場所でもあります

*4:開発してる本人曰く、もうちょっとリファクタリングしてからgithubにpushしたいらしい

pandocでプログラムが記述された納品用PDFを作ってみる

仕事で一人プロジェクト(開発/コンサルティング)の時にはMarkdownとpandocでお客さん向けのPDFを作っていたんですが、デフォルトのテンプレートだとプログラムやシェルの動作などを記載したときにPDFではtext wrapが動かなくて特にシェルなんかは複数行に改行したり工夫していました。ただ、これをやっていくと精神がガリガリ削られてしまいます。

また、出力したPDFもちょっと格好悪いので使えそうなテーマを探してみました。

User contributed templates · jgm/pandoc Wiki · GitHub

今回は次のテンプレートが良さそうなので使ってみたというお話です。

GitHub - Wandmalfarbe/pandoc-latex-template: A pandoc LaTeX template to convert markdown files to PDF or LaTeX.

まず手元の環境ですが、 Homebrew 経由で入れた MacTex と pandoc となります。OSなどの違いは各自汲み取ってください。

とりあえず、導入をしてみます。

mkdir -p ~/.pandoc/templates/
cd ~/.pandoc/templates/
wget https://raw.githubusercontent.com/Wandmalfarbe/pandoc-latex-template/master/eisvogel.latex

あとは pandoc に --template eisvogel というオプションを追加すればよいのですが、単純にこれだけだとうまく動きません。

まず以下のような markdown があるとして、適当に処理してみます。

# openmaptilesでベクトルタイルの作成

本ドキュメントはopenmaptilesを利用してベクトルタイルのバイナリ(.mbtile形式)を作成するところまでを解説します。

## ターゲット

### ハードウェア

- Ubuntu 16.10 or Ubuntu 17.04
- 64bit CPU
- 4GBメモリ以上
- 30GB以上のディスクスペース
pandoc -f markdown_github test.md -o test.pdf --from markdown --template eisvogel --listings

すると次のようなエラーになります。

! Package inputenc Error: Unicode char テ (U+30C6)
(inputenc)                not set up for use with LaTeX.

See the inputenc package documentation for explanation.
Type  H <return>  for immediate help.
 ...

l.308 \section{テストドキュメント}

Try running pandoc with --latex-engine=xelatex.
pandoc: Error producing PDF

メッセージに沿って xelatex を使うようにします。

pandoc -f markdown_github test.md -o test.pdf --from markdown --template eisvogel --listings --latex-engine=xelatex

これでうまく行ったかと思ったら、日本語フォントが出てきません。

f:id:smellman:20170523041717p:plain

これを解決するには CJKmainfont のパラメータを与える必要があります。今回は完全な個人的な趣味で IPAexGothic を使います。

pandoc -f markdown_github test.md -o test.pdf --from markdown --template eisvogel --listings --latex-engine=xelatex -V CJKmainfont=IPAexGothic

f:id:smellman:20170523041902p:plain

これで日本語もばっちり表示されるようになりました。

ただ、 usage を見るとYAMLでタイトルを拡張できるようです。なぜYAMLを閉じるのが ... なのかはわかりませんが、とりあえず markdown に組み込んでみます。

最終的なサンプルは以下のようにしました*1

---
title: "ベクトルタイルの作成方法"
author: [Taro Matsuzawa taro@georepublic.co.jp]
date: \today
...

# テストドキュメント

本ドキュメントはopenmaptilesを利用してベクトルタイルのバイナリ(.mbtile形式)を作成するところまでを解説します。

## ターゲット

### ハードウェア

- Ubuntu 16.10 or Ubuntu 17.04
- 64bit CPU
- 4GBメモリ以上
- 30GB以上のディスクスペース

### ソフトウェア

- Docker > 1.11.0
- Docker Compose > 1.7.1
- git
- make
- bc

## セットアップ

### utility

openmaptiles の ```quickstart.sh``` の実行に必要なコマンドをインストールします。

```bash
sudo apt-get install git make bc
```

### Docker

apt-getコマンドでdockerをインストールし、サービスを起動します。

```bash
sudo apt-get install docker.io
sudo service docker start
```

### Docker Compose

#### Ubuntu 16.10

Ubuntu 16.10ではパッケージで提供しているバージョンが古いため、手動でインストールをします。

```bash
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
```

#### Ubuntu 17.04

Ubuntu 17.04ではパッケージが提供してるものを利用します。

```bash
sudo apt-get install docker-compose
```

これで出力してみましょう。

pandoc -f markdown_github test.md -o test.pdf --from markdown --template eisvogel --listings --latex-engine=xelatex -V CJKmainfont=IPAexGothic

f:id:smellman:20170523043120p:plain

これできれいになったと思ったのですが、よく見ると日付がドイツ語になっています。これはデフォルトがドイツ語になっているためなので、 README を参考にして英語にしてみましょう*2

pandoc -f markdown_github test.md -o test.pdf --from markdown --template eisvogel --listings --latex-engine=xelatex -V CJKmainfont=IPAexGothic -V lang=en-US

f:id:smellman:20170523043611p:plain

これでうまくいきました。なお、日付のフォーマットを変更するのであれば --metadata date="`date +%Y-%m-%d`" などとしてdateの値を与えるとうまくいきます。

pandoc -f markdown_github test.md -o test.pdf --from markdown --template eisvogel --listings --latex-engine=xelatex -V CJKmainfont=IPAexGothic -V lang=en-US --metadata date="`date +%Y-%m-%d`"

ちなみに、僕の場合は最初にTable of Contentsをつけるので --toc オプションも追加します。この --toc オプションも言語設定によって影響があるので、このテンプレートを使う場合は -V lang=en-US をつけておくのがおすすめです。

なお、全て試していないのですが text wrap が有効なのは --listings オプションを追加したときで、他の Syntax Highlighting を設定するとうまく動きません。

というかそもそも --listings をつければ最初の text wrap の問題解決していたような気がするんだけど考えるのをやめました。

幸せになればいいんだよ!!!!なりてえよ!!!!

あ、ついでですが、これあくまでPDF向きなのでこのmarkdownをhtmlに出力すると変になるから気をつけてね!

*1:お客さんに怒られないようちょっと構成を変えてる

*2:http://tug.ctan.org/language/hyph-utf8/doc/generic/hyph-utf8/hyphenation.pdf によると日本語はサポートされていないようです。

地図エンジニア死亡かるた

地図エンジニア歴がバイトを除いてそろそろ五年になるので、地図エンジニア死亡かるたを考えてみる。
なお、かるたってよくわからないので適当にあいうえお順で書いてみる。

あ: ArcGISは触ったことがないのに質問される
い: 伊能忠敬をそんなに知らない
う: 海の上に出て来るマーカー
え: 絵心がなくビジュアライゼーションを諦める
お: OpenLayers2
か: 漢字が読めない地名
き: 汚い図面
く: 苦しい修正仕様
け: 険しい3Dへの道
こ: 小受けが逃亡
さ: 殺意を覚える仕様書とスケジュール
し: 4月に案件がない
す: スケジュールがなぞの前倒し(お客さん都合)
せ: Sal◯sf◯rceに案件を持ってかれる
そ: SOAP
た: だいたいデータ量が多い
ち: 地図がそもそも読めない
つ: ツイッターで質問しても誰もわからない
て: 転送量の計算ミスで死ぬ
と: トイレのマッピングの重要性を痛感するまで五秒前
な: 夏休みはだいたい秋休み(もしくは冬休み)
に: 人月計算が適当
ぬ: Null Pointer Exception
ね: ネットでの地図界隈繋がり、だいたいリアルの繋がり、たまにお客さん
の: 納期がだいたい年度末
は: 破壊的仕様変更
ひ: 標準化
ふ: ブラウザーの知識が曖昧な人が多い
へ: 減らないというか増えていくExcelで管理されているタスクシート
ほ: 本気でその仕様でやるつもり?
ま: まじでその仕様でやるつもり?
み: 見積もりにG◯◯gle API for W◯rksの値段を入れ忘れる(てへぺろ)
む: 無理なスケジュール
め: メモリリークとの戦い
も: 文字コードで死ぬ(特にShapefile)
や: 休みも趣味で地図を描く
ゆ: 有給も趣味で地図を描く
よ: 呼ばれて見積もり作ってさんざんミーティングに時間使って案件にならない
ら: 来期もよろしくお願いいたします
り: リアルな3Dに見えるようにごまかす
る: ルーラを使って好きな街に飛んでいきたい
れ: 連休明けのメールチェック
ろ: 老朽化したGISとなんか違う座標のデータ
わ: 忘れた頃に復活する案件
京: 京都の住所

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

昨年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:毎回なんで俺こんな遊びやるんだろう...