LoginSignup
57
48

More than 5 years have passed since last update.

Graghvizでグラフ構造からグラフを描画する

Last updated at Posted at 2015-09-22

GraphvizはDOT言語で記述されたグラフ構造からグラフを出力するソフトフェア。

インストール

homebrewだと

$ brew install graphviz

でインストールできる。

サンプルコード

以下にまるっとしたサンプルコードを置く。色々な例を書くためにかなりごちゃごちゃしている。

digraph sample1 /* ←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-Roman
        fontsize=10,              // デフォルトは14
        fontcolor="#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の形。デフォルトはellipse
        width=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=circle
        style=striped
        width=0.5
        height=0.5
        color="#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=2
        shape=box
        style=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=<<table border="0"><tr><td><img src="tmsanrinsha_icon.jpg" /></td></tr><tr><td><font color="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, none
    D -> E [dir=both];
    E -> F;
    E -> G -> H;                            // まとめてかける
    F -> {J, K}

    // サブグラフ。名前をclusterで始めると枠ができて、ラベルも指定できる
    // サブグラフの中にサブグラフ、サブグラフ間のedgeはdot layoutではできない。
    // fdp layoutならできる
    subgraph cluster1 {
        label="cluster1";
        I [shape=ellipse color=black, fontcolor=black, fontname="Times-Roman", fillcolor="#fdf6e3" ]
        I -> A;
        {rank=same; A; I;}
    }

}

コードと同じディレクトリに画像も置いた状態で、例えばpngに変換するには

$ dot -T png sample1.dot -o sample1.png

と打つと画像が出力される。

2015-09-20-194311.png

Node

nodeのshape一覧

Edge

edgeのshape一覧

color

color name一覧

画像の埋め込み

node Fでやっているようにimage属性を使うか、node GでやっているようにlabelでHTMLを使う。

画像にラベルを入れる方法として、xlabelを使うと画像の外側にラベルを置くことができる

F [
    image="tmsanrinsha_icon.jpg"
    shape=none
    label=""
    xlabel="\N"
    color="#fdf6e3"
]

しかしこの方法だとラベルの位置を指定できない。
image属性を使って、下にラベルをおきたい場合は、下に余白のある画像を作るかheightを少し大きめにとって

F [
image="tmsanrinsha_icon.jpg"
shape=none
label="\N"
height=2
labelloc=b
fillcolor="#fdf6e3"
color="#fdf6e3"
]

としてやる。

HTML-Like Label

  • labelにtable, br, font, imgのなどのタグが使える。
  • imgはtableの中にしかかけない。imageとbrは/>で閉じる
  • <>で全体を囲む

以下が参考になる

cluster

layoutをfdpにするとnodeとcluster、cluster間でedgeを設定できて、subgraphの中にsubgraphを作ることも可能のようだ。

その他

  • 無向グラフと有向グラフを混ぜることはできない。

参考資料

Vim

syntaxやomni補完が使えるようになるプラグイン。
コンパイルでできるがそれはquickrunでやっている。

omni補完をneocompleteで使うための設定

if !exists('g:neocomplete#force_omni_input_patterns')
    let g:neocomplete#force_omni_input_patterns = {}
endif
let g:neocomplete#force_omni_input_patterns.dot = '\%(=\|,\|\[\)\s*\w*'

forceで設定しないとうまく行かなかった。パターンについてはhttps://github.com/wannesm/wmgraphviz.vim/blob/master/ftplugin/dot.vim のGraphvizCompleteを見て設定。

スニペットは大したものがないので、設定しなくてもよいが、設定するならこんな感じ。

let g:neosnippet#snippets_directory= [
\   '~/.vim/bundle/vim-snippets/snippets',
\   '~/.vim/bundle/wmgraphviz.vim/snippets',
\]

quickrunの設定

開いているdotのコードからpng画像を生成(ファイル名は拡張子をpngに変更したもの)して、それをopenする設定(mac用)。
open -gでバックグラウンドで起動しようとしたけどだめだった。

let g: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つ目に対応している。

57
48
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
48