OpenStreetMap のタイルをバッチ処理的に一括生成する

OpenStreetMap のタイルサーバを構築する でOpenStreetMap (OSM)のタイルサーバを構築しましたが、そこではブラウザ上での地図表示操作からのリクエストに応じてオンデマンドでタイルを作成していました。そのため、初回表示時にはタイル作成処理がサーバ側で走るため、表示が若干もたつきます。特にズームレベルの小さい表示では待てないほど時間がかかります。そのため、事前にタイルを生成しておけると便利です。

ここでは、サーバ側であらかじめバッチ処理的にタイルを一括生成する方法として、mod_tile付属のrender_listコマンドを利用する手順を記載します。

mod_tile 付属のコマンド

mod_tileをインストールすると、以下のコマンド群もインストールされます。renderdがデーモンで、それ以外のrender_*というのが各コマンドです。

$ ls /usr/local/bin/ | grep render
render_expired
render_list
render_old
render_speedtest
renderd

タイルを一括作成するにはrender_listを使います。使用方法は以下のとおりです。

$ render_list -h
Usage: render_list [OPTION] ...
  -a, --all            render all tiles in given zoom level range instead of reading from STDIN
  -f, --force          render tiles even if they seem current
  -m, --map=MAP        render tiles in this map (defaults to 'default')
  -l, --max-load=LOAD  sleep if load is this high (defaults to 16)
  -s, --socket=SOCKET  unix domain socket name for contacting renderd
  -n, --num-threads=N the number of parallel request threads (default 1)
  -t, --tile-dir       tile cache directory (defaults to '/var/lib/mod_tile')
  -z, --min-zoom=ZOOM  filter input to only render tiles greater or equal to this zoom level (default is 0)
  -Z, --max-zoom=ZOOM  filter input to only render tiles less than or equal to this zoom level (default is 20)
If you are using --all, you can restrict the tile range by adding these options:
  -x, --min-x=X        minimum X tile coordinate
  -X, --max-x=X        maximum X tile coordinate
  -y, --min-y=Y        minimum Y tile coordinate
  -Y, --max-y=Y        maximum Y tile coordinate
Without --all, send a list of tiles to be rendered from STDIN in the format:
  X Y Z
e.g.
  0 0 1
  0 1 1
  1 0 1
  1 1 1
The above would cause all 4 tiles at zoom 1 to be rendered

render_list コマンドでタイルを一括生成する

render_list のオプションの内、以下のものはぜひ指定したほうが良いと思います。

オプション説明
-a, –all全世界や特定のエリア(四隅座標で指定)のタイルを作成する場合にはこのオプションを指定します。これを指定しないと、タイル作成対象を標準入力から与える必要があります。
-m, –map=MAPほぼ必須のようです。これを指定しなかったところ処理が空振りしました。コマンド実行するとなにか始まったように見えるのですがどうもCPUもログも動いている気配がありませんでした。/usr/local/etc/renderd.confで設定している名称をオプションに与えます。renderdを設定でデフォルトで設定されていた「ajt」を指定する必要がありました。
-s, –socket=SOCKET指定しなくても動作しました。renderdと通信するためのソケットのパスです。今回の環境では/var/run/renderd/renderd.sockでした。これはApacheを設定/etc/apache2/sites-available/000-default.conf内にも記載しているソケットです。
-n, –num-threadsタイルの一括生成は非常に時間がかかるので、マシンのコア数や/usr/local/etc/renderd.confに設定したnum_threadsをふまえてなるべく大きな値を指定するのがよいです。
-z, –min-zoom指定しないと全ズームレベルを生成しようとしますので、特定のズームレベルだけに処理を絞りたい場合は指定します。
-Z, –max-zoom同上

今回はマシンが6CPUなのでスレッド数を6にします。/usr/local/etc/renderd.confnum_threadsもあわせて6にしておきます。
ズームレベルについては、例えばレベル0から18までのタイルを生成する場合は以下のようになります。

