新しいことにはウェルカム

[技術] [電子工作] [ガジェット] [ゲーム] のメモ書き

テキストだけで図が描けるGraph::Easyの使い方メモ




パワーポイントなどで図を描こうとすると、レイアウトやサイズなどがなかなか決められず、サクッと描くことができない性分です。

設定を変更できるから迷うのであって、いっその事、ガチガチに制約があった方が割り切れていいんじゃないかと、よくある、テキストで描かれた図を作成するツールを検討してみました。

テキストだけで図が描けるGraph::Easyの使い方メモ

そのようなツールはいくつかあるのですが、一番シンプルで分かりやすかった「Graph::Easy」を使ってみることにしました。

Graph::Easyの使い方はそれほど難しくないのですが、CUIツールなので使っていないとすぐに忘れてしまうため、個人用備忘録としてここにまとめました。

インストール

Graph::EasyはPerlのモジュールなのでcpanを使ってインストール

cpan Graph::Easy

cpanが入っていない場合は下記でcpanをインストール

sudo apt-get install build-essential

使い方

ファイルを介した方が後々楽なのでその方法を記す。結果は標準出力に出力されるので、必要ならばリダイレクトでファイルに出力する

graph-easy <インプットファイルパス>

書き方

基本:ノードに線を引く

  • 線の向きは「直線」「矢印」「双方向矢印」
  • 線の種類は「-」「.」「=」
    • 他にもあるが、テキストなので違いはほとんど分からず、これで十分
■入力■
[A]--[B]->[C]<->[D]
[E]..[F].>[G]<.>[H]
[I]==[J]=>[K]<=>[L]

■出力■
+---+     +---+     +---+      +---+
| A | --- | B | --> | C | <--> | D |
+---+     +---+     +---+      +---+
+---+     +---+     +---+      +---+
| E | ... | F | ..> | G | <..> | H |
+---+     +---+     +---+      +---+
+---+     +---+     +---+      +---+
| I | === | J | ==> | K | <==> | L |
+---+     +---+     +---+      +---+

ノードの並びは、アウトプットが左でインプットが右に決まっている。右から左、つまり「[B]<-[C]」という書き方はできない。そういう場合は「[C]->[B]」の行を追加する。

■入力■
[A]->[B]
[C]->[B]

■出力■
+---+     +---+     +---+
| A | --> | B | <-- | C |
+---+     +---+     +---+

線に名前をつける。ノードの表示名を変える

■入力■
[A]--{label:line}[B]
[C]{label:node}--[D]

■出力■
+------+  line   +---+
|  A   | ------- | B |
+------+         +---+
+------+         +---+
| node | ------- | D |
+------+         +---+

線に名前をつける方法は他に「[A]- line ->[B]」」というやり方もあるが、これは向きの無い線(「--」など)には使えないので、「label」を使ったやり方に統一しておいた方が覚えることが少なくて済む。

分岐・合流

■入力■
[A]->[B]->[C]
[D]->[B]
[B]->[E]

■出力■
          +---+
          | E |
          +---+
            ^
            |
            |
+---+     +---+     +---+
| A | --> | B | --> | C |
+---+     +---+     +---+
            ^
            |
            |
          +---+
          | D |
          +---+

各線のつながりを1つ1つ分けて書いていけば、Graph::Easyがよしなにつないでくれる。

1点からの分岐・1点への合流

■入力■
[A]->{start:front,0}[B]
[A]->{start:front,0}[C]

■出力■
+---+          +---+
| A | -+-----> | B |
+---+  |       +---+
       |       +---+
       +-----> | C |
               +---+

■入力■
[A]->{end:back,0}[C]
[B]->{end:back,0}[C]

■出力■
+---+           +---+
| A | ------+-> | C |
+---+       |   +---+
            |
            |
            |
+---+       |
| B | ------+
+---+

線の途中の分岐・合流

■入力■
[L1]{shape:edge}
[L2]{shape:edge;label:""}
[A]--[L1]->[B]--[L2]->[C]
[L1]->[D]
[E]->[L2]

