Graphviz 适合编程快速绘制流程图之类的图形。 而pygraphviz对graphviz进行了封装,提供python程序调用接口。网上有很多对graphiviz进行python封装的程序如pydot等等,个人觉得pygraphviz比较好用,有好的文档和示例程序。https://networkx./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) 解压缩,然后 sudo python2.6 setup.py install即可。
下面给个例子,如何利用graphiviz 的布局绘制下面的图形呢:
1 //s.dot
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 { ..... } 但是一个时刻只能有一种布局方式,例如上图是采用从上到下的布局方式,为了使得边b->d能够水平,需要采用 subgraph 的方法添加子图,同时说明rank=same. dot s.dot -Tpng -o s.png -Gsplines=line 中-Gsplines=line 表示强迫边是直线.
http://www./mywiki/FaqBalanceTree 1 digraph G {
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 2 import pygraphviz as pgv
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.采用不可见点,边,绘制二叉树的效果,感觉稍微好一点,更像二叉树了:) 下面的代码仅仅是示例,可以提出子函数简化代码。
1 import pygraphviz as pgv
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 |
|