LoginSignup
9
8

More than 3 years have passed since last update.

blockdiag(edge_layout=flowchart)に言うことを聞かせる

Last updated at Posted at 2018-05-29

概要
blockdiagでフローチャートを描こうとするも、コレジャナイ出力が得られることが少なくない。
いろいろ使ってみる中で解決できた・できなかった事例について、記録を残していく。

ちょっとの修正で直せたもの

if分岐が横から出ない

状況

edge_layout=flowchartを設定しているにも関わらず、if分岐がひし形の下から出てしまう。
break.png

回避策

ダミーのノードdb0と横並びさせる。
これは、横から分岐を出すには2つのノードが横並びになっている必要があるため。
ダミーノードはshape=noneを使うのが無難。クラス化しておくと使いやすい。
ダミーノードには矢印が付いて欲しくないので、分岐側のエッジはdir=noneとして頭を消しておく。

break_1.diag
blockdiag{
    orientation = portrait;
    edge_layout = flowchart;

    bp [shape=beginpoint];
    lin [shape=flowchart.loopin];
    c [shape=flowchart.condition];
    b0 [shape=box];
    lout [shape=flowchart.loopout];
    ep [shape=endpoint];

    class dummy [shape=none];
    d [class=dummy];

    // main
    bp -> lin -> c -> b0 -> lout -> ep;

    // break
    c -> d -> ep [dir=none];
}

break_1.png

if分岐の左右が思い通りにならない

状況

ifの「そっちじゃない方(b0)」が下に分岐し、とっても不格好になる。
ループを巻き込んじゃったりすると左右にずれてしまい、もう目も当てられない事態になる。

if.png

回避策

なんと、分岐の左右はノードを定義した順序に依存している模様。
というわけで、「分岐の真下に配置したいノード(b1)」を分岐(c)の直後に定義する。
こういうの、ちゃんとコードを読み漁って情報を集めたほうが良いかもしれない。

if_1.png

if_1.diag
blockdiag{
    orientation = portrait;
    edge_layout = flowchart;

    bp [shape=beginpoint];
    lin [shape=flowchart.loopin];
    c [shape=flowchart.condition];

    // b1 -> b0
    b1 [shape=box];
    b0 [shape=box];

    lout [shape=flowchart.loopout];
    ep [shape=endpoint];

    bp -> lin -> c -> b1 -> lout -> ep;
    c -> b0 -> ep;
}

めっちゃ横に膨らむ

状況

分岐の仕方や数によってはフローチャートが横に膨らんでいく場合がある。
スライドの端にちょこっと載せるとか、縦長が嬉しい場合にちょっと直したくなる。
以下の終端が複数あるフローチャートを題材にしてみる。
end2.png

回避策1:下に回り込ませる

1つめの終端(hoge)から、2つめの終端への分岐の開始点(b1)に見えないエッジ(style=none)を引いてあげる。
この2ノードが縦に揃えられることで、レイアウトが変わる。

end2_1.png

end2_1
blockdiag{
    orientation = portrait;
    edge_layout = flowchart;

    bp [shape=beginpoint];
    lin [shape=flowchart.loopin];
    c [shape=flowchart.condition];
    b0 [shape=box];
    b1 [shape=box];
    lout [shape=flowchart.loopout];
    ep0 [shape=endpoint, label="hoge"];
    ep1 [shape=endpoint, label="fuga"];

    // dummy
    class dummy [shape=none];
    d [class=dummy];

    // main
    bp -> lin -> c -> b0 -> lout -> ep0;

    // break
    c -> d [dir=none];
    d -> b1 -> ep1;

    // invisible edge
    ep0 -> b1 [style=none];
}

回避策2:回り道を縮める

上図だが、回り道の矢印が膨らんでいてあまりダイエットできていない。
この「回り具合」はspan_width及びnode_width依存なので、これらを小さく設定する。
ただし、node_widthを縮めてノードまで細くなっては意味ないので、
ノードのサイズ設定に関してはclassを定義してそちらにまとめて書いてやると良い。

end2_2.png

end2_2.diag
blockdiag{
    orientation = portrait;
    edge_layout = flowchart;

    node_width = 20;
    span_width = 20;

    class box [shape=box, width=128];
    class if [shape=flowchart.condition, width=128];
    class lin [shape=flowchart.loopin, width=128];
    class lout [shape=flowchart.loopout, width=128];

    bp [shape=beginpoint];
    lin [class=lin];
    c [class=if];
    b0 [class=box];
    b1 [class=box];
    lout [class=lin];
    ep0 [shape=endpoint, label="hoge"];
    ep1 [shape=endpoint, label="fuga"];

    class dummy [shape=none];
    d [class=dummy, width=10];

    // main
    bp -> lin -> c -> b0 -> lout -> ep0;

    // break
    c -> d [dir=none];
    d -> b1 -> ep1;

    // invisible edge
    ep0 -> b1 [style=none];
}

class定義より上は「おまじない」として使いまわすのが望ましいかもしれない。
bpepのラベルが潰れているが、これも適切なwidthを設定すれば直せる。

どうにもならなさそうなもの

戻りの矢印が引けない

基本的に下から上(左から右)のノードに矢印を引くことが想定されていない模様。
そもそも戻り矢印なんか使わない努力をするべきかも。

  • ループはflowchart.loopin(loopout)を使って書く
  • 折り返し(folded)は使わず、terminatorなどをつかって2つ以上に区切る

左から回り込めない

もし出来る方法があったらマジで教えてほしい。
ただ、実際やるとなるとマッピングの難易度的な意味で開発者への負荷が爆上がりしそう。

文字数制限がキツい

特にflowchart.conditionなどがそうだが、文字数制限がキツい。
また、エッジのラベルも同様(TとかFくらいしか書かないけど)。
横長いノードが嫌なら、heightを増やしてテキストを改行するのが無難か。
改行はlabel="1行目\n2行目"のように書くと普通にできる。

まとめ

上手に使いこなせていないのでつらい。

9
8
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
9
8