🌏

tilemaker で vector tile を self hosting

2023/12/16に公開

https://github.com/systemed/tilemaker

tilemaker というツールで vectortile を生成をして自前で hosting する練習。

https://qiita.com/Kanahiro/items/6a98ee285d3de7ac61fc

動く手順を記録。

  • memory 16G くらい

いちおう gh-pages で self-host するところまでたどり着いてた

sample repository
https://github.com/ousttrue/map_sample

gh-pages

https://ousttrue.github.io/map_sample/

このリポジトリの説明。
さすがに gh-action でマップタイトルを生成するのは無謀なので、
pubilc/tiles に gzip で圧縮された maptile をコミットしている。
gh-action で gzip を解凍している。
(完全に海の tile がサイズ0 なのに注意)

https://github.com/ousttrue/map_sample/blob/master/.github/workflows/build.yml

走り書き

https://ousttrue.github.io/posts/2024/0122-vectortile/

config-example.json 最小限の動作確認

vector tile を生成

ビルド済みの tilemaker を入手

https://github.com/systemed/tilemaker/releases

プラットフォームに合わせて適当に。

元データを入手

https://download.geofabrik.de/asia

から

japan-latest.osm.pbf をダウンロードしました(2G弱)。

tilemaker を実行する

4つの引数があります。

  • input: japan-latest.osm.pbf です
  • output: 出力ディレクトリを指定します。無くても作ってくれます。
  • config: tilemakerの resources/config-example.json
  • process: tilemakerの resources/process-example.lua
# powershell の例
PS1> .\tilemaker\build\RelWithDebInfo\tilemaker.exe --input .\japan-latest.osm.pbf --output example --config .\tilemaker\resources\config-example.json --process .\tilemaker\resources\process-example.lua

i7 + memory 16G で 20分くらいかかった。
zoomlevel 12,13,14 が生成されていて、それぞれの容量は以下の通り。zoom するごとに 2倍に増える?

  • 12 => 127 MB
  • 13 => 245 MB
  • 14 => 555 MB

生成した vector tile を使う

構成

+ example
  + 12
  + 13
  + 14
+ index.html
+ main.ts
+ package.json
> npm init -y
> npm install -S vite typescript maplibre-gl
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <title>map</title>
    <style>
      #map {
        width: 500px;
        height: 500px;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script type="module" src="main.ts"></script>
  </body>
</html>
import maplibregl from 'maplibre-gl';

document.addEventListener("DOMContentLoaded", async (event) => {

  const port = location.port
    ? (':' + location.port) : '';
  const baseUrl = `${location.protocol}//${location.hostname}${port}`;

  new maplibregl.Map({
    container: 'map',
    style: {
      "version": 8,
      "name": "Basic",
      "sources": {
        "openmaptiles": {
          "type": "vector",
          "tiles": [`${baseUrl}/example/{z}/{x}/{y}.pbf`] // 👈 tilemaker の生成物
        }
      },
      "layers": [
        {
          "id": "background",
          "type": "background",
          "paint": { "background-color": "hsl(47, 26%, 88%)" }
        },
        {
          "id": "transportation",
          "type": "line",
          "source": "openmaptiles",
          "source-layer": "transportation",
          "layout": { "visibility": "visible" },
          "paint": {
            "line-color": "hsl(34, 12%, 66%)",
            "line-opacity": {
              "base": 1,
              "stops": [
                [11, 0],
                [16, 1]
              ]
            }
          }
        },
      ],
    },
    center: [139.7024, 35.6598],
    zoom: 14,
    minZoom: 12,
    maxZoom: 14,
  });
});

動作確認

> npx vite

背景色しか出ない。

gzip 圧縮への対処

console を見ると pbr の parse error が。
どうも gzip に圧縮されているらしい。

Unable to parse the tile at http://xxx/{zoom}/{x}/{y}.pbf, 
please make sure the data is not gzipped and that you have configured the relevant header in the server

確かに。

> D:\msys64\usr\bin\file.exe .\example\14\13788\7042.pbf
.\example\14\13788\7042.pbf: gzip compressed data, from TOPS/20, original size modulo 2^32 141

tilemaker/resources/config-example.json

{
	"layers": {
		"waterway": { "minzoom": 11, "maxzoom": 14 },
		"transportation": { "minzoom": 12, "maxzoom": 14, "simplify_below": 13, "simplify_level": 0.0001, "simplify_ratio": 2.0 },
		"building": { "minzoom": 14, "maxzoom": 14 },
		"poi": { "minzoom": 13, "maxzoom": 14 }
	},
	"settings": {
		"minzoom": 12,
		"maxzoom": 14,
		"basezoom": 14,
		"include_ids": false,
		"name": "Tilemaker example",
		"version": "0.1",
		"description": "Sample vector tiles for Tilemaker",
		"compress": "gzip", // 👈 これ
		"metadata": {
			"json": { "vector_layers": [
						{ "id": "transportation",     "description": "transportation",     "fields": {"class":"String"}},
						{ "id": "waterway",     "description": "waterway",     "fields": {"class":"String"}},
						{ "id": "building", "description": "building", "fields": {}}
					] }
		}
	}
}

*.pbf*.pbf.gz にリネーム。

# powershell でまとめてリネームする例
> cd .\example\
example> Get-ChildItem -Recurse "*.pbf" | ForEach-Object {Move-Item $_ "$_.gz"}

style.sources を書き換え

  new maplibregl.Map({
    container: 'map',
    style: {
      "version": 8,
      "name": "Basic",
      "sources": {
        "openmaptiles": {
          "type": "vector",
          "tiles": [`${baseUrl}/example/{z}/{x}/{y}.pbf.gz`] // 👈 .pbf.gz

動きました。

おそらく example を openmaptiles に変えて、
長い style.json を既存の地図から頂いてくればそれなりの地図が出ると思われます(まだやっていない)。

config-openmaptiles.json

動作確認ができたので今度は、config-openmaptiles.json やってみます。

手順は、こちらにあります。

https://blog.kleunen.nl/blog/tilemaker-generate-map

海岸データの取得

https://osmdata.openstreetmap.de/data/water-polygons.html

から

water-polygons-split-4326.zip

をダウンロードします。
解凍してフォルダ名を coastline に変えます( config-openmaptiles.json の記述に合わせる )。

# powershell の例
PS1> .\tilemaker\build\RelWithDebInfo\tilemaker.exe --input .\japan-latest.osm.pbf --output openmaptiles --config .\tilemaker\resources\config-openmaptiles.json --process .\tilemaker\resources\process-openmaptiles.lua

0 ~ 14 zoom が生成されました。

生成した vector tile を使う(openmaptiles)

前回の実験の tiles パスだけ変更

動いた。
しかし、スタイルが無いので表示は同じ。

font 入手

git clone https://github.com/klokantech/klokantech-gl-fonts fonts

style 入手

https://openmaptiles.org/styles/#maptiler-basic

から

MapTiler Basicstyle.json を入手。

https://github.com/openmaptiles/maptiler-basic-gl-style

2か所修正します。

const port = location.port
  ? (':' + location.port) : '';
const baseUrl = `${location.protocol}//${location.hostname}${port}`;

const tiles = `${baseUrl}/openmaptiles/{z}/{x}/{y}.pbf
const glyphs = `${baseUrl}/fonts/Klokantech {fontstack}/{range}.pbf`

海岸線、フォント付きで動作しました。

trouble

フォントの設定ミスがある場合・・・

console に次のエラーがでました。

unimplemented type: 4

network を見ると 404。

Discussion