图形可视化软件graphviz-01

www.ahageek.com

2015.09.04

Ubuntu中软件的安装方法如下(其他系统的安装方法,自己去Google一下吧):
apt-get install graphviz graphviz-doc
先来看一个例子,将以下代码保存为world.txt
digraph world {
size="17,17";
graph [bgcolor="transparent"]
	{rank=same; S8 S24 S1 S35 S30;}
	{rank=same; T8 T24 T1 T35 T30;}
	{rank=same; 43 37 36 10 2;}
	{rank=same; 25 9 38 40 13 17 12 18;}
	{rank=same; 26 42 11 3 33 19 39 14 16;}
	{rank=same; 4 31 34 21 41 28 20;}
	{rank=same; 27 5 22 32 29 15;}
	{rank=same; 6 23;}
	{rank=same; 7;}

	S8 -> 9;
	S24 -> 25;
	S24 -> 27;
	S1 -> 2;
	S1 -> 10;
	S35 -> 43;
	S35 -> 36;
	S30 -> 31;
	S30 -> 33;
	9 -> 42;
	9 -> T1;
	25 -> T1;
	25 -> 26;
	27 -> T24;
	2 -> {3 ; 16 ; 17 ; T1 ; 18}
	10 -> { 11 ; 14 ; T1 ; 13; 12;}
	31 -> T1;
	31 -> 32;
	33 -> T30;
	33 -> 34;
	42 -> 4;
	26 -> 4;
	3 -> 4;
	16 -> 15;
	17 -> 19;
	18 -> 29;
	11 -> 4;
	14 -> 15;
	37 -> {39 ; 41 ; 38 ; 40;}
	13 -> 19;
	12 -> 29;
	43 -> 38;
	43 -> 40;
	36 -> 19;
	32 -> 23;
	34 -> 29;
	39 -> 15;
	41 -> 29;
	38 -> 4;
	40 -> 19;
	4 -> 5;
	19 -> {21 ; 20 ; 28;}
	5 -> {6 ; T35 ; 23;}
	21 -> 22;
	20 -> 15;
	28 -> 29;
	6 -> 7;
	15 -> T1;
	22 -> T35;
	22 -> 23;
	29 -> T30;
	7 -> T8;
	23 -> T24;
	23 -> T1;
}

    
好的,现在打开终端,输入命令:dot world.txt -Tpng -oworld.png,产生的图形如下:
这幅图来自官网,地址是http://www.graphviz.org/content/world,源码只是做了一点儿修改,包括改变了尺寸大小,设置为透明背景色两项.
一般情况下,编译源码生成图片的命令为:dot InputFilename -Ttype -oOutputFilename.实际上,dot是有向图的过滤器.其他的还包含:
       dot      :绘画有向图的过滤器
       neato    :绘画无向图的过滤器
       twopi    :绘画放射性布局图形的过滤器
       circo    :绘画环状布局图形的过滤器
       fdp      :绘画无向图的过滤器
       sfdp     :绘画大型无向图的过滤器
       patchwork:树形图过滤器
    
目前仅仅在学习利用dot作图,其他的目前还不甚了解,主要参考的是文末链接1中的文档dotguide.pdf, 你可以认为此系列是该文档的阅读笔记罢!.

1.基本的图形绘画

dot的运作分为四个阶段:
  1. 确保图中没有任何环,这可以通过改变图中某些边的方向实现.
  2. 将节点划分为不同的等级,从上到下,再由等级决定Y坐标.
  3. 设置X坐标
  4. 节点之间连线
节点在文件中第一次出现时创建,边在节点通过->连接时出现.下面是一个例子:
1  digraph G
2  {
3      graph[bgcolor="transparent"]
4      main -> parse -> execute;
5      main -> init;
6      main -> cleanup;
7      execute -> make_string;
8      execute -> printf
9      init -> make_string;
10      main -> printf;
11      execute -> compare;
12   }
    
