20

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

1
  • 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$}; Nov 22, 2015 at 0:42

3 Answers 3

30
+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

9
  • 4
    Everybody is complaining about my handwriting these days
    – percusse
    Nov 5, 2015 at 9:46
  • @tom bombadil how exactly will I be able to produce this animation? Nov 10, 2015 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! Nov 11, 2015 at 7:17
  • Any idea how to pick out the first two triangles (iterations) and label the sides and points?
    – Relative0
    Nov 19, 2015 at 2:19
  • @Relative0: Does the naming follow some pattern, or should it be completely customizable? Nov 19, 2015 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

5
  • +1 Screenshot added ;) Are you happy with the result? Nov 4, 2015 at 23:56
  • @GonzaloMedina Much appreciated. Not so much about my ridiculous choice of triangle though :)
    – percusse
    Nov 4, 2015 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. Nov 5, 2015 at 0:03
  • @GonzaloMedina Of course not.
    – percusse
    Nov 5, 2015 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 =). Nov 5, 2015 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}
5
  • 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? Nov 27, 2015 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. Nov 27, 2015 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! Nov 27, 2015 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 ;-) Nov 27, 2015 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. Nov 29, 2015 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.