$ render_list -a -n 6 -z 0 -Z 18 -m ajt

ズームレベルごとの実行時間とデータサイズ

今回の実行環境です。

  • ホストマシン: Core i7-8700 @ 3.20GHz 6コア12スレッド、メモリ DDR4 32GB、HDD 5400RPM SATA/600、Windows 10
  • ゲストマシン: VirtualBox 6.1、CPU×6、メモリ 16GB、Ubuntu 20.04、PostgreSQL 12(shared_buffers = 8192MB)
  • 地図データ: 日本、アゼルバイジャン(アゼルバイジャンはタイルサーバ構築当初の動作確認用にインポートしていた)

ズームレベル0~13での各実行時間を測定してみました。レベル14以降は時間が長くかかりすぎるため省略しています。

表の左側はrender_listコマンドの標準出力メッセージ、中央はrender_listコマンドをdateコマンドで挟んで測定した実行時間、右側はfind . -type f | wc -lでカウントしたファイル数とdu -sで測ったデータサイズです。
ちなみに、生成されたタイルデータは/usr/local/etc/renderd.conf内で定義したディレクトリ(今回の環境では/var/lib/mod_tile/ajt/)配下にズームレベルごとに格納されます。ファイル数は4の(ズームレベル-3)乗になっています。4の累乗なのは、ズームレベルが1つ上がるにつれてタイル数が倍×倍(4倍)になるためです。また、ズームレベル3まで1ファイルのままなのは、8×8タイル単位で1つのファイルにまとめられているためです。
render_listが出力した「total」というのが実際の実行時間とは違っており、どのような値なのか分かりません。とはいえ、dateコマンドで測定した結果と傾向は似ています。

render_listコマンドの標準出力メッセージにある「requests」の値です。指数的に増加しています。

render_listコマンドをdateコマンドで挟んで測定した実行時間です。指数的に増加しています。

レベル13で33時間かかっています。

以下はコマンドの実行結果です。まとめたのが上記の表とグラフです。

ズームレベル 0

$ date && render_list -a -n 6 -z 0 -Z 0 -m ajt && date
2020年  5月  6日 水曜日 18:36:51 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 0 to zoom 0
Rendering all tiles for zoom 0 from (0, 0) to (0, 0)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 1 tiles in 3.53 seconds (0.28 tiles/s)
Total tiles rendered: Rendered 64 tiles in 3.53 seconds (18.12 tiles/s)
Total tiles handled: Rendered 1 tiles in 3.53 seconds (0.28 tiles/s)
*****************************************************
Zoom 00: min:  3.5    avg:  3.5     max:  3.5     over a total of      3.5s in 1 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:36:54 JST

ズームレベル 1

$ date && render_list -a -n 6 -z 1 -Z 1 -m ajt && date
2020年  5月  6日 水曜日 18:39:03 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 1 to zoom 1
Rendering all tiles for zoom 1 from (0, 0) to (1, 1)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 1 tiles in 2.94 seconds (0.34 tiles/s)
Total tiles rendered: Rendered 64 tiles in 2.94 seconds (21.79 tiles/s)
Total tiles handled: Rendered 1 tiles in 2.94 seconds (0.34 tiles/s)
*****************************************************
Zoom 01: min:  2.9    avg:  2.9     max:  2.9     over a total of      2.9s in 1 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:39:06 JST

ズームレベル 2

$ date && render_list -a -n 6 -z 2 -Z 2 -m ajt && date
2020年  5月  7日 木曜日 08:49:02 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 2 to zoom 2
Rendering all tiles for zoom 2 from (0, 0) to (3, 3)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 1 tiles in 3.12 seconds (0.32 tiles/s)
Total tiles rendered: Rendered 64 tiles in 3.12 seconds (20.51 tiles/s)
Total tiles handled: Rendered 1 tiles in 3.12 seconds (0.32 tiles/s)
*****************************************************
Zoom 02: min:  3.1    avg:  3.1     max:  3.1     over a total of      3.1s in 1 requests
*****************************************************
*****************************************************
2020年  5月  7日 木曜日 08:49:05 JST

