Previous Up Next
Retour à la page personnelle de Bernard Parisse.

Chapitre 10  Quelques exemples de récursivité

10.1  Récursivité ayant un seul appel récursif

On commence par des exemples simples.

10.1.1  Les carrés

On trace un carré puis le carré qui joint les milieux des cotés etc... on s’arrête quand les segments à dessiner deviennent trop petits ou quand on a un dessin de profondeur n (n est le nombre d’étapes necessaires pour réaliser le dessin).
On tape dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK :

 
carres(A,B):={
local L;
L:=carre(A,B);
if (longueur2(A,B)>0.01) {
  L:=L,carres(A+(B-A)/2,B+(B-A)*i/2);
}
return L;
};

On tape :
carres(point(-1),point(1)) :
On obtient :

On obtient le dessin des carrés avec le tracé qui est fait du plus grand au plus petit : le dessin du carré (-1,1,1+2*i,-1+2*i) puis du carré (0,1+i,i,-1+i)....
bf Remarque si on tape

 
carres2(A,B):={
local L;
if (longueur2(A,B)>0.01) {
  L:=L,carres2(A+(B-A)/2,B+(B-A)*i/2);
}
L:=L,carre(A,B);
return L;
};

puis :
carres2(-1.0,1.0)
le dessin des carrés ne se fera pas dans le même ordre et se fera du plus petit au plus grand.
Autre test d’arrêt On peut avoir besion de connaitre le nombre de n de fois que l’on fait le ou les appels récursifs pour avoir un dessin de "profondeur" n. On rajoute pour cela un paramètre qui sera la profondeur.
Dans l’exemple ci-dessus, on tape dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK le programme :

 
carrep(A,B,n):={
local L;
L:=carre(A,B);
 if (n==0) return NULL;
 L:=L,carrep(A+(B-A)/2,B+(B-A)*i/2,n-1);
return L;
};

On tape :
carrep(-1.0,1.0,5)
On obtient le dessin des carrés du plus grand au plus petit et de profondeur 5

Généralisation
On trace un carré ABCD, puis le carré MNPQ avec :
AM=a*AB,
BN=a*BC,
CO=a*CD,
DP=a*DA,
a est un nombre réel entre 0 et 1.

 
carresp(A,B,a):={
local L;
L:=carre(A,B);
if (longueur2(A,B)>0.01) {
L:=L,carresp(A+(B-A)*a,B+(B-A)*i*a,a);
}
return L;
}:;

On tape par exemple :
carresp(-1.0,1.0,0.2) On obtient :

10.1.2  Les triangles

On trace un triangle puis le triangle qui joint les milieux des cotés etc...on s’arrête quand les segments à dessiner deviennent trop petits.
On tape dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK :

 
triangles(A,B,C):={
local L;
L:=triangle(A,B,C);
if (longueur2(A,B)>0.01) {
   L:=L,triangles(A+(B-A)/2,B+(C-B)/2,C+(A-C)/2);
}
return L};

On tape :
triangles(-2.0,1,2*i)
On obtient le dessin des triangles du plus grand au plus petit :le dessin du triangle (-2,1,2*i) puis du triangle (-0.5,0.5+i,-1+i,)....

Remarque si on tape

 
trianglesp(A,B,C):={
local L;
if (longueur2(A,B)>0.01) {
  L:=L,trianglesp(A+(B-A)/2,B+(C-B)/2,C+(A-C)/2);
}
L:=L,triangle(A,B,C);
return L};

On tape :
trianglesp(-2.0,1,2*i)
On obtient le même dessin, mais le tracé des triangles ne se fera pas dans le même ordre et se feradu plus petit au plus grand.
Généralisation
On trace un triangle ABC, puis le triangle MNP avec :
AM=a*AB,
BN=a*BC,
CO=a*CD,
a est un nombre réel entre 0 et 1.

 
trianglea(A,B,C,a):={
local L;
L:=triangle(A,B,C);
if (longueur2(A,B)>0.01) {
L:=L,trianglep(A+(B-A)*a,B+(C-B)*a,C+(A-C)*a,a);
}
return L}:;

On tape par exemple :
trianglea(-2.0,1.0,2*i,0.2)
On obtient :

10.2  Récursivité ayant plusieurs appels récursifs

Voici des exemples encore assez simples.

10.2.1  Les triangles

On trace un triangle puis on joint les milieux des cotés.
On obtient ainsi 4 petits triangles semblables au précédent.
On recommence le même processus avec les trois triangles qui ont un angle commun avec le grand triangle et ainsi de suite.....on s’arrête quand les segments à dessiner deviennent trop petits.
On tape dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK :

 
triangle3(A,B,C):={
local L;
L:=triangle(A,B,C);
 if (longueur2(A,B)<0.005) return NULL;
 L:=L,triangle3(A,A+(B-A)/2,C+(A-C)/2);
 L:=L,triangle3(A+(B-A)/2,B,B+(C-B)/2);
 L:=L,triangle3(C+(A-C)/2,B+(C-B)/2,C);
return L;
};

On tape par exemple :
triangle3(-2.0,1.0,2*i)
On obtient :

Remarque
Le tracé du triangle ne peut se faire qu’a la fin car il suffit de tracer les derniers petits triangles on écrit donc dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK :

 
trianglep(A,B,C):={
local L:=NULL;
if (longueur2(A,B)<0.01) {return triangle(A,B,C);}
L:=L,trianglep(A,A+(B-A)/2,C+(A-C)/2);
L:=L,trianglep(A+(B-A)/2,B,B+(C-B)/2);
L:=L,trianglep(C+(A-C)/2,B+(C-B)/2,C);
return L;
};

On tape par exemple :
trianglep(-2.0,1.0,2*i)
On obtient le même dessin.

Généralisation
On trace un triangle ABC, puis le triangle MNP avec :
AM=a*AB,
BN=a*BC,
CO=a*CD,
a est un nombre réel entre 0 et 1.

 
triangle3p(A,B,C,a):={
local L:=NULL;
if (longueur2(A,B)<0.02) {return triangle(A,B,C);}
L:=L,triangle3p(A,A+(B-A)*a,C+(A-C)*a,a);
L:=L,triangle3p(A+(B-A)*a,B,B+(C-B)*a,a);
L:=L,triangle3p(C+(A-C)*a,B+(C-B)*a,C,a);
return L;
}:;

On tape par exemple :
triangle3p(-2.0,1.0,2*i,0.6)
On obtient :

Et avec un autre test d’arrêt en utilisant la profondeur n du dessin :

 
triangle3an(A,B,C,a,n):={
local L;
if (n==0) {return triangle(A,B,C);}
L:=L,triangle3an(A,A+(B-A)*a,C+(A-C)*a,a,n-1);
L:=L,triangle3an(A+(B-A)*a,B,B+(C-B)*a,a,n-1);
L:=L,triangle3an(C+(A-C)*a,B+(C-B)*a,C,a,n-1);
return L;
}:;

On tape par exemple :
triangle3an(-2.0,1.0,2*i,0.6,3)
0n obtient un dessin de profondeur 3 :

10.2.2  Les hexagones

On considère un hexagone de coés de longueur l, on remplace cet hexagone par 7 hexagones de cotés de longueur l/3 qui sont :les 6 hexagones ayant un angle commun avec l’hexagone de départ et un septième hexagone se trouvant au centre comme sur la figure :

