DOT语言

前言

常会在一些技术书籍、文章里面看到描述数据结构的图形,很大一部分应该是用DOT语言生成的图片,还有一部分可能是metapost生成的。

对于DOT语言 ,是一种文本图形描述语言,文件通常是具有.gv或是.dot的文件扩展名,比较常用的用Graphviz软件包 渲染为多种文件格式。

DOT语言适合快速、高效的画出流程图、结构图等,但图中元素是自动布局的,无法精确控制每个元素的具体位置;当有大量元素的时候,自动布局的优势就显现出来了。如果需要精确布局,可以生成图片然后调整图片内容。

语法

语言定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
graph:[ strict ] (graph | digraph) [ ID ] '{' stmt_list '}'
stmt_list:[ stmt [ ';' ] [ stmt_list ] ]
stmt: node_stmt
| edge_stmt
| attr_stmt
| ID '=' ID
| subgraph
attr_stmt:(graph | node | edge) attr_list
attr_list:'[' [ a_list ] ']' [ attr_list ]
a_list:ID '=' ID [ ',' ] [ a_list ]
edge_stmt:(node_id | subgraph) edgeRHS [ attr_list ]
edgeRHS:edgeop (node_id | subgraph) [ edgeRHS ]
node_stmt:node_id [ attr_list ]
node_id:ID [ port ]
port:':' ID [ ':' compass_pt ]
|':' compass_pt
ubgraph:[ subgraph [ ID ] ] '{' stmt_list '}'
compass_pt:(n | ne | e | se | s | sw | w | nw | c | _)

无向图

用关键字graph定义一个无向图,用“ - - ”表示节点之间的关系,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
#+begin_src dot -l -n
graph test1{
a[label="旧金山",shape=house];
b[label="KDS",shape=box,fillcolor=yellow];
c[label="北京",shape=egg,style=filled,fillcolor=yellow];
d[label="沈阳",shape=ellipse];
a--b[label="总部"];
b--c[label="MOA",color=red];
b--d[label="神秘部队",color=blue];
label="test1.png";
}
#+end_src

生成一张PNG图片:

1
dot -Tpng test1.dot > test1.png

有向图

用关键字digraph定义一个有向图,用“ -> ”表示节点之间的关系,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#+begin_src dot -l -n
digraph test2{
rank=TD;
a[label="Buiness Analysis"];
b[label="Requirement Analysis"];
c[label="Design"];
d[label="Module Design"];
e1[label="Code A"];
e2[label="Code B"];
f[label="Test"];
f1[label="Test A"];
f2[label="Test B"];
g[label="N+1 Product"];
h[label="N Product"];
a -> b;
b -> c[label="Review",color=red];
c -> d;
d -> e1;
d -> e2;
e1 -> f1;
e2 -> f2;
f1 -> f;
f2 -> f;
f -> g;
g -> h[label="Review",color=red];
label="\n\nSDM WorkFlow\n\n";
}
#+end_src

生成图片: dot -Tpng test2.dot > test2.png

属性

对于图片中的节点、线条和边框,都可以定义自己的属性,比如颜色等,多个属性用”, “ 分割:

1
2
3
4
5
6
7
8
#+begin_src dot -l -n
graph graphname {
a [label="Foo"]; // label属性可以改变节点的显示名称
b [shape=box]; // 节点形状被改变了
a -- b -- c [color=blue]; // a-b边和b-c边有相同的属性
b -- d [style=dotted];
}
#+end_src

这个例子可以看到(命令 info dot 能查看更多细节):

  • label属性定义节点的显示名称
  • shape属性定义节点的形状,其中box是盒子外框,更多查阅:http://www.graphviz.org/content/node-shapes
  • “//”是注释符,“#”也是注释,“/../”也是注释,类似C风格和Shell风格
  • color属性定义边框线条颜色
  • style属性定义线条的样式风格,风格列表:solid、dashed 、dotted、 bold、 invis

数据结构示意图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#+begin_src dot -l -n
digraph g {
size="30,40";
bgcolor="#BBCAF2";
// graph属性,用来定义图片的一些属性
// rankdir=LR , 表示从Left到Right排列图形,LR,TD
// center=ture, 图片居中显示
// margin=0.2, 边缘间距,0表示不需要边缘间距
// nodesep=2.1, 表示节点之间的距离
// ranksep=0.3, 表示列与列之间的距离
// 关于属性attr: http://www.graphviz.org/content/attrs
graph[rankdir=LR, center=true, margin=0.2, nodesep=10, ranksep=1]
// edge用来定义线条的属性
// arrowsize=1.0, 设置箭头大小
// arrowhead=vee, 设置箭头形状是v字型
// 关于线条edge:http://www.graphviz.org/content/arrow-shapes
edge[arrowsize=1.0, arrowhead=vee]
// node用来定义节点的属性
// shape=record, 定义节点形状是类似档案记录
// height=10,定义节点的高度
// width=10,定义节点宽度
// fontname="Courier-Bold", 定义字体
// fontsize=10, 定义字体大小
// fixedsize=true, 固定大小,false是自动变更大小
// 关于节点node: http://www.graphviz.org/content/node-shapes
node [shape = record,fontname="sans-serif", fontsize=20, width=1, height=1, fixedsize=false];
node0[label = "<prev> prev|<value> A|<next> next"]; // <xx>,这里xx是一个属性元素,可以调用
node1[label = "<prev> prev|<value> B|<next> next"]; // B, 这是节点的显示名称
node2[label = "<prev> prev|<value> C|<next> next"]; // | 用来分割,label有很多魔法,要查看文档
head [label = "HEAD", url="http://lesliezhu.github.com"];
head -> node0:value[dir=both, arrowtail=dot]; //箭尾是点,只有both的才有效
node0:next -> node1:value[color=red, tailport=s headport=s, dir=both,arrowtail=vee]; //这里的dir=both是双向箭头
node1:next -> node2:value[color=blue, tailport=s headport=s,arrowhead=normal]; //箭头是普通造型
//{rank=same; node0 node1 node2;} // 3个节点在同一列
label="\n简单的数据结构关系图\n";
}
#+end_src

效果:

1
$ dot -Tpng test5.dot -o test5.png

子图

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
digraph Agency {
size="30,40";
bgcolor="#BBCAF2";
// graph属性,用来定义图片的一些属性
// rankdir=LR , 表示从Left到Right排列图形,LR,TD
// center=ture, 图片居中显示
// margin=0.2, 边缘间距,0表示不需要边缘间距
// nodesep=2.1, 表示节点之间的距离
// ranksep=0.3, 表示列与列之间的距离
graph[center=true, margin=0.2, nodesep=1, ranksep=1]
// edge用来定义线条的属性
// arrowsize=1.0, 设置箭头大小
// arrowhead=vee, 设置箭头形状是v字型
edge[arrowsize=1.0, arrowhead=vee]
// node用来定义节点的属性
// shape=record, 定义节点形状是类似档案记录
// height=10,定义节点的高度
// width=10,定义节点宽度
// fontname="Courier-Bold", 定义字体
// fontsize=10, 定义字体大小
// fixedsize=true, 固定大小,false是自动变更大小
node [shape = record,fontname="sans-serif", fontsize=20, width=1, height=1, fixedsize=false];
subgraph cluster_agency{
agency[label="Agency Data"];
subgraph cluster_info{
label = "Factor Day";
the4th1[label = "4th",shape = record,fontname="sans-serif", fontsize=20,
width=1, height=0.5, fixedsize=false,color=red,style=filled];
the6th[label = "6th",shape = record,fontname="sans-serif", fontsize=20,
width=1, height=0.5, fixedsize=false,color=blue,style=filled];
the8th[label = "8th",shape = record,fontname="sans-serif", fontsize=20,
width=1, height=0.5, fixedsize=false,color=green,style=filled];
}
subgraph cluster_fnma{
label="FNMA";
fn[label = "{<fix> FIX|<arm>ARM|<breakout> Breakout|<ll> Loan Level}"];
}
subgraph cluster_fhlmc{
label="FHLMC";
fh[label = "{<fix> FIX|<arm>ARM|<breakout> Breakout|<ll> Loan Level}"];
}
gnma[label="{GNMA I|FIX|Breakout|Loan Level||GNMA II|FIX|ARM|Breakout|Loan Level}"];
agency->gnma;
agency->fn;
agency->fh;
agency->the8th;
agency->the6th;
agency->the4th1;
}
label="\nMBS Agency关系图\n";
}

Graphviz工具

  • dot :: 一个用来将生成的图形转换成多种输出格式的命令行工具。其输出格式包括PostScript,PDF,SVG,PNG,含注解的文本等等。
  • neato :: 用于sprint model的生成(在Mac OS版本中称为energy minimized)。
  • twopi :: 用于放射状图形的生成
  • circo :: 用于圆形图形的生成。
  • fdp :: 另一个用于生成无向图的工具。
  • dotty :: 一个用于可视化与修改图形的图形用户界面程序。
  • lefty :: 一个可编程的控件,它可以显示DOT图形,并允许用户用鼠标在图上执行操作。

更多文档查阅:http://www.graphviz.org/Documentation.php

吴羽舒 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!