1. 从一张图说起:为什么我放弃外部工具,改用LaTeX直接画三维图
熟悉我写作习惯的朋友都知道,我写技术文档和笔记一直用LaTeX。之前需要插图时,习惯用外部软件算好数据,再用Python或第三方绘图库出图,最后导出PDF或PNG插入文档。这套流程用久了,痛点会越来越明显:一是图片和正文的字体、字号很难完全统一;二是修改数据后需要重新出图、重新插入,版本管理很麻烦;三是一篇文档几十张图,文件路径和格式问题能把人逼疯。
转机出现在一次需要绘制参数曲面图的场景。当时我在某模拟项目中需要展示一个三维结构模型的数据分布,手头有现成的数据表,但要快速试几组不同视角和配色方案。外部工具来回导出确实能出图,但每次调整视角都要重新渲染、重新截图,效率很低。我开始认真考虑用LaTeX直接绘制三维图。
LaTeX中绘制高质量图形的方案其实不少,TikZ与pgfplots这对组合是首选。pgfplots是建立在TikZ之上的数学绘图宏包,支持二维和三维图形,语法和数据处理能力比直接用TikZ原生命令高效得多。特别是三维绘图,pgfplots提供了一条完整的绘制路径:从坐标网格、参数曲面到流线图,只需一组简洁的指令,而且最后生成的是矢量图,插入PDF文档后无论怎么缩放都不会糊。
这篇文章我主要分享一下用pgfplots绘制三维曲线图的完整思路和实操过程,从基本语法到坐标轴美化,从空间曲线到参数曲面,再到实际调试中容易踩的坑。内容适合两类读者:一类是刚开始接触LaTeX绘图、想直接上手三维图的新手;另一类是在用外部工具绘图但希望统一文档风格、提升效率的进阶用户。文章里所有的示例代码都是可以直接复制编译的,方便对照学习。
2. 夯实基础:理解pgfplots三维绘图的核心概念
2.1 三维图形与二维图形在LaTeX中的本质区别
用pgfplots画二维图,核心是定义坐标轴环境和数据格式,画三维图则需要额外处理几个维度问题:空间中的坐标映射、视角投射、深度关系(即遮挡)、颜色映射。这些在二维中完全不存在,但在三维中每一项都直接影响最终呈现效果。
先说坐标映射。三维空间中的点(x, y, z)需要投影到二维纸面上,pgfplots简化了这个过程,你不需要自己计算如何投影。默认情况下,视角由两个参数控制:view={azimuth}{elevation},分别是水平旋转角和仰角。例如默认视角view={0}{90}其实正上方看,就是一个平面图。但对三维图来说,视角往往需要调整为非正交视角,让三个坐标轴都能清晰呈现。我第一次画3D图时用默认视角,出来的图完全没有立体感,调整view参数后效果立刻不一样了。
再看深度关系。二维图不存在遮挡问题,三维图则要处理前后位置关系。pgfplots提供了z buffer机制,通过设置z buffer=auto,图形在后端渲染时会根据z坐标值自动划分先后绘制次序,形成正确的遮挡关系。这个开关在绘制复杂曲面时尤为重要,如果不开启,图会非常奇怪——后面的线条可能盖住前面的面。
2.2 三个坐标轴使用的数学约定
在pgfplots中处理三维图时,坐标顺序是(x, y, z),数据点的坐标全部在axis环境中按此顺序解读。绘制曲线时,关键的地方在于:不同面的曲线,坐标表达方式不一样。
举个例子,在XZ平面(即x变化、y固定、z变化)的一条曲线,在pgfplots中的表达应该把y保持为一个常量或仅作为响应变量。我画图时经常遇到的问题是坐标轴方向混淆,尤其是y轴和z轴默认方向不同。实际上,三维坐标轴的默认方向是:x轴向右,y轴指向右后方(形成等轴投影效果),z轴竖直向上。这个默认方向很重要,不熟悉的话会给出令人困惑的图形。
关于坐标数据,pgfplots支持两种三维数据的格式:
- 坐标对格式,即
coordinates {(x1,y1,z1) (x2,y2,z2) ...},适合数据量较小的示例场景; - 网格格式,即用表格形式组织的矩阵数据(每一行对应固定的x,每一列对应固定的y),适合曲面图和较大数据量。
绘制三维曲线图时,我大多数情况下用的是坐标对格式,因为空间曲线本质上是离散点按顺序连接而成的线,每个点自适应确定x、y、z三重坐标。讲述一条空间曲线的数据时,坐标对格式最自然。
2.3 从二维逐步升级到三维的过渡方式
假如你已经会用pgfplots画二维图,那么三维图的上手路径会非常平滑。二维绘图的常用基础结构是:
\begin{axis} \addplot coordinates {(0,0) (1,1) (2,4)}; \end{axis}三维绘图的对应结构仅仅在\addplot后面加一个3,并让坐标数据包含三个维度的值:
\begin{axis} \addplot3 coordinates {(0,0,0) (1,1,1) (2,4,2)}; \end{axis}同时,axis环境默认的二维模式需要显式声明为三维,即在\begin{axis}后添加view参数或者直接设置三维坐标域范围。选pair后,将坐标轴的域限制扩展到z轴,pgfplots就自动进入三维模式。这个迁移成本极低,但带来的表达空间却大得多。
如果之前完全没有接触过pgfplots,建议先花一点时间读官方文档的入门部分,或者用简单的二维示例练手,理解坐标轴、数据格式、循环变量几个概念,再看三维就会非常顺畅。入门直接上手三维其实也可以,但遇到问题排查时基础是否扎实决定了效率。
3. 手把手实现:三维曲线图绘制的全流程实操
3.1 准备一个可编译的最小示例
我的建议是先用一个最简单可行的例子跑通完整流程,再逐渐加上复杂效果。以下这段代码展示了pgfplots绘制三维曲线图的最小结构,使用TikZ的pgfplots库:
\documentclass{standalone} \usepackage{pgfplots} \pgfplotsset{compat=1.18} \begin{document} \begin{tikzpicture} \begin{axis}[ view={60}{30}, xlabel={$x$}, ylabel={$y$}, zlabel={$z$}, ] \addplot3[ mesh, draw=blue, ] coordinates { (0,0,0) (1,1,1) (2,0,2) (3,-1,1) (4,0,0) }; \end{axis} \end{tikzpicture} \end{document}先来解释这段代码里的几个关键部分。view={60}{30}是三维图的视角参数,第一个数60表示在水平面旋转60度,第二个数30表示从水平面上方30度俯视。你可以试着修改这两个数字感受视角变化——我个人喜欢60度和30度,因为三个轴都有一定的投影长度,立体感比较好。
mesh选项把散点数据连接成网格线,这是三维曲线图的常见表达方式之一。draw=blue指定线条颜色,简单直接。你还可以加thick、dashed等样式选项让线条更突出。
xlabel、ylabel、zlabel分别给三个轴添加标签。数学模式中的美元符号让标签能以公式形式呈现,这样下标、希腊字母都可以正常显示。
这段代码在TeX Live环境中是可以直接编译的,我用的是pdflatex,两次编译后输出矢量PDF,插入论文或报告中效果很好。
3.2 绘制一条完整的空间螺旋线
为了说明三维曲线图的表达能力,我拿空间螺旋线作为演示。螺旋线是三维曲线中最经典的形式之一,虽然简单,但足以展示pgfplots处理参数方程的能力。
螺旋线的参数方程是:
- x = cos(t)
- y = sin(t)
- z = t
代码实现有两种方式。第一种是数据点方式,提前用脚本生成坐标数据填入coordinates;第二种是直接利用pgfplots的内置函数计算。
我推荐直接用参数方程声明,这样可维护性更强。示例代码如下:
\documentclass[border=10pt]{standalone} \usepackage{pgfplots} \pgfplotsset{compat=1.18} \begin{document} \begin{tikzpicture} \begin{axis}[ view={60}{30}, xlabel={$x$}, ylabel={$y$}, zlabel={$z$}, domain=0:6*pi, samples=200, xmin=-1.2, xmax=1.2, ymin=-1.2, ymax=1.2, zmin=0, zmax=20, axis lines=box, width=10cm, height=8cm, ] \addplot3[ thick, blue, samples y=0, ] ({cos(deg(x))}, {sin(deg(x))}, {x}); \end{axis} \end{tikzpicture} \end{document}参数方程在pgfplots中是一个很有特色的能力:\addplot3后的坐标位置可以用花括号包裹表达式,按 (x表达式, y表达式, z表达式) 的顺序排列。表达式中的变量x实际上是参数遍历的变量名,这是pgfplots约定的规则,注意不要搞混。
domain=0:6*pi定义参数的取值范围,这里让螺旋线绕三圈;samples=200控制采样点数,采样点数越多曲线越平滑,但编译时间也随之增加。对于螺旋线这种快速变化的曲线,200个点比较合适,肉眼几乎看不出折线感。
axis lines=box把坐标轴显示成完整的立方体框,这是三维图常见的样式,相比默认的axis线样式更清晰,可以明确看出图形在三维空间中的位置。
编译后的图像中,一条蓝色螺旋线沿着z轴方向上升,旋转三圈,线条流畅,背景是标准的三维坐标轴。这个结构可以扩展为任何参数曲线——只需要改方程表达式即可。
3.3 在一张图内绘制多条三维曲线
实际应用中我很少只画一条曲线,更多情况是把多条曲线放在同一张图里对比。pgfplots完全支持这一操作,在同一个axis环境内并列多个\addplot3命令即可。
比如我想在同一张图中对比两条不同的螺旋线,一条半径不变,一条半径随高度衰减:
\begin{axis}[ view={60}{30}, xlabel={$x$}, ylabel={$y$}, zlabel={$z$}, domain=0:4*pi, samples=150, axis lines=box, legend pos=outer north east, ] \addplot3[ thick, blue, ] ({cos(deg(x))}, {sin(deg(x))}, {x}); \addlegendentry{等半径螺旋线} \addplot3[ thick, red, dashed, ] ({cos(deg(x))*exp(-0.1*x)}, {sin(deg(x))*exp(-0.1*x)}, {x}); \addlegendentry{衰减螺旋线} \end{axis}多条曲线的配色和线型可以灵活调整,我在对比场景中使用一实一虚、颜色分开的方案,既清晰又不混淆。图例设置为legend pos=outer north east,放在图的右上角外侧,不会遮挡数据区域。
这是三维曲线图的一个大优势:二维只能表现两个变量之间的关系,拓展到三维后,可以直观展示三个变量之间的复杂联系。多条曲线同时呈现时,数据之间的关系一目了然,这对科技论文和实验报告的价值非常大。
3.4 特别注意:三维曲线与三维曲面是两回事
把三维曲线图说清楚之后,特别要区分一个概念:三维曲线图和三维曲面图虽然都属于三维图形范畴,但它们是不同的东西。
三维曲线图描述的是空间中的一条或几条线,数据是线状的,使用\addplot3 coordinates { ... }或参数方程即可。三维曲面图描述的是一个面,数据必须是网格状的,x和y组成网格坐标,z对应每个网格点的高度。
如果你把曲面数据用曲线图的语法去写,pgfplots会报错或者只绘制边界线,无法形成完整的面。曲面图在pgfplots中使用\addplot3[surf]选项,数据通常以矩阵格式或者外部数据文件形式提供,这个和曲线图有本质区别。
我见过不少初学者把两者混淆:试图用coordinates写曲面数据,或者在surf图形中用线性数据,导致结果非常奇怪。这两周我在某模拟项目中也遇到过一次这样的混淆场景,后来把数据重新整理成网格格式后一切正常。建议画图前先想清楚:你的数据是线状的还是面状的?这个判断决定了使用哪种语法,也决定了数据的组织方式。
4. 进阶美化:让三维曲线图达到论文出版级质量
4.1 坐标轴样式定制与标注
论文和报告中,坐标轴是展示数据严肃性的门面。pgfplots提供了非常细粒度的控制选项,可以有效统一图的风格。
轴标签(xlabel、ylabel、zlabel)、刻度(xtick、ytick、ztick)、网格(grid)、坐标轴线条粗细(axis line style)都可以分别设置。我的常用配置如下:
\begin{axis}[ view={65}{25}, width=12cm, height=9cm, xlabel={时间 $t$ (s)}, ylabel={振幅 $A$ (mm)}, zlabel={位移 $s$ (mm)}, xtick={0, 0.5, 1.0, 1.5, 2.0}, ytick={-1, 0, 1}, ztick={-2, 0, 2}, grid=both, grid style={gray!30, dashed}, axis lines=box, every axis x label/.style={at={(ticklabel cs:0.5)}, anchor=near ticklabel}, every axis y label/.style={at={(ticklabel cs:0.5)}, anchor=near ticklabel}, every axis z label/.style={at={(ticklabel cs:0.5)}, anchor=near ticklabel}, ]轴标签位置是个细节问题。默认位置经常和刻度数字重叠或太靠近坐标轴,这时可以用every axis label系列选项手动调整。坐标轴标签使用物理量名称加上单位,对论文质量的提升非常明显。
刻度值的设置建议根据数据范围合理选择步长,尽量不要让pgfplots自动生成过密的刻度。三维图的刻度太密会看起来非常杂乱,而且旋转后容易重叠。我一般手动指定3到5个刻度,保持图的简洁性。更少反而更清晰,这是三维图的一个常见取舍。
4.2 colormap与颜色映射
三维曲线图虽然主要是线状图,但颜色也可以承载数据信息。pgfplots的colormap机制不仅可以用于曲面,也可以沿曲线按参数值变化颜色。这本质上是用颜色表达第四维信息。
曲线按高度着色,既保持了图的简洁,又能额外呈现数据的分布趋势。实现方式如下:
\addplot3[ mesh, line width=1pt, point meta=z, colormap/viridis, ] coordinates { (0,0,0) (1,1,0.5) (2,0,1.5) (3,-1,2.8) (4,0,4.0) (5,1,5.5) };这里mesh在曲线图中会把每条线段按point meta=z的值分配颜色,颜色从colormap中插值取得。colormap/viridis是pgfplots内置的多个colormap之一,色盲友好,对比度适中,我非常推荐。如果追求更强的视觉冲击力,也可以换用colormap/jet或colormap/hot,但要注意风格与文档整体调性匹配。
point meta可以设定为z值,也可以设定为其他数据值,甚至是自定义表达式(例如距离原点的长度),灵活性极高。比如在物理场景中,你完全可以让曲线颜色随着速度变化而上色,而不仅限于Z轴坐标。
4.3 光照与阴影效果在曲线图中的巧妙运用
很多人觉得光照效果只适用于曲面图,其实pgfplots对曲线图也提供了光照模拟的能力,只是效果比较微妙。设置faceted color配合point meta,可以让曲线在空间中的朝向通过颜色深浅来表现,增强立体感。
但根据我的经验,曲线图的光照效果要克制使用。曲线本身就是细线条,过度添加光照效果会让线条颜色不均匀,反而干扰数据读取。除非是特别需要强化立体感的场景,否则我更推荐用线条粗细和颜色变化来区分信息,而不是依赖光照模拟。
真正提升三维曲线图质感的地方是视角选择。不同的view参数会让空间曲线呈现完全不同的观感。比如一条空间曲线,在某些角度看起来像二维投影,换一个角度立体感就出来了。我常用的做法是设置多个视角预览,选择最能体现曲线特征的那个。pgfplots支持在一个tikzpicture内并列多个axis,实现子图对比,也可以利用\foreach循环批量生成不同视角的图,快速筛选。
一个小技巧:如果你不确定选择哪个视角,就用view={60}{30}作为起点,这是视觉平衡比较好的黄金视角。之后在10度范围内微调仰角,观察图形变化再定稿。
5. 复杂场景实战:参数曲面与投影曲线的组合呈现
5.1 将三维数据文件导入pgfplots
在工程实践中,数据通常不是手工输入,而是由模拟或实验软件生成。pgfplots支持直接从外部文件读取数据,这对真实场景至关重要。
文件格式一般是以空格或逗号分隔的纯文本表格。假设有一个data3d.dat文件,内容如下:
0 0 0 1 0 0.5 2 0 1.2 3 0 2.0 ...在LaTeX中读取该文件并绘图:
\addplot3[ thick, blue, ] table {data3d.dat};如果文件每一列有不同的含义,可以用x index、y index和z index指定列索引,也可以直接用表头名称。比如:
\addplot3[thick, red] table[x=time, y=amplitude, z=displacement] {simulation.dat};从文件读取数据的优势在于:数据更新后只需替换文件内容,重新编译LaTeX即可,不需要修改任何绘图代码。这种工作流在数据频繁更新的模拟项目中极其顺手,也是我弃用外部绘图工具的关键原因之一。数据文件与LaTeX源码分离,版本管理更加清晰。
5.2 在曲面图基础上叠加空间曲线
复杂的三维图往往需要同时展示多个层次的几何信息。一个典型场景:在一个参数曲面上叠加一条空间曲线作为轨迹线。这种组合图能表达丰富的信息——比如在某个地形曲面上标注一条路径。
pgfplots实现这一组合非常高效,只需在一个axis内并列smooth与surf两个addplot命令:
\begin{axis}[ view={60}{25}, xlabel={$x$}, ylabel={$y$}, zlabel={$z$}, domain=0:4, samples=30, z buffer=auto, ] % 曲面 \addplot3[ surf, shader=interp, opacity=0.6, ] {sin(deg(x)) * cos(deg(y))}; % 曲面上的路径曲线 \addplot3[ thick, red, samples y=0, samples=100, ] ({2 + 2*cos(deg(x))}, {2 + 2*sin(deg(x))}, {sin(deg(2+2*cos(deg(x)))) * cos(deg(2+2*sin(deg(x))))}); \end{axis}关键设置是z buffer=auto,它保证了曲面和曲线之间的正确遮挡关系。如果曲线位于曲面前方,它会覆盖在曲面上;若位于曲面后方,则会被曲面遮挡。这个机制是生成自然三维感的关键,务必开启。
opacity=0.6让曲面半透明,这样即使曲线在曲面后方也能隐约看到轮廓,这对复杂场景有非常大的帮助。shader=interp让曲面颜色过渡更柔和,不显示数据网格线。
5.3 处理多个图的并排对比
科研和工程报告中经常需要并列展示多个三维图作对比。pgfplots既支持单个tikzpicture内多个axis子图,也支持使用LaTeX的minipage或subfigure环境并排。
我常用的方式是在同一个tikzpicture中设置\nextgroupplot(需要加载groupplots库):
\usepackage{pgfplots} \pgfplotsset{compat=1.18} \usepgfplotslibrary{groupplots} \begin{tikzpicture} \begin{groupplot}[ group style={group size=2 by 1, horizontal sep=1.5cm}, view={60}{30}, width=7cm, height=6cm, ] \nextgroupplot[xlabel=$x$, ylabel=$y$, zlabel=$z$] \addplot3[mesh, blue] coordinates {(0,0,0) (1,1,1) (2,0,2)}; \nextgroupplot[xlabel=$x$, ylabel=$y$, zlabel=$z$] \addplot3[mesh, red] coordinates {(0,0,0) (1,-1,1) (2,0,2)}; \end{groupplot} \end{tikzpicture}group size=2 by 1表示一行两列。子图之间的坐标轴对齐是groupplots自动处理的,这比手动调节多个axis的尺寸和位置要省心太多。我在写对比型报告和论文时,几乎全部使用groupplots来组织多图。
5.4 动画:给三维曲线图加上时间维度
严格来说这不算静态绘图,但pgfplots配合animate宏包可以生成动态的三维曲线图。原理很简单:同一张图在不同帧中改变某个参数(例如相位),然后逐帧渲染。
% 需要额外加载 animate 宏包 \documentclass{standalone} \usepackage{pgfplots} \usepackage{animate} \pgfplotsset{compat=1.18} \begin{document} \begin{animateinline}[controls, loop]{24} \multiframe{36}{r=0+10}{ \begin{tikzpicture} \begin{axis}[ view={60}{30}, domain=0:360, xlabel={$x$}, ylabel={$y$}, zlabel={$z$}, width=8cm, height=7cm, ] \addplot3[ thick, blue, ] ({cos(x)}, {sin(x)}, {sin(x+\r)}); \end{axis} \end{tikzpicture} } \end{animateinline} \end{document}这里\multiframe{36}{r=0+10}表示生成36帧动画,每帧参数r增加10度。曲线形状随时间连续变化,演示空间波的传播等动态物理现象非常直观。生成的是PDF动画(在PDF阅读器中播放),也可以在导出视频时逐帧截取。
不过要提醒一句:动画PDF在部分阅读器或期刊投稿系统中可能不显示,实际应用前确认目标平台的兼容性再决定是否采用。
6. 调试与避坑:从我踩过的错误里提炼的实用清单
6.1 常见错误速查表
| 错误现象 | 原因 | 解决方案 |
|---|---|---|
| 编译报错"Package pgfplots Error: Sorry, I could not determine the data format" | 数据格式疑似错误,比如坐标只有两列却使用了addplot3 | 检查coordinates中每个点的维度数,确保三元组格式正确 |
| 三维图显示为平面图 | 没有正确设置三维视角或数据本身同一维度恒定 | 在axis选项中显式设置view={60}{30};检查z值是否有变化 |
| 曲面图变成一堆散乱线条 | 没有开启z buffer或未使用surf选项 | 添加z buffer=auto;确认曲面用\addplot3[surf]声明 |
| 编译时间过长 | 采样点数过多,或图形尺寸过大 | 降低samples值,优先尝试samples=100~200 |
| 坐标轴标签重叠 | 默认标签位置不适合当前视角 | 手动调整标签锚点位置,用every axis label选项 |
| 多条曲线图例混乱 | 图例名称没有绑定到对应addplot | 用addlegendentry按顺序绑定;或使用legend entries选项 |
| 字体不匹配 | LaTeX文档字体和图中字体样式不一致 | 在axis选项统一设置字体样式,如font=\small |
| 图片宽度超出页面 | 未设置尺寸或设置过大 | 显式设置width和height;或使用scale=0.8 |
6.2 关于compat版本的强制提醒
这是pgfplots使用中最高频的坑:\pgfplotsset{compat=1.18}这一行看似可有可无,但如果没有指定compat版本,pgfplots会进入兼容模式,很多三维图形选项的行为会退化到老版本状态,尤其影响view的坐标标签位置、轴范围推断方式等。
我出现过一次记忆深刻的错误:一个三维图在本地编译正常,换到另一台机器上就出现坐标轴标签位置偏移,最后发现就是不同tex发行版中compat设置不一致导致的。建议所有文档统一在导言区设置一个明确的compat版本,并且在自己的常用发行版上测试。这在合作写作或多终端写作场景中非常重要。
6.3 视角和曲线外观的实际迭代经验
调试三维曲线图,视角选择往往是耗时最多的环节。坐标轴标题、刻度、曲线的遮挡关系在不同视角下视觉效果差异巨大。我总结的调试流程大致如下:
- 先用
view={60}{30}渲染第一版,检查数据本身是否有误。 - 观察三个轴的可见性,确认没有axis被完整遮挡。
- 如果曲线某些部分被前景遮挡、关键特征不清晰,微调仰角(第二参数)多试几个值(20、30、40),再看特征显露情况。
- 旋转角(第一参数)调整整体构图方向,我一般让它与文档中其他图的风格保持一致。
- 锁定视角后再进行颜色、线宽、标签等美化工作。
如果在最终版本中换了视角,标签位置可能也需要重新微调。这个迭代过程虽然琐碎,但直接决定图的质量。熟悉之后,从初稿到定稿大概只需要几次编译就能完成。
6.4 编译性能优化
大型三维图(特别是高采样曲面)编译耗时可能惊人。我建过一些包含几十张三维图的文档,在普通配置电脑上编译一次需要好几分钟。压缩这一时间,我有几个心得:
- 将
preview功能与standalone文档类配合:单张图单独编译成PDF,在主文档中直接插入结果PDF,主文档编译时间大幅减少。 - 编译单张图期间,可以使用
\begin{tikzpicture}加上[trim left, trim right]选项裁剪空白区域,内容更紧凑。 - 绘制试验阶段(尤其是频繁调整视角时),使用
draft模式或降低采样数。等所有参数定稿后再恢复高采样重新编译最终版。 - 如果文档非常大,也可以把pgfplots图预编译为独立PDF并用
\includegraphics引入,效果一致,但主文档编译速度能快好几倍。
6.5 一个容易被忽视的细节:坐标轴比例与等轴设置
默认情况下,pgfplots三个坐标轴的尺度是独立的,各自缩放以适应取值范围。这在数据幅度相差较大时非常方便,但有些场合需要三个轴等比例显示——例如展示几何形状时,非等比缩放会扭曲形状,引起误读。
设置等轴比例的方法是添加axis equal选项。这会强制x、y、z三个轴的单位长度一致,图形形状不会再被拉伸。
不过要注意,axis equal会大幅压缩绘图区域,特别是在高度和水平范围相差很大的时候。我的经验是:涉及螺旋线、椭圆、球面等几何形状时使用axis equal;单纯展示数据趋势和变化时,使用独立缩放即可。这两类语义在科学文献中区别明显:前者关注形状,后者关注变化。
7. 我的习惯与经验:一个轻量高效的三维图工作流
在这里分享一下我目前稳定使用的工作流,给正准备开始使用pgfplots三维绘图的读者参考。
绘图源码和数据文件分开管理是第一步。数据文件统一放在data/目录下,绘图代码按照文档章节组织成独立的TeX片段。这样无论是改数据还是改样式,可定位性很强。团队合作时,同事只需要修改数据文件,不需要动绘图代码,就能获得更新后的图。
第二步是建立自己的样式模板。我会在导言区定义一组全局的axis样式,把所有常用的三维图配置(字体、线宽、网格样式、图例位置、边框风格)固定下来。这样同文档中的所有图自动保持高度一致的风格,视觉上更像一个整体。这比每张图重复写大量配置要省心得多。
关于配色方案,我建议选一个主色和一个辅色,不要每张图都用彩虹色。我的倾向是:单曲线图用深蓝色系;多曲线对比时用蓝、红、青三色交替,外加线型的区别(实线、虚线、点划线)。完全通过颜色区分在黑白打印时会失效,所以线型上的区分不可省略。
另外,坚持使用无色盲友好的colormap是个好习惯。这在轮换colormap时多花一点时间,但能让图更易读、更专业。
在实际操作中我发现,pgfplots三维图在“学习-应用-调试-复用”这个循环中,真正花时间的其实不是语法本身,而是数据准备和视角调试。语法是有限的知识,掌握了以后就是固定复用的工具。数据准备涉及真实业务逻辑,每个项目的差异都很大;视角调试则依赖美学经验和不断的预览对比,无法用书面规则完全概括。如果时间有限,建议多投入在前两者上:把数据结构梳理清楚,图上呈现的就必然清晰;把好视角多看几遍,审美直觉会逐步建立起来。
最后再分享一个小技巧:当你面对一张复杂的空间关系图无法确定如何取舍时,可以先把所有该展示的要素全部放上去,然后逐层精简——删掉网格线、减掉非关键刻度、去掉辅助曲线,直到信息量刚饱和为止。好图是“减”出来的,不是“加”出来的,这一点在三维图中尤其明显。