On obtient ainsi 7 petits hexagones semblables au précédent et on recommence le même processus.

On tape la fonction hexago ou on utilise la commande hexagone de Xcas :

 
// dessin d'un hexagone
hexago(x,y):={
local a,b,c,L;
a:=x;
b:=y;
L:=NULL;
for (j:=1;j<=6;j++) {
c:=a+(b-a)*exp(evalf(i*pi*2/3));
L:=L,segment(a,c);
b:=a;
a:=c;
}
return L;
}:;

puis on fait un premier appel récursif correspondant à l’hexagone du centre et avec la même itération que dans la fonction hexago, on fait un appel récursif au lieu de tracer un segment pour les hexagones des angles, on tape :

hexagones(a,b,n):={
local j,c,L;
L:=NULL;
if (n==0) {return hexago(a,b);}
c:=a+(b-a)*2/3*exp(evalf(i*pi/3));
// dessin de l'hexagone central
L:=L,hexagones(c,c+(b-a)/3, n-1);
//dessin des 6 hexagones dans les angles
for (j:=1;j<=6;j++) {
c:=a+(b-a)*exp(evalf(i*pi*2/3));
L:=L,hexagones(c,c+(a-c)/3,n-1);
b:=a;
a:=c;
} 
return L;};

On tape :
hexagone(point(-1),point(1)),hexagones(-1,1,3)
On obtient :

10.2.3  Les polygones réguliers

On part d’un polygone régulier P à k sommets et on le remplace par k polygones réguliers à k sommets de façon à ce que ces k polygones aient chacun un angle commun avec P et de façon à ce qu’ils ne se chevauchent pas. Puis on contine le processus et on ne dessine que les derniers petits polygones.
Par exemple un hexagone H de coté a est remplacé par 6 hexagones de côtés a/3 obtenus par homothétie de rapport 1/3 et de centre les sommets de l’hexagone H.
Pour écrire une procédure générale il faut faire un peu de trigonométrie.
Le calcul du coté h du petit polygone k-régulier doit vérifier :
- si k=3, 4 on a h=(ba)/2
- si k=5, 6, 7, 8 on a h+hcos(2π/k)=(ba)/2
- si k=9, 10, 11, 12, 13, 14, 15, 16 on a :
h+hcos(2π/k)+hcos(4π/k)=(ba)/2 - si p=iquo(k-1,4), on a :
hl=0p cos(2pπ/k)=(ba)/2
On a donc :
s=∑l=0p cos(2pπ/k)=(sin((2p+1)π/k)+sin(π/k))/(2sin(π/k))
donc h=(ba)/2/s
et on tape :

//napperon de Cantor ou de Sierpinski k=3,4...
//utilise isopolygone(a,b,k) k>0 
//ex polyserp(-1-2*i,1-2*i,5,3); polyserp(-2*i,1-2*i,9,2)
polyserp(a,b,k,n):={
local c,h,j,q,p,s,L;
if (n==0) {return isopolygone(a,b,k);}
//pour k=3 ou 4  h:=(b-a)/3;
//pour k=5,6,7,8 h:=(b-a)/2/(cos(evalf(2*pi/k))+1);
//pour autre k il faut calculer s avec la trigo ou avec
//s:=1;for (l:=1;l<=iquo(k-1,4);l++){s:=s+cos(2*l*evalf(pi)/k);} 
p:=iquo(k-1,4);
s:=(sin(evalf(pi)/k)+sin((2*p+1)*evalf(pi)/k))/
    2/sin(evalf(pi)/k);
for (j:=1;j<=k;j++) {
h:=(b-a)/2/s;
L:=L,polyserp(a,a+h,k,n-1);
c:=a+(b-a)*exp(evalf(i*pi*(k-2)/k));
b:=a;
a:=c;
}
retourne L;
};

On tape :
polyserp(-1-2*i,1-2*i,5,3)
On obtient :

On tape :
polyserp(-2*i,1-2*i,9,2)
On obtient :

Le programme du dessin d’un polygone régulier à k cotés peut vous aider á comprendre le programme précédent.

 
// dessin d'un polygone regulier de k cotes
polyreg(x,y,k):={
local a,b,c;
a:=x;
b:=y;
DispG();
for (j:=1;j<=k;j++) {
c:=a+(b-a)*exp(evalf(i*pi*(k-2)/k));
segment(a,c);
b:=a;
a:=c;
}
};

Dans Xcas, pour tracer un polygone régulier, on utilise la commande isopolygone. Remarque
Une faute de signe peut vous faire voir de jolis dessins pour k=7,8...et n=2

//utilise polyreg(a,b,k) k>0 k=nb de cotes
//ex polyserr(-2*i,1-2*i,8,2); polyserr(-2*i,1-2*i,9,2)
polyserr(a,b,k,n):={
local c,h,j,q,p,s,L;
L:=NULL;
if (n==0) return isopolygone(a,b,k);
//if (n==0) {return polyreg(a,b,k);}
p:=iquo(k-1,4);
s:=(sin(evalf(pi)/k)-sin((2*p+1)*evalf(pi)/k))/
    2/sin(evalf(pi)/k);
for (j:=1;j<=k;j++) {
if ( s!=0) h:=(b-a)/2/s; else h:=(b-a)/3;
L:=L,polyserr(a,a+h,k,n-1);
c:=a+(b-a)*exp(evalf(i*pi*(k-2)/k));
b:=a;
a:=c;
}
return L;
};

On tape :
polyserr(-2*i,1-2*i,8,2)
On obtient :

Un autre dessin avec des octogones en traçant un octogone au centre et 8 octogones dans les angles :

polyserp8(a,b,n):={
local c,h,j,q,p,s,k,L;
if (n==0) return isopolygone(a,b,8);
k:=8;
//if (n==0) {return polyreg(a,b,k);}
p:=iquo(k-1,4);
s:=(sin(evalf(pi)/k)+sin((2*p+1)*evalf(pi)/k))/
    2/sin(evalf(pi)/k);
h:=(b-a)/2/s;
L:=polyserp8(a+h+i*h*(sqrt(2)+1),a+h*(sqrt(2)+1)+i*h*(sqrt(2)+1),n-1);
for (j:=1;j<=k;j++) {
L:=L,polyserp8(a,a+h,n-1);
c:=a+(b-a)*exp(evalf(i*pi*(k-2)/k));
b:=a;
a:=c;
h:=(b-a)/2/s;
}
return L;
};

On tape :
polyserp8(-2*i,1-2*i,3)
On obtient :

10.2.4  Le napperon de Cantor ou de Sierpinski avec des points aléatoires

On tape :

Sierpinski(n):={
local T,j,N,x,y,r;
T:=triangle_equilateral(-1/2-i*sqrt(3)/4,1/2-i*sqrt(3)/4,affichage=rouge);
z:=0;
N:=[0$n];
N[0]=<point(0,affichage=point_point)
pour j de 1 jusque n faire
r:=alea(3);
si r==0 alors
  x:=(-1/2+x)/2.;
  y:=(-sqrt(3)/4+y)/2.;
sinon
  si r==1 alors
    x:=(1/2+x)/2.;
    y:=(-sqrt(3)/4+y)/2.;
  sinon
    x:=x/2.;
    y:=(sqrt(3)/4+y)/2.;
  fsi;
fsi;
N[j]=<point(x,y,affichage=point_point)
fpour
retourne(T,N);
}
:;

