Rubyでアニメーション・グラフを作ろう!
ベルマンフォードのアルゴリズムで実行される結果も逐次表示 - Seeking for my unique color.
を見てGraphVizの出力からアニメーションgifを作りたくなった
Rubyにはruby-graphvizというGraphVizのinterface libraryと
RMagickというImageMagickのinterface libraryがあり
これらを使えば目的は達成できるみたいだ
ruby-graphvizのinterfaceは自分にはわかり辛かったので
これをラップする形でGraphAz*1というクラスを書いて
上のアニメーションgifを出力してみた
用途が限定的で実装にも問題がありそうだけれど
GraphVizのDOTデータの出力としても使えるので
無責任無保証で使ってくれる人がいればうれしい
使い方
コードを見るのが早いと思うので
簡単な例を示した
まずはDOTデータを作る例
require "graphaz" routes = [ ':main => :parse => :execute', ':main => :init', ':main => :cleanup', ':execute => :make_string', ':execute => :printf', ':init => :make_string', ':main => :printf', ':execute => :compare' ] ga = GraphAz.new(:G) routes.each { |route| ga.add route } ga.print_graph
GraphAz.newでオブジェクトを生成し
addメソッドで用意したルートを追加する
addメソッドは対応するノードとエッジを同時に生成する
最後にprint_graphメソッドを呼べば
DOTデータが標準出力に出力される
コマンドラインから以下のように実行すれば
DOTファイルが生成される
> ruby small_graph.rb > small_graph.dot
pixelglow | graphviz
などのツールで開けば以下のような
グラフが得られるはずだ
今度はアニメーションgifを作成してみる
コードを示す
require "graphaz" routes = [ ':main => :parse => :execute', ':main => :init', ':main => :cleanup', ':execute => :make_string', ':execute => :printf', ':init => :make_string', ':main => :printf', ':execute => :compare' ] ga = GraphAz.new(:G) routes.each { |route| ga.add route } ga.lap color = 'tomato' ga.node('main', :style => 'filled', :fillcolor => color) ga.lap ga.edge('main_parse', :color => color) ga.node('parse', :style => 'filled', :fillcolor => color) ga.lap ga.edge('parse_execute', :color => color) ga.node('execute', :style => 'filled', :fillcolor => color) ga.lap ga.edge('execute_make_string', 'execute_compare', 'execute_printf', :color => color) ga.node('make_string', 'compare', 'printf', :style => 'filled', :fillcolor => color) ga.lap ga.write
15行目までは同じで
16行目でprint_graphに代えてlapメソッドを使う
lapメソッドはそこまでのコードに基づいて
グラフをimageファイルとしてcurrent directoryに出力する*2
次にnodeまたはedgeメソッドを使って
グラフの属性を変化させる
node,edgeメソッドは
複数のnode, edgeおよび属性を取ることができる
その後lapメソッドを使ってそこまでの変化を出力する
これを繰り返し
最後にwriteメソッドを呼ぶことによって
lapメソッドで出力したファイルを読み込み
1つのgifファイルout.gifを生成する
他のimageファイルはdefaultでは削除される
out.gifをブラウザなどで開き
アニメーションgifが完成しているか確認する
ノードを後から追加するなどイメージデータのサイズが変わると
うまくいかないなどの問題があります
(追記:2010-02-04) タイトルとrubyclass_graph.rbを修正しました
(追記:2010-02-18) Ruby1.9対応です。それ以前のRubyで使うときはnodeとedgeメソッドの第一引数の*を削除して配列を渡すようにしてください
(追記:2010-10-24) graphvizの0.9.9以降のヴァージョンではうまく動作しません。version0.9.8を使ってください
(追記:2010-10-25) graphviz ver.0.9.18に対応しました。clusterを表現できるようになりました。