Graph::EasyとGraphvizでステキなグラフを作ってみる

Graph::EasyはASCII, HTML, SVG *1での出力が可能なグラフに変換し描画してくれるモジュールです。

ASCIIでの出力

+------+     +-------+
| AAA  | --> |  BBB  |
+------+     +-------+
+------+     +-------+
| test | --> | test2 |
+------+     +-------+
 #!/usr/bin/perl 
 use strict;
 use warnings;
 use utf8;
 use Graph::Easy;
 
 my $graph = Graph::Easy->new();
 $graph->add_edge_once ('AAA', 'BBB');
 $graph->add_edge_once ('test', 'test2');
 print $graph->as_ascii();

コマンドラインから出力

graph-easy コマンドで簡単にできます。

echo "[ Bonn ] -- car --> [ Berlin ], [ Ulm ]" | graph-easy
+--------+  car   +-----+
|  Bonn  | -----> | Ulm |
+--------+        +-----+
  |
  | car
  v
+--------+
| Berlin |
+--------+

source: http://search.cpan.org/~tels/Graph-Easy/bin/graph-easy

    • >や==>などの書き方については、公式ドキュメントでサンプルが沢山載ってます。

外部ファイルを読み込んで出力

mygraph.txt

[ Bonn ]      --> [ Berlin ]
[ Frankfurt ] <=> [ Dresden ]
[ Bonn ]      --> [ Frankfurt ]
[ Bonn ]      = > [ Frankfurt ]

graph_parser.pl

#!/usr/bin/perl 
use strict;
use warnings;

use Graph::Easy::Parser;
my $parser = Graph::Easy::Parser->new();
print $parser->from_file('mygraph.txt')->as_ascii();
  # = = = = = = =#
  "              v
+--------+     +-----------+      +---------+
|  Bonn  | --> | Frankfurt | <==> | Dresden |
+--------+     +-----------+      +---------+
  |
  |
  v
+--------+
| Berlin |
+--------+

HTML,CSSでの出力

graph_parser.plのas_ascii()をas_html_file()に変更すれば、CSSの入ったHTMLでアウトプットしてくれます。

perl graph-parser.pl > mygraph.html  


先ほどのgraph-easyコマンドでもできます。

graph-easy --html --output=mygraph.html mygraph.txt

Graph::Easyでdotファイルに出力して、Graphvizpngのグラフに変換する。

Graph::Easy、Graphvizを使って任意のディレクトリ以下の階層をアウトプットさせてみる。


macportsであれば、port installするだけでおk

sudo port install graphviz


参考ソース(一部変更したくらいのgraph-output-files.pl)を使って、*.dotファイルを出力→ source: http://www.wickle.com/wiki/index.php/Perl_code

perl graph-output-files.pl ~/Sites/Acme-Oppai-0.03/


.dotファイル

digraph G
{
   rotate=90;
   nodesep=.05;
   node[height=.7, shape=record, fontsize=8];
	_ [shape=box, label=""];
	__Users [shape=box, label="Users"];
	__Users_acotie [shape=box, label="acotie"];
	__Users_acotie_Sites [shape=box, label="Sites"];
	__Users_acotie_Sites_Acme_Oppai_0_03 [shape=box, label="Acme-Oppai-0.03"];
	__Users_acotie_Sites_Acme_Oppai_0_03__Changes [shape=box,label="Changes"];
	__Users_acotie_Sites_Acme_Oppai_0_03__example_pearl [shape=box,label="pearl"];
	__Users_acotie_Sites_Acme_Oppai_0_03__lib_Acme_Oppai_pm [shape=box,label="Oppai.pm"];
	__Users_acotie_Sites_Acme_Oppai_0_03__lib_Acme_Yaruo_pm [shape=box,label="Yaruo.pm"];
	__Users_acotie_Sites_Acme_Oppai_0_03__Makefile_PL [shape=box,label="Makefile.PL"];
	__Users_acotie_Sites_Acme_Oppai_0_03__MANIFEST [shape=box,label="MANIFEST"];
	__Users_acotie_Sites_Acme_Oppai_0_03__META_yml [shape=box,label="META.yml"];
	__Users_acotie_Sites_Acme_Oppai_0_03__README [shape=box,label="README"];
	__Users_acotie_Sites_Acme_Oppai_0_03__t_Acme_Oppai_t [shape=box,label="Acme-Oppai.t"];
_->__Users;
__Users->__Users_acotie;
__Users_acotie->__Users_acotie_Sites;
__Users_acotie_Sites->__Users_acotie_Sites_Acme_Oppai_0_03;
__Users_acotie_Sites_Acme_Oppai_0_03->__Users_acotie_Sites_Acme_Oppai_0_03_;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__Changes;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__MANIFEST;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__META_yml;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__Makefile_PL;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__README;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__example;
__Users_acotie_Sites_Acme_Oppai_0_03__example->__Users_acotie_Sites_Acme_Oppai_0_03__example_pearl;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__lib;
__Users_acotie_Sites_Acme_Oppai_0_03__lib->__Users_acotie_Sites_Acme_Oppai_0_03__lib_Acme;
__Users_acotie_Sites_Acme_Oppai_0_03__lib_Acme->__Users_acotie_Sites_Acme_Oppai_0_03__lib_Acme_Oppai_pm;
__Users_acotie_Sites_Acme_Oppai_0_03__lib_Acme->__Users_acotie_Sites_Acme_Oppai_0_03__lib_Acme_Yaruo_pm;
__Users_acotie_Sites_Acme_Oppai_0_03_->__Users_acotie_Sites_Acme_Oppai_0_03__t;
__Users_acotie_Sites_Acme_Oppai_0_03__t->__Users_acotie_Sites_Acme_Oppai_0_03__t_Acme_Oppai_t;
}

Graphvizのdotコマンドでpngのグラフに変換

dot -Tgif OUTPUT-.dot -o acme-oppai.png


フォントやカラーなどのスタイルを変更させたら、色々とドキュメント作成時に楽ができそうな予感!

余談

Graphvizの対応している出力フォーマットは以下を参照。PDFにも対応しているようです。
http://graphviz.org/doc/info/output.html

*1: 生成したdotファイルをGraphvizのdotコマンドを使用してpngやgifのグラフに変換