Tikz 分形 - Menger 海绵

Tikz 分形 - Menger 海绵

好的,我继续在 Tikz 中构建分形 - 另一个在这里:Tikz 分形 - Cantor Dust。我希望有人能帮我创建另一个稍微复杂一点的分形。它被称为孟格海绵,本质上是“3D”(尽管将分形定义为这样有点矛盾)谢尔宾斯基地毯。它看起来像这样:

在此处输入图片描述

从单位立方体开始,然后递归地移除立方体中每个面的中心 9 分之一。这里有一个更好、更精确的描述:https://en.wikipedia.org/wiki/Menger_sponge

我认为使用“lindenmayer 系统”应该可以实现,但我对该系统只有很少的经验,而且我从未将其用于 3D 形状。

使用 Nancy-N 的解决方案后,我得到了以下结果:

在此处输入图片描述

(注意每个小立方体周围的细线)。

答案1

我不知道这是否会让您高兴,但确实,一种 Lindenmayer 系统可以解决您的问题,利用这样一个事实:立方体由 20 个 3 倍大小的立方体副本组成,而这些副本本身又由 3 倍大小的立方体组成,依此类推。您可以采用以下方法;我让您进行必要的调整以获得更好的图像。

level0.tex首先使用以下代码生成一个 .tex 文件 \documentclass左右,\begin{document}其内容将是:

\fill[yellow] (1, 1, 1) -- (1, -1, 1) -- (-1, -1, 1) -- (-1, 1, 1) -- cycle;
\fill[cyan] (1, 1, 1) -- (1, 1, -1) -- (1, -1, -1) -- (1, -1, 1) -- cycle;
\fill[magenta] (1, 1, 1) -- (1, 1, -1) -- (-1, 1, -1) -- (-1, 1, 1) -- cycle;

现在你创建一个文件level1.tex(同样,不是\documentclass左右),在其中使用 20 次的内容,level0就像你将几个小立方体放在一起一样。请注意,你必须按正确的顺序绘制立方体,这样隐藏另一个立方体的立方体才会被绘制它。您的文件level1.tex将如下所示:

\begin{scope}[scale=.3333333333]
\begin{scope}[shift={(-2, -2, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(0, -2, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, -2, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(-2, 0, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, 0, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(-2, 2, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(0, 2, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, 2, -2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(-2, -2, 0)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, -2, 0)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(-2, 2, 0)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, 2, 0)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(-2, -2, 2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(0, -2, 2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, -2, 2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(-2, 0, 2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, 0, 2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(-2, 2, 2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(0, 2, 2)}]
\input{level0}
\end{scope}
\begin{scope}[shift={(2, 2, 2)}]
\input{level0}
\end{scope}
\end{scope}

接下来,创建一个level2.tex与 相同的文件level1.tex,只是\input{level0}被 替换\input{level1}。最后,您的最终绘图(在 等真实.tex源文件中\documentclass)将是

\begin{tikzpicture}
\input{level2}
\end{tikzpicture}

下面是我得到的渲染。当然,至少理论上你可以达到 3、4 级左右,但不要忘记,每增加一个级别,计算量和内存使用量就会增加 20 倍!

门格海绵,2级

诚挚的问候,/Nancy-N


编辑:Paul Gaborit 很好地改进了我的解决方案,他编写了一个\mengersponge带有一个参数的命令,这样你就不必为每个级别创建一个文件了。这是他的代码(他还选择了更相关的颜色 ;-)):

\documentclass[tikz]{standalone}
\usepackage{luatex85}
\newcommand\mengersponge[1]{
  \pgfmathsetmacro\level{int(#1 - 1)}
  \ifnum \level = 0 \relax
  \filldraw[gray!50!black,line width=0] (1, 1, 1) -- (1, 1, -1) -- (1, -1, -1) -- (1, -1, 1) -- cycle;
  \filldraw[gray,line width=0] (1, 1, 1) -- (1, 1, -1) -- (-1, 1, -1) -- (-1, 1, 1) -- cycle;
  \filldraw[gray!50,line width=0] (1, 1, 1) -- (1, -1, 1) -- (-1, -1, 1) -- (-1, 1, 1) -- cycle;
  \else
  \begin{scope}[scale=.3333333333]
    \begin{scope}[shift={(-2, -2, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(0, -2, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, -2, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(-2, 0, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, 0, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(-2, 2, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(0, 2, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, 2, -2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(-2, -2, 0)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, -2, 0)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(-2, 2, 0)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, 2, 0)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(-2, -2, 2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(0, -2, 2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, -2, 2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(-2, 0, 2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, 0, 2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(-2, 2, 2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(0, 2, 2)}]
      \mengersponge{\level}
    \end{scope}
    \begin{scope}[shift={(2, 2, 2)}]
      \mengersponge{\level}
    \end{scope}
  \end{scope}
  \fi
}
\begin{document}
\begin{tikzpicture}
  \mengersponge{4}
\end{tikzpicture}
\end{document}

使用 时pdflatex,Paul Gaborit 只能执行到第 3 级的计算(对应于\mengersponge{4}他的代码中的),这需要 40 秒才能编译完成;但使用lualatex他可以编译第 4 级(对应于\mengersponge{5})。以下是他的照片 :-)

对于 3 级:

门格海绵,3级

对于 4 级:

门格海绵,4级

问候,/Nancy-N

相关内容