MBTilesの内容

今回は、OpenMapTilesで作成したMBTilesの内容を確認します。

OpenMapTilesが使用する地図データ

まず、OpenMapTiles(以降、OMT)が使用している地図データを確認します。
OpenStreetMap(以降、OSM)のデータを頒布しているGeoFabrik社のサイトの四国データのダウンロードページは、以下のようになっています。

GeoFabrikの四国データのダウンロードページ

図の赤枠で示すように、shp.zip、osm.bz2、osm.pbfの3種類がダウンロードできます。

  • shp.zip:18種類のシェープファイル(圧縮時114MB、解凍後424MB)
  • osm.bz2:1つのXMLファイル(圧縮時109MB、解凍後1.3GB)
  • osm.pbf:Google社が仕様を策定したProtocol Buffersにより符号化(63MB、非圧縮ですがデータはgzip圧縮)

OMTでは、osm.pbfを元地図データとして使用しています。

MBTilesとは

MBTilesとは、複数のMVT(Mapbox Vector Tile)を1つにまとめたファイルです。
といっても、少しわかりにくいと思います。関連ファイルの概要をまとめると以下のようになります。

ファイルデータの概要データの形式仕様策定者
osm.pbfOpenStreetMap(OSM)のデータを個人情報を除いて全て収容したファイル。生データはXML形式だが、サイズが大きく最も高圧縮なosm.pbfが流通している。Protocol BuffersOSM?
.mvt1タイルごとのベクトル図形を収容したバイナリファイルProtocol BuffersMapbox
.mbtiles1タイル1レコードとして複数の.mbtを収容したSQLiteデータベースSQLiteMapbox

関係を図にすると以下のようになります。

ややこしいPBF関係の整理

ベースとしてGoogle社のProtocol Buffersの仕様があり、それを使ってosm.pbf、mvtの仕様が策定されています。MBTilesは、単純にmvtの集合と考えるとよいでしょう。

一方で、OMTが実行する処理の観点では、以下のような整理もできます。

  1. OSM協力者により地図データが作成されOSM上のデータベースに蓄積
  2. GeoFabrik社がOSMデータを抽出し、XML形式、SHP形式、osm.pbf形式で頒布
  3. OMTはそのうちのosm.pbfを利用
  4. OMTによりMapboxVectorTile形式(.mvt)に変換(1タイル1ファイル)
  5. OMTにより.osm.pbfを.mvt形式に変換
  6. .mvtを.mbtiles形式(SQLite形式)に変換
  7. 完成した.mbtilesをTileServerGLなどの配信サーバーにて配信
  8. 配信サイトに利用者がアクセスすることで地図を参照できる

以降にOMTに関係するファイルの仕様・概要を確認していきます。

Protocol Buffers

Protocol Buffers(以降、PBF、.pbf)の概要を確認しておきましょう。
Wikipediaの説明を以下に引用します。

Protocol Buffers(プロトコルバッファー)はインタフェース定義言語 (IDL) で構造を定義する通信や永続化での利用を目的としたシリアライズフォーマットであり、Googleにより開発されている。
オリジナルのGoogle実装はC++、Java、Pythonによるものであり、フリーソフトウェアとしてオープンソースライセンスで公開されている。また、ActionScript・C言語・C#・Clojure・Common Lisp・D言語・Erlang・Go・Haskell・JavaScript・Lua・MATLAB・Mercury・Objective-C・OCaml・Perl・PHP・R言語・Ruby・Scala・.NET Frameworkなどの実装が利用可能である。

Wikipedia https://ja.wikipedia.org/wiki/Protocol_Buffers

PBFは、Google社により開発された符号化方式と理解するとよいでしょう。
”符号化”というと、?という方も多いと思いますが、簡単に書くと以下のようなイメージです。

符号化の簡単なイメージ

上記は、”あ”(SJIS”82A0”)を”01”、”い”(SJIS”82A2”)を”02”に置き換えた(符号化した)イメージです。
通信回線やファイルについて、上記のように符号化した状態で伝送したり保存したりすると、通信量やファイルサイズが少なくて済みます(上記の例では4バイトの内容を2バイトで表現)。これが符号化のメリットとなります。

PBFでは、符号化のルールを.protoファイルに記述してPythonやGo、C++などの言語で使用できるようにコンパイルします。符号化と復号化は書くプログラム言語にて行います。
また、各言語向けのコンパイラ(protocol compiler)はGitHubにて公開されています。

https://github.com/protocolbuffers/protobuf

osm.pbf

osm.pbfの概要を確認します。
仕様は以下のページに記載されていますが、難解で今のところ私も十分理解していません。

