自作ソフトを進化させようとした&2024年の振り返り
この記事は「防災アプリ開発 Advent Calendar 2024」の15日目の記事です。
はじめに
5年連続でこんぽ様主催のアドベントカレンダーに参加させていただきます。
好きなおにぎりの具はツナマヨと鮭です。どっちもド定番!
毎年12月中旬で参加していますが、結局ギリギリの執筆になっており、もれなく今年もそんな感じですがご了承ください。
この記事は、以下の構成になっています。
- 自作ソフトQuarogに活用すべくAvaloniaを触ってみた
- 今年の振り返り
- 来年(今日以降)の目標
自作ソフトQuarogに活用すべくAvaloniaを触ってみた
Quarogの問題点
Quarogのコードは基本的にC#で書かれており、現在はUIフレームワークにWinFormsを利用しています。
また、昨年の記事でも紹介した現在開発中のVer.1.1.0(仮)も、WinFormsがベースになっています。
しかし、WinFormsは、リッチなソフトを作るのにはあまり向いていません。
向いていない例
- GDI+なので基本的にCPU描画しか行えない
- EEWの到達予想円のアニメーションなど、高度なグラフィック描画に向いていない
- UIカスタマイズの柔軟性が少なく、高DPI環境などでうまく利用できない場合がある
- Windows環境にしか対応していない
現在開発中のVer.1.1.0(仮)については、現状SkiaSharpを利用して描画関連の問題を解消しようとしていますが、CPU描画を相変わらず使っており、根本的な問題解決はできていません。(SKGLControlを使うことでGPU描画は可能ですが、他の問題は残ったままです。)
また、UIカスタマイズについてはWinFormsのままでは解決が困難であることがわかりきっているため、今後のためにも早いうちに移行したいと考えるようになりました。
Avaloniaを選んだ理由
今回は移行にAvaloniaを選びました。
C#では、WinForms以外にもWPFやUWPアプリ、WinUIなど、やり方は様々にあります。
WinFormsからの移行であれば、WPFが有力候補としてあがると思います。私も最初はWPFで作り直そうかな~と思っていました。
WPFではなくAvaloniaを選んだ理由は、だいたい次のとおりです。
- WPFに似ている
- 描画エンジンにSkiaSharpが使われており、すでに作成中のVer.1.1.0(仮)のコードを流用しやすそう
- クロスプラットフォーム対応できそう
- ingen084様のKyoshinEewViewer for ingenで使われていて、使用している体感(アプリの触り心地(?))がとても良い
- スタイル変更など、見た目にこだわれそう
私はこれまでWPFアプリを作成したことが無く、xamlやMVVMなどの知識も皆無でした。
そのため、WinFormsアプリ以外を初めて触るにはややハードルは高いと思っています。
しかし、Avaloniaについて調べていると、WPF関連の記事の内容がAvaloniaにもそこそこあてはめられそうで、「はじめてのWPF(xaml、MVVM)」用の内容を参考にできるかもしれないと見切り発車が決定しました。
自分用のソフトをAvaloniaに移植してみる
お試しをするソフトを決める
Quarogで「はじめてのAvalonia」をすると、途中で挫折するのがわかりきっていたので、まずはほどほどに小さいアプリで試してみようと考え、Fukuarogで移植を開始しました。(ここで12月4日)

XAMLで見た目を作ってみる
Avaloniaのドキュメントやネット記事を見ながら、メインウィンドウの見た目を作ってみました。
WinFormsアプリのようにデザイナーでコントロールをマウスドラッグで配置していく方式はなく、基本的にxaml手打ちで書いていくことになりましたが、AvaloniaのVisual Studio向け拡張機能でプレビューが表示できたため、それほど不便無くできます。

marginやcornerradiusなどのパラメータもつけながら、相対は位置を作成できるため、手軽さに感動しました。(令和6年の感想か??)
特に、BorderなどでCornerradiusを角ごとに決められることに一番感動しています。
Fukuarogはメインウィンドウ上部に左上と右上を丸めない角丸四角形を描画する必要があり、移植前の描画処理ではかなり強引に実装していました。
また、今後作りたい気象警報・注意報の画面表示でも一部分の角が丸まってない図形が登場する予定なので、そういった点でも都合が良かったです。

(環境のため、去年の画像を再利用しています)
Fukuarogのメインウィンドウは画面上部、メインビジュアル、画面下部の3つで構成されているため、メインビジュアルは別のxamlに書いてメインウィンドウのxamlに統合するようにしました。

