19

What I am trying to do is to create an image such as that below, that is, triangles inside triangles. I can get a single triangle created and I commented out the parts that create circles (for a Venn diagram, the original code was found here), but I am not sure how to create midpoints on each of the sides and connect those midpoints.

While I am only looking for depth two (the image is depth 3), I figure it would be useful to figure out how to do it programmatically so as to create something such as a fractal. I am also wanting to label the sides - at least for the first and second depth guessing that there would have to be some kind of if structure. Any ideas?

 \documentclass[tikz,border=10pt]{standalone}
    \begin{tikzpicture}
        \node (tri) [regular polygon, regular polygon sides=3, draw, densely dashed, minimum width=50mm] {};
    %    \foreach \i/\j in {1/2,2/3,3/1}
    %    {
    %      \node [draw] at (tri.corner \i) [circle through={($(tri.corner \i)!1/2!(tri.corner \j)$)}, draw] {};
    %      \path [fill] ($(tri.corner \i)!1/2!(tri.corner \j)$) circle (2.5pt);
    %    }
  \end{document}

EDIT! Using a small piece (not employing the arbitrary depth) of Tom Bombadil's extra-ordinary answer I added the labels for the sides in which I sought. The reason I added it is note that each of the three 'sides' of the largest (outer) triangle is really 6 sides - that is, instead of for example (A) -- (B) there is a coordinate (D) half way in between (A) and (B), so each of the three sides is halved to make 6 sides. While my problem is solved in this manner, I thought that someone might be able to modify Tom's code for labeling to support this ability. My labeling of a simple triangle inside triangle from Tom's code is:

\documentclass[tikz,border=10pt]{standalone}
\begin{figure}
\begin{tikzpicture}
    \coordinate [label=right:$Y \wedge \neg (X \vee Z)$] (A) at (-30:5);
    \coordinate [label=above:$X \wedge \neg (Y \vee Z)$] (B) at (90:5);
    \coordinate [label=left:$Z \wedge \neg (X \vee Y)$] (C) at (210:5);
  %  $\draw (A) -- (B) -- (C) -- cycle;


        \coordinate  [label=right:$X \wedge Y \wedge \neg Z$] (D) at ($(A)!0.5!(B)$);
        \coordinate  [label=left:$X \wedge Z \wedge \neg Y$] (E) at ($(B)!0.5!(C)$) ;
        \coordinate  [label=below:$Y \wedge Z \wedge \neg X$] (F) at ($(C)!0.5!(A)$);

      \draw (B) -- (D) node[right] at ( $ (B)!0.5!(D) $) (a) {$X \wedge \neg Z$};
      \draw (B) -- (E) node[left] at ( $ (B)!0.5!(E) $) (a) {$X \wedge \neg Y$};
      \draw (E) -- (C) node[left] at ( $ (E)!0.5!(C) $) (a) {$Z \wedge \neg Y$};
      \draw (C) -- (F) node[below] at ( $ (C)!0.3!(F) $) (a) {$Z \wedge \neg X$};
      \draw (F) -- (A) node[below] at ( $ (F)!0.7!(A) $) (a) {$Y \wedge \neg X$};
      \draw (A) -- (D) node[right] at ( $ (A)!0.5!(D) $) (a) {$Y \wedge \neg Z$};

    % \draw (D) -- (E) -- (F) -- cycle;
      \draw (D) -- (E) node[above] at ( $ (E)!0.5!(D) $) (a) {$X \wedge (Y \Updownarrow Z)$};
      \draw (E) -- (F) node[left] at ( $ (E)!0.65!(F) $) (b) {$Z \wedge (X \Updownarrow Y)$};
        \draw (F) -- (D) node[right] at ( $ (F)!0.35!(D) $) (c) {$Y \wedge (X \Updownarrow Z)$};
\end{tikzpicture}
\end{figure}

