# Drawing rotated triangles inside triangles

How do I draw rotated triangles inside a triangle as shown above? I already know how to draw one triangle; But I'm not able to draw this specific figure. I found a similar example from https://latexdraw.com/tikz-shapes-triangle/

\documentclass[border=0.2cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}

\begin{document}

\begin{tikzpicture}[thick,violet]
\foreach \i in {-30,-28,...,0}{

\node[draw,
fill=violet!10,
isosceles triangle,
isosceles triangle apex angle=60,
minimum size=-2*\i mm,
rotate=\i,inner sep =0pt] at (0,0){};
}

\end{tikzpicture}

\end{document}


Only for comparison, compile with Asymptote.

In all my examples, s is a scale.

A similar code of Thruston's answer.

size(300);
real s=1/8;
for (int m=3; m<=5; ++m){
path[] a={polygon(m)};
for (int i=1; i<= m/s; ++i){
pair[] A;
for (int j=0; j < size(a[i-1]); ++j)
{
A[j] = point(a[i-1],j+s);
}
a[i]=operator --(... A)--cycle;
}
picture P;
for (int i=0; i<a.length; ++i)
filldraw(P,a[i],interp(white,blue,(i+1)*s));
}


Animation:

settings.tex="pdflatex";
import animate;
size(300);
real s=1/8;
animation Ani;

path[] testpolygon(int m)
{
path[] a={polygon(m)};
for (int i=1; i<= m/s; ++i){
pair[] A;
for (int j=0; j < size(a[i-1]); ++j)
{
A[j] = point(a[i-1],j+s);
}
a[i]=operator --(... A)--cycle;
}
return a;
}
for (int n=3; n<=5; ++n){
for (int i=0; i<testpolygon(n).length; ++i){
save();
filldraw(testpolygon(n)[i],interp(white,blue,(i+1)*s));
}
erase();
}
erase();
Ani.movie();


Example 1:

unitsize(3cm);

pair A=(0,0),B=(4,0),C=rotate(60,A)*B;
path d=A--B--C--cycle;
int n=15;
path pic(real s=0.2)
{
pair M=A;
A=relpoint(A--B,s);
B=relpoint(B--C,s);
C=relpoint(C--M,s);
return A--B--C--cycle;
}

for (int i=0; i < n; ++i)
{
if (i==0) draw(d,blue);
else draw(pic(0.2),(i%2 == 1) ? red : blue);
}


Example 2:

unitsize(3cm);

pair A=(0,0),B=(4,0),C=(4,4),D=(0,4);
path d=A--B--C--D--cycle;
int n=15;
path pic(real s=0.2)
{
pair M=A;
A=relpoint(A--B,s);
B=relpoint(B--C,s);
C=relpoint(C--D,s);
D=relpoint(D--M,s);
return A--B--C--D--cycle;
}

for (int i=0; i < n; ++i)
{
if (i==0) fill(d,blue);
else fill(pic(0.2),(i%2 == 1) ? red : blue);
}


Example 3:

unitsize(4cm);

path g=polygon(5);
pair A=point(g,0),B=point(g,1),C=point(g,2),D=point(g,3),E=point(g,4);
path d=A--B--C--D--E--cycle;
int n=35;
path pic(real s=0.2)
{
pair M=A;
A=relpoint(A--B,s);
B=relpoint(B--C,s);
C=relpoint(C--D,s);
D=relpoint(D--E,s);
E=relpoint(E--M,s);
return A--B--C--D--E--cycle;
}

for (int i=0; i < n; ++i)
{
if (i==0) fill(d,blue);
else fill(pic(0.2),(i%2 == 1) ? red : blue);
}


Example 4:

size(300);

void testpolygon(pair[] A, int n=3, real s=0.2, pen p1=green, pen p2=magenta)
{
pair[] a=copy(A);
guide g= operator --(... a)--cycle;
guide pic()
{
pair M=a[0];
for (int i=0; i<a.length; ++i)
{
if (i != (a.length-1))
{
a[i]=relpoint(a[i]--a[i+1],s);
} else {
a[i]=relpoint(a[i]--M,s);
}
}
return operator --(... a)--cycle;
}
for (int i=0; i <= n; ++i)
{
if (i==0) filldraw(g,p1);
else filldraw(pic(),(i%2==1) ? p2 : p1);
}
}

int n=25;
path g=rotate(-60)*polygon(6);
testpolygon(new pair[]{(0,0),point(g,0),point(g,1)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,1),point(g,2)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,2),point(g,3)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,3),point(g,4)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,4),point(g,5)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,5),point(g,0)},n,0.1);