On tape :
Sierpinski(10000)
On obtient :

Pour comprendre on reprend le programme :

polyserp(a,b,k,n):={
local c,h,j,q,p,s,L;
if (n==0) {return isopolygone(a,b,k);}
//pour k=3 ou 4  h:=(b-a)/3;
//pour k=5,6,7,8 h:=(b-a)/2/(cos(evalf(2*pi/k))+1);
//pour autre k il faut calculer s avec la trigo ou avec
//s:=1;for (l:=1;l<=iquo(k-1,4);l++){s:=s+cos(2*l*evalf(pi)/k);} 
p:=iquo(k-1,4);
s:=(sin(evalf(pi)/k)+sin((2*p+1)*evalf(pi)/k))/
    2/sin(evalf(pi)/k);
for (j:=1;j<=k;j++) {
h:=(b-a)/2/s;
L:=L,polyserp(a,a+h,k,n-1);
c:=a+(b-a)*exp(evalf(i*pi*(k-2)/k));
b:=a;
a:=c;
}
retourne L;
}:;

et on tape :
Sierpinski(6),polyserp(-1/2-i*sqrt(3)/4,1/2-i*sqrt(3)/4,3,4) avec pour Sierpinski(6) 7 gros points aléatoires de couleurs 0,1...6. On a fait 6 tirages qui sont : 2, 1, 1, 1, 0 ,0.
On obtient :

10.2.5  Le flocon

Tous les programmes qui sont dans cette section se trouve dans le fichier :
flocon.cas On considère un segment AB et on place las points PQR tels que :
3*AP=AB
3*BQ=BA
et le triangle PQR est équilatèral direct.
On remplace alors le tracé du segment AB par le tracé APRQB.
On continue en faisant subir le même traitement aux 4 segments AP,PR,RQ,QB...on s’arrête quand la longueur des segments devient trop petite ou quand la profondeur est nulle.
Il y a donc 4 appels récursifs.

 
flocon(A,B):={
local L;
L:=NULL;
if (longueur2(A,B)<0.005) {return segment(A,B);}
L:=L,flocon(A,A+(B-A)/3);
L:=L,flocon(A+(B-A)/3,A+(B-A)/3*(1+exp(i*pi/3)));
L:=L,flocon(A+(B-A)/3*(1+exp(i*pi/3)),A+2*(B-A)/3);
L:=L,flocon(A+2*(B-A)/3,B);
return L;
}:;

On tape par exemple :
flocon(-1.0,1.0)
On obtient :

ou avec la profondeur :

 
floconp(A,B,n):={
local h,L;
L:=NULL;
if (n==0) {return segment(A,B);}
h:=(B-A)/3;
L:=L,floconp(A,A+h,n-1);
L:=L,floconp(A+h,A+h*(1+exp(i*pi/3)),n-1);
L:=L,floconp(A+h*(1+exp(i*pi/3)),A+2*h,n-1);
L:=L,floconp(A+2*h,B,n-1);
return L;
}:;

On tape par exemple :
floconp(-2.0,2.0,5)
On obtient :

Généralisation
On coupe le segment initial AB en trois en placant P et Q de façon à avoir :
AP=a*AB
BQ=a*BA
avec 0.25< a <0.5. puis on construit un triangle isocéle PQR tel que PR=QR=AP . On remplace le segment AB par les segments APRQB et on recommence le processus. Il y a donc 4 appels récursifs.

 
flocong(A,B,a,n):={
local h,t,L;
L:=NULL;
if (n==0) {return segment(A,B);}
t:=acos((0.5-a)/a);
h:=(B-A)*a;
L:=L,flocong(A,A+h,a,n-1);
L:=L,flocong(A+h,A+h*(1+exp(i*t)),a,n-1);
L:=L,flocong(A+h*(1+exp(i*t)),B-h,a,n-1);
L:=L,flocong(B-h,B,a,n-1);
return L;
}:;

On tape par exemple :
flocong(-2.0,2.0,0.4,4)
On obtient :

10.2.6  Le tapis carré

Ces programmes se trouvent dans examples/recur/carre.cxx.
On trace un carré puis puis on partage les cotés de ce carré en trois partie égales. On obtient ainsi 9 carrés.
On recommence le même processus avec les 8 carrés qui ont un coté commun avec le grand carré et ainsi de suite.....on s’arrête quand les segments à dessiner deviennent trop petits. Il y a donc 8 appels récursifs.
On tape dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK :

 
carre8(A,B):={
local h,L;
L:=carre(A,B);
if (longueur2(A,B)<0.005) return NULL;
h:=(B-A)/3;
L:=L,carre8(A,A+h);
L:=L,carre8(A+h,A+2*h);
L:=L,carre8(A+2*h,B);
L:=L,carre8(A+i*h,A+i*h+h);
L:=L,carre8(A+i*h+2*h,B+i*h);
L:=L,carre8(A+2*i*h,A+2*i*h+h);
L:=L,carre8(A+2*i*h+h,A+2*i*h+2*h);
L:=L,carre8(A+2*i*h+2*h,B+2*i*h);
return L;
}:;

On tape par exemple :
carre8(-1.0,1.0)
On obtient :

Autre test d’arrêt
On peut avoir besion de connaitre le nombre de n de fois que l’on fait le ou les appels récursifs pour avoir un dessin de "profondeur" n. On rajoute pour cela un paramètre qui sera la profondeur.
Dans l’exemple ci-dessus, on tape dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK le programme :

 
carre8p(A,B,n):={
local h,L;
h:=(B-A)/3;
L:=carre(A,B);
if (n==0)  return NULL;
h:=(B-A)/3;
L:=L,carre8p(A,A+h,n-1);
L:=L,carre8p(A+h,A+2*h,n-1);
L:=L,carre8p(A+2*h,B,n-1);
L:=L,carre8p(A+i*h,A+i*h+h,n-1);
L:=L,carre8p(A+i*h+2*h,B+i*h,n-1);
L:=L,carre8p(A+2*i*h,A+2*i*h+h,n-1);
L:=L,carre8p(A+2*i*h+h,A+2*i*h+2*h,n-1);
L:=L,carre8p(A+2*i*h+2*h,B+2*i*h,n-1);
return L;
}:;

On tape par exemple :
carre8p(-1.0,1.0,4) On obtient le même dessin

10.2.7  Une courbe de Péano

Ces programmes se trouvent dans examples/recur/peano.cxx.
On trace la diagonale AC d’un carré ABCD.
Puis puis on partage les cotés de ce carrés en trois partie égales. On obtient ainsi 9 carrés.
On remplace alors la diagonale du carré précédent par les diagonales des 9 carrés de façon à avoir une ligne continue allant de A à C. On recommence le même processus avec les 9 carrés de façon à avoir une ligne continue allant de A à C, et ainsi de suite.....on s’arrête quand les segments à dessiner deviennent trop petits.
On a choisit comme paramètre les affixes des points A et B et d’utiliser la profondeur comme test d’arrêt.
On tape dans un éditeur de programme (que l’on ouvre avec Alt+p), puis on valide avec OK : ou on utilise la commande :
read("peano.cas") car ce progrmme se trouve dans le fichier peano.cas.

 
//arc qui remplit le carre de cote x,y 
peano(x,y,n):={
local u,v,L;
u:=(y-x)/3;
v:=i*u;
L:=NULL;
if (n==0) {return segment(x,y+3*v);}
L:=L,peano(x,x+u,n-1);
L:=L,peano(x+u+v,x+u,n-1);
L:=L,peano(x+2*u,y,n-1);
L:=L,peano(y+v,y+2*v,n-1);
L:=L,peano(x+2*(u+v),x+u+2*v,n-1);
L:=L,peano(x+(u+v),x+u+2*v,n-1);
L:=L,peano(x+2*v,x+2*v+u,n-1);
L:=L,peano(x+3*v+u,x+u+2*v,n-1);
L:=L,peano(x+2*(u+v),y+2*v,n-1);
return L;
}:;

