Welcome 微信登录

首页 / 操作系统 / Linux / Graphviz的使用及中文乱码问题解决

缘起
在Linux下的绘图软件,自动的,半自动的,最后遇到神器Graphviz。整个流程还算波折,起初,编译docbook的部分遇到这个软件,后来,在看Korat: Automated Testing Based on Java Predicates(2000年ACM的最佳论文),发现其软件实现Korat中使用了Graphviz的实现来绘图程序依赖图,最后,在学习Latex的时候,考虑要嵌入图片,想起这个绘图工具,就对这个著名的工具做了一些研究,其实就是Google了一下,只能算是文献调研。以下,是OpenFoundry上看到的介绍Graphviz的文章,原文为繁体字,用google translation转换为简体中文,修改一下一些术语,添加了一下内容(乱码问题)。1. 简介
Graphviz 是一个运用广泛的命令行绘图软体,不过说是绘图软体,它能绘的图并不是一般人想像中的漫画或logo,而是数学意义上的"graph",比较通俗的说法就是「关系图」。举例来说,像是下面这种图: 2. 安装
Graphviz 支援Windows、Mac OS X、FreeBSD、Solaris、Linux 等多种系统。Ubuntu或Debian下安装很简单,sudo apt-get install graphviz。Windows用户,请前往这里下载安装档:http://www.graphviz.org/Download_windows.phpMac OS X的使用者请往这边走:http://www.graphviz.org/Download_macos.php3. Graphviz的使用
# Graphviz<cmd> <inputfile> -T <format> -o <outputfile>#举例:输出pngdot input.dot -T png -o output.png#举例:一样是输出png ,只不过档名是txtdot input.dot -T png -o output.txt首先,我们看看上面的<cmd> 部份。Graphviz 的<cmd> 有好几种,每种使用方法都完全相同,差别只在于渲染出来的图片效果不一样。man中的简介是这样的:dot
 渲染的图具有明确方向性。
 
neato
 渲染的图缺乏方向性。
 
twopi
 渲染的图采用放射性布局。
 
circo
 渲染的图采用环型布局。
 
fdp
 渲染的图缺乏方向性。
 
sfdp
 渲染大型的图,图片缺乏方向性。
 可以透过man <cmd> 取得进一步说明。但还是亲自用用比较容易理解。在本文中,凡没有说明的图,预设都是以dot渲染出来的。继续往下看。在Graphviz中,若您不指定-T参数,Graphviz并不会自动猜测您想要产生什么格式,只会以预设格式渲染。可选格式相当多,包括(但不限于)jpg、png、svg等,全部列表可见官网说明页的最下方。-o 可让您指定储存档案的档名。如果您不用-o 选项指定输出档名,Graphviz 则会将结果输出到标准输出上(图片格式输出到标准输出就是乱码的二进制文件)。除非用法很特殊,否则这两个参数,每次都要输入并传递给dot。这样输入命令就是:dot -Tpng demo.dot -o demo.png为了减少打字的次数,编写简单的shell脚本dot.sh,其中涉及获取文件名和扩展,从网上搜的,工作的很好,但不太清楚实现原理:#!/bin/sh# dot.shfile=$1filename=${file%.*}extension=${file##*.}outfile=${filename}.pngdot -Tpng $file -o $outfile#show generate image fileeog $outfile &
 给脚本dot.sh加上执行权限,然后调用命令就简化为:./dot.sh demo.dot当然,如果整个命令很常用的话,可以将改作函数其写到.bashrc中。4. dot语言说明
指挥Graphviz 绘图时,所使用的语言叫作"dot"。下边就来介绍如何使用它。4.1. 有向图与无向图
使用dot 语言,第一步就是决定要画哪种图。图分两种:有向图与无向图。有向图以digraph申明图片,节点间的关系写为"->"。/*demo1。顺便一提,在dot语言中可使用C++中允许的注解。本行为C风格注解*/
digraph demo1{ //这也是注解,C++风格的。
a -> b -> c;
c -> a;
}结果图:无向图以graph 宣告图片,节点间的关系可以写为"--"。//demo2
graph demo2{
a -- b -- c;
c -- a;
}结果图:
其中demo1 与demo2 是图片的名称。4.2. 使用引号
上文中的a, b, c 除了作为程式内的识别字以外,也会成为节点的显示名称(label)。不过如果这名称中混了中文或夹了空格,Graphviz 就有可能搞错你的意思。为防不必要的误解,所以平常最好都用英文引号括住。就像下面这样://demo3
digraph {
"总攻" -> "受";
"强攻" -> "受";
"健气攻" -> "受";
}图4:混合了空白的示范这样就没问题了!子图与简化技巧来看个复杂一点的例子,这是一份地中海海域的大略连接图://demo4graph G{"黑海" -- "亚速海";"黑海" -- "博斯普鲁斯海峡""达达尼尔海峡" -- "爱琴海"subgraph cluster_T{//新东西label = "黑海海峡";//新东西"达达尼尔海峡" -- "马尔马拉海" -- "博斯普鲁斯海峡";}subgraph cluster_M{label = "地中海海域";"中部地中海" -- {"爱琴海" "爱奥尼亚海" "西西里海峡"}; //也是新东西"西部地中海" -- {"西西里海峡" "第勒尼安海" "利古里亚海" "伊比利海" "阿尔沃兰海"};"爱奥尼亚海" -- "亚得里亚海";"阿尔沃兰海" -- "直布罗陀海峡";}}结果图: 图5:地中海海域连接图,使用dot渲染。这张图有些新东西可以看。第一个是subgraph 关键字。一如名字所示,他是用来定义「次级图片」用的。次级图片在dot的官方文件中常被叫作cluster subgraph,特指图示中被方框包裹起来的那两块,其定义方式和一般的graph非常相似,不过使用上有两件事需要留意:graph的命名得以cluster前缀开头,否则语法虽然能过关,但生不出图面上您预期的效果。如果父图是无向图,他本身也得是无向图;反之如果父图是有向图,这边也得乖乖照着来。第二个重点是下面这段:1 "中部地中海" -- {"爱琴海" "爱奥尼亚海" "西西里海峡"};用大括号括起,用空格分开-这是一口气将好几个节点群组起来同时操作的方法,其等效于:1 "中部地中海" -- "爱琴海"; 2 "中部地中海" -- "爱奥尼亚海"; 3 "中部地中海" -- "西西里海峡";您甚至可以用以下程式码画出图6://demo5digraph G{//{}中的注意空格{ a b c} -> { d e f }}
图6:大括号效果示意图这语法糖很方便好吃,可以灵活运用。第三个不同处在于label=XXX 这行。这是「属性」的指定方式。关于属性,我们下章再讲。4.3. 属性
有了前面介绍过的技巧,所有图面关系都可以顺利地绘制出来。然而,通常我们画图的时候,还会对图片做一些特别的处理。好比说把字加粗、把图变色、把标签或连接线的外型改变、把某些节点水平对齐......诸如此类。要控制这些东西,就要用到属性。属性有四种:1. 用在节点上(Node, N)2. 用在线段上(Edge, E)3. 用在根图片上(Graph, G)4. 用在子图片上(Cluster subgraph, C)您可以阅读手册中的表,判断哪些属性能用在哪些地方。那么,属性要怎么用呢?4.3.1. 属性的套用
如果要设定根图片或子图片的属性,得像前面范例中所示的那样,在图片的大括号范围内指定..属性名称=值;这样就行了。对于节点(node) 的属性,有以下几种指定法:1节点名[节点属性名=值];2节点名[节点属性名=值,节点属性名=值];3 node [节点属性名=值,节点属性名=值];属性指定的语句必须要被中括号括起。当一次指定多值时,需用英文逗点隔开。第三行中的node 是个关键字,用来代称「图片范围内」所有「还没创建」的节点,或者您也可将它理解为:在当前大括号的范围内,所有尚未创建节点的属性预设值,会被这个语句给变更。线段(edge)的属性指定,与节点属性指定方式很类似:1节点名->节点名[线段属性名=值];2节点名--节点名[线段属性名=值,线段属性名=值];3 edge [线段属性名=值,线段属性名=值];其中edge 是关键字。这边顺便补充一个关于线段的观念:有些线段相关的属性,具有head值与tail值。而这边说的head 与tail,得将它想像成一个「箭头」的形状(就像是「a -> b」这样)。对于线段来说,这个箭头指向的头部才是head。这可能和直觉上不一样,因为这边说的「Head」其实是两个节点中,后面的那一个。4.3.2. 属性范例
把先前的看过的例子加上一些属性试试。//demo6graph G{"黑海" [shape = circle, color = blueviolet, fontcolor = blueviolet, fontsize = 20];"黑海" -- "亚速海" [label = "刻赤海峡"];subgraph cluster_T{label = "黑海海峡";fontsize = 24;fillcolor = darkslategray;style = filled;fontcolor = white;node [fontcolor = white, color = white];"博斯普鲁斯海峡" -- "马尔马拉海" -- "达达尼尔海峡" [color = white];"博斯普鲁斯海峡" [shape = parallelogram];"达达尼尔海峡" [shape = parallelogram];}"黑海" -- "博斯普鲁斯海峡" [color = red ,penwidth = 2];"达达尼尔海峡" -- "爱琴海" [color = red ,penwidth = 2];subgraph cluster_M{label = "地中海海域";fontsize = 24;"西部地中海" [shape = Mcircle, style = filled, color = grey, fillcolor = aquamarine, fontsize = 20];"中部地中海" [shape = Mcircle, style = filled, color = grey, fillcolor = aquamarine, fontsize = 20];"直布罗陀海峡" [shape = parallelogram, fontcolor = red];"西西里海峡" [shape = parallelogram ];"中部地中海" -- {"爱琴海" "爱奥尼亚海" "西西里海峡"};"西部地中海" -- {"西西里海峡" "第勒安海" "利古里亚海" "伊比利海" "阿尔沃兰海"};"爱奥尼亚海" -- "亚得里亚海"; 30 "阿尔沃兰海" -- "直布罗陀海峡";}}
图7:地中海海域连接图(加入属性)。更多详情见请继续阅读下一页的精彩内容: http://www.linuxidc.com/Linux/2016-05/131050p2.htm
  • 1
  • 2
  • 下一页
Graphviz - 用指令来画关系图吧!绘图工具Graphviz学习使用相关资讯      Graphviz  Graphviz中文乱码 
  • 程序员绘图利器 — Graphviz  (05月06日)
  • Graphviz - 用指令来画关系图吧!  (05月06日)
  • 看开源代码利器—用Graphviz +   (01/09/2015 08:17:33)
  • 绘图工具Graphviz学习使用  (05月06日)
  • 使用 Graphviz 生成自动化系统图  (05月06日)
  • Graphviz “yyerror()”缓冲区溢出  (01/08/2014 14:30:47)
本文评论 查看全部评论 (0)
表情: 姓名: 字数