風データをWEB地図に重ね表示する

この記事では、SDGsの目標13「気候変動への対処」をテーマに、気象データの利用方法の普及と気象関連ソリューション開発を促進することを目的としています。

今回は、オープンソースなWEB地図ライブラリであるLeafletで表示した地図上に、気象庁MSMの数値予報結果の風データを重ね表示する手順について解説していきます。

Leafletを使った基礎的なWEBアプリケーションの作成方法については、以下の記事で紹介していますので参考にしてください。

風データをWEB地図に重ね表示する

今回は、WEB地図上に風データを表示させるためのLeaflet-velocityというプラグインを使用します。

開発環境については、以下のとおりです。

OSRed Hat Enterprise Linux release 8.9 (Ootpa)
WEBサーバApache/2.4.37 (Red Hat Enterprise Linux)
JavascriptライブラリJQuery 3.7.1
GRIB2関連ツールwgrib2 v3.1.3
grib2json
WEB地図ライブラリLeaflet 1.8.0 Previous stable version, released on April 18, 2022.
地図タイルサーバOpenStreetMap(OSM)
WEB地図ライブラリプラグインleaflet-velocity Version 2
開発環境一覧

なお、本記事ではApache WEBサーバの構築に関する説明については割愛します。

leaflet-velocityをダウンロードする

leaflet-velocityはMITライセンスで提供されており、こちらからダウンロードすることができます。

distディレクトリの中にleaflet-velocity.min.cssとleaflet-velocity.min.jsが入っているので、これらをWEBサーバのディレクトリにコピーします。

$ git clone https://github.com/onaci/leaflet-velocity.git
Cloning into 'leaflet-velocity'...
remote: Enumerating objects: 752, done.
remote: Counting objects: 100% (241/241), done.
remote: Compressing objects: 100% (70/70), done.
remote: Total 752 (delta 205), reused 176 (delta 171), pack-reused 511
Receiving objects: 100% (752/752), 5.04 MiB | 19.40 MiB/s, done.
Resolving deltas: 100% (502/502), done.

$ ls
leaflet-velocity

$ cd leaflet-velocity/dist

$ ls
leaflet-velocity.css leaflet-velocity.min.css
leaflet-velocity.js leaflet-velocity.min.js

grib2jsonをビルドする

grib2jsonはMITライセンスで提供されており、こちらからダウンロードすることができます。ダウンロードしたら、ディレクトリに入って、Apache Mavenでプロジェクトをビルドします。

grib2jsonのビルド手順は、以下のとおりです。