Depth 3 Triangles

  • Things like \draw (B) -- (D) node[right] at ( $ (B)!0.5!(D) $) (a) {$X \wedge \neg Z$}; you can simplify with the pos key (does not even need the calc library): \draw (B) -- (D) node[right, pos=0.5] (a) {$X \wedge \neg Z$}; – Tom Bombadil Nov 22 '15 at 0:42
28
+100

My solution does the same as percusses, but probably is a bit easier to read. It uses the calc library to compute the midpoints of the edges, and then renames the coordinates appropriately.

Code

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc}

\begin{document}

\newcommand{\DrawIterated}[1]% number of iterations
{ \foreach \i in {1,...,#1}
    { \draw (A) -- (B) -- (C) -- cycle;
        \coordinate (D) at ($(A)!0.5!(B)$);
        \coordinate (E) at ($(B)!0.5!(C)$);
        \coordinate (F) at ($(C)!0.5!(A)$);
        \coordinate (A) at (D);
        \coordinate (B) at (E);
        \coordinate (C) at (F);
    }
}

\begin{tikzpicture}
    \coordinate (A) at (-30:5);
    \coordinate (B) at (90:5);
    \coordinate (C) at (210:5);
    \DrawIterated{7}
\end{tikzpicture}

\begin{tikzpicture}
    \coordinate (A) at (0:3);
    \coordinate (B) at (90:5);
    \coordinate (C) at (180:7);
    \DrawIterated{7}
\end{tikzpicture}

\end{document}

Output

enter image description here


Edit 1: Generalized for regular n-Gons, where the meeting point is variable and color fill is added:

Code

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc}

\begin{document}

