我欣赏 LaTeX 的所见即所得功能,但随着时间的推移,我开始怀疑纯图形的所见即所得理念是否仍然合理。今天我花了一个多小时才用下面的代码(以及另外两个非常相似的代码)实现了下面的图片。
在我的联想 ThinkPad L530(Ubuntu 和 Openbox)上,每次编译都要花费 15 秒以上的时间,而将样本从 2000 减少到 500 也需要 3 秒以上的时间,结果更糟糕。我仍然对这幅图像不满意,因为抛物线与水平线和垂直线的交点太尖锐了。以下是我的问题:
- 我应该使用什么正确的代码才能制作出快速编译且美观的图片?
- 您通常需要多长时间才能为这样的图像提供正确的代码?
- 对于此类图片,您会推荐哪种所见即所得的 tikz 替代品?
感谢您的耐心等待。
\documentclass{standalone}
\usepackage{tikz,pgfplots}
\pgfplotsset{compat=1.10}
\usepgfplotslibrary{fillbetween}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis lines=middle,
axis line style=->,
xmin=-.4,xmax=1.4,
ymin=-.4,ymax=2.4,
x=3cm,
y=3cm,
xlabel=$p$,
ylabel=$s$,
]
\addplot[name path=A,black,restrict x to domain=-0.001:0.359, samples= 2000] {2};
\addplot[name path=B,black,restrict x to domain=-0.001:0.359, samples= 2000] {1+0.5*x};
\addplot[gray!40] fill between[of=A and B];
\addplot[name path=C,black,restrict x to domain=0.349:1.001, samples= 2000] {2};
\addplot[name path=D,black,restrict x to domain=0.349:1.001, samples= 2000] {2*sqrt(x)};
\addplot[gray!40] fill between[of=C and D];
\addplot[restrict x to domain=-0.001:1.001, samples= 2000, smooth,line width=0.35mm, -]{2*sqrt(x)};
\addplot[restrict y to domain=-0.001:2.001, samples= 2000, smooth,line width=0.35mm, -]({0},{x});
\addplot[restrict x to domain=-0.001:1.001, samples= 2000, smooth,line width=0.35mm, -]{2};
\addplot[restrict x to domain=-0.301:1.301, samples= 2000, smooth,line width=0.15mm, -]{1+0.5*x};
\end{axis}
\end{tikzpicture}
\end{document}
答案1
\documentclass[border=3mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usepgfplotslibrary{fillbetween}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis lines=middle,
axis line style=->,
xmin=-.4,xmax=1.4,
ymin=-.4,ymax=2.4,
x=3cm,
y=3cm,
xlabel=$p$,
ylabel=$s$,
samples=100% <--- moved here
]
\addplot[name path=A,domain=0:0.36] {2};
\addplot[name path=B,domain=0:0.36] {1+0.5*x};
\addplot[gray!40] fill between[of=A and B];
%
\addplot[name path=C,domain=0.35:1] {2};
\addplot[name path=D,domain=0.35:1] {2*sqrt(x)};
\addplot[gray!40] fill between[of=C and D];
\addplot[domain=0:1, line width=0.35mm]{2*sqrt(x)};
\addplot[domain=0:2, line width=0.35mm]({0},{x});
\addplot[domain=0:1, line width=0.35mm]{2};
\addplot[domain=-0.3:1.3, line width=0.15mm]{1+0.5*x};
\end{axis}
\end{tikzpicture}
\end{document}
我做了以下更改:
- 将样本数量减少到 100,并将声明移至
axis
选项(为了缩短代码) - 删除
smooth
选项 - 替换
restrict x to domain
为domain
- 域的四舍五入范围(从
-0.001
到0
等)
经过这一更改后,我的旧电脑上的计算时间减少了约 4 秒,并且生成的图像(符合我的口味)看起来更好 :-)
附录:
正如所指出的谢尔盖·戈洛万在下面的评论中,为了在域上绘制函数平方根函数,0:1
将其绘制为参数形式的反函数是合理的。
由于平方根函数在零附近有无穷导数,因此很难画好它,也就是说,你需要很多样本点。反函数在原点的导数为零,因此可以用很少的样本来画出它。例如,仅用 25 个样本,使用反函数的结果与使用 200 个样本的正函数的结果几乎相同。
\documentclass[border=3mm]{standalone}
\usepackage{pgfplots}
\pgfplotsset{compat=1.10}
\usepgfplotslibrary{fillbetween}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
axis lines=middle,
axis line style=->,
xmin=-.4,xmax=1.4,
ymin=-.4,ymax=2.4,
x=3cm,
y=3cm,
xlabel=$p$,
ylabel=$s$,
samples=20
]
\addplot[name path=A,domain=0:0.36] {2};
\addplot[name path=B,domain=0:0.36] {1+0.5*x};
\addplot[gray!40] fill between[of=A and B];
%
\addplot[name path=C,domain=0.35:1] {2};
\addplot[name path=D,domain=0.35:1] {2*sqrt(x)};
\addplot[gray!40] fill between[of=C and D];
% parametric form of inverse function
\addplot[domain=0:2, line width=0.35mm] ({x*x/4}, % <-- x values
{x} % <-- y values
);
\addplot[domain=0:1, line width=0.35mm]{2};
\addplot[domain=-0.3:1.3, line width=0.15mm]{1+0.5*x};
\end{axis}
\end{tikzpicture}
\end{document}
答案2
为了好玩,来一个pstricks
版本:
\documentclass[x11names, svgnames, border=3pt]{standalone}
\usepackage{pstricks-add}
\usepackage{auto-pst-pdf} %% for pdflatex compilation
\begin{document}
\psset{unit=2cm, algebraic, plotstyle=curve, plotpoints=500,arrowinset=0.125, arrowsize=3pt, linejoin=1,labelsep = 8pt}
\begin{pspicture*}(-0.4,-0.3)(1.6,2.5)
\psaxes[linecolor=LightSteelBlue3, ticksize =-3pt 3pt, tickcolor=LightSteelBlue3, arrows=->, subticksize =1, subtickcolor=LightSteelBlue3, subtickwidth=0.4pt, subticks=2, Dx=1, Dy=1](0,0)(-0.4,- 0.3)(1.5, 2.5) [$p$,120] [$s$,-30]
\uput[d](0.5,0){0.5} \uput[l](0,0.5){0.5}\uput[l](0,1.5){1.5}
\psplot{0}{1}{2*sqrt(x)}
\psplot[linewidth=0.5pt]{-0.4}{1.5}{1 + x/2}
\pscustom[linecolor=SteelBlue, fillstyle=solid, fillcolor=Gainsboro!80!Lavender]{\psline(0,1)(0,2)(1,2)\psplot{1}{0.343}{2*sqrt(x)}\closepath}
\end{pspicture*}
\end{document}