域边界附近的精确三维函数图

域边界附近的精确三维函数图

我正在尝试绘制这个函数

f(x,y) = -sqrt(x^2+y^2-1)

应该渲染成类似这样的内容(由计算图3Dcalcplot3d 图

问题是,即使使用像 150 这样相当大的数字,我也无法让 pgfplots 生成类似的东西。samples此外,编译时间会变得非常长,考虑到我正在外部化图表,这将是一个小问题,但结果仍然不是最优的。 pgfplots 图 正如您在图像中看到的,我的输出在 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}

相关内容