風データをビジュアルに表現する

こんにちは、梶原です。
これは TECHSCORE Advent Calendar 2015 の13日目の記事です。

wind

衝撃のビジュアル表現

あれは忘れもしません。大阪の環状線を止めるほどの台風が来た日の事です。

テレビを観ていると、NHKが天気・災害情報を放送していましたが、とてもカッコよく、わかりやすいビジュアル表現をしていました。画面上には「DIGITAL EARTH」と記載されており、NHKの新システムだったようです。

(参考) 「NHKデジタルアース」が凄い

特に風の表現に衝撃を受けたので、色々調べてみると、世界風速は、とても良くできていて、フリーバージョンはソースが公開されています

そこで世界風速のソースや、気象データ処理や地図表現についても、調べたのでまとめてみました。

ソースはこちらに置いておきます。

地図表現

ビジュアル表現に、地図表現はつきもの!

という訳で、こちらは色々な手法があると思いますが、ブラウザで表示したかったので、D3.jsを利用する方法が一番簡単に実現できそうでした。海岸線を非常に簡単にSVG描画できます。海岸線情報自体は、Natural Earthを利用させていただく事にしました。

上記サイトで手に入るShapeデータを、GeoJSONに変換して、さらにより効率的に処理する為TopoJSONに変換して描画するのが一般的のようです。

(参考) D3.js と TopoJSONで地図を作る

出来上がったmap_topo.jsonを利用するhtml/javascriptを作成し、httpサーバに置くと

01_map

ね、簡単でしょ(汗)!ソースはgithubにおいてみました。

こだわりポイントとしては、

  • 緯度経度線があるとかっこいい
  • 海岸線はくっきり
  • 地図図法の"それっぽさ"は大事なので、正射図法を利用

あたりでしょうか。なおモンゴルが欠けているのは秘密です。余力のある方は、Natural Earthの湖データを利用して琵琶湖を描いてみてください。

地図を描画できる事が一番重要ですが、座標変換ロジックが関数として再利用できる事も重要です。
なぜなら次の気象データは、「緯度A、経度Bの風向きは〜」という形で得られる為、緯度A, 経度B地点を、画面上の座標に変換できる必要があります。上記の場合、下記のような変数に入れて後で利用します。

気象データ処理

最近気象データの多くは、「GRIB2」形式というファイルフォーマットで配信される事が多いです。しかし、このフォーマットはとても複雑で、とても自分でparserを書けるようなものではない事がわかりました。

(参考) ファイルフォーマットを日本語で説明されています

行いたい事はデータを利用する事ですので、先人の肩にのるべく調べると、 wgrib2というツールで、ダンプできる事がわかりました。下記のような手順でコンパイル可能です。

(参考) コンパイル手順

wgrib2/wgrib2が出来上がったツールになります。試しに動かしてみると...

気象データ自体はNOMADSや、学術目的なら地球流体電脳倶楽部あたりで見つける事ができました。

# 業務で気象データを扱う際は、気象業務支援センターより購入する必要があります。

ここではNOMADSから、下記ファイルー条件でデータダウンロードしてみます。grib filterから条件を選択してダウンロードできます。

  • 2015/12/11
  • 緯度経度の刻みは0.25
  • 高度は、10 m above ground
  • 風の強さなので、VGRD/UGRD

http://nomads.ncep.noaa.gov/cgi-bin/filter_gfs_0p25.pl?file=gfs.t00z.pgrb2.0p25.f000&lev_10_m_above_ground=on&var_UGRD=on&var_VGRD=on&dir=%2Fgfs.2015121100

データを先ほどのwgrib2で見てみると、どんなデータが含まれているかわかります。

wgrib2には非常に多くのオプションがありますので、

  • データのみ
  • 南北方向を北から南に変換
  • 1データ4byte浮動小数点(big endian)

としてダンプしてみます。

いい感じですね。1440 * 721 * 4 = 4152960なので、ちゃんとダンプできている事がわかります。

ただ、結構ファイルサイズが大きくなるので、精度を落として1データ1byteにするとか、必要な緯度経度内に絞る、gzip圧縮する等、色々工夫はできると思います(ここでは説明を簡単にする為、このまま進めます)。

