我正在尝试绘制这个函数
应该渲染成类似这样的内容(由计算图3D)
问题是,即使使用像 150 这样相当大的数字,我也无法让 pgfplots 生成类似的东西。samples
此外,编译时间会变得非常长,考虑到我正在外部化图表,这将是一个小问题,但结果仍然不是最优的。
正如您在图像中看到的,我的输出在 z=0 附近破碎(其中函数是圆周),但对于我的说明来说,这是图中最重要的部分,因为我必须指出该函数具有无限的绝对最大值点。
这是我当前的代码(免责声明:除非你的 CPU 使用率为 100%,否则不要运行它)
\documentclass{book}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.7}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xlabel=$x$, ylabel=$y$,
]
\addplot3[surf, domain =-2:2, domain y=-2:2, unbounded coords=jump, samples=150]
{ x^2 + y^2 >= 1 ? -sqrt(x^2+y^2-1) : NaN };
\end{axis}
\end{tikzpicture}
\end{document}
除了嵌入预渲染图像之外,你们还有什么关于如何正确绘制此函数的提示吗?
答案1
通常,为了获得良好的径向对称函数效果,人们会切换到极坐标。然而,这在底部看起来并不好,至少在不进行大量手术的情况下是如此。因此,一种可能性是叠加两个图。
\documentclass{book}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xlabel=$x$, ylabel=$y$,
]
\addplot3[surf, domain =-2:2, domain y=-2:2, unbounded coords=jump,
samples=51]
{ x^2 + y^2 >= 1.1 ? -sqrt(x^2+y^2-1) : NaN };
\addplot3[surf, domain=1.001:1.2, domain y=0:360,samples=5,samples y=51,
z buffer=sort]
({x*cos(y)},{x*sin(y)},{-sqrt(x^2-1)});
\end{axis}
\end{tikzpicture}
\end{document}
远非完美,但边缘也不锯齿状。
您也可以只使用极坐标图或裁剪的极坐标图。请注意,裁剪路径取决于视角,因此如果您大幅改变视图,则此方法将不起作用。
\documentclass{book}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\begin{document}
\begin{tikzpicture}
\begin{axis}[xmin=-2,xmax=2,ymin=-2,ymax=2,
xlabel=$x$, ylabel=$y$]
\clip plot[domain=0:-2] (-2,{\x},{-sqrt(3+\x*\x)}) --
plot[domain=-2:2] ({\x},-2,{-sqrt(3+\x*\x)})
-- plot[domain=-2:2] (2,{\x},{-sqrt(3+\x*\x)}) -- (2,2,0) -- (-2,2,0)
--cycle;
\addplot3[surf, domain=1.001:{2*sqrt(2)}, domain y=0:360,
samples y=50, z buffer=sort] ({x*cos(y)},{x*sin(y)},{-sqrt(x^2-1)});
\end{axis}
\end{tikzpicture}
\end{document}
或者使用在两个坐标系之间进行插值的函数。该函数Rplane
是正方形的极坐标表示,取自这里和这里其最初目的也是在 3d 环境中,为了处理非常相似的问题。
\documentclass{book}
\usepackage{pgfplots}
\pgfplotsset{compat=1.17}
\begin{document}
\begin{tikzpicture}
\begin{axis}[declare function={
Rplane(\t)=1/max(abs(cos(\t)),abs(sin(\t)));
Rcheat(\r,\t)=\r*0.5*(tanh(7*(\r-1.5))+1)*Rplane(\t)
+\r*0.5*(1-tanh(7*(\r-1.5)));},
xlabel=$x$, ylabel=$y$,
]
\addplot3[surf, domain =1:2, domain y=0:360, unbounded coords=jump,
samples=51,z buffer=sort]
({Rcheat(x,y)*cos(y)},{Rcheat(x,y)*sin(y)},{-sqrt(pow(Rcheat(x,y),2)-1) });
\end{axis}
\end{tikzpicture}
\end{document}
答案2
我还有两次截断
\documentclass{book}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.7}
\begin{document}
\pgfmathdeclarefunction{volcano_z}{2}{%
\pgfmathsetmacro\radsq{#1^2 + #2^2}% \radsq is radius^2 in FPU notation
\pgfmathfloattofixed{\radsq}\let\radsqsafe=\pgfmathresult % in safe notation
\ifdim\radsqsafe pt > 1pt\relax
\pgfmathparse{-sqrt(\radsq-1)}%
\else\ifdim\radsqsafe pt > 0.25pt\relax
\pgfmathparse{+0}%
\else % \radsq pt <= 0.25
\pgfmathparse{NaN}%
\fi\fi
}
\begin{tikzpicture}
\begin{axis}[xlabel=$x$, ylabel=$y$,]
\addplot3[surf,domain =-2:2,unbounded coords=jump,samples=32]
{volcano_z(x,y)};
\end{axis}
\end{tikzpicture}
\pgfmathdeclarefunction{volcano_x}{2}{%
\pgfmathsetmacro\radsq{#1^2 + #2^2}% \radsq is radius^2 in FPU notation
\pgfmathfloattofixed{\radsq}\let\radsqsafe=\pgfmathresult % in safe notation
\ifdim\radsqsafe pt > 1pt\relax
\pgfmathparse{#1}%
\else\ifdim\radsqsafe pt > 0.25pt\relax
\pgfmathparse{#1/sqrt(\radsq)}%
\else % \radsq pt <= 0.25
\pgfmathparse{NaN}%
\fi\fi
}
\begin{tikzpicture}
\begin{axis}[xlabel=$x$, ylabel=$y$,]
\addplot3[surf,domain =-2:2,unbounded coords=jump,samples=32]
( {volcano_x(x,y)},
{volcano_x(y,x)},
{volcano_z(x,y)}
);
\end{axis}
\end{tikzpicture}
\end{document}