我想比较一下 TikZ 和 Asymptote 在二维和三维函数绘图以及其他通用简单绘图方面的能力。
TikZ 相对于 Asymptote 的优势是什么?
答案1
我都用过,但我更喜欢 TikZ。
- TikZ 和
asymptote
同样强大,但编程asymptote
更容易。 - TikZ 具有可用于强制实施一致外观和感觉的样式。例如,您可以为帮助行定义样式。如果
asymptote
您没有样式。 asymptote
只能通过编写asymptote
程序、生成图片并包含图片来使用。您无法引用图片中的内容。TikZ 则不同。您可以在某些类型的 TikZ 图片中定义标签,并在另一个 TikZ 图片中引用它。这允许您从 TikZ 图片的一个特定部分到图片的另一部分TikZ
或到页面的特定位置(中心、北、西南……)绘制线条。再举一个例子,您可以定义 TikZ 图片的基线,以便整齐地对齐它们。- 要了解上一点的优势,请考虑该
pgfkeys
软件包,它提供了一些非常有用的工具来解析 key=value 列表。即使您不想绘制任何东西,您的 LaTeX 代码也可以从该软件包中受益。Joseph Wright 已使用pgfkeys
他的软件包在类和软件包中提供 -style 解析pgfopts
。很难看出您的 LaTeX 编程如何从(外部)asymptote
程序中受益(除非允许 shell 转义,这会带来麻烦)。另一个有趣的发展是 TikZ 的面向对象编程,当我有更多时间时,我想进一步探索一下。(事实上,pgf
正确探索 TikZ/ 手册是我最想做的事情......) - TikZ 图片与主 LaTeX 文档位于同一环境中,因此 TikZ 中使用的任何 LaTeX 命令都使用与主 LaTeX 文档相同的定义。但
asymptote
情况并非如此,您必须做额外的工作来了解asymptote
LaTeX 命令的定义。这对我来说非常重要,因为我经常beamer
在不同模式下使用该软件包。根据模式的不同,输出中使用不同的字体。使用 TikZ 会自动选择字体。要asymptote
做到这一点需要额外的工作。
答案2
根据要求,我将我的评论转化为答案。
我非常喜欢tikz-3dplot
包,附加到 tikz 的 3D 功能。
您确实应该仔细阅读手册来了解它的功能,但这里是一些示例:
\documentclass{minimal}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\newcommand{\ve}[1]{\ensuremath{\mathbf{#1}}}
\newcommand{\ud}[0]{\mathrm{d}}
\tikzset{
vector/.style = {
thick,
> = stealth',
},
axis/.style = {
very thin,
> = stealth',
},
}
\begin{document}
\tdplotsetmaincoords{60}{110}
\begin{tikzpicture}[tdplot_main_coords,scale=0.8]
% draw axes
\draw[axis,->] (0,0,0) coordinate (O) -- (5,0,0) node[anchor=north east]{$x$};
\draw[axis,->] (0,0,0) -- (0,4.95,0) node[right,anchor=west]{$y$};
\draw[axis,->] (0,0,0) -- (0,0,4.95) node[anchor=south]{$z$};
% draw
\draw[vector,->] (O) -- node[above left]{\ve{v}} (2,4,3) coordinate (V);
\draw[vector,->] (O) -- node[below right]{$\ve{v}_x$}(2,0,0)node[left]{$2$};
\draw[vector,->] (O) -- node[below]{$\ve{v}_y$}(0,4,0)node[below right]{$4$};
\draw[vector,->] (O) -- node[left]{$\ve{v}_z$}(0,0,3)node[above left]{$3$};
\draw[densely dotted] (0,4,0) -- (2,4,0) -- (2,0,0);
\draw[densely dotted] (V) -- (0,4,3) -- (0,0,3) -- (2,0,3) -- (2,0,0);
\draw[densely dotted] (2,0,3) -- (V) -- (2,4,0);
\draw[densely dotted] (0,4,0) -- (0,4,3);
\foreach \s in{1,2,3,4}{
\draw[fill](\s,0,0)circle(0.5pt);
\draw[fill](0,\s,0)circle(0.5pt);
\draw[fill](0,0,\s)circle(0.5pt);
}
\end{tikzpicture}
\bigskip
\tdplotsetmaincoords{70}{120}
\tdplotsetrotatedcoords{90}{90}{90}
\begin{tikzpicture}[tdplot_main_coords,scale=0.5]
\draw (0,0,0) -- ++(0,-2.3,0) node[above left]{$-$};
% draw a condensor plate
\draw[fill=lightgray] (-1.5,0,-1.5)--(-1.5,0,1.5)--(1.5,0,1.5)--(1.5,0,-1.5)--cycle;
\draw[fill=lightgray] (1.5,0,-1.5)--(1.5,-0.2,-1.5)--(1.5,-0.2,1.5)--(1.5,0,1.5)--cycle;
\draw[fill=lightgray] (1.5,-0.2,1.5)--(-1.5,-0.2,1.5)--(-1.5,0,1.5)--(1.5,0,1.5)--cycle;
\def\q{-2.3}
% draw surface
\draw (0,-0.5*\q,0) coordinate(R);
\tdplotdrawarc[tdplot_rotated_coords,fill opacity=0.5,fill=lightgray!30,draw=black]{(R)}{3}{0}{360}{}{}
\draw[tdplot_rotated_coords](R)++(-110:3) node[below left]{$S_2$};
\draw[tdplot_rotated_coords](R)++(70:3) node[above right]{$C$};
% draw second condensor plate
\draw[fill=lightgray] (-1.5,0-\q,-1.5)--(-1.5,0-\q,1.5)--(1.5,0-\q,1.5)--(1.5,0-\q,-1.5)--cycle;
\draw[fill=lightgray] (1.5,0-\q,-1.5)--(1.5,-0.2-\q,-1.5)--(1.5,-0.2-\q,1.5)--(1.5,0-\q,1.5)--cycle;
\draw[fill=lightgray] (1.5,-0.2-\q,1.5)--(-1.5,-0.2-\q,1.5)--(-1.5,0-\q,1.5)--(1.5,0-\q,1.5)--cycle;
\draw (0,-\q,0)--++(0,2,0)node[above right]{$+$};
\end{tikzpicture}%
\begin{tikzpicture}[tdplot_main_coords,scale=0.5]
\tdplotsetrotatedcoords{90}{90}{90}%
\draw (0,0,0)--++(0,-2.3,0)node[above left]{$-$};
% draw condensore plate
\draw[fill=lightgray] (-1.5,0,-1.5)--(-1.5,0,1.5)--(1.5,0,1.5)--(1.5,0,-1.5)--cycle;
\draw[fill=lightgray] (1.5,0,-1.5)--(1.5,-0.2,-1.5)--(1.5,-0.2,1.5)--(1.5,0,1.5)--cycle;
\draw[fill=lightgray] (1.5,-0.2,1.5)--(-1.5,-0.2,1.5)--(-1.5,0,1.5)--(1.5,0,1.5)--cycle;
% draw surface
\def\q{-2.3}
\def\R{3}
\draw (0,-0.5*\q,0) coordinate(R);
\tdplotdrawarc[tdplot_rotated_coords,fill=lightgray,fill opacity=0.5,draw=black]{(R)}{\R}{0}{360}{}{}
\draw[tdplot_rotated_coords](R)++(-110:\R) node[below left]{$S_1$};
\draw[tdplot_rotated_coords](R)++(70:\R) node[above right]{$C$};
\tdplotsetrotatedcoords{0}{70}{90}
\draw[tdplot_rotated_coords](R)++(90:\R) coordinate (A) circle(0.5pt);
\draw[tdplot_rotated_coords,fill opacity=0.5,fill=lightgray!30](A)arc(90:270:\R);
\tdplotsetrotatedcoords{90}{90}{90}
\tdplotdrawarc[tdplot_rotated_coords,fill=lightgray!10,draw=black]{(R)}{\R}{0}{360}{}{}
\begin{scope}
% draw condensor plate again, inside (clip outside)
\clip[tdplot_rotated_coords] (R)++(0:\R) arc (0:360:\R);
\draw[fill=lightgray] (-1.5,0,-1.5)--(-1.5,0,1.5)--(1.5,0,1.5)--(1.5,0,-1.5)--cycle;
\draw[fill=lightgray] (1.5,0,-1.5)--(1.5,-0.2,-1.5)--(1.5,-0.2,1.5)--(1.5,0,1.5)--cycle;
\draw[fill=lightgray] (1.5,-0.2,1.5)--(-1.5,-0.2,1.5)--(-1.5,0,1.5)--(1.5,0,1.5)--cycle;
\end{scope}
\draw[tdplot_rotated_coords] (R)++(0:\R) arc (0:360:\R);
% draw second condensor plate
\draw[fill=lightgray] (-1.5,0-\q,-1.5)--(-1.5,0-\q,1.5)--(1.5,0-\q,1.5)--(1.5,0-\q,-1.5)--cycle;
\draw[fill=lightgray] (1.5,0-\q,-1.5)--(1.5,-0.2-\q,-1.5)--(1.5,-0.2-\q,1.5)--(1.5,0-\q,1.5)--cycle;
\draw[fill=lightgray] (1.5,-0.2-\q,1.5)--(-1.5,-0.2-\q,1.5)--(-1.5,0-\q,1.5)--(1.5,0-\q,1.5)--cycle;
\draw (0,-\q,0)--++(0,2,0)node[above right]{$+$};
\end{tikzpicture}
\bigskip
\tdplotsetmaincoords{90}{120}
\tdplotsetrotatedcoords{90}{90}{0}
\begin{tikzpicture}[tdplot_main_coords,scale=1.6]
% praw circular plate
\tdplotdrawarc[tdplot_rotated_coords,fill=lightgray,draw=lightgray,line width=0pt]{(0,-0.5,0)}{1}{0}{360}{}{}
\tdplotdrawarc[tdplot_rotated_coords,fill=lightgray]{(0,-0.5,0)}{1}{180}{360}{}{}
\tdplotdrawarc[tdplot_rotated_coords,fill=lightgray]{(0,0,0)}{1}{0}{360}{}{}
\draw[yshift=1cm](0,0)--(0.5,0);
\draw[yshift=-1cm](0,0)--(0.5,0);
\draw[help lines] (0,0,0)--(-9,0,0)node[right]{$s$};
\draw[help lines] (-6,0,0)--(-6,0,1.5);
\draw[fill](-6,0,0) circle (0.5pt) node[above,fill=white]{$P(a)$}node[below]{$q$};
\draw[fill](-6,0,0) circle (0.5pt);
% draw inner circle
\tdplotdrawarc[tdplot_rotated_coords,help lines]{(0,0,0)}{0.6}{0}{360}{}{}
\draw[tdplot_rotated_coords,<->](0,0,0)--node[below]{$r$}(0.05,-0.6);
\draw[tdplot_rotated_coords,<->](0,0,0)--node[right]{$R$}(0.7,0.7);
% dtheta angle
\draw[tdplot_rotated_coords](-0.42,-0.42,0)--(-0.57,-0.57,0);
\draw[tdplot_rotated_coords](-0.6,0,0)--(-0.8,0,0);
\tdplotdrawarc[tdplot_rotated_coords]{(0,0,0)}{0.8}{180}{225}{}{}
\tdplotdrawarc[tdplot_rotated_coords]{(0,0,0)}{0.6}{180}{225}{}{}
\draw[tdplot_rotated_coords,help lines](0,0,0)--(-1.1,-1.1,0);
\draw[tdplot_rotated_coords,help lines](0,0,0)--(-1.5,0,0);
\tdplotdrawarc[tdplot_rotated_coords,<->]{(0,0,0)}{1.4}{180}{225}{above left}{$\ud\theta$}
% annotate stuff
\draw[tdplot_rotated_coords] (-0.65,-0.25,0) coordinate (X);
\draw[vector,->] (X)--node[above]{$x$}(-6,0,0);
\draw[<->] (0,0,1.2)--node[above]{$a$}(-6,0,1.2);
\draw (-0.2,0,-1) node[right]{$S$};
\draw[vector,->] (-6,0,0)--(-7,0,0)node[below]{$\ve{K}$};
\draw[vector,->] (-6,0,0)--(-8,0,0)node[below]{$\ve{E}$};
\tdplotsetrotatedcoords{0}{90}{90}
\draw(-6,0,0) coordinate (Q);
\tdplotdrawarc[tdplot_rotated_coords]{(Q)}{1.2}{170}{180}{left}{$\phi$}
\end{tikzpicture}
\end{document}
(请注意,上述代码只是复制粘贴的代码,有时来自相当旧的文档,因此可能其中有一些效率低下的代码,因为那时我还不太擅长使用 TikZ)。编译上述文档可获得以下数据:
您可以使用 TikZ 完成几乎所有操作,尽管有时操作起来会非常棘手。我记得我曾经以 3D 形式绘制过 Stern Gerlach 实验(形状奇怪的磁铁及其磁场线),但我丢失了代码。示例还有一个 3D 类别,其中包含大量可以在 TikZ 中完成的 3D 图像示例。
答案3
这是一篇老帖子,但我认为答案没有足够强烈地强调,有时,由于缺乏真正的 3D 支持,Asymptote 是无法避免的,正如零计数。
更准确地说,如果我没有记错的话,tikz-3dplot
其他 LaTeX 软件包会添加元素,就像它们出现在代码中一样。如果一个元素有时应该在前台,该怎么办和有时在后台?嗯,它不起作用。
两个例子来说明我的观点:
- 一个来自 TeXample 的:关联当你仔细观察黑色体积时,你会发现它总是落后于其他曲线,这是不应该的。这在那里可能是可以接受的,但更普遍地说,这可能是一个严重的缺点。
- 我自己的另一个例子(带有
pgfplots
),是蓝色曲线错误地覆盖了红色曲线:
此外,嵌入 3D 对象的可能性也pdf
为 Asymptote 带来了巨大优势:可以在 pdf 文件中使用鼠标交互操作 3D 图(参见中华人民共和国了解更多信息)。例如参见这个文件,遗憾的是只能使用 Adobe Reader 9+ 打开。请注意,据我所知,在执行此操作时必须对 3D 对象进行栅格化。
编辑为了说明我的第一点,这是对同一 3D 对象的略微不同的视图,其中Asymptote
。主要要注意的是曲线有时在顶部,有时在后面,这是 Tikz 和 pgfplots 的主要缺陷。
根据我最近的经验进行小总结:
Tikz
:
- 优点:更简单
- 缺点:虚假 3D,物体要么完全在前景,要么完全在背景中
Asymptote
:
- 优点:真正的 3D
- 优点:透视图和正交图均可
- PRO:可以在 PDF 中嵌入 3D 对象
prc
- 缺点:需要栅格化
- 缺点:渲染有时会包含不必要的黑色条纹(有一些解决方案可以避免这种情况,但会减慢工作流程)
为了简单起见,我建议使用 Tikz 和 pgfplots(只要它能满足您的需求),否则就换成渐近线!
答案4
更新:
- 令我大为惊讶的是,Christian Feuersänger 成功地将贝塞尔曲面纳入了他出色的
pgfplots
软件包中;请参阅下面的评论。我仍然更喜欢 Asymptote 风格的照明,它更“逼真”;截至撰写本文时,它pgfplots
支持色彩图(即由用户提供的三维空间函数确定的颜色)和明确描述的颜色,但无法计算光和阴影。 - 关于文档:我一直在写教程适用于 Asymptote 的教程,该教程以第一个 TikZ 教程为蓝本(但我希望没有达到抄袭的程度)。我认为关于二维绘图的章节已经足够完整,可以使用,并且比官方 Asympote 手册更加用户友好。三维章节还有很长的路要走,但我敢说它们已经很有帮助了。欢迎提供反馈。
我想补充一些似乎还没有被提出的观点:
- 文档:
TikZ
文档很棒。Asymptote
文档还可以,但可以更加方便用户使用。除了源代码外,还有很多方面Asymptote
没有记录。 a
模块化:在 Asymptote 中,用、b
和等名称定义事物更加容易和自然,而f
不必担心这些名称会以某种方式干扰其他事物。创建一个对象然后以多种不同方式使用它也更加容易,尽管我认为TikZ
一旦面向对象方面更充分地融入文档中,这里的情况就会得到改善。- 贝塞尔曲面:使用 Asymptote,可以绘制一个看起来非常平滑的复杂 3D 曲面(网格线相交处没有拐角)。我无法想象任何基于 TeX 的绘图程序能够模仿这一壮举,即使调用 gnuplot 也是如此。同样,Asymptote 可以提供复杂的阴影(具有镜面反射等),这几乎肯定超出了 TikZ 或任何基于 TeX 的系统的范围。例如,请参见克莱因瓶的图片渐近线画廊。