\newcommand{\DrawIteraredReGularPolygon}[7]%
% 1: number of  corners
% 2: corner radius
% 3: iterations
% 4: draw options
% 5: start color
% 6: end color
% 7: fraction
{ \foreach \a in {1,...,#1}
        {   \coordinate (c-\a) at (360/#1*\a+90:#2);
        }
    \foreach \iteration in {1,...,#3}
    {   \pgfmathtruncatemacro{\colorpercentage}{int((\iteration-1)/(#3-1)*100)}
        \draw[#4, fill=#6!\colorpercentage!#5] (c-1) 
            \foreach \a in {2,...,#1}
            {   -- (c-\a)
            } -- cycle;
        \foreach \a in {1,...,#1}
        {   \pgfmathtruncatemacro{\nextindex}{mod(\a,#1)+1}
            \coordinate (t-\a) at ($(c-\a)!#7!(c-\nextindex)$);
        }
        \foreach \a in {1,...,#1}
        {   \coordinate (c-\a) at (t-\a);
        }
    }
}

\begin{tikzpicture}
    \DrawIteraredReGularPolygon{3}{5}{7}{black}{white}{white}{0.5}
\end{tikzpicture}

\begin{tikzpicture}
    \DrawIteraredReGularPolygon{5}{5}{20}{black,thin}{orange}{blue}{0.27}
\end{tikzpicture}

\begin{tikzpicture}
    \DrawIteraredReGularPolygon{8}{5}{35}{black,thin}{black!90}{red}{0.3}
\end{tikzpicture}

\end{document}

Output

enter image description here


Edit 2: And of cause, one can produce silly animations! The following

\foreach \frame in {0,5,...,359}
{   \begin{tikzpicture}
        \pgfmathsetmacro{\myfraction}{0.45*cos(\frame)+0.5}
        \pgfmathsetmacro{\mycolor}{49*sin(\frame)+50}
        \colorlet{onecolor}{orange!\mycolor!red}
        \colorlet{twocolor}{blue!\mycolor!green}
        %\node {\myfraction};
        \DrawIteraredReGularPolygon{5}{5}{20}{black,thin}{onecolor}{twocolor}{\myfraction}
    \end{tikzpicture}
}

converted with ImageMagick's convert -loop 0 -delay 5 -dispose previous -density 50 swirl.pdf swirl.gif produces this:

enter image description here


Edit 3: For labeling the sides, here's how on could go about this. As this command now has the maximum of 9 parameters, switching to some key-value mechanism like pgfkeys is advised. If the "upside down" text is considered bad, remove the allow upside down option, but then the labels are not always placed on the "right side" (outside) of the triangle.

Code

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc, positioning}

\begin{document}

\newcommand{\DrawIteraredReGularPolygon}[9]%
% 1: number of  corners
% 2: corner radius
% 3: iterations
% 4: draw options
% 5: start color
% 6: end color
% 7: fraction
% 8: label names
% 9: label position
{ \renewcommand{\labelnumbers}[1]%
    {   \ifcase##1
        #8
        \else ERROR!
        \fi
    }
    \foreach \a in {1,...,#1}
  { \coordinate (c-\a) at (360/#1*\a+90:#2);
  }
  \foreach \iteration in {1,...,#3}
  { \pgfmathtruncatemacro{\colorpercentage}{int((\iteration-1)/(#3-1)*100)}
    \draw[#4, fill=#6!\colorpercentage!#5] (c-1)
    \foreach \a in {2,...,#1}
    { -- (c-\a)
    } -- cycle;
    \foreach \a in {1,...,#1}
    {   \pgfmathtruncatemacro{\nextindex}{mod(\a,#1)+1}
        \coordinate (t-\a) at ($(c-\a)!#7!(c-\nextindex)$);
        \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*#1+\a-1}
        % ========== remove the "allow upside down" if desired
        \path (c-\a) -- node[below ,sloped, pos=#9, allow upside down] {\labelnumbers{\labelindex}} (c-\nextindex);
    }
    \foreach \a in {1,...,#1}
    {   \coordinate (c-\a) at (t-\a);
    }
    }
}

\newcommand{\labelnumbers}{}

\begin{tikzpicture}
    \DrawIteraredReGularPolygon{3}{5}{2}{black}{white}{white}{0.5}{a\or B\or $\gamma$\or dd\or  $\epsilon^{\epsilon^{\epsilon}}$\or F}{0.25}
\end{tikzpicture}

\end{document}

Output

enter image description here


Edit 4: Here's a variant for giving two labels to all but the inner iteration.

Code

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc, positioning}
\usepackage{xifthen}

\begin{document}

\newcommand{\DrawIteraredReGularPolygon}[9]%
% 1: number of  corners
% 2: corner radius
% 3: iterations
% 4: draw options
% 5: start color
% 6: end color
% 7: fraction
% 8: label names
% 9: label position
{ \renewcommand{\labelnumbers}[1]%
    {   \ifcase##1
        #8
        \else ERROR!
        \fi
    }
    \foreach \a in {1,...,#1}
  { \coordinate (c-\a) at (360/#1*\a+90:#2);
  }
  \foreach \iteration in {1,...,#3}
  { \pgfmathtruncatemacro{\colorpercentage}{int((\iteration-1)/(#3-1)*100)}
    \draw[#4, fill=#6!\colorpercentage!#5] (c-1)
    \foreach \a in {2,...,#1}
    { -- (c-\a)
    } -- cycle;
    \foreach \a in {1,...,#1}
    {   \pgfmathtruncatemacro{\nextindex}{mod(\a,#1)+1}
        \coordinate (t-\a) at ($(c-\a)!#7!(c-\nextindex)$);
            \ifthenelse{\iteration = #3}
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*#1*2+\a-1}
                \path (c-\a) -- node[below ,sloped, pos=#9, allow upside down] {\labelnumbers{\labelindex}} (c-\nextindex);
            }
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*#1*2+2*(\a-1)}
                \path (c-\a) -- node[below ,sloped, pos=#9, allow upside down] {\labelnumbers{\labelindex}} (t-\a);
                \pgfmathtruncatemacro{\labelindex}{\labelindex+1}
            \path (t-\a) -- node[below ,sloped, pos=1-#9, allow upside down] {\labelnumbers{\labelindex}} (c-\nextindex);
            }
    }
    \foreach \a in {1,...,#1}
    {   \coordinate (c-\a) at (t-\a);
    }
    }
}

\newcommand{\labelnumbers}{}

\begin{tikzpicture}
    \DrawIteraredReGularPolygon{3}{5}{3}{black}{white}{white}{0.5}{a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m\or n\or o}{0.5}
\end{tikzpicture}

\end{document}

Output

enter image description here


Edit 5: If you don't like the sloped style, here's how you can do it via computing appropriate angles. It seems unneccessarily complicated to first define a temp coordinate and then placing a node at the fitting angle, but using the pos and label options of a node together does not seem to work, as the node is then always placed at the end.

Code

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc, positioning}
\usepackage{xifthen}

\begin{document}

\newcommand{\DrawIteraredReGularPolygon}[9]%
% 1: number of  corners
% 2: corner radius
% 3: iterations
% 4: draw options
% 5: start color
% 6: end color
% 7: fraction
% 8: label names
% 9: label position
{ \renewcommand{\labelnumbers}[1]%
    {   \ifcase##1
        #8
        \else ERROR!
        \fi
    }
    \foreach \a in {1,...,#1}
  { \coordinate (c-\a) at (360/#1*\a+90:#2);
  }
  \foreach \iteration in {1,...,#3}
  { \pgfmathtruncatemacro{\colorpercentage}{int((\iteration-1)/(#3-1)*100)}
    \draw[#4, fill=#6!\colorpercentage!#5] (c-1)
    \foreach \a in {2,...,#1}
    { -- (c-\a)
    } -- cycle;
    \foreach \a in {1,...,#1}
    {   \pgfmathtruncatemacro{\nextindex}{mod(\a,#1)+1}
        \coordinate (t-\a) at ($(c-\a)!#7!(c-\nextindex)$);
        \path (c-\a);
        \pgfgetlastxy{\tempx}{\tempy}
        \path (c-\nextindex);
        \pgfgetlastxy{\tempxx}{\tempyy}
        \pgfmathsetmacro{\labelangle}{atan2(\tempyy-\tempy,\tempxx-\tempx)-90}
            \ifthenelse{\iteration = #3}
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*#1*2+\a-1}
                \path (c-\a) -- coordinate[pos=0.5] (temp) (c-\nextindex);
                \node at ($(temp)+(\labelangle:0.2)$) {\labelnumbers{\labelindex}};
            }
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*#1*2+2*(\a-1)}
                \path (c-\a) -- coordinate[pos=0.5] (temp) (t-\a);
                \node at ($(temp)+(\labelangle:0.2)$) {\labelnumbers{\labelindex}};
                \pgfmathtruncatemacro{\labelindex}{\labelindex+1}
            \path (t-\a) -- coordinate[pos=0.5] (temp) (c-\nextindex);
                \node at ($(temp)+(\labelangle:0.2)$) {\labelnumbers{\labelindex}};

            }
    }
    \foreach \a in {1,...,#1}
    {   \coordinate (c-\a) at (t-\a);
    }
    }
}

\newcommand{\labelnumbers}{}

\begin{tikzpicture}
    \DrawIteraredReGularPolygon{3}{5}{3}{black}{white}{white}{0.5}{a\or b\or c\or d\or e\or f\or g\or h\or i\or j\or k\or l\or m\or n\or o}{0.5}
\end{tikzpicture}

\end{document}

Output

enter image description here


Edit 6: Now it should work to place labels of arbitrary width (if the triangle is big enough).

Code

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc, positioning}
\usepackage{xifthen}

\begin{document}

\newcommand{\DrawIteraredReGularPolygon}[9]%
% 1: number of  corners
% 2: corner radius
% 3: iterations
% 4: draw options
% 5: start color
% 6: end color
% 7: fraction
% 8: label names
% 9: label position
{ \renewcommand{\labelnumbers}[1]%
    {   \ifcase##1
        #8
        \else ERROR!
        \fi
    }
    \foreach \a in {1,...,#1}
  { \coordinate (c-\a) at (360/#1*\a+90:#2);
  }
  \foreach \iteration in {1,...,#3}
  { \pgfmathtruncatemacro{\colorpercentage}{int((\iteration-1)/(#3-1)*100)}
    \draw[#4, fill=#6!\colorpercentage!#5] (c-1)
    \foreach \a in {2,...,#1}
    { -- (c-\a)
    } -- cycle;
    \foreach \a in {1,...,#1}
    {   \pgfmathtruncatemacro{\nextindex}{mod(\a,#1)+1}
        \coordinate (t-\a) at ($(c-\a)!#7!(c-\nextindex)$);
        \path (c-\a);
        \pgfgetlastxy{\tempx}{\tempy}
        \path (c-\nextindex);
        \pgfgetlastxy{\tempxx}{\tempyy}
        \pgfmathsetmacro{\labelangle}{atan2(\tempyy-\tempy,\tempxx-\tempx)-90}

            \ifthenelse{\iteration = #3}
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*#1*2+\a-1}
                \path (c-\a) -- coordinate[pos=0.5] (temp) (c-\nextindex);
                \node[label={\labelangle:\labelnumbers{\labelindex}}] at ($(temp)+(\labelangle:-0.15)$) {};
            }
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*#1*2+2*(\a-1)}
                \path (c-\a) -- coordinate[pos=#9] (temp) (t-\a);
                \node[label={\labelangle:\labelnumbers{\labelindex}}] at ($(temp)+(\labelangle:-0.15)$) {};

                \pgfmathtruncatemacro{\labelindex}{\labelindex+1}
            \path (t-\a) -- coordinate[pos=1-#9] (temp) (c-\nextindex);
            \node[label={\labelangle:\labelnumbers{\labelindex}}] at ($(temp)+(\labelangle:-0.15)$) {};
            }
    }
    \foreach \a in {1,...,#1}
    {   \coordinate (c-\a) at (t-\a);
    }
    }
}

\newcommand{\labelnumbers}{}

\begin{tikzpicture}
    \DrawIteraredReGularPolygon{3}{7}{3}{black}{white}{white}{0.5}{$X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$\or $X \wedge \neg Z$}{0.65}
    \end{tikzpicture}

\end{document}

Output

enter image description here


Edit 7: I switched to pgfkeys so that one has named parameters and can also have more than nine.

Code

\documentclass[tikz, border=2mm]{standalone}
\usetikzlibrary{calc, positioning}
\usepackage{xifthen}

\begin{document}

\tikzset{
    iterngramopt/.is family,
    iterngramopt,
    radius/.initial=5,
    corners/.initial=5,
    iterations/.initial=3,
    start color/.initial=white,
    end color/.initial=white,
    draw options/.style={black},
    side fraction/.initial=0.5,
    label names/.initial={a,b,c},
    label position/.initial=0.5,
    label options/.style={},
}

\newcommand{\INKey}[1] % access a specific key by name
{\pgfkeysvalueof{/tikz/iterngramopt/#1}}

\newcommand{\IteratedNGram}[1]%
% 1: options as "key1=value, key2=value, ..."
{ \tikzset{iterngramopt,#1} % Process Keys passed to command

    \xdef\LabelNames{\INKey{label names}}   
    \foreach \Label [count=\c] in \LabelNames
    {   \expandafter\xdef\csname LabelNo\c\endcsname{\Label}
        %\node at (5,6-\c) {This is label number \c: \csname LabelNo\c\endcsname};
    }

    \foreach \a in {1,...,\INKey{corners}}
  { \coordinate (c-\a) at (360/\INKey{corners}*\a+90:\INKey{radius});
  }
  \foreach \iteration in {1,...,\INKey{iterations}}
  { \pgfmathtruncatemacro{\colorpercentage}{int((\iteration-1)/(\INKey{iterations}-1)*100)}
    \colorlet{mystartcolor}{\INKey{start color}}
    \colorlet{myendcolor}{\INKey{end color}}
    \draw[iterngramopt/draw options, fill=myendcolor!\colorpercentage!mystartcolor] (c-1)
    \foreach \a in {2,...,\INKey{corners}}
    { -- (c-\a)
    } -- cycle;
    \foreach \a in {1,...,\INKey{corners}}
    {   \pgfmathtruncatemacro{\nextindex}{mod(\a,\INKey{corners})+1}
        \coordinate (t-\a) at ($(c-\a)!\INKey{side fraction}!(c-\nextindex)$);
        \path (c-\a);
        \pgfgetlastxy{\tempx}{\tempy}
        \path (c-\nextindex);
        \pgfgetlastxy{\tempxx}{\tempyy}
        \pgfmathsetmacro{\labelangle}{atan2(\tempyy-\tempy,\tempxx-\tempx)-90}

            \ifthenelse{\iteration = \INKey{iterations}}
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*\INKey{corners}*2+\a}
                \path (c-\a) -- coordinate[pos=0.5] (temp) (c-\nextindex);
                \node[label={[iterngramopt/label options]\labelangle:\csname LabelNo\labelindex\endcsname}] at ($(temp)+(\labelangle:-0.15)$) {};
            }
            {   \pgfmathtruncatemacro{\labelindex}{(\iteration-1)*\INKey{corners}*2+2*(\a)-1}
                \path (c-\a) -- coordinate[pos=\INKey{label position}] (temp) (t-\a);
                \node[label={[iterngramopt/label options]\labelangle:\csname LabelNo\labelindex\endcsname}] at ($(temp)+(\labelangle:-0.15)$) {};

                \pgfmathtruncatemacro{\labelindex}{\labelindex+1}
            \path (t-\a) -- coordinate[pos=1-\INKey{label position}] (temp) (c-\nextindex);
            \node[label={[iterngramopt/label options]\labelangle:\csname LabelNo\labelindex\endcsname}] at ($(temp)+(\labelangle:-0.15)$) {};
            }
    }
    \foreach \a in {1,...,\INKey{corners}}
    {   \coordinate (c-\a) at (t-\a);
    }
    }
}

\newcommand{\labelnumbers}{}

\begin{tikzpicture}
    \IteratedNGram{%
        corners=3,
        label names={a,b,c,d,e,f,ggg,hhhh,ii,j j,$k_k$,$l_l^l$,m,n nn,o},
        start color=red!10,
        end color=blue!10,
        iterations=3,
        label options/.style={thick,violet,draw, rounded corners, outer sep=2pt},
        draw options/.style={red, thick, densely dashed},
        side fraction=0.47,
        label position=0.57,
    }
    \end{tikzpicture}

\end{document}

Output

enter image description here

  • 4
    Everybody is complaining about my handwriting these days – percusse Nov 5 '15 at 9:46
  • @tom bombadil how exactly will I be able to produce this animation? – Reinhard Neuwirth Nov 10 '15 at 22:16
  • 2
    @ReinhardNeuwirth: The above code produces a PDF with 72 pages which act as frames for the animation. For the conversion to GIF you'll need ImageMagick. Then you can use the command line tool of your choice to navigate to the directory of the PDF and type the following: convert -loop 0 -delay 5 -dispose previous -density 50. There are many more options available, have a look on the website! – Tom Bombadil Nov 11 '15 at 7:17
  • Any idea how to pick out the first two triangles (iterations) and label the sides and points? – Relative0 Nov 19 '15 at 2:19
  • @Relative0: Does the naming follow some pattern, or should it be completely customizable? – Tom Bombadil Nov 19 '15 at 12:12
15

You can do recursion with any initial triangle with node names below. I didn't test it but it should be roughly around this code.

\documentclass[border=5pt,tikz]{standalone}
\begin{document}
\begin{tikzpicture}
% initial path
\draw (0,0)--coordinate(t1)++(0:10cm)--coordinate(t2)++(120:10cm)-- coordinate (t3) cycle;
% define the recursion
\def\tricurse#1{%
  \ifnum#1=0\else% If zero stop
    \draw (t1)--coordinate(t1)(t2)--coordinate(t2)(t3)--coordinate(t3) cycle;%draw and rename
    \tricurse{\number\numexpr#1-1\relax}%Recurse with counter value - 1
  \fi% endif
}
\tricurse{7}
\end{tikzpicture}
\end{document} 

enter image description here

  • +1 Screenshot added ;) Are you happy with the result? – Gonzalo Medina Nov 4 '15 at 23:56
  • @GonzaloMedina Much appreciated. Not so much about my ridiculous choice of triangle though :) – percusse Nov 4 '15 at 23:56
  • I liked the initial triangle :) what is most important is the solution and not the initial triangle; in any case, I produced a boring equilateral triangle now. I hope you don't mind. – Gonzalo Medina Nov 5 '15 at 0:03
  • @GonzaloMedina Of course not. – percusse Nov 5 '15 at 0:09
  • "...Are you happy with the result" ... "of course not" ... Those comments are confusing if you don't pay attention to the time stamps =). – Chris Chudzicki Nov 5 '15 at 0:33
7

While this answer does not even approach Tom Bombadil's, I can't help but point out that L-systems offer a nice, compact way to draw many sorts of fractals to arbitrary depth.

\documentclass[border=5pt,tikz,png]{standalone}
\usetikzlibrary{lindenmayersystems}
\pgfdeclarelindenmayersystem{inner triangle}{
  \symbol{h}{\tikzset{scale=0.5}}
  \rule{T -> F++F++F++hf+T}  % F draw forward
                             % + rotate 60 degrees counterclockwise (angle=60 specified below)
                             % h (defined above) scale all subsequent down by two
                             % f move forward without drawing
                             % T recurse (draw another triangle)
}
\begin{document}
\tikz \draw [line join=round, line cap=round,
             l-system={inner triangle, axiom=T, step=10cm, angle=60, order=8}]
  l-system;
\end{document}

To demonstrate the versatility of this approach for drawing fractals, here's another favorite of mine:

nonKoch snowflake fractal

\documentclass[border=5pt,tikz,png]{standalone}
\usetikzlibrary{lindenmayersystems}
\pgfdeclarelindenmayersystem{snowflake}{
  \rule{F -> [+F--F]-F++F-}
}
\begin{document}
\tikz \draw [line join=round, line cap=round, ultra thick,
             l-system={snowflake,
                       axiom=[F]++++[F]++++[F]++++[F]++++[F]++++F,
                       step=0.5cm, angle=15, order=5}]
  l-system;
\end{document}
  • Wow, very nice, L-Systems was the first thing I did, until I realized that this question was not asking for a Sierpinski-Triangle. Unfortunately, I wasn't able to come up with a solution for this. How did you find it? – Tom Bombadil Nov 27 '15 at 2:32
  • The same way you "found" your solution and percusse "found" his--a touch of creativity and a large dollop of familiarity with the tools. Long before I heard of Tex, I had a hobby of drawing fractals using L-systems. The requested image is no harder to draw this way than a Pythagorean tree, for instance. – Charles Staats Nov 27 '15 at 5:23
  • I only heard of L-Systems a few months back through TikZ. While I did some of the common ones (like Koch's snow flake or the dragon curve), I'm not yet familiar with the stuff. But thanks to you, I now know of a new concept, scaling, and thus having lines of different lengths! Thanks for that! – Tom Bombadil Nov 27 '15 at 13:58
  • Oh, and by "how did you find it", I was hoping for something like this Wikipedia list, so some long list for finding nice new stuff ;-) – Tom Bombadil Nov 27 '15 at 14:01
  • I suggest you check out this tutorial. It's designed for the software FRACTINT, but you should be able to adapt the examples to TikZ by defining appropriate symbols where necessary. – Charles Staats Nov 29 '15 at 18:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.