用graphviz,pygraphviz快速自动绘图
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 的布局绘制下面的图形呢:
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 {
rankdir=LR;
.....
}
但是一个时刻只能有一种布局方式,例如上图是采用从上到下的布局方式,为了使得边b->d能够水平,需要采用
subgraph 的方法添加子图,同时说明rank=same.
dot s.dot -Tpng -o s.png -Gsplines=line 中-Gsplines=line 表示强迫边是直线.
http://www.graphviz.org/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