6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PMTiles ベクトルタイル読み込みを観察する

Last updated at Posted at 2023-01-10

はじめに

PMTilesを使ったウェブ地図を作成することをためすこと、またタイルのZXYの範囲がどのようにリクエストされているかを確認すること、が必要だったので実験してみました。

記録をメモしておきます。

環境

  • GitHub ページ
  • Google Chrome
  • Windows Powershell

やったこと

1. PMTilesを使ったWeb地図をつくる(MapLibre GL JS)

通常のMapLibre GL JSでのウェブ地図作成に、以下のような手順を加えます。

htmlファイルのheadに以下を追加

<script src="https://unpkg.com/pmtiles@2.5.0/dist/index.js"></script>

そして、htmlファイルのbody、script内に以下を追加

let protocol = new pmtiles.Protocol();
maplibregl.addProtocol("pmtiles",protocol.tile);

スタイルJSON中のソースの書き方をURLで以下のように書く(以下の例は https://ubukawa.github.io/109/test123.pmtiles を使う場合 )

"url": "pmtiles://https://ubukawa.github.io/109/test123.pmtiles"

実際に作ったhtmlファイルはこちら: https://github.com/ubukawa/109/blob/main/map/map.html
実際に作ったスタイルファイルはこちら: https://github.com/ubukawa/109/blob/main/map/style1.json

これでPMTilesのベクトルタイルが見られます。
https://ubukawa.github.io/109/map/map.html
image.png

2. PMTilesへのアクセスを観察

作ったマップをGoogle Chromeでひらき、F12の開発者モードでPMTilesへのアクセスを観察します。
image.png

  • 発見 1:pmtilesの取得は206のステータス。これはリクエストヘッダに書いてある通りにPartial Contentの取得が成功したということらしい。なるほど。
  • 発見 2:プロトコルはh2を使えている。

さらに、リクエストヘッダを見てみる。if-rangeとrangeというものがあるようだ。。
image.png

  • 発見 3:if rangeは共通で、rangeが所定のタイルに相当するようだ。if-rangeについて調べると、前に断片を受け取ってからデータが変わったかを確認するための情報らしい。なので、データベースが更新されていなければそのままなのだろう。
    image.png

  • 疑問 1: あるタイルのデータ範囲がどこからどこにあるというのはどこに書いてあるのだろう???

  • 発見 4: リクエストの中にはif-range がないものもある。一番最初に読んだものにはif-rangeがないのかもしれない。これは0からでないrangeなので理由がよくわからない。
    image.png

  • 発見 5: もう一度やってみたところ、最初のリクエストは、rangeのバイトが0から始まっている。if-rangeはない。
    image.png

なお、二番目になると、if-rangeがついている。
image.png

  • 発見 6: 最初のリクエストで得られたデータはほかのリクエストに比べてデータサイズが小さい。
    image.png

初期ズームレベルが1の地図で、最初によまれる5つのPMTilesの断片について、rengeとコンテンツ長をみたら以下の通りであった:

  1. bytes=0-16383, 16384
  2. bytes=356261-765489, 409229
  3. bytes=24447-260732, 236286
  4. bytes=308376-356260, 47885
  5. bytes=260733-308375, 47643
  • 発見 7: 上記、2~5のPMTilesの断片は、もともとのデータの 1/x/y.pbf シリーズ(4つ)にサイズがよく似ている。
    image.png
    image.png

  • 推測 1: そうすると、bytes=0-16383 の範囲が、タイル分布のマッピングというか、どのタイルがどのデータ長かを書いてあるものだと思われる。WindowsPowershell の curl.exeで見てみた。

curl.exe https://ubukawa.github.io/109/test123.pmtiles -i -H "Range: bytes=0-16383"

↓バイナリーなのでファイルが見られない。(--outputオプションでテキストに出力しても読めない。)
image.png

最初に読まれるPMtilesの断片(bytes=0-16383)は、PMTiles共通で、各タイルのデータ長が含まれるという仮説を強化すべく、別のPMTiles地図を観察した。
@hfu さんの https://x.optgeo.org/zoomstack/ を開く。
image.png

  • 発見 8: ここでも最初に読まれているPMTiles の rangeが bytes=0-16383 であることが分かった。ヘッダ情報というか、メタデータというか、この部分に各タイルのデータ長が記載されているのではないかと思われる。
    image.png

まとめ

  • GitHubページで静的にホストしているPMtilesは、MapLibre GL JSで簡単に読めることが分かった。
  • PMTilesを読み込むとき:
    • range をしてしたリクエストで部分的に読み込みをしている(206)。if-range を使って、データが更新されていないかもチェックしている。
    • リクエストヘッダのなかに、x,y,zのタイル番号はない。あるのはrangeだけ。
    • タイルごとのデータ長は、おそらく最初のPMTilesへのアクセス (bytes=0-16383)で情報を得ているようだ。16384という数字がキーポイント。

参考ページ

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?