TikZ-PGF – How to Create Iterations of the Sierpinski Carpet

diagramsfractalslindenmayertikz-pgf

What I want to do is create a sequence of iterations of the Sierpinski carpet. The Sierpinski carpet is created by dividing the square into nine congruent subsquares and removing the middle one, then then dividing the remaining subsquares into nine smaller subsquares and removing the middle one, then iterating the process.

I created the diagram below using tikz by drawing and, where necessary, filling each individual rectangle. However, this is a tedious and inefficient process, particularly as the next iteration would require an additional 512 white rectangles.

Sierpinski carpet

\begin{tikzpicture}
\fill (0, 0) rectangle (1, 1);
\begin{scope}[xshift = 1.5 cm]
\fill (0, 0) rectangle (1, 1);
\fill[color=white] (1/3, 1/3) rectangle (2/3, 2/3);
\end{scope}
\begin{scope}[xshift = 3 cm]
\fill (0, 0) rectangle (1, 1);
\fill[color=white] (1/3, 1/3) rectangle (2/3, 2/3);
\fill[color=white] (1/9, 1/9) rectangle (2/9, 2/9);
\fill[color=white] (4/9, 1/9) rectangle (5/9, 2/9);
\fill[color=white] (7/9, 1/9) rectangle (8/9, 2/9);
\fill[color=white] (1/9, 4/9) rectangle (2/9, 5/9);
\fill[color=white] (7/9, 4/9) rectangle (8/9, 5/9);
\fill[color=white] (1/9, 7/9) rectangle (2/9, 8/9);
\fill[color=white] (4/9, 7/9) rectangle (5/9, 8/9);
\fill[color=white] (7/9, 7/9) rectangle (8/9, 8/9);
\end{scope}
\begin{scope}[xshift = 4.5 cm]
\fill (0, 0) rectangle (1, 1);
\fill[color=white] (1/3, 1/3) rectangle (2/3, 2/3);
\fill[color=white] (1/9, 1/9) rectangle (2/9, 2/9);
\fill[color=white] (4/9, 1/9) rectangle (5/9, 2/9);
\fill[color=white] (7/9, 1/9) rectangle (8/9, 2/9);
\fill[color=white] (1/9, 4/9) rectangle (2/9, 5/9);
\fill[color=white] (7/9, 4/9) rectangle (8/9, 5/9);
\fill[color=white] (1/9, 7/9) rectangle (2/9, 8/9);
\fill[color=white] (4/9, 7/9) rectangle (5/9, 8/9);
\fill[color=white] (7/9, 7/9) rectangle (8/9, 8/9);
\fill[color=white] (4/81, 4/81) rectangle (5/81, 5/81);
\fill[color=white] (13/81, 4/81) rectangle (14/81, 5/81);
\fill[color=white] (22/81, 4/81) rectangle (23/81, 5/81);
\fill[color=white] (31/81, 4/81) rectangle (32/81, 5/81);
\fill[color=white] (40/81, 4/81) rectangle (41/81, 5/81);
\fill[color=white] (49/81, 4/81) rectangle (50/81, 5/81);
\fill[color=white] (58/81, 4/81) rectangle (59/81, 5/81);
\fill[color=white] (67/81, 4/81) rectangle (68/81, 5/81);
\fill[color=white] (76/81, 4/81) rectangle (77/81, 5/81);
\fill[color=white] (4/81, 13/81) rectangle (5/81, 14/81);
\fill[color=white] (22/81, 13/81) rectangle (23/81, 14/81);
\fill[color=white] (31/81, 13/81) rectangle (32/81, 14/81);
\fill[color=white] (49/81, 13/81) rectangle (50/81, 14/81);
\fill[color=white] (58/81, 13/81) rectangle (59/81, 14/81);
\fill[color=white] (76/81, 13/81) rectangle (77/81, 14/81);
\fill[color=white] (4/81, 22/81) rectangle (5/81, 23/81);
\fill[color=white] (13/81, 22/81) rectangle (14/81, 23/81);
\fill[color=white] (22/81, 22/81) rectangle (23/81, 23/81);
\fill[color=white] (31/81, 22/81) rectangle (32/81, 23/81);
\fill[color=white] (40/81, 22/81) rectangle (41/81, 23/81);
\fill[color=white] (49/81, 22/81) rectangle (50/81, 23/81);
\fill[color=white] (58/81, 22/81) rectangle (59/81, 23/81);
\fill[color=white] (67/81, 22/81) rectangle (68/81, 23/81);
\fill[color=white] (76/81, 22/81) rectangle (77/81, 23/81);
\fill[color=white] (4/81, 31/81) rectangle (5/81, 32/81);
\fill[color=white] (13/81, 31/81) rectangle (14/81, 32/81);
\fill[color=white] (22/81, 31/81) rectangle (23/81, 32/81);
\fill[color=white] (58/81, 31/81) rectangle (59/81, 32/81);
\fill[color=white] (67/81, 31/81) rectangle (68/81, 32/81);
\fill[color=white] (76/81, 31/81) rectangle (77/81, 32/81);
\fill[color=white] (4/81, 40/81) rectangle (5/81, 41/81);
\fill[color=white] (22/81, 40/81) rectangle (23/81, 41/81);
\fill[color=white] (58/81, 40/81) rectangle (59/81, 41/81);
\fill[color=white] (76/81, 40/81) rectangle (77/81, 41/81);
\fill[color=white] (4/81, 49/81) rectangle (5/81, 50/81);
\fill[color=white] (13/81, 49/81) rectangle (14/81, 50/81);
\fill[color=white] (22/81, 49/81) rectangle (23/81, 50/81);
\fill[color=white] (58/81, 49/81) rectangle (59/81, 50/81);
\fill[color=white] (67/81, 49/81) rectangle (68/81, 50/81);
\fill[color=white] (76/81, 49/81) rectangle (77/81, 50/81);
\fill[color=white] (4/81, 58/81) rectangle (5/81, 59/81);
\fill[color=white] (13/81, 58/81) rectangle (14/81, 59/81);
\fill[color=white] (22/81, 58/81) rectangle (23/81, 59/81);
\fill[color=white] (31/81, 58/81) rectangle (32/81, 59/81);
\fill[color=white] (40/81, 58/81) rectangle (41/81, 59/81);
\fill[color=white] (49/81, 58/81) rectangle (50/81, 59/81);
\fill[color=white] (58/81, 58/81) rectangle (59/81, 59/81);
\fill[color=white] (67/81, 58/81) rectangle (68/81, 59/81);
\fill[color=white] (76/81, 58/81) rectangle (77/81, 59/81);
\fill[color=white] (4/81, 67/81) rectangle (5/81, 68/81);
\fill[color=white] (22/81, 67/81) rectangle (23/81, 68/81);
\fill[color=white] (31/81, 67/81) rectangle (32/81, 68/81);
\fill[color=white] (49/81, 67/81) rectangle (50/81, 68/81);
\fill[color=white] (58/81, 67/81) rectangle (59/81, 68/81);
\fill[color=white] (76/81, 67/81) rectangle (77/81, 68/81);
\fill[color=white] (4/81, 76/81) rectangle (5/81, 77/81);
\fill[color=white] (13/81, 76/81) rectangle (14/81, 77/81);
\fill[color=white] (22/81, 76/81) rectangle (23/81, 77/81);
\fill[color=white] (31/81, 76/81) rectangle (32/81, 77/81);
\fill[color=white] (40/81, 76/81) rectangle (41/81, 77/81);
\fill[color=white] (49/81, 76/81) rectangle (50/81, 77/81);
\fill[color=white] (58/81, 76/81) rectangle (59/81, 77/81);
\fill[color=white] (67/81, 76/81) rectangle (68/81, 77/81);
\fill[color=white] (76/81, 76/81) rectangle (77/81, 77/81);
\end{scope}
\end{tikzpicture}

What I was hoping to do is adapt Jake's solution using lindenmayer systems to How to create a Sierpinski triangle in LaTeX? to a rectangle, as marsupilam did for a hexagon in Tikz Fractal – Sierpinski Hexagon.

I am aware that questions about generating a Sierpinski carpet have been asked previously. Mark Wibrow's answer to Generating a Sierpinski carpet with tikz does not use a lindenmayer system and causes my system to hang. Henri Menke's answer to Drawing a Simple Fractal in Tikz is beautiful, but it becomes quite small when I reduce the order of the fractal and sits on a vertex rather than a side. I wish to keep each iteration the same size, as shown above.

I suppose that if I set order=\level, I would want to set the \squarewidth=9^\level since each square is divided into nine squares and that I should set the angle=90 since each angle is a right angle. However, I am confused about how to adapt the rules for the symbols X and Y that Jake and marsupilam used in their answers to generate the patterns shown above.

Best Answer

Here is a macro that places white nodes at the appropriate locations.

\sierpinski[options]{levels}

The option I have in mind is scale=, but rotate= will work as well. Or xscale= if you want rectangles that aren't squares. Be sure to use transform shape.

enter image description here

\documentclass{article}

\usepackage{tikz}

\newcommand{\sierpinski}[2][]{\tikz[#1]{
  \draw[fill=black] rectangle(1,1);
    \foreach \n[evaluate=\n as \m using \n-1, evaluate=\n as \s using 1/3^\n, evaluate=\m as \p using 3^\m] in {1,...,#2}{
      \foreach \k[evaluate=\k as \x using (2*\k-1)/2/3^\m] in {1,...,\p}{
        \foreach \j[evaluate=\j as \y using (2*\j-1)/2/3^\m] in {1,...,\p}{
          \node[fill=white, minimum size=\s cm, inner sep=0] at (\x,\y){};
}}}}}

\begin{document}

\tikz{\draw[fill=black] rectangle(1,1);}\quad\sierpinski{1}\quad\sierpinski{2}\quad\sierpinski{3}\quad\sierpinski{4}

\end{document}

Here is \sierpinski[scale=3, transform shape]{5}, which is about all my machine can handle. It's O(9ⁿ), so prepare to wait.

enter image description here