また〜U.ieeeのあとに〜V.ieeeを連結して1度にダウンロードできるようにします(こちらも簡単の為)。

風のビジュアル表現に挑戦

さて、ここまでで道具は揃ったので、風のビジュアル表現をしてみようと思います。

先ほど処理した風データは、ある地点でのUV方向の風の強さを表現したデータ、すなわちベクトル場といえる為、そこを漂う粒子として可視化します。

具体的には

  • 風データをダウンロードして、javascript上でベクトル場データを準備。
  • 多くの粒子を、範囲内にランダムに配置、寿命を設定する。
  • 毎描画フレーム毎に
    • 粒子座標の風の強さを、ベクトル場データから補間によって求め、次の粒子の座標を再計算する。
    • 範囲外に出てしまった、もしくは寿命に達したら、再度ランダムに粒子を配置する。
    • 粒子の移動(前回と今回の座標)を線で描画。

というステップで描画してみます。いわゆるパーティクルシステムのアプローチの一つになります。

実際に描画時には幾つか必要なテクニックがありました。

  • ベクトル場データの補間は簡単の為、近傍4点での線形補間にしました。
  • canvasでの描画の際に、beginPath / moveTo / lineTo / stroke を、1粒子毎に実行すると一気にフレームレートが落ちます。風の強さで色を変える等の機能を実装する際には注意が必要になります。
  • 粒子の軌跡を残像として描画すると見た目がぐっと良くなります。こちらは、冒頭の世界風速で利用されているテクニックが大変参考になりました。

詳細は、ソースをご確認ください。当記事作成の為急いで書いたので、不備はご容赦ください(汗)

動かすと下記のような風の表現がアニメーションします。 是非動かしてみてください。
githubからclone後、01~03のshを実行すると、必要なデータは、ダウンロードできると思います(関連するプロダクトは参照ページを参考にご準備下さい)。

wind

世界風速や、DIGITAL EARTHで表現している手法を学ぶ入り口になっている事は、見てとれると思います。

さらに...

今回は、風データを固定された日時のデータを1つ利用して描画しました。

お気づきの方もいらっしゃると思いますが、時系列に並んだ複数のデータを利用して、補間しつつ描画する事によって、「時事刻々と変わる風向き、風の強さ」を表現する事ができます。

今回はコードの整理が間に合わなかったので、またの機会がありましたら投稿してみようと思います。

最後まで読んで頂きありがとうございました。

Comments are closed, but you can leave a trackback: Trackback URL.

Advent Calendar 2015の連載記事

  1. TECHSCORE Advent Calendar 2015
  2. Redshift と PostgreSQL に同時に JDBC 接続する
  3. Lombok で Spice up your Java!
  4. 画像を指定するだけ!非デザイナーでも簡単にそれっぽい配色ができるツールを作ってみた
  5. 新卒文系エンジニアの記録:配属半年間の失敗を振り返ってみた
  6. 非同期処理のすすめ
  7. ioDrive2の導入で支える、そのIOPS - 導入検討編.
  8. GoでパイプラインからSlackに通知する
  9. fuse でオレオレファイルシステムを作ってみた (Haskell で)
  10. Erlang はじめました
  11. ちょっと地味なビルドとリリースの話 (レガシーシステム改革、はじめの一歩)
  12. Java8 最速 boolean[] to Stream 選手権
  13. Google Apps の Directory API にてWebブラウザを介さずに認証する
  14. 風データをビジュアルに表現する
  15. マイクロフレームワーク「Ninja」を使ってみる
  16. 赤ちゃんvimmerからよちよちvimmerにクラスチェンジを果たすためのTips
  17. PostgreSQL FDW を作ってSQLでログ検索してみた
  18. Goで偽名ジェネレータを作りました
  19. 書き込み中に削除されたファイルを救出する
  20. 運用情報更新のススメ
  21. ちゃんと読んでくれましたか?
  22. Presto コネクターを実装する 第三回
  23. Ruby2.3を触ってみる
  24. Git 困ったときのtips集
  25. 5分で読む入門編:Java 8 ラムダ式 コレクション編(2)リストの検索
  26. CloudFront (+ S3) + JWPLAYER で様々なデバイスのブラウザから動画をストリーミング再生する