2018年3月26日
気象庁防災情報XMLの受信と周辺サービスをGCPに移行した話
そろそろ何かアウトプットしておかないとNo Activityマンになってしまうと思いつつも色々やることは山積みで筆の捗らない今日この頃、みなさんいかがお過ごしでしょうか。
さて、2015年12月にEVI 地震火山詳報を公開してから約2年と3ヶ月(その前身の桜島詳報から数えると3年7ヶ月)が経過しました。
実は、2017年10月頃のConoHaの障害によりサブスクライバが長時間止まってしまい、気象庁のPuSH配信から外されたため同月よりEVIのサービスが停止しておりました。
この際、本業(ゲヒルン=UN_NERVへ作画提供)でも震源・震度地図の作画エンジンを作っているので完全にサービスを畳んでしまおうかとも思ったのですが...
振り返って周りを見てみれば、インタラクティブな震源・震度マップに挑戦している方が意外と少なく、作画方法も本業の仕組みとは全く異なるので 防災情報デザインに関する異なるアプローチの研究 ということで緩く継続してみようと思い立った訳です。
#防災情報デザイン、特に地震に関するものに関しては、様々な方が主にUN_NERVで提供されている地図デザインをパクって何度も何度も車輪の再発明をされていますが、みなさん少しは配色を変えてオリジナリティを出したり、「俺ならこうする!」といった伝え方の工夫を取り込んでみてはいかがでしょうか...? 芸が無さすぎて全くつまらんです。
EVI 地震火山詳報のサービスと後ろ側については、以前書いた記事をご覧ください。
地震とか火山噴火情報を閲覧できるWebサイトを作った (2015年12月)
上記の記事の通り、EVIは後ろ側がかなり複雑に絡み合っており、機能追加や改修をするにも面倒になっていました。
また、受信したXMLや生成したGeoJSON、画像の保管も同じインスタンス内に入っていたため、ある一定期間ごとに古いデータを削除する等のメンテナンスが必要でした。
...そこで、今回EVIを改修するにあたり以下の目標を立てて移行計画を実行することにしました。
1. 出来る限りマネージドなクラウドサービスに載る(俗にいうサーバレス)システムにする
2. 出来る限り最新の設計・構築方法、技術を用いる
3. デザインをなんかイケてる感じにする←重要
ということで、これらを念頭に置きつつ、隙間時間を使って3ヶ月ほどで作ったものがこちらになります。(冒頭のスクリーンショットのサービス)
QUAKE.ONE
https://quake.one/
#火山要素が消えたことには目をつぶってください
Twitterは以前のIDのまま Prioris_EVI を使っています。
Pushbulletも以前のままです。
日本国内で発生した全ての震源・震度情報
earthquake_jp
日本国内で発生した震度3以上の震源・震度情報
earthquake_int3over
さて、ここからは技術的なお話。
EVIからの進化ポイントは以下の通り。
1. 小さな画面を持つデバイスにおいて、操作可能な地図が非常に小さくなる問題を解決
→どの画面サイズのデバイスにおいても全画面で地図を表示し、情報をマップ上に配置する新しいデザインを採用
2. OpenLayersのバージョンアップ
→OL3から最新のOL4へ移行
3. ページを動的から静的生成に変更、SPA(single-page application)化
→地震発生をトリガーにしてレンダリング用のJSONをあらかじめ生成
4. Twitter、Pushbulletにて配信する画像形式の震源・震度地図のデザイン変更
→画像の生成方法もwkhtmltoimageからPuppeteer + Headless Chromeに刷新
また、これに伴ってサブスクライバから後ろも全て刷新しました。
構成図は以下の通り。(横に非常に長いので、拡大してご覧ください)
使用したサービスは以下の通り。
Google Cloud Platform
・App Engine
・Compute Engine
・Cloud Functions
・Cloud Datastore
・Cloud Storage
・Cloud Pub/Sub
・Firebase Hosting
地震が発生して「震源・震度に関する情報」が流れてきた時のパターンを簡単に説明すると...
1. 気象庁からPubSubHubbubでJMAXML publishing feedを受ける
2. atomを解析してEntryを取り出し、Task Queueに投げ入れ、Entryの内容をDatastoreに書き込む
3. WorkerはXMLを取得、XMLスキーマを適用してJSON形式に変換、XMLとJSONをStorageに保存し、JSONをPub/Subに流す
4. 3種のPub/Subトピックのうち地震に関係するトピックにぶら下がっているCloud Functionsが実行、Datastore内の地域コード対地域重心座標に基づいてGeoJSONを生成してStorageに保存、概要をPub/Sub(topic: quake-one)に流す
5. Pub/Sub(topic: quake-one)にぶら下がっているCloud Functionsが実行、Puppeteer(+Express)が待ち受けているGCEインスタンスに画像生成リクエストを送信
6. Headless Chromeで画像用ページを表示して撮影、Storageに保存
7. 画像生成リクエストが成功すると、当該eventIDの地震の概要と画像のURLをPub/Sub(topic: quake-one-with-image)に流す
8. Pub/Sub(topic: quake-one-with-image)にぶら下がっている各Cloud Functionsが実行、PushbulletやTwitterへ投稿
9. QUAKE.ONE はStorageを参照し、概要の入ったJSONとインタラクティブ地図描画用のGeoJSONを取得、JavaScriptでレンダリング
以前の複雑に絡み合った状態からすれば、随分とメンテナンスしやすいシステムへと変わりました。
AppEngine、Firebase Hostingは自動的にLet's EncryptでSSL証明書を更新してくれるし、しっかりキャッシュ、CDNが効いてくれます。
Storageは、ライフサイクルを設定することで、古いXMLやJSON、画像データを自動的にNear line→Cold lineと安価なストレージに移行、あるいは削除してくれます。
Cloud Functionsは実行時課金で、気象庁XMLをトリガーにして実行する程度の回数では全て無料範囲内に収まります。
唯一、画像を生成するためのPuppeteer + Headless Chromeが入っているGCEインスタンスだけは面倒を見てあげなければなりませんが、これも永続化が必要なデータやステートは持っていないので管理は楽々です。
さらに、副産物としてJMAXML JSON Viewerも出来ました。
こちらはデータ保存期間が浅い&検索が弱いので受信状況の確認程度用です。
商用利用は禁止ですので、お仕事で使いたい方はゲヒルンの気象庁XML Viewerをご契約ください。
というわけで、出来る限り新しめの手法でマネージドな感じのイケてるサービスが出来ました。
めでたし、めでたし。(終)
追記:その後の話を書きました。
続・気象庁防災情報XMLの受信と周辺サービスをGCPに移行した話
2015年12月8日
地震とか火山噴火情報を閲覧できるWebサイトを作った
作るのを思い立ってから半年くらい掛かった... (実質作業時間は短い)
地震火山詳報
http://evi.prioris.jp
地震と火山(桜島に限らない)に関する気象庁XML電文情報と、それに付随する情報を配信するWebサイトです。
これの立ち上げに伴い、桜島詳報を閉じました。
現時点では火山噴火情報は未実装ですが、統合するつもりで地震火山詳報とネーミングしたので、近々実装します。
と言っても、桜島詳報のコードをちょっと改造して合体させるだけなのですが、最近全国的に火山活動が落ち着いているのでモチベーションが...
→ 実装しました!
12月12日より、噴火に関する火山観測報も追加しました。
桜島詳報では桜島の噴火・爆発のみを扱っていましたが、地震火山詳報では桜島以外の火山(阿蘇山など)の情報を配信されます。
発生した地震の詳細ページでは、震源と揺れを観測した地域の震度がGoogle Mapsライクな操作感で閲覧できます。
例 : 震源・震度情報(2015年12月4日 5時40分頃に発生した地震) - 地震火山詳報
震源や震度のアイコンをクリックすると、上記画像のように地名や座標が表示されます。
地図はOpenStreetMapを使っています。
あとレスポンシブ対応なのでスマホでもPCでも良い感じに閲覧可能です。
地震火山詳報は、地震に関する情報をTwitterとPushbulletでも配信しています。
(Pushbulletって何?っていう人は、EngadgetとかLifehackerの記事を読むといいです。)
Twitter : @Prioris_EVI
Pushbullet : #earthquake_jp
上記Pushbulletのチャンネルは、日本全国のすべての地震(震度1〜)をプッシュ通知で教えてくれるので若干鬱陶しいです。
(日本全国でこんな頻度で地震が起きてるんだ〜!っと認識するのには最高ですが)
というわけで、震度3以上の地震があった時だけプッシュ通知してくれるチャンネルもあります。
Pushbullet : #earthquake_int3over
桜島、阿蘇山の噴火・爆発時プッシュ通知はYoにて配信しています。
Yo : SAKURAJIMA (鹿児島県 桜島の噴火・爆発時に配信)
Yo : ASOSAN (熊本県 阿蘇山の噴火・爆発時に配信)
以下の記事の集大成みたいな感じです。
PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる (2015/06)
PostGISで気象庁の細分区域&市町村等に対応する重心を求める (2015/06)
OpenLayers 3で気象庁発表の震度をマッピングする (2015/07)
OL3で扱える地図タイルをShapeから生成する (2015/12)
あと、ベースとして以下も。
桜島が噴火したYoの裏側 (2014/08)
上記の記事中にも書いていますが、気象庁XML電文から震度マップ(GeoJSON)を作るのに必要なデータやGeoJSON生成コードはオープンソースとして公開しています。
9SQ/jma-eqarea-centroid (気象庁が用いる地域区分の重心座標テーブル)
9SQ/jma-eqxml2geojson (気象庁XMLから上記テーブルを利用してGeoJSONを生成する)
9SQ/seismic-intensity-map (震度GeoJSONをOpenStreetMapにオーバーレイ表示する)
...以下詳細...
気象庁から送られてくる震源・震度に関する情報のXML電文には、発生時刻や地震の規模を表すマグニチュード、震源地の座標、津波に関するコメント、そして揺れを観測した地域の地域コードと地名、震度が含まれています。
このXML電文から、震源地の座標を地図にプロットするのは非常に簡単ですが、各地の震度を、その地域の中心となる場所にプロットするというのが結構面倒です。
というのも、気象庁は地域コードや地名のテーブルは公開していますが、その中心(厳密に言えば重心)座標は提供していません。
また、気象庁の区域割りはちょっと特殊で、例えば「石狩地方北部」みたいに、ある程度の市区町村をまとめていたりします。
そこで、まずこれらの区域の中心座標を求めよう、ということで...
1. PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる (2015/06)
国土交通省から提供されている行政区域(群市区町村みたいな区域割り)のShapefileをPostgreSQLに読み込んで
2. PostGISで気象庁の細分区域&市町村等に対応する重心を求める (2015/06)
PostGISを使って気象庁が提供している区域とすり合わせて、重心を出力し、テーブルを作り
3. OpenLayers 3で気象庁発表の震度をマッピングする (2015/07)
作成した重心テーブルと気象庁XML電文からOpenLayersなどの地図システムで扱えるGeoJSON形式のデータを生成する
という流れで、震度を地図上のその地域の上に表示させることが出来ました。
ちなみに、表示される位置が中心ではなく重心なのは、地域の形が収まるバウンディングボックスから中心を求めてしまうと、突起やへこみ、極端に長細い岬が出ているような地形ではそれらに引っ張られて視覚的(感覚的?実際的?)な中心から外れてしまうからです。
重心をSQLを叩いてパッと計算(全国分計算するのには数分掛かりましたが)することができるのは、PostGIS最強としか言えません。
この生成した重心座標のテーブルは、上にもリンク張っていますが、GitHubに置いているので、これから気象庁による区域割りの地図上に何か情報を表示させるようなことをしたい方は使ってみてください。
昨年作った桜島の噴火情報配信サイト「桜島詳報」と若干設計が異なります。
以下は、桜島詳報とプッシュ通知システムの構成。
さらに詳しいスライド版はこちら
桜島詳報ではSubscriber自身に色々と他の処理もさせていました。
そして、詳細ページにアクセスする度にXML本体をパースしてサーバ側でページを組み立ていました。
今回のシステムでは、SubscriberはXMLの保存と、電文の種類別に行う動作を振り分けるBridgeに概要を渡すところまでさせています。
それと、概要とUUIDを一緒にMySQLへ入れていた処理を廃止して、XMLをJSONに変換してMongoDBに入れるようにしています。
(桜島詳報のシステムを合体させるために、元のXMLも一緒に保存しています)
今回のシステムでは電文が届く度にjsonが生成され、詳細ページにアクセスすると生成されたjsonを取得してクライアントサイドでページを組み立てていく仕組みです。
届いた電文が震源・震度情報の場合の処理は以下のとおり。
将来的にAPIとか公開するかもなぁーということで、複数のサーバに分けています。
(現時点では性能に余裕があるので1つのVPSの中に上記4つが詰まっている)
地震火山詳報は上記のEVIの部分になります。
今回新たにEDSという地震に関する情報を保存&提供するサーバと、AZMAPという日本の地図タイルを持っているサーバを作りました。
地震火山詳報の震源・震度情報一覧から任意の1ページを開くと、info.json(発生日時や最大震度、マグニチュードなどが入っている)、smallScalePoints.json(広域ポイント)、largeScalePoints.json(詳細ポイント)の3つがEDSからダウンロードされて、JavaScript(jQuery, OpenLayers3)で処理されます。
地震火山詳報のページ内では提供していませんが、情報を各種SNSに流す時に付属させるデータとして、震度マップをWebKitに描画させてキャプチャした画像も生成しています。
こんな画像がTwitterに震源・震度情報の概要と共に投稿されます。
似たような震源・各地の震度画像出力エンジンを作っている会社もありますが、こちらは普通のHTML/CSS/JSで記述されたWebページから画像を生成しているので、簡単に出力する画像のデザインが可能というわけです。
この画像地図は詳細ページの地図と違って、OpenStreetMapの地図タイルを使用していません。
国土交通省の国土数値情報(行政区分)Shapefileから地図タイルを生成して、使用しています。(この地図タイルを持っているのがAZMAPサーバ)
これも公開していないのですが、気象庁XML電文が届く度にheadlineをJSONに変換して流しているWebSocketサーバも作って使っています。
これは、グローバルIPを持つサーバが無いと受け取れない気象庁XML電文を、どこでも受信できるように...という考えで立てているのですが、キャパシティがそんなに無いので(今のところ)自分用です。
これをRaspberry Piで受けとって64x16ドットのフルカラーLEDマトリクスに表示させたりしている話は、また改めて記事にしようと思います。
地震火山詳報
http://evi.prioris.jp
地震と火山(桜島に限らない)に関する気象庁XML電文情報と、それに付随する情報を配信するWebサイトです。
これの立ち上げに伴い、桜島詳報を閉じました。
→ 実装しました!
12月12日より、噴火に関する火山観測報も追加しました。
桜島詳報では桜島の噴火・爆発のみを扱っていましたが、地震火山詳報では桜島以外の火山(阿蘇山など)の情報を配信されます。
発生した地震の詳細ページでは、震源と揺れを観測した地域の震度がGoogle Mapsライクな操作感で閲覧できます。
例 : 震源・震度情報(2015年12月4日 5時40分頃に発生した地震) - 地震火山詳報
震源や震度のアイコンをクリックすると、上記画像のように地名や座標が表示されます。
地図はOpenStreetMapを使っています。
あとレスポンシブ対応なのでスマホでもPCでも良い感じに閲覧可能です。
地震火山詳報は、地震に関する情報をTwitterとPushbulletでも配信しています。
(Pushbulletって何?っていう人は、EngadgetとかLifehackerの記事を読むといいです。)
Twitter : @Prioris_EVI
Pushbullet : #earthquake_jp
上記Pushbulletのチャンネルは、日本全国のすべての地震(震度1〜)をプッシュ通知で教えてくれるので若干鬱陶しいです。
(日本全国でこんな頻度で地震が起きてるんだ〜!っと認識するのには最高ですが)
というわけで、震度3以上の地震があった時だけプッシュ通知してくれるチャンネルもあります。
Pushbullet : #earthquake_int3over
桜島、阿蘇山の噴火・爆発時プッシュ通知はYoにて配信しています。
Yo : SAKURAJIMA (鹿児島県 桜島の噴火・爆発時に配信)
Yo : ASOSAN (熊本県 阿蘇山の噴火・爆発時に配信)
技術的な話
以下の記事の集大成みたいな感じです。
PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる (2015/06)
PostGISで気象庁の細分区域&市町村等に対応する重心を求める (2015/06)
OpenLayers 3で気象庁発表の震度をマッピングする (2015/07)
OL3で扱える地図タイルをShapeから生成する (2015/12)
あと、ベースとして以下も。
桜島が噴火したYoの裏側 (2014/08)
上記の記事中にも書いていますが、気象庁XML電文から震度マップ(GeoJSON)を作るのに必要なデータやGeoJSON生成コードはオープンソースとして公開しています。
9SQ/jma-eqarea-centroid (気象庁が用いる地域区分の重心座標テーブル)
9SQ/jma-eqxml2geojson (気象庁XMLから上記テーブルを利用してGeoJSONを生成する)
9SQ/seismic-intensity-map (震度GeoJSONをOpenStreetMapにオーバーレイ表示する)
...以下詳細...
気象庁から送られてくる震源・震度に関する情報のXML電文には、発生時刻や地震の規模を表すマグニチュード、震源地の座標、津波に関するコメント、そして揺れを観測した地域の地域コードと地名、震度が含まれています。
このXML電文から、震源地の座標を地図にプロットするのは非常に簡単ですが、各地の震度を、その地域の中心となる場所にプロットするというのが結構面倒です。
というのも、気象庁は地域コードや地名のテーブルは公開していますが、その中心(厳密に言えば重心)座標は提供していません。
また、気象庁の区域割りはちょっと特殊で、例えば「石狩地方北部」みたいに、ある程度の市区町村をまとめていたりします。
そこで、まずこれらの区域の中心座標を求めよう、ということで...
1. PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる (2015/06)
国土交通省から提供されている行政区域(群市区町村みたいな区域割り)のShapefileをPostgreSQLに読み込んで
2. PostGISで気象庁の細分区域&市町村等に対応する重心を求める (2015/06)
PostGISを使って気象庁が提供している区域とすり合わせて、重心を出力し、テーブルを作り
3. OpenLayers 3で気象庁発表の震度をマッピングする (2015/07)
作成した重心テーブルと気象庁XML電文からOpenLayersなどの地図システムで扱えるGeoJSON形式のデータを生成する
という流れで、震度を地図上のその地域の上に表示させることが出来ました。
ちなみに、表示される位置が中心ではなく重心なのは、地域の形が収まるバウンディングボックスから中心を求めてしまうと、突起やへこみ、極端に長細い岬が出ているような地形ではそれらに引っ張られて視覚的(感覚的?実際的?)な中心から外れてしまうからです。
重心をSQLを叩いてパッと計算(全国分計算するのには数分掛かりましたが)することができるのは、PostGIS最強としか言えません。
この生成した重心座標のテーブルは、上にもリンク張っていますが、GitHubに置いているので、これから気象庁による区域割りの地図上に何か情報を表示させるようなことをしたい方は使ってみてください。
裏側の話
昨年作った桜島の噴火情報配信サイト「桜島詳報」と若干設計が異なります。
以下は、桜島詳報とプッシュ通知システムの構成。
さらに詳しいスライド版はこちら
桜島詳報ではSubscriber自身に色々と他の処理もさせていました。
そして、詳細ページにアクセスする度にXML本体をパースしてサーバ側でページを組み立ていました。
今回のシステムでは、SubscriberはXMLの保存と、電文の種類別に行う動作を振り分けるBridgeに概要を渡すところまでさせています。
それと、概要とUUIDを一緒にMySQLへ入れていた処理を廃止して、XMLをJSONに変換してMongoDBに入れるようにしています。
(桜島詳報のシステムを合体させるために、元のXMLも一緒に保存しています)
今回のシステムでは電文が届く度にjsonが生成され、詳細ページにアクセスすると生成されたjsonを取得してクライアントサイドでページを組み立てていく仕組みです。
届いた電文が震源・震度情報の場合の処理は以下のとおり。
将来的にAPIとか公開するかもなぁーということで、複数のサーバに分けています。
(現時点では性能に余裕があるので1つのVPSの中に上記4つが詰まっている)
地震火山詳報は上記のEVIの部分になります。
今回新たにEDSという地震に関する情報を保存&提供するサーバと、AZMAPという日本の地図タイルを持っているサーバを作りました。
地震火山詳報の震源・震度情報一覧から任意の1ページを開くと、info.json(発生日時や最大震度、マグニチュードなどが入っている)、smallScalePoints.json(広域ポイント)、largeScalePoints.json(詳細ポイント)の3つがEDSからダウンロードされて、JavaScript(jQuery, OpenLayers3)で処理されます。
地震火山詳報のページ内では提供していませんが、情報を各種SNSに流す時に付属させるデータとして、震度マップをWebKitに描画させてキャプチャした画像も生成しています。
こんな画像がTwitterに震源・震度情報の概要と共に投稿されます。
似たような震源・各地の震度画像出力エンジンを作っている会社もありますが、こちらは普通のHTML/CSS/JSで記述されたWebページから画像を生成しているので、簡単に出力する画像のデザインが可能というわけです。
この画像地図は詳細ページの地図と違って、OpenStreetMapの地図タイルを使用していません。
国土交通省の国土数値情報(行政区分)Shapefileから地図タイルを生成して、使用しています。(この地図タイルを持っているのがAZMAPサーバ)
関連する話
これも公開していないのですが、気象庁XML電文が届く度にheadlineをJSONに変換して流しているWebSocketサーバも作って使っています。
これは、グローバルIPを持つサーバが無いと受け取れない気象庁XML電文を、どこでも受信できるように...という考えで立てているのですが、キャパシティがそんなに無いので(今のところ)自分用です。
これをRaspberry Piで受けとって64x16ドットのフルカラーLEDマトリクスに表示させたりしている話は、また改めて記事にしようと思います。
感想と告知
- 自分の想像(妄想)を形にするものづくりは楽しい。生きている、生きていける理由。
- Web系欲が満たされたので、またしばらく組み込み系に戻ります。
- 3か月くらい前から、はぐれエンジニアになって実家療養中です。
2015年7月5日
OpenLayers 3で気象庁発表の震度をマッピングする
色々忙しくて、前回から丸1ヶ月空きました...
気象庁の防災情報XML電文で発表される震源地と各地の震度情報をOpenLayers3で表示しようプロジェクト、その3です。
その1 : PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる
その2 : PostGISで気象庁の細分区域&市町村等に対応する重心を求める
こんな感じになりました。
ココマデ長イ道ノリダッタ...
コードはまるっと以下に。
9SQ/jma-eqxml2geojson
#相変わらずのウンコードですが、動けば良いの精神で。
動作は
1. jma_area_centroid.csv と jma_city_centroid.csv をメモリ上のSQLiteデータベースにそれぞれ展開
2. 電文XMLを開いてBeautiful Stone Soupでパース
3. 震源地(epicenter)はそのまま経度緯度を取り出して辞書に入れる
4. 震度毎にリストを作り、各区域の区域コードに対応する重心(経度緯度)をデータベースから探してきてリストに追加
5. 上の3と4を一緒にしてjsonで出力
という感じ。
コードはまるっと以下に。
9SQ/seismic-intensity-map
データが揃えばOpenLayers 3のパワーでサクッと表示できてしまいます。
XML電文の震度情報は、細分区域と市町村等区域でやってくるので、縮尺に応じて表示を切り替えするようにしました。
ズームして、ある一定以上になると市町村等レベルの震度表示に切り替わります。
初期のズームレベルと中央は、細分区域レベルでのポイントから、だいたい全体が入るように自動調整されます。
これが100行(スタイル定義を除けば実質60行)くらいで実現できるので、OpenLayers 3 凄い。
デモを以下に設置しましたので、ご自由にご覧ください。
http://www.quitsq.com/demo/seismic_intensity_map/
(2015年5月30日 20:24分頃に小笠原諸島西方沖で発生した最大震度5強の地震)
以上で終わりです。
もう少し暇になったら、地震発生毎に各地の震度情報を上記デモのように表示できるサービスを作ろうと思います。
(ついでに、Yoとかtwitterへのツイート機能も含めて。)
追記 2015/12:作りました→ 地震とか火山噴火情報を閲覧できるWebサイトを作った
気象庁の防災情報XML電文で発表される震源地と各地の震度情報をOpenLayers3で表示しようプロジェクト、その3です。
その1 : PostgreSQLとPostGISで国土数値情報(行政区域)を扱ってみる
その2 : PostGISで気象庁の細分区域&市町村等に対応する重心を求める
こんな感じになりました。
ココマデ長イ道ノリダッタ...
1. XML電文からGeoJSONを作る
まず、PostGISで気象庁の細分区域&市町村等に対応する重心を求める で生成した jma_area_centroid.csv と jma_city_centroid.csv を使って、気象庁防災情報XML電文の震度速報、震源・震度に関する情報から、区域別の震度(数値)情報と重心(緯度経度)を持つGeoJSONを出力します。コードはまるっと以下に。
9SQ/jma-eqxml2geojson
#相変わらずのウンコードですが、動けば良いの精神で。
動作は
1. jma_area_centroid.csv と jma_city_centroid.csv をメモリ上のSQLiteデータベースにそれぞれ展開
2. 電文XMLを開いてBeautiful Stone Soupでパース
3. 震源地(epicenter)はそのまま経度緯度を取り出して辞書に入れる
4. 震度毎にリストを作り、各区域の区域コードに対応する重心(経度緯度)をデータベースから探してきてリストに追加
5. 上の3と4を一緒にしてjsonで出力
という感じ。
2. OpenLayers 3でGeoJSONのデータを描画
できたGeoJSONをOpenLayers 3でOpenStreetMap上に描画します。コードはまるっと以下に。
9SQ/seismic-intensity-map
データが揃えばOpenLayers 3のパワーでサクッと表示できてしまいます。
XML電文の震度情報は、細分区域と市町村等区域でやってくるので、縮尺に応じて表示を切り替えするようにしました。
ズームして、ある一定以上になると市町村等レベルの震度表示に切り替わります。
初期のズームレベルと中央は、細分区域レベルでのポイントから、だいたい全体が入るように自動調整されます。
これが100行(スタイル定義を除けば実質60行)くらいで実現できるので、OpenLayers 3 凄い。
デモを以下に設置しましたので、ご自由にご覧ください。
http://www.quitsq.com/demo/seismic_intensity_map/
(2015年5月30日 20:24分頃に小笠原諸島西方沖で発生した最大震度5強の地震)
以上で終わりです。
もう少し暇になったら、地震発生毎に各地の震度情報を上記デモのように表示できるサービスを作ろうと思います。
(ついでに、Yoとかtwitterへのツイート機能も含めて。)
追記 2015/12:作りました→ 地震とか火山噴火情報を閲覧できるWebサイトを作った
登録:
投稿 (Atom)