On tape par exemple :
peano(-i,3-i,3)
On obtient :

Vous pouvez voir les différentes étapes de la construction en faisant successivement n=1,2,3,4 en utilisant le bouton stop si le tracé est trop long.

10.3  Quelques dessins doublement récursifs

Dans ce chapitre on va faire des dessins qui obligent à écrire plusieurs procédures récursives qui s’appellent l’une l’autre.

10.3.1  Les trapèzes

On considère les trapèzes ABCD rectangle en A et D et tel que AB=2DC=2AD. On dira que l’on a un trapèze droit si l’angle AB,AS=+π/2 et sinon ce sera un trapèze gauche. Voici le programme du dessin du trapèze gauche et du trapèze droit : (le paramètre a est l’affixe de A et b est l’affixe de B)

trapd(a,b):={
local c,d,L;
L:=segment(a,b);
L:=L,segment(a,a+i*(b-a)/2);
L:=L,segment(a+i*(b-a)/2,(a+b)/2+i*(b-a)/2);
L:=L,segment(b,(a+b)/2+i*(b-a)/2);
retourne L;
}:;
trapg(a,b):={
local c,d,L;
L:=segment(a,b);
L:=L,segment(a,a-i*(b-a)/2);
L:=L,segment(a-i*(b-a)/2,(a+b)/2-i*(b-a)/2);
L:=L,segment(b,(a+b)/2-i*(b-a)/2);
retourne L;
}:;

On tape :
trapg(0,10),trapd(10,20)
On obtient :

On partage le trapèze droit en 3 trapèzes droits et un trapèze gauche et le trapèze gauche en 3 trapèzes gauches et un trapèze droit :

Puis on continue le même processus, on tape : (a et b sont les affixes de A et de B, n=1 trace un trapèze, n=2 dessine le partage (soit 4 trapèzes), n=3 dessine 16=42 trapèzes et n=4 en dessine 64=43 etc...)

trapdr(a,b,n):={
local L;
L:=NULL;
si n==0 alors retourne NULL; fsi;
L:=L,trapd(a,b);
L:=L,trapgr((a+b)/2,a,n-1);
L:=L,trapdr(a+i*(b-a)/2,a,n-1);
L:=L,trapdr(a+(b-a)/4+i*(b-a)/4,a+3*(b-a)/4+i*(b-a)/4,n-1);
L:=L,trapdr((a+b)/2,b,n-1);
return L;
}:;
trapgr(a,b,n):={
local L;
L:=NULL;
si n==0 alors return NULL; fsi;
L:=trapg(a,b);
L:=L,trapdr((a+b)/2,a,n-1);
L:=L,trapgr(a-i*(b-a)/2,a,n-1);
L:=L,trapgr(b+3*(a-b)/4+i*(a-b)/4,b+(a-b)/4+i*(a-b)/4,n-1);
L:=L,trapgr((a+b)/2,b,n-1);
return L;
}:;

On tape : trapgr(10,0,4);trapdr(10,20,4);
On obtient :

10.3.2  Les sphinx

Voici un sphinx droit et un sphinx gauche :

sphinxd(x,y):={
local z,u,t,L;
L:=NULL;
z:=x+2*(y-x)/3*exp(evalf(pi)*i/3);
t:= y+(x-y)/3*exp(-evalf(pi)*i/3);
u:=t+(x-y)/3;
L:=L,segment(x,z);
L:=L,segment(z,u);
L:=L,segment(u,t);
L:=L,segment(t,y);
L:=L,segment(y,x);
return L;
}:;
sphinxg(x,y):={
local z,u,t,L;
L:=NULL;
z:=y+2*(x-y)/3*exp(-evalf(pi)*i/3);
t:= x+(y-x)/3*exp(evalf(pi)*i/3);
u:=t+(y-x)/3;
L:=L,segment(y,z);
L:=L,segment(z,u);
L:=L,segment(u,t);
L:=L,segment(t,x);
L:=L,segment(x,y);
return L;
}:;

On tape :
sphinxd(0,1),sphinxg(1.2,2.2)
On obtient :

Voici un sphinx droit et ses 4 petits (composé de trois sphinx gauches et d’un sphinx droit) et un sphinx gauche et ses 4 petits (composé d’un sphinx gauches et de trois sphinx droit) :

sphinxd4(x,y):={
local z,u,t,L;
L:=NULL;
z:=x+2*(y-x)/3*exp(3.14*i/3);
t:= y+(x-y)/3*exp(-3.14*i/3);
u:=t+(x-y)/3;
L:=L,segment(x,z);
L:=L,segment(z,u);
L:=L,segment(u,t);
L:=L,segment(t,y);
L:=L,segment(y,x);
L:=L,sphinxg(x,(x+y)/2);
L:=L,sphinxg((x+y)/2,y);
L:=L,sphinxg(t,t+(x-y)/2);
L:=L,sphinxd(z,(3*x+z)/4);
return L;
}:;
sphinxg4(x,y):={
local z,u,t,L;
L:=NULL;
z:=y+2*(x-y)/3*exp(-evalf(pi)*i/3);
t:= x+(y-x)/3*exp(evalf(pi)*i/3);
u:=t+(y-x)/3;
L:=L,segment(y,z);
L:=L,segment(z,u);
L:=L,segment(u,t);
L:=L,segment(t,x);
L:=L,segment(x,y);
L:=L,sphinxd(x,(x+y)/2);
L:=L,sphinxd((x+y)/2,y);
L:=L,sphinxd(t+(y-x)/2,t);
L:=L,sphinxg((3*y+z)/4,z);
return L;
}:;

On tape :
sphinxd4(0,1),sphinxg4(1.2,2.2)
On obtient :

Et voici toute la famille des sphinx droits et toute la famille des sphinx gauches : (sphinxds(x,y,n) est une fonction récursive qui utilise la fonction récursive sphinxgs(x,y,n) et sphinxgs(x,y,n) est une fonction récursive qui utilise la fonction récursive sphinxds(x,y,n)).

sphinxds(x,y,n):={
local z,u,t,L;
if (n==0) return NULL;
z:=x+2*(y-x)/3*exp(evalf(pi)*i/3);
t:= y+(x-y)/3*exp(-evalf(pi)*i/3);
u:=t+(x-y)/3;
L:=NULL;
L:=L,segment(x,z);
L:=L,segment(z,u);
L:=L,segment(u,t);
L:=L,segment(t,y);
L:=L,segment(y,x);
L:=L,sphinxgs(x,(x+y)/2,n-1);
L:=L,sphinxgs((x+y)/2,y,n-1);
L:=L,sphinxgs(t,t+(x-y)/2,n-1);
L:=L,sphinxds(z,(3*x+z)/4,n-1);
return L;
}:;

