インターネットに接続できない環境でもバンドル以外の地図を利用する方法

# はじめに
Splunk のダッシュボードでは "Cluster Map" をはじめ、様々な地図による可視化を行うことができます。Splunk にバンドルされている地図を利用することも可能ですが、ズームできる限界が低く、世界全体を表示させるような用途では問題ありませんが、日本国内を表示させるにはかなり使いづらいのではないでしょうか。

日本地図を最大にズームするとこんな感じです。
![バンドルされている地図を Max ズーム](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1931706/de420b96-7c7c-cac0-91dc-01d03b710efe.png)

だからという理由かはわかりませんが、多くの地図を用いた可視化では、Google Map や OpenStreetMap といった、外部の地図サービスを利用することが可能となっています。

しかしながら、Splunk サーバがインターネットに接続されていない場合、これらのサービスは利用することができず、バンドルされている地図で我慢するしかないと思っている方が多いようです。

ということで、今回は、インターネットに接続されていない Splunk サーバでバンドルされている地図以外の地図を利用する方法について説明します。

# 方法
## Splunk で外部地図サービスを利用するには

Splunk で外部の地図サービスを利用するには、その地図サービスの定める URL を指定する必要があります。

下記は、"Cluster Map" で Goole Map を利用するように設定している例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1931706/b2e47213-f69d-5b77-555d-f2b01ec3a248.png)

これ以外にも利用できる地図サービスはいくつもあり、代表的なものをまとめてみました。

