はじめに
本記事は、以下の記事の続きです。まだご覧になっていない方は、先にQGIS編をご覧ください。
ちなみに、前回触れませんでしたが、水文水質データベースには「地図からの検索」という機能がちゃんとあります。ですが、個人的にはコレジャナイ感が強いです。(触れば私が言いたいことは分かると思います)
そのため、本記事では水位流量観測所を可視化するWebGISを構築して国土交通省に「地図からの検索」機能を改善してくれたら嬉しいよアピールをしていきます。
必要となるツール等
前回に比べると河川技術者には馴染みのないものが増えていますが、Web上で公開するために必要なのでご了承ください。
手順
今回のおおまかな流れは以下の通りです。
- ベクトルタイルに変換する
- ベクトルタイルを配信する
- MapLibre上で可視化する
ベクトルタイルって何?という方に向けて国土地理院の説明ページも載せておきますが、現時点では理解していなくても問題ないです。
では、早速やってみましょう。
ベクトルタイルに変換する
さて、前回やった通り、QGIS上に水位流量観測所のポイントを表示させておきましょう。
(私は調子に乗って山梨県の水位流量観測所も追加しました)
作成したポイントデータをそのままWebGISに載せることも可能なのですが、もし誰かが血迷って全国の観測所を全てポイントデータにした場合、表示するポイントの数が多くなり、描画パフォーマンスが低下する(要するに描画までに時間がかかる)ことが懸念されます。
そのため、今回はポイントデータを「ベクトルタイル」という形式に変換をします。変換自体はQGISで簡単にできるので、やってみましょう。
QGISのメニューから プロセシング
> ツールボックス
を選択します。
プロセシングツールボックスの検索欄に「mbtiles」と入力し、ベクタタイルを書き出し(MBTiles)
という機能を起動します。
ダイアログが表示されるので、以下のように設定します。
実行
ボタンを押すと、指定した出力先にベクトルタイルが書き出されます。広範囲のデータを変換する場合、処理時間が長くなることが懸念されます。どうしても許容できないレベルで遅い場合は、処理を中断して最大ズームレベルを下げてから再実行してください。
(地理院タイルに合わせて5~18で指定していますが、16とかに下げても問題ないと思います)
書き出されたMBTilesは一度QGISに読み込んで、確認しておきましょう。(ドラッグ&ドロップすれば簡単に読み込めます)
ベクトルタイルを配信する
さて、作成したMBTilesをインターネット上で配信してみましょう。
事前にGitHubとRenderのアカウントを作成しておいてください。(GitHubアカウントを作ってから、作ったGitHubアカウントでRenderにログインする、という手順を推奨します)
アカウントが作成できたら、以下のリポジトリページを開いてください。
READMEに書いてあるcreate your own repository from this template
をクリックすると、上記リポジトリをベースに、自身のリポジトリを作成することができます。
自分のリポジトリが作成できたら、vectorフォルダを開きます。
vectorフォルダにてAdd file
> Upload files
をクリックします。
QGISで作成したMBTilesをドラッグ&ドロップでアップロードし、コミット名を適当に設定し、Commit changes
をクリックします。
これでGitHub側の準備は完了です。次にRenderのDashboardにアクセスしてAdd new
> Web Service
をクリックします。
最初は何も連携されていないと思うのでGitHubのリポジトリを連携します。
多分、GitHubの認証画面に飛ばされると思うので認証情報を入力してください。無事に認証されると以下のように連携するリポジトリが選択できるようになるので、先ほど作成したリポジトリを選択して、Save
をクリックします。
Renderの画面に戻って、作成したリポジトリが表示されていればOKです。
リポジトリを指定したら、以下を設定します。
- Region:シンガポール(別に変えなくてもいい)
- Build Command:
pip install uv && uv sync --frozen
- Start Command:
uv run uvicorn main:app --host 0.0.0.0 --port $PORT
- Instance Type:Free
設定できたら、Deploy Web Service
をクリックして、サーバーを立ち上げます。
実感は無いかもしれませんが、この時点であなたが作成したベクトルタイルはインターネット上で配信されています。
MapLibre上で可視化する
では、配信されているはずのベクトルタイルをWebGIS上で確認してみましょう。可視化するための地図ライブラリはMapLibre GL JSを使用します。
とはいえ、河川技術者がJavaScriptをゴリゴリ書くことは想定していないので、例のごとくコピペで済ませます。ローカル上の任意の場所にindex.html
というファイルを作成し、テキストエディタで開いた後に、以下のコードを貼り付けて下さい。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>水位流量観測所 デモ</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<link
href="https://unpkg.com/maplibre-gl@4.1.0/dist/maplibre-gl.css"
rel="stylesheet"
integrity="sha384-m6tadjb5ohv1Fw3GJynIWn5c1scKfW7kxSXuDrhlq1gdXPn7I7UL0sSKDfCUErOb"
crossorigin="anonymous"
/>
<script
src="https://unpkg.com/maplibre-gl@4.1.0/dist/maplibre-gl.js"
integrity="sha384-3pNy86i5zyrCrbNJElT1ZPPx8EaXDW676Upmm6GTpZsvYkot0AZeCGAolgBQKCBg"
crossorigin="anonymous">
</script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
// 以下の3つの定数を修正してください。
const TILE_SERVER_URL = 'https://observation-station.onrender.com'; // ご自身のデプロイしたサーバーURL
const MBTILES_FILE_NAME = 'observation_station' // MBTilesのファイル名(xxx.mbtilesの「xxx」の部分)
const LAYER_NAME = '水位流量観測所_ポイント' // MBTilesを作成した時のポイントレイヤの名前
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [139.767, 35.681],
zoom: 5 // Zoom level to show entire Japan
});
map.addControl(new maplibregl.NavigationControl(), 'top-right');
map.on('load', () => {
// Add raster tile layer
map.addSource('raster-source', {
'type': 'raster',
'tiles': [
`https://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png`
],
'tileSize': 256,
'attribution': '地理院タイル'
});
map.addLayer({
'id': 'raster-layer',
'type': 'raster',
'source': 'raster-source',
'paint': {
'raster-opacity': 1.0
},
'layout': {
'visibility': 'visible'
}
});
// Add vector tile layer (Observation Stations)
map.addSource('vector-source', {
'type': 'vector',
'tiles': [
`${TILE_SERVER_URL}/vector/${MBTILES_FILE_NAME}/{z}/{x}/{y}.pbf`
],
'attribution': '国土交通省 水文水質データベースを加工して作成'
});
map.addLayer({
'id': 'vector-layer',
'type': 'circle',
'source': 'vector-source',
'source-layer': LAYER_NAME,
'paint': {
'circle-radius': 5,
'circle-color': 'rgba(255, 0, 0, 0.7)',
'circle-stroke-color': 'rgba(255, 0, 0, 1)',
'circle-stroke-width': 1
},
'layout': {
'visibility': 'visible'
}
});
map.addLayer({
'id': 'label-layer',
'type': 'symbol',
'source': 'vector-source',
'source-layer': LAYER_NAME,
'layout': {
'text-field': ['get', '観測所名'],
'text-font': ['Noto Sans Regular'],
'text-size': 12,
'text-anchor': 'top',
'text-offset': [0, 1]
},
'paint': {
'text-color': '#000000',
'text-halo-color': '#FFFFFF',
'text-halo-width': 1
}
});
});
</script>
</body>
</html>
変更が必要なのは以下の部分です。
const TILE_SERVER_URL = 'https://observation-station.onrender.com'; // ご自身のデプロイしたサーバーURL
const MBTILES_FILE_NAME = 'observation_station' // MBTilesのファイル名(xxx.mbtilesの「xxx」の部分)
const LAYER_NAME = '水位流量観測所_ポイント' // MBTilesを作成した時のポイントレイヤの名前
変更したら、index.html
をダブルクリックしてブラウザで見てみましょう。以下のように、水位流量観測所が赤丸で示されている地図が表示されればOKです。
諸注意
今回ご紹介したタイル配信方法には以下の制約がありますのでご注意ください。
- MBTilesのファイル容量は100MBまで(GitHubの仕様)
- 最終アクセスから15分以上間隔が空くとコールドスタートが発生する(Render Freeプランの仕様)
おわりに
河川技術者の方を想定読者としたため、可能な限りコーディングを避けたやり方で可視化してみました。本来であれば、水文水質データベースの各観測所ページに飛べるようにしたり、観測所の種別によってアイコンを変えたりするべきですが、それはまたいつかの機会に取っておきます。
ちなみに、本記事ではテンプレートを活用することで全く中身を触れずに済ませたベクトルタイル配信ですが、もし興味をお持ちであれば参考となる書籍を載せておきます。昨今話題の出版社から出ている書籍なので今後どうなるのかはよく分かりませんが気になる方は是非!