sphinxgs(x,y,n):={
local z,u,t,p,L;
if (n==0) return NULL;
L:=NULL;
z:=y+2*(x-y)/3*exp(-evalf(pi)*i/3);
t:= x+(y-x)/3*exp(evalf(pi)*i/3);
u:=t+(y-x)/3;
L:=L,segment(y,z);
L:=L,segment(z,u);
L:=L,segment(u,t);
L:=L,segment(t,x);
L:=L,segment(x,y);
L:=L,sphinxds(x,(x+y)/2,n-1);
L:=L,sphinxds((x+y)/2,y,n-1);
L:=L,sphinxds(t+(y-x)/2,t,n-1);
L:=L,sphinxgs((3*y+z)/4,z,n-1);
return L;
}:;

On tape :
sphinxds(0,1,4),sphinxgs(1.2,2.2,4)
On obtient :
ou encore en ne dessinant que la dernière génération du sphinx droit ou la dernière génération du sphinx gauche :
sphindps(-2,2,4) met 0.52s alors que sphinds(-2,2,4) met 0.83s

sphinxdps(x,y,n):={
local z,u,t,L;
L:=NULL;
if (n==1) {return sphinxd(x,y);}
z:=x+2*(y-x)/3*exp(evalf(pi)*i/3);
t:= y+(x-y)/3*exp(-evalf(pi)*i/3);
u:=t+(x-y)/3;
L:=L,sphinxgps(x,(x+y)/2,n-1);
L:=L,sphinxgps((x+y)/2,y,n-1);
L:=L,sphinxgps(t,t+(x-y)/2,n-1);
L:=L,sphinxdps(z,(3*x+z)/4,n-1);
return L;
}:;
sphinxgps(x,y,n):={
local z,u,t,p,L;
L:=NULL;
if (n==1) {return sphinxg(x,y);}
z:=y+2*(x-y)/3*exp(-evalf(pi)*i/3);
t:= x+(y-x)/3*exp(evalf(pi)*i/3);
u:=t+(y-x)/3;
L:=L,sphinxdps(x,(x+y)/2,n-1);
L:=L,sphinxdps((x+y)/2,y,n-1);
L:=L,sphinxdps(t+(y-x)/2,t,n-1);
L:=L,sphinxgps((3*y+z)/4,z,n-1);
return L;
}:;

On tape :
sphinxdps(0,1,4),sphinxgps(1.2,2.2,4)
On obtient le même dessin que précédemment.
Mais si on remplace dans le sphinx droit, un sphinx gauche par un segment et dans le sphinx gauche, un sphinx droit par un segment on n’obtient pas la même chose !!!

sphinxdpst(x,y,n):={
local z,u,t,L;
L:=NULL;
if (n==1) return sphinxd(x,y);
z:=x+2*(y-x)/3*exp(evalf(pi)*i/3);
t:= y+(x-y)/3*exp(-evalf(pi)*i/3);
u:=t+(x-y)/3;
L:=L,sphinxgpst(x,(x+y)/2,n-1);
L:=L,sphinxgpst((x+y)/2,y,n-1);
L:=L,segment(t,t+(x-y)/3);
L:=L,sphinxdpst(z,(3*x+z)/4,n-1);
return L;
}:;

sphinxgpst(x,y,n):={
local z,u,t,p,L;
L:=NULL;
if (n==1) return sphinxg(x,y);
z:=y+2*(x-y)/3*exp(-evalf(pi)*i/3);
t:= x+(y-x)/3*exp(evalf(pi)*i/3);
u:=t+(y-x)/3;
L:=L,sphinxdpst(x,(x+y)/2,n-1);
L:=L,sphinxdpst((x+y)/2,y,n-1);
L:=L,segment(t+(y-x)/3,t);
L:=L,sphinxgpst((3*y+z)/4,z,n-1);
return L;
}:;

On tape :
sphinxdpst(0,1,4),sphinxgpst(1.2,2.2,4)
On obtient :

10.3.3  Le dragon

On se donne deux points A et B (ou deux nombres complexes a et b qui sont l’affixe de ces points) et on considère le carré ACBD direct ayant pour diagonale AB.
Le segment AB peut donner naissance à un dragon gauche, pour cela, on remplace le segment AB par les deux côtés AD et DB du carré ACBD situé à gauche du vecteur AB ou,
le segment AB peut donner naissance à un dragon droit, pour cela, on remplace le segment AB par les deux côtés AC et CB du carré ACBD situé à droite du vecteur AB. Pour la fabrication du dragon gauche, ces deux segments sont considérés comme allant donner naissance à un dragon gauche (AD) et à un dragon droit (DB) et
pour la fabrication du dragon droit, ces deux segments sont considérés comme allant donner naissance à un dragon gauche (AC) et à un dragon droit (CB).
On a :
bc=i*(ac) et bd=−i*(ad) donc :
c=(bi*a)*(1+i)/2 et d=(b+i*a)*(1−i)/2.
On écrit donc en prenant comme test d’arrêt la profondeur n c’est à dire le nombre de générations.

// dessine un dragon dragong(-i,2+i,10)
//x=a,y=b et d=u
 dragong(x,y,n):={
local u,L;
L:=NULL;
if (n==0){return segment(x,y);}
u:=(y+i*x)*(1-i)/2;
L:=L,dragong(x,u,n-1);
L:=L,dragond(u,y,n-1);
return L;
}:;
// dessine un dragon dragond(-i,2+i,10)
//x=a,y=b et c=u
dragond(x,y,n):={
local u,L;
L:=NULL;
if (n==0){return segment(x,y);}
u:=(y-i*x)*(1+i)/2;
L:=L,dragong(x,u,n-1);
L:=L,dragond(u,y,n-1);
return L;
}:;

On tape :
dragong(-i,2+i,10)
On obtient :

Remarque
Il est facile d’obtenir la courbe du dragon en prenant une longue bande de papier que l’on plie n fois sur elle même, toujours dans le même sens. Lorsqu’on a pris soin de bien marquer les plis, on obtient un dragon lorsqu’on déplie la bande en disposant les plis à angle droit.
Ce n’est pas tout à fait ce que l’on a programmer car dans le programme à chaque étape on multiplie la longueur du dragon par √2.
Sauriez vous programmer le dragon de la bande de papier ?

Voici la solution : on remarquera que le dragon droit est réalisé par la deuxième moitié de la bande de papier et donc la fonction dragonpapierd est la fonction dragonpapierg en changeant gauche en droite, et en commençant par la dernière instruction.

dragonpapierg(x,y,n):={
local u,v,a,b;
DispG();
if (n==0){segment(x,y);return y;}
u:=x+(y-x)/2;
a:=dragonpapierg(x,u,n-1);
v:=a+(y-x)*i/2;
b:=dragonpapierd(a,v,n-1);
return b
}:;

dragonpapierd(x,y,n):={
local u,v,a,b;
DispG();
if (n==0){segment(x,y); return y;}
v:=x+(y-x)*i/2;
b:=dragonpapierg(x,v,n-1);
u:=b+(y-x)/2;
a:=dragonpapierd(b,u,n-1);
return a;
}:;

On tape :
dragonpapierg(-3.0,13,5)
On obtient le dragon dans l’écran DispG :