「自作ソフトQuarogに活用すべくAvaloniaを触ってみた」の内容はここまでになります。
見た目をxamlで書いて終わりです…。
予定ではFukuarogの移植が完了していたはずだったのですが、全然間に合いませんでした。すみません。

サブピクセルレンダリングがとても苦手なのですが、ソフト内で無効にする方法はあるのでしょうか
以降は今年の振り返りになります。お暇があればご覧ください。
今年の振り返り
令和6年能登半島地震
今年は始まって早々に令和6年能登半島地震が発生しました。
発生当時、私は家族とともに初詣のために島内の神社に訪れていました。
16時6分ごろの最大震度5強の地震が発生したときは参拝の列に並んでいて、正月早々に大きい地震だな…とか考えていました。
その後、Twitterで地震情報の収集やツイートをしている最中に、最大震度7の地震が発生します。
とっさにBSC24のライブを開いて目に飛び込んできたのは、予想最大震度7や、振動レベル3000などの情報で、最初は信じられませんでした。
程なくYahoo!防災速報アプリから、「兵庫県南あわじ市 予想震度3」の通知が届き、しばらくたってからゆらゆらとした揺れを感じました。参拝の列で石段の途中にいましたが、めまいでふらつくような揺れだったのを覚えています。
その後、津波警報の通知や16時18分の地震のEEW通知、さらには大津波警報の通知まで、ひっきりなしにいろんな情報が流れてきて、家族にも頼んで私だけ自宅に帰ることにしました。
帰宅途中の車内ではカーナビでNHKを流していましたが、これまで訓練の映像などでしか見たことが無いようなアナウンサーの呼びかけが行われており、いっそうの非現実感がありました。
令和6年能登半島地震の一連の活動で、複数のEEWが短い間隔でいくつも発表されたり、震度速報の取消報が発表されたりなど、当時リリースしていたQuarogでは上手に捌けないケースがたくさん登場しました。特にEEWの処理については以前から修正案を頭では考えていたものの、実装せずにVer.1.1.0(仮)を作成していたこともあって、かなり反省点だったと思っています。
その後、早い段階で修正バージョンをリリースすべきだと考え、GitHubからVer.1.0.1からブランチを作成し、Ver.1.0.2の制作に取り組みました。
Ver.1.0.1で確認していた不具合の修正と、地震情報の取消報への暫定的な対応などを行い、最初にデバッガーの方向けに配布したのが1月3日でした。

その後、さらに不具合修正を行い、デバッガーの方向けに2週間ほど使用していただいた上で、1月20日にVer.1.0.2を一般公開しました。
これまでに公開したQuarogの中では、Ver.1.0.2が最も不具合が少なく安定していますので、まだVer.1.0.0やVer.1.0.1を使っていてこの記事を読んでいる方がいましたら、どうか更新してください…。
Quarog Ver.1.1.0(仮)での津波情報の実装
令和6年能登半島地震でさらに反省すべきだったのは、Quarogで津波情報を表示できないことでした。
これは重い腰をあげずにいたから起こってしまったことで、とりあえず実装してみようと考えて見た目の考案から順に作業を始めました。
見た目の考案については昨年からすでにやろうとはしていたのですが、全くよさげな案が浮かばずに年を越していました。
今回の作業では、能登半島地震発生時の各テレビ局の放送画面などを参考にして、シンプルかつ分かりやすい見た目を考案できました。
本当はUD新ゴフォントを使いたいですが、アプリ組み込みのハードル(お金含む)が高すぎるため断念…。

いざSkiaSharpを使って描画処理を実装するぞとなったときの課題と解決法は次の2点
- SKCanvas.DrawTextだと、フォントウェイトがRegularでも太く見える
→SKCanvas.DrawPathを活用して、文字のアウトラインを描画するようにした
- とても長い地名が登場したときに、狭いスペースに文字が入らない
→あらかじめテキストのサイズの画像にテキストを描画し、それをサイズ変形しつつ本体のSKCanvasに張り付けるようにした

(System.DrawingのGraphics.DrawStringに近いのはDrawPathのほう)
そして津波情報のサイドパネル用の表示を実装できました。

