国土数値情報の地図データはなぜ簡素化が必要なのか — 237MBのポリゴンとブラウザのOOM
ウェブアプリで日本地図の塗り分け(コロプレス図)を表示するには、都道府県や市区町村の境界ポリゴンが必要です。国土交通省の「国土数値情報」が提供する行政区域データ(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 拡張で使用できます。
最終的な処理フロー
- ST_Dump + ST_Area フィルタ: 面積が極小の小島を除去
- 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で再現した