Voici une autre solution où on repère l’arrivée et la direction du dernier trait. Dans ce cas on connait le départ et la direction de départ du dragon droit....mais c’est nettement plus compliqué.

dragonpaperg(x,y,n):={
local u,v,a,b;
DispG();
if (n==0){segment(x,y); return (x,y);}
u:=x+(y-x)/2;
a:=dragonpaperg(x,u,n-1);
v:=a[1]+abs((y-x)/(a[1]-a[0]))*(a[1]-a[0])*i/2;
b:=dragonpaperd(a[1],v,n-1);
return b;
}:;

dragonpaperd(x,y,n):={
local u,v,a,b;
DispG();
if (n==0){segment(x,y); return (x,y);}
u:=x+(y-x)/2;
a:=dragonpaperg(x,u,n-1);
v:=a[1]-abs((y-x)/(a[1]-a[0]))*(a[1]-a[0])*i/2;
b:=dragonpaperd(a[1],v,n-1);
return b;
}:;

On tape par exemple :
dragonpaperg(-3,13,5)
On obtient le dragon dans l’écran DispG.

10.3.4  Deux courbes de Péano formée d’arcs de cercle

Parmi les nombreuses courbes inventées par Péano on va en décrire deux qui sont des courbes rècursives formées par des arcs de cercle.
Ces programmes se trouvent dans examples/recur/peano.cxx

Une courbe de Péano formée par 13 arcs

On écrit la fonction arcg (resp arcd) qui dessine des arcs définit par le début de l’arc, la fin de l’arc, et de mesure π/3 (resp −π/3).

//arc x y  de mesure +pi/3
arcg(x,y):={
return arc(x,y,pi/3);
};
//arc x y de de mesure -pi/3
arcd(x,y):={
return arc(x,y,-pi/3);
}:;

Puis on écrit la fonction peanog (resp peanod) :
Soient deux points A d’affixe a et B d’affixe b.
Pour la fonction peanog, on débute par l’arc AB de mesure π/3, situé sur le cercle de centre Cg d’affixe cg=(ba*exp(i*π/3))*(1−exp(−i*π/3)) que l’on appellera arcg.
Pour la fonction peanod, on débute par l’arc AB de mesure −π/3, situé sur le cercle de centre Cd d’affixe cd=(ba*exp(−i*π/3))*(1−exp(i*π/3)) que l’on appellera arcd.
On remplace ensuite arcg (resp arcd) par 13 arcs de mesure π/3 ou de mesure −π/3 selon le dessin que l’on obtient en tapant :
peanog(-2-2*i,2-2*i,1) (resp peanod(-2-2*i,2-2*i,1)).
Ces deux figures sont symétriques.
Et on continue en appliquant le même traitement à chacun de ses 13 arcs en remplacant les arcg (resp arcd) par 13 arcs.

// courbe de peano avec 13 arcs
//par ex peanod(-2-2*i,2-2*i,3)
peanod(x,y,n):={
local c1,b,c,d,e1,f,g,h,i1,j,k,l,m,L;
L:=NULL;
if (n==0) {return arc(x,y,-pi/3);}
c1:=x+(y-x)*exp(evalf(pi)*2*i/3)/3;
b:=x+(y-x)/3*exp(evalf(pi)*i/3);
c:=x+(y-x)/3*2*exp(evalf(pi)*i/3);
d:=c+(y-x)/3;
e1:=b+2*(y-x)/3;
f:=c1+(y-x)*(15+i*sqrt(3))/18;
g:=c1+(y-x)*(6+i*sqrt(3))/9;
h:=f-(y-x)/3;
i1:=h-i*(y-x)/9*sqrt(3);
j:=i1+(y-x)/3;
k:=g-i*2*(y-x)/9*sqrt(3);
l:=x+(y-x)/3;
m:=x+2*(y-x)/3;
L:=L,peanog(x,b,n-1);
L:=L,peanod(b,c,n-1);
L:=L,peanod(c,d,n-1);
L:=L,peanod(d,e1,n-1);
L:=L,peanod(e1,f,n-1);
L:=L,peanog(f,g,n-1);
L:=L,peanog(g,h,n-1);
L:=L,peanog(h,i1,n-1);
L:=L,peanod(i1,j,n-1);
L:=L,peanod(j,k,n-1);
L:=L,peanog(k,l,n-1);
L:=L,peanog(l,m,n-1);
L:=L,peanod(m,y,n-1);
return L;
}:;
peanog(x,y,n):={
local c1,b,c,d,e1,f,g,h,i1,j,k,l,m,L;
L:=NULL;
if (n==0) {return arc(x,y,pi/3);}
c1:=x+(y-x)*exp(evalf(-2*pi)*i/3)/3;
b:=x+(y-x)/3*exp(evalf(-pi)*i/3);
c:=x+(y-x)/3*2*exp(evalf(-pi)*i/3);
d:=c+(y-x)/3;
e1:=b+2*(y-x)/3;
f:=c1+(y-x)*(15-i*sqrt(3))/18;
g:=c1+(y-x)*(6-i*sqrt(3))/9;
h:=f-(y-x)/3;
i1:=h+i*(y-x)/9*sqrt(3);
j:=i1+(y-x)/3;
k:=g+i*2*(y-x)/9*sqrt(3);
l:=x+(y-x)/3;
m:=x+2*(y-x)/3;
L:=L,peanod(x,b,n-1);
L:=L,peanog(b,c,n-1);
L:=L,peanog(c,d,n-1);
L:=L,peanog(d,e1,n-1);
L:=L,peanog(e1,f,n-1);
L:=L,peanod(f,g,n-1);
L:=L,peanod(g,h,n-1);
L:=L,peanod(h,i1,n-1);
L:=L,peanog(i1,j,n-1);
L:=L,peanog(j,k,n-1);
L:=L,peanod(k,l,n-1);
L:=L,peanod(l,m,n-1);
L:=L,peanog(m,y,n-1);
return L;
}:;

On tape :
peanod(-2-2*i,2-2*i,3)
On obtient :

Une courbe C1 de Péano qui remplit un carré

On va maintenant décrire la courbe de Péano ternaire qui remplit un carré direct de coté XY, en étant C1 .
Soient x est l’affixe de X et y est l’affixe de Y.
Le dessin de base est obtenu en tapant:
bases(x,y)
il est composé de 8 arcs de cercle de mesure π/2 ou de mesure −π/2 et débute au point A d’affixe a:=x+(yx)/6*1+i) et se termine au point K d’affixe k, symétrique de A par rapport au centre du carré.
Á partir de ce dessin de base on fait la figure un :
un(x,y)
qui est composée d’un arc de mesure π/2 commençant au point d’affixe :
a−(yx)/3 et se terminant au point A suivi du dessin de base.
Á partir de ce dessin de base on fait la figure deux :
deux(x,y)
qui est composée d’un arc de mesure π/2 commençant au point d’affixe :
ai*(yx)/3 et se terminant au point A suivi du dessin de base.
On partage le carré en 9 petits carrés et dans chacun des petits carrés on trace la figure de base ou la figure de baseun ou la figure de basedeux de façon à obtenir une ligne continue etc....
On écrit ensuite les procédures :
peano0 qui débute par la figure bases,
peano1 qui débute par la figure un,
peano2 qui débute par la figure de deux,
Taper par exemple peano0(-1,2,1) pour voir l’étape 1.