ズームレベル 3

$ date && render_list -a -n 6 -z 3 -Z 3 -m ajt && date
2020年  5月  6日 水曜日 18:39:40 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 3 to zoom 3
Rendering all tiles for zoom 3 from (0, 0) to (7, 7)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 1 tiles in 3.16 seconds (0.32 tiles/s)
Total tiles rendered: Rendered 64 tiles in 3.16 seconds (20.28 tiles/s)
Total tiles handled: Rendered 1 tiles in 3.16 seconds (0.32 tiles/s)
*****************************************************
Zoom 03: min:  3.2    avg:  3.2     max:  3.2     over a total of      3.2s in 1 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:39:43 JST

ズームレベル 4

$ date && render_list -a -n 6 -z 4 -Z 4 -m ajt && date
2020年  5月  6日 水曜日 18:40:07 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 4 to zoom 4
Rendering all tiles for zoom 4 from (0, 0) to (15, 15)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 4 tiles in 6.06 seconds (0.66 tiles/s)
Total tiles rendered: Rendered 256 tiles in 6.06 seconds (42.25 tiles/s)
Total tiles handled: Rendered 4 tiles in 6.06 seconds (0.66 tiles/s)
*****************************************************
Zoom 04: min:  0.3    avg:  1.8     max:  6.1     over a total of      7.0s in 4 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:40:13 JST

ズームレベル 5

$ date && render_list -a -n 6 -z 5 -Z 5 -m ajt && date
2020年  5月  6日 水曜日 18:40:44 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 5 to zoom 5
Rendering all tiles for zoom 5 from (0, 0) to (31, 31)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 12 tiles in 10.53 seconds (1.14 tiles/s)
Total tiles rendered: Rendered 768 tiles in 10.53 seconds (72.96 tiles/s)
Total tiles handled: Rendered 16 tiles in 10.53 seconds (1.52 tiles/s)
*****************************************************
Zoom 05: min:  0.3    avg:  1.7     max:  9.9     over a total of     20.1s in 12 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:40:55 JST

ズームレベル 6

$ date && render_list -a -n 6 -z 6 -Z 6 -m ajt && date
2020年  5月  6日 水曜日 18:41:17 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 6 to zoom 6
Rendering all tiles for zoom 6 from (0, 0) to (63, 63)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 54 tiles in 3.84 seconds (14.04 tiles/s)
Total tiles rendered: Rendered 3456 tiles in 3.84 seconds (898.87 tiles/s)
Total tiles handled: Rendered 64 tiles in 3.84 seconds (16.65 tiles/s)
*****************************************************
Zoom 06: min:  0.3    avg:  0.4     max:  0.9     over a total of     21.0s in 54 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:41:21 JST

ズームレベル 7

$ date && render_list -a -n 6 -z 7 -Z 7 -m ajt && date
2020年  5月  6日 水曜日 18:42:38 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 7 to zoom 7
Rendering all tiles for zoom 7 from (0, 0) to (127, 127)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 248 tiles in 35.65 seconds (6.96 tiles/s)
Total tiles rendered: Rendered 15872 tiles in 35.65 seconds (445.23 tiles/s)
Total tiles handled: Rendered 256 tiles in 35.65 seconds (7.18 tiles/s)
*****************************************************
Zoom 07: min:  0.3    avg:  0.6     max: 22.7     over a total of    142.8s in 248 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:43:13 JST

ズームレベル 8

