背景

地理、楽しいっすよね。めっちゃ好きです。
でも Google Maps って使うと、結局は Google って会社にお世話になってるわけですよ。

僕はこの「どっかの会社のお世話になっている状態」があまり好きではない。
だからサーバやデータセンターも自前運用するし、
Slack の代わりに Rocket.Chat を使うし、
JIRA ではなく Redmine を使うんです。

じゃあ Google Maps を自前で運用するにはどうするか?
これが今回のテーマです。


地図アプリがどうやって動いているか

必要なものは大きく分けて二つ。

  1. レンダリングエンジン(地図を描画するライブラリ)
  2. マップデータ(地図そのもののソース)

OSSのレンダリングエンジン(ライブラリ)

それぞれでベースマップを比較できるデモも作りました。
👉 比較サイト

OSSのマップデータ

選択肢は色々あります。

  • OpenStreetMap (OSM)
    世界中のボランティアが作る地図データ。ラスタ(画像タイル)も配布されているが、見た目は少し古臭い。
    実際の中身はベクタだが、配信されている地図はあらかじめ描画されているラスタタイル。(元がベクタならそれを出せばいいじゃん、、とは思った)

  • OpenMapTiles
    OSMデータをベクトルタイル化するOSS。
    これを使えば、Google Maps 並みにきれいなベクトル地図を完全自前で運用できる。


ラスタはやっぱり綺麗に映らないですね。なのでベクトルマップが欲しいのですが、 ベクトルマップは自分で作るしかないっぽいです。(Maptilerって会社がOSMを所有しようとしているので気をつけて)

実際に OSM → Vector Map を自前ホストする流れ

1. OSMデータのダウンロード

Geofabrik から地域ごとの .osm.pbf を落とす。

例: 日本全体
https://download.geofabrik.de/asia/japan.html

2. OpenMapTiles でベクトルタイル生成

まずは GitHub から OpenMapTiles を取得します。

# クローン
git clone https://github.com/openmaptiles/openmaptiles.git
cd openmaptiles
Docker を使ってインポートと生成。
# OSMデータをPostGISに取り込み
make import-osm DOWNLOAD_PBF=data/japan-latest.osm.pbf

# 1) 外部ベースデータ(未実行なら)
make import-data

# 2) スキーマ生成 & 適用(これが getmvt をDBに作る)
make build-sql       # (通常 import-sql 実行時に自動生成されますが、明示でOK)
make import-sql

# 3) ベクタマップを生成
BBOX=122,20,154,46 MAX_ZOOM=13 MBTILES_FILE=japan.mbtiles make generate-tiles-pg

これで、japan.mbtilesというラスタマップが入ったファイルが生成されます。 ちなみに、ZOOMレベルは10とかだと5分で生成が完了しますが、 14にすると、12時間 15にすると、2日 かかります。 ちなみに、google mapsはzoom level 21までサポートしているけど、ぶっちゃけここまではいらん。 16くらいで十分。 しかし、18まであると最高です。とは言っておこう。17まで行けば、マジでgoogle mapsと遜色ないレベルまでいける。まあこれ結構厳しいのだがね笑

ちなみに、Zが一段上がると、タイル数は4倍になる。1タイルを4つに分割する感じだね。

ただ、ほとんど何もない北海道とかをどんなに細かく制度よく出力しても勿体無いですよね? ってことで、実は部分的に15階層とか16をOKにして、マージすることができるんですね。これはすごい。

BBOX の形式: minLon,minLat,maxLon,maxLat 例:東京23区近辺

139.55,35.50,139.95,35.90
# 東京エリアだけ z15
BBOX=139.55,35.50,139.95,35.90 \
MAX_ZOOM=15 \
MBTILES_FILE=tokyo.z15.mbtiles \
make generate-tiles-pg
tile-join -o japan_merged.mbtiles \
  --no-tile-size-limit \
  japan.z14.mbtiles \
  tokyo.z15.mbtiles

Dockerバージョンはこんな感じ

docker-compose run --rm openmaptiles-tools \
  tile-join -o /data/japan_merged.mbtiles /data/japan.z14.mbtiles /data/tokyo.z15.mbtiles

おまけ:生成の過程で何が行われているのか

Geofabrik で落ちてくるものは?

👉 生の OSM データ(.osm.pbf)だけです。

中身は 道路・建物・POI・地名・行政境界・自然地物など、世界中のボランティアが OSM に入れているすべてのタグ付きジオメトリ。 「地形だけ」ではなく、ほぼすべてのベクトル情報が入ってます。 例:

  • 高速道路から小道まで
  • 鉄道・飛行場
  • 建物ポリゴン
  • POI(レストラン、学校、寺社…)
  • 水域(湖、河川、海岸線)
  • 行政境界
  • 山のピーク
  • 住所・ house number
  • place=city/town/village などの地名ラベル

ただし 「どうレイヤーに分けて、どのズームで出すか」情報は一切入っていない。 → これを与えるのが OpenMapTiles の YAML/SQL スキーマ。(ここポイント)

OpenMapTiles 側がやっていること