将上述代码保存为graph1.gv,然后使用命令 dot -Tpng graph1.gv -o graph1.png来生成如下图形:
1.行3处的代码设置背景色为透明,这主要是为了使图片在博客的文章里看起来比较搭配.
2.行4-11处,就是绘图指令了,节点名称直接写出来,比如"main","parse"节点.节点之间的连线使用标志符号"->",代码书写的顺序建议按照节点层次,从顶层开始往下一层层进行书写.
3.这里的代码就是按照这样的规则,第一层main,第二层(在第一层中已经链接了).然后是第三层init,execute.
4.每一句用分号结尾,但是设置属性的语句可以不用分号结尾,如第三行处的代码.
通常情况下,我们需要对图,以及对图中的节点,边的属性进行一些设置.这些属性通过字符串形式的键值对在源码中进行控制.第二部分就是讲解属性的设置.

2.绘画属性

2.1节点以及线的属性

节点默认的属性为椭圆形状,宽0.75cm,高0.5cm(shape=ellipse,width=.75,height=.5)以及使用节点的名字作为节点显示的名称.
其他常见的节点形状有box,cricle,record以及plaintext.其中plaintext是指节点不使用任何外轮廓.需要说明的是,节点类型可归为两大类: 基于多边形形状的节点和基于记录类型的节点.下面会分别提到.
首先是基于多边形形状的节点,第一个示例:
1  digraph G
2  {
3      graph[bgcolor="transparent"]
4      size ="4,4";
5      main [shape=box]; /* this is a comment */
6      main -> parse [weight=8];
7      parse -> execute;
8      main -> init [style=dotted];
9      main -> cleanup;
10     execute -> { make_string; printf}
11     init -> make_string;
12     edge [color=red]; // so is this
13     main -> printf [style=bold,label="100 times"];
14     make_string [label="make a\nstring"];
15     node [shape=box,style=filled,color=".7 .3 1.0"];
16     execute -> compare;
17  }
结果如下所示:
1.行4中为图的大小属性,键为size,值为"4,4"表示图的大小为4x4cm,需要说明的是,如果图没有设置fixedsize=true(图的大小尺寸固定)属性,那么
所绘制出来的图形实际尺寸将会进行适当的放大或者缩小.
2.节点或者边的属性设置在中括号内,比如行5中设置main节点的形状为box,行6设置main到parese的线权重(weight),在dot中,线权重代表了所画连线 的长度和弯曲程度,简单来说,当一条来连线的权重越大,那么该连线将会更加趋向于直线.默认的权重值是1.其他的设置有:
3.注释符和C/C++相同,可以使用/* */ 或者 //.
第二个示例:
1  digraph G
2  {
3      graph[bgcolor="transparent"]
4      a -> b -> c;
5      b -> d;
6      a [shape=polygon,sides=5,peripheries=3,color=darkgreen,style=filled];
7      c [shape=polygon,sides=4,skew=.4,label="c-hello world"]
8      d [shape=invtriangle];
9      e [shape=polygon,sides=4,distortion=.7];
10  }
图形如下:
第三个示例:
1  digraph structs
2  {
3      graph[bgcolor="transparent"]
4      node [shape=record];
5      struct1 [shape=record,label=" left| mid\ dle| right"];
6      struct2 [shape=record,label=" one| two"];
7      struct3 [shape=record,label="hello\nworld |{ b |{c|d|e}| f}| g | h"];
8      struct1 -> struct2;
9      struct1 -> struct3;
10  }
图形如下:
该图形中的节点形状是基于记录型的.基于记录型的节点分为两类,一类是record,一类是Mrecord,除了后者是圆角之外,两个都是一样的.
记录类型的形状就是表格,将表格作为一个节点来呈现.表格的构造放在lable属性值中.

关于graphviz就先写到这里,以后有时间再写该系列第二部.然而实际上,对于简单需求,通过本文所提到的知识,基本上能够做出来.
参考:
1.http://www.graphviz.org/pdf/dotguide.pdf
2.http://www.graphviz.org/Gallery.php
3.http://www.graphviz.org/Documentation.php

By KillerLegend