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?

MartinでGeoParquetからMVTを配信する

0
Posted at

はじめに

Martinのv2.0からDuckDB GeoParquetソースが追加されました。

これは、DuckDB経由でGeoParquetから動的にMVTを生成して配信する機能です。

本記事では、この機能について紹介したいと思います。

DuckDBソース機能オプションをつけてMartinをビルドする

こちらに記載があるとおり、本機能は現在unstableであるため、デフォルトビルドには含まれていません。

試すには、unstableフィーチャオプションをつけてビルドする必要があります。

私のWSL(Ubuntu)の環境では、依存解決のため、事前にいくつかパッケージをインストール必要がありました。

それと合わせて実行すると以下のようになります。

sudo apt update

sudo apt install -y \
  build-essential \
  pkg-config \
  libssl-dev \
  clang \
  cmake \
  libcurl4-openssl-dev \
  libjpeg-dev \
  libpng-dev \
  libuv1-dev \
  libwebp-dev \
  glslang-dev \
  spirv-tools
  
cargo install martin --locked --features=unstable-duckdb

動作確認用に国土数値情報の学校データを準備

以下からデータをダウンロードします。

文字コードがShift-JISになっているため、UTF-8に変換します。

また、座標系がJGD2000のため、WGS84に変換しておきます。

変換にはogr2ogrを使い、GeoJSONとして出力します。

ogr2ogr \
  -f GeoJSON \
  schools.geojson \
  P29-13.shp \
  -oo ENCODING=CP932 \
  -s_srs EPSG:4612 \
  -t_srs EPSG:4326

GeoParquetに変換

DuckDBを使って、GeoParquetに変換します。

DuckDBの最新版をインストールします。

curl https://install.duckdb.org | bash

GeoParquetを作成する際のrow groupサイズの参考にするため、データの件数を調べておきます。

duckdb
INSTALL spatial;
LOAD spatial;

SELECT COUNT(*) FROM ST_Read('schools.geojson');
> 39689

約4万件のため、GeoParquetのrow groupを5000件ずつで8グループに分割することにします。

row group pruningの効果を最大化するため、ヒルベルト順にソートして空間的に近い地物が連続して並ぶようにします。

COPY (
    SELECT *
    FROM ST_Read('schools.geojson')
    ORDER BY ST_Hilbert(geom)
)
TO 'schools.parquet'
(
    FORMAT PARQUET,
    GEOPARQUET_VERSION 'V2',
    COMPRESSION 'ZSTD',
    ROW_GROUP_SIZE 5000
);

Martin設定ファイル(config.yaml)を作成

Martinの設定ファイルにDuckDBソースの設定と定義を記載します。

書き方はこちらを参照します。

duckdb:
  pool_size: 4
  threads: 2
  memory_limit_mb: 1024
  auto_bounds: quick

  sources:
    - geoparquet: schools.parquet
      layer_id: schools
      geometry_column: geom
      srid: 4326
      minzoom: 0
      maxzoom: 14
      extent: 4096
      buffer: 64
      clip_geom: true

Martin起動

以下のコマンドでMartinを起動します。

martin --config config.yaml

タイルリクエストのエンドポイントは次のようになります。

http://localhost:3000/schools/{z}/{x}/{y}

MapLibreで可視化してみる

MapLibre GL JSで、例えば、以下のようにMapオブジェクトを作成するとOpenStreetMapsをベースマップとしつつ学校のポイントデータを表示できます。

const map = new Map({
  container: 'map',
  hash: true,
  style: {
    version: 8,
    glyphs: 'https://tile.openstreetmap.jp/fonts/{fontstack}/{range}.pbf',
    sources: {
      basemap: {
        type: 'raster',
        tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
        tileSize: 256,
        maxzoom: 19,
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap contributors</a>'
      },
      schools: {
        type: 'vector',
        tiles: ['http://localhost:3000/schools/{z}/{x}/{y}'],
        minzoom: 0,
        maxzoom: 14,
        attribution: "<a href=\"https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-P29.html\" target=\"_blank\">国土数値情報-学校データ</a>"
      }
    },
    layers: [
      {
        id: 'basemap',
        type: 'raster',
        source: 'basemap',
        paint: {
          'raster-opacity': 0.3
        }
      },
      {
        id: 'schools',
        type: 'circle',
        source: 'schools',
        'source-layer': 'schools',
        paint: {
          'circle-radius': 5,
          'circle-color': '#e63946'
        }
      },
      {
        id: 'school-labels',
        type: 'symbol',
        source: 'schools',
        'source-layer': 'schools',
        minzoom: 13,
        layout: {
          'text-field': ['get', 'P29_005'],
          'text-font': ['Noto Sans JP Regular'],
          'text-size': 12,
          "text-variable-anchor": ["top", "left"],
          "text-justify": "auto",
          "text-radial-offset": 0.5
        },
        paint: {
          'text-color': '#222222',
          'text-halo-color': '#ffffff',
          'text-halo-width': 1.5
        }
      }
    ]
  },
  center: [139.767125, 35.681236],
  zoom: 10
});

ブラウザで確認すると以下のような表示になります。

MapLibreで可視化

ローカルで動かしているというのもありますが、このくらいのデータであればほとんど間断なく表示されます。

まとめ

GeoParquet対応はリリースされたばかりで、unstable機能の位置づけであるため、現状ではテスト的に使うのが無難かと思われます。

しかしながら、事前にタイル化しておく必要がなく、データベースも必要ないため、管理コストや性能などの観点で非常に有用な機能になる可能性があります。

今後の動向を注視しながら実際の運用に耐えうる機能になるか引き続き検証していきたいと思います。

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?