国土数値情報の地図データはなぜ簡素化が必要なのか — 237MBのポリゴンとブラウザのOOM

queria

ウェブアプリで日本地図の塗り分け(コロプレス図)を表示するには、都道府県や市区町村の境界ポリゴンが必要です。国土交通省の「国土数値情報」が提供する行政区域データ(N03)は、国土地理院の基盤地図情報を元に作成された公的データソースで、GeoJSON/Shapefile/GML形式で無償公開されています。

QGISなどのデスクトップGISであればこのデータをそのまま扱えますが、QueriaのようにDuckDB WASM・Observable Plot・MapLibreでブラウザ描画する場合、メモリ不足で描画できません。Queriaでは行政区域データをnlftp.boundaryスキーマで提供していますが、公開にあたって簡素化処理が必要でした。この記事は、ウェブGISやデータパイプラインに関わるエンジニアに向けて、なぜ簡素化が必要なのか、どのような手法を組み合わせたのかを解説します。

課題: フル解像度のポリゴンはブラウザに載らない

国土数値情報 N03 の行政区域データは、全国で約12万の個別ポリゴンから構成されています。離島や入り江ごとに1つのポリゴンがあり、市区町村単位に結合すると頂点数1,541万、WKB 237MBに達します。

このデータをブラウザ上のDuckDB WASMで集計処理を行ったところ、Out of Memoryが発生しました。フル解像度のポリゴンデータをメモリ上に展開し、さらにST_AsGeoJSONでGeoJSON文字列(約573MB)に変換する過程で、WASMのメモリ上限に達したと考えられます。

2つの簡素化手法とその効果

市区町村単位に結合したフル解像度データ(237MB)に対して、頂点間引きと小島除去の効果を比較しました。

手法 WKB サイズ 削減率
簡素化前 237 MB -
頂点間引きのみ 13 MB 95%
小島除去のみ 187 MB 21%
両方 3.6 MB 98.5%

頂点間引き(ST_CoverageSimplify)が主力で、95%を削減します。一方、小島除去だけでは21%しか減りません。小島は数は多くても、1つあたりの頂点数が少ないためです。

ただし、頂点間引き後の13MBのうち大部分は、間引いても残る大量の小島ポリゴン(各3〜4頂点)が占めています。小島除去を組み合わせることで、13MB → 3.6MBへの削減が実現します。

以下は頂点間引きのみを適用した地図です。本土の海岸線は滑らかになっていますが、小島・岩礁が大量のドットとして残っていることがわかります。

長崎県周辺にズームすると、五島列島の周囲に無数の小さなポリゴンが散在しています。これらがサイズの大部分を占めており、地図の視認性にも寄与していません。

解決策: 小島除去 → カバレッジ簡素化

隣接境界の一貫性: ST_CoverageSimplify

小島除去後の頂点間引きには、ST_SimplifyPreserveTopologyではなくST_CoverageSimplifyを使用しています。

ST_SimplifyPreserveTopologyは各ポリゴンを独立に簡素化します。隣接する市区町村は境界線を共有していますが、独立に簡素化すると共有境界がそれぞれ異なる形に変形し、隙間や重なりが発生します。

ST_CoverageSimplify(GEOS CoverageSimplifier)は、全ポリゴンの隣接関係を考慮し、共有境界を一貫して簡素化します。隙間が生じません。DuckDB 1.4.4 以降の Spatial 拡張で使用できます。

最終的な処理フロー

  1. ST_Dump + ST_Area フィルタ: 面積が極小の小島を除去
  2. ST_CoverageSimplify: 全市区町村を一括で簡素化(隣接境界の一貫性を保持)

小島除去を先に行うのは、フル解像度の正確な面積で小島を判定するためです。簡素化後に除去しても結果はほぼ同じですが、判定根拠が明確な方を採用しています。

都道府県境界は、簡素化済みの市区町村境界を dissolve して導出します。市区町村レベルで隣接境界が一致しているため、都道府県境界も自動的に正確になります。

同じ長崎県周辺で小島除去 + カバレッジ簡素化後の地図を確認します。無数のドットが消え、五島列島・対馬・壱岐など主要な離島だけが残っています。

市区町村境界の確認

市区町村レベルでも、ST_CoverageSimplifyにより隣接する境界にずれがないことを確認します。簡素化により海岸線やカーブの細部は丸められていますが、市区町村間の共有境界は一貫して簡素化されており、隙間は発生していません。

政令指定都市の区を統合したバリアント

nlftp.boundary.municipalityは政令指定都市の区(横浜市鶴見区、横浜市神奈川区など)を個別に保持しています。市レベルで集計したい場合に備え、区を統合したnlftp.boundary.designated_cityも提供しています。東京23区(特別区)は独立した地方公共団体のため統合しません。

前のセクションの神奈川県マップ(58市区町村)と比較すると、横浜市・川崎市・相模原市の区境界が消えて市単位(33市町村)になっていることがわかります。

まとめ

  • 国土数値情報 N03 のフル解像度ポリゴンは市区町村単位で頂点1,541万、WKB 237MBに達し、ブラウザのDuckDB WASMでは集計・変換時にメモリ不足が発生する
  • 頂点間引き(ST_CoverageSimplify)が95%削減の主力、小島除去が残りの13MB → 3.6MBの仕上げ
  • ST_SimplifyPreserveTopologyは各ポリゴンを独立に簡素化するため、隣接する市区町村の共有境界にずれが生じる。ST_CoverageSimplifyで共有境界の一貫性を保持して解決した
  • 簡素化により海岸線の細部は失われるが、塗り分け地図としては実用上問題ない精度を維持。原データ(raw/stg)はフル解像度で保持しており、GIS分析が必要な場合は参照できる
  • nlftp.boundary.prefecture(47都道府県)、nlftp.boundary.municipality(1,898市区町村、政令市の区を含む)、nlftp.boundary.designated_city(1,747市区町村、政令市の区を市に統合)として全記事から参照可能

参考

  • K-Oxon/Japan-map-for-BI: 国土数値情報から mapshaper でポリゴンを簡素化し、Power BI / Tableau 向けの TopoJSON を公開。簡素化の手法(ポリゴン簡素化 + 小島除去 + dissolve)はこのプロジェクトを参考にした
  • smartnews-smri/japan-topography: TopoJSON の共有アーク構造で隣接境界の一貫性を保持。Queria では同じ考え方を DuckDB の ST_CoverageSimplify で再現した

本記事はAIを活用して作成し、編集部が内容を確認しています。記事内のSQLを実行してデータをご自身で検証いただけます。