The final code:

\documentclass[12pt]{article}
\usepackage[margin=1.5cm]{geometry}
\usepackage[inline]{asymptote}
\usepackage{graphicx}
\usepackage{subcaption} % https://latex-tutorial.com/tutorials/figures/

\begin{document}

In TeXstudio, Options $\rightarrow$ Configure TeXstudio... $\rightarrow$ Build $\rightarrow$ Build \& View is txs:///asy-pdf-chain $\rightarrow$ OK. Then press Build \& View, processing... (Compile two times)

\begin{figure}[h!]
\centering
\begin{subfigure}[b]{0.4\linewidth}
\centering
\begin{asy}
unitsize(1.5cm);

pair A=(0,0),B=(4,0),C=rotate(60,A)*B;
path d=A--B--C--cycle;
int n=10;
path pic(real s=0.2)
{
pair M=A;
A=relpoint(A--B,s);
B=relpoint(B--C,s);
C=relpoint(C--M,s);
return A--B--C--cycle;
}

for (int i=0; i < n; ++i)
{
if (i==0) filldraw(d,blue,green+0.8bp);
else filldraw(pic(0.2),(i%2 == 1) ? red : blue,green+0.8bp);
}
\end{asy}
\caption{Picture 1}
\end{subfigure}
\begin{subfigure}[b]{0.4\linewidth}
\centering
\begin{asy}
unitsize(1.25cm);

pair A=(0,0),B=(4,0),C=(4,4),D=(0,4);
path d=A--B--C--D--cycle;
int n=10;
path pic(real s=0.2)
{
pair M=A;
A=relpoint(A--B,s);
B=relpoint(B--C,s);
C=relpoint(C--D,s);
D=relpoint(D--M,s);
return A--B--C--D--cycle;
}

for (int i=0; i < n; ++i)
{
if (i==0) filldraw(d,blue,green+0.8bp);
else filldraw(pic(0.2),(i%2 == 1) ? red : blue,green+0.8bp);
}
\end{asy}
\caption{Picture 2}
\end{subfigure}
\begin{subfigure}[b]{\linewidth}
\centering
\begin{asy}[width=10cm]
size(300);

void testpolygon(pair[] A, int n=3, real s=0.2, pen p1=green, pen p2=magenta)
{
pair[] a=copy(A);
guide g= operator --(... a)--cycle;
guide pic()
{
pair M=a[0];
for (int i=0; i<a.length; ++i)
{
if (i != (a.length-1))
{
a[i]=relpoint(a[i]--a[i+1],s);
} else {
a[i]=relpoint(a[i]--M,s);
}
}
return operator --(... a)--cycle;
}
for (int i=0; i <= n; ++i)
{
if (i==0) filldraw(g,p1);
else filldraw(pic(),(i%2==1) ? p2 : p1);
}
}

int n=25;
path g=rotate(-60)*polygon(6);
testpolygon(new pair[]{(0,0),point(g,0),point(g,1)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,1),point(g,2)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,2),point(g,3)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,3),point(g,4)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,4),point(g,5)},n,0.1);
testpolygon(new pair[]{(0,0),point(g,5),point(g,0)},n,0.1);
\end{asy}
\caption{Picture 3}
\end{subfigure}
\end{figure}
Done!
\end{document}


• Good job! I think you should edit your post to put your code inside a an asy environment in a LaTeX document Sep 15, 2021 at 14:44
• @HafidBoukhoulda Yes, I updated my answer. Sep 15, 2021 at 16:49
• @Hafid Boukhoulda: Wrapping the asy code inside an asy environment is convenient, only when you need to be sure that asy graphics uses the same font/text settings used in the document. Otherwise this is absolutely optional (unnecessary) step. Sep 16, 2021 at 5:43
• @g.kov. The idea is to have the drawing code within the same file as the text document. And also to make it easy for beginners who don't know yet asymptote to test the answer. Sep 16, 2021 at 9:11
• @Hafid Boukhoulda: On the contrary, especially for beginners, it is usually much easier and potentially less confusing to test a standalone asy code. Sep 16, 2021 at 10:58

In Metapost you can define a general transform operation by equating any three non-co-linear points. This is wrapped up in luamplib so compile it with lualatex.

