Menu


グラフの自動レイアウトに挑戦 #2 Windows Formで表示

ソースコード

今回の中間ソースコードのダウンロード (zip/tar, 13.6KB)

今回の完成ソースコードのダウンロード (zip/tar, 14.1KB)

はじめに

前回は「Eadesのばねモデル」を使ってノードにかかる力を計算するところまで実装した。

今回はWindows Formを使ってアニメーション表示してみたいと思う。

ただし、今回は「やってはいけない」アンチパターンとして、わざとVisual Studioにおまかせ状態で、頭を使わずに書いてみる。

おすすめパターンは、次回にとっておくのでそのつもりで。

初期化ロジック

プロジェクトを「Windows フォーム アプリケーション」に変更し、MainForm.csを追加する。そして、このフォームのプライベートフィールドとして、前回作ったノードコレクションを置く。

このままだとnodesフィールドがnullなので、どこかで初期化しないといけない。ってことで、MainFormのコンストラクタに書く。

ついでに初期配置もしておこう。初期状態だと、ノード間の距離が0になってしまうのでいろいろ不都合なのだ。とりあえず円形に並べておく。

描画ロジック

描画のため、MainFormのPaintイベントにイベントハンドラを書く。

ノードは円、エッジは線で表現した。なお、ノードの座標を画面上の座標に変換するためのメソッドを用意した。

物理シミュレーション作動

MainFormにはボタンとタイマーを追加する。

ボタンのClickイベントでタイマーの開始/停止を制御する。タイマーのTickイベントでnodesを動かして画面を再描画する。

この段階が、冒頭に示した中間ソースコードである。

実行するとノードが動き出した。エッジはばねでできており、ノード同士には反発力が働くというEadesのばねモデルの通りに動いているように見える。

しかし、ノードの動きが平衡状態に近づいても、結果として得られたレイアウトは美しいとは言いがたい。エッジが絡まっているからだ。シミュレーション実行中に、ノードの位置を自由に変更できないだろうか。

ノードをドラッグできるようにする

マウスの左ボタンを押している間は、マウスカーソルに最も近かったノードの位置を自由に変更できるようにしよう。ドラッグしているノードはばねモデルに従わずに、マウスカーソルの位置に追随する。左ボタンを離せば、ノードは再びばねモデルにしたがって動き出す。

これを実装するためにソースコードを変更する。まずはノードコレクション。ノードをロック/ドラッグ/アンロックするメソッドを実装した。

そして、ロックされたノードがばねモデルに従わないようにMoveAllメソッドを修正する。

次はMainForm。マウスの左ボタンのアップダウンイベント、およびマウスカーソルの移動イベントでノードコレクションにメッセージを送る。

ついでに、ロックされたノードは赤い円で描画するようにしよう。

この段階が、冒頭に示した完成ソースコードである。

今度は、実行中にノードを「引っ張る」ことができる。

適当に引っ張っていたら、エッジが絡まないように配置できた。

次回は、Model-View-Controller(MVC)パターンに適合するように、このプログラムをリファクタリングしてみたいと思う。


グラフの自動レイアウトに挑戦 インデックスへ戻る


Last Update: 2012-07-17 19:43:19