//motif de base
bases(x,y):={
local a,b,c,d,e1,f,g,h,i1,k,L;
L:=NULL;
h:=(y-x)/3;
a:=x+h/2+i*h/2;
b:=a+i*h;
c:=b+i*h;
d:=c+h
e1:=b+h;
f:=a+h;
g:=f+h;
k:=e1+h;
i1:=d+h;
L:=L,arc(a,b,pi/2);
L:=L,arc(c,b,pi/2);
L:=L,arc(d,c,pi/2);
L:=L,arc(e1,d,pi/2);
L:=L,arc(e1,f,pi/2);
L:=L,arc(f,g,pi/2);
L:=L,arc(g,k,pi/2);
L:=L,arc(i1,k,pi/2);
return L;
}:;
//un arc et le motif de base
un(x,y):={
local h,a,L;
L:=NULL;
h:=(y-x)/3;
a:=x+h/2+i*h/2;
L:=L,arc(a-h,a,pi/2);
L:=L,bases(x,y);
return L;
}:;
//un  autre arc et le motif de base
deux(x,y):={
local h,a,L;
L:=NULL;
h:=(y-x)/3;
a:=x+h/2+i*h/2;
L:=L,arc(a,a-h*i,pi/2);
L:=L,bases(x,y);
return L;}:;

//courbe qui remplit un carre debute par le motif bases
// ex peano0(-1,2,1) ou  peano0(-1,2,3)  
// utilise bases un deux peano1 peano2
peano0(x,y,n):={
local a,h,L;
if (n==0) {return bases(x,y);}
L:=NULL;
h:=(y-x)/3;
a:=x+h;
L:=L,peano0(x,a,n-1);
L:=L,peano2(a+i*h,a,n-1);
L:=L,peano1(a+h,y,n-1);
L:=L,peano1(y+i*h,y+2*i*h,n-1);
L:=L,peano1(a+h+2*i*h,a+2*i*h,n-1);
L:=L,peano2(a+i*h,a+2*i*h,n-1);
L:=L,peano2(x+2*i*h,a+2*i*h,n-1);
L:=L,peano2(a+3*i*h,a+2*i*h,n-1);
L:=L,peano1(a+h+2*i*h,y+2*i*h,n-1);
return L;
}:;
//courbe qui remplit un carre debute par le motif un
// ex peano1(-1,2,1) 
// utilise bases un deux peano2
peano1(x,y,n):={
local a,h,L;
if (n==0) {return un(x,y);}
L:=NULL;
h:=(y-x)/3;
a:=x+h;
L:=L,peano1(x,a,n-1);
L:=L,peano2(a+i*h,a,n-1);
L:=L,peano1(a+h,y,n-1);
L:=L,peano1(y+i*h,y+2*i*h,n-1);
L:=L,peano1(a+h+2*i*h,a+2*i*h,n-1);
L:=L,peano2(a+i*h,a+2*i*h,n-1);
L:=L,peano2(x+2*i*h,a+2*i*h,n-1);
L:=L,peano2(a+3*i*h,a+2*i*h,n-1);
L:=L,peano1(a+h+2*i*h,y+2*i*h,n-1);
return L;
}:;
//courbe qui remplit un carre debute par le motif deux
// ex peano2(-1,2,1) 
// utilise bases un deux peano1
peano2(x,y,n):={
local a,h,L;
if (n==0) {return deux(x,y);}
L:=NULL;h:=(y-x)/3;
a:=x+h;
L:=L,peano2(x,a,n-1);
L:=L,peano2(a+i*h,a,n-1);
L:=L,peano1(a+h,y,n-1);
L:=L,peano1(y+i*h,y+2*i*h,n-1);
L:=L,peano1(a+h+2*i*h,a+2*i*h,n-1);
L:=L,peano2(a+i*h,a+2*i*h,n-1);
L:=L,peano2(x+2*i*h,a+2*i*h,n-1);
L:=L,peano2(a+3*i*h,a+2*i*h,n-1);
L:=L,peano1(a+h+2*i*h,y+2*i*h,n-1);
return L;
}:;

On tape :
peano0(-1,2,3)
On obtient :

Autres courbes : des programmes sans commentaires

La courbe de Hibert

Voici les programmes composées de 4 fonctions, qui dessine la courbe de Hilbert dans l’écran DispG :

//courbe de hilbert par exemple hilg(-2,0,4) est 
//compos\'e par 4 morceaux hilg hild berg et berd
//ou hild(0,2,4) ou berg(2,2-2*i,4) ou berd(2,2-2*i,4)
//le morceau 1
hilg(x,y,n):={
local u,v,a,b;
DispG();
if (n==0) {segment(x,y);return 0;}
u:=(y-x)/2;
v:=u*i;
hild(x,x+v,n-1);
hilg(x+v,x+v+u,n-1);
a:=berg(x+v+u,x+u,n-1);
b:=berd(a,a+u,n-1);
};
//le morceau 2
hild(x,y,n):={
local u,v,a,b;
DispG();
if (n==0) {segment(x,y);return 0;}
u:=(y-x)/2;
v:=u*i;
hilg(x,x-v,n-1);
hild(x-v,x-v+u,n-1);
b:=berd(x-v+u,x+u,n-1);
a:=berg(b,b+u,n-1);
};
//le morceau 3
berg(x,y,n):={
local u,v,b;
DispG();
if (n==0) {segment(x,y);return y;}
v:=(x-y)/2;
u:=-v*i;
hild(x,x+v,n-1);
hilg(x+v,x+v+u,n-1);
b:=berg(x+v+u,x+u,n-1);
hild(b,b-v,n-1);
return(b-v);
};
//le morceau 4
berd(x,y,n):={
local u,v,a;
DispG();
if (n==0) {segment(x,y);return y;}
v:=(x-y)/2;
u:=-v*i;
hilg(x,x+v,n-1);
hild(x+v,x+v-u,n-1);
a:=berd(x+v-u,x-u,n-1);
hilg(a,a-v,n-1);
return a-v;
};

Voici les programmes composées de 4 fonctions, qui dessine la courbe de Hilbert dans l’écran de réponse :

hilg(x,y,n):={
local u,v,a,b,L;
L:=NULL;
if (n==0) {return segment(x,y);}
u:=(y-x)/2;
v:=u*i;
L:=L,hild(x,x+v,n-1);
L:=L,hilg(x+v,x+v+u,n-1);
a:=berg(x+v+u,x+u,n-1);
L:=L,tail(a);
a:=a[0];
b:=berd(a,a+u,n-1);
L:=L,tail(b);
b:=b[0];
return L;
}:;
//le morceau 2
hild(x,y,n):={
local u,v,a,b,L;
L:=NULL;
if (n==0) {return segment(x,y);}
u:=(y-x)/2;
v:=u*i;
L:=L,hilg(x,x-v,n-1);
L:=L,hild(x-v,x-v+u,n-1);
b:=berd(x-v+u,x+u,n-1);
L:=L,tail(b);
b:=b[0];
a:=berg(b,b+u,n-1);
L:=L,tail(a);
a:=a[0];
return L;
}:;
//le morceau 3
berg(x,y,n):={
local u,v,b,L;
L:=NULL;
if (n==0) {return y,segment(x,y);}
v:=(x-y)/2;
u:=-v*i;
L:=L,hild(x,x+v,n-1);
L:=L,hilg(x+v,x+v+u,n-1);
b:=berg(x+v+u,x+u,n-1);
L:=L,tail(b);
b:=b[0];
L:=L,hild(b,b-v,n-1);
return (b-v),L;
}:;
//le morceau 4
berd(x,y,n):={
local u,v,a,L;
L:=NULL;
if (n==0) {return y,segment(x,y);}
v:=(x-y)/2;
u:=-v*i;
L:=L,hilg(x,x+v,n-1);
L:=L,hild(x+v,x+v-u,n-1);
a:=berd(x+v-u,x-u,n-1);
L:=L,tail(a);
a:=a[0];
L:=L,hilg(a,a-v,n-1);
return a-v,L;
}
:;