\documentclass{standalone}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
beginfig(1);
numeric s; s = 1/8;
for n=3 upto 5:
path t; t = for i=0 upto n-1: 100 up rotated (360/n*i) -- endfor cycle;
transform r;
for i=0 upto 2:
point i of t transformed r = point i + s of t;
endfor
picture P; P = image(
for i=1 upto floor (n/s):
draw t;
fill t withcolor (i * s / n)[white, blue];
t := t transformed r;
endfor
);
draw P shifted (200n, 0);
endfor
endfig;
\end{mplibcode}
\end{document}


Borrowing the scaling calculation from one of the other solutions, you could also do this with MP's zscaled operator. Here is an alternative that allows you more easily to control the angle of rotation a and the number of turns N.

\documentclass{standalone}
\usepackage{luamplib}
\begin{document}
\begin{mplibcode}
beginfig(1);
numeric a, N; a = 12; N = 7;
for n=3 upto 5:
path t; t = for i=0 upto n-1: 100 up rotated (360/n*i) -- endfor cycle;
numeric b, c; c = 180 - 360/n; b = 180 - c - a;
pair r; r = dir a scaled (sind(c) / (sind(a) + sind(b)));
picture P; P = image(
for i=1 upto N:
draw t;
fill t withcolor (i / 2N)[white, blue];
t := t zscaled r;
endfor
);
draw P shifted (200n, 0);
endfor
endfig;
\end{mplibcode}
\end{document}


Here I have set the turn angle to 12° and the number of turns to 7. Note: In order to make the calculations work as expected, you need to keep the turn angle in the range 0 < a < 360/n.

Compile the second example with lualatex to get this:

If you want to learn more about Metapost, then you can find tutorials and examples on the MP page at Tug.

## Explanations

Here is an explanation of how the scaling works, and why it generalizes to polygons with more sides.

For a given angle of rotation α, the original polygon with sides of length a+b needs to be scaled down to one with sides of length c. So the required scaling ratio is c/(a+b). You can't measure the lengths, but you can measure the angles: α is given; γ is 180-360/n where n is the number of sides; and β is 180-α-γ.

The Law of Sines tells us that

sin α / a = sin β / b = sin γ / c = x


hence

ax = sin α, bx = sin β, and cx = sin γ


so the required scaling ratio can be expressed using the sines

c/(a+b) = cx / (ax+bx) = sin γ / (sin α + sin β)


and as you can see from the diagram this works for any regular polygon where n>2.

• Please can you be more precise and cite the solution post ;) .Good job for the generalization to the 4 and five sides polygons. Sep 16, 2021 at 10:09
• I am not quite sure what you mean by "cite the solution post" ? If you mean "how can you adapt my example so that it draws exactly what you posted", then try reducing a to 10 and removing the fill t...  line. All of my examples are only supposed to be starting points for your own experiments! Sep 16, 2021 at 10:28
• Sorry but what I mean is it would be more helpful for the post readers to know exactly which post you reference to with "Borrowing the scaling calculation from one of the other solutions,..." Sep 16, 2021 at 10:38
• OK will do, thanks. Sep 16, 2021 at 10:41

A simple solution with not too much calculation. Just place new vertices at \p% of the previous edge, and then draw.

\documentclass[tikz,border=3.14mm]{standalone}

\begin{document}

\def\n{15}      % Number of triangles
\def\r{3}       % Radius of the larger triangle
\def\p{20}      % Percentage for positioning the next vertex on the edge
\def\col{violet}

\begin{tikzpicture}
\path (90:\r)  coordinate(A)
(210:\r) coordinate(B)
(330:\r) coordinate(C);
\draw[\col,fill=\col!20] (A) -- (B) -- (C) -- cycle;
\foreach \x in {1,...,\n}{%
\path (A) coordinate(M);
\path (A) -- (B) coordinate[pos=\p/100](A)
-- (C) coordinate[pos=\p/100](B)
-- (M) coordinate[pos=\p/100](C);
\draw[\col,fill=\col!20] (A)--(B)--(C)--cycle;
}
\end{tikzpicture}
\end{document}

• When I tried with \def\n{0} , I get two triangles. Am I wrong? Sep 15, 2021 at 14:25
• If you define n to 0, you then try to make a loop from 1 to 0. Issues occur when you do that. Note that n is the number of inner triangles, the larger one is drawn before the loop. It is highly customizable, then, even to draw a higher order regular polygon, for example. Sep 15, 2021 at 14:28

with tikz

\documentclass{article}
\usepackage{xfp}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\sca}{0.85} % scale
\pgfmathsetmacro{\nt}{7} % number of triangles
\coordinate (A1) at (0,0);
\coordinate (B1) at (5,0);
\coordinate (C1) at (60:5);
\draw (A1) -- (B1) -- (C1) -- cycle;