■出力■
+---+      L1        +---+               +---+
| A | -------------> | B | ------------> | C |
+---+                +---+               +---+
            |                    ^
            |                    |
            v                    |
          +----+               +---+
          | D  |               | E |
          +----+               +---+

「{shape:edge}」でノードを線の途中のポイントとすることができる。ポイント名をlabelで無名にすると、名前が表示されなくなる。

グループ化

■入力■
(GroupA [A]->[B])
[B]->[C]
[A]->[D]

■出力■
+ - - - - - - - - - -+
' GroupA             '
'                    '
' +------+     +---+ '     +---+
' |  A   | --> | B | ' --> | C |
' +------+     +---+ '     +---+
'                    '
+ - - - - - - - - - -+
    |
    |
    v
  +------+
  |  D   |
  +------+

「()」で囲むとグループになる。ただ、イマイチ使い勝手が良くないので、あまり凝ったことはせず、アクセント程度に用いるのがよさげ。

全体の向きの変更

■入力■
graph{flow:south}
[A]->[B]

■出力■
+---+
| A |
+---+
  |
  |
  v
+---+
| B |
+---+

何も設定しないと図は左から右に描かれるが、「graph{flow:[north|south|east|west]}」で全体の向きを指定できる。

線が出ていく面と、入っていく面の指定

■入力■
[A]->{start:north; end:south}[B]

■出力■
  +----+
  |    |
+---+  |  +---+
| A |  |  | B |
+---+  |  +---+
       |    ^
       +----+

どうしても、この面から線が出て、この面へ入っていくのを決めたい時は、指定することが可能。どちらか一方だけの指定も可能。

同じ面から複数の線を並行に出す

■入力■
[A]->{start:east}[B]
[A]->{start:east}[C]
[A]->{start:east}[D]

■出力■
+---+     +---+
|   | --> | B |
|   |     +---+
|   |     +---+
| A | --> | C |
|   |     +---+
|   |     +---+
|   | --> | D |
+---+     +---+

同じ面から複数線を定義すると、複数の線が並行に並ぶ。

ノードの枠線を変える

■入力■
[A]->[B]{border:dotted}

■出力■
+---+     .....
| A | --> : B :
+---+     :...:

他にもあるが、テキストなので違いはほとんど分からず、これで十分

テキスト折り返し

■入力
[A\nB]->[C]{label:C\nD}

■出力■
+---+     +---+
| A |     | C |
| B | --> | D |
+---+     +---+

「\n」で改行を入れられる。

画像出力

dot形式で出力して画像化する場合

テキストだけで図が描けるGraph::Easyの使い方メモ
dot画像化例

「dot」を使って画像を作成しているのでdotが必要。dotは「Graphviz」をインストールすると付いてくる。

sudo apt-get install graphviz

「-png」オプションでpng出力

graph-easy <入力ファイル名> -png

画像サイズを指定する場合は、一旦「dot」形式で出力して、それを「dot」に渡してオプションで指定する。

graph-easy <入力ファイル名> -as_dot | dot -Tpng -Gsize=1 -Gdpi=500 -o <出力ファイル名>

上記は500pxの出力例。縦横のどちらか大きい方の最大値が指定値になる。(縦のみ、横のみのサイズ指定は無理そう)

テキストを画像化する場合

テキストだけで図が描けるGraph::Easyの使い方メモ
テキスト画像化例

「Imagemagick」を使ってテキストを画像化する。Imagemagickが入っていない場合はインストール。

sudo apt-get install imagemagick

色、サイズを指定して出力

graph-easy <入力ファイル名> | \
    head -c -1 | \
    convert -background "#ffffff" -fill "#000000" -font "FreeMono" -size 100x100 \
        -label:@- <出力ファイル名>

最後に改行が入るので「head -c -1」で取り除いている。

幅を指定して縦をよしなにする場合は、「-size 100x」と縦を指定しない。ただし、その時の出力画像の縦サイズは、1フォント分の縦になるので、テキストの縦行数から実際の縦幅を計算して、「-size 100x<計算後の縦サイズ>」で再度出力し直す。

縦を指定して横をよしなにする場合は、「-size x100」と幅を指定しない。