On tape :
hilg(-2,0,4)
On obtient :

On tape :
hilg(-2,0,5)
On obtient :

La courbe de Gosper

//gosper(-2-2*i,2-2*i,2)ou gosper(-2-2*i,2-2*i,3)
gosper(x,y,n):={
local a,b,c,d,f,g,L;
L:=NULL;
if (n==0) return segment(x,y);
a:=x+(y-x)/sqrt(7)*exp(evalf(-i*acos(5*sqrt(7)/14)));
c:=x+(a-x)*exp(evalf(i*pi/3));
b:=c+a-x;
d:=c+(a-x)*exp(evalf(2*i*pi/3));
f:=d+2*(a-x);
g:=(d+f)/2;
L:=L,gosper(x,a,n-1);
L:=L,gosper(b,a,n-1);
L:=L,gosper(c,b,n-1);
L:=L,gosper(c,d,n-1);
L:=L,gosper(d,g,n-1);
L:=L,gosper(g,f,n-1);
L:=L,gosper(y,f,n-1);
};

On tape :
gosper(-2-2*i,2-2*i,3)
On obtient :

On tape :
gosper(-2-2*i,2-2*i,4)
On obtient :

Des plantes et des arbres

Voici des sapins :

//Voici des sapins....sapin(0,2*i)
sapin(x,y):={
 local L;
 L:=NULL;
 if (abs(x-y)<0.05) {return segment(x,y);}
 L:=L,sapin(x,x+(y-x)*0.5*exp(i));
 L:=L,sapin(x,x+(y-x)*0.5*exp(-i));
 L:=L,segment(x,(3*x+y)/4);
 L:=L,sapin((3*x+y)/4,y);
return L;
}:;

On tape : sapin(0,2*i)
On obtient :

Voici des fleurs :

//Voici des fleurs....fleur(0,2*i)
fleur(x,y):={
 local L;
 L:=NULL;
 if (abs(x-y)<0.05) {return segment(x,y),cercle(y,(y-x)*0.3);}
 L:=L,segment(x,y),cercle(y,(y-x)*0.3),cercle(y,(y-x)*0.2);
 L:=L,fleur(x,x+(y-x)*0.5*exp(i*0.5));
 L:=L,fleur(x,x+(y-x)*0.5*exp(-i*0.5));
}:;

On tape : fleur(0,2*i)
On obtient :

Voici des arbres :

arbre1(x,y):={
 local L;
 L:=NULL;
 if (abs(x-y)<0.1) {return segment(x,y);}
 L:=L,segment(x,(x+y)/2);
 L:=L,arbre1((x+y)/2,(x+y)/2+(y-x)*0.5*exp(i*0.5));
 L:=L,arbre1((x+y)/2,(x+y)/2+(y-x)*0.5*exp(-i*0.5));
return L;
}:;

On tape : arbre1(0,2*i)
On obtient :

et des arbres moins déplumés :

arbre2(x,y):={
 local L;
 L:=NULL;
 if (abs(x-y)<0.1) {return segment(x,y);}
 L:=L,segment(x,(x+y)/2);
 L:=L,arbre2((x+y)/2,(x+y)/2+(y-x)*0.5*exp(i*0.5));
 L:=L,arbre2((x+y)/2,(x+y)/2+(y-x)*0.5*exp(-i*0.5));
 L:=L,arbre2((x+y)/2,(x+y)/2+(y-x)*0.5*exp(i));
 L:=L,arbre2((x+y)/2,(x+y)/2+(y-x)*0.5*exp(-i));
return L;
}:;

On tape : arbre2(0,2*i)
On obtient :

et un epineux :

arbre3(x,y):={
 local L;
 L:=NULL;
 if (abs(x-y)<0.1) {return segment(x,y);}
 L:=L,segment(x,(x+y)*0.5);
 L:=L,arbre3((3*x+y)/4,(3*x+y)/4+(y-x)*0.25*exp(i*0.5));
 L:=L,arbre3((3*x+y)/4,(3*x+y)/4+(y-x)*0.25*exp(-i*0.5));
 L:=L,arbre3((x+y)/2,(x+y)/2+(y-x)*0.5*exp(i));
 L:=L,arbre3((x+y)/2,(x+y)/2+(y-x)*0.5*exp(-i));
return L;
}:;

On tape : arbre3(0,2*i)
On obtient :


Voici des fougères :

//une fougere par ex fougere(-2*i,2*i)
fougere(x,y):={
local a,L;
L:=NULL;
 if (abs(x-y)<0.2) {return segment(x,y);}
a:=x+(y-x)*0.15*exp(-i*0.2);
L:=L,segment(x,a);
L:=L,fougere(a,a+(y-x)*0.33*exp(i*1.2));
L:=L,fougere(a,a+(y-x)*0.33*exp(-i*1.2));
L:=L,fougere(a,a+(y-x)*0.85*exp(-i*0.2));
return L;
}:;
//par ex fougeres(-2*i,2*i,0.05,6)
fougeres(x,y,t,n):={
local a,L;
if (n==0) {return segment(x,(x+y)/2);}
//a:=x+(y-x)*0.15*exp(-i*t);
a:=x+(y-x)*0.15;
L:=NULL;
L:=L,segment(x,a);
L:=L,fougeres(a,a+(y-x)*0.33*exp(i*1.2),t,n-1);
L:=L,fougeres(a,a+(y-x)*0.33*exp(-i*1.2),t,n-1);
L:=L,fougeres(a,a+(y-x)*0.85*exp(-i*t),t,n-1);
return L;
}:;

On tape : fougere(-2*i,2*i)
On obtient :

On tape : fougeres(-2*i,2*i,0.05,6)
On obtient :

Et enfin, le bouquet final :

//et le bouquet final bouquet(0,2*i)
bouquet(x,y):={
 local L;
 L:=NULL;
 if (abs(x-y)<0.1) {return segment(x,y);}
 L:=L,segment(x,(x+y)*0.5);
 L:=L,bouquet((3*x+y)/4,(3*x+y)/4+(y-x)*0.25*exp(i*0.5));
 L:=L,bouquet((3*x+y)/4,(3*x+y)/4+(y-x)*0.25*exp(-i*0.5));
 L:=L,bouquet((x+y)/2,(x+y)/2+(y-x)*0.5*exp(i));
 L:=L,bouquet((x+y)/2,(x+y)/2+(y-x)*0.5*exp(-i));
 L:=L,bouquet((x+y)/2,(x+y)/2+(y-x)*0.5);
 return L;
}:;

On tape : bouquet(0,2*i)
On obtient :

Retour à la page personnelle de Bernard Parisse.
Previous Up Next