« ^ »

ditaaで描画した図のテキストをGraphvizで描画可能なDOT形式に変換する

所要時間: 約 4分

システムの構成などをダイアグラムで表現する方法はいくつかあるが、私はよくditaaを使っている。ditaaはアスキーアートで作図し、それをditaaに処理させ画像ファイルを生成する。このようなツールは他にもいろいろとある。例えばPlantUML、Graphviz、Mermeid、blogdiag等だ。これらのツールは、それぞれ専用の記法があり、それはditaaも同様だ。では何故ditaaを使っているかというと、ditaaは元となるテキストファイルもアスキーアートとして視覚的に図として成立しているからだ。他の独自記法は、構成要素の論理的なつながりに重点を置いている。そのため複雑な図の場合、どのような図が描かれているかは描画してみないとイメージしにくい。一方、ditaaはアスキーアートだから、ぱっと見ただけで、どのような図が描かれているかを把握できる。またアスキーアートだから、独自の記法を覚えていなくても、なんとなく描ける。それらの理由からditaaを使用している。ditaaはJavaで実装されており、内部では構成要素のパースをかなり頑張ってやっているようだった。この変換機構に手を入れたいと常々考えていたが、それはなかなか大変な作業だった。昨今はLLMの進歩により、プログラムのソースコードの生成を機械にやらせても、それなりの品質のものを生成できるようになってきた。ditaaのソースはアスキーアートである事を考えると、表現されている図の論理構造を解析し、描画可能な状態にする事はLLMやディープラーニングの得意分野にも思えた。そこでditaaのソースを食わせて、DOT形式に変換できるか試してみる。

いきなり複雑なものからやると混乱するため、シンプルな図から試す。2つの四角(A, B)と、AからBへの向きのある矢印が1つある。

+----------+        +----------+
|          |        |          |
| A        +------->+ B        |
|          |        |          |
+----------+        +----------+

ChatGPTを使い次のように依頼をする。

次のダイアグラムを、位置を崩さずgraphvizで描画可能なdot形式に変換して。

+----------+        +----------+
|          |        |          |
| A        +------->+ B        |
|          |        |          |
+----------+        +----------+

以下の返答がくる。

以下は、graphvizで描画可能なdot形式のコードです。

css
Copy code
digraph {
  A -> B
}
このコードでは、digraphキーワードでグラフの種類を指定し、{}でグラフの要素を囲んでいます。A -> Bは、AからBへ向かう有向矢印を表します。

DOT形式としては次のようになる。

digraph {
  A -> B
}

これでは枠線が四角から丸になってしまうし、AとBの位置関係も横から縦へと変化してしまう。確かに論理的な構造は同一だけれど、位置や形状はそのままにしたい。そこで、位置が崩れないように再生成を依頼してみる。

これでは位置が崩れるのでやりなおして。

すると以下の返答がくる。

申し訳ありません。以下は、図を位置を崩すことなく描画するための修正版です。

css
Copy code
digraph {
  node [shape=none];
  rankdir=LR;
  A -> B;
}
このコードをgraphvizのdotコマンドに渡すと、ダイアグラムが描画されます。

これは以下のようなDOT形式だ。

digraph {
  node [shape=none];
  rankdir=LR;
  A -> B;
}

確かに位置は崩れてはいないけれど、今度は枠線が消失した。なかなか意図した状態にはならない。もう一度試す。

罫線と位置もそのままの状態にして

すると以下の返答がくる。

以下が修正版のdot形式コードになります。図の位置と罫線を保持するため、pos属性を使用しています。

css
Copy code
digraph {
  node [shape=none];
  A [pos="0,0!"];
  B [pos="1,0!"];
  edge [dir=none];
  A -> B [pos="e,50%,50%"];
}
このコードをgraphvizのdotコマンドに渡すと、位置と罫線を保ったままダイアグラムが描画されます。

次のDOT形式が返される。

digraph {
  node [shape=none];
  A [pos="0,0!"];
  B [pos="1,0!"];
  edge [dir=none];
  A -> B [pos="e,50%,50%"];
}

位置が崩れ、枠線が消失した。

指示の仕方が良くない(プロンプトがイマイチ)というのはあるのだが、それを鑑みてもまだ手いた方が自分にとっては都合が良さそうだった。