graphviz 是一个很古老的开源软件包了,用来绘制结构化的图形。
通过它,你只需要编写简单的脚本(dot 语言),描述图的逻辑和关系, 它就能够自动帮你搞定布局之类的琐碎事情,生成你需要的图。
在编程当中,其实很多时候并不太在乎图的美观和布局,往往我们需要的是一种直观的图形方式来表达我们内在的复杂逻辑。 这时,graphviz 的威力就发挥出来了。只需要使用 dot 脚本简单描述下逻辑,就能很好的得到需要的直观图形。
这篇博文总结了下 dot 的常用语法和几个示例以让我更好的使用 dot。 我本人喜欢在 org-mode 中使用 org-babel 插入所需要的图,关于这方面的配置留到下篇博文再讲。
首先上一个很厉害也很实用的示例,有人用 dot 轻松的绘制出了离散数学的思维导图: https://zhuanlan.zhihu.com/p/20450190
1. 有向图和无向图
|
|
使用 digraph 定义有向图。上面的代码定义了有向图 G。 有向图中,使用 -> 符号表示边。上面的代码中,从节点 a 指向节点 b 有一条边。
|
|
使用 graph 定义无向图。上面的代码定义了无向图 G。 无向图中,使用 – 符号表示边。上面的代码中,节点 a 和节点 b 之间有一条边。
2. 边和节点
如下定义了节点 a 和 b:
|
|
如下定义了节点 a 到 b 的边:
|
|
可以看到,在定义边的时候需要说明节点。如果这些节点之前没有定义过,在这里也会被定义。
如果一个节点到多个节点都有边,还有一种简写法:
|
|
甚至,多个节点到多个节点都有边:
|
|
连着写也是可以的:
|
|
实际上,末尾的分号是可写可不写的。而且无论你写不写分号,换不换行都不影响语义。 这个看个人习惯,dot 的语法并没有强制规定这个。
3. 设置属性
3.1. 对单个节点或边设置属性
在边或节点的后面加上一对方括号,里面使用 key=value 的形式设置它的属性。
边和节点都有个 label 属性,表示它实际显示的文字。默认情况下,边是不显示文字的,节点的文字就是节点的名称。 下面给节点和边手动设置 label 属性:
|
|
节点的 shape 属性表示节点的形状,边的 arrowhead 表示箭头的形状:
|
|
可以看到,要设置这个边或这个节点的多个属性,之间用逗号隔开。
更多关于边和节点的形状,参考这里: 节点的形状:http://graphviz.org/content/node-shapes 边的形状:http://graphviz.org/content/arrow-shapes
3.2. 对所有的节点或边设置属性
如果你想一次设置对多个节点生效,这样:
|
|
在 node 后接中括号,里面写上属性设置,接下来定义的所有节点会默认使用这里的属性设置。
对多个边设置属性也类似节点。在 edge 后接中括号设置属性。
3.3. 设置图的属性
图本身也能设置一些属性,比如布局方式,图本身的说明标签:
|
|
rankdir 设置了图的布局为 LR,即从左向右;默认图的布局是 TB,即从上向下。 label 设置了对图本身的说明标签。
3.4. 常用属性
这篇文章里对常用的图,边和节点的属性做了一个较好的总结: http://www.jianshu.com/p/5b02445eca1d
4. 注释
dot 支持 C 和 C++风格的注释,//和/* */两种。
5. 复杂的节点结构
通过对 label 进行一定格式的编写,就能够在 label 中呈现出如下这样的结构:
|
|
注意到节点被分成了几个小方框,而且每一个方框都可以指定一个名称。
在连接节点时,通过这个名称就能更细的指定具体连接到哪一个小方框上:
|
|
使用这个特点,能够使用 dot 很方便的画出数据结构的图。
6. 子图
通过子图,可以对边和节点进行分组。
如果子图名以 cluster 开头,这个子图会用一个方框框起来。 而且 cluster 会被当成一个新的布局来处理。 你还可以对 cluster 设置某些属性,比如背景色,标签之类的。
|
|
7. 几个示例
通过下面几个示例可以看到,用 dot 绘制标准化的图形,很简单直观。
悄悄的说一句,这些图,是我从官方的《dotguide》里面剽窃来的,嘘。。。
7.1. 函数调用图
|
|
7.2. 数据结构二叉树
|
|
7.3. 数据结构 hash 表
|
|
8. 最后及其它资料
可以看到,dot 这种语言语法简单,稍微学习就能编辑简单的脚本来描述复杂的图形。 对于这种方式生成图形,初始用时可能有些不习惯,毕竟使用这种“写代码”的方式来生成图形是很反直觉的。
但是熟悉之后就会发现,使用 dot 在画某些图形,特别是思维导图类时, dot 能帮助我们从烦琐的布局中解脱出来,让我们的思绪和注意力集中在真正的逻辑上。 专心思考一件事情时,任何一个分心点,都有可能让思维大打折扣。
在学习使用 dot 的过程中参考了以下资料,特此感谢: