zzdot學習筆記

『dot 學習筆記』二. 記錄 Shell 的變遷
LiYanrui posted @ 3 年前 in 數(shù)據可視化 with tags graphviz dot , 1812 閱讀
上一篇「基本概念」中,我闡述了我所理解的 dot 繪圖的基本知識,現(xiàn)在到了絕知此事要躬行的時刻。從本篇開始,我希望能夠通過一些應用實例來歷練一下 dot 繪圖技能,許多關于 dot 的繪圖細節(jié)知識與技巧也在這些實例的分析中進行探討。
本篇所采用的實例來源于 graphviz 軟件包附帶的一個示例。我所做的就是對之詳加分析,并且按照我的審美標準進行了一點修改。
Go ahead!

要做什么
本文全部的工作就是要繪制下面這幅圖形,它直觀地描述了 Unix-like 系統(tǒng) shell 的變遷。

a8de650844eda9064c1747062995b45e.png

設置全局屬性
圖形中的結點、邊可能會有一些相同的屬性設置,我們可以在繪圖開始時進行全局性的設定。在 Shell 變遷圖中,我要求所有的結點使用的字體大小為 11pt,所有的結點的高度設為 dot 預定義的最小值 0.02 英寸,所有的邊的箭頭尺寸為默認尺寸的 0.5 倍,具體代碼如下:

digraph shells {node [fontsize = 11, height = .02]edge [arrowsize= .5]}
或許你會擔心結點的高度設為 0.02 英寸有些太小了。事實上,只要不開啟結點的 'fixedsize = true
'
屬性,dot 會根據結點的 label 文本長度適應性確定結點的高度。對結點的寬度屬性,同理。
繪制時間線
Shell 變遷圖的左側是從上之下的時間軸線,是由 plaintext 結點和有向邊構成的,具體繪制代碼如下:

digraph shells { node [fontsize = 11, height = .02] edge [arrowsize= .5]node [shape = plaintext]1972 -> 1976 -> 1978 -> 1980 -> 1982 -> 19841984 -> 1986 -> 1988 -> 1990 -> future;}
現(xiàn)在可以使用 dot 編譯一下這份文件,你會看到時間線。
年表
1972 年,Thompson 寫了第一個 Unix Shell。對于這一史實,我們可以使用 dot 語言將其表示為:
{rank = same; 1972; Thompson}
上述代碼是將 1972 與 Thomepson 兩個結點放在一個匿名的子圖里。如果你不嫌麻煩,可以將其寫為帶有名字的子圖,譬如:

subgraph subgraph_name {rank = same; 1972; Thompson}
之所以采用子圖,是因為我們希望 1972 與 Thompson 出現(xiàn)在同一層次。因為我們還要繼續(xù)描述其它年間出現(xiàn)的各個 Shell,它們需要分別與時間軸上對應的時間結點出現(xiàn)在同一層次上,這就是圖的 'rank = same
' 屬性要解決的問題。關于 rank 屬性的詳細解釋,請參考『Drawing graphs with dot』文檔的表 3。
1976 年,在 Thompson 的 Shell 基礎上,發(fā)展出了 Mashey 和 Bourne?,F(xiàn)在先不關心這些 Shell 之間的繼承與派生關系,單單去描述 1976 出現(xiàn)了 Mashey 和 Bourne。我們可以像描述 Thompson Shell 那樣來做,即:

{rank = same; 1976; Mashey; Bourne}
同理,我們可以很容易地依次寫出用于描述其它各年間出現(xiàn)的 Shell 的 dot 代碼。
由于在繪制時間軸的步驟中,我將結點的 shape 屬性設為了 plaintext,現(xiàn)在,我們需要將它設回 box。所以,用于繪制 Shell 年表的代碼可以表示為:
node [shape = box]{rank=same; 1972; Thompson}{rank=same; 1976; Mashey; Bourne}... ... ...
這里,要注意的是,我在各個子圖之前所設定的結點 shape 屬性為 box 并不會影響到像 1972、1976 這些時間結點,它們還是會保持著 plaintext 的形狀屬性。不要問我為什么,因為 dot 就是這么做的。把這個知識點當作知識記住吧。
上述代碼可以進一步簡化一下。因為圖的屬性設置是可以被子圖繼承的,因此,可以將各子圖中的 'rank=same
' 屬性提到上一層。另外,那些結點之間的 ';
' 符號也不是必須的。
基于上述討論,我們現(xiàn)在可以完整的寫出時間軸 + Shell 年表圖形的繪制代碼,如下:

digraph shells { node [fontsize = 11, height = .02] edge [arrowsize= .5] node [shape = plaintext] 1972 -> 1976 -> 1978 -> 1980 -> 1982 -> 1984 1984 -> 1986 -> 1988 -> 1990 -> future node [shape = box]rank = same{1972 Thompson}{1976 Mashey Bourne}{1978 Formshell csh}{1980 esh vsh}{1982 ksh "System-V"}{1984 v9sh tcsh}{1986 "ksh-i"}{1988 KornShell Perl rc}{1990 tcl Bash}{"future" POSIX "ksh-POSIX"}}
生成的圖形如下:
[圖片上傳中。。。(3)]

![Uploading a51897f7a14d99c4e7e9aa9c9753ceac_169643.png . . .]
繼承與派生關系
各個 Shell 之間的繼承與派生關系可以利用有向邊的走向來示意,這是 dot 的拿手好戲?;谇懊娴墓ぷ鳎偌由献约簩τ?Shell 歷史知識的把握,用 dot 來描述這些 Shell 之間的繼承與派生關系,事實上只是個體力活,具體代碼如下:
digraph shells { node [fontsize = 11, height = .02] edge [arrowsize= .5] node [shape = plaintext] 1972 -> 1976 -> 1978 -> 1980 -> 1982 -> 1984 1984 -> 1986 -> 1988 -> 1990 -> future node [shape = box] rank = same {1972 Thompson} {1976 Mashey Bourne} {1978 Formshell csh} {1980 esh vsh} {1982 ksh "System-V"} {1984 v9sh tcsh} {1986 "ksh-i"} {1988 KornShell Perl rc} {1990 tcl Bash} {"future" POSIX "ksh-POSIX"} Thompson -> MasheyThompson -> BourneThompson -> cshcsh -> tcshBourne -> kshBourne -> eshBourne -> vshBourne -> "System-V"Bourne -> v9shv9sh -> rcBourne -> Bash"ksh-i" -> BashKornShell -> Bashesh -> kshvsh -> kshFormshell -> kshcsh -> kshKornShell -> POSIX"System-V" -> POSIXksh -> "ksh-i""ksh-i" -> KornShellKornShell -> "ksh-POSIX"Bourne -> Formshell}
現(xiàn)在,我們已經完成了一幅 Shell 變遷圖,可以見識一下它的真實面目了。
[圖片上傳中。。。(4)]

a62255920faae512349b0b5ae98846ad.png

相信你會有些困惑。因為它看起來并不像我在這篇文章的開始所給出的那幅圖形。事實上,dot 就是這樣,它并不保證所產生的圖形有多美觀,它的工作只是正確表示出你想表達的那種思想。
欺騙
如果你真的希望得到本文開始處的那幅圖,就不得不使用一些障眼法,只需將以下代碼放在上一節(jié)代碼的尾部即可。
edge [style=invis]1984 -> v9sh -> tcsh1988 -> rc -> KornShellFormshell -> cshKornShell -> Perl
這個障眼法,就是將邊設置為不可見,偷偷地通過連接幾個結點來調整某些結點的位置。
我不推薦在這種障眼法上浪費太多時間。除非你真的無法忍受丑陋的真實。

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

相關閱讀更多精彩內容

友情鏈接更多精彩內容