自由绘图软件中有两大神器:gnuplot 和 graphviz。前者一般用来可视化你的数据,比如,描绘函数曲线、数据分布之类的,对我来说其实用的不多。后者在软件领域使用得可能相对频繁,比如,显示一些结构化信息、流程图、网络拓扑图、函数调用序列等等,很是实用。本文介绍一下graphviz。
我之所以说他俩是神器,因为他们提供非常方便的命令行接口,可以完成自动化绘图功能,并且你不必仔细考虑节点尺寸、连线、布局等细节,只需要把握处理流程或者拓扑结构就可以了。这是一种“所思即所得”的绘图工具。
直接举官方的一个示例,这应该是一段代码的流程图:
如下代码就可以胜任:
digraph G {
subgraph cluster_0 {
style=filled;
color=lightgrey;
node [style=filled,color=white];
a0 -> a1 -> a2 -> a3;
label = "process #1";
}
subgraph cluster_1 {
node [style=filled];
b0 -> b1 -> b2;
label = "process #2";
color=blue
}
start -> a0;
start -> b0;
a1 -> b2 [color=red,label="call it",fontcolor=red];
b2 -> b0 [style=dotted];
a3 -> end;
b2 -> end;
start [shape=Mdiamond];
end [shape=Msquare];
}
然后,你可以用make来管理它:
DOT=d:/program/Graphviz/bin/dot.exe
all: graphviz_cluster.png
%.png: %.dot
$(DOT) -Tpng $< -o $@
实际使用中,Graphviz的具体绘图是由一系列的小工具完成的:
- dot 适用于有向无环图(DAG)和各种层次结构绘图。
- neato 常用于无向图,基于一种弹性模型,可以自动优化各节点之间的距离。
- twopi 适用于放射状的布局,即从一个中心出发,以固定的半径绘制其他节点,以此扩展开。
- circo 适用于环状布局,它会先寻找双连通分量,把内聚度较高的子图绘制成团。
- fdp 基于Force-directed算法的弹性模型,适合绘制没有交叉边的无向图。
- sfdp 更适用于大型无向图绘制,节点尺寸的比例相对小很多。
- patchwork 绘制方块形的格状图,该工具忽略边的定义,主要利用
subgraph
进行布局。
它们都是解释一种名为DOT的语法,只是各自适用于不同风格和布局的绘图。从语言的命名就能看出,一般常用的工具就是dot,还有一个以此命名的交互式绘图工具dotty,适用于X Window图形环境。DOT语法大致如下:
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
subgraph : [ subgraph [ ID ] ] '{' stmt_list '}'
compass_pt : (n | ne | e | se | s | sw | w | nw | c | _)
其中,node、edge、graph、digraph、subgraph和strict是关键字。
Update@2008-10-30: BTW,后来一朋友看了这篇短文,说,本来也想用这工具画画图,显示数据的,不过后来都用python替代。言者无心,听者有意。的确多掌握工具,不如只精通一种脚本呢,同学们来学python吧~ 的确很火热,很流行,也很强大。
Update@2011-02-12: 扩展:用 Graphviz 可视化函数调用