$ git clone https://github.com/cambecc/grib2json.git
Cloning into 'grib2json'...
remote: Enumerating objects: 322, done.
remote: Counting objects: 100% (42/42), done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 322 (delta 34), reused 32 (delta 32), pack-reused 280
Receiving objects: 100% (322/322), 52.25 KiB | 7.46 MiB/s, done.
Resolving deltas: 100% (107/107), done.
$ cd grib2json
$ mvn package
・・・<途中省略>・・・
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.941 s
[INFO] Finished at: 2024-04-30T14:49:41Z
[INFO] ------------------------------------------------------------------------
$ cd target
$ tar -zxvf grib2json-0.8.0-SNAPSHOT.tar.gz
grib2json-0.8.0-SNAPSHOT/LICENSE.md
grib2json-0.8.0-SNAPSHOT/README.md
grib2json-0.8.0-SNAPSHOT/bin/
grib2json-0.8.0-SNAPSHOT/bin/grib2json
grib2json-0.8.0-SNAPSHOT/bin/grib2json.cmd
grib2json-0.8.0-SNAPSHOT/lib/slf4j-api-1.7.5.jar
grib2json-0.8.0-SNAPSHOT/lib/logback-classic-1.0.9.jar
grib2json-0.8.0-SNAPSHOT/lib/logback-core-1.0.9.jar
grib2json-0.8.0-SNAPSHOT/lib/joda-time-2.3.jar
grib2json-0.8.0-SNAPSHOT/lib/javax.json-1.0.3.jar
grib2json-0.8.0-SNAPSHOT/lib/jewelcli-0.8.8.jar
grib2json-0.8.0-SNAPSHOT/lib/grib-4.3.19.jar
grib2json-0.8.0-SNAPSHOT/lib/netcdf-4.3.19.jar
grib2json-0.8.0-SNAPSHOT/lib/udunits-4.3.19.jar
grib2json-0.8.0-SNAPSHOT/lib/commons-httpclient-3.1.jar
grib2json-0.8.0-SNAPSHOT/lib/commons-codec-1.2.jar
grib2json-0.8.0-SNAPSHOT/lib/jcl-over-slf4j-1.7.5.jar
grib2json-0.8.0-SNAPSHOT/lib/jdom2-2.0.4.jar
grib2json-0.8.0-SNAPSHOT/lib/jcip-annotations-1.0.jar
grib2json-0.8.0-SNAPSHOT/lib/jna-3.0.9.jar
grib2json-0.8.0-SNAPSHOT/lib/quartz-2.1.1.jar
grib2json-0.8.0-SNAPSHOT/lib/c3p0-0.9.1.1.jar
grib2json-0.8.0-SNAPSHOT/lib/protobuf-java-2.5.0.jar
grib2json-0.8.0-SNAPSHOT/lib/ehcache-core-2.6.2.jar
grib2json-0.8.0-SNAPSHOT/lib/je-4.0.92.jar
grib2json-0.8.0-SNAPSHOT/lib/jsoup-1.7.2.jar
grib2json-0.8.0-SNAPSHOT/lib/grib2json-0.8.0-SNAPSHOT.jar
$ cd grib2json-0.8.0-SNAPSHOT/bin
$ ls
grib2json grib2json.cmd

作成されたgrib2jsonのロードモジュールに対して、.bashrcなどにエイリアスを設定しておくとよいでしょう。

風データを作成する

leaflet-velocityに入力するデータはJSON形式で作成されている必要があります。このデータは、grib2jsonを利用して簡単に作成することができます。

今回は、気象庁MSMの地上10m風速成分をWEB地図上に重ね表示させていきます。気象庁MSMのgrib2データは、流体電脳倶楽部からダウンロードさせていただきました。

grib2jsonに入力するgrib2データは、東西成分ベクトルと南北成分ベクトルがセットになったものである必要があります。このため、米国海洋大気庁(NOAA)から提供されているwgrib2というツールを使って、東西成分ベクトルと南北成分ベクトルがセットになった新しいgrib2データを作成していきます。

以下の例では、初期時刻における地上10mの東西成分ベクトルと南北成分ベクトルのデータをwgrib2で抽出して、新しいgrib2データファイル(10m_wind_vector.grib2.bin)を作成しています。

$ ls
Z__C_RJTD_20240430000000_MSM_GPV_Rjp_Lsurf_FH00-15_grib2.bin
$ wgrib2 Z__C_RJTD_20240430000000_MSM_GPV_Rjp_Lsurf_FH00-15_grib2.bin
1.1:0:d=2024043000:PRMSL:mean sea level:anl:
1.2:0:d=2024043000:PRES:surface:anl:
1.3:0:d=2024043000:UGRD:10 m above ground:anl:
1.4:0:d=2024043000:VGRD:10 m above ground:anl:
1.5:0:d=2024043000:TMP:1.5 m above ground:anl:
1.6:0:d=2024043000:RH:1.5 m above ground:anl:
1.7:0:d=2024043000:LCDC:surface:anl:
1.8:0:d=2024043000:MCDC:surface:anl:
1.9:0:d=2024043000:HCDC:surface:anl:
・・・<途中省略>・・・
$ wgrib2 Z__C_RJTD_20240430000000_MSM_GPV_Rjp_Lsurf_FH00-15_grib2.bin -match "(UGRD|VGRD):10 m above ground:anl:" -grib 10m_wind_vector.grib2.bin
1.3:0:d=2024043000:UGRD:10 m above ground:anl:
1.4:0:d=2024043000:VGRD:10 m above ground:anl:
$ wgrib2 10m_wind_vector.grib2.bin
1:0:d=2024043000:UGRD:10 m above ground:anl:
2:364537:d=2024043000:VGRD:10 m above ground:anl:

次に新たに作成したgrib2データ(10m_wind_vector.grib2.bin)をgrib2jsonツールに入力して、leaflet-velocityが読み込み可能なJSON形式ファイル(10m_wind_vector.json)を作成します。

$ grib2json --names --data --o 10m_wind_vector.json 10m_wind_vector.grib2.bin
$ ls
10m_wind_vector.grib2.bin
10m_wind_vector.json
Z__C_RJTD_20240430000000_MSM_GPV_Rjp_Lsurf_FH00-15_grib2.bin

WEB地図を実装する

ここからは、WEBアプリケーションを実装していきます。

参考まで、今回のWEBサーバにおけるディレクトリ配置は以下のとおりです。

$ tree
html
└── leaflet
├── css
│   ├── index.css
│   ├── leaflet-velocity.min.css
│   └── leaflet.css
├── data
│   └── 10m_wind_vector.json
├── images
│   ├── layers-2x.png
│   ├── layers.png
│   ├── marker-icon-2x.png
│   ├── marker-icon.png
│   └── marker-shadow.png
├── index.html
└── js
├── jquery-3.7.1.min.js
├── leaflet-velocity.min.js
└── leaflet.js

5 directories, 13 files

index.htmlコードの全体は、以下のとおりです。

<!DOCTYPE html>
<html>
<head>
<!-- CSS -->
<link rel="stylesheet" href="./css/index.css" />
<!-- JQuery -->
<script src="./js/jquery-3.7.1.min.js"></script>
<!-- Leaflet -->
<link rel="stylesheet" href="./css/leaflet.css" />
<script src="./js/leaflet.js"></script>
<!-- leaflet-velocity -->
<link rel="stylesheet" href="./css/leaflet-velocity.min.css" />
<script src="./js/leaflet-velocity.min.js"></script>
<script>
function mapinit() {
// 地図レイヤーの設定
var map = L.map('map').setView([36.0,135.0],5);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
}).addTo(map);
// JSONファイル読み込み及び風ベクトルレイヤーの設定
$.getJSON("./data/10m_wind_vector.json", function(data){
var windLayer = L.velocityLayer({
displayValues: true, // 方位と流速を表示する
displayOptions: {
velocityType: "MSM 10m wind", // 方位と流速表示のタイトル
position: "bottomleft", // 方位と流速表示位置
angleConvention: "meteoCW", // 流れの向きの表現
showCardinal: false, // 文字による方位表示
speedUnit: "ms", // 流速の単位
directionString: "dir", // 方位表示の文字列
speedString: "spd", // 流速表示の文字列
},
data: data,
maxVelocity: 15.0, // 流速がスケールの最大に達する値
minVelocity: 0.0, // 流速がスケールの最小に達する値
velocityScale: 0.03, // ベロシティの長さ
colorScale: [ // カラースケール
"rgb(36,104,180)", // 遅い流速側
"rgb(60,157,194)",
"rgb(128,205,193)",
"rgb(151,218,168)",
"rgb(198,231,181)",
"rgb(238,247,217)",
"rgb(255,238,159)",
"rgb(252,217,125)",
"rgb(255,182,100)",
"rgb(252,150,75)",
"rgb(250,122,52)",
"rgb(245,64,32)",
"rgb(237,45,28)",
"rgb(220,24,32)",
"rgb(180,0,35)" // 早い流速側
],
opacity: 0.97, // 透過率
}).addTo(map);
});
}
</script>
<title>Leaflet Test Page</title>
</head>
<body onload="mapinit()">
<div id="map"></div>
</body>
</html>

Javascriptのmapinit()関数の中では、地図を表示するタイルレイヤーと風を表示するベロシティレイヤーの2つを設定しています。

地図を表示するタイルレイヤーの設定では、L.map()メソッドで地図オブジェクトを作成し、setView()メソッドでデフォルト表示する地図の中心緯度経度とズームレベルを設定し、地図オブジェクトmapに追加しています。

