はじめに
動機
2024年4月15日に公開された令和6年度の地図XMLをベクトルタイルにしたいと考えています。タイル作成にあたってGeoJSON形式からベクトルタイル(PMTiles形式)への変換は前の記事でまとめたのですが、その時はG空間情報センターから出ている変換済みのGeoJSONファイルを使いました。2024年度地図XMLはまだGeoJSONになっていません。一方で、デジタル庁がコンバーターを公開しているので、自分で地図XMLをGeoJSONに変換してみたので、メモしておきます。
環境
- Windows 11 home
- WondowsPowerShell version 5.1 (Build 22621, Revision 2506)
- WSL Ubuntu version 2
- tippecanoe v2.53.0
- GDAL 3.4.1, released 2021/12/27
- Python 3.10.12, pip 22.0.2
- デジタル庁のコンバータをインストール済み
手順
Step 1: データのダウンロード
2024年度の地図XMLファイルをダウンロードします。WindowsPowerShellのコマンドでダウンロードできます。ダウンロードに少しかかりますが2010ファイルをダウンロードしました。
$jsonData = (curl.exe 'https://www.geospatial.jp/ckan/api/3/action/resource_search?query=name:-2024.zip&limit=2100' | ConvertFrom-JSON)
for ($i=0; $i -lt $jsonData.result.results.name.length ; $i++ ){
curl.exe -LO $jsonData.result.results.URL[$i]
}
Step 2: 投影法リストの作成
地図XMLの半分は任意座標系で座標変換ができないので、公共座標系のファイルだけを対象にする必要があります。そのためにはまず各ファイルの座標が何かをリストする必要があります。以前の記事に詳しく書きましたが、以下のような感じで各ファイルの投影法一覧を作成します。こちらもWindowsPowerShellのコマンドで実行します。
# 作業フォルダの準備
#rm unpack
#rm list
mkdir unpack
mkdir list
# 出力ファイル名を定義
$resultTXT = "projection-list.txt"
$fileSize = "xml-file-size.txt"
# 出力ファイルを初期化
if(Test-Path $resultTXT){
rm $resultTXT
}
if(Test-Path $fileSize){
rm $fileSize
}
# XMLの市区町村パッケージ(ZIP)リストの取得
$zipList = Get-Childitem -Path . -filter *.zip
##################
# 各市区町村ごとのループ開始
foreach($zippedPack in $zipList){
# 市区町村のパッケージfileをunpackフォルダに解凍
Expand-Archive $zippedPack -DestinationPath unpack
# unpackフォルダ中のZIPファイルをリスト
$testList = Get-Childitem -Path unpack -filter *.zip
# unpackフォルダ内のzipファイルを解凍
foreach($item in $testList){
Expand-Archive unpack/$item -DestinationPath unpack
Write-host($item)
}
# 解凍したlistを移動
Move-Item unpack/*.csv -Destination list
# unpackフォルダ内のzipファイルを削除
rm unpack/*.zip
# unpack フォルダ内のxmlファイルの座標系を検索。ファイル一覧も記録。
if ($zahyo) {
remove-variable zahyo
}
$zahyo = Select-String "座標系" unpack/*.xml
Write-Output $zahyo | Add-Content $resultTXT
#Get-Item unpack/* | Add-Content $fileSize #ファイル名しか記録されない
Get-Item unpack/* >> $fileSize #ファイルサイズも残る
# unpackフォルダをクリーン
rm unpack/*
}
7行目が投影法法なのですが、それ以外で拾われている行(今回は以下の3つ)は要削除です。
テキストファイルとして置換などをしながら、csvファイルで処理できるように加工します。
最終的にエクセルなどで処理して、公共座標系を持つファイル一覧を抜き出して作成します。全部で316,300ファイル中、137,011ファイルが公共座標系でした。
Step 3: 投影法リストを参照しながら公共座標のものを変換
今、ローカルディスクにはダウンロードしてきた2010のZIPがあるchizu-xml2024というフォルダがありますが、ここにgeojson2024というフォルダを準備します。
geojson2024に、前のステップで作った公共座標一覧をコピーして、作業用のフォルダunpackを作ります。
ここからはWSLを使います。chizu-xmlとgeojson2024のフォルダがおいておる場所にいって、以下のコマンドを実行します。デジタル庁の地図XML変換コンバーターも事前にインストールしておきます。
<スクリプトの説明>
- 市区町村-法務局のパッケージ全部をforループで処理します。
- 市区町村のものをgeojson2024のunpackに解凍し、個別ファイルのZIP版がそこにできます。
- とりあえず個別ファイルのZIP版をXMLに解凍します。
- 解凍した各XML(ZIP)について、すでに作成した公共座標一覧(geojson2024/kokyo-list.txt)の中に名前があるか探します(grep)。もしあれば($?がゼロ)デジタル庁コンバータmojxml2geojsonを使います。
- unpackの中にgeojsonができますが、作業の過程でできたZIPファイル、XMLファイル、リストCSVは不要なので削除します。
##各市区町村-法務局ファイルに対して行うforループ
for f in chizu-xml2024/*-2024.zip;
#for f in chizu-xml2024/4738*-2024.zip; #練習用(1つのところで)
do echo ${f}; unzip ${f} -d geojson2024/unpack; #まずは市区町村のパッケージを解凍(2度圧縮のうち最初)
#そのあとに、個別ファイルがgeojson2024/unpackにあるので解凍(2度圧縮のうち最初)
for g in geojson2024/unpack/*zip; do unzip ${g} -d geojson2024/unpack ; done
#解凍したところに移動
cd geojson2024/unpack
#それぞれのZIPについて公共座標リストにあった場合には変換(grepと$?を利用)
for g in *zip; do cat ../../geojson2024/kokyo-list.txt| grep `basename ${g} .zip`.xml ;
#echo $?;
if [ $? = 0 ]; then
#echo $?
mojxml2geojson `basename ${g} .zip`.xml
fi;
done
rm *.zip
rm *.xml
rm *.csv
cd ..
cd ..
done
ファイル解凍の時にエラーが出て警告がでているのですが、解凍自体はできているのでよしとします。
作業中のフォルダはこんな感じです。見ているとXMLよりGeoJSONのほうがずいぶん軽いです。
後日追記:
以下のほうが無駄な解凍がないので早いと思います。
##各市区町村-法務局ファイルに対して行うforループ
for f in chizu-xml2024/*-2024.zip;
#for f in chizu-xml2024/4738*-2024.zip; #練習用(1つのところで)
do echo ${f}; unzip ${f} -d geojson2024/unpack; #まずは市区町村のパッケージを解凍(2度圧縮のうち最初)
#それぞれのZIPについて公共座標リストにあった場合には解凍して変換(grepと$?を利用)
for g in geojson2024/unpack/*zip; do cat geojson2024/kokyo-list2.txt| grep `basename ${g} .zip`.xml ;
if [ $? = 0 ]; then
unzip ${g} -d geojson2024/unpack
mojxml2geojson geojson2024/unpack/`basename ${g} .zip`.xml
fi;
done
rm geojson2024/unpack/*.zip
rm geojson2024/unpack/*.xml
rm geojson2024/unpack/*.csv
done
追記(変換終了と市区町村ごとのマージ)
Windowsが再起動してしまったりいろいろと途中で止まってしまったことがあったのですが、12日くらいかけてファイルの変換が終了しました。ファイル数は以下の内訳ですが、公共座標のXMLと同じ137,011ファイルでした。
- 0で始まるファイル: 29,147
- 1で始まるファイル: 21,144
- 2で始まるファイル: 26,651
- 3で始まるファイル: 32,886
- 4で始まるファイル: 27,183
ファイル数が多いので、0で始まるファイル、1で始まるファイル、2で始まるファイル、3で始まるファイル、4で始まるファイルに分けました。
マージについてはnpmモジュールのgeojson-mergeを当初試みた(以下図のコマンド)のですが、途中で止まってしまってうまくできませんでした。
最終的にgdalを使ってGeoJSONseqにしてしまい、それを市町村ごとにファイルに書き込んでいくという方策をとることにしました。GeoJSONseqをそのままtippecanoeに入れたかったのですが、tippecanoe属性調整のためのfileterを作る時間がなかったのでGeoJSONseqを中間ファイルとして準備しておきます。
for f in */*.geojson; do ogr2ogr -f GeoJSONseq -lco RS=YES /vsistdout/ ${f} >>
merge/`basename ${f:3:5}`-2024.geojsons; done #basenameの次の3:5は各自のフォルダ構成により適宜修正
途中、地図番号のところで変換がうまくいかない可能性があるという警告が出ているファイルがいくつかありました。地図番号は気にしませんが、入っているデータの文字コードなどの関係でしょうか。
追伸:ベクトルタイル化
GeoJSONseqファイルができたので、あとはベクトルタイルにします。まずは市区町村それぞれのGeoJSONseqをmbtiles形式にします。WSLで行います。
for f in merge/*.geojsons; do tippecanoe -o pmtiles/`basename ${f} .geojsons`.mbtiles --no-feature-limit --no-tile-size-limit -Z14 -z16 -L fude:${f}; done
20時間くらいで市区町村ごとにまとめられました。次は、都道府県ごとにpmtilesにします。当該フォルダに移動して、以下のコマンドを実行しました。
for i in $(seq -w 1 47); do fileList=$(ls ${i}*-2024.mbtiles); echo $i;tile-join -f --
no-tile-size-limit -o c-${i}.pmtiles $fileList; done
最後に、都道府県ごとのpmtilesをまとめます。
fileList=$(ls *.pmtiles)
tile-join -f --no-tile-size-limit -o c.pmtiles $fileList
以下のコマンドで不要な属性を削ると少しサイズが小さくなりました。
tile-join -x version -x 測地系判別 -x 地図名 -x 代表点緯度 -x 代表点経度 --no-tile-size-limit -f -o c2.pmtiles c.pmtiles
まとめ
やり方をいろいろと考えたのですが、地図XMLのうち公共座標のファイルだけをGeoJSONに変換する方法を考えました。Windows環境だけでできるので私のパソコンだけでも大丈夫です。
GeoJSONを市区町村ごとにまとめて、そのあとにPMtilesに変換し、全国マージして2024年度版のベクトルタイル(PMTiles)になりました。
感謝
デジタル庁のコンバータ、ありがとうございます。法務省、G空間情報センターの登記所備付データ公開に感謝します。
参考