mac下的Graphviz安装及使用
一.安装
Graphviz http://www.graphviz.org/
mac用户建议直接用homebrew来安装,官网上版本比较旧
1.安装homebrew
打开终端复制、粘贴以下命令:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
- 1
2.安装Graphviz
homebrew安装完毕后运行 brew install graphviz即可
注:运行第2步时可能会提示-bash: brew: command not found
解决办法:
终端输入sudo vim .bash_profile
,
输入i
进入输入模式,
添加export PATH="/usr/local/bin:$PATH"
,
按esc键退出输入模式,
输入:wq
退出并保存
最后输入source .bash_profile
使配置生效。
(注意:
和空格也要输入,bash_profile保存时可能会警告,:w!
强制保存即可,更多vim命令参考http://www.cnblogs.com/usergaojie/p/4583796.html)
二.使用
随便找的一个例子:
1.使用文本编辑器(这里用的是sublime )输入以下内容:
digraph pic {
Hello -> World
}
- 1
- 2
- 3
2.保存为pic.dot文件
3.打开终端,切换到dot文件所在目录,输入dot pic.dot -T png -o pic.png
4.可以看到在dot文件目录下生成了一个pic.png文件
三.进阶
目的:流程图较复杂时,能够边写代码边看效果
目前找了两个教程,还没试,有问题了再更新。
https://blog.zengrong.net/post/2294.html
https://zhuanlan.zhihu.com/p/22820399
通过Anaconda安装Graphviz
简单三步走
1.打开Anaconda终端,Open terminal
2.在终端窗口一次输入:
conda install graphviz
pip install graphviz
3.添加环境变量
找到Graphviz的安装路径,然后添加到环境变量中即可。我的安装路径是 C:\Users\linxid\Anaconda3\Library\bin\graphviz
安装后记得重启,环境变量修改才可以生效,调用库,即可成功。
通过Graphviz绘制的决策树:
2.创建桌面快捷方式:
安装目录\bin文件夹\:找到gvedit.exe文件右键 发送到桌面快捷方式,如下图:
3.配置环境变量:
dot -version
,然后按回车,如果显示graphviz的相关版本信息,则安装配置成功。如图:6.在pycharm中运行
# coding:utf-8
from graphviz import Digraph
dot = Digraph(comment='The Round Table')
# 添加圆点 A, A的标签是 King Arthur
dot.node('A', 'king')
dot.view() #后面这句就注释了,也可以使用这个命令查看效果
# 添加圆点 B, B的标签是 Sir Bedevere the Wise
dot.node('B', 'Sir Bedevere the Wise')
#dot.view()
# 添加圆点 L, L的标签是 Sir Lancelot the Brave
dot.node('L', 'Sir Lancelot the Brave')
#dot.view()
#创建一堆边,即连接AB的边,连接AL的边。
dot.edges(['AB', 'AL'])
#dot.view()
# 在创建两圆点之间创建一条边
dot.edge('B', 'L', constraint='false')
#dot.view()
# 获取DOT source源码的字符串形式
print(dot.source)
# 保存source到文件,并提供Graphviz引擎
dot.render('test-output/round-table.gv', view=True)
# coding:utf-8
from graphviz import Digraph
dot = Digraph(comment='The Round Table')
# 添加圆点 A, A的标签是 King Arthur
dot.node('A', 'king')
dot.view() #后面这句就注释了,也可以使用这个命令查看效果
# 添加圆点 B, B的标签是 Sir Bedevere the Wise
dot.node('B', 'Sir Bedevere the Wise')
#dot.view()
# 添加圆点 L, L的标签是 Sir Lancelot the Brave
dot.node('L', 'Sir Lancelot the Brave')
#dot.view()
#创建一堆边,即连接AB的边,连接AL的边。
dot.edges(['AB', 'AL'])
#dot.view()
# 在创建两圆点之间创建一条边
dot.edge('B', 'L', constraint='false')
#dot.view()
# 获取DOT source源码的字符串形式
print(dot.source)
# 保存source到文件,并提供Graphviz引擎
dot.render('test-output/round-table.gv', view=True)
- 在安装目录找到如下文件用记事本打开:
- 将对应位置代码修改为如下:
- 代码中加如下语句:
- dot input.dot -T png -o output.txt
cmd:
- 有向图:diagraph申明,结点关系为"->",可以//注释
- 无向图:graph 申明 结点关系"--"
- 子图 :subgraph声明 父图是无向图他本身也得是无向图 父图是有向图本身也得是有向图
digraph G{
{ a b c} -> { d e f }
}
digraph G{
{ a b c} -> { d e f }
}
简述
原文: http://www.tuicool.com/articles/vy2Ajyu
本文翻译自 Drawing Graphs using Dot and Graphviz
1. 许可
Copyright (C) 2013, 2014 Tony Ballantyne. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
Code in this document is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
2. 介绍
2.1 什么是DOT?
DOT是纯文本图像描述语言,对于计算机和人来说,都很容易阅读。
2.2 什么是Graphviz?
Graphviz是一个开源的图像可视化的软件,所谓图像可视化就是使用一种简单的方法,来将结构化的信息表现成用抽象图片和网络构成的示意图。
2.3 谁适合看这篇文章?
这篇文章本来是我写来给自己当速成手册看的。不过现在看起来已经被我弄成给学计算机的学生看的教程了。现在这篇文章可以给任何想通过例子学习DOT的人看。
2.4 相关材料
我博客还有类似的其他文章 TonyBallantyne.com/tech
如果你是想了解关于我作为一名SF and Fantasy writer的工作,但不幸点到这篇文章的话,下面的链接可能就对你比较有用:
- TonyBallantyne.com : 这里有我的小说和短故事
- Emacs Tutorial : 给作家的一个关于Emacs的简短介绍
- My Emacs Writing Setup : 关于我如何使用Emacs的Org Mode来写小说和短故事
译注:这儿所谓的相关材料其实是作者自己其他的一些文章,跟DOT关系不大
3. 安装
如果你要顺着这个教程继续下去,那你可能就需要要装Graphviz套件了。Graphviz可以在 官网 免费下载。
4. 基础例子
4.1 简单图例
graph graphname { a -- b; b -- c; b -- d; d -- a; }
4.2 一样的图,不一样的布局
graph graphname { rankdir=LR; //Rank Direction Left to Right a -- b; b -- c; b -- d; d -- a; }
4.3 简单有向图
digraph graphname{ a -> b; b -> c; a -> c; }
4.4 带标签的简单有向图
digraph graphname{ T [label="Teacher"] // node T P [label="Pupil"] // node P T->P [label="Instructions", fontcolor=darkgreen] // edge T->P }
4.5 同样的图,不同的形状和颜色
digraph graphname { T [label="Teacher" color=Blue, fontcolor=Red, fontsize=24, shape=box] // node T P [label="Pupil" color=Blue, fontcolor=Red, fontsize=24, shape=box] // node P T->P [label="Instructions", fontcolor=darkgreen] // edge T->P }
这儿你可以选择的形状有: box
, polygon
, ellipse
, oval
, circle
, point
, egg
, triangle
, plaintext
, diamond
, trapezium
, parallelogram
, house
, pentagon
, hexagon
, septagon
, octagon
, doublecircle
, doubleoctagon
, tripleoctagon
更多的形状看 这里
4.6 总结
digraph summary{ start [label="Start with a Node"] next [label="Choose your shape", shape=box] warning [label="Don't go overboard", color=Blue, fontcolor=Red,fontsize=24,style=filled, fillcolor=green,shape=octagon] end [label="Draw your graph!", shape=box, style=filled, fillcolor=yellow] start->next start->warning next->end [label="Getting Better...", fontcolor=darkblue] }
5. 高级
5.1 节省时间的技巧
单独地去定义每一个节点其实很浪费时间的,下面这个技巧能够让你快点儿。
digraph hierarchy { nodesep=1.0 // increases the separation between nodes node [color=Red,fontname=Courier,shape=box] //All nodes will this shape and colour edge [color=Blue, style=dashed] //All the lines look like this Headteacher->{Deputy1 Deputy2 BusinessManager} Deputy1->{Teacher1 Teacher2} BusinessManager->ITManager {rank=same;ITManager Teacher1 Teacher2} // Put them on the same level }
5.2 记录
你现在可以用HTML来定义这一类节点了, 这里 有更多相关信息。
digraph structs { node[shape=record] struct1 [label="<f0> left|<f1> mid\ dle|<f2> right"]; struct2 [label="{<f0> one|<f1> two\n\n\n}" shape=Mrecord]; struct3 [label="hello\nworld |{ b |{c|<here> d|e}| f}| g | h"]; struct1:f1 -> struct2:f0; struct1:f0 -> struct3:f1; }
6. 例子
6.1 有限状态机
digraph finite_state_machine { rankdir=LR; size="8,5" node [shape = circle]; S0 -> S1 [ label = "Lift Nozzle" ] S1 -> S0 [ label = "Replace Nozzle" ] S1 -> S2 [ label = "Authorize Pump" ] S2 -> S0 [ label = "Replace Nozzle" ] S2 -> S3 [ label = "Pull Trigger" ] S3 -> S2 [ label = "Release Trigger" ] }
6.2 数据流示意图
digraph dfd{ node[shape=record] store1 [label="<f0> left|<f1> Some data store"]; proc1 [label="{<f0> 1.0|<f1> Some process here\n\n\n}" shape=Mrecord]; enti1 [label="Customer" shape=box]; store1:f1 -> proc1:f0; enti1-> proc1:f0; }
6.3 数据流示意图2
digraph dfd2{ node[shape=record] subgraph level0{ enti1 [label="Customer" shape=box]; enti2 [label="Manager" shape=box]; } subgraph cluster_level1{ label ="Level 1"; proc1 [label="{<f0> 1.0|<f1> One process here\n\n\n}" shape=Mrecord]; proc2 [label="{<f0> 2.0|<f1> Other process here\n\n\n}" shape=Mrecord]; store1 [label="<f0> |<f1> Data store one"]; store2 [label="<f0> |<f1> Data store two"]; {rank=same; store1, store2} } enti1 -> proc1 enti2 -> proc2 store1 -> proc1 store2 -> proc2 proc1 -> store2 store2 -> proc1 }
6.4 对象继承
digraph obj{ node[shape=record]; rankdir="BT"; teacher [label = "{<f0> Teacher|<f1> \n |<f2> \n }"]; course [label = "{<f0> Course|<f1> \n |<f2> \n }"]; student [label = "{<f0> Student|<f1> \n |<f2> \n }"]; lesson [label = "{<f0> Lesson |<f1> \n |<f2> \n }"]; tutorial [label = "{<f0> Tutorial|<f1> \n |<f2> \n }"]; assessment[label = "{<f0> Assessment|<f1> \n |<f2> \n }"]; coursework [label = "{<f0> Coursework|<f1> \n |<f2> \n }"]; exam [label = "{<f0> Exam|<f1> \n |<f2> \n }"]; {rank=same; teacher course student} teacher->course [dir="forward",arrowhead="none",arrowtail="normal",headlabel="1",taillabel="1.."]; student->course [dir="forward",arrowhead="none",arrowtail="normal",headlabel="1",taillabel="1.."]; lesson->course [dir="forward",arrowhead="diamond",arrowtail="normal"]; tutorial->course [dir="forward",arrowhead="diamond",arrowtail="normal"]; assessment->course [dir="forward",arrowhead="diamond",arrowtail="normal"]; coursework->assessment; exam->assessment; }
6.5 关系型实体
digraph ER{ node[shape=box]; Book; Customer; Loan; {rank=same;Book,Customer,Loan} Book->Loan[dir="forward",arrowhead="crow",arrowtail="normal"]; Customer->Loan[dir="forward",arrowhead="crow",arrowtail="normal"]; }
7. 参考
以下可能是你在画图时候最有用的一些属性,完整的列表可以在 这里 看。
7.1 图像属性
label="My Graph"; # 给图像设置标签 rankdir=LR; # 将图片由原来的从上到下布局变成从左到右布局 {rank=same; a, b, c } # 将一组元素放到同一个level splines="line"; # 让边框变为直线,没有曲线和锐角 K=0.6; # 用来在布局中影响spring属性,spring属性可以用于将节点往外推,这个在twopi和sfdp布局中很有用。
译注:暂时还没明白这个spring属性应该怎么翻,初步猜测是弹性。胡克定律里面的常量名也叫K。
7.2 交点属性
[label="Some Label"] # 给交点打标签 [color="red"] # 给交点上色 [fillcolor="blue"] # 设置交点的填充色
7.3 边的属性
[label="Some Label"] # 给边设置标签 (设置路径权重的时候很有用) [color="red"] # 给交点上色 (标示路径的时候很有用) [penwidth=2.0] # 给边适配厚度,标示路径的时候很有用。
7.4 尺寸, 背景颜色
fixedsize=true; size="1,1"; resolution=72; bgcolor="#C6CFD532"; # 不是我偷懒不翻译哦,原文就没有解释。
8. 附录
8.1 拓展阅读
An Introduction to GraphViz and dot
Graphviz Examples and Tutorial
8.2 使用Emacs的Org Mode
Emacs的Org Mode不管对于写作,还是执行和导出DOT图片都是个很理想的工作环境。
8.2.1 配置
下载并安装Graphviz,然后把相关路径加到exec-path这个变量里去。
你也要把你的.emacs文件更新成能够把DOT作为babel语言加载,下面这个配置可以很容易的设置DOT为babel语言,其他语言也可以类似操作
(org-babel-do-load-languages (quote org-babel-load-languages) (quote ( (emacs-lisp . t) (java . t) (dot . t) (ditaa . t) (R . t) (python . t) (ruby . t) (gnuplot . t) (clojure . t) (sh . t) (ledger . t) (org . t) (plantuml . t) (latex . t) ) ) )
8.2.2 将Dot嵌入Emacs
Org Mode通过使用Library of Babel来解析各种语言。要想这么做的话,就用 begin_src
和 end_src
标签把你的dot代码想下面这样包含进去。你也需要在包裹的时候像下面那样添加一些命令行参数。
用 <s[TAB]
快捷键可以快速生成一个 begin_src
代码块。
#+begin_src dot :file ./img/example1.png :cmdline -Kdot -Tpng graph graphname { a -- b; b -- c; b -- d; d -- a; } #+end_src
8.2.3 命令行相关
#+begin_ src dot :file ./img/example1.png :cmdline -Kdot -Tpng
里的 :cmdline -Kdot -Tpng
就是命令行参数. 他们告诉dot如何渲染和展示。
-
-Kdot
使用dot
布局方式. 你也可以尝试其他的布局方式,比如Kneato
,Kcirco
,Ktwopi
,Kfdp
,Ksfdp
-
-Tpng
渲染成png格式
完整的命令行参数可以看 这里
Date: <2013-10-21 Mon>
Author: Tony Ballantyne
Translator: Casa Taloyum
Created: 2014-04-12 Sat 10:13
Emacs 23.3.1 (Org mode 8.0.2)
Graphviz典型例子
例子1
//先来看一个例子,我们创建一个文档graph1.dot:
//digraph是有向图,graph是无向图,要注意,->用在有向图中,--用在无向图中表示一条边,不能混用。
//第一行给出了图的类型和名字
digraph graph1{
main -> parse -> execute;
main -> init;
main -> cleanup;
execute -> make_string;
execute -> printf;
init -> make_string;
main -> printf;
execute -> compare;
}
效果:
例子2
/*
来看下一个稍微复杂点的例子,我们开始手动的设置一下图的属性。可以给点设置属性,
也可以给边设置属性。先来讲讲怎么设置边的属性,在每条边后面的双括号里设置边的属性。
也可以在用edge设置边的默认值。
而给点设置属性就必须给每个点单独的设置一个属性,node表示点的默认值。
*/
//点的默认参数是shape=ellipse, width=.75, height=.5 and labeled by the node name.
//一些点的形状在appendix.h中,一些常用的形状有bos,circle,record,plaintext。
digraph graph2{
size = "4,4"; //把图的尺寸设为4 inch,4 inch
main[shape=box]; //把main点的形状设为方形
main -> parse [weight=8]; //weight是设置了这条边的重要程度,默认是1
parse -> execute;
main -> init [style=dotted] //让这条线是点状的
main -> cleanup;
execute -> {make_string;printf} //这条语句一次连接了两条条线
init -> make_string;
//把边的默认颜色设为了red
edge[color=red];
//label就是在边上写了一行字
main -> printf[style=bold,label="100 times"];
//让make_string变成了一个两行的字符串(注意那个\n)。
make_string [label="make a\nstring"];
//设置了一下点的默认参数,蓝色,这个被用在了compare中。
node [shape=box,style=filled,color=".7 .3 1.0"];
execute -> compare;
}
效果:
例子3
//可以设置每条边箭头的方向,
//用dir,有forward(default),back,both,none四种。
digraph graph3{
A -> B[dir=both];
B -> C[dir=none];
C -> D[dir=back];
D -> A;
}
效果:
例子4
/*
点的shape除了record和Mrecord这两种之外,其他的形状都是多边形,
而我们可以对多边形进行一下属性上的设置,shape = polygon。
Sides用于设置它的边数,peripheries用于设置多边形的外框的层数,
regular = true可以让你的多边形是一个规则的多边形,
orientation = *,可以让你的多边形旋转一个角度,
如orientation = 15就是转了15度。
Skew后面跟一个(-1.0~1.0)的小数,能让你的图形斜切一个角度,
distortion是让你的图形产生透视效果。
*/
digraph graph4{
a -> b -> c;
b -> d;
a[shape=polygon,sides=5,peripheries=3.color=lightblue,style=filled];
c[shape=polygon,sides=4,skew=.4,label="hello world"];
d[shape=invtriangle];
e[shape=polygon,sides=4,distortion=.7];
}
效果:
例子5
//record和Mrecord的区别就是Mrecord的角是圆的。Record就是由矩形组成的图形。
digraph structs {
node [shape=record];
struct1 [shape=record,label="<f0> left | <f1> middle | <f2> right"];
struct2 [shape=record,label="<f0> one | <f1> two"];
struct3 [shape=record,label="hello\nworld |{ b |{ c | <here> d | e }| f }| g | h"];
struct1 -> struct2;
struct1 -> struct3;
}
效果:
例子6
/*
当你的线和线label比较多时,可以给线的属性decorate = true,
使得每条线的label与所属线之间连线。你还可以给每条线加上headlabel和taillabel,
给每条线的起始点和终点加上label,他们的颜色由labelfontcolor来决定,
而label的颜色由fontcolor来决定。
*/
graph graph6{
label = "I love you"; //给这幅图设置,名字
labelloc = b; //图名字的位置在bottom,也可以是t
labeljust = l; //图名字的对齐方式在left,也可以是r
edge[decorate = true];
C -- D[label = "s1"];
C -- E[label = "s2"];
C -- F[label = "s3"];
D -- E[label = "s4"];
D -- F[label = "s5"];
edge[decorate = false, labelfontcolor = blue, fontcolor = red];
C1 -- D1[headlabel = "c1", taillabel = "d1", label = "c1 - d1"];
}
效果:
例子7
digraph hierarchy {
graph [fontname="Microsoft Yahei"];
nodesep=1.0 // increases the separation between nodes
bgcolor="#EEE8D5"
//All nodes will this shape and colour
node [color="#FB9400",fontname="Microsoft Yahei",shape=box]
edge [color="#414141", style=filled] //All the lines look like this
rankdir = TB;
n元线性方程组 -> {n维向量空间 矩阵}
双线性函数 -> 一般线性空间[dir=back]
一般线性空间 -> 线性映射[dir=foreward]
{rank=same;双线性函数;一般线性空间;线性映射;}
n维向量空间 -> 一般线性空间
矩阵 -> 线性映射[dir=both]
}
效果:
例子8
digraph html {
abc [shape=none, margin=0, label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR><TD>0</TD><TD>1</TD><TD>2</TD><TD>3</TD><TD>4</TD>
</TR>
<TR><TD>1</TD><TD></TD><TD></TD><TD></TD><TD></TD>
</TR>
<TR><TD>2</TD><TD></TD><TD></TD><TD></TD><TD></TD>
</TR>
<TR><TD>3</TD><TD></TD><TD></TD><TD></TD><TD></TD>
</TR>
<TR><TD>4</TD><TD></TD><TD></TD><TD></TD><TD></TD>
</TR> </TABLE>>];
}
效果:
例子9
/*
默认时图中的线都是从上到下的,我们可以将其改为从左到右,
在文件的最上层打入rankdir=LR就是从左到右,默认是TB(top -> bottom),也可以是RL,BT。
//当图中时间表之类的东西时,我们会需要点能排在一行(列),
这时要用到rank,用花括号把rank=same,然后把需要并排的点一次输入。
*/
digraph html {
rankdir = LR;
{
node[shape = plaintext];
1995 -> 1996 -> 1997 -> 1998 -> 1999 -> 2000 -> 2001;
}
{
node[shape = box, style = filled];
WAR3 -> Xhero -> Footman -> DOTA;
WAR3 -> Battleship; }
{rank = same; 1996; WAR3;}
{rank = same; 1998; Xhero; Battleship;}
{rank = same; 1999; Footman;}
{rank = same; 2001; DOTA;}
}
效果:
/*
设立一条边时,我们可以制定这条边从起点的那个位置射出和从哪个位置结束。
控制符有"n", "ne","e", "se", "s", "sw", "w" 和 "nw",具体效果见下:
*/
digraph html {
node[shape = box];
c:n -> d[label = n];
c1:ne -> d1[label = ne];
c2:e -> d2[label = e];
b:se -> a[label = se];
c3:s -> d3[label = s];
c4:sw -> d4[label = sw];
c5:w -> d5[label = w];
c6:nw -> d6[label = nw];
}
效果:
参考
Node, Edge and Graph Attributes
使用Graphviz绘图(一)
前言
日常开发或者编写课程论文时,除了代码文档的编写,其中一个很重要的部分就是需要绘制流程图、示意图
绘制流程图有很多工具,一般常见的就有如下几种:
- Word、PPT等办公软件
- Viso以及开源的Dia
- 画图(MSPaint)、PS、AI
- PicPicke
- 在线流程图绘制(eg. www.processon.com)
对于这些软件无论功能强大与否,适合与否,方便与否,都具有一个特点——所见即所得。你制作过程中看到的就是最终得到的结果。图中形式、布局在制作过程中都由自己设置,其实还有一类绘图系统的存在,其思想是——所思即所得。其中具有代表性的软件就是——Graphviz。Graphviz是贝尔实验室开发的一个开源的工具包,它使用一个特定的DSL(领域特定语言)——Dot作为脚本语言,然后使用布局引擎解析脚本并完成自动布局。Graphviz的设计初衷是对图进行自动布局(有向图、无向图、),可以使用dot脚本来定义图形元素,选择一定的算法进行布局,通过对输入脚本的解析,分析出其中的点,边以及子图,然后根据属性进行绘制,继而将结果以自己需要的格式导出来。
相对于其他的绘图软件,Granphviz的特点有如下几个方面:
- 代码控制,所思即所得
- 布局引擎自动布局
- (导出格式非常丰富)
如下即为Graphivz官网上的一些示例效果:
一个生成有向图的小例子
我们先来看一个小例子来看一下使用Graphviz绘制一张图的完整流程(我使用的是Ubuntu 14.04 LTS,在其它系统上的使用应该差不多,下面不再标注了)。
要使用Graphviz,先要在系统上安装Graphviz。在Ubuntu上可以使用命令sudo apt-get install graphviz
进行安装,在其他系统安装的方法可以查看Graphviz官网进行查看。程序安装好之后我们就可已使用了。
Step 1:首先,需要编辑dot脚本
可以使用你熟悉的纯文本编辑器进行脚本编写(必须是纯文本编辑器,如vim、notepad++,像word这样的富文本编辑器是不行的),只需设置编码为UTF-8。
编辑下面的脚本代码,保存为test.dot
(先不用管其具体的意思,直接复制就行了):
digraph G{
main -> parse -> execute;
main -> init;
main -> cleanup;
execute -> make_string;
execute -> printf;
init -> make_string;
main -> printf;
execute -> compare;
}
Step 2:随后,选用布局生成结果
使用如下命令生成结果:dot -Tpng sample.dot -o sample.png
对于这条命令,dot
表示用dot布局,-Tpng
表示生成png图片格式,sample.dot
是脚本文件名,-o sample.png
表示生成输出的图片名称。
改命令也可以写成dot -Kdot -Tpng sample.dot -o sample.png
,其中-Kdot
表示使用dot布局。
Graphviz支持几种布局引擎:
- dot : 默认布局方式,主要用于有向图
- neato : 主要用于无向图
- twopi : 主要用于径向布局
- circo : 圆环布局
- fdp : 主要用于无向图
- sfdp : 主要绘制较大的无向图
- patchwork : 主要用于树哈希图(tree map)
Graphviz支持的输出图片格式更是相当的多,常用的有以下几种:
- pdf :
- gif
- png :
- jpeg : 一种有损压缩图片格式
- bmp : 一种位图格式
- svg : 矢量图,一般用与Web,,可以用浏览器打开
- ps : 矢量线图,多用于打印
更多的输出格式可以浏览Graphviz输出格式进行查看。
Step 3:查看生成结果
输出的图片,可以用支持相应图片格式的软件打开。Graphviz软件安装好之后,有一个图片浏览器可以进行图片预览,只需输入命令display sample.png
即可(sample.png为生成的图片文件名),该示例预览结果如下(你可以在上一步使用不同的布局方式,查看一下结果有什么不同):
正确完成三个步骤得到结果说明Graphviz已经可以在你的系统中正确安装可以使用了。后续我会介绍Graphviz Dot脚本的具体编写方法。
graphviz 安装和入门
画流程图装逼神器:graphviz,不解释 ———————————如下言归正传,切入正题———————————– 1、下载http://www.graphviz.org/Download_windows.php 2、配置环境变量将 D:\Program Files\graphviz\release\bin 添加到环境变量 Path 中。 3、验证进入windows命令行界面,输入dot -version,然后按回车,如果显示graphviz的相关版本信息,则安装配置成功。
4、基本绘图入门运行 D:\Program Files\graphviz\release\bin 目录下的 gvedit.exe 可以运行打开图形界面。 小试牛刀:
效果:
效果(这个不错,可以当以后的模板用 ^_^): 示例1:graph 使用 – 描述关系
效果: 示例2:digraph 使用 -> 描述关系
效果: 示例3:
效果: 示例4:
效果: 这张图有些新东西可以看。
您甚至可以用以下程式码画出下面这个图:
除了直接使用工具查看和生成结果外,还可以使用命令来操作:
Graphviz 中的 cmd 有好多种,每种使用方法都完全相同,差别只在于渲染出来的图片效果不一样。 PS:Setting(快捷键Shift + F5) 里面我们可以设置生成的文件格式,例如可以生成 svg、pdf 等等格式,很强大。你可以参考工具里面可以选择的值带入到命令行执行。 关于中文乱码问题的解决方法: 先将源文件保存为UTF-8格式,然后对中文内容设置 frontname,例如:
fontname后面也可以直接指定 xxx.ttf 字体文件 参考资料: |
windows下Graphviz安装及入门教程
- 下载安装配置环境变量
- intall
- 配置环境变量
- 验证
- 基本绘图入门
- graph
- digraph
- 一个复杂的例子
- 和python交互
发现好的工具,如同发现新大陆。有时,我们会好奇,论文中、各种专业的书中那么形象的插图是如何做出来的,无一例外不是对绘图工具的熟练使用。
下载安装、配置环境变量
intall
windows版本下载地址:http://www.graphviz.org/download/
双击msi
文件,然后一直next(记住安装路径,后面配置环境变量会用到路径信息),安装完成之后,会在windows开始菜单创建快捷信息,默认快捷方式不放在桌面。
配置环境变量
将graphviz安装目录下的bin文件夹添加到Path环境变量中:
验证
进入windows命令行界面,输入dot -version
,然后按回车,如果显示graphviz的相关版本信息,则安装配置成功。
基本绘图入门
打开windows下的graphviz编辑器gvedit,编写如下的dot脚本语言,保存成gv格式文本文件。然后进入命令行界面,使用dot命令,将gv文件转化为png图形文件。
dot D:\test\1.gv -Tpng -o image.png
- 1
graph
graph使用--
描述关系
graph pic1 {
a -- b
a -- b
b -- a [color=blue]
}
digraph
使用->
描述关系
digraph pic2 {
a -> b
a -> b
b -> a [style=filled color=blue]
}
一个复杂的例子
digraph startgame {
label="游戏资源更新流程"
rankdir="TB"
start[label="启动游戏" shape=circle style=filled]
ifwifi[label="网络环境判断是否 WIFI" shape=diamond]
needupdate[label="是否有资源需要更新" shape=diamond]
startslientdl[label="静默下载" shape=box]
enterhall[label="进入游戏大厅" shape=box]
enterroom[label="进入房间" shape=box]
resourceuptodate[label="资源不完整" shape=diamond]
startplay[label="正常游戏" shape=circle fillcolor=blue]
warning[label="提醒玩家是否更新" shape=diamond]
startdl[label="进入下载界面" shape=box]
//{rank=same; needupdate, enterhall}
{shape=diamond; ifwifi, needupdate}
start -> ifwifi
ifwifi->needupdate[label="是"]
ifwifi->enterhall[label="否"]
needupdate->startslientdl[label="是"]
startslientdl->enterhall
needupdate->enterhall[label="否"]
enterhall -> enterroom
enterroom -> resourceuptodate
resourceuptodate -> warning[label="是"]
resourceuptodate -> startplay[label="否"]
warning -> startdl[label="确认下载"]
warning -> enterhall[label="取消下载"]
startdl -> enterhall[label="取消下载"]
startdl -> startplay[label="下载完成"]
}
和python交互
graphviz强大而便捷的关系图/流程图绘制方法,很容易让我们联想到机器学习中的Decision Tree
的展示方式。幸运的是,scikit-learn提供了生成.dot
文件的接口,具体操作如下:
在python编辑环境下:
from sklearn.tree import export_graphviz # 导入的是一个函数
# tree表示已经训练好的模型,即已经调用过DecisionTreeClassifier实例的fit(X_train, y_train)方法
export_graphviz(tree, out_file='tree.dot',
feature_names=['petal length', 'petal width'])
进入windows命令行界面,cd 切换到tree.dot
所在的路径,执行
dot -Tpng tree.dot -o tree.png
学习Graphviz绘图
一、关于Graphviz
1.1 简介
Graphviz (英文:Graph Visualization Software的缩写)是一个由
AT&T实验室
启动的开源工具包,用于绘制DOT语言
脚本描述的图形。它也提供了供其它软件使用的库。Graphviz是一个*软件
,其授权为Eclipse Public License
。其Mac版本曾经获得2004年的苹果设计奖
[2]。Graphviz由一种被称为DOT语言的图形描述语言[3] 与一组可以生成和/或处理DOT文件的工具组成:
命令 | 说明 |
---|---|
dot | 一个用来将生成的图形转换成多种输出格式的命令行工具。其输出格式包括PostScript,PDF,SVG,PNG,含注解的文本等等。 |
neato | 用于sprint model的生成(在Mac OS版本中称为energy minimized)。 |
twopi | 用于放射状图形的生成 |
circo | 用于圆形图形的生成。 |
fdp | 另一个用于生成无向图的工具。 |
dotty | 一个用于可视化与修改图形的图形用户界面程序。 |
lefty | 一个可编程的(使用一种被EZ影响的语言[4])控件,它可以显示DOT图形,并允许用户用鼠标在图上执行操作。Lefty可以作为MVC模型的使用图形的GUI程序中的视图部分。 |
- 官网:
http://www.graphviz.org/
- 官方文档:
http://www.graphviz.org/Documentation.php
- 下载地址:
http://www.graphviz.org/Download..php
1.2 DOT语言
DOT语言是一种文本图形描述语言它提供了一种简单的描述图形的方法,并且可以为人类和计算机程序所理解。DOT语言文件通常是具有
.gv
或是.dot
的文件扩展名。很多程序都可以处理DOT文件。
1.3 安装
Mac下直接通过brew install graphviz
了,也可以直接从官网下载。
1.4 简单示例
Graphviz画图只需要两步。第一步创建文本文件并命令为x.dot,输入以下内容:
graph demo {
"Browser" -- {"Chrome", "Fiefox", "Safari", "..."}
}
第二步,使用命令将文本内容转换为图片。
dot demo.dot -T png -o demo.png
-T
表示输出类型,可以指定jpg、gif、svg等等,-o
指定输出文件名,不指定则输出到标准输出上。执行上面命令后不出意外则可以看到如下效果。
上面是用dot
命令来生产,也可以用Graphviz中包含的其他命令来处理dot文本,比如用下面命令渲染出来的图片排列方式则不一样。
neato demo.dot -T png -o demo.png
本文后面的示例都以dot命令来渲染。
1.5 开发工具
可以直接通过上面的这种命令生成,缺点就是看不到实时效果。有一些工具可以实时查看,我这里使用的是vscode
的PlantUML
插件。Atom
、Sublime
应该也都有自己的插件,Eclipse
上也可以安装PlantUML
。Plantuml支持dot需要将开头的@startuml
和结尾的@enduml
换成@startdot
和@enddot
,也可以在前面加个//
或者#
(#@startdot
#@enddot
),这样子dot
命令生成的时候也不需要额外注释掉该部分。
二、DOT用法
2.1 基本用法
DOT中使用图(digraph
/graph
/subgraph
)、节点(node
)和边(edge
)来描述关系图/流程图,在配合一些属性的设置完成绘图。看下面例子:
#@startdot
digraph demo {
label="示例"
bgcolor="beige"
node[color="grey"]
father[label="爸爸", shape="box"]
mother[label="妈妈", shape="box"]
brother[label="哥哥", shape="circle"]
sister[label="姐姐", shape="circle"]
node[color="#FF6347"]
strangers[label="路人"]
edge[color="#FF6347"]
father->mother[label="夫妻", dir="both"]
father->brother[label="父子"]
father->sister[label="父子"]
father->我[label="父子"]
mother->{brother,sister,我}[label="母子"]
{rank=same; father, mother}
{rank=same; brother,sister,我}
}
#@enddot
说明:
-
graph
用来描述无向图,关系使用--
来描述,digraph
用来描述有向图,关系使用->
来描述。 -
demo
为定义的图片名称,label和bgcolor为定义的图片属性。 -
father
、mother
、brother
、sister
、我
、strangers
为节点。可以把前面4个节点理解成变量定义,比如定义了一个变量father
,名字叫爸爸,用方形来渲染,后面所有调用father
都会按照方形爸爸来渲染,但这里其实和变量定义是不同的,因为这个节点即便不用也会渲染出来,比如strangers
,变量思维为加强理解。比如我
没有定义也是可以直接使用的。 - 描述节点与节点的关系理解为边。边有有向(
->
)和无向(--
)两种。比如father
和mother
之间的关系为相互的。 - 上面有两个特殊的节点,
node
和edge
,node用来定义节点的默认属性,edge用来定义边的默认属性。作用域从本次定义到下一次定义截住。特定节点/边设置的属性会覆盖默认值。 -
[]
内属性,属性可以针对图、节点、边来设置。 -
father
与子女的关系为一条条写的,mother
的关系则为直接通过大括号的方式来对应三个节点。 -
rank
定义设置节点处在同一行,辅助渲染出来的图的效果。 - 注释和C语言类似,
//
和#
注释单行,/* */
多行注释。 - DOT的写法不算严格,比如结束可以有分号,属性可以没有引号。
最后看一下生成的效果图:
该图最基本的关系用一句话就可以表达出来了
{"爸爸", "妈妈"}->{"哥哥", "我", "姐姐"}
2.2 常用属性
2.2.1 常用图属性
属性名 | 默认值 | 说明 |
---|---|---|
label | 图片标签,如上面示例
|
|
bgcolor | 背景颜色,颜色文档点此 | |
fontcolor | black | 字体颜色,定义上面示例 的颜色 |
fontname | Times-Roman | 字体 |
fontsize | 14 | 字体大小 |
rank | 子图等级限制, same,min,max,source,sink | |
rankdir | TB | 排序方向,LR(left to right) or TB(top to bottom) |
compound | false | If true, allow edges between clusters. 配合 lhead 和 ltail 使用 |
2.2.2 常用节点属性
属性名 | 默认值 | 说明 |
---|---|---|
label | node name | 节点显示内容 |
color | black | node边框颜色 |
fontcolor | black | 字体颜色 |
fillcolor | 背景色 | |
fontname | Times-Roman | 字体 |
fontsize | 14 | 字体大小 |
shape | ellipse | 形状,box、ellipse、circle、diamond、plaintext、point、triangle、invtriangle |
style | 图形样式,eg. bold、dashed、dotted、filled | |
image | 背景图片地址 |
shape示例
digraph demo {
bgcolor="floralwhite"
"box"[shape=box]
"polygon"[shape=polygon,sides=7]
"ellipse"[shape=ellipse]
"circle"[shape=circle]
"point"[shape=point]
"triangle"[shape=triangle]
"invtriangle"[shape=invtriangle]
"plaintext"[shape=plaintext]
"diamond"[shape=diamond]
}
2.2.3 常用边属性
属性名 | 默认值 | 说明 |
---|---|---|
label | 描述关系 | |
color | black | 箭头颜色 |
fontcolor | black | 关系文字颜色 |
dir | forward | 设置方向:forward,back,both,none |
arrowhead | normal | 箭头头部形状。box、crow、diamond、dot、none、normal、vee。箭头文档点此 |
arrowtail | 箭头尾部形状 | |
arrowsize | 1.0 | 箭头大小 |
style | 图形样式,eg. bold、dashed、dotted、filled | |
lhead | 当 compound 为true时,lhead用于指定边指向的cluster | |
ltail | 与ltail类似 |
arrowhead示例
digraph demo {
bgcolor="floralwhite"
rankdir=LR
"box"->"crow"[arrowhead=box]
"crow"->"curve"[arrowhead=crow]
"curve"->"diamond"[arrowhead=curve]
"diamond"->"dot"[arrowhead=diamond]
"dot"->"inv"[arrowhead=dot]
"inv"->"none"[arrowhead=inv]
"none"->"normal"[arrowhead=none]
"normal"->"tee"[arrowhead=normal]
"tee"->"vee"[arrowhead=tee]
"vee"->"box"[arrowhead=vee]
#来个高级的用法
a->b[arrowhead=lcrowortee]
}
2.3 一些示例
2.3.1 子图
一个图可以包含多个子图,以及子图也可以嵌套子图。子图的名字须为cluster*
,否则就直接当节点渲染了。
digraph demo {
bgcolor="beige"
subgraph cluster_husband {
node[color="grey"]
{"爸爸", "妈妈"} -> "我"
}
subgraph cluster_wife {
{"岳父", "岳母"} -> "老婆"
}
"我" -> "老婆"[label="夫妻", dir="both"]
{rank=same; "我", "老婆"}
}
渲染效果如下:
2.3.2 二叉树形式
digraph demo {
bgcolor="beige"
node [shape="record", height=.1]
node0[label="<f0> | <f1> G | <f2>"]
node1[label="<f0> | <f1> E | <f2>"]
node2[label="<f0> | <f1> B | <f2>"]
node0:f0 -> node1:f1
node0:f2 -> node2:f1
}
其中,用 | 隔开的串会在绘制出来的节点中展现为一条分隔符,用 <> 括起来的串称为锚点。效果如下:
记录形式的节点也可以是竖形排列的。与横向排列的记录的不同只是label的形式不同,label中内容使用 {} 包围则是竖形排列的。代码如下:
digraph demo {
bgcolor="beige"
node [shape="record"]
a [label="{a | b | c}"]
}
2.3.3 直接指向子图
边直接指向cluster,需要设置 compound 为true,并配合 lhead 或 ltail 来实现。代码如下:
digraph demo {
bgcolor="beige"
compound=true
subgraph cluster0 {
a
}
subgraph cluster1 {
b
}
a -> b [lhead=cluster1];
}
Markdown可以让使用者关注内容的书写,不太需要关注文档格式;Graphviz也是一样,让使用者更多的关注内容本身之间的关系而不用太在意展现形式,以文本的方式来绘图也方便进行版本管理。当关系数据量比较大时(比如从数据库读取数据)Graphviz的优势将更明显。
参考文档: