1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

水位流量観測所を地図上で探したい ~WebGIS編~

Posted at

はじめに

本記事は、以下の記事の続きです。まだご覧になっていない方は、先にQGIS編をご覧ください。

ちなみに、前回触れませんでしたが、水文水質データベースには「地図からの検索」という機能がちゃんとあります。ですが、個人的にはコレジャナイ感が強いです。(触れば私が言いたいことは分かると思います)

そのため、本記事では水位流量観測所を可視化するWebGISを構築して国土交通省に「地図からの検索」機能を改善してくれたら嬉しいよアピールをしていきます。

必要となるツール等

前回に比べると河川技術者には馴染みのないものが増えていますが、Web上で公開するために必要なのでご了承ください。

  • 前回作ったデータ
  • QGIS 3.40
  • GitHubのアカウント
  • Renderのアカウント

手順

今回のおおまかな流れは以下の通りです。

  • ベクトルタイルに変換する
  • ベクトルタイルを配信する
  • MapLibre上で可視化する

ベクトルタイルって何?という方に向けて国土地理院の説明ページも載せておきますが、現時点では理解していなくても問題ないです。

では、早速やってみましょう。

ベクトルタイルに変換する

さて、前回やった通り、QGIS上に水位流量観測所のポイントを表示させておきましょう。
(私は調子に乗って山梨県の水位流量観測所も追加しました)
image.png

作成したポイントデータをそのままWebGISに載せることも可能なのですが、もし誰かが血迷って全国の観測所を全てポイントデータにした場合、表示するポイントの数が多くなり、描画パフォーマンスが低下する(要するに描画までに時間がかかる)ことが懸念されます。

そのため、今回はポイントデータを「ベクトルタイル」という形式に変換をします。変換自体はQGISで簡単にできるので、やってみましょう。

QGISのメニューから プロセシング > ツールボックス を選択します。
image.png

プロセシングツールボックスの検索欄に「mbtiles」と入力し、ベクタタイルを書き出し(MBTiles)という機能を起動します。
image.png

ダイアログが表示されるので、以下のように設定します。

  • 入力レイヤ:(水位流量観測所のポイントレイヤ)
  • 最小ズーム:5
  • 最大ズーム:18
  • 領域:レイヤから計算 > (水位流量観測所のポイントレイヤ)
  • 出力先タイル:(任意の出力先)
    image.png

実行ボタンを押すと、指定した出力先にベクトルタイルが書き出されます。広範囲のデータを変換する場合、処理時間が長くなることが懸念されます。どうしても許容できないレベルで遅い場合は、処理を中断して最大ズームレベルを下げてから再実行してください。
(地理院タイルに合わせて5~18で指定していますが、16とかに下げても問題ないと思います)

書き出されたMBTilesは一度QGISに読み込んで、確認しておきましょう。(ドラッグ&ドロップすれば簡単に読み込めます)
image.png

ベクトルタイルを配信する

さて、作成したMBTilesをインターネット上で配信してみましょう。

事前にGitHubRenderのアカウントを作成しておいてください。(GitHubアカウントを作ってから、作ったGitHubアカウントでRenderにログインする、という手順を推奨します)

アカウントが作成できたら、以下のリポジトリページを開いてください。

READMEに書いてあるcreate your own repository from this templateをクリックすると、上記リポジトリをベースに、自身のリポジトリを作成することができます。
image.png

自分のリポジトリが作成できたら、vectorフォルダを開きます。
image.png

vectorフォルダにてAdd file > Upload filesをクリックします。
image.png

QGISで作成したMBTilesをドラッグ&ドロップでアップロードし、コミット名を適当に設定し、Commit changesをクリックします。
image.png

これでGitHub側の準備は完了です。次にRenderのDashboardにアクセスしてAdd new > Web Serviceをクリックします。
image.png

最初は何も連携されていないと思うのでGitHubのリポジトリを連携します。
image.png

多分、GitHubの認証画面に飛ばされると思うので認証情報を入力してください。無事に認証されると以下のように連携するリポジトリが選択できるようになるので、先ほど作成したリポジトリを選択して、Saveをクリックします。
image.png

Renderの画面に戻って、作成したリポジトリが表示されていればOKです。
image.png

リポジトリを指定したら、以下を設定します。

  • 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
    image.png

設定できたら、Deploy Web Serviceをクリックして、サーバーを立ち上げます。
image.png

こんな感じの画面になっていればOKです。
image.png

実感は無いかもしれませんが、この時点であなたが作成したベクトルタイルはインターネット上で配信されています。

MapLibre上で可視化する

では、配信されているはずのベクトルタイルをWebGIS上で確認してみましょう。可視化するための地図ライブラリはMapLibre GL JSを使用します。

とはいえ、河川技術者がJavaScriptをゴリゴリ書くことは想定していないので、例のごとくコピペで済ませます。ローカル上の任意の場所にindex.htmlというファイルを作成し、テキストエディタで開いた後に、以下のコードを貼り付けて下さい。

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です。
image.png

諸注意

今回ご紹介したタイル配信方法には以下の制約がありますのでご注意ください。

  • MBTilesのファイル容量は100MBまで(GitHubの仕様)
  • 最終アクセスから15分以上間隔が空くとコールドスタートが発生する(Render Freeプランの仕様)

おわりに

河川技術者の方を想定読者としたため、可能な限りコーディングを避けたやり方で可視化してみました。本来であれば、水文水質データベースの各観測所ページに飛べるようにしたり、観測所の種別によってアイコンを変えたりするべきですが、それはまたいつかの機会に取っておきます。

ちなみに、本記事ではテンプレートを活用することで全く中身を触れずに済ませたベクトルタイル配信ですが、もし興味をお持ちであれば参考となる書籍を載せておきます。昨今話題の出版社から出ている書籍なので今後どうなるのかはよく分かりませんが気になる方は是非!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?