Graphviz 适合编程快速绘制流程图之类的图形。
而pygraphviz对graphviz进行了封装,提供python程序调用接口。网上有很多对graphiviz进行python封装的程序如pydot等等,个人觉得pygraphviz比较好用,有好的文档和示例程序。https://networkx.lanl.gov/trac/browser/pygraphviz/
在ubuntu下面安装 graphviz
sudo apt-get install graphviz, graphviz-dev
注意graphiviz-dev是pygraphviz所依赖的必须安装。
安装pygraphviz
注意不要sudo apt-get了,因为这样安装的不是最新版本,程序运行会有问题。
到这个地址下载最新的pygraphviz-0.99.1.tar.gz (md5)
http://pypi.python.org/pypi/pygraphviz/
解压缩,然后 sudo python2.6 setup.py install即可。
下面给个例子,如何利用graphiviz 的布局绘制下面的图形呢:
2 //dot s.dot -Tpng -o s.png -Gsplines=line
3 digraph G {
4 //a -> c;
5 a -> b;
6 b -> c;
7 subgraph x{
8 rank=same;
9 b->d;
10 }
11 subgraph y{
12 //rank = same;
13 d->e;
14 }
15 subgraph z{
16 rank=same;
17 c->e;
18 }
19
20 }
21
这里解释下,默认的图布局是自上到下的,TD,当然你可以改成自左向右布局,
digraph G {
rankdir=LR;
.....
}
但是一个时刻只能有一种布局方式,例如上图是采用从上到下的布局方式,为了使得边b->d能够水平,需要采用
subgraph 的方法添加子图,同时说明rank=same.
dot s.dot -Tpng -o s.png -Gsplines=line 中-Gsplines=line 表示强迫边是直线.http://www.graphviz.org/mywiki/FaqBalanceTree
2 a -> b0
3 xb [label="",width=.1,style=invis]
4 a -> xb [style=invis]
5 a -> b1
6 {rank=same b0 -> xb -> b1 [style=invis]}
7 b0 -> c0
8 xc [label="",width=.1,style=invis]
9 b0 -> xc [style=invis]
10 b0 -> c1
11 {rank=same c0 -> xc -> c1 [style=invis]}
12 }
下面给出利用pygrahviz进行二叉树的绘制
首先给出最简单的绘制,然后是按照上面提到的利用invis属性,构造不可见的顶点和边强迫产生较合适的位置。
a
|
b0—t--b1 原理如昨图所示,对照上面的图示a到b0,a到b1是实边,t为不可见点,a到t,b0到t,t到b1都是不可见边,
这样强迫布局的时候对于横坐标,a尽量在b0,b1的中间。
1.不采用不可见点,边的二叉树绘制效果
1 #printTreeOld.py
3
4 A=pgv.AGraph(directed=True,strict=True)
5 A.add_edge(1,2)
6 A.add_edge(1,3)
7 A.add_edge(2,4)
8 A.add_edge(2,5)
9 A.add_edge(5,6)
10 A.add_edge(5,7)
11 A.add_edge(3,8)
12 A.add_edge(3,9)
13 A.add_edge(8,10)
14 A.add_edge(8,11)
15 A.graph_attr['epsilon']='0.001'
16 print A.string() # print dot file to standard output
17 A.write('fooOld.dot')
18 A.layout('dot') # layout with dot
19 A.draw('fooOld.png') # write to file
2.采用不可见点,边,绘制二叉树的效果,感觉稍微好一点,更像二叉树了:)
下面的代码仅仅是示例,可以提出子函数简化代码。
2 # strict (no parallel edges)
3 # digraph
4 # with attribute rankdir set to 'LR'
5 A=pgv.AGraph(directed=True,strict=True)
6 A.add_edge(1,2)
7 A.add_edge(1,3)
8 A.add_node('a',style='invis')
9 A.add_edge(1,'a',style='invis')
10 B=A.add_subgraph([2,3,'a'],rank='same')
11 B.add_edge(2,'a',style='invis')
12 B.add_edge('a',3,style='invis')
13
14 A.add_edge(2,4)
15 A.add_edge(2,5)
16 A.add_node('b',style='invis')
17 A.add_edge(2,'b',style='invis')
18 C=A.add_subgraph([4,5,'b'],rank='same')
19 C.add_edge(4,'b',style='invis')
20 C.add_edge('b',5,style='invis')
21
22 A.add_edge(5,6)
23 A.add_edge(5,7)
24 A.add_node('c',style='invis')
25 A.add_edge(5,'c',style='invis')
26 D=A.add_subgraph([6,7,'c'],rank='same')
27 D.add_edge(6,'c',style='invis')
28 D.add_edge('c',7,style='invis')
29
30 A.add_edge(3,8)
31 A.add_edge(3,9)
32 A.add_node('d',style='invis')
33 A.add_edge(3,'d',style='invis')
34 E=A.add_subgraph([8,9,'d'],rank='same')
35 E.add_edge(8,'d',style='invis')
36 E.add_edge('d',9,style='invis')
37
38 A.add_edge(8,10)
39 A.add_edge(8,11)
40 A.add_node('e',style='invis')
41 A.add_edge(8,'e',style='invis')
42 F=A.add_subgraph([10,11,'e'],rank='same')
43 F.add_edge(10,'e',style='invis')
44 F.add_edge('e',11,style='invis')
45
46
47 A.graph_attr['epsilon']='0.001'
48 print A.string() # print dot file to standard output
49 A.write('foo.dot')
50 A.layout('dot') # layout with dot
51 A.draw('foo.png') # write to file
52