グラフ作成スクリプトはレイアウト指定がイマイチ

Table of Contents

tunnel ツールのネタを書いた時、 dot を使ってグラフを作った。

dot は手軽にグラフを書ける便利なツールだが、 レイアウト制御に難があると思う。

この記事は、そんな思いを書いた単なる愚痴だ。 解決策は用意していない。

1 グラフ作成ツールの利点と欠点

dot などのグラフ作成ツールの利点には次が挙げられる。

ノードのリンクを指定するだけで、後はツールが良い感じにグラフを自動で作成してくれる。

パワポ等でグラフを作成するのと比べると、これは大きな利点だ。

そして多くの場合、ツールが作成するグラフは、それなりに見易いグラフになってくれる。

ただ、自動で作成するため、 意図とは異なるレイアウトのグラフが出来あがることもある。

レイアウトのことは割り切って使うとか、 気に入らないなら他のパワポなどの draw 系のツールで描けば良いという話もあるが、 それは何か違うと思っている。

2 dot のグラフ

例えば次の図は、 tunnel と host を繋ぐ処理をグラフ化したものだ。

Sorry, your browser does not support SVG.

このグラフの 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 指定を取ってグラフを生成すると次のようになる。

Sorry, your browser does not support SVG.

Sorry, your browser does not support SVG.

3 rank 指定の有無の違い

グラフの違い分かり易いように並べて表示する。

  • rank 指定あり

Sorry, your browser does not support SVG.

  • rank 指定なし

Sorry, your browser does not support SVG.

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 を指定しても、 思った通りにならないことが多いということだ。

例えば、次の指定を追加で行なうと、

Sorry, your browser does not support SVG.

Sorry, your browser does not support SVG.

Date: 2020-06-09

Author: ifritJP

Created: 2020-06-09

Validate