\documentclass[french]{article}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{babel}
\usepackage{nopageno}
\usepackage{tikz}
\usepackage[margin=1.5cm]{geometry}
\usepackage{pas-math}
\usepackage[urlcolor=blue, linkcolor=blue, colorlinks=blue, urlbordercolor=white]{hyperref}
\usepackage{listings}
	\lstset{%
		basicstyle=\fontsize{9}{9}\selectfont\ttfamily,
		commentstyle = \color{gray}\ttfamily,
		keywordstyle = \color{green!50!black}\ttfamily,
		tabsize = 3,
		breaklines=true,
		frame=single,
		frameround=tttt,
		showstringspaces=false,
		numbers = left,
		numberstyle = \small\color{gray}\ttfamily,
		language = python,
		inputencoding=utf8,
    	extendedchars=true,
    	emphstyle=\color{red},
    	literate=
        {é}{{\'e}}1
        {è}{{\`e}}1
        {ê}{{\^e}}1
        {à}{{\`a}}1
        {â}{{\^a}}1
        {ç}{{\c{c}}}1
        {ô}{{\^o}}1
        {î}{{\^i}}1
        {ù}{{\`u}}1,
		}
		
\usepackage{enumitem}
	\setlist[itemize,1]{label=$\bullet$}
\usepackage{titlesec}
\titleformat{\section}  % Cible les \section
  {\color{orange!75!red}\bfseries\Large\fontfamily{lmss}\selectfont}   % Style : couleur, gras, taille
  {\tikz[baseline=-0.25em]\node[circle,fill=orange!75!red,text=white]{\thesection};}     % Numérotation
  {1em}             % Espace entre le numéro et le titre
  {}         

\begin{document}
%\maketitle
\begin{center}
\fontfamily{lmss}\selectfont
{
\Huge
\color{orange!50!red}
Un arbre de Pythagore
}

\bigskip
\color{orange!30!red}
\'Ecrit à partir de la vidéo \url{https://www.youtube.com/watch?v=BCR7IhRFNDo}
\end{center}

\section{Notion de similitude}

Considérons:

\begin{itemize}
\item un point $\Omega$ du plan, 
\item un réel $k$,
\item un ange $\alpha$.
\end{itemize}

À tout point $A$ du plan, on peut considérer successivement:

\begin{itemize}
\item son image $A'$ par la rotation de centre $\Omega$ et d'angle $\alpha$,
\item puis $A''$ l'image de $A'$ par l'homothétie de centre $\Omega$ et de rapport $k$.
\end{itemize}

\begin{center}
\begin{tikzpicture}
\fill (0,0) circle (1pt) node[below] {$\Omega$};
\fill (3,0) circle (1pt) node[below] {$A$} ;
\fill (30:3) circle (1pt )node[right] {$A'$};
\fill (30:4.5) circle (1pt )node[right] {$A''$};
\draw (0,0) -- (3,0) node[midway,below] {$\ell$};
\draw[thin,red] (0,0) -- (30:3) node[midway,above] {$\ell$};
\draw[thin, dotted, red] (30:3) -- (30:4.5);
\draw[red,->,>=latex] (0.75,0) arc (0:30:0.75);
\node[right,red] at (15:.8) {$\alpha$};
\draw[orange,->,>=latex] (0,0) to[bend left=30] (30:4.5);
\node[orange,above] at (50:2.3) {$k\ell$};
\end{tikzpicture}
\end{center}
 
À l'aide de la trigonométrie, on démontre que:
\[
\left.\begin{array}{l}
\Omega\coord{x_\Omega}{y_\Omega}\\
A\coord{a}{b}
\end{array}\right\rbrace \Longrightarrow
\begin{cases}
A'\coord{x_\Omega+(a-x_\Omega)\cos\alpha-(b-y_\Omega)\sin\alpha}{y_\Omega+(a-x_\Omega)\sin\alpha+(b-y_\Omega)\cos\alpha}\\
A''\coord{x_\Omega + k(a-x_\Omega)\cos\alpha-k(b-y_\Omega)\sin\alpha}{y_\Omega+k(a-x_\Omega)\sin\alpha+k(b-y_\Omega)\cos\alpha}
\end{cases}
\]

On dit ici que $A''$ est obtenu à partir du point $A$ par similitude de centre $\Omega$, d'angle $\alpha$ et de rapport $k$.

\section{Introduction à l'arbre de Pythagore}

Partons d'un carré $ABCD$ de côté $L$, puis traçons un triangle rectangle $ECD$ tel que $\widehat{CDE}=\theta$, sur lequel nous traçons des carrés:

\begin{center}
\begin{tikzpicture}[scale=0.5]
\draw (0,0) node[below left] {$A$} -- (5,0) node[midway,below] {$L$} node[below right] {$B$} -- (5,5) node[right] {$C$} -- (0,5) node[left] {$D$} -- cycle;
\draw (0,5) -- (2.93,7.46) node[above] {$E$} -- (5,5);
\draw[->,>=latex] (0.75,5) arc (0:40:0.75);
\node[right] at (0.85,5.4) {$\theta$};
\draw[red] (0,5) -- (-2.46, 7.93) node[left] {$G$} -- (0.47,10.4) node[above] {$F$} -- (2.93,7.46);
\draw[red] (2.93,7.46) -- (5.4,9.53) -- (7.46,7.07) -- (5,5);
\end{tikzpicture}
\end{center}

\begin{itemize}
\item Le point $E$ est obtenu par similitude de centre $D$, d'angle $\theta$ et de rapport $k=L\cos\theta$ car $\dfrac{DE}{DC}=\cos\theta$.

\item Le point $F$ est obtenu à partir de $D$ par rotation de centre $E$ et d'angle $-\frac{\pi}{2}$.

\item Le point $G$ est obtenu à partir de $E$ par rotation de centre $D$ et d'angle $\frac{\pi}{2}$.
\end{itemize}

On peut construire de même le carré sur $|EC]$.

\section{Construction de l'arbre de Pythagore}

L'idée est de reproduire ce qui vient d'être expliqué sur les carrés obtenus, et sur ceux qui vont l'être par la suite.

Nous allons faire cela à l'aide de Python:

\begin{lstlisting}
from math import pi, cos, sin
from PIL import Image, ImageDraw 

width = 1748
height = 1240

tree = Image.new('RGB', (width,height), (255,255,255))
draw = ImageDraw.Draw(tree,'RGBA')

theta = pi/180 * 40 # 40 degrés
L = 200 # longueur de l'arête du premier carré
A = (width/2 - L/2 , height-250)
B = (width/2 + L/2 , height-250)

def sim(centre, point, angle, k):
    # angle devient "-angle" dans les sinus à cause de la logique graphique de PIL
    x = centre[0] + k*(point[0]-centre[0])*cos(angle)-k*(point[1]-centre[1])*sin(-angle)
    y = centre[1] + k*(point[0]-centre[0])*sin(-angle)+k*(point[1]-centre[1])*cos(angle)
    
    return x,y

def arbre(A,B,angle,n):
    if n==0: return 
    
    C = sim(B,A,-pi/2,1)
    D = sim(A,B,pi/2,1)
    E = sim(D,C,angle,cos(angle))
    
    draw.polygon([A,B,C,D], fill=(0,0,0,125))
    
    arbre(D, E, angle, n-1)
    arbre(E, C, angle, n-1)
    

arbre(A,B,theta,10)
tree.show()
\end{lstlisting}

\begin{center}
\includegraphics[width=0.75\textwidth]{arbre-gris.png}
\end{center}

\newpage

\begin{lstlisting}
from math import pi, cos, sin
from PIL import Image, ImageDraw 
from random import randint

width = 1748
height = 1240

tree = Image.new('RGB', (width,height), (255,255,255))
draw = ImageDraw.Draw(tree,'RGBA')

theta = pi/180 * 40 # 40 degrés
L = 200 # longueur de l'arête du premier carré
A = (width/2 - L/2 , height-250)
B = (width/2 + L/2 , height-250)

def sim(centre, point, angle, k):
    # angle devient "-angle" dans les sinus à cause de la logique graphique de PIL
    x = centre[0] + k*(point[0]-centre[0])*cos(angle)-k*(point[1]-centre[1])*sin(-angle)
    y = centre[1] + k*(point[0]-centre[0])*sin(-angle)+k*(point[1]-centre[1])*cos(angle)
    
    return x,y

def arbre(A,B,angle,n):
    if n==0: return 
    
    C = sim(B,A,-pi/2,1)
    D = sim(A,B,pi/2,1)
    E = sim(D,C,angle,cos(angle))
    
    draw.polygon([A,B,C,D], fill=(randint(0,255),randint(0,255),randint(0,255),125))
    
    arbre(D, E, angle, n-1)
    arbre(E, C, angle, n-1)
    

arbre(A,B,theta,10)
tree.show()
\end{lstlisting}

\begin{center}
\includegraphics[width=0.9\textwidth]{arbre-couleur.png}
\end{center}

\section{L'arbre est-il \og infini \fg{} ? }

Nous allons noter $C_n$ le centre des carrés allant vers la gauche.

\begin{center}
\begin{tikzpicture}[scale=0.5]
\draw (0,0) node[below left] {$A$} -- (5,0) node[midway,below] {$L$} node[below right] {$B$} -- (5,5) node[right] {$C$} -- (0,5) node[left] {$D$} -- cycle;
\draw (0,5) -- (2.93,7.46) node[above] {$E$} -- (5,5);
\draw[->,>=latex] (0.75,5) arc (0:40:0.75);
\node[right] at (0.85,5.4) {$\theta$};
\draw[red] (0,5) -- (-2.46, 7.93) node[below] {$G$} -- (0.47,10.4) node[right] {$F$} -- (2.93,7.46);
\draw[red] (2.93,7.46) -- (5.4,9.53) -- (7.46,7.07) -- (5,5);
\fill (2.5,2.5) circle (2pt) node[below] {$C_0$};
\fill (0.24,7.7) circle (2pt) node[above] {$C_1$};
\draw[green!50!black] (-2.46,7.93) -- (-1.95,10.82) -- (0.47,10.4);
\draw[green!50!black] (-2.46,7.93) -- (-5.35,8.44) -- (-4.84,11.33) -- (-1.95,10.82);
\draw[green!50!black] (0.47,10.4) -- (0.9,12.82) -- (-1.52,13.25) -- (-1.95,10.82);
\fill (-3.65,9.63) circle(2pt) node[below] {$C_2$};
\draw[dashed,blue] (2.5,2.5) -- (0.24,7.7) -- (-3.65,9.63);
\end{tikzpicture}
\end{center}
On peut observer que:
\[
\dfrac{C_2C_1}{C_1C_0}=\cos\theta.
\]
En effet, $DEFG$ est l'image de $ABCD$ ($DC$ se transforme en $DG$) par la similitude de centre $D$, d'angle $\theta+\frac{\pi}{2}$ et de rapport $k=\cos\theta$ (par construction). De même, le carré vert est l'image du carré rouge par la similitude de centre $G$ et de mêmes angles et rapport.

Toutes les longueurs sont donc multipliées par $\cos\theta$ pour passer d'un carré au suivant.

La suite $(C_{n-1}C_n)$ est donc géométrique de raison $\cos\theta$.

\medskip

Calculons alors longueur:
\begin{align*}
L_n & = \sum_{k=0}^{n-1} C_kC_{k+1}= C_0C_1 + C_1C_2 + \cdots + C_{n-1}C_{n}\\
& = C_0C_1 \times (1 + \cos\theta + \cos^2\theta + \cdots + \cos^n\theta)\\
& = C_0C_1\times\dfrac{1-\cos^{n+1}\theta}{1-\cos\theta}.
\end{align*}

Comme $0 \leqslant \cos\theta < 1$, 
\[
\limite{n}{+\infty}{L_n} = \dfrac{C_0C_1}{1-\cos\theta}.
\]

L'arbre de Pythagore (noté $\mathcal{A}$) ne peut donc pas être \og infini \fg{} (dans le sens où la distance entre $C_0$ et $C_\infty$ ne peut pas être infinie).

\medskip

On appellera \textit{diamètre} le maximum de la distance entre $C_0$ et $C_n$, pour tout entier naturel $n$:
\[
\text{diam}(\mathcal{A})=\max\{C_0C_n,\ n\geqslant1\}.
\]

On peut ainsi modifier le script précédent pour déterminer une valeur approchée du diamètre (en pixels) de l'arbre (voir page suivante).

\newpage

\begin{lstlisting}
from math import pi, cos, sin
from PIL import Image, ImageDraw, ImageFont
from random import randint

width = 1748
height = 1240

tree = Image.new('RGB', (width,height), (255,255,255))
draw = ImageDraw.Draw(tree,'RGBA')

theta = pi/180 * 40 # 40 degrés
L = 200 # longueur de l'arête du premier carré
A = (width/2 - L/2 , height-250)
B = (width/2 + L/2 , height-250)

centres = []

def sim(centre, point, angle, k):
    # angle devient "-angle" dans les sinus à cause de la logique graphique de PIL
    x = centre[0] + k*(point[0]-centre[0])*cos(angle)-k*(point[1]-centre[1])*sin(-angle)
    y = centre[1] + k*(point[0]-centre[0])*sin(-angle)+k*(point[1]-centre[1])*cos(angle)
    
    return x,y
 
def arbre(A,B,angle,n):
    if n==0: return 
    
    global centres
    
    C = sim(B,A,-pi/2,1)
    D = sim(A,B,pi/2,1)
    E = sim(D,C,angle,cos(angle))
    
    centres.append(((A[0]+C[0])/2,(A[1]+C[1])/2))
    
    draw.polygon([A,B,C,D], fill=(randint(0,255),randint(0,255),randint(0,255),125))
    
    arbre(D, E, angle, n-1)
    arbre(E, C, angle, n-1)
    
def diam():
    global centres
    origine = centres[0] # premier centre
    d = 0
    
    for c in centres:
        if c != origine:
            distance = (origine[0]-c[0])**2 + (origine[1]-c[1])**2
            if distance > d:
                d = distance
                faraway = c
                
    return d**0.5, faraway

arbre(A,B,theta,10)
diametre = f"Diamètre de l'arbre: {diam()[0]}"
draw.text((10,10), diametre, font=ImageFont.truetype("arial.ttf", size=30), fill=(0, 0, 0, 255))
# on trace le diamètre
draw.line([centres[0],diam()[1]],fill=(100,100,100),width=1) 

tree.show()
\end{lstlisting}

\newpage

\begin{center}
\texttt{n=10}

\includegraphics[width=0.85\textwidth]{arbre-couleur-2.png}

\medskip

\texttt{n=15}

\includegraphics[width=0.85\textwidth]{arbre-couleur-3.png}

\newpage

\texttt{n=20}

\includegraphics[width=0.75\textwidth]{arbre-couleur-4.png}

\medskip

\texttt{n=20, angle=22.5}

\includegraphics[width=0.75\textwidth]{arbre-couleur-5.png}

\end{center}

\newpage

Ce dernier exemple est intéressant: on aimerait que le nombre d'itérations soit plus grand afin que la \og spirale \fg{} continue davantage... Nous allons donc légèrement modifier le script afin de le permettre car avec ce que nous avons, pour $n=25$, ça plante...

\begin{lstlisting}
from math import pi, cos, sin
from PIL import Image, ImageDraw, ImageFont
from random import randint

width = 1748
height = 1240

tree = Image.new('RGB', (width,height), (255,255,255))
draw = ImageDraw.Draw(tree,'RGBA')

theta = pi/180 * 22.5
L = 150 # longueur de l'arête du premier carré
A = (width/2 - L/2 +100, height-250)
B = (width/2 + L/2 +100, height-250)

centres = []

def sim(centre, point, angle, k):
    # angle devient "-angle" dans les sinus à cause de la logique graphique de PIL
    x = centre[0] + k*(point[0]-centre[0])*cos(angle)-k*(point[1]-centre[1])*sin(-angle)
    y = centre[1] + k*(point[0]-centre[0])*sin(-angle)+k*(point[1]-centre[1])*cos(angle)
    
    return x,y
 
def arbre(A,B,angle,n):
    if (n==0) or (length(A,B)<8): return 
    
    global centres
    
    C = sim(B,A,-pi/2,1)
    D = sim(A,B,pi/2,1)
    E = sim(D,C,angle,cos(angle))
    
    centres.append(((A[0]+C[0])/2,(A[1]+C[1])/2))
    
    draw.polygon([A,B,C,D], fill=(randint(0,255),randint(0,255),randint(0,255),125))
    
    arbre(D, E, angle, n-1)
    arbre(E, C, angle, n-1)

def length(A,B):
    return (A[0]-B[0])**2 + (A[1]-B[1])**2
    
def diam():
    global centres
    origine = centres[0] # premier centre
    d = 0
    
    for c in centres:
        if c != origine:
            distance = length(origine,c) #(origine[0]-c[0])**2 + (origine[1]-c[1])**2
            if distance > d:
                d = distance
                faraway = c
                
    return d**0.5, faraway

arbre(A,B,theta,50)
diametre = f"Diamètre de l'arbre: {diam()[0]}"
draw.text((10,10), diametre, font=ImageFont.truetype("arial.ttf", size=30), fill=(0, 0, 0, 255))
draw.line([centres[0],diam()[1]],fill=(100,100,100),width=1) 

tree.show()
\end{lstlisting}

Nous avons introduit:
\begin{itemize}
\item une nouvelle fonction \texttt{length} qui permet de renvoyer le carré de la distance entre deux points;
\item un test dans la fonction \texttt{arbre}: on n'exécute la fonction que si $AB^2 > 8$ (par exemple). En effet, inutile d'aller plus loin si l'on ne voit plus les points.
\end{itemize}

Cette modification donne, pour $n=50$:

\begin{center}
\includegraphics[width=\textwidth]{arbre-couleur-6.png}
\end{center}
\end{document}