使用dot來(lái)繪圖

寫(xiě)在前面


第一次了解到dot已經(jīng)是很久之前的事情了,但是到今天才決定寫(xiě)下一點(diǎn)東西,可見(jiàn)懶到什么程度。最開(kāi)始對(duì)dot感興趣是因?yàn)橄旅孢@張圖:

網(wǎng)絡(luò)圖

對(duì)于這種網(wǎng)絡(luò)圖用visio很容易搞定,但是復(fù)制、粘貼、拖拽這些用起來(lái)總是感覺(jué)不怎么順手。但是用dot來(lái)做就完全不一樣了,只需寫(xiě)段文本:

digraph G {
    main -> parse -> execute;
    main -> init;
    main -> cleanup;
    execute -> make_string;
    execute -> printf;
    init -> make_string;
    main -> printf;
    execute -> compare;
}

然后在需要的時(shí)候在這段文本中增加邊、節(jié)點(diǎn)即可。保存之后只需要用貝爾實(shí)驗(yàn)室搞的graphviz來(lái)生成目標(biāo)圖片就可以了:

dot -Tpng G.dot -o g.png

這樣你的vim、emacs就馬上變成了一個(gè)可以畫(huà)圖的工具了:)。

可能你覺(jué)得這樣還不夠爽,想想看如果用代碼自動(dòng)生成dot文件,也就是說(shuō)可以通過(guò)用代碼輸出dot文件來(lái)間接到達(dá)輸出圖片的目的,是不是能做的事情多多了?

簡(jiǎn)單用法


日常中用到畫(huà)圖的地方,知道下面幾點(diǎn)基本上就夠用了:

  1. 有向圖(digraph)用a->b,無(wú)向圖(graph)用a--b;
  2. 節(jié)點(diǎn)、邊通過(guò)中括號(hào)中的key=value來(lái)設(shè)置,比如main[shape=box];將main節(jié)點(diǎn)設(shè)置為矩形;
  3. 連接點(diǎn)的方向可以通過(guò)b->c:se;進(jìn)行指定;
  4. 使用subgraph定義子流程圖;

常用屬性


對(duì)于各種結(jié)構(gòu)的通用的屬性如下:

屬性名稱(chēng) 默認(rèn)值 含義
color black 顏色
colorscheme X11 顏色描述
fontcolor black 文字顏色
fontname Times-Roman 字體
fontsize 14 文字大小
label 顯示的標(biāo)簽,對(duì)于節(jié)點(diǎn)默認(rèn)為節(jié)點(diǎn)名稱(chēng)
penwidth 1.0 線條寬度
style 樣式
weight 重要性

常用邊屬性如下:

屬性名稱(chēng) 默認(rèn)值 含義
arrowhead normal 箭頭頭部形狀
arrowsize 1.0 箭頭大小
arrowtail normal 箭頭尾部形狀
constraint true 是否根據(jù)邊來(lái)影響節(jié)點(diǎn)的排序
decorate 設(shè)置之后會(huì)用一條線來(lái)連接edge和label
dir forward 設(shè)置方向:forward,back,both,none
headclip true 是否到邊界為止
tailclip true 與headclip類(lèi)似

常用節(jié)點(diǎn)屬性如下:

屬性名稱(chēng) 默認(rèn)值 含義
shape ellipse 形狀
sides 4 當(dāng)shape=polygon時(shí)的邊數(shù)
fillcolor lightgrey/black 填充顏色
fixedsize false 標(biāo)簽是否影響節(jié)點(diǎn)的大小

常用圖屬性如下:

屬性名稱(chēng) 默認(rèn)值 含義
bgcolor 背景顏色
concentrate false 讓多條邊有公共部分
nodesep .25 節(jié)點(diǎn)之間的間隔(英寸)
peripheries 1 邊界數(shù)
rank same,min,source, max,sink,設(shè)置多個(gè)節(jié)點(diǎn)順序
rankdir TB 排序方向
ranksep .75 間隔
size 圖的大?。ㄓ⒋纾?/td>

高級(jí)用法