$ date && render_list -a -n 6 -z 8 -Z 8 -m ajt && date
2020年  5月  6日 水曜日 18:44:00 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 8 to zoom 8
Rendering all tiles for zoom 8 from (0, 0) to (255, 255)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 1018 tiles in 246.45 seconds (4.13 tiles/s)
Total tiles rendered: Rendered 65152 tiles in 246.45 seconds (264.36 tiles/s)
Total tiles handled: Rendered 1024 tiles in 246.45 seconds (4.15 tiles/s)
*****************************************************
Zoom 08: min:  0.4    avg:  1.1     max: 166.0     over a total of   1137.0s in 1018 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:48:07 JST

ズームレベル 9

$ date && render_list -a -n 6 -z 9 -Z 9 -m ajt && date
2020年  5月  6日 水曜日 18:48:45 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 9 to zoom 9
Rendering all tiles for zoom 9 from (0, 0) to (511, 511)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 4090 tiles in 432.87 seconds (9.45 tiles/s)
Total tiles rendered: Rendered 261760 tiles in 432.87 seconds (604.71 tiles/s)
Total tiles handled: Rendered 4096 tiles in 432.87 seconds (9.46 tiles/s)
*****************************************************
Zoom 09: min:  0.4    avg:  0.6     max: 106.9     over a total of   2559.6s in 4090 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 18:55:58 JST

ズームレベル 10

$ date && render_list -a -n 6 -z 10 -Z 10 -m ajt && date
2020年  5月  6日 水曜日 18:57:11 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 10 to zoom 10
Rendering all tiles for zoom 10 from (0, 0) to (1023, 1023)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 16376 tiles in 2624.07 seconds (6.24 tiles/s)
Total tiles rendered: Rendered 1048064 tiles in 2624.07 seconds (399.40 tiles/s)
Total tiles handled: Rendered 16384 tiles in 2624.07 seconds (6.24 tiles/s)
*****************************************************
Zoom 10: min:  0.5    avg:  0.8     max: 966.9     over a total of  13002.7s in 16376 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 19:40:57 JST

ズームレベル 11

$ date && render_list -a -n 6 -z 11 -Z 11 -m ajt && date
2020年  5月  6日 水曜日 20:00:25 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 11 to zoom 11
Rendering all tiles for zoom 11 from (0, 0) to (2047, 2047)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 65528 tiles in 7554.18 seconds (8.67 tiles/s)
Total tiles rendered: Rendered 4193792 tiles in 7554.18 seconds (555.16 tiles/s)
Total tiles handled: Rendered 65536 tiles in 7554.18 seconds (8.68 tiles/s)
*****************************************************
Zoom 11: min:  0.5    avg:  0.7     max: 295.3     over a total of  45320.3s in 65528 requests
*****************************************************
*****************************************************
2020年  5月  6日 水曜日 22:06:21 JST

ズームレベル 12

$ date && render_list -a -n 6 -z 12 -Z 12 -m ajt && date
2020年  5月  6日 水曜日 22:16:46 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 12 to zoom 12
Rendering all tiles for zoom 12 from (0, 0) to (4095, 4095)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 262138 tiles in 27566.90 seconds (9.51 tiles/s)
Total tiles rendered: Rendered 16776832 tiles in 27566.90 seconds (608.59 tiles/s)
Total tiles handled: Rendered 262144 tiles in 27566.90 seconds (9.51 tiles/s)
*****************************************************
Zoom 12: min:  0.5    avg:  0.6     max: 177.5     over a total of 165393.6s in 262138 requests
*****************************************************
*****************************************************
2020年  5月  7日 木曜日 05:56:14 JST

ズームレベル 13

$ date && render_list -a -n 6 -z 13 -Z 13 -m ajt && date
2020年  5月  7日 木曜日 11:13:19 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 13 to zoom 13
Rendering all tiles for zoom 13 from (0, 0) to (8191, 8191)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 1048570 tiles in 120018.60 seconds (8.74 tiles/s)
Total tiles rendered: Rendered 67108480 tiles in 120018.60 seconds (559.15 tiles/s)
Total tiles handled: Rendered 1048576 tiles in 120018.60 seconds (8.74 tiles/s)
*****************************************************
Zoom 13: min:  0.6    avg:  0.7     max: 150.9     over a total of 720083.9s in 1048570 requests
*****************************************************
*****************************************************
2020年  5月  8日 金曜日 20:33:37 JST

タイル生成範囲を限定する

以上のように-aオプションで一括生成できますが、これだけだと全世界が処理対象とされます。それでいい場合ならよいのですが、今回のようにインポート済みの地図データが一部地域だけ(日本、アゼルバイジャン)の場合には、地域外についても処理が回ってしまい余計な時間がかかります。そこで、前述の以下のオプションで処理範囲を限定します。

If you are using --all, you can restrict the tile range by adding these options:
-x, --min-x=X minimum X tile coordinate
-X, --max-x=X maximum X tile coordinate
-y, --min-y=Y minimum Y tile coordinate
-Y, --max-y=Y maximum Y tile coordinate

ところで、このオプションに与えるXY座標は経緯度ではなく、タイルの場所を示す値である必要があります。

経緯度からタイル座標を算出する

関数やスクリプトの形でいくつか例が見つかりました。

GoogleProjection.fromPixelToLL 関数

”ウェブブラウザで地図を表示するとタイルサーバへリクエストが飛んで、タイルを(必要に応じて新規生成して)ブラウザへ返す”、”ブラウザ上ではおそらく経緯度を使っているはず”、と考えると、どこかのタイミングで経緯度からタイル座標への変換ロジックがあるだろうと思い探してみたところ、GoogleProjection.fromPixelToLL関数というのがありました。
これはタイル作成をしているmod_tile(のgen_tile.cpp)でも使われており、同様のロジックのコードが他にも複数見つかりました。

上記のspeedtest.cppから必要最小限の部分を抜粋して、テスト実行用にmain関数を書き加えたものが以下です。

#include <stdio.h>
#include <math.h>

#define DEG_TO_RAD (M_PI/180)
#define RAD_TO_DEG (180/M_PI)

static const int maxZoom = 18;

static double minmax(double a, double b, double c)
{
#define MIN(x,y) ((x)<(y)?(x):(y))
#define MAX(x,y) ((x)>(y)?(x):(y))
    a = MAX(a,b);
    a = MIN(a,c);
    return a;
}

class GoogleProjection
{
    double *Ac, *Bc, *Cc, *zc;

    public:
        GoogleProjection(int levels=18) {
            Ac = new double[levels];
            Bc = new double[levels];
            Cc = new double[levels];
            zc = new double[levels];
            int d, c = 256;
            for (d=0; d<levels; d++) {
                int e = c/2;
                Bc[d] = c/360.0;
                Cc[d] = c/(2 * M_PI);
                zc[d] = e;
                Ac[d] = c;
                c *=2;
            }
        }

        void fromLLtoPixel(double &x, double &y, int zoom) {
            double d = zc[zoom];
            double f = minmax(sin(DEG_TO_RAD * y),-0.9999,0.9999);
            x = round(d + x * Bc[zoom]);
            y = round(d + 0.5*log((1+f)/(1-f))*-Cc[zoom]);
        }
};

static GoogleProjection gprj(maxZoom+1);

int main(int argc, char **argv)
{
	double lon = atof(argv[1]);
	double lat = atof(argv[2]);
	int zoom = atoi(argv[3]);

	gprj.fromLLtoPixel(lon, lat, zoom);
	printf("(x,y)=(%d,%d)\n", (int)(lon/256), (int)(lat/256));
}

例えば、(経度, 緯度) = (122.5607, 45.80245)のズームレベル14でのタイル座標は(x, y)=(13769, 5841)となります。

$ g++ test.cpp 
$ ./a.out 122.5607 45.80245 14
(x,y)=(13769,5841)

MapTiler のスクリプト

MapTilerのウェブサイトに経緯度からタイル座標を算出できるPythonスクリプトがあります。GitHubにもアップされています。以下の形式で実行できます。

python globalmaptiles.py [zoom] [lat] [lon]

render_list コマンドを呼び出すラッパースクリプト

引数として経緯度を受け取り、タイル座標に変換したうえでrender_listコマンドを呼び出すラッパースクリプトがあります。

注意点:緯度は -85.06 ~ 85.06 度

これらの方法を使うにあたり注意しなければいけないのは、緯度は-85.06 ~ 85.06度の範囲にとどめる必要がある点です。それ以上の高緯度ではタイル座標が大きくなりすぎたりマイナスになったりして、有効なタイル座標を得られません。

というのは、ウェブマップのタイルサービスは地図投影法としてWebメルカトル図法を想定しており、Webメルカトル図法の経緯度の有効範囲は緯度が-85.06 ~ 85.06度、経度が-180~180度となっているためです。
http://epsg.io/3857
http://www.epsg-registry.org/ (3857で検索)

このため、上記のプログラムを使う場合にも、緯度-85.06 ~ 85.06度、経度-180~180度の範囲で指定する必要があります。

範囲を指定してタイルを生成する

手順は以下のようになります。

  1. タイルを生成したい範囲の経緯度を調べる
  2. 経緯度をタイル座標に変換する
  3. タイル座標を指定してrender_listコマンドを実行する

もしくは、

  1. タイルを生成したい範囲の経緯度を調べる
  2. 経緯度を指定して上記のrender_listのラッパースクリプト(render_latlon.pyやrender_latlon.py)を実行する

経緯度は地図を目で見て決めてもよいですし、OpenStreetMapのPBFファイルから調べることもできます。
例えばOpenStreetMapの日本のPBFファイルを持っていて、日本域に限定してタイル生成を行いたいという場合には、以下のコマンドでPBFファイルが持つ地図の経緯度を調べられます。

$ osmium fileinfo japan-latest.osm.pbf
File:
  Name: japan-latest.osm.pbf
  Format: PBF
  Compression: none
  Size: 1498025738
Header:
  Bounding boxes:
    (122.5607,20.08228,154.4709,45.80245)
  With history: no
  Options:
    generator=osmium/1.8.0
    osmosis_replication_base_url=http://download.geofabrik.de/asia/japan-updates
    osmosis_replication_sequence_number=2598
    osmosis_replication_timestamp=2020-05-01T20:59:03Z
    pbf_dense_nodes=true
    timestamp=2020-05-01T20:59:03Z

japan-latest.osm.pbfの範囲は、矩形でいうと、左上が(経度, 緯度) = (122.5607, 45.80245)、右下が(経度, 緯度) =(154.4709, 20.08228)です。
これはズームレベル14のタイル座標でいうと、以下の通り、左上が(x,y)=(13769, 5841)、右下が(x,y)=(15222, 7258)になります。(render_listに対しては、「TileMapService: z / x / y」の方ではなく「Google」の方の値が適切です。)ちなみに、前述のGoogleProjection.fromPixelToLL関数でも同じ値が得られました。

$ python2 globalmaptiles.py 14 45.80245 122.5607
Spherical Mercator (ESPG:900913) coordinates for lat/lon: 
(13643394.715267165, 5748748.01273476)
14/13769/10542 ( TileMapService: z / x / y )
	Google: 13769 5841
	Quadkey: 13032133021003 ( 121238083 )

	EPSG:900913 Extent:  (13641257.815885697, 5748064.527045254, 13643703.80079082, 5750510.511950381)
	WGS84 Extent: (45.79816953017265, 122.54150390625001, 45.81348649679973, 122.5634765625)
	gdalwarp -ts 256 256 -te 13641257.8159 5748064.52705 13643703.8008 5750510.51195 <your-raster-file-in-epsg900913.ext> 14_13769_10542.tif

$ python2 globalmaptiles.py 14 20.08228 154.4709
Spherical Mercator (ESPG:900913) coordinates for lat/lon: 
(17195621.930378683, 2282780.674088647)
14/15222/9125 ( TileMapService: z / x / y )
	Google: 15222 7258
	Quadkey: 13321103132130 ( 132462492 )

	EPSG:900913 Extent:  (17195273.88303325, 2282103.9164822213, 17197719.867938373, 2284549.901387349)
	WGS84 Extent: (20.076570104545173, 154.4677734375, 20.0972062270839, 154.48974609374997)
	gdalwarp -ts 256 256 -te 17195273.883 2282103.91648 17197719.8679 2284549.90139 <your-raster-file-in-epsg900913.ext> 14_15222_9125.tif

よって、render_listコマンドで日本域に限定してタイル生成をする場合は、オプションとして以下を与えればよいことになります。

-x 13769 -X 15222 -y 5841 -Y 7258

ズームレベル 14

$ date && render_list -a -n 6 -z 14 -Z 14 -m ajt -x 13769 -X 15222 -y 5841 -Y 7258 && date
2020年  5月  9日 土曜日 17:12:36 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 14 to zoom 14
Rendering all tiles for zoom 14 from (13769, 5841) to (15222, 7258)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 32395 tiles in 5209.75 seconds (6.22 tiles/s)
Total tiles rendered: Rendered 2073280 tiles in 5209.75 seconds (397.96 tiles/s)
Total tiles handled: Rendered 32396 tiles in 5209.75 seconds (6.22 tiles/s)
*****************************************************
Zoom 14: min:  0.6    avg:  1.0     max: 99.7     over a total of  31256.4s in 32395 requests
*****************************************************
*****************************************************
2020年  5月  9日 土曜日 18:39:26 JST

ズームレベル 15

$ python2 globalmaptiles.py 15 45.80245 122.5607
Spherical Mercator (ESPG:900913) coordinates for lat/lon: 
(13643394.715267165, 5748748.01273476)
15/27539/21084 ( TileMapService: z / x / y )
	Google: 27539 11683
	Quadkey: 130321330210033 ( 484952335 )

	EPSG:900913 Extent:  (13642480.808338258, 5748064.527045254, 13643703.80079082, 5749287.5194978155)
	WGS84 Extent: (45.79816953017265, 122.552490234375, 45.805828539928356, 122.5634765625)
	gdalwarp -ts 256 256 -te 13642480.8083 5748064.52705 13643703.8008 5749287.5195 <your-raster-file-in-epsg900913.ext> 15_27539_21084.tif

$ python2 globalmaptiles.py 15 20.08228 154.4709
Spherical Mercator (ESPG:900913) coordinates for lat/lon: 
(17195621.930378683, 2282780.674088647)
15/30444/18250 ( TileMapService: z / x / y )
	Google: 30444 14517
	Quadkey: 133211031321302 ( 529849970 )

	EPSG:900913 Extent:  (17195273.88303325, 2282103.9164822213, 17196496.87548581, 2283326.908934787)
	WGS84 Extent: (20.076570104545173, 154.4677734375, 20.08688850556103, 154.47875976562497)
	gdalwarp -ts 256 256 -te 17195273.883 2282103.91648 17196496.8755 2283326.90893 <your-raster-file-in-epsg900913.ext> 15_30444_18250.tif

$ date && render_list -a -n 6 -z 15 -Z 15 -m ajt -x 27539 -X 30444 -y 11683 -Y 14517 && date
2020年  5月  9日 土曜日 18:45:45 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 15 to zoom 15
Rendering all tiles for zoom 15 from (27539, 11683) to (30444, 14517)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 129220 tiles in 17448.12 seconds (7.41 tiles/s)
Total tiles rendered: Rendered 8270080 tiles in 17448.12 seconds (473.98 tiles/s)
Total tiles handled: Rendered 129220 tiles in 17448.12 seconds (7.41 tiles/s)
*****************************************************
Zoom 15: min:  0.6    avg:  0.8     max: 43.5     over a total of 104680.7s in 129220 requests
*****************************************************
*****************************************************
2020年  5月  9日 土曜日 23:36:33 JST

