使用graphviz绘图

2015年11月10日更新 在实践中,我又发现了一些graphviz的有趣的特性,比如时序图,rank以及图片节点等。在这里一并更新。 ##前言 日常的开发工作中,为代码添加注释是代码可维护性的一个重要方面,但是仅仅提供注释是不够的,特别是当系统功能越来越复杂,涉及到的模块越来越多的时候,仅仅靠代码就很难从宏观的层次去理解。因此我们需要图例的支持,图例不仅仅包含功能之间的交互,也可以包含复杂的数据结构的示意图,数据流向等。 但是,常用的UML建模工具,如Visio等都略显复杂,且体积庞大。对于开发人员,特别是后台开发人员来说,命令行,脚本才是最友好的,而图形界面会很大程度的限制开发效率。相对于鼠标,键盘才是开发人员最好的朋友。 ###graphviz简介 本文介绍一个高效而简洁的绘图工具graphviz。graphviz是贝尔实验室开发的一个开源的工具包,它使用一个特定的DSL(领域特定语言): dot作为脚本语言,然后使用布局引擎来解析此脚本,并完成自动布局。graphviz提供丰富的导出格式,如常用的图片格式,SVG,PDF格式等。 graphviz中包含了众多的布局器: dot 默认布局方式,主要用于有向图 neato 基于spring-model(又称force-based)算法 twopi 径向布局 circo 圆环布局 fdp 用于无向图 graphviz的设计初衷是对有向图/无向图等进行自动布局,开发人员使用dot脚本定义图形元素,然后选择算法进行布局,最终导出结果。 首先,在dot脚本中定义图的顶点和边,顶点和边都具有各自的属性,比如形状,颜色,填充模式,字体,样式等。然后使用合适的布局算法进行布局。布局算法除了绘制各个顶点和边之外,需要尽可能的将顶点均匀的分布在画布上,并且尽可能的减少边的交叉(如果交叉过多,就很难看清楚顶点之间的关系了)。所以使用graphviz的一般流程为: 定义一个图,并向图中添加需要的顶点和边 为顶点和边添加样式 使用布局引擎进行绘制 一旦熟悉这种开发模式,就可以快速的将你的想法绘制出来。配合一个良好的编辑器(vim/emacs)等,可以极大的提高开发效率,与常见的GUI应用的所见即所得模式对应,此模式称为所思即所得。比如在我的机器上,使用Sublime Text 编辑dot脚本,然后将F7/Cmd-B映射为调用dot引擎去绘制当前脚本,并打开一个新的窗口来显示运行结果: 对于开发人员而言,经常会用到的图形绘制可能包括:函数调用关系,一个复杂的数据结构,系统的模块组成,抽象语法树等。 ###基础知识 graphviz包含3中元素,图,顶点和边。每个元素都可以具有各自的属性,用来定义字体,样式,颜色,形状等。下面是一些简单的示例,可以帮助我们快速的了解graphviz的基本用法。 ####第一个graphviz图 比如,要绘制一个有向图,包含4个节点a,b,c,d。其中a指向b,b和c指向d。可以定义下列脚本: digraph abc{ a; b; c; d; a -> b; b -> d; c -> d; } 使用dot布局方式,绘制出来的效果如下: 默认的顶点中的文字为定义顶点变量的名称,形状为椭圆。边的默认样式为黑色实线箭头,我们可以在脚本中做一下修改,将顶点改为方形,边改为虚线。 ####定义顶点和边的样式 在digraph的花括号内,添加顶点和边的新定义: node [shape="record"]; edge [style="dashed"]; 则绘制的效果如下: ####进一步修改顶点和边样式 进一步,我们将顶点a的颜色改为淡绿色,并将c到d的边改为红色,脚本如下: digraph abc{ node [shape="record"]; edge [style="dashed"]; a [style="filled", color="black", fillcolor="chartreuse"]; b; c; d; a -> b; b -> d; c -> d [color="red"]; } 绘制的结果如下:...

November 10, 2015 · 6 min · 邱俊涛 | Juntao Qiu