グラフ作成スクリプトはレイアウト指定がイマイチ
Table of Contents
tunnel ツールのネタを書いた時、 dot を使ってグラフを作った。
dot は手軽にグラフを書ける便利なツールだが、 レイアウト制御に難があると思う。
この記事は、そんな思いを書いた単なる愚痴だ。 解決策は用意していない。
1 グラフ作成ツールの利点と欠点
dot などのグラフ作成ツールの利点には次が挙げられる。
ノードのリンクを指定するだけで、後はツールが良い感じにグラフを自動で作成してくれる。
パワポ等でグラフを作成するのと比べると、これは大きな利点だ。
そして多くの場合、ツールが作成するグラフは、それなりに見易いグラフになってくれる。
ただ、自動で作成するため、 意図とは異なるレイアウトのグラフが出来あがることもある。
レイアウトのことは割り切って使うとか、 気に入らないなら他のパワポなどの draw 系のツールで描けば良いという話もあるが、 それは何か違うと思っている。
2 dot のグラフ
例えば次の図は、 tunnel と host を繋ぐ処理をグラフ化したものだ。
このグラフの dot コードは次になる。
digraph G { rankdir = RL; tunnel [shape=doublecircle]; subgraph clusterA { packetWriter [shape=rect; margin=0.2;]; packetReader [shape=rect; margin=0.2;]; keepalive [shape=rect; margin=0.2;]; WriteQueue tunnel2Stream [shape=rect; margin=0.2;]; stream2Tunnel [shape=rect; margin=0.2;]; ReadQueue {rank = max; packetReader; packetWriter} {rank = same; WriteQueue; ReadQueue} {rank = min; tunnel2Stream; stream2Tunnel; keepalive} } host [shape=box3d]; tunnel -> packetReader packetReader -> ReadQueue ReadQueue -> tunnel2Stream stream2Tunnel -> WriteQueue WriteQueue -> packetWriter packetWriter -> tunnel keepalive -> WriteQueue tunnel2Stream -> host host -> stream2Tunnel {rank=min;host} }
コードの細かい部分はここでは触れないが、
{rank=}
を次の 4 つ指定していることを確認して欲しい。
{rank = max; packetReader; packetWriter}
{rank = same; WriteQueue; ReadQueue}
{rank = min; tunnel2Stream; stream2Tunnel; keepalive}
{rank=min;host}
この rank 指定を取ってグラフを生成すると次のようになる。
3 rank 指定の有無の違い
グラフの違い分かり易いように並べて表示する。
- rank 指定あり
- rank 指定なし
rank 指定ありは矢印の向きが素直に円を描いる一方で、 rank 指定なしは矢印が交差していたり、矢印が長かったりで、 動きが捉え辛くないだろうか?
rank を指定して、目的のレイアウトになったから良いといえば良いんだが、 その rank の指定が試行錯誤の末、なんでこの指定でいけたかの納得がいかない。
4 rank 指定の意味
今回指定した 4 つの rank の内、次の 3 つは中央の四角の中の並び順を指定している。
{rank = max; packetReader; packetWriter}
{rank = same; WriteQueue; ReadQueue}
{rank = min; tunnel2Stream; stream2Tunnel; keepalive}
そもそも、 rank は何を指定するものなのかというと、 ノードの配置ランクを指定する。
上記の 3 つの指定は、 packetReader, packetWriter が max のランクで、 WriteQueue, ReadQueue が同じランクで、 tunnel2Stream, stream2Tunnel, keepalive が min のランクであることを設定している。
これは、 rank 指定した時の図と見比べて、 中央の四角の中の左側から max, same, min の順で並べられていることから納得できる。
次に 4 つの内の最後の rank 指定は、 host の場所を指定している。
{rank=min;host}
これは、 host が min のランクであることを設定している。
これも rank 指定した時の図と見比べて、 host が一番右に配置されていることから納得できる。
じゃぁ、この章の最初に「納得いかない」と言ったのは何だったのか?と思うだろう。
それは、これと同じ考え方で rank を指定しても、 思った通りにならないことが多いということだ。
例えば、次の指定を追加で行なうと、