🌐

GeoJSONからベクタータイルを作成してTiling Serviceから配信する

2024/04/08に公開

GeoJSONからベクタータイルを作成してTiling Serviceから配信する

はじめに

アイディオットCTOの小倉です。
今回は、GeoJSONファイルからベクタータイルを作成して、MapboxのTiling Serviceから配信する方法についてお話します。

目的

MapboxのソースとしてGeoJSONファイルを利用する場合、大量のデータを扱う場合にはパフォーマンスの問題が発生することがあります。
そのため、大量のデータを効率的に配信するためには、ベクタータイルを作成して配信する方法が有効です。
ベクタータイルとして配信することで、データの取得や描画のパフォーマンスを向上させることができます。

必要なもの

  • Mapboxのアクセストークン (後述)
  • GeoJSONファイル
    • 今回は地理院地図で作図した簡単なGeoJSONファイルをサンプルとして扱います。

アクセストークンについて

権限について

Mapboxのアクセストークンはコンソールから発行できます。
付与する権限は以下の通りです。

  • TILESETS:LIST
  • TILESETS:READ
  • TILESETS:WRITE

環境変数へのセットについて

後ほど実行するコマンドでは --token オプションによりトークンを利用することも可能ですが、環境変数へセットする場合は下記のコマンドを実行してください。

$ export MAPBOX_ACCESS_TOKEN=pk.**********

実行環境の準備

今回はDockerで実行環境を用意します。以下はdocker-compose.ymlとDockerfileの内容です。

  python:
    container_name: 'python'
    image: python
    environment:
      MAPBOX_ACCESS_TOKEN: $MAPBOX_ACCESS_TOKEN
    build:
      context: .
      dockerfile: ./Dockerfile
    volumes:
      - ./:/var/www/src
    tty: true
FROM python:3
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

RUN apt-get install -y vim less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools
RUN pip install mapbox-tilesets

# to use `tilesets estimate-area`
RUN apt-get install -y gdal-bin libgdal-dev
RUN pip install "mapbox-tilesets[estimate-area]"

# Move to Document Root
WORKDIR /var/www/src

変換について

GeoJSONファイルからベクタータイルの作成の流れは以下のようになります。

変換のフロー

(1) GeoJsonファイルをアップロードしてtileset-sourceを作成する。
(2) recipeを用意する。
(3) アップロードしたGeoJsonファイルをタイルセットに変換する。
(4) タイルセットをpublishする。
(5) 利用する。

(1) GeoJSONファイルをアップロードしてtileset-sourceを作成する。

コンテナにアクセスし、下記のコマンドでGeoJSONファイルをアップロードします。

$ tilesets upload-source [mapboxユーザー名] [任意のtileset-source名] [GeoJSONファイルのパス]

ex) $ tilesets upload-source aidiot_dev sample-source ./sample.geojson

アップロードに成功すると、tileset-sourceのIDが出力されます。

(2) recipeを用意する。

次にrecipeファイルを作成します。
こちらはどのようにtileset-sourceデータからベクターファイルを生成するかを定義したファイルになります。
recipeの中で、minzoomとmaxzoomを指定することで、どのズームレベルまで表示するかを指定することができます。
※ ただしmaxzoomを超えたら非表示となるわけではなく、overzoomにより表示は行われます。

以下の内容を sample-recipe.json として保存します。

{
  "version": 1,
  "layers": {
    "hello_world": {
      "source": "{先ほど出力されたtileset-sourceのID}",
      "minzoom": 0,
      "maxzoom": 5
    }
  }
}

注意点として、maxzoomが6以上の値は課金額に影響するため、適切な値を設定することが重要です。
課金額はこちらでシミュレーションができるので、一定のズームレベルで詳細なタイルセットを必要とする場合は事前によく検討してください。

またコンテナ内で下記のコマンドでgeojsonファイルを対象として、課金額のシミュレーションに必要な面積の見積が出ます。

# precision = 10m, 1m, 30cm, 1cm
$ tilesets estimate-area ./sample.geojson -p <precision>

ex) $ tilesets estimate-area ./sample.geojson -p 10m

{"km2": "266925", "precision": "10m", "pricing_docs": "For more information, visit https://www.mapbox.com/pricing/#tilesets"}

(3) アップロードしたGeoJsonファイルをタイルセットに変換する。

recipeを使用して、下記のコマンドでタイルセットを作成します。

$ tilesets create {mapboxユーザー名}.{任意のtileset ID} --recipe {レシピファイルへのパス} --name "{任意のtileset名}"

ex) $ tilesets create aidiot_dev.sample-tileset --recipe ./sample-recipe.json --name "sample-tileset"

(4) タイルセットをpublishする。

最後に、タイルセットをpublishします。

$ tilesets publish {mapboxユーザー名}.{任意のtileset ID}

ex) $ tilesets publish aidiot_dev.sample-tileset

無事タイルセットが作成され配信されると、mapbox Studioで確認することができ、Tileset IDも取得できます。

  • Tilesets一覧へ追加されている

mapbox Studioのタイルセット一覧

  • 詳細を見ると、見づらいですが、サンプルで作成した矩形がmap上に表示されています。

mapbox Studio map上でのサンプル表示

(5) 利用する。

以下は作成したタイルセットの利用の実装例になります。

map.addSource('sample-source-id', {
  type: 'vector',
  url: 'mapbox://{Tileset ID}',
})

map.addLayer(
  {
    id: 'sample-layer-id',
    type: 'fill',
    source: 'sample-source-id',
    'source-layer': 'sample_tileset', // source-layerはrecipeで指定したレイヤー名 
    paint: {
      'fill-color': '#ff0000',
      'fill-opacity': 0.5,
    },
  },
  'waterway-label',
)

map上でのサンプル表示

まとめ

というわけでGeoJSONファイルからベクタータイルを作成し、Tiling Serviceから配信する方法をご紹介いたしました。
今回は手動により行いましたが、自動化も可能かと思います。

以前、こちらの記事でGeoJSONの生成方法をご紹介いたしましたが、
合わせることでシステム上からアップロードしたshapefileをGeoJSONに変換し、ベクタータイルとして配信することが可能となるかもしれません。

アイディオットではGISを開発したいエンジニアを募集中!

AI・データ利活用をリードし、世界にインパクトを与えるプロダクトを開発しませんか?

アイディオットでは、今後の事業拡大及びプロダクト開発を担っていただけるエンジニアチームの強化を行っております。
さらに会社の成長を加速させるため、フロントエンドエンジニア、バックエンドエンジニア、インフラエンジニアのメンバーを募集しております!
日本を代表する企業様へ自社プロダクトを活用した、新規事業コンサルティング、開発にご興味のある方はお気軽にご連絡ください。

【リクルートページ】
https://aidiot.jp/recruit/
【募集ポジション一覧】
https://open.talentio.com/r/1/c/aidiot/homes/3925
【採用についてのお問合せ先】
株式会社アイディオット 採用担当:佐藤
メールアドレス:recruit@aidiot.jp

今回の記事の参考サイト

Discussion