Quarogの内部で管理する用のクラスも新たに作成しましたが、津波情報の電文構造がそこそこ複雑で、DMDATA.JPのJson化データのドキュメントや気象庁の技術情報とだいぶにらめっこしながら作成しました。
地図描画についても、すでにある程度実装できています。(残りは観測点の描画のみ)
TopoJSONの攻略
昨年の記事時点のQuarog Ver.1.1.0(仮)のコードでは、パッと見は普通に地図描画ができていました。
しかし、この時点では穴あきポリゴンが非対応で、かつ一部のポリゴンが正常に描画できない不具合が残っていました。

このままリリースするのは明らかによろしくなかったため、修正に取り掛かりました。
TopoJSONのドキュメントをちゃんと読んで原因を探った結果、ポリゴンのパス作成時点でいろいろ間違っていることがわかりました。
関連するコードを修正した結果、不正なポリゴン描画はなくなりました。
穴あきポリゴンについては、SkiaSharpのSKPathに穴をあける方法があったため、こちらも正常に描画できるようになりました。

久々に頭を使ってコードの修正および追記をしたため、楽しかったです。
EQIS-1の情報を表示するソフトの作成
EQIS-1の完成品(プログラム未書き込み版)を2023年に購入し、しばらくはingen084様のPiDASPlusGraphをすこし改変して使っていました。
しかし、自分用のOBS画面に表示するには、スペースが狭すぎることもあり、自分で作るか~~となって制作に取り組みます。(将来的にはWxBeacon2の情報も表示したいな~とか思っていたこともあり、それも同じソフト内で実現したいなと構想していました。)
まずは見た目から、Figmaでごにょごにょして作成しました。
見た目を作る上で考えていたこと
- 震度は計測震度も含めて大きく表示したい
- 計測時刻を表示したい
- 加速度はグラフ付でほしい
- OBS画面で表示したときに文字がちゃんと読める大きさにする

ソフトはC#のWinFormsで作成しました。
見た目の描画にはSkiaSharpを使っています。Quarog Ver.1.1.0(仮)で津波情報を作成したときのノウハウを活用し、理想どおりの見た目にできました。
実際の受信処理やグラフの描画処理については、ingen084様のPiDASPlusGraphのコードをとても参考にしています。
完成したのが5月ごろで、そこから半年以上使用していますが、特に不具合なく使用できています。不満点としては、表示される時刻がPC時計の時刻なためめちゃくちゃズレることです…。

日向灘の地震(8月8日)
この日はたまたま仕事を休んでいて、自部屋で動画を鑑賞しているときに発生しました。震度速報前に津波注意報が発表されたり、南海トラフ地震臨時情報も発表されたり、まさかそんなたいそうなことが今年起こるとはと感じたことを覚えています。(南海トラフ地震臨時情報も、Quarog内で表示できるようにしたい。)
自宅では、4月の豊後水道の地震ほどの揺れではなかったですが、能登半島地震の時のようなゆらゆらした揺れを感じました。

Quarog Ver.1.1.0(仮)でのEEWの実装
11月に、Quarog Ver.1.1.0(仮)にEEWの受信と描画処理を実装し始めました。
EEWのJSONを解析するコードはQuarog Ver.1.0.2の時のものを使いまわせるため使いまわし、描画処理は地震情報などで実装していた方法を参考に実装しています。
残るタスクはサイドパネルの表示と地図左上に表示する情報パネルの描画です。

来年(今日以降)の目標
今年は前半はそこそこコード書いたりしていましたが、後半はスカスカでした…。
遅れを取り戻す意味合いも兼ねて、今日以降の目標を書いてみます。
FukuarogをAvaloniaで完全に移植する
今回の記事で完全に移植するつもりだったのですが、結局中途半端なままになってしまいました。この移植なくして今後のソフト制作はできないと思っているため、ちゃんとやりたいです。
Quarog Ver.1.1.0をちゃんと作る
今はまだそれぞれの描画処理や内部処理をバラバラに実装している状態で、イベントやDMDATA.JPからの情報受信などの機能は手つかずの状態です。
WinFormsからAvaloniaへの移行作業と合わせて、はやく終わらせたいです…。
Clock For Fukuをなんとかする
昨年6月の強震モニタの利用条件の策定以降、「EEWを受信する設定をオフにして使って」と暫定的な対処だけにとどまっているClock For Fukuですが、さすがに放置しすぎですので、なんとかします。
おわりに
日本語がヤバい箇所の多い駄文でいたが、ここまで読んでいただきありがとうございました。
来年は仕事内容がガラッと変わりそうな気がしているので、年度が変わってからどこまでこちらに時間をさけるのかが未知数です。
だからこそ、来年からではなく今日から、「とにかくやる!!!!!」をやっていきたいです。