GraphvizはDOT言語を記述されたグラフ構造からグラフを出力するソフトフェア。
インストール
homebrewだと
$ brew install graphviz
でインストールできる。
サンプルコード
以下にまるっとしたサンプルコードを置く。色々な例を書くためにかなりごちゃごちゃしている。
digraphsample1/* ←idはつけなくもよい */{layout=dot// デフォルトはdot。dotは階層を持ったグラフを描くのに適している。他にfdp, neato, circo, osageなど。=の両側には空白があってもよい// graph (node, edge以外の部分)の設定graph[// graph []で囲まなくても良い。カンマで区切らなくてもいいっぽいlabel="サンプルだよ☆",// 全体のラベル。文字列は"(ダブルクォート)で囲む。'(シングルクォート)は使えない// labelloc = t, ラベルを上に指定// labeljust = l, ラベルを左寄せ(l)、右寄せ(r)fontname="Ricty Discord",// font指定。デフォルトはTimes-Romanfontsize=10,// デフォルトは14fontcolor="#d33682",// デフォルトはblack。16進数表記"#0033aF"や、0から1の実数で色、彩度、明度をカンマorスペース区切りで指定"0.6,.4 1"できるbgcolor="#fdf6e3",// 背景色の設定。// rotate=90 90度回転。指定できるのは90のみ。指定したら、何も出力されなくなった。// size="4,3!", インチ指定で、横、縦。縦横比は保たれる。// !をつけないとデフォルトのサイズから縮小はされるが、拡大はされないrankdir=TB,// ノードの配置の仕方。デフォルトTBで上から下に向かって配置される。他にBT,LR,RLがある。]// nodeの設定// nodeの宣言。node[]で設定する前なのでデフォルトの設定になるA;// nodeの設定node[shape=diamond,// nodeの形。デフォルトはellipsewidth=1.5,// 幅。設定しないと自動で調節してくれるheight=0.5,// 高さ// fixedsize=false, デフォルトfalse。trueにすると中に入っている文字よりも小さくできるstyle=rounded,// 枠線のスタイル。デフォルトはsolid。color="#268bd2",// 枠線の色fontname="Monaco",fontcolor="#b58900",peripheries=2,// 二重線。]// nodeの宣言。上の設定が反映されるB;C;// nodeの設定を上書きnode[shape=circlestyle=stripedwidth=0.5height=0.5color="#93a1a1"style=filled,// 塗りつぶしfillcolor="#eee8d5",// 塗りつぶしのカラーperipheries=1]// nodeの宣言。上書きされた設定が反映されるD;// nodeごとに個別の設定ができるE[label="E\lsecond line\nthird line\r"// labelの設定。デフォルトは\N(nodeのid)。// \nでセンタリング改行、\lで左寄せ改行、\rで右寄せ改行width=2shape=boxstyle=dashed];F[image="tmsanrinsha_icon.jpg"// 画像を指定できるshape=none// recordは指定しても画像が表示されない。label=""xlabel="\N"// 外側にnodeのidを表示。位置は決められないっぽいcolor="#fdf6e3"// 枠を見せたくないので背景色に]G[shape=none,// labelにtable, br, font, imgのタグが使える。// imgはtableの中にしかかけない。imageとbrは/>で閉じる// <>で全体を囲むlabel=<<tableborder="0"><tr><td><imgsrc="tmsanrinsha_icon.jpg"/></td></tr><tr><td><fontcolor="red">red</font><br/>G</td></tr></table>>,]H[shape=record,// recordを指定すると線で区切ってラベルを書けるlabel="left|center|right"// |で区切る。{}で囲むと縦に並ぶようになる。もっと複雑なものが描ける]// edgeの設定edge[color="#859900",labelfloat=false,// ラベルの重なりを許さない(デフォルト)];// edgeの個別の設定は矢印の横に書くA->A;A->B[label="A → B"];// edgeにもlabelが使えるA->C[arrowsize=2];// 矢印のサイズ{rank=same;B;C}// BとCを同じランクにするC->D[arrowhead=odot,arrowtail=inv// 矢印の始端と終端の形。arrowtailが効かない?weight=2// C-D間のedgeの重みを上げるとなるべく近く、垂直なるように配置される];B->E[dir=back,arrowhead=inv];// 矢印の向き。back, both, noneD->E[dir=both];E->F;E->G->H;// まとめてかけるF->{J,K}// サブグラフ。名前をclusterで始めると枠ができて、ラベルも指定できる// サブグラフの中にサブグラフ、サブグラフ間のedgeはdot layoutではできない。// fdp layoutならできるsubgraphcluster1{label="cluster1";I[shape=ellipsecolor=black,fontcolor=black,fontname="Times-Roman",fillcolor="#fdf6e3"]I->A;{rank=same;A;I;}}}
コードと同じディレクトリに画像も置いた状態で、例えばpngに変換するには
$ dot -T png sample1.dot -o sample1.png
と打つと画像が出力される。
Node
nodeのshape一覧
Edge
edgeのshape一覧
color
color name一覧
画像の埋め込み
node Fでやっているようにimage属性を使うか、node GでやっているようにlabelでHTMLを使う。
画像にラベルを入れる方法として、xlabelを使うと画像の外側にラベルを置くことができる
F[image="tmsanrinsha_icon.jpg"shape=nonelabel=""xlabel="\N"color="#fdf6e3"]
しかしこの方法だとラベルの位置を指定できない。
image属性を使って、下にラベルをおきたい場合は、下に余白のある画像を作るかheightを少し大きめにとって
F[image="tmsanrinsha_icon.jpg"shape=nonelabel="\N"height=2labelloc=bfillcolor="#fdf6e3"color="#fdf6e3"]
としてやる。
HTML-Like Label
- labelにtable, br, font, imgのなどのタグが使える。
- imgはtableの中にしかかけない。imageとbrは/>で閉じる
- <>で全体を囲む
以下が参考になる
- clmemo@aka: Graphviz に画像を埋め込む; 例. 画面遷移を描く
- Node Shapes | Graphviz - Graph Visualization Softwareの#html
cluster
layoutをfdpにするとnodeとcluster、cluster間でedgeを設定できて、subgraphの中にsubgraphを作ることも可能のようだ。
その他
- 無向グラフと有向グラフを混ぜることはできない。
参考資料
- Graphviz チュートリアル
- Documentation | Graphviz - Graph Visualization Software公式ドキュメント
- Gvizの目次 - Rubyの世界からGraphvizの世界にこんにちは! rubyのgraphvizパッケージを使った色々な例が載っている
- rich-iannone/DiagrammeR Rからgraphvizをつかうパッケージ
- Q-BPM:プロセスダイアグラム画像の書き方 - Q-BPM配置の調節するのに参考になる
- Graphvizの出力サイズ指定 (1) - とあるソフトウェア開発者のブログ sizeの指定
Vim
syntaxやomni補完が使えるようになるプラグイン。
コンパイルでできるがそれはquickrunでやっている。
omni補完をneocompleteで使うための設定
if!exists('g:neocomplete#force_omni_input_patterns')letg:neocomplete#force_omni_input_patterns = {}
endifletg:neocomplete#force_omni_input_patterns.dot ='\%(=\|,\|\[\)\s*\w*'
forceで設定しないとうまく行かなかった。パターンについてはhttps://github.com/wannesm/wmgraphviz.vim/blob/master/ftplugin/dot.vimのGraphvizCompleteを見て設定。
スニペットは大したものがないので、設定しなくてもよいが、設定するならこんな感じ。
letg:neosnippet#snippets_directory= [
\ '~/.vim/bundle/vim-snippets/snippets',
\ '~/.vim/bundle/wmgraphviz.vim/snippets',
\]
quickrunの設定
開いているdotのコードからpng画像を生成(ファイル名は拡張子をpngに変更したもの)して、それをopenする設定(mac用)。open -g
でバックグラウンドで起動しようとしたけどだめだった。
letg:quickrun_config['dot'] = {
\ 'hook/cd/directory' : '%S:p:h',
\ 'command' : 'dot',
\ 'cmdopt' : '',
\ 'exec' : ['%c -T png %s -o %s:r.png','open %s:r.png'],
\ 'outputter/quickfix/errorformat' : 'Error: %f: %m in line %l %.%#,%EError: %m,%C%m,%Z%m'
\}
dotのコンパイルエラーは二種類あって、一つはdotのシンタックスエラー
Error: sample1.dot: syntax error in line 21 near ';'
で、もう一つはHTML-Likeなlabelを設定した時のエラー
Error: Unknown HTML element <able> on line 1
in label of node G
や
Error: syntax error in line 1
... </td><tr> ...
in label of node G
でこちらはファイル内の行数は入ってない。
それぞれerrorformatの1つ目、2つ目に対応している。