在dot里面label的玩法比較多,在上面看到的每個(gè)節(jié)點(diǎn)都是簡(jiǎn)單的一段文字,如果想要比較復(fù)雜的結(jié)構(gòu)怎么辦?如下圖:

復(fù)雜的節(jié)點(diǎn)

對(duì)應(yīng)的代碼如下:

digraph structs {
    node [shape=record];
    struct1 [shape=record,label="<f0> left|<f1> mid\ dle|<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;
}

這個(gè)還不算厲害的,label還支持HTML格式的,這樣你能想得到的大部分樣子的節(jié)點(diǎn)都可以被定義出來(lái)了:

HTML格式的label

代碼如下:

digraph html {
    abc [shape=none, margin=0, label=<
    <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">
        <TR><TD ROWSPAN="3"><FONT COLOR="red">hello</FONT><BR/>world</TD>
            <TD COLSPAN="3">b</TD>
            <TD ROWSPAN="3" BGCOLOR="lightgrey">g</TD>
            <TD ROWSPAN="3">h</TD>
        </TR>
        <TR><TD>c</TD>
            <TD PORT="here">d</TD>
            <TD>e</TD>
        </TR>
        <TR><TD COLSPAN="3">f</TD></TR>
    </TABLE>>];
}

接著來(lái)看cluster的概念,在dot中以cluster開(kāi)頭的子圖會(huì)被當(dāng)做是一個(gè)新的布局來(lái)處理,而不是在原圖的基礎(chǔ)上繼續(xù)操作。比如:

流程圖

對(duì)應(yīng)代碼如下:

digraph G {
    subgraph cluster0 {
        node [style=filled,color=white];
        style=filled;
        color=lightgrey;
        a0 -> a1 -> a2 -> a3;
        label = "process #1";
    }
    subgraph cluster1 {
        node [style=filled];
        b0 -> b1 -> b2 -> b3;
        label = "process #2";
        color=blue
    }
    start -> a0;
    start -> b0;
    a1 -> b3;
    b2 -> a3;
    a3 -> a0;
    a3 -> end;
    b3 -> end;
    start [shape=Mdiamond];
    end [shape=Msquare];
}

如果沒(méi)有cluster的話我們大概能想象的出來(lái)最后的結(jié)果是什么樣子的??赡軙?huì)想能不能將一個(gè)節(jié)點(diǎn)直接指向cluster?答案是不能!對(duì)于這種需求可以用lhead來(lái)搞定:

digraph G {
    compound=true;
    subgraph cluster0 {
        a -> b;
        a -> c;
        b -> d;
        c -> d;
    }
    subgraph cluster1 {
        e -> g;
        e -> f;
    }
    b -> f [lhead=cluster1];
    d -> e;
    c -> g [ltail=cluster0, lhead=cluster1];
    c -> e [ltail=cluster0];
    d -> h;
    cluster0->cluster1;
}

生成的圖片如下:

節(jié)點(diǎn)指向cluster
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,502評(píng)論 19 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評(píng)論 25 709
  • 夏天是最不無(wú)聊的季節(jié), 一直以來(lái),都是蜜遞君最喜歡的季節(jié)。 無(wú)論時(shí)光怎樣更迭,只要到了夏天,好像就會(huì)回到膠原蛋白滿...
    蜜遞伊甸園閱讀 1,473評(píng)論 0 0
  • 這是一段發(fā)生在江南茶鄉(xiāng)的普通故事,普通到我們每個(gè)人可能都見(jiàn)過(guò)都聽(tīng)過(guò)…… 老黃很老了,老到天天只能保持一個(gè)坐姿在門(mén)口...
    凌家龍少閱讀 1,141評(píng)論 4 6
  • 親愛(ài)的程程你好,這是媽媽給你的第二封情書(shū)。 現(xiàn)在你應(yīng)該是坐在教室里聽(tīng)課吧?我知道你上課總是非常積極的回答問(wèn)...
    日出東方天剛曉閱讀 213評(píng)論 0 0

友情鏈接更多精彩內(nèi)容