使用Graphviz下的dot工具繪制圖像
來自: http://my.oschina.net/Tsybius2014/blog/617963
一、關于Graphviz下的dot工具
Graphviz是一個畫圖軟件,其中的dot工具可以用于繪制流程圖。dot工具可以根據dot語言代碼生成GIF、PNG、SVG、PDF、PostScript格式的圖片文件。
通過dot工具,可以繪制出如下面這樣復雜的流程圖(摘自dot工具官方幫助手冊):

dot工具畫圖通過以下四個步驟來完成:
第一步:通過翻轉一些循環邊的內部方向,打破在輸入圖中出現的環路。
第二步:將節點分配給不同的等級(rank)和層次(level),自頂向下繪圖,等級決定了縱軸的位置。跨越了多個等級的邊,會被拆分成有多個虛擬節點相連接的鏈條。
第三步:根據節點等級(rank)為節點排序以避免節點的交叉。
第四步:在保持邊長盡量短的情況下,設置節點的橫坐標,同時繪出邊的樣條曲線。
dot工具的繪圖方法,其官網 www.graphviz.org 上面有著詳細地介紹,這里不再做詳盡說明。
二、使用dot工具生成圖片
安裝Graphviz后,新建一個文件夾,建立一個bat文件取名【GenerateJpgsBatch.bat】,代碼如下:
:: 在這里設置調用文件路徑 set dotPath=D:\Graphviz2.38 set sourcePath=C:\Users\Tsybius\Desktop\graphviz_study rem 測試文件XXX %dotPath%\bin\dot.exe -Tjpg %sourcePath%\XXX.dot -o %sourcePath%\XXX.jpg pause
其中dotPath為dot代碼文件地址,sourcePath為生成后文件的地址。
上面的代碼就是用dot.exe,將一個名為XXX.dot的文件,生成為圖片XXX.jpg。
使用dot程序生成帶有漢字信息的圖片,需要注意兩點,否則生成的圖片中漢字會被顯示為亂碼:
1、文件應使用UTF-8編碼保存,而不是Windows默認的ANSI編碼
2、字體應指定為支持漢字的字體,如宋體為SimSun
三、實例一:最簡單的dot圖-高速公路節點圖
下圖是一張高速公路重要節點圖。這張圖是一張較為簡單dot圖,只有節點之間的簡單指向關系。
文件【expressway.dot】內代碼如下:
digraph {
edge[fontname="SimSun",fontcolor=red];
node[fontname="SimSun",size="20,20"];
北京[shape=doublecircle];
湘潭[shape=plaintext]
//高速公路節點關系
北京->石家莊->鄭州->武漢->長沙->廣州[label=京港澳高速,color=red];
北京->天津->沈陽->長春->哈爾濱[label=京哈高速,color=lawngreen];
北京->呼和浩特->銀川->蘭州->西寧->拉薩[label=京藏高速,color=purple];
鄭州->西安->蘭州->烏魯木齊[label=連霍高速,color=blue]
上海->杭州->南昌->湘潭->貴陽->昆明[label=滬昆高速,color=orange];
福州->南昌->武漢->西安->銀川[label=福銀高速,color=brown];
湘潭->長沙[style=dotted];
} 生成圖片如下:

四、實例二:類HTML語言編寫復雜的節點-華容道
dot也支持解釋一些類HTML的代碼繪制近似于復雜表格的數據。
下圖是由一個單一節點組成的,這個節點被劃分成很多區域,被繪制成華容道最經典的圖形-橫刀立馬
文件【huarongpass.dot】內代碼如下:
digraph {
huarongpass [shape=none, margin=0, fontname="SimSun" label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
<TR><TD>張<BR/>飛</TD><TD COLSPAN="2">曹操</TD><TD>馬<BR/>超</TD></TR>
<TR>
<TD ROWSPAN="2">趙<BR/>云</TD>
<TD COLSPAN="2">關羽</TD>
<TD ROWSPAN="2">黃<BR/>忠</TD>
</TR>
<TR><TD>卒</TD><TD>卒</TD></TR>
<TR><TD>卒</TD><TD COLSPAN="2"></TD><TD>卒</TD></TR>
</TABLE>
>];
} 生成圖片如下:
五、實例三:為圖片添加層次關系-世系樹
世系樹要求將同一個輩分的人放在同一個層次,下面這個例子描繪了漢宣帝從高祖到其自身的世系樹,它設置了5個rank。
文件【familytree.dot】內代碼如下:
digraph {
ranksep=2.75; size="15,15";
{
edge [fontname="SimSun", fontcolor=red];
//時間線
node [shape=plaintext, fontname="SimSun", fontsize=60];
"高祖輩"->"曾祖輩"->"祖父輩"->"父輩"->"本人";
}
{
rank = same;
};
node [shape=box, fontname="SimSun", fontsize=60];
{ rank = same; "高祖輩"; "孝景皇帝劉啟"; "孝景皇后王氏"; "外高祖父衛父"; "外高祖母衛媼"; }
{ rank = same; "曾祖輩"; "曾祖父世宗武皇帝劉徹"; "曾祖母思皇后衛子夫"; "外曾祖母貞君"; }
{ rank = same; "祖父輩"; "祖父戾太子劉據"; "祖母戾后史氏"; "外祖父思成侯王乃始"; "外祖母博平君思成夫人王媼"; }
{ rank = same; "父輩"; "父悼皇考劉進"; "母悼后王翁須" }
{ rank = same; "本人"; "中宗孝宣皇帝劉詢" }
{"孝景皇帝劉啟", "孝景皇后王氏"}->"曾祖父世宗武皇帝劉徹";
{"外高祖父衛父", "外高祖母衛媼"}->"曾祖母思皇后衛子夫";
{"曾祖父世宗武皇帝劉徹", "曾祖母思皇后衛子夫"}->"祖父戾太子劉據";
"外曾祖母貞君"->"祖母戾后史氏"
{"祖父戾太子劉據", "祖母戾后史氏"}->"父悼皇考劉進";
{"外祖父思成侯王乃始", "外祖母博平君思成夫人王媼"}->"母悼后王翁須";
{"父悼皇考劉進", "母悼后王翁須"}->"中宗孝宣皇帝劉詢";
} 生成圖片如下:

六、實例四:通過創建子圖對大圖中的節點進行分組-三國君主傳承順序
dot支持可以通過創建子圖(subgraph)對節點進行分區,如下圖總結三國時代魏蜀吳三國君主傳承順序,將魏、蜀、吳三國的君主分到了各自的區域內。
文件【threekingdoms.dot】內代碼如下:
digraph {
edge[fontname="SimSun",fontcolor=red];
node[fontname="SimSun",size="20,20"];
subgraph cluster0 {
color=red;
"曹操(0)","曹丕(1)","曹叡(2)","曹髦(3)","曹芳(4)","曹奐(5)"[shape=box];
fontname="SimSun"
label="#1 魏國";
"曹操(0)"->{"曹丕(1)", "曹彰", "曹宇"};
"曹丕(1)"->{"曹叡(2)", "曹霖"};
"曹霖"->"曹髦(3)"
"曹彰"->"曹楷"->"曹芳(4)"
"曹宇"->"曹奐(5)"
}
subgraph cluster1 {
color=blue;
"劉備(0)","劉禪(1)"[shape=box];
fontname="SimSun"
label="#2 蜀國";
"劉備(0)"->"劉禪(1)"
}
subgraph cluster2 {
color=purple;
"孫堅(0)","孫策(1)","孫權(2)","孫亮(3)","孫休(4)","孫和(5)","孫皓(6)"[shape=box];
fontname="SimSun"
label="#3 吳國";
"孫堅(0)"->{"孫策(1)","孫權(2)"};
"孫權(2)"->{"孫和(5)","孫休(4)","孫亮(3)"};
"孫和(5)"->"孫皓(6)";
}
"初代君主"->{"曹操(0)","劉備(0)","孫堅(0)"}[style=dotted];
{"曹奐(5)","劉禪(1)","孫皓(6)"}->"末代君主"[style=dotted];
} 生成圖片如下:

END
