Graphviz
来自智得网
简介
Graphviz 是一个开源的图形编辑语言,可以进行图形的可视化编辑,绘制结构化的图标和图形非常方便。
Graphviz 使用 DOT 语言来表示图形。
DOT语言可以用简单的文本来表示结点,连线,布局等。
原理
DOT语言描述结点,连线,布局的文本都非常简单,而且从文本本身可以推测中起含义。
结点
DOT语言描述结点的方式是`NodeName`[label=`LabelName`]。
结点可以分为普通的节点和列表节点,列表节点可以使用竖线分隔多个Label来表示,`NodeName`[label=`LabelName1|LabelName2|LabelName3|...|LabelNameN`]。
列表节点的展示可以横排或者竖排,横排使用中括号[]还包裹列表元素,竖排使用{}包裹列表元素。
连线
使用`NodeName1`->`NodeName2`的方式可以绘制一条从节点1到结点2的直线。
`NodeName1`->{`NodeName2` `NodeName3`},可以使NodeName1的结点指向用{}包裹,空格分隔的多个结点。
splines=false;可以强制连线都是直线。
布局
布局可以分为水平布局(左右布局)和垂直布局,rankdir=LR;指定水平布局,在全局范围内生效。
水平布局的时候,可能有一些record需要垂直摆放,label="{}",如果和randdir一致,则不需要{}。
技巧
绘图过程中可以创建一些隐藏结点使得图形对齐。
示例
Hash表
digraph G {
nodesep=.05;
rankdir=LR;
splines=false;
node [shape=record,width=.1,height=.1];
node0 [label = "<f0> |<f1> |<f2> |<f3> |<f4> |<f5> |<f6> | ",height=2.5];
node [width = 1.5];
node1 [label = "<n> user1 | name=jack |sex=m", width=.1];
node2 [label = "<n> user2 | name=andy |sex=m", width=.1];
node3 [label = "<n> user3 | name=will |sex=m", width=1.12];
node4 [label = "<n> user4 | name=great |sex=m", width=.1];
node5 [label = "<n> user5 | name=lina |sex=f", width=1.12] ;
node6 [label = "<n> user6 | name=lida |sex=f", width=.1] ;
node7 [label = "<n> user7 | name=lily |sex=f", width=.1] ;
node0:f0:e -> node1:n;
node0:f1 -> node2:n;
node0:f2 -> node3:n;
node0:f5 -> node4:n;
node0:f6 -> node5:n;
node2:p -> node6:n;
node4:p -> node7:n;
}
B+树
digraph {
rankdir = UD;
splines = false;
nodesep = .3;
node [shape = record,width = .1,height = .1];
node01 [label = "15|<n01>|58|<n02>|89|<n03>"]
node11 [label = "<n11>15|<n12>|<n13>25|<n14>|<n15>37|<n16>"]
node12 [label = "......"]
node13 [label = "......"]
node21 [shape = none, margin = 0, label = <
<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr><td>15</td></tr>
<tr><td port="0">37</td></tr>
<tr><td>Will</td></tr>
</table>>]
node22 [shape =none, margin = 0, label = <
<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr><td>21</td></tr>
<tr><td port="0">56</td></tr>
<tr><td>Eric</td></tr>
</table>>]
node23 [shape = none, margin = 0, label = <
<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr><td>25</td></tr>
<tr><td port="0">12</td></tr>
<tr><td>Bob</td></tr>
</table>>]
node24 [shape = none, margin = 0, label = <
<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr><td>21</td></tr>
<tr><td port="0">53</td></tr>
<tr><td>Jim</td></tr>
</table>>]
node25 [shape = none, margin= 0, label = <
<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr><td>37</td></tr>
<tr><td port="0">2</td></tr>
<tr><td>Eric</td></tr>
</table>>]
node26 [shape = none, margin =0, label = <
<table border="0" cellborder="1" cellspacing="0" cellpadding="4">
<tr><td>87</td></tr>
<tr><td port="0">7</td></tr>
<tr><td>ROSE</td></tr>
</table>>]
node01 : n01 -> node11
node01 : n02 ->node12
node01 : n03 -> node13
node11 : n11 :s -> node21 : n
node11 : n12 -> node22 : n
node11 : n13 -> node23
node11 : n14 -> node24
node11 : n15 -> node25 : n
node11 : n16 -> node26 :n
{
rankdir = LR
rank = same;
node21 -> node22 -> node23 ->node24 -> node25 -> node26
}
}
叶子节点对齐的时候注意,如果是普通的record节点,rank=same,不同的weight权重,以及constraint=false都不能实现对齐,所以使用了HTML like labels