地図を含むツールやアプリケーションを作ることがあると思います。一般公開サーバ (OpenStreetMap や国土地理院のタイルサーバなど) の配信データを参照すればすぐに手元のブラウザに地図を表示することができます (Leaflet の例) (MapLibre GL JS の例)。が、用途によっては一般公開サーバを叩けないこともあります (負荷が大きくなる / 外部ネットワークに接続できない / 秘密情報を含む場合など)。
この記事では、利用者視点で「地図を表示する」というゴールからさかのぼって、どのような配信形式・配信サーバ・配信用データ・元データが必要かを整理したいと思います。記述に誤りがありましたらご指摘いただけますと幸いです。
この記事では以下を想定しています。
- 地図描画ライブラリは Leaflet か MapLibre GL JS を想定しています。
- 日本全国の道路・建物を表示する用途を想定しています (特定地域のみや特定要素のみの描画ではなく)。そのため、タイル形式の配信データの描画を想定しており、WMS 形式や GeoJSON 形式は扱いません。
参考文献
- 地図タイルへの入門知識を考える - Qiita : こちらにより周辺の情報があります。
- Leaflet - a JavaScript library for interactive maps : Leaflet のドキュメントです。
- MapLibre GL JS : MapLibre GL JS のドキュメントです。
- 地理院地図|地理院タイルについて
- web mapping - What are the Differences Between TMS, XYZ & WMTS? - Geographic Information Systems Stack Exchange
- Japan/OSMFJ Tileserver - OpenStreetMap Wiki
- 地理院地図|地理院タイル一覧
- mapbox/vector-tile-spec: Mapbox Vector Tile specification
- Protocol Buffers Documentation : Protocol Buffers のドキュメントです。
- gsi-cyberjapan/gsivectortile-mapbox-gl-js: 地理院地図VectorのベクトルタイルをMapbox GL JSで表示するサンプル
- gsi-cyberjapan/tdlmn: 地理院タイルダウンロードツール
- maptiler/tileserver-gl: Vector and raster maps with GL styles. Server side rendering by MapLibre GL Native. Map tile server for MapLibre GL JS, Android, iOS, Leaflet, OpenLayers, GIS via WMTS, etc. : TileServer GL の GitHub リポジトリです。
- MBTiles - OpenStreetMap Wiki
- PMTiles Concepts | Protomaps Docs
- protomaps/PMTiles: Pyramids of map tiles in a single file on static storage
- onthegomap/planetiler: Flexible tool to build planet-scale vector tilesets from OpenStreetMap data fast
- systemed/tilemaker: Make OpenStreetMap vector tiles without the stack
- openmaptiles/openmaptiles: OpenMapTiles Vector Tile Schema Implementation
- Download OpenStreetMap for Japan | Geofabrik Download Server : 日本の OpenStreetMap 生データの PBF ファイル japan-latest.osm.pbf が配布されています。地方単位のファイルもあります。タイル群データファイルのビルドツールによっては勝手にダウンロードしてくれるのでダウンロードしておく必要はありません。
地図を表示するために必要なもの
利用側からさかのぼると、以下を明らかにする必要があると思います。
- 1. 地図描画ライブラリ
-
2. 地図描画ライブラリから利用できるデータ配信形式
一般公開サーバの配信データを利用できる場合はここで終わりです。 - 3. タイルサーバを立てる方法
- 4. タイルサーバに与えるためのタイル群データファイルの形式
- 5. 日本全国の道路・建物を含むタイル群データファイルを用意する方法
1. 地図描画ライブラリ
以下の JavaScript ライブラリで地図を表示できます。Python から利用したい場合は、どちらも Python バインディングがあると思うので探してください。
Leaflet
- CDN からライブラリを読み込む場合は https://leafletjs.com/download.html から CDN URL と integrity を確認できます。
- 基本的にラスタタイルを描画します。ベクタタイルであっても VectorGrid プラグインを読み込めば描画できますが、クライアント側でスタイル定義の記述が必要になります。
- 地図を表示するだけの例はこちらです (記事冒頭のリンクと同じです)。
MapLibre GL JS
- CDN からライブラリを読み込む場合は https://maplibre.org/maplibre-gl-js/docs/#cdn から CDN URL が確認でき、バージョンに応じて https://unpkg.com/maplibre-gl@5.13.0/dist/?meta から integrity が確認できます。
- ラスタタイルもベクタタイルも描画できます。ベクタタイルのスタイル定義ファイルを参照することもできるのでベクタタイルも手軽に描画できます。
- 地図を表示するだけの例はこちらです (記事冒頭のリンクと同じです)。
2. 地図を描画するためのデータの提供形式
先のようなライブラリを利用すると http(s)://.../{z}/{x}/{y}.(png|pbf) といった感じに地図の断片の URL を指定すると思います ( {z}/{x}/{y} の意味は [4] [1] 及びこちらの記事を参照ください) ( [4] [5] [1] にあるようにこれは「いわゆる XYZ 形式」であって標準規格ではないが、広く利用されているようです)。この形式は大きく以下の 2 つに分かれます。
ラスタタイル http(s)://.../{z}/{x}/{y}.png
- リクエストされたズームレベル・x座標・y座標の範囲の地図画像を配信する形式です。
- サーバで予め生成しておいた画像を返す方式もあるし、サーバでオンデマンドにベクタタイルをラスタライズして返す方式もあります。
- ⭕ クライアント側は画像を読み込むだけでスタイルの記述などがなく楽です。
- ❌ 反面、表示スタイルのカスタマイズはできません (色や線の太さを変えたり、細い道路を非表示にしたり、地名のフォントサイズを大きくしたりなど)。
- OpenStreetMap、国土地理院も PNG ラスタタイルを配信しています (利用例)。
ベクタタイル http(s)://.../{z}/{x}/{y}.pbf (MVT形式)
- リクエストされたズームレベル・x座標・y座標の範囲の地図を描画するために必要なデータを配信する形式です。
- したがって、そのデータをどのようなスタイル (道路は灰色にして、川は青色にして、等) で描画するかを与えて実際に描画するのはクライアント側になります。
- ベクタタイルのデータ形式は Mapbox Vector Tile (MVT) Specification が標準的です (データをプロトコルバッファ方式でシリアライズするところまでが MVT なので、拡張子は
.mvtか.pbfのことが多いです)。MVT は地物 (地図上に表示する山や道路や建物などのオブジェクト) をタイル内の整数座標 (典型的には 4096 × 4096 グリッド) にある図形として保持しています。よって、ベクタタイル (をまとめたデータファイル) をビルドするときに何を含めるかの指示 (=タイルスキーマ) を与えることになります。描画時に与えるスタイルはタイルスキーマと整合性がなくてはなりません (道路が含まれないのに「道路を灰色に」というスタイルを与えたら噛み合いません)。
- ❌ クライアント側で見映えのよいスタイルを定義するには記述量がかさむと思います。
- ただし TileServer GL は Maplibre 系描画エンジン向けのスタイル定義ファイルも配信してくれるので、TileServer GL と Maplibre GL JS の組み合わせならスタイル定義ファイルを利用できて楽です。
- ⭕ 反面、表示スタイルのカスタマイズが効きます。
- OpenStreetMap、国土地理院 もベクタタイルを配信しています (利用例)。
3. タイルサーバを立てる方法
一般公開サーバの配信タイルを利用できればそれでよいですが、用途によっては一般公開サーバを叩けないこともあると思います。その場合、自前でタイルサーバ ( =「いわゆる XYZ 形式」でリクエストされたラスタ / ベクタタイルを返す Web サーバ) を立てる必要があります。立てる方法には以下があります。
適当な Web サーバに /{z}/{x}/{y}.(png|pbf) のディレクトリ構造でタイルを配置する
- これが直感的な方法ですが、日本全国規模の地図でこれをやると準備に何日もかかる可能性が高いので (必要な最大ズームレベルにもよります)、時間がある場合向けです。
- 手軽に試したい場合であっても、後述の Planetiler であれば日本全国の MBTiles のビルドでも数分で終わるので (元データのダウンロード時間とマシンスペックには依存します) それを後述の Tileserver GL で配信すればよく、手軽に試したいならそちらで十分だと思います。
- ただし、外部タイルをダウンロードして運用するような場合はこの方法を取るかもしれません (地理院タイルダウンロードツールなどが公開されています)。この場合でも、タイル群データファイルにまとめて配信した方が管理しやすいかもしれません。
Tileserver GL でタイルサーバを立てる
- MBTiles / PMTiles 形式のラスタ / ベクタタイル群データファイルを与えると、タイルを配信してくれる Maptiler 社の OSS タイルサーバです。Docker イメージの利用が便利です。
- ⭕ 特に、ベクタタイル群データを与えても描画エンジン MapLibre GL でラスタタイルにレンダリングして配信してくれるので、クライアント側でラスタタイルを利用したいときに便利です。
- ⭕ また、ベクタタイルとしての利用でも、MapLibre 系描画エンジン向けのスタイル定義ファイルも配信してくれるので、MapLibre GL JS では少ない記述量で地図描画できます (これをやるとサーバ側レンダリングと見た目は変わらないですが、クライアントサイド描画のほうが鮮明です)。
- 具体的に、ベクタ MBTiles を
data/output.mbtilesに配置した上で以下を実行すれば、5000 番ポートからデフォルトスタイルでラスタタイル、ベクタタイル、スタイル JSON が配信されます (http://{server_ip}:5000の TileServer GL 画面から配信 URL を確認できます)。docker run -it -v "$(pwd)/data":/data -p 5000:8080 maptiler/tileserver-gl- ただ、デフォルトスタイルでのラスタタイル配信ではレンダリング用フォントが存在しないため地名が表示されません。
data/fonts/{フォント名}に glyphs ファイル群に変換したフォントを配置してdata/styles/{スタイル名}/style.jsonでそのフォント名を指定する必要があります (参考:私がフォントを配置したブログ記事)。
- ただ、デフォルトスタイルでのラスタタイル配信ではレンダリング用フォントが存在しないため地名が表示されません。
PMTiles 形式 のファイルを配置する
- これはタイルサーバソフトというよりタイル群データファイルの形式ですが、PMTiles 形式のファイルを Web サーバや S3 に置くだけでタイル配信できます。
4. タイルサーバに与えるためのタイル群データファイルの形式
タイルサーバを立てるには通常 MBTiles, PMTiles といったタイル群データファイル (タイルをまとめたファイルをこの記事でこう呼びます) が必要らしいのでそれらを整理します。なお、これらはあくまでタイルのまとめ方の形式であって、まとめるタイルがどんなラスタだとかどんなベクタだとかは含みません。つまり、ラスタ MBTiles もベクタ MBTiles もあります。
MBTiles 形式
- タイル群を 1 ファイルにまとめた形式で、実体は SQLite データベースです。
- このファイルを置くだけでタイルを配信はできないので、対応したタイルサーバソフト (Tileserver GL など) によって配信する必要があります。
PMTiles 形式
- Protomaps プロジェクトによって設計されたタイル群データファイル形式です。
- このファイルを Web サーバや S3 に置くだけでタイルを配信できます。
- なのでこれによる配信が便利そうですが、もしもチーム内にラスタタイル配信を求めるメンバーが要る場合、ラスタタイル群を用意してラスタ PMTiles をビルドする必要があります。この場合はラスタタイル群の用意がボトルネックになると思います。
5. 日本全国の道路・建物を含むタイル群データファイルを用意する方法
そういうわけで、日本全国の道路・建物を含むタイル群データファイルを用意したいです。そもそも日本全国の道路・建物を含む地図情報ソースとして利用できるのは OpenStreetMap や国土地理院になると思います。OpenStreetMap 生データ (.osm.pbf) をベクタタイル群データファイルにビルドする方法には以下があります。
なお、日本全国の道路・建物を含むラスタタイル群データファイルをビルドするよい方法は私がわかっていません (時間がかかってよければ、外部タイルサーバから / レンダリング機能付き自前タイルサーバからタイルをダウンロードしてまとめる方法があると思います)。
Planetiler で OpenStreetMap 生データ (.osm.pbf) をベクタ MBTiles / PMTiles にビルド
-
Planetiler はベクタタイル群データファイルを高速にビルドできる OSS です。Docker イメージや .jar ファイルから利用できます。OpenStreetMap 生データを MBTiles にも PMTiles にもビルドできます。
- 以下のコマンドで
japan.osm.pbfを勝手にダウンロードしてくれます。その他、デフォルトのプロファイル (加工指示) にしたがって水域データなどもダウンロードします。が、この OpenStreetMap の水域ポリゴン (water_polygons) のダウンロードが時間帯によってかなり時間がかかることがあるようです。MBTiles のビルド自体は 3 分半でした (EC2 インスタンスの m8a.4xlarge 使用時)。mkdir data docker run -e JAVA_TOOL_OPTIONS="-Xmx16g" \ -v "$(pwd)/data":/data ghcr.io/onthegomap/planetiler:latest \ --download --area=japan
- 以下のコマンドで
tilemaker で OpenStreetMap 生データ (.osm.pbf) をベクタ MBTiles にビルド
- tilemaker も OpenStreetMap 生データからベクタ MBTiles をビルドできます。が、Planetiler が利用できれば Planetiler の方が速いかもしれません。
OpenMapTiles で OpenStreetMap 生データ (.osm.pbf) をベクタ MBTiles にビルド
- OpenMapTiles も OpenStreetMap 生データからベクタ MBTiles をビルドできます。が、Planetiler か tilemaker でビルドした方が速いと思います。
- ただし OpenMapTiles は単なるタイル群データファイルのビルドツールではなく、タイルスキーマ (タイルの中にどんな情報を何というレイヤーに入れるか) やスタイルも包括するプロジェクトであり、Planetiler も tilemaker も OpenMapTiles 準拠のタイルスキーマを採用しています。