绘制此图像的正确方法是什么?

绘制此图像的正确方法是什么?

我欣赏 LaTeX 的所见即所得功能,但随着时间的推移,我开始怀疑纯图形的所见即所得理念是否仍然合理。今天我花了一个多小时才用下面的代码(以及另外两个非常相似的代码)实现了下面的图片。

在我的联想 ThinkPad L530(Ubuntu 和 Openbox)上,每次编译都要花费 15 秒以上的时间,而将样本从 2000 减少到 500 也需要 3 秒以上的时间,结果更糟糕。我仍然对这幅图像不满意,因为抛物线与水平线和垂直线的交点太尖锐了。以下是我的问题:

  1. 我应该使用什么正确的代码才能制作出快速编译且美观的图片?
  2. 您通常需要多长时间才能为这样的图像提供正确的代码?
  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 domaindomain
  • 域的四舍五入范围(从-0.0010等)

经过这一更改后,我的旧电脑上的计算时间减少了约 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} 

在此处输入图片描述

相关内容