また、利用するタイル地図のURLと著作権情報を、L.tileLayer()メソッドに設定しています。タイル地図は、設定したURLからオンデマンドで非同期に取得され、ユーザがインタラクティブに地図を操作できるようになります。

     // 地図レイヤーの設定
var map = L.map('map').setView([36.0,135.0],5);
L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
}).addTo(map);

風を表示するベロシティレイヤーの設定では、JQueryを利用してJSONファイル(10m_wind_vector.json)を読み込み、ベロシティレイヤーにおける各種項目について設定し、地図オブジェクトmapに追加しています。

各設定項目の詳細な説明は割愛しますが、実際に各種値を変更してどのように表示が変化するか是非体験してください。

      // JSONファイル読み込み及び風ベクトルレイヤーの設定
$.getJSON("./data/10m_wind_vector.json", function(data){
var windLayer = L.velocityLayer({
displayValues: true, // 方位と流速を表示する
displayOptions: {
velocityType: "MSM 10m wind", // 方位と流速表示のタイトル
position: "bottomleft", // 方位と流速表示位置
angleConvention: "meteoCW", // 流れの向きの表現
showCardinal: false, // 文字による方位表示
speedUnit: "ms", // 流速の単位
directionString: "dir", // 方位表示の文字列
speedString: "spd", // 流速表示の文字列
},
data: data,
maxVelocity: 15.0, // 流速がスケールの最大に達する値
minVelocity: 0.0, // 流速がスケールの最小に達する値
velocityScale: 0.03, // ベロシティの長さ
colorScale: [ // カラースケール
"rgb(36,104,180)", // 遅い流速側
"rgb(60,157,194)",
"rgb(128,205,193)",
"rgb(151,218,168)",
"rgb(198,231,181)",
"rgb(238,247,217)",
"rgb(255,238,159)",
"rgb(252,217,125)",
"rgb(255,182,100)",
"rgb(252,150,75)",
"rgb(250,122,52)",
"rgb(245,64,32)",
"rgb(237,45,28)",
"rgb(220,24,32)",
"rgb(180,0,35)" // 早い流速側
],
opacity: 0.97, // 透過率
}).addTo(map);
});

次に、地図を表示するためのコンテナのサイズをindex.cssに記述します。

#map {
height: 600px;
width : 800px;
margin: 0 auto;
}

これでWEB地図上に風データを重ね表示するコードの作成が完了しました。

地図を表示させてみる

では、WEB地図上に風データを重ねたWEBアプリに実際にアクセスしてみましょう。地図上で風の流れが動画のように表示されるはずです。

次に、地図をズームインして特定の地点上にマウスオーバーしてみましょう。左下にマウスオーバーした地点の風向と風速の情報が表示されます。

まとめ

いかがでしたでしょうか。

今回は、オープンソースなWEB地図ライブラリであるLeafletとleaflet-velocityを使って、地図上に気象庁MSMの風情報を表示するインタラクティブなWEBアプリの実装方法について紹介しました。

通常、気象予報の現場においては、天気図上に表示された矢羽から風向風速を読み取ることが一般的ですが、この場合は各地点の詳細な風向風速を読み取ることはとても困難です。

また、風の流れにより発生する気流の収束が局地的な雲の発生や降水現象を引き起こすため、現業を行う上で風の把握は重要なポイントになります。

Leaflet-velocityを活用することで、各地点の風向風速や気流の収束が地図上で一目瞭然となるため、気象予報業務の効率化と予報精度の向上に貢献できるかもしれません。

Leaflet-velocityを海流データにも応用することで、漁業や海運業における船舶の安全な航行にも貢献することができることでしょう。

参考になれば幸いです。

気象データ利用のお悩みについてご相談ください

気象データの利用に関するお悩みは、こちらからお問い合わせください。
気象システムの設計製造及び運用保守にかかわる現役システムエンジニアが、気象予報士の視点で気象データを活用したビジネスアイディアの創出と課題解決のお手伝いをさせていただきます。
気象や波浪などの数値予報モデルを活用した気象予報システム開発や運用についても是非ご相談ください。