\foreach \x in {2,...,\nt} {
\coordinate (A\x) at ($(A\fpeval{\x-1})!\fpeval{1-\sca}!(B\fpeval{\x-1})$);
\coordinate (B\x) at ($(B\fpeval{\x-1})!\fpeval{1-\sca}!(C\fpeval{\x-1})$);
\coordinate (C\x) at ($(C\fpeval{\x-1})!\fpeval{1-\sca}!(A\fpeval{\x-1})$);
\draw (A\x) -- (B\x) -- (C\x) -- cycle;
}
\end{tikzpicture}
\end{document}


• To elucidate on @polyn's answer, the secret here is not to think of this as rotations, but rather in terms of what's happening geometrically. Each iteration of the triangle has its vertices at some fixed proportion of the line segment between the vertices of the enclosing triangle. Thinking of the problem in mathematical terms always helps with TikZ Sep 15, 2021 at 13:33

With triangle nodes as in the OP MWE: and with the help of the math tikzlibrary

The idea is to rotate and downscale appropriately all the triangles. It can be found that the scale factor s and the rotation angle a are related by:

s=sin(60) / ( sin(120-a) + sin a)

\documentclass[border=0.2cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric,math}

\begin{document}

\begin{tikzpicture}[violet]

\tikzmath{
\dangle=15; % angle variation  between two successive triangles
\scale=(sin(60)/(sin(120-\dangle)+sin(\dangle)); % reduction factor of the triangle sides (from elementary geometry)
\a=50;  % the size of the wider triangle
}

\foreach \i in {0,...,5}{ % (5+1) triangles to draw

\node[draw,line join=round,
fill=violet!10,
regular polygon,
regular polygon sides=3,
minimum size=\a*(\scale)^\i ,
rotate=\i*\dangle,
inner sep =0pt] at (0,0){};
}

\end{tikzpicture}
\end{document}


• Interesting use of calculation too! Sep 15, 2021 at 14:29
• Apologies for stealing your calculation idea in my second solution... Sep 16, 2021 at 9:53

Just another trivial solution with PSTricks for either fun or comparison purposes.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-calculate,pst-node,multido}
\begin{document}
\begin{pspicture}(10,\pscalculate{5*sqrt(3)})
\pnodes{P}(0,0)(10,0)(10;60)
\psnpolygon(0,\Pnodecount){P}
\foreach \i in {1,2,...,10}
{
\nodexn{.75(P0)+.25(P1)}{Q0}
\nodexn{.75(P1)+.25(P2)}{Q1}
\nodexn{.75(P2)+.25(P0)}{Q2}
\pspolygon(Q0)(Q1)(Q2)
\nodexn{Q0}{P0}
\nodexn{Q1}{P1}
\nodexn{Q2}{P2}
}
\end{pspicture}
\end{document}


# Animated version

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-calculate,pst-node,multido}
\begin{document}
\foreach \N in{0,1,2,...,50}{%
\begin{pspicture}(10,\pscalculate{5*sqrt(3)})
\pnodes{P}(0,0)(10,0)(10;60)
\psnpolygon(0,2){P}
\psLoop{\N}
{
\foreach \i in {0,1,2}{\nodexn{.95(P\i)+.05(P\pscalculate{1+5*\i/2-3*\i^2/2})}{Q\i}}
\foreach \i in {0,1,2}{\nodexn{Q\i}{P\i}}
\psnpolygon(0,2){P}
}
\end{pspicture}}
\end{document}


# General Solution

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-node,pst-plot}

\def\M{60}% number of children

\begin{document}
\foreach \N  in {3,4,...,13}{% number of vertices
\degrees[\N]
\pspicture(-\R,-\R)(\R,\R)
\psnpolygon(0,\numexpr\N-1){P}
\psLoop{\M}
{
\foreach \i in {0,1,...,\numexpr\N-1}{\nodexn{.95(P\i)+.05(P\the\numexpr\i+1\relax)}{Q\i}}
\foreach \i in {0,1,...,\numexpr\N-1}{\nodexn{Q\i}{P\i}}
\nodexn{P0}{P\N}
\psnpolygon(0,\numexpr\N-1){P}
}
\rput[rt](\R,\R){$N=\N$}
\endpspicture}
\end{document}


# Much More General Solution

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-node,pst-plot}
\pstVerb{realtime srand}
\def\M{30}% number of children
\let\closedcurve\psnccurve % other option: \psnpolygon
\begin{document}
\foreach \N  in {3,4,...,20}{% number of vertices
\degrees[\N]
\pspicture(-\R,-\R)(\R,\R)
\curvepnodes[plotpoints=\numexpr\N+1]{0}{\N\space AnytoDeg}{Rand neg 3 mul 3 add 3 div \R\space mul t PtoC}{P}
\closedcurve[linecolor=red](0,\numexpr\N-1){P}
\nodexn{P0}{P\N}
\psLoop{\M}
{
\foreach \i in {0,1,...,\numexpr\N-1}{\nodexn{.85(P\i)+.15(P\the\numexpr\i+1\relax)}{Q\i}}
\foreach \i in {0,1,...,\numexpr\N-1}{\nodexn{Q\i}{P\i}}
\nodexn{P0}{P\N}
\closedcurve(0,\numexpr\N-1){P}
}
\rput[rt](\R,\R){$N=\N$}
\endpspicture}
\end{document}


# The Last And Least

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-node,pst-plot}
\pstVerb{realtime srand}
\def\M{20}% number of children
\let\closedcurve\psnpolygon % other option: \psnpolygon
\begin{document}
\foreach \N  in {3,4,...,40}{% number of vertices
\degrees[\N]
\pspicture[showpoints](-\R,-\R)(\R,\R)
\closedcurve[linecolor=red](0,\numexpr\N-1){P}
\nodexn{P0}{P\N}
\psLoop{\M}
{
\foreach \i in {0,1,...,\numexpr\N-1}{\nodexn{.9(P\i)+.1(P\the\numexpr\i+1\relax)}{Q\i}}
\foreach \i in {0,1,...,\numexpr\N-1}{\nodexn{Q\i}{P\i}}
\nodexn{P0}{P\N}
\closedcurve[strokeopacity=.5](0,\numexpr\N-1){P}
}
\rput[rt](\R,\R){$N=\N$}
\endpspicture}
\end{document}


• +1 for PSTricks. Sep 17, 2021 at 4:55

I pay attention to clean coding from this 2008 link to TikZ and Asymptote. For this figure, Asymptote is more comfortable then TikZ, due to handy array operations. opacity makes the picture more 3D.

With Asymptote, just make an array A to store the vertices of the consecutive polygon in a loop. Another array B is for temporary storing; array operations A.push, A.cyclic=true, B=A have natural meaning; operator--(...A)--cycle is for straight joining the polygon path.

unitsize(1cm);
defaultpen(opacity(.5));
int n=3; // number of vertices
real r=3;
real pos=.1;
pair[] A; A.cyclic=true;
for(int i=0; i<n;++i) A.push(r*dir(90+360*i/n));
filldraw(operator--(...A)--cycle,.1red+.9white);

for(int k=1;k<25;++k){
int kcolor=10+5*k;
pen p=kcolor/100*red+(1-kcolor/100)*white;
pair[] B; B.cyclic=true;
for(int i=0; i<n;++i) B.push(pos*A[i]+(1-pos)*A[i+1]);
filldraw(operator--(...B)--cycle,p);
A=B;
}

shipout(bbox(5mm,Fill(black)));


With TikZ,

\documentclass[tikz,border=5mm]{standalone}
\pagecolor{green!50}
\begin{document}
\begin{tikzpicture}[fill opacity=.5]
\def\n{5}
\def\r{3}
\def\pos{.2}
\colorlet{mycolor}{purple}
\foreach \i in {1,...,\n}
\path ({90+360*\i/\n}:\r) coordinate (A\i);

\path (A\n) coordinate (T);
\draw[fill=mycolor!10] (T) foreach \i in {1,...,\n} {--(A\i)};

\foreach \k in {1,2,...,50}{
\pgfmathsetmacro{\kcolor}{10+5*\k}
\path (T) foreach \i in {1,...,\n}
{--(A\i) coordinate[pos=\pos] (A\i)};

\path (A\n) coordinate (T);
\draw[fill=mycolor!\kcolor] (T) foreach \i in {1,...,\n} {--(A\i)};
}
\end{tikzpicture}
\end{document}

\documentclass[border=0.2cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}

\begin{document}

\begin{tikzpicture}[thick,violet]
\foreach \i in {-30,-28,...,0}{

\node[draw,
fill=violet!10,
isosceles triangle,
isosceles triangle apex angle=60,
minimum size=-2*\i mm,
rotate=\i,inner sep =0pt] at (0,0){};
}

\end{tikzpicture}

\end{document}