带有计算参数的 Pgfplot 嵌套循环

带有计算参数的 Pgfplot 嵌套循环

我需要在 3D 表面下绘制有限数量的立方体。因此我需要嵌套循环。以下代码接近我想要的,只是我想修改参数的 z 限制以使\k所有立方体都在表面图下。基本上,我想使用\fun{\i}{\j}-\dl而不是\fun{\i}{\j}

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
 \usetikzlibrary{calc}
\pgfplotsset{compat=1.16}


\begin{document}


 
\newcommand{\fun}[2]{{4*((#1/(#1+1))*(#2/(#2+1))+0.5)}}


\tikzset{
    mycube/.pic={
        \pgfmathsetmacro\size{{#1}}
        \draw[fill=gray!20] (0,0,\size) -- ++(0,\size,0) -- ++(\size,0,0) -- ++(0,-\size,0) -- cycle; % top
        \draw[fill=gray!10] (0,0,0) --++(\size,0,0)-- ++ (0,0,\size)--++(-\size,0,0)  -- cycle; % front
        \draw[fill=gray!40] (\size,0,0) --++(0,\size,0)-- ++ (0,0,\size)--++(0,-\size,0)  -- cycle; %side
}
}

\begin{tikzpicture}
\def\dl{1}
\begin{axis}[xlabel = $x$, ylabel = $y$, zlabel = {$z$},
    xmin=0, xmax=5,
    ymin=0, ymax = 5,
    zmin=0, 
    clip=false]

% WORKING but not satisfactory
\pgfplotsforeachungrouped \i in {0,0+\dl,...,5-\dl}{
    \pgfplotsforeachungrouped \j in {5-\dl,5-(2*\dl),...,0}{
        \pgfplotsforeachungrouped \k in {0,0+\dl,...,int(\fun{\i}{\j})}{
            \edef\temp{\noexpand \draw (\i,\j,\k) pic{mycube={\dl}};}\temp
        }
    }
}

% NOT working
% \pgfplotsforeachungrouped \i in {0,0+\dl,...,5-\dl}{
%     \pgfplotsforeachungrouped \j in {5-\dl,5-(2*\dl),...,0}{
%         \pgfplotsforeachungrouped \k in {0,0+\dl,...,int(\fun{\i}{\j}-\dl)}{
%             \edef\temp{\noexpand \draw (\i,\j,\k) pic{mycube={\dl}};}\temp
%         }
%     }
% }

% NOT working
% \pgfplotsforeachungrouped \i in {0,0+\dl,...,5-\dl}{
%     \pgfplotsforeachungrouped \j [evaluate=\j as \klim using {int(\fun{\i}{\j})}] in {5-\dl,5-(2*\dl),...,0}{
%         \pgfplotsforeachungrouped \k in {0,0+\dl,...,\klim}{
%             \edef\temp{\noexpand \draw (\i,\j,\k) pic{mycube={\dl}};}\temp
%         }
%     }
% }

    \addplot3[surf,domain=0:5,y domain=0:5,fill opacity = 0.3] {\fun{x}{y}};
\end{axis}
\end{tikzpicture}
 
\end{document}

表面下的立方体

我尝试了几种方法来降低这个 z 限制,但都不起作用。任何帮助都将不胜感激!


附加问题:

  • 我不确定将表面函数定义为单独的宏是否是最好的方法。如何以更简洁的方式做到这一点?
  • int( )为什么循环中必须要使用\k参数呢?

多谢。

答案1

尝试理解“降低 z 限制”的含义,我最终猜测 OP 希望将盒子在 z 方向上向下移动,同时保持函数不变,以使盒子不超过函数。

我将\k循环索引调整为

\pgfplotsforeachungrouped \k in {0,0+\dl,...,(int(\fun{\i}{\j}) - 1.5)}

为什么-1.5?因为\k开始绘制于 0,并且零绘制延伸至z=1,因此需要减去 1。然后,我发现如果我\z手动将 的上限设置为 ,例如 ,2.5它会将其四舍五入,就像它是 一样,3并且实际上绘制的框最多为z=4。因此,实际函数(z=2.5)和堆叠的 z 框(到 z=4)之间的差异可能很大,为 4 - 2.5 = 1.5。这就是为什么必须从总数中减去 1.5 的原因,以确保框高度永远不会超过函数高度。

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
 \usetikzlibrary{calc}
\pgfplotsset{compat=1.16}

\begin{document}

\newcommand{\fun}[2]{{4*((#1/(#1+1))*(#2/(#2+1))+0.5)}}

\tikzset{
    mycube/.pic={
        \pgfmathsetmacro\size{{#1}}
        \draw[fill=gray!20] (0,0,\size) -- ++(0,\size,0) -- ++(\size,0,0) -- ++(0,-\size,0) -- cycle; % top
        \draw[fill=gray!10] (0,0,0) --++(\size,0,0)-- ++ (0,0,\size)--++(-\size,0,0)  -- cycle; % front
        \draw[fill=gray!40] (\size,0,0) --++(0,\size,0)-- ++ (0,0,\size)--++(0,-\size,0)  -- cycle; %side
}
}

\begin{tikzpicture}
\def\dl{1}
\begin{axis}[xlabel = $x$, ylabel = $y$, zlabel = {$z$},
    xmin=0, xmax=5,
    ymin=0, ymax = 5,
    zmin=0, 
    clip=false]

% WORKING but not satisfactory
\pgfplotsforeachungrouped \i in {0,0+\dl,...,5-\dl}{
    \pgfplotsforeachungrouped \j in {5-\dl,5-(2*\dl),...,0}{
    \pgfplotsforeachungrouped \k in {0,0+\dl,...,(int(\fun{\i}{\j}) - 1.5)}{
            \edef\temp{\noexpand \draw (\i,\j,\k) pic{mycube={\dl}};}\temp
        }
    }
}

    \addplot3[surf,domain=0:5,y domain=0:5,fill opacity = 0.3] {\fun{x}{y}};
\end{axis}
\end{tikzpicture}
 
\end{document}

在此处输入图片描述

相关内容