https://wiki.openstreetmap.org/wiki/JA:PBFフォーマット

以下のサイトも参考になります。

https://code-house.jp/2016/10/18/osmpbf1/

上記のサイトの情報をもとに簡単なクラス図を作成すると、以下のようになります。

osm.pbfを表現したクラス図
  • dense(XML上はnodeのようです)がX、Yで構成される座標点1つを表現します
  • wayは複数のdenseにより構成され属性なしの地物を表現します
  • 属性付きの地物は、relationとして表現され複数のwayにより構成点が表現されタグなどの属性値が設定されます

MVT

MVTは、Mapbox社が定めたベクトルタイルデータの仕様です。
以下のサイトに仕様が公開されています。

https://docs.mapbox.com/vector-tiles/specification/

基本的には、GeoJSONをPBFにより符号化したものと考えるとよいでしょう。
以下に、前述のMapbox社のサイトからGeoJSONとMVTを対比している部分を引用します。

GeoJSONとMVTの対比(Mapbox社のサイトから引用)
  • GeoJSON上に2つの地物が定義されている
  • 1つ目の地物の属性”h”には値として”world”が設定されている
  • MVT上では1つ目の地物の3つ目のタグに項目名(keys)を示すtag=0を設定
  • 続いて4つ目のタグに項目の値(values)を示すtag=1を設定

MBTiles

MBTilesは、Mapbox社が定めたベクトルタイルデータの仕様です。
以下のサイトに仕様が公開されています。

https://docs.mapbox.com/help/glossary/mbtiles/

SQLiteをベースにしたデータベースであり、ラスターかベクトルタイルが収容できると記載されています。

MBTilesの内容を確認

ここまで、MBTilesを理解する上で必要な各種仕様を簡単に確認してきました。
ここから本日の主題であるMBTilesの内容確認です。

SpatialiteまたはSQLiteを導入されていない方は、以下の記事を参考に導入してみてください。なお、MBTilesはSpatialite(空間拡張機能)に依存していませんので、通常のSQLiteが導入されていれば、本記事と同じような確認は可能です。

Spatialiteの過去記事

まず最初に、OMTで作成されたtiles.mbtilesをCLIを使って確認します。
ファイルを指定してspatialite(sqlite3でも可)を起動し、テーブル一覧を確認します。

$ spatialite tiles.mbtiles
spatialite>.tables
geocoder_data  grid_key       grids          keymap         metadata     
grid_data      grid_utfgrid   images         map            tiles   

10種類のテーブル(ビューを含む)が確認できました。
この中で、TileServerGLによる配信に必要なテーブルは、tilesとmetadataの2つです。
tilesのカラムを確認しましょう。

spatialite> .schema tiles
CREATE VIEW tiles AS
    SELECT
        map.zoom_level AS zoom_level,
        map.tile_column AS tile_column,
        map.tile_row AS tile_row,
        images.tile_data AS tile_data
    FROM map
    JOIN images ON images.tile_id = map.tile_id;

tilesは、mapテーブルとimageテーブルを結合したビューのようで、4つのカラムから構成されていることがわかります。
では、データを確認してみます。

spatialite> select * from tiles;
0|0|0|?
1|1|1|?
2|3|2|?
3|6|4|?
3|7|4|?
4|13|9|?
4|14|9|?
5|26|18|?
5|26|19|?
5|27|18|?
5|27|19|?
5|28|18|?
5|28|19|?
6|53|37|?
6|53|38|?

全部で42レコード(zoomlevel=7まで)存在しています。なお、カラムtile_dataは、blob(バイナリ・ラージ・オブジェクト)のためCLIでは表示できません。

spatialite_guiで表示した結果を以下に示します。

spatialite_guiでtilesテーブルのデータを確認

tilesテーブルは、ズームレベル(zoom_level)、X(tile_column)、Y(tile_row)ごとにtile_data(imageテーブルのtile_dataカラム)が管理され、tile_dataカラムにはMVT形式の地図タイルがgzip圧縮されて収容されています。
また、TileServerGLは、tilesテーブルを使って地図データを配信(HTTPリクエストへの応答)しています。

まとめ

今回は、MBTilesの内容確認ということで、周辺のデータを含めて説明しました。
MBTilesはSQLiteでMVTの集合、MVTはPBF、でもosm.pbfとは定義が異なる。。といったところで、登場人物が多くて混乱すると思います。

一見面倒なようですが、Protocol Buffersを利用してOSMやMapboxが独自の使用を作成したと理解すれば、この状況もなんとなく納得できます。

近いうちに、PythonかGoを使ってosm.pbfをパースしてみたいと思います。