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繪制的決策樹:
dot -version
,然后按回車,如果顯示graphviz的相關版本信息,則安裝配置成功。如圖:
# 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
An Introduction to GraphViz and dot
Graphviz Examples and Tutorial
使用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的優勢將更明顯。
參考文檔: