其他绘图系统

“PSTricks 是过去的工具,TikZ 才是现役” —— 这是常见的说法,但翻开 TeX Live 2024 的内容会发现事情正好相反。其中附带的 PSTricks 是 2024 年 2 月 2 日的 v3.19c,至今仍在发布新版。而以交换图经典工具闻名的 Xy-pic,最后一次更新是 2013 年 10 月 6 日,而且每次编译都会把这个日期写进日志。本页将梳理 LaTeX 中除 TikZ 之外可用的四种绘图系统——调用 PostScript 的 PSTricks、图式老将 Xy-pic、作为独立语言的 Asymptote,以及继承 METAFONT 血脉的 MetaPost——并以各自的 输出路径 为主线。因为真正区分它们的,与其说是表现力,不如说是能用哪个引擎、以何种方式排版。

如果是新画一幅图,默认仍该选 TikZ 吗

是的,几乎必然选 TikZ。理由不在功能,而在 没有摩擦。TikZ 可在 pdflatexlualatexxelatex 中运行,不需要外部程序,也不需要额外的编译阶段。本页讨论的四种系统,每一种至少会打破其中一个条件:PSTricks 无法在 pdfLaTeX 下直接运行,Asymptote 需要外部二进制程序和三步编译,MetaPost 以 LuaLaTeX 或专用程序为前提,Xy-pic 虽然能跑,但自 2013 年起停止更新。尽管如此,了解其他系统仍有价值,原因有三:维护既有文档正式的 3D,以及 ConTeXt 这类特定生态

PSTricks:三十年历史,至今仍在更新

PSTricks 是一组宏,可从 TeX/LaTeX 源码中直接调用 PostScript 的绘图功能。pstricks.tex 开头的版权声明本身就讲清了这个体系的历史:Timothy Van Zandt(1993、1994、1999)Denis Girou(2000–2003),以及 Herbert Voß(2004 年至今)。经三代维护者相传,TeX Live 2024 中的版本是 v3.19c,日期为 2024 年 2 月 2 日。PSTricks 古老的是它的设计前提,而不是它的维护状况。

它的语法大多可以从名字看出功能。\psline 画线或折线,\pscircle 画圆,\psframe 画矩形。坐标写在圆括号里,如 \psline(0,0)(3,2);圆用中心和半径指定:\pscircle(2,2){1}。整幅图放在 pspicture 环境 中,打开时给出左下角和右上角坐标:\begin{pspicture}(0,0)(4,3)。要把任意对象放到某个坐标,用 \rput;若还需要角度或偏移,则用 \uput。线型、箭头和颜色统一写在方括号选项中。

latex
\begin{pspicture}(0,0)(4,3)
  \psframe(0,0)(4,3)
  \psline[linewidth=1pt]{->}(0,0)(3,2)
  \pscircle(2,1.5){1}
  \rput(2,1.5){$O$}
\end{pspicture}

这幅图画出宽 4、高 3 的边框,从原点向 (3,2) 拉一条带箭头的线段,叠上一个以 (2,1.5) 为中心、半径 1 的圆,并在圆心放一个 O。它的扩展包也很丰富:pst-plot(函数图)、pst-node(节点与连线)、pst-3dplot(3D)等等。就表现力而言它至今仍然强大。问题集中在下一节的那一点上。

PSTricks 在 pdfLaTeX 下报的错,以及绕过的办法

在第一条绘图命令处会出现 ! Undefined control sequence.。在 TeX Live 2024 上把带 \usepackage{pstricks} 的文档交给 pdflatex,它在 \psframe 那一行停下:"! Undefined control sequence. \c@lor@to@ps ->\PSTricks _Not_Configured_For_This_Format"。展开过程中出现了一个名为 \PSTricks_Not_Configured_For_This_Format 的标记记号,它是 有意保持未定义的,用名字本身喊出“此格式不受支持”。麻烦之处在于,在 nonstopmode 下它会重复报错几十次,却 仍然把 PDF 生成到底——一个恰好缺了那幅图的 PDF。

原因就在输出机制本身。PSTricks 的设计是把绘图输出为 PostScript 的 \special(嵌入 DVI 的特殊指令),而直接生成 PDF 的 pdflatex 没有承接它们的地方。出路有三条,三条都在 TeX Live 2024 上实测可用。

terminal
# route 1: the classic DVI path
latex figure.tex
dvips figure.dvi -o figure.ps
ps2pdf figure.ps

# route 2: stay in pdflatex, let auto-pst-pdf shell out
pdflatex --shell-escape figure.tex

# route 3: just use xelatex - no extra package needed
xelatex figure.tex

路线 1 是经典做法,也最可靠:latex 生成 DVI,dvips 转成 PostScript,ps2pdf(Ghostscript)再转成 PDF。这里有一条实测提醒——Ghostscript 10.03.0 在过程中输出了 "WARNING: Transparency operations ignored - need to use -dALLOWPSTRANSPARENCY"。这意味着 PSTricks 的透明度(opacity 一族)会被 悄悄丢弃,如果用了半透明填充,务必亲眼检查结果。