|地図サービス|URL|
|:---|:---|
|Open Street Map|http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png|
|Google Map(通常)|http://mt3.google.com/vt/lyrs=m@114&z={z}&x={x}&y={y}|
|Google Map(衛星画像)|http://mt3.google.com/vt/lyrs=s,h&z={z}&x={x}&y={y}|
|国土地理院標準地図|https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png|
|地理院地図の淡色地図|https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png|
|地理院地図の航空写真|https://cyberjapandata.gsi.go.jp/xyz/seamlessphoto/{z}/{x}/{y}.jpg|
|CARTO map(Dark)|https://1.basemaps.cartocdn.com/rastertiles/dark_all/${z}/${x}/${y}.png|
[こちら](https://qiita.com/hyugma/items/c29f27e58ad5046156be)にも Splunk で利用できる地図が紹介されています。特に、それぞれのがどんな感じの地図なのかを確認したい方は、ぜひ見てみてください。

## ここで理解しておきたいこと
「インターネットに接続できない環境で」という縛りを入れながら、インターネットに接続できないと利用できないサービスを紹介したのには 2 つの理由があります。

1つ目、

### 地図はタイルデータの集合である

各地図サービスの URL を見ていただくとわかりますが、いずれも {x},{y},{z} というパラメータがあり、どうやら PNG 画像をダウンロードしてきて表示させていることがわかります。

ここで {z} というのはズームレベルで、文字通りこの値が大きくなるとズームレベルが上がる、つまり、より狭い範囲を拡大して表示させることになります。ちなみに Splunk にバンドルされている地図はズームレベル 7 までです。ズームレベルが 1 上がると、元のズームレベルで表示していた領域を縦横に 4 分割します。

次に {x} と {y} ですが、{x} は東から西へのタイルの通し番号、{y} は北から南へのタイルの通し番号になります。ズームレベル毎に {x} と {y} の最大値は異なります(4倍ずつ増えます)。

全くの余談ですが、どの地図もメルカトル図法のため、極に近づくと歪みが大きくなるため、{y}=0 は北極点を含んではいないそうです。

言葉では分かりづらい部分もあると思います。産総研が提供している[タイル座標確認ツール](https://gsj-seamless.jp/labs/tools/tileCoord.html)を見ていただくと、説明を読むよりもわかりやすいと思います。

タイル座標確認ツールの表示例
![タイル座標確認ツール](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1931706/aa1082f2-fd4a-e7b3-e355-b60e397bd6fd.png)

このように、普段利用している Google Map 等の地図サービスは正方形の画像データがタイル状に並んでできているということがおわかりいただけたでしょうか。

次に 2 つ目のポイント

### 地図データをローカルにダウンロードして利用することができる

これが意外と知られていない重要なポイントです。
`$SPLUNK_HOME/etc/apps/<任意のApp>/appserver/static/` 配下の任意の場所にタイルデータを用意すれば Splunk から利用できます。ただし、ファイルシステム内でのパスと URL のパスが順序が違うので注意が必要です。

例えば、`$SPLUNK_HOME/etc/apps/Tips/appserver/static/map_tiles/{z}/{x}/{y}`のようにタイルデータを配置したとします。この場合、URL の指定は `/static/app/Tips/map_tiles/{z}/{x}/{y}.png` のように指定します。パスの前半部分の順序が違うのと、ファイルシステムでは `apps` なのに URL では `app` と、 ”ｓ” がないことに注意してください。

また、{z}/{x}/{y}.png というのは、map_tiles ディレクトリ配下に各ズームレベルのディレクトリ(0 1 2 ...) があり、それぞれのズームレベルのディレクトリ配下に {x}、更に各 {x} に対して {y}.png のタイル画像が配置されているという意味です。

"Cluster Map" での設定例
![スクリーンショット 2021-08-30 18.46.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1931706/41c0d89b-569d-9622-be0a-a7204e5bb643.png)

## タイルデータを用意する

ここまでで、タイルデータさえ準備できればインターネットに接続されていない Splunk サーバでもバンドル以外の地図が利用できることを理解いただけたと思います。

ただ、取得する地図データのズームレベルにもよりますが、ダウンロードが必要なファイル数が膨大となるため手動で行うのは不可能だと思います。ちなみに、ズームレベル 0 から ズームレベル 13 まで世界全体の画像をダウンロードすると 89万以上のファイルをダウンロードすることになります。

|ズームレベル|ファイル数|
|---:|---:|
|0|1|
|1|4|
|2|16|
|3|64|
|4|256|
|5|1,024|
|6|4,096| 
|7|16,384| 
|8|65,536|
|9|262,144| 
|10|1,048,576|
|11|4,194,304|
|12|16,777,216| 
|13|67,108,864|
|合計|89,478,485|

ということで、考えるべきことが 2 つあります。

1. 自動化
2. 取得する地図領域を限定

これらについてそれぞれ考えます。

### 自動化

こんな shell script を作ってみました。何年も前に作ったので内容は詳しく覚えていないのですが、OpenStreetMap は、だんだんダウンロード速度が遅くなったり、ダウンロードしたファイルが壊れていたりと、色々と問題が発生したので変に手を入れてよくわからない感じになっています。それでも、一応動くことは確認しました。
(今思えば Python とかで書いておいたほうが良かった)

この例は国土地理院のタイルデータ用ですが、別なタイルデータが欲しい場合には 39行目の URL 部分を別なサービス用に書き換えてください。もちろん URL は[上の表](#Splunk で外部地図サービスを利用するには)にあるものが使えます。

`download_tile.conf` はタイルを取得する範囲を指定する設定ファイルですが、こちらは後述します。

```shell:download_tile_gsi.sh
#!/bin/bash

SKIP_EXIST=TRUE
PARALLEL=TRUE
SKIP_RANDOM=FALSE

while read line; do
    line=`echo ${line} | sed "s/ //g"`
    z=`echo ${line} | cut -d , -f 1`
    MIN_X=`echo ${line} | cut -d , -f 2`
    MAX_X=`echo ${line} | cut -d , -f 3`
    MIN_Y=`echo ${line} | cut -d , -f 4`
    MAX_Y=`echo ${line} | cut -d , -f 5`
    if [ ! -d $z ]; then
        mkdir $z
    fi
    cd $z
    for x in `seq ${MIN_X} ${MAX_X}`; do
        if [ ! -d $x ]; then
            mkdir $x
        fi
        cd $x
        y=${MIN_Y}
        while [ $y -le ${MAX_Y} ]; do
            echo z=$z, x=$x, y=$y
            if [ -s ${y}.png -a ${SKIP_EXIST}=TRUE ]; then
                echo "file already exists. skipping..."
                if [ ${PARALLEL} = "TRUE" ]; then
                    break
                fi
                if [ ${SKIP_RANDOM} = "TRUE" ]; then
                    y=$((y+RANDOM*20/32768))
                    if [ $y -gt ${MAX_Y} ]; then
                        break
                    fi
                fi
            else
                touch $y.png
                curl -m 3 --retry 5 "https://cyberjapandata.gsi.go.jp/xyz/std/${z}/${x}/${y}.png " > ${y}.png
                if [ ! -s ${y}.png ]; then
                    echo "file ${y}.png is empty. removing"
                    rm ${y}.png
                fi
            fi
            y=$((y+1))
        done
        cd ..
    done
    cd ..
done < download_tile.conf
```

### 取得する地図領域を限定
用途にもよりますが、いくら自動化されるとはいえ、ズームレベルの高い海外のタイルデータはいらない(少なくとも私は日本だけでよかった)ので、日本の領土範囲を上記の[タイル座標確認ツール](https://gsj-seamless.jp/labs/tools/tileCoord.html)で確認しました。その結果が下記となります。

```sh:download_tile.conf
0, 0, 0, 0, 0
1, 0, 1, 0, 1
2, 0, 3, 0, 3
3, 0, 7, 0, 7
4, 0, 15, 0, 15
5, 0, 31, 0, 31
6, 53, 59, 22, 28
7, 106, 117, 44, 56
8, 210, 232, 91, 113
9, 430, 475, 182, 226
10, 861, 950, 365, 452
11, 1723, 1900, 731, 905
12, 3445, 3742, 1464, 1765
13, 6890, 7484, 2928, 3531
```

各行が、

```
ズームレベル, {x}の最小値, {x}の最大値, {y}の最小値, {y}の最大値
```
という形式になっていますので、日本国外の領域を取得したい場合や、さらに高いズームレベルも欲しい場合には参考にしてください。

# 最後に

本記事ではインターネット上の地図サービスからタイルデータをダウンロードし、インターネットに接続されていない環境でも、Splunk にバンドルされている地図以外の地図を利用する方法について説明しました。

ただ、実際に**タイルデータをダウンロードして利用する際には利用許諾について事前に確認してください**。

調べた限りでは、OpenStreetMap の地図データは CC-BY-SA 2.0 となっており、自由に利用が可能です。
https://openstreetmap.jp/terms_and_privacy

国土地理院の地図も自由に利用が可能で、商用利用も認められているように読めるのですが、出典の記載等いくつかの遵守事項がありますので、利用の際には下記利用規約を確認してください。
https://www.gsi.go.jp/kikakuchousei/kikakuchousei40182.html

それ以外の Google Map や CARTO map については確認しておりませんので、各自ご確認ください。