ズームレベル 16

$ python2 globalmaptiles.py 16 45.80245 122.5607
Spherical Mercator (ESPG:900913) coordinates for lat/lon: 
(13643394.715267165, 5748748.01273476)
16/55079/42169 ( TileMapService: z / x / y )
	Google: 55079 23366
	Quadkey: 1303213302100331 ( 1939809341 )

	EPSG:900913 Extent:  (13643092.30456454, 5748676.023271535, 13643703.80079082, 5749287.5194978155)
	WGS84 Extent: (45.80199916666154, 122.5579833984375, 45.805828539928356, 122.5634765625)
	gdalwarp -ts 256 256 -te 13643092.3046 5748676.02327 13643703.8008 5749287.5195 <your-raster-file-in-epsg900913.ext> 16_55079_42169.tif

$ python2 globalmaptiles.py 16 20.08228 154.4709
Spherical Mercator (ESPG:900913) coordinates for lat/lon: 
(17195621.930378683, 2282780.674088647)
16/60888/36501 ( TileMapService: z / x / y )
	Google: 60888 29034
	Quadkey: 1332110313213020 ( 2119399880 )

	EPSG:900913 Extent:  (17195273.88303325, 2282715.4127085023, 17195885.37925953, 2283326.908934787)
	WGS84 Extent: (20.081729389971578, 154.4677734375, 20.08688850556103, 154.4732666015625)
	gdalwarp -ts 256 256 -te 17195273.883 2282715.41271 17195885.3793 2283326.90893 <your-raster-file-in-epsg900913.ext> 16_60888_36501.tif

$ date && render_list -a -n 6 -z 16 -Z 16 -m ajt -x 55079 -X 60888 -y 23366 -Y 29034 && date
2020年  5月  9日 土曜日 23:55:57 JST
debug: init_storage_backend: initialising file storage backend at: /var/lib/mod_tile
Rendering client
Starting 6 rendering threads
Rendering all tiles from zoom 16 to zoom 16
Rendering all tiles for zoom 16 from (55079, 23366) to (60888, 29034)
Waiting for rendering threads to finish

*****************************************************
*****************************************************
Total for all tiles rendered
Meta tiles rendered: Rendered 515443 tiles in 69150.86 seconds (7.45 tiles/s)
Total tiles rendered: Rendered 32988352 tiles in 69150.86 seconds (477.05 tiles/s)
Total tiles handled: Rendered 515443 tiles in 69150.86 seconds (7.45 tiles/s)
*****************************************************
Zoom 16: min:  0.6    avg:  0.8     max: 24.1     over a total of 414892.2s in 515443 requests
*****************************************************
*****************************************************
2020年  5月 10日 日曜日 19:08:29 JST

実行時間とデータサイズ

範囲を指定してズームレベル14~16のタイルを生成した場合の実行時間は以下のようになりました(本当は同じレベルどうしで比べたほうが良いのですが面倒だったので…)。範囲指定しなければもっと長い時間がかかるはずでしたが、日本域に範囲を絞ったことで時間が短縮されています。それでもレベル16で19時間かかっているので、レベル17ではおそらく4倍くらいの約3日、レベル18ではさらに4倍くらいの約12日かかりそうです。日本域に絞ったためデータサイズも少なく済んでいます。

まとめ

mod_tile付属のrender_listコマンドを利用してタイルを一括生成する方法を試してみました。処理時間が長くかかるので、小さいズームレベルのタイルは特に範囲を指定せず(つまり全世界を対象にして)コマンドを実行して問題ないですが、大きいズームレベルでは極力範囲を指定した方が現実的です。

ちなみに、https://tools.geofabrik.de/calc/ ではズームレベル毎のタイル数と容量を概算できます。

コメントを残す