UNIX 下繪圖面面觀

在UNIX下有很多非常優秀的繪圖工具,從手繪到語繪的,應有盡有。

最為強大的當屬 MetaPost 和 asymptote,據說二者擇一即可滿足一生繪圖的需求。asymptote 是後來者,C 語言風格,支持 3d 效果,也有一群粉絲。我看二者的語法都令人頭痛,要精通不易啊。

這種情況下,偷懶是必須的。出於和其他工具軟件接口的考慮,我選擇 MetaPost 作為我的頂級繪圖工具。手繪的我選擇 xfigure,語繪的我喜歡 GnuPlot、graphviz、TikZ&PGF 包和 MetaPost,它們側重點不同,下面逐一介紹。PSTricks 我沒用過,據說也很方便,現有的工具足夠強大了,所以就不再選 PSTricks 了。

用 GnuPlot 和 XFigure 輸出 MetaPost

天底下繪圖的工具很多,我用過 Visio、Dia、XFig、GnuPlot 等等,當我用到 MetaPost,我想它應該是終極畫圖工具了。MetaPost 集嚴謹與美感於一身,是TeX 用戶最最合適的選擇。但,MetaPost 語言實在令人抓狂,常用的還好說,稍微複雜一點的就難說了。好在我們有 GnuPlot 和 XFigure,前者是函數繪圖工具,後者是手繪工具。它們都能輸出 MetaPost 格式的文件 foo.mp,可以直接用 mpost foo.mp 得到 eps 格式的結果。

set terminal png           # 輸出格式
set output "sin.png"       # 輸出文件
set samples 40
set isosamples 40
set hidden3d               # 不透明
set title "2-d surface"    # 標題
set xrange [-3:3]
set yrange [-3:3]
set contour                # 等高線
splot sin(x*y)             # 畫二維曲面

我們利用GnuPlot畫函數圖像,輸出為MetaPost格式的文件,如果需要,可以在結果中做適當修改,然後再利用mpost得到我們想要的東西。

set terminal mp prologues 2
set output "surface.mp"
set samples 40
set isosamples 40
set hidden3d
set title "2-d surface"
set xrange [-3:3]
set yrange [-3:3]
set contour
splot sin(x*y)

可以對自動生成的 surface.mp 進行修改,譬如插入一個公式等等。另外,GnuPlot 還是一些數學軟件的圖形輸出端,如 octave 等。手繪工具 Xfigure 可以導出 MetaPost 格式的文件,也能進行相似的操作。如果不是為了加入數學公式,或者做一些 GnuPlot 不能做的小修改,是沒有必要動用 MetaPost 的,直接把 png 格式的圖像 \includegraphics 到 LaTeX 中生成 pdf 也不錯啊,不一定要搞個 eps 的出來。

##用 graphviz 輸出流程圖等

graphviz 是基於 dot 語言的繪圖工具,對於有向圖、無向圖、關係圖、目錄圖、流程圖等,我認為用 graphviz 比較快捷。好處是:只要描述好對象之間的關係,圖的生成是自動的,比 mindmap 還要好用(mindmap 有一個根節點,graphviz 對根節點個數沒有限制)。缺點是:圖的生成是自動的,有時得到的不是自己想要的。

另外一個不大不小的缺點是:graphviz 只支持中文 utf-8 編碼,所以我在 emacs 下寫完代碼後要將之存為 utf-8 格式才能生成正常顯示中文的 png 文件。例如,

digraph test {
	node[shape=box,fontname="/usr/local/share/fonts/TrueType/simsun.ttf",fontsize=12];
	node0 [shape=house, label="特徵函數",fillcolor=red];
	node1 [shape=house, label="Chebyshev不等式",fillcolor=red];
	node2 [shape=house, label="Kolmogorov不等式",fillcolor=red];
	node3 [shape=ellipse, label="Kolmogorov強大數定律"];
	node1 -> Markov弱大數定律 -> Chebyshev弱大數定律 -> Poisson弱大數定律;
	Chebyshev不等式 -> Chebyshev弱大數定律 -> Bernoulli弱大數定律;
	Kolmogorov弱大數定律 -> Markov弱大數定律;
	node0 -> Khintchine弱大數定律 -> Bernoulli弱大數定律;
	node2  -> node3;
}

dot語言在emacs下可以實現語法高亮,詳情見:/usr/local/share/emacs/site-lisp/graphviz-dot-mode.el。 graphviz自帶的手冊是:/usr/local/share/doc/graphviz/html/index.htmlC-x RET f utf-8 RET 將當前緩衝區的編碼改為 utf-8

C-x RET c utf-8 RET C-x C-s filename RET	在保存時轉換編碼格式
C-x RET r utf-8 RET	重新以utf-8編碼加載文件

##用 LaTeX 的宏包 TikZ&PGF

TikZ&PGF 是一個 LaTeX 宏包,功能直追 MetaPost,可以在 TeX 文件中直接描述所繪圖形,pdflatex 後得到含所需圖形的 pdf 文件。TikZ&PGF 包在描述路徑方面與 MetaPost 的語法是一致的。teTeX 下這個宏包是缺省安裝的,現在的版本是2.0,手冊(/usr/local/share/doc/latex-pgf/pgfmanual.pdf)有560 頁之多,令人畏懼。這個宏包幾乎無所不能,例如

\begin{tikzpicture}
  \node {root}
    child {node {left}}
    child {node {right}
      child {node {child}}
      child {node {child}}
    };
\end{tikzpicture}
\begin{tikzpicture}[domain=0:4]
  \draw[very thin,color=gray] (-0.1,-1.1) grid (3.9,3.9);
  \draw[->] (-0.2,0) -- (4.2,0) node[right] {$x$};
  \draw[->] (0,-1.2) -- (0,4.2) node[above] {$f(x)$};
  \draw[color=red]    plot (\x,\x)             node[right] {$f(x) =x$};
  \draw[color=blue]   plot (\x,{sin(\x r)})    node[right] {$f(x) = \sin x$};
  \draw[color=orange] plot (\x,{0.05*exp(\x)}) node[right] {$f(x) = \frac{1}{20} \mathrm e^x$};
\end{tikzpicture}

看手冊pp282頁,TikZ&PGF 可以畫 mindmap,生成的 mindmap 是我見到的最漂亮的。TikZ&PGF 的語法比 MetaPost 要簡單,讓人感嘆 TeX 之偉大。和 MetaPost 相比,TikZ&PGF 是內置的,\usepackage{tikz} 引入宏包後,直接在 TeX 代碼中繪圖即可。MetaPost 則是一個外置的獨立的畫圖工具,它生成 eps 格式的文件,通過 \includegraphics 插入。可能在編譯時耗上有點差別,二者的功能應該在仲伯之間。

##強大的 MetaPost

王垠對 MetaPost 及其中文化做了概要介紹,不再敷述。感興趣的在網上 google 能找出一片 introductions,也可以看類似一日遊的 tutorial。上手的捷徑就是搞幾個模板,在此基礎上修修改改,藉此熟悉 MetaPost 語言。


书籍推荐