0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MapLibreでPMTiles形式の町丁目ベクトルタイルを表示してみる

Posted at

はじめに

TerraMap APIでも利用している町丁目ポリゴンを、tippecanoeでPMTiles形式に変換し、Web地図上に表示してみることにしました。作成したPMTilesファイルについては、MapLibreでOpenStreetMap上に表示しています。

PMTilesとは

単一ファイル形式のタイルデータです。種類には背景地図、ベクトルタイル、画像等があり、S3のようなストレージサービスにホストすることができます。サーバープログラムは不要で、低コストでタイルデータを提供することができるとされています。

PMTilesファイル作成

以下の手順で、町丁目ポリゴンのGeoJSONファイルからベクトルタイルのPMTilesファイルを作成しました。作業OSはWindowsで、GitやDockerが使えることが前提の手順になります。

  1. tippecanoeのソースを取得
    最新tippecanoeのDockerイメージが共有されているかは分からなかったので、まず現在も更新され続けている以下のソースを取得しました。
    https://github.com/felt/tippecanoe

  2. Dockerイメージのビルド
    READMEに従って、Dockerイメージのビルドから実行していきます。

    docker build -t tippecanoe:latest .
    
  3. コンテナの起動

    docker run --name pmtiles-conv -it ^
    -v {ホスト側の作業ディレクトリパス}:/data ^
    tippecanoe:latest
    
  4. GeoJSONをPMTilesへ変換

    tippecanoe -zg -pk -pn -l chomoku-layer -o /data/chomoku.pmtiles /data/chomoku.geojson
    

    tippecanoeのオプションについてはケースバイケースと思いますが、今回は以下を使用しています。

    オプション 概要
    -zg ズームレベル0から妥当な最大ズームレベルまでのタイルを作成
    -pk タイルを500Kバイトに制限しない
    -pn フィーチャ間で共有しているノードは簡素化しない
    -l -l {レイヤー名} でレイヤー名を指定
    ※ 省略した場合はGeoJSONのファイル名になる
    -o -o {ファイル名} で出力ファイル名を指定

    処理の結果、980MBあったGeoJSONが、77MBのPMTilesに変換されました。

MapLibreでのPMTiles表示処理

この記事ではMapLibreでPMTilesを表示させる方法を知りたいので、ローカルにPMTilesファイルを置いて確認しました。ソースは以下のようになりました。

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>MapLibreで町丁目ポリゴンのPMTilesを表示</title>
    <script src="https://unpkg.com/maplibre-gl@4.7.0/dist/maplibre-gl.js"></script>
    <link
      href="https://unpkg.com/maplibre-gl@4.7.0/dist/maplibre-gl.css"
      rel="stylesheet"
    />
    <script src="https://unpkg.com/pmtiles@3.2.0/dist/pmtiles.js"></script>
  </head>
  <body>
    <div id="map" style="width: 100%; height: 95vh"></div>
    <script>
      const protocol = new pmtiles.Protocol();
      maplibregl.addProtocol("pmtiles", protocol.tile);

      const map = new maplibregl.Map({
        container: "map",
        center: [139.66204291, 35.67260863],
        zoom: 10,
        maxZoom: 17,
        style: {
          version: 8,
          sources: {
            osm: {
              type: "raster",
              tiles: ["https://tile.openstreetmap.org/{z}/{x}/{y}.png"],
              tileSize: 256,
              attribution:
                '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
            },
          },
          layers: [
            {
              id: "osm-layer",
              source: "osm",
              type: "raster",
            },
          ],
        },
      });

      map.addControl(new maplibregl.NavigationControl());

      map.on("load", function () {
        map.addSource("mvt_data", {
          type: "vector",
          tiles: [
            `pmtiles://chomoku.pmtiles/{z}/{x}/{y}`,
          ],
          minzoom: 0,
          maxzoom: 11,    // タイルがある最大ズームレベルを設定
        });

        map.addLayer({
          id: "mvt_polygon",
          type: "fill",
          source: "mvt_data",
          "source-layer": "chomoku-layer",   // PMTilesのレイヤー名
          layout: {},
          paint: {
            "fill-color": "#7fffd4",
            "fill-opacity": 0.2,
          },
        });

        map.addLayer({
          id: "mvt_line",
          type: "line",
          source: "mvt_data",
          "source-layer": "chomoku-layer",   // PMTilesのレイヤー名
          layout: {},
          paint: {
            "line-color": "#2e8b57",
            "line-width": 0.5,
          },
        });
      });
    </script>
  </body>
</html>

詳細① PMTilesを扱うにはpmtiles.jsを利用します。

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

PMTilesをロードするためのプロトコルを追加します。

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

詳細② tilesのURLは、プロトコル名pmtilesを先頭に付与し、pmtiles:PMTilesファイルのURL/{z}/{x}/{y}という形式で指定します。

tiles: [
  `pmtiles://chomoku.pmtiles/{z}/{x}/{y}`,
],

町丁目ポリゴンの表示結果

実際に町丁目ポリゴンを表示した例が以下になります。
pmtiles_polygons.gif
ローカル環境ではありますが、静的なファイルなのでパフォーマンスに優れているのが分かると思います。
町丁目ポリゴンをFlatGeobuf形式に変換したこともありますが、それと比べても高速でメモリ使用量の心配もほとんどありません。これはtippecanoeによるズームレベルに応じたポリゴンの簡素化に起因していると思われます。

その他の参考情報

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?