路线 2 保持 pdflatex 的流程,把幕后工作交给 auto-pst-pdf。机制很朴素:在 pdflatex 运行过程中,auto-pst-pdf以子进程启动另一个 LaTeX,只把 PSTricks 部分经 PostScript 渲染成 <文档名>-pics.pdf,再并入。实际运行时日志会显示 "auto-pst-pdf: Auxiliary LaTeX compilation",可以看到路线 1 正在背后运转。既然要启动外部进程,--shell-escape 就是必须的;忘了加,它会相当直白地训你:"! Package auto-pst-pdf Error: auto-pst-pdf will not work!"。若同一文档中还要混用 PNG 或 JPEG,这条路线很合适。

路线 3 最出人意料,也最简单:源码一个字符都不改,直接交给 xelatex 即可。不需要额外安装任何宏包——TeX Live 2024 中 PSTricks 本身就附带了配置文件 tex/generic/pstricks/config/xdvipdfmx.cfg,在 XeLaTeX 下运行时会自动载入(日志里确实会出现这个文件名)。由于 XeLaTeX 内部经过 DVI 系的中间格式,PostScript 的 \special 能顺畅通过。如果整篇文档本来就用 XeLaTeX 排版,那么可以说 PSTricks 根本不需要什么“变通办法”。

Xy-pic 与 \xymatrix:仍能运行,但停在 2013 年

Xy-pic(包名 xy)是一个通用宏包,用于排版图与图式,可在 plain TeX、LaTeX 和 AMS-LaTeX 下工作。它不需要特殊的输出路径——pdflatex 直接就能处理。有意思的是,它每次编译都会把自己的身世写进日志;在 TeX Live 2024 上它打印 " Xy-pic version 3.8.9 <2013/10/06>"。xy.tex 的版权声明写着 1991 年至 2013 年,Kristoffer H. Rose 等。二十多年的使用,加上十多年没有更新,浓缩在这一行里。

实际用得最多的是用于 交换图\xymatrix。这是一种像矩阵一样排布图式的模式:和 tabular 一样,条目用 & 分隔,行用 \\ 换行。对象之间的箭头用 \ar 绘制,目标以方向键给出——[r] 向右,[l] 向左,[u] 向上,[d] 向下,像 [rd] 这样组合表示右下相邻的格。箭头标签沿用数学上下标的记法:^ 把标签放在箭头上方(沿箭头方向看是左侧),_ 放在下方(右侧)。通常用 \usepackage[all]{xy} 载入,其中 [all] 启用标准功能集。

latex
\usepackage[all]{xy}
% ...
\[
\xymatrix{
  A \ar[r]^{f} \ar[d]_{\alpha} & B \ar[d]^{\beta} \\
  C \ar[r]_{g}                  & D
}
\]

这会得到一个四角为 A、B、C、D 的交换正方形:上边是向右的 f,左边是向下的 α,右边是向下的 β,下边是向右的 g。图式本身也是数学内容,所以放在陈列数学环境中。如果是新画交换图,今天的现代选择是基于 TikZ 的 tikz-cd——处理曲线、复杂箭头和多行图式更容易,错误信息也读得懂。本节知识的价值在于 读写已经用 Xy-pic 写成的稿件。两者的比较属于交换图那一页。

Asymptote:编译器就装在 TeX Live 里的语言

一听说需要外部程序就会紧张,但 Asymptote 的 asy 就在 TeX Live 里。查看 TeX Live 2024 的可执行文件目录,一个约 45 MB 的 asympostmf 并排;asy --version 回答 "Asymptote version 2.88",并在已启用选项中列出 "V3D 3D vector graphics output"。也就是说,装好 TeX Live 就已经拥有 Asymptote,无需另外获取。这正是它与 gnuplot 的决定性区别——gnuplot 不在 TeX Live 中,必须自己安装。

Asymptote 不是一组 TeX 宏,而是一门 独立的矢量图形语言。它采用类 C++ 语法,作为具备变量、函数、循环和类型的真正编程语言来描述图形。它的设计意图也很有意思:官方手册把 Asymptote 定位为受 MetaPost 启发的语言,同时标榜更整洁的类 C++ 语法。最特别的是它决定尺寸的方式。当 size(6cm) 这样的整体尺寸与不随之缩放的元素(标签、箭头)发生冲突时,Asymptote 会用 单纯形法,也就是线性规划,来求解这些约束。用线性规划来决定图有多大的绘图语言,可不多见。