OpenMapTiles (OMT) は「OSM の生データ」を PostgreSQL/PostGIS に入れて、ズーム別にどのデータを出すかを SQL で定義しています。 その設計をまとめているのが openmaptiles.yaml と各 layers/**.yaml + SQL スクリプトです。

代表的なレイヤー:

  • water / waterway → 海・湖・河川
  • landcover / landuse / park → 森林、農地、公園など
  • mountain_peak → 山頂ポイント
  • boundary → 行政境界
  • aeroway → 空港滑走路
  • transportation → 道路・鉄道
  • building → 建物
  • water_name / transportation_name / place → ラベル類
  • housenumber → 番地
  • poi → 各種ポイント(レストラン、コンビニ、寺など)
  • aerodrome_label → 空港ラベル

これらは 全部 OSM のタグから SQL で抽出しているだけ。 たとえば building なら「WHERE building IS NOT NULL」のような抽出をして、ズーム別に ST_Simplify していたりします。

3. 配信

./dataにjapan.mbtilesを入れておきます。

docker run -d --name tileserver   -v "$PWD/data:/data"   -p 10008:8080   maptiler/tileserver-gl

参考

OpenStreetMaps(地図界隈の始祖みたいな存在。)

geofabrik(OSMを毎日更新してデータにしてくれているやつ)

Yahoo Maps(Map Box + OSMから生成したラスタ使ってるだけ笑)

Google Maps

Maputnik

おまけ

Maputnikについて。

🖌 Maputnikとは?

Mapbox Style Spec 準拠のスタイルエディタ(OSS)。

Webブラウザ上で動いて、手元やリモートの ベクトルタイルサーバ(TileJSONやmbtiles) を読み込んで、 レイヤーの色・線の太さ・ラベルの表示方法などをGUIで編集できる。

前提知識

.mbtiles → 中身は OSM由来のベクトルデータをタイル化したもの(道路・建物・水系などレイヤごとにズーム別で格納)。 → これは「素材集」とか「生データの倉庫」。

style.json → Mapbox Style Spec 準拠の「CSSみたいなもの」。 → 「道路は白線」「公園は緑」「水色はラベルつける」とか、見た目のルールを記述するだけ。 → .mbtiles の内容は変えずに、スタイルを切り替えるだけで「Google Maps風」「ダークモード」「航空図っぽい」など自在に表現できる。

ということで、mautnikでは、このstyle.jsonを自分好みに作ることができます。

作ったスタイルは style.json として出力できて、MapLibreGL / OpenLayers / MapboxGL でそのまま使える。

👉 要するに 「Illustratorで地図のデザインする」感覚で、タイルの見た目を自由にいじれるツール です。 OSSだから、商用の Mapbox Studio を使わずに済むのが大きい。

使い方の例

make start-maputnik

→ http://localhost:8088 にブラウザでアクセス → データソースに http://localhost:8090/data/v3.json (postserveのTileJSON URL)を指定 → 編集して保存すると style.json が出てきて、MapLibre に食わせれば完成。

実際、openmaptilesに入ってる。

ray@kong:~/Map/tileserver-gl/openmaptiles$ cat Makefile | grep maput
  make start-maputnik                  # start Maputnik Editor + dynamic tile server [ see $(OMT_HOST):8088 ]
  make stop-maputnik                   # stop Maputnik Editor + dynamic tile server
	@echo "*     --> can view it locally (use make start-maputnik)"
	@echo "*     --> or can use https://maputnik.github.io/editor"
.PHONY: start-maputnik
start-maputnik: stop-maputnik start-postserve
	@echo "* Start maputnik/editor "
	$(DOCKER_COMPOSE) up -d maputnik_editor
.PHONY: stop-maputnik
stop-maputnik:
	-$(DOCKER_COMPOSE) stop maputnik_editor
	@docker images "maputnik/editor" -q               | $(XARGS) docker rmi -f

OSMについて

運営母体: イギリスに本部を置く OpenStreetMap Foundation (OSMF) という非営利組織が法的な管理をしています。 → ただし OSM の実態は「世界中のボランティア・自治体・研究者・企業」が共同で編集・利用している、Wikipedia 的な存在です。

データ作成者:

個人ユーザー(徒歩で歩きながらGPSログを取る人、ドローンで撮影する人など)

行政(自治体や国のオープンデータ)

企業(Mapbox, Meta, Microsoft, Grab, Apple などが積極的に編集)

資金: OSMFは寄付で運営されています。サーバー代とか基盤維持のために世界中の企業や個人から寄付を募っている。 (Microsoft, Facebook, Amazon, Mapbox, Foursquare, Grab, などの企業がスポンサー)

Google Mapsはどうなっているのか?

Googleは基本的に「完全クローズド」な巨大システムです。OSMと真逆。

独自データ収集網

「Google Street Viewカー」🚙:世界中を走り回って道路を撮影 & GPS測位。

「衛星画像」🛰️:Googleは衛星データのライセンスを購入し、地図生成に使っている。

「Androidスマホ」📱:ユーザーの位置履歴(交通量・渋滞情報)を匿名統計として収集。

提携:一部は国や企業の地図データを購入。

内部の地図チーム

数千人単位のスタッフがデータを整理・修正。

機械学習で建物の形を抽出、AIで道路ネットワークを認識。

ビジネスモデル

Google Maps API は商用利用だと有料。

広告(検索で出てくる店舗情報)と連携して莫大な収益源に。

結論

OSS最高!会社はF