Voici le dessin de spirale(90) :
igtortue/spirale.tex
On tape :
spirale(l):={ si (l>10) alors avance(l); tourne_gauche 90; avance(l); tourne_gauche 90; spirale(l-10); fsi }
On tape :
//chaque segment de la spirale est obtenu par similitude de rapport k //k=rapport et t=angle de rotation (externe) //n=nombre de segments a construire spirale(l,k,t,n):={ for (j:=1;j<=n;j++){ avance(l); tourne_gauche(t); l:=k*l; } };
ou encore avec la recursivité
//n=nombre de segments a construire=nombre d'appels recursifs spiraler(l,k,t,n):={ if (n>0) { avance(l); tourne_gauche(t); spiraler(l*k,k,t,n-1); } };
On tape par exemple :
spiraler(90,0.8,60,20)
On obtient :
igtortue/spiraler.tex
Un arbre est composé d’un tronc de hauteur h et de deux branches
symétriques faisant 45 degrés avec le tronc et que l’on définit comme
étant chacune un arbre de tronc h/2.
Pour le réaliser, on tape :
//tourne_gauche;arbre1(60) arbre1(h):={ si (h<5) alors avance(h); recule(h); sinon avance(h); tourne_droite(45); arbre1(h/2); tourne_gauche(90); arbre1(h/2): tourne_droite(45); recule(h); fsi; }
Ou bien, on rajoute un paramètre n (la profondeur) pour faire le test d’arrêt, on tape :
//tourne_gauche;arbre2(60,3) arbre2(h,n):={ si (n==0) alors avance(h); recule(h); sinon avance(h); tourne_droite(45); arbre2(h/2,n-1); tourne_gauche(90); arbre2(h/2,n-1): tourne_droite(45); recule(h); fsi; }
Un arbre est composé d’un tronc de hauteur h et de p branches
également réparties et que l’on définit comme
étant chacune un arbre de tronc h/2.
//tourne_gauche;arbre3(60,4) arbre3(h,p):={ si (h<5) alors avance(h); recule(h); sinon avance(h); tourne_droite(90*(p-1)/p); repete(p,arbre3(h/2,p),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); recule(h); fsi }
Ou bien, on rajoute un paramètre n (la profondeur) pour faire le test d’arrêt, on tape :
//tourne_gauche;arbre4(60,5,3) arbre4(h,p,n):={ si (n==0) alors avance(h); recule(h); sinon avance(h); tourne_droite(90*(p-1)/p); repete(p,arbre4(h/2,p,n-1),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); recule(h); fsi }
Et maintenant, un arbre aléatoire :
à chaque nœud on choisit, de façon aléatoire le rapport k de
réduction, qui fera les p branches comme un arbre réduit avec le
coefficient k.
On tape
//tourne_gauche ;saute(-80);arbre5(60,4,3); arbre5(h,p,n):={ local k; si (n==0) alors avance(h); recule(h); sinon avance(h); tourne_droite(90*(p-1)/p); k:=rand(0,1); repete(p,arbre5(h*k,p,n-1),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); recule(h); fsi; }
efface(); tourne_gauche ; saute(-80); arbre5(60,4,3);
igtortue/arbrer.tex
Et enfin, un arbre encore plus aléatoire :
pour chaque branche on choisit, de façon aléatoire le rapport
rand(0,1) de réduction, qui fera cette branche comme un arbre réduit
avec ce coefficient.
On tape
//tourne_gauche ;saute(-80);arbre6(60,4,3); arbre6(h,p,n):={ si (n==0) alors avance(h); recule(h); sinon avance(h); tourne_droite(90*(p-1)/p); repete(p,arbre6(h*rand(0,1),p,n-1),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); recule(h); fsi; }
efface(); tourne_gauche ; saute(-80); arbre6(60,4,3);
igtortue/arbrea.tex
Ici on suppose que, du tronc de longueur h, il part p branches de longueur h/2. Ces branches donnent naissance à p−1 branches de longueur h/4 etc... jusqu’à p=2.
//tourne_gauche;saute(-80);arbre7(60,5) arbre7(h,p):={ avance(h); si (p>=2) alors tourne_droite(90*(p-1)/p); repete(p,arbre7(h/2,p-1),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); fsi; recule(h); }
Puis on tape :
efface(); tourne_gauche ; saute(-80); arbre7(60,5);
En utilisant aussi la profondeur dans le test d’arrêt on tape :
//tourne_gauche;saute(-80);arbre8(90,5,3) arbre8(h,p,n):={ avance(h); si (p>=2 et n>=1) alors tourne_droite(90*(p-1)/p); repete(p,arbre8(h/2,p-1,n-1),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); fsi; recule(h); }
Puis on tape :
efface(); tourne_gauche ; saute(-80); arbre8(60,5,3);
On obtient :
igtortue/arbrera.tex
Les 8 procédures ci-dessus se trouvent dans le fichier :
examples/tortue/arbre.cxx.
Exercice
Refaire les exemples précédents mais en ne dessinant que la frondaison de
l’arbre, c’est à dire l’arbre sans son tronc.
Une réponse
Voici la réponse correspondant à arbre7 et à arbre8. Bien
sûr, pour avoir la frondaison de arbre7(60,5) il faut taper
arbre9(30,5) et pour avoir la frondaison de arbre8(60,5,3) il faut
taper arbre10(30,5,3).
//tourne_gauche;saute(-80);arbre9(90,5,3) arbre9(h,p):={ si (p>=2) alors tourne_droite(90*(p-1)/p); repete(p,avance(h),arbre9(h/2,p-1),recule(h),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); fsi; }
//tourne_gauche;saute(-80);arbre10(90,5,3) arbre10(h,p,n):={ si (n>=1 et p>=2) alors tourne_droite(90*(p-1)/p); repete(p,avance(h),arbre10(h/2,p-1,n-1),recule(h),tourne_gauche(180/p)); tourne_droite(90*(p+1)/p); fsi; }
On décrit un sapin comme étant composé de :
- deux branches basses
latérales symétriques et faisant un angle de 60 degrés avec le tronc,
- d’un bout de tronc et
- d’une tête.
Cette définition sera
récursive si on dit que les deux branches basses
latérales sont des sapins plus petits (de hauteur égale à la moitié de
la hauteur du sapin) et que la
tête est aussi un sapin plus petit (de hauteur égale au trois-quart de
la hauteur du sapin). Le tronc a donc pour hauteur le quart de la hauteur du
sapin. Il nous faut alors définir ce que l’on considére
comme sapin "initial" : c’est le sapin formé d’un tronc unique.
Il faut choisir un paramètre par exemple la hauteur h du sapin.
Voici la croissance de ces sapins :
igtortue/sapinr.tex
On tape :
//tourne_gauche;sapin1(90) sapin1(h):={ si (h<5) alors avance(h); recule(h); sinon tourne_droite(60); sapin1(h/2); tourne_gauche(120); sapin1(h/2): tourne_droite(60); avance(h/4); sapin1(3*h/4); recule(h/4); fsi; }
Ou on tape en utilisant pour faire le test d’arrêt la profondeur n :
//tourne_gauche;sapin2(90,4) sapin2(h,n):={ si (n==0) alors avance(h); recule(h); sinon tourne_droite(60); sapin2(h/2,n-1); tourne_gauche(120); sapin2(h/2,n-1): tourne_droite(60); avance(h/4); sapin2(3*h/4,n-1); recule(h/4); fsi; }
Les différentes étapes ont été obtenus en exécutant :
tourne_gauche; sapin2(90,0) puis
tourne_gauche; sapin2(90,1) puis
tourne_gauche; sapin2(90,2) puis
tourne_gauche; sapin2(90,3) puis
tourne_gauche; sapin2(90,4).
Les 2 procédures ci-dessus se trouvent dans le fichier :
examples/tortue/sapin.cxx
Voici les étapes de construction d’une courbe découverte par Koch :
igtortue/flocon.tex
On voit l’étape 0 : un segment de longueur l.
Pour obtenir l’étape 1, on divise ce segment de longueur l en trois et on
réalise la deuxième figure qui est composée de quatre segments de
longueur l/3 (le deuxiéme et troisiéme segments sont les côtés d’un
triangle équilatéral),
puis on recommence en transformant chacun de ces 4 segments en 4 segments....
et cela tant que l ≥ 10.
La troisiéme figure est alors koch1(90).
On tape :
//koch1(90) koch1(l):={ si (l<10) alors avance(l); sinon koch1(l/3);tourne_gauche(60); koch1(l/3);tourne_droite(120); koch1(l/3);tourne_gauche(60); koch1(l/3); fsi; };
Ou on tape en utilisant un paramètre n représentant la profondeur (i.e. le nombre d’appels récursifs) :
//koch2(90,3) koch2(l,n):={ si (n==0) alors avance(l); sinon koch2(l/3,n-1);tourne_gauche(60); koch2(l/3,n-1);tourne_droite(120); koch2(l/3,n-1);tourne_gauche(60); koch2(l/3,n-1); fsi; };
Les dessins des différentes étapes ont été obtenus en tapant :
koch2(90,0) puis,
koch2(90,1) puis,
koch2(90,2) et,
koch2(90,3)
Les 2 procédures ci-dessus se trouvent dans le fichier :
examples/tortue/koch.cxx
Parmi les nombreuses courbes inventées par Péano, prouvant l’existence de courbes remplissant un carré, on n’en retiendra que trois, celles décrites dans les paragraphes suivants.
Soit un carré de diagonale l :
au jour 0, on trace une diagonale,
au jour 1, on divise ce carré en 9 carrés et on trace les diagonales de ces
carrés, de façon à avoir un trait continu en parcourant la première
ligne, puis la deuxième, et enfin la troisième, comme ci-dessous :
igtortue/peano.tex
puis on recommence le même processus.
On tape :
//peano(90) peano(l):={ si (l<10) alors avance(l); sinon peano(l/3); tourne_droite;peano(l/3); tourne_gauche;peano(l/3); tourne_gauche;peano(l/3); tourne_gauche;peano(l/3); tourne_droite;peano(l/3); tourne_droite;peano(l/3); tourne_droite;peano(l/3); tourne_gauche;peano(l/3); fsi };
Soit un carré de coté l :
au jour 0, on trace un segment de longueur l i.e. un coté du carré,
au jour 1, on remplace ce segment, en tracant les trois coés d’un rectangle
de largeur l/2 et de longueur l,
au jour 2, on remplace chaque segment de longueur k, en tracant les trois
coés d’un rectangle de largeur k/2 et de longueur k comme cela :
igtortue/peanobi.tex
puis on recommence le même processus.
On remarque que l’on remplace un segment en tracant un rectangle situé soit
à droite soit à gauche de la position de la tortue : on introduit donc un
paramètre s qui vaut 1 si ce rectangle se situe à droite et qui vaut -1
si ce rectangle se situe à gauche.
On tape :
//peanob(90,1) peanob(l,s):={ si (l<10) alors avance(l); sinon tourne_gauche(-90*s);peanob(l/2,-s); tourne_droite(-90*s);peanob(l/2,s); peanob(l/2,s);tourne_droite(-90*s); peanob(l/2,-s);tourne_gauche(-90*s); fsi };
Au jour 1, on trace la première courbe peano1(l,0) dans le carré de
coté l,
Au jour 2, on trace la deuxème courbe dans le carré de coté l
obtenue en partageant le carré en 9 carrés et en traçant dans le premier carré peano1(l,0), et dans les autres soit
peano1(l,1), soit peano1(l,-1), de façon à ce que les
courbes se raccordent entre elles.
Voici les dessins, où la position de départ et d’arrivée de la tortue est
choisie comme indiquée sur la première figure :
igtortue/peanoter.tex
peano1(l,0) peanot(l,0) peano1(l,1) peano1(l,-1)
//peano1(30,0) ou peano1(30,-1) ou peano1(30,1) peano1(l,s):={ si (s==-1) alors tourne_droite(45);saute(-l*sqrt(2)/6);rond(round(l*sqrt(2)/6),90); sinon si (s==1) alors tourne_gauche(135);saute(-l*sqrt(2)/6);rond(round(-l*sqrt(2)/6),90); sinon tourne_gauche(45); saute(l*sqrt(2)/6); fsi; fsi; rond(round(l*sqrt(2)/6),90); rond(round(-l*sqrt(2)/6),270); rond(round(l*sqrt(2)/6),270); rond(round(-l*sqrt(2)/6),90); saute(l*sqrt(2)/6); tourne_droite(45); }; //peanot(90,0) peanot(l,s):={ si (l<31) alors peano1(l,s); sinon si (s==-1) alors peanot(l/3,-1); sinon si (s==1) alors peanot(l/3,1); sinon peanot(l/3,0); fsi; fsi; tourne_droite;peanot(l/3,1); tourne_gauche;peanot(l/3,-1); tourne_gauche;peanot(l/3,-1); tourne_gauche;peanot(l/3,-1); tourne_droite;peanot(l/3,1); tourne_droite;peanot(l/3,1); tourne_droite;peanot(l/3,1); tourne_gauche;peanot(l/3,-1); fsi; };
ou bien en supprimant les saute, les tourne et les √2, c’est
à dire en prenant comme départ et d’arrivée de la tortue les tangentes
aux arcs et comme paramètre l la diagonale du carré et en rajoutant le
paramètre n pour la profondeur.
On tape :
//peano2(30,0) ou peano2(30,-1) ou peano2(30,1) peano2(l,s):={ si (s==-1) alors rond(round(l/6),90); sinon si (s==1) alors rond(round(-l/6),90); fsi; fsi; rond(round(l/6),90); rond(round(-l/6),270); rond(round(l/6),270); rond(round(-l/6),90); }; //tourne_gauche 45;peanot2(90,0,2) peanot2(l,s,n):={ si (n==1) alors peano2(l,s); sinon si (s==-1) alors peanot2(l/3,-1,n-1); sinon si (s==1) alors peanot2(l/3,1,n-1); sinon peanot2(l/3,0,n-1); fsi; fsi; peanot2(l/3,1,n-1); peanot2(l/3,-1,n-1); peanot2(l/3,-1,n-1); peanot2(l/3,-1,n-1); peanot2(l/3,1,n-1); peanot2(l/3,1,n-1); peanot2(l/3,1,n-1); peanot2(l/3,-1,n-1); fsi; };
Puis on tape par exemple :
tourne_gauche 45; peanot2(90,0,2)
On remarquera que peanot2 commence à un sommet du carré et se termine
en un point proche du sommet opposé : le point d’arrivée est ici fonction
de la valeur du paramètre n et est a une distance de l/3n+1 du
sommet opposé.
Si on définit :
//peanot1(90,0,2) peanot1(l,s,n):={ tourne_gauche 45; saute(l/2/3^n); peanot2(l,s,n); saute(l/2/3^n); tourne_droite 45; }
On a :
peanot1(l/sqrt(2),s,n) ressemble à peanot(l,s)....mais ce n’est
pas parfait à cause des erreurs d’arrondis.
Les procédures ci-dessus se trouvent dans le fichier :
examples/tortue/peano.cxx
C’est une courbe remplissant un carré qui a été
découverte par Hilbert :
cette courbe se fait a partir de quatre procédures récursives qui
s’appellent les unes les autres et que j’ai
appelé hilbg, hilbd, bertg, bertd.
Voici les étapes de construction :
- au jour 0 on trace un segment,
- au jour 1 on trace les dessins où on a dessiné les positions de départ
et d’arrivée de la tortue (la forme pleine représente la tortue au départ
et la forme vide celle d’arrivée).
igtortue/hilbert.tex
hilbg hilbd bertg bertd
hilbg est composée de 4 segments qui sont le dessin obtenu au jour 0
par hilbd hilbg bertg bertd
hilbd est composée de 4 segments qui sont le dessin obtenu au jour 0
par hilbg hilbd bertd bertg
bertg est composée de 4 segments qui sont le dessin obtenu au jour 0
par hilbd hilbg bertg hilbd
bertd est composée de 4 segments qui sont le dessin obtenu au jour 0
par hilbg hilbd bertd hilbg
On écrit :
//hilbg(200) hilbg(l):={ si (l<10) alors avance(l); sinon tourne_gauche(90);hilbd(l/2); tourne_droite(90);hilbg(l/2); tourne_droite(90);bertg(l/2); tourne_gauche(90);bertd(l/2); fsi; }; hilbd(l):={ si (l<10) alors avance(l); sinon tourne_droite(90);;hilbg(l/2); tourne_gauche(90);;hilbd(l/2); tourne_gauche(90);bertd(l/2); tourne_droite(90);bertg(l/2); fsi; }; bertg(l):={ si (l<10) alors avance(l); sinon tourne_droite(180);hilbd(l/2); tourne_droite(90);hilbg(l/2); tourne_droite(90);bertg(l/2); hilbd(l/2); fsi; }; bertd(l):={ si (l<10) alors avance(l); sinon tourne_droite(180);hilbg(l/2); tourne_gauche(90);hilbd(l/2); tourne_gauche(90);bertd(l/2); hilbg(l/2); fsi; };
On tape par exemple :
efface();pas_de_cote(-40);hilbg(200)
Les 4 procédures ci-dessus se trouvent dans le fichier :
examples/tortue/hilbert.cxx
0/ Prener une longue bande de papier AB de longueur l : c’est le dragon au
jour 0.
1/ Plier cette bande de papier en deux, en amenant B
en coincidence avec A par une rotation d’angle +2 et de centre C,
milieu de AB : en dépliant à angle droit, on a le dragon au jour 1.
2/ Replier comme précédemment, puis plier à nouveau en deux, en amenant
C en coincidence avec A par une rotation d’angle +2 : en dépliant
à angle droit chaque pliure, on a le dragon au jour 2.
3/ Recommencer tant que la longueur à plier n’est pas trop petite (pour la
tortue on s’arrête de plier si l<10).
Voici les 5 premières étapes :
igtortue/dragon.tex
On remarque que le segment AC et le segment CB donne naissance à deux
dragons symétriques : on appelle dragong le dragon obtenu par des
pliages fait avec une rotation d’angle +2 et dragond le dragon
obtenu par des pliages fait avec une rotation d’angle −2.
On tape :
//dragong(1800) dragong(l):={ si (l<10) alors avance(l); sinon dragong(l/2); tourne_gauche(90); dragond(l/2); fsi; }; dragond(l):={ si (l<10) alors avance(l); sinon dragong(l/2); tourne_droite(90); dragond(l/2); fsi; }
Ou encore en utilisant une seule procédure dragon2 mais avec un
paramètre supplémentaire s (si s=1 on a un dragon gauche et
si s=-1 on a un dragon droit).
On tape :
//dragon2(1800,1) dragon2(l,s):={ si (l<10) alors avance(l); sinon dragon2(l/2,1); tourne_gauche(90*s); dragon2(l/2,-1); fsi; }
On tape par exemple :
efface();pas_de_cote(-20);dragon2(2880,1)
igtortue/dragon2.tex
Ou encore on écrit dragon3 en utilisant le paramètre n profondeur pour faire le test d’arrêt :
//dragon3(1800,1,3) dragon3(l,s,n):={ si (n==0) alors avance(l); sinon dragon3(l/2,1,n-1); tourne_gauche(90*s); dragon3(l/2,-1,n-1); fsi; }
Les dessins des 5 premières étapes ont été réalisés
en exécutant :
dragon3(90,1,0) puis,
dragon3(90,1,1) puis,
dragon3(90,1,2) puis,
dragon3(90,1,3) puis,
dragon3(90,1,4).
Les procédures ci-dessus se trouvent dans le fichier :
examples/tortue/dragon.cxx
Voici deux étapes et le début de l’étape 3 de la courbe de Gosper :
igtortue/gosper.tex
On remarque que les 7 segments de la première courbe donne naissance soit
à la première courbe, soit à la courbe obtenue en faisant le
trajet en sens inverse. On va donc définir deux procédures :
gosperg et gosperd qui réalisent les dessins suivants (avec comme
position de départ de la tortue, le triangle plein et comme position
d’arrivée, le triangle vide) :
igtortue/gosperdg.tex
On déduit l’écriture de gosperd de celle de gosperg en mettant les instructions de gosperg de la dernière à la première en changeant gauche en droite et réciproqement.
//gosperg(80,3) gosperg(l,n):={ si (n==0) alors avance(l); sinon gosperg(l/2,n-1); tourne_gauche(60); gosperd(l/2,n-1); tourne_gauche(120); gosperd(l/2,n-1); tourne_droite(60); gosperg(l/2,n-1); tourne_droite(120); gosperg(l/2,n-1); gosperg(l/2,n-1); tourne_droite(60); gosperd(l/2,n-1); tourne_gauche(60); fsi; }; gosperd(l,n):={ si (n==0) alors avance(l); sinon tourne_droite(60); gosperg(l/2,n-1); tourne_gauche(60); gosperd(l/2,n-1); gosperd(l/2,n-1); tourne_gauche(120); gosperd(l/2,n-1); tourne_gauche(60); gosperg(l/2,n-1); tourne_droite(120); gosperg(l/2,n-1); tourne_droite(60); gosperd(l/2,n-1); fsi; };
On tape :
gosperg(80,3)
On obtient :
la courbe de gosper à la troisième génération
Autre écriture on choisit les flèches départ et d’arrivée comme
ci-dessous mais alors la tortue a changé de direction il faut donc aussi la
faire changer de la même direction dans le test d’arrêt. L’écriture de
gosperd se fait encore à partir de celle de gosperg, en mettant
les instructions de gosperg de la dernière à la première en
changeant gauche en droite et réciproqement, et cela même dans
le test d’arrêt!!!
igtortue/gosper2.tex
//gosperg2(80,3) gosperg2(l,n):={ si (n==0) alors avance(l);tourne_droite(60); sinon gosperg2(l/2,n-1); tourne_gauche(60); gosperd2(l/2,n-1); tourne_gauche(60); gosperd2(l/2,n-1); tourne_droite(60); gosperg2(l/2,n-1); tourne_droite(60); gosperg2(l/2,n-1); tourne_gauche(60); gosperg2(l/2,n-1); tourne_droite(60); gosperd2(l/2,n-1); fsi; }; gosperd2(l,n):={ si (n==0) alors tourne_gauche(60);avance(l); sinon gosperg2(l/2,n-1); tourne_gauche(60); gosperd2(l/2,n-1); tourne_droite(60); gosperd2(l/2,n-1); tourne_gauche(60); gosperd2(l/2,n-1); tourne_gauche(60); gosperg2(l/2,n-1); tourne_droite(60); gosperg2(l/2,n-1); tourne_droite(60); gosperd2(l/2,n-1); fsi; };
On tape :
gosperg2(80,3)
On obtient :
la courbe de gosper à la troisième génération
Les procédures ci-dessus se trouvent dans le fichier :
examples/tortue/gosper.cxx