要嵌入 LaTeX,先载入 \usepackage{asymptote},把图形代码写在 asy 环境 中。由于其机制,编译需要 三步——在 TeX Live 2024 上实测的过程是这样:首先运行 pdflatexasy 环境的内容会被写出为 <文档名>-1.asy,同时给出警告 "Package asymptote Warning: file ... not found on input line 11."——图还不存在,这很自然。接着运行 asy <文档名>-1.asy 生成 <文档名>-1.pdf,再运行一次 pdflatex,这个 PDF 就被引入了。手动执行这三步很繁琐,实际使用中交给 latexmk

terminal
pdflatex document        # writes document-1.asy
asy document-1.asy       # produces document-1.pdf
pdflatex document        # includes it

# or, in one go:
latexmk -pdf document
asymptote
// a standalone .asy file, run with:  asy figure.asy
import three;
size(6cm);
draw(unitcube);
draw(O--X, red,   Arrow3);
draw(O--Y, green, Arrow3);
draw(O--Z, blue,  Arrow3);

这段代码导入 three 模块(3D 功能),画出一个单位立方体,并从原点沿 x、y、z 轴方向画出红、绿、蓝三维箭头。图不必嵌入文档:像这样写成 独立的 .asy 文件,用 asy figure.asy 单独运行,就能输出 PDF、EPS、SVG、WebGL,或可嵌入 PDF 的 3D 格式。由于标签由 TeX 排版,图中的数学内容与正文字体一致。对于 正式的 3D——带坐标轴的立体与曲面——Asymptote 比 TikZ 自然得多。它还附带 GUI 前端 xasy,可交互式绘图并导出 .asy 源码。

MetaPost:用 LuaLaTeX 完全不需要外部程序

MetaPost 是 John Hobby 对 Knuth 的 METAFONT(描述字体的语言)所作的改造,并把输出改为 PostScript。它继承了 METAFONT 由点和方向求解并绘制平滑曲线的记法(Hobby 算法),并允许把坐标 以方程的方式声明式地 写出。经典用法是把它当独立语言使用:把 .mp 文件交给专用程序 mpost,得到 EPS。

不过在现代 LaTeX 中,这个外部调用并不必要。载入 luamplib 宏包后,就可以在 mplibcode 环境 中直接写 MetaPost。LuaTeX 内置了 MetaPost 引擎,即 mplib 库,因此既不需要另外启动 mpost,也不需要 --shell-escape。在 TeX Live 2024 上把下面的示例交给 lualatex,没有调用任何外部进程就一次生成了 PDF。本页所讲的四种体系中,完全不需要额外外部工具的只有经由 LuaLaTeX 的 MetaPost

document.tex
% compile with lualatex
\documentclass{article}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
beginfig(1);
  draw fullcircle scaled 2cm withpen pencircle scaled 1pt;
  draw (-1cm,0)--(1cm,0);
  draw (0,-1cm)--(0,1cm);
endfig;
\end{mplibcode}
\end{document}

mplibcode 里的内容是纯 MetaPost。beginfig(1)endfig 划出一个图;它用 1pt 的笔画出放大到直径 2cm 的单位圆,再各画一条水平和垂直直径。fullcirclepencirclescaled 都属于 MetaPost 的内置词汇。它生态中的关键是 MetaFun 这一高功能格式,排版系统 ConTeXt 正是通过它深度集成 MetaPost。若使用 ConTeXt,MetaPost 就是核心作图手段;若主要使用 LaTeX,则日常用 TikZ,需要 METAFONT 式的曲线描述时再用 MetaPost。

四种体系比较:何时选哪一个

按输出路径和引擎排列后,选择的依据就清楚了。维护既有文档 时,应能读写该文档原本使用的体系。需要 3D 图形 就选 Asymptote。使用 ConTeXt 就用 MetaPost(经 MetaFun)。要画 新的交换图,选 tikz-cd 而非 Xy-pic。至于不属于上述任何情况的大多数作图,最稳妥的判断是用 TikZ——不需要外部工具,也不需要特殊输出路径。

体系输出路径 / 引擎外部工具强项 / 主要用途
PSTrickslatex → dvips → ps2pdf,或配 auto-pst-pdf 的 pdfLaTeX,或直接用 XeLaTeXdvips 与 Ghostscript;auto-pst-pdf 路线还需要 --shell-escape高质量的 PostScript 填充与效果;既有文档多;仍在维护(v3.19c,2024)
Xy-pic在普通 LaTeX 下运行;不需要特殊路径交换图老将;现代替代是 tikz-cd;停在 3.8.9(2013)
Asymptotelatex/pdflatex → asy → 再次 latex;或独立 .asyasy 随 TeX Live 附带;可用 latexmk 自动化正式的 2D 与 3D;带坐标轴的立体与曲面;可输出 SVG、WebGL 乃至 3D PDF
MetaPostmpost 处理 .mp;或 LuaLaTeX 加 luamplibmplibcode经 LuaLaTeX 则无需——mplib 已内置于 LuaTeXMETAFONT 传承的曲线与以方程表达的坐标;ConTeXt(MetaFun)的核心