简介

graphviz是贝尔实验室开发的一个开源的工具包,它使用一个特定的DSL(领域特定语言):dot作为脚本语言,然后使用布局引擎来解析此脚本,并完成自动布局。graphviz提供丰富的导出格式,如常用的图片格式,SVG,PDF格式等。

相对于ms viso需要手动拖动图标,graphviz只需要通过DOT代码表达各节点的逻辑关系,然后自动布局和输出关系图。最小化复杂关系的连线交叉,增强可读性。尤其在绘制非常复杂的逻辑关系、组织架构、模块组成、数据结构等图时,可以大大减少工作量,理清思路。

但是无法绘制需要自定义或者固定布局的图,比如时序图。

布局器

Graphviz除了DOT语言用于描述图像,还有许多渲染生成工具 —— 布局器:

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

DOT语言

DOT语言是一种文本图形描述语言它提供了一种简单的描述图形的方法,并且可以为人类和计算机程序所理解。DOT语言文件通常是具有.gv或是.dot的文件扩展名。很多程序都可以处理DOT文件。

首先,在dot脚本中定义图的顶点和边,顶点和边都具有各自的属性,比如形状,颜色,填充模式,字体,样式等。然后使用合适的布局算法进行布局。布局算法除了绘制各个顶点和边之外,需要尽可能的将顶点均匀的分布在画布上,并且尽可能的减少边的交叉(如果交叉过多,就很难看清楚顶点之间的关系了)。所以使用graphviz的一般流程为:

  • 定义一个图,并向图中添加需要的顶点和边
  • 为顶点和边添加样式
  • 使用布局引擎进行绘制

基本用法

DOT中使用图(digraph/graph/subgraph)、节点(node)和边(edge)来描述关系图/流程图,在配合一些属性的设置完成绘图。

顶点和边都接受属性的定义,形式为在顶点和边的定义之后加上一个由方括号括起来的key-value列表,每个key-value对由逗号隔开。如果图中顶点和边采用统一的风格,则可以在图定义的首部定义node, edge的属性。

说明:

  • graph 用来描述无向图,关系使用 –来描述,digraph用来描述有向图,关系使用 -> 来描述。
  • demo为定义的图片名称,label和bgcolor为定义的图片属性。
  • father、mother、brother、sister、我、strangers为节点。可以把前面4个节点理解成变量定义,比如定义了一个变量father,名字叫爸爸,用方形来渲染,后面所有调用father都会按照方形爸爸来渲染,但这里其实和变量定义是不同的,因为这个节点即便不用也会渲染出来,比如strangers,变量思维为加强理解。比如我没有定义也是可以直接使用的。
  • 描述节点与节点的关系理解为边。边有有向(->)和无向(–)两种。比如father和mother之间的关系为相互的。
  • 上面有两个特殊的节点,node和edge,node用来定义节点的默认属性,edge用来定义边的默认属性。作用域从本次定义到下一次定义截住。特定节点/边设置的属性会覆盖默认值。
  • []内属性,属性可以针对图、节点、边来设置。
  • father 与子女的关系为一条条写的, mother 的关系则为直接通过大括号的方式来对应三个节点。
  • rank 定义设置节点处在同一行,辅助渲染出来的图的效果。
  • 注释和C语言类似,// 和 # 注释单行, /* */多行注释。
  • DOT的写法不算严格,比如结束可以有分号,属性可以没有引号。

关键字

  • node:定义全局节点属性时使用
  • edge:定义全局连线属性时使用
  • graph:定义全局图属性,或声明一个无向图时使用
  • digraph:声明一个有向图时使用
  • subgraph:声明一个子图时使用,如果父图是有向图则子图是有向图,如果父图是无向图则子图也是无向图
  • strict:用于防止相同的两个节点间使用重复的连线。

ID命名规则

ID是编辑者自定义的字符串,相当于C语言中的标识符。如果ID中间包含空格一定要用双引号包裹。

  • 英文字母[a-zA-Z\200-\377],下划线_,数字[0-9](但不能数字开头),如:Version_3;
  • 纯数字[-]?(.[0-9]+|[0-9]+(.[0-9]*)?),如:-.1或1.414;
  • 双引号包裹的字符串”…“,字符串中的双引号需要转义\“,如:”DOT language”;
  • 尖括号包裹的HTML字符串<…>,如:<Welcome to China.>;实际上甚至可以插入表格。

转义与实体符号

字符串中的字符,只有双引号\“和反斜杠\需要转义。

字符串支持还HTML式的实体符号,如:&表示&,<表示<,β表示β。

当节点的属性shape=record时,竖杠|、花括号{ }、方括号[ ]和尖括号< >都需要转义。

分组符号

前面介绍了两种包裹字符串的符号,双引号”…“和<…>;

另外还有两种包裹分组的符号:方括号[…]和花括号{…}。

罗盘端口

罗盘也就是确定八个方位,罗盘端口就是方位端口。

方位端口是每个节点隐藏自带的,可以直接使用。

每个节点都有八个方位:北n、东北ne、东e、东南se、南s、西南sw、西w和西北nw。

利用方位可以指定连线从哪个位置连接节点,不同于默认情况下的自动连线,利用方位可以手动指定连线的位置。

graphviz中包含了众多的布局器:

  • dot 默认布局方式,主要用于有向图
  • neato 基于spring-model(又称force-based)算法
  • twopi 径向布局
  • circo 圆环布局
  • fdp 用于无向图

无向图

在最简单的应用中,DOT语言可以用来描述一张无向图。无向图显示了对象间最简单的关系,例如人之间的友谊。使用关键字graph开始一张无向图的定义,并用大括号包含要描述的节点,双连字号(–)被用来描述节点间的关系。另外,一行的末尾需要加上分号(;)。

有向图

类似于无向图,DOT语言也可以用来描述一张有向图,类似于流程图和树状图。其语法与无向图相似,但要在图的最开始使用关键字’digraph’,并用箭头(->)表示节点直接的关系。

常用图属性

属性名 默认值 说明
label 图片标签,如上面示例
bgcolor 背景颜色
fontcolor black 字体颜色,定义上面示例的颜色
fontname Times-Roman 字体
fontsize 14 字体大小
rank 子图等级限制, same,min,max,source,sink
rankdir TB 排序方向,LR(left to right) or TB(top to bottom)
compound false If true, allow edges between clusters. 配合 lhead 和 ltail 使用

Graphviz颜色表

Graphviz颜色表

节点

常用节点属性

属性名 默认值 说明
label node name 节点显示内容
color black node边框颜色
fontcolor black 字体颜色
fillcolor 背景色
fontname Times-Roman 字体
fontsize 14 字体大小
shape ellipse 形状,box、ellipse、circle、diamond、plaintext、point、triangle、invtriangle
style 图形样式,eg. bold、dashed、dotted、filled
image 背景图片地址

Graphviz节点样式

Graphviz节点样式

在顶点的形状为record的时候,label属性的语法比较奇怪,但是使用起来非常灵活。比如,用竖线”|”隔开的串会在绘制出来的节点中展现为一条分隔符。用<>括起来的串称为锚点,当一个节点具有多个锚点的时候,这个特性会非常有用,比如节点st_table的type属性指向st_hash_type,第4个属性指向st_table_entry等,都是通过锚点来实现的。

常用边属性

属性名 默认值 说明
label 描述关系
color black 箭头颜色
fontcolor black 关系文字颜色
dir forward 设置方向:forward,back,both,none
arrowhead normal 箭头头部形状。box、crow、diamond、dot、none、normal、vee
arrowtail 箭头尾部形状
arrowsize 1.0 箭头大小
style 图形样式,eg. bold、dashed、dotted、filled
lhead 当 compound 为true时,lhead用于指定边指向的cluster
ltail 与ltail类似

Graphviz箭头样式

Graphviz箭头样式

Graphviz边样式

Graphviz边样式

子图

graphviz支持子图,即图中的部分节点和边相对对立(软件的模块划分经常如此)。

一个图可以包含多个子图,以及子图也可以嵌套子图。子图的名字须为cluster*,否则就直接当节点渲染了。