はじめに
こちらの記事でunデータのズームレベル6~15のベクトルタイルを作成するproduce-gsc-unレポジトリを解説しました。この記事では、オープンストリートマップ(OSM)データのズームレベル6~15のベクトルタイルを作成するproduce-gsc-osmレポジトリを解説します。
作業レポジトリはこちらです。
unデータのズームレベル6~15のベクトルタイルを作成する
参照しているレポジトリには、「index_day01.js」や「index_everyday.js」などがありますが、参照する設定ファイルなどが少し異なるのみで、コードとしてはほぼ同じなので、「index_everyday.js」を使用することにします。index_everyday.jsのコードはこれまで解説してきたコードとほぼ同じなので、解説は省略します。
modify.js
それぞれのテーブルに対して、レイヤ名、最小ズームレベル、最大ズームレベルの付与、属性の削除などを行っています。「@mapbox/geojson-area」モジュールが使用されています。解説はこちらの記事にあります。新しく関数flapが使用されているので、こちらを解説します。
const geojsonArea = require('@mapbox/geojson-area');
const flap = (f, defaultZ) => {
switch (f.geometry.type) {
case 'MultiPolygon':
case 'Polygon':
let mz = Math.floor(19 - Math.log2(geojsonArea.geometry(f.geometry)) / 2);
if (mz > 15) {
mz = 15;
}
if (mz < 6) {
mz = 6;
}
return mz;
default:
return defaultZ ? defaultZ : 10;
}
};
・引数
f:地理データ(フィーチャ)オブジェクト
defaultZ:デフォルトのズームレベル
・switch (f.geometry.type) {
case 'MultiPolygon':
case 'Polygon':
}
地理データのタイプが MultiPolygon または Polygon の場合、面積に基づいてズームレベルを計算します。それ以外のジオメトリタイプ(例えば Point や LineString)の場合は、デフォルトのズームレベルを返します。
・let mz = Math.floor(19 - Math.log2(geojsonArea.geometry(f.geometry)) / 2);
geojsonArea.geometry(f.geometry) は、@mapbox/geojson-area モジュールを使って、f.geometry の面積を計算しています。
Math.log2(面積) で面積の対数(ベース2)を計算し、それを 2 で割り、その結果を 19 から引くことでズームレベルを計算しています。
Math.floor() で結果を切り捨て、小数点以下を取り除きます。
例えば、Math.log2(8) は 3 を返します。なぜなら 2^3 = 8 だからです。つまり、100平方メートルの面積を持つポリゴンだと、Math.log2(100) ≒ 6.64であり、2で割ると3.32、これを19から引くと15.68となります。Math.floor(15.68)は15なので、mz = 15となります。
・default:
return defaultZ ? defaultZ : 10;
default ブロックでは、もしジオメトリタイプが MultiPolygon または Polygon でない場合、defaultZ が指定されていればその値を返し、指定されていない場合は 10 を返します。
まとめると、関数flapがあることで、最小ズームレベルをポリゴンの面積に基づいて設定することが出来ます。面積が小さい地物に関して、ズームレベルが大きくなってから表示されることで、効率的にウェブ地図を表示出来ます。
default.hjson
「index_everyday.js」を見ながら、参照したレポジトリのdefault/default-sample.hjsonから不必要な部分を削除して作成しました。
※その他
「npm init」を実行して、package.jsonを作成し、必要なモジュールをインストールします。@mapbox/tilebeltはバージョン1.0.2をインストールすることに注意します。
npm install @mapbox/geojson-area @mapbox/tilebelt@1.0.2 better-queue cli-spinner config hh-mm-ss hjson pg prettysize winston winston-daily-rotate-file
プログラムの実行
ローカルでファイルなどを用意したので、次にLinuxPCで作業をします。
すべての範囲でプログラムを回すと時間がかかり過ぎるので、6-35-31(z-x-y)のデータのみで実行します。中央アフリカ共和国の首都バンギ辺りのデータです。設定ファイルはdefault_shortList.hjsonとしました。
LinuxPC上で、npm installとして必要なモジュールをインストールしてから、以下のコードを実行します。
sudo node produce-gsc-osm/index_everyday.js
今回もPMTiles形式のベクトルタイルを作成するために、index_everyday_pmtiles.jsというファイルも用意して、プログラムを実行しました。
PMTilesビューワで見ると、以下の地図が表示されます。
次は、以下の3つの領域で実行してプログラムが回るか確かめます。
5-14-13
5-14-14
5-15-13
設定ファイルはdefault_shortList2.hjsonとしました。
mbtiles形式とpmtiles形式の両方で作成出来ました。
tile-join
前回の記事でUNベクトルタイルを、今回の記事でOSMのベクトルタイルを作成しました。ここでは、複数の地図タイルセットを結合するためのコマンドであるtile-joinを使用して、2つのベクトルタイルをマージさせたいと思います。tile-joinの使い方はこちらに記載されています。
今回は、pmtilesファイルを作成しました。
tile-join --no-tile-size-limit -f -o large_tiles/unosm/tile_every/6-35-31.pmtiles produce-gsc-un/mbtiles/un_tile/6-35-31un.pmtiles produce-gsc-osm/mbtiles/osm_tile_every/6-35-31osm.pmtiles;
出力されるpmtilesファイル
- large_tiles/unosm/tile_every/6-35-31.pmtiles
入力されるpmtilesファイル
- produce-gsc-un/mbtiles/un_tile/6-35-31un.pmtiles
- produce-gsc-osm/mbtiles/osm_tile_every/6-35-31osm.pmtiles
Linux PCにおいては、以下のコマンドで実行出来ます。
sudo /usr/local/bin/tile-join --no-tile-size-limit -f -o large_tiles/unosm/tile_every/6-35-31.pmtiles produce-gsc-un/mbtiles/un_tile/6-35-31un.pmtiles produce-gsc-osm/mbtiles/osm_tile_every/6-35-31osm.pmtiles;
オプション
--no-tile-size-limit: 500kb以上のタイルをスキップしない
-f: アウトプットファイルが存在しても上書きして処理を実行
-o: 出力するアウトプットファイルを指定
作成したpmtilesファイルをpmtilesビューワで見ると以下のとおりです。unデータとosmデータがマージされて、どちらも表示されています。
scpコマンドでmbtilesファイルをリモートサーバにコピー
下記のようなコマンドを実行することで、mbtilesファイル等をリモートサーバにコピー出来ます。LinuxPCで試してみたところ、無事にコピー出来ました。
scp -i XXX(path to your ssh key) -r ./large_tiles/unosm/tile_every/* (username)@(hostingserver):(path)/mbtiles/unosm
scpコマンドの説明はこちらの記事にあります。
crontabを利用した定期的なプログラムの実行
参照しているこちらのレポジトリにあるシェルスクリプトを実行するために、crontabが使用されています。
crontabの使い方はこちらの記事にあります。
crontab -l
として、現在設定されているcronジョブをリスト表示してみると以下のとおり表示されます。
03 7 * * * cd /home/vectortile/data_conversion/produce-gsc-6; ./work_every.sh > /home/vectortile/data_conversion/cron-log/everyday-log.log 2>&1
00 14 * * 1 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day01.sh > /home/vectortile/data_conversion/cron-log/day01-log.log 2>&1
00 14 * * 2 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day02.sh > /home/vectortile/data_conversion/cron-log/day02-log.log 2>&1
00 14 * * 3 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day03.sh > /home/vectortile/data_conversion/cron-log/day03-log.log 2>&1
00 14 * * 4 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day04.sh > /home/vectortile/data_conversion/cron-log/day04-log.log 2>&1
00 14 * * 5 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day05.sh > /home/vectortile/data_conversion/cron-log/day05-log.log 2>&1
00 14 * * 6 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day06.sh > /home/vectortile/data_conversion/cron-log/day06-log.log 2>&1
00 14 * * 7 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day07.sh > /home/vectortile/data_conversion/cron-log/day07-log.log 2>&1
## twice a week
00 22 * * 3 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day01.sh > /home/vectortile/data_conversion/cron-log/day01-log.log 2>&1
00 22 * * 4 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day02.sh > /home/vectortile/data_conversion/cron-log/day02-log.log 2>&1
00 22 * * 5 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day03.sh > /home/vectortile/data_conversion/cron-log/day03-log.log 2>&1
00 22 * * 6 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day04.sh > /home/vectortile/data_conversion/cron-log/day04-log.log 2>&1
00 22 * * 7 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day05.sh > /home/vectortile/data_conversion/cron-log/day05-log.log 2>&1
00 22 * * 1 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day06.sh > /home/vectortile/data_conversion/cron-log/day06-log.log 2>&1
00 22 * * 2 cd /home/vectortile/data_conversion/produce-gsc-6; ./work_day07.sh > /home/vectortile/data_conversion/cron-log/day07-log.log 2>&1
例えば、1行目は、毎日7時3分に work_every.sh スクリプトを実行し、出力ログを everyday-log.log に保存することを示しています。
2行目から8行目では、毎週月曜日から日曜日の14:00にそれぞれ異なるスクリプトを実行しています。
10行目以降は、夜22:00にスクリプトを実行しています。
例えば、work_day01.shは月曜14時と、水曜22時の週2回実行されます。
実行にかかる時間は、過去の資料によるとosmの変換に最大7時間、マージに4時間程度です。
上記コマンドの通り、osmデータは定期的にアップデートされますが、UNデータはされないので、必要に応じて手動でアップデートする必要があります。
まとめ
オープンストリートマップ(OSM)データのズームレベル6~15のベクトルタイルを作成するproduce-gsc-osmレポジトリを解説しました。さらにtile-joinを利用したmbtilesファイル等のマージ、scpコマンドを用いたファイルをリモートサーバにコピーする方法、crontabを利用した定期的なプログラムの実行について記載しました。
Reference