Logiciel libre de géométrie, d'analyse et de simulation multiplateforme par Yves Biton

Accueil Tutoriels l’API de MathGraph32

Programmer une figure en Python : La courbe de Hilbert

modification dimanche 16 avril 2024.

Toutes les versions de cet article : [English] [français]



La version 7.9.1 permet de créer des objets dans une figure en langage Python ou JavaScript.

Ici nous allons générer une figure fractale : la courbe de Hilbert en Python.

Vous pouvez voir l’équivalent codé en JavaScript sur cette page.

Si vous changez le code Python ci-dessous, cliquez sur le bouton Exécuter en dessous de ce cadre d’édition.

La figure obtenue est dynamique : vous pouvez capturer les points A, B et C une fois la figure construite.
Cliquez sur un des boutons sur fonc jaune pour lancer la construction à un nveau donné.

Vous trouverez en bas de cet article des explications sur la méthode employée et les fonctions de l’API utilisées.


Comment est construite la figure

La construction de base figure est affichée ci-dessous :

Les trois points de base sont A, B et C.

On commence par construire les milieux I et J des segments [AB] et [BC] puis le point D, image de A par l’homothétie (dilation en anglais) de centre C et rapport -1/4.
On construit ensuite à l’aide de translations successives les points D, E, F, G, H, K, L, M, N, O, P, Q, R, S, T, U et on génère la ligne brisée pour le niveau de profondeur 0.

Pour le niveau de profondeur 1, on réitère la constriction précédente quatre fois de suite :
- En remplaçant A, B et C par D, E et F
- En remplaçant A ,B et C par H, K et L
- En remplaçant A ,B et C par N, O et B
- En remplaçant A ,B et C par R, S et T

On obtient alors la figure ci-dessous (les segments verts font la jonction entre les quatre lignes brisées rajoutées).


La courbe de Hilbert théorique est obtenue en réitérant le processus à l’infini. C’est une courbe continue qui remplit entièrement un carré (ici un parallélogramme).

Dans notre figure ci-dessus nous nous arrêtons au niveau 5 de récursion. Au-delà on dépasse la définition graphique d’un écran usuel.

Explications concernant le code de l’API de MathGraph32 utilisé ici :

On commence par créer les trois points de base A, B et C avec les lignes de codes suivantes :

A = addFreePoint({'x':width/4 + 20, 'y':3*height/4 - 20, 'name':'A', 'color':'red', 'absCoord': True})
B = addFreePoint({'x':3*width/4 - 20, 'y':3*height/4 - 20, 'name':'B', 'color':'red', 'absCoord': True})
C = addFreePoint({'x':3*width/4 - 20, 'y':height/4 + 20, 'name':'C', 'color':'red', 'absCoord': True})

On emploie ici la syntaxe objet pour les créer pour pouvoir passer le paramètre absCoord à True ce qui implique sue les paramètres coordonnées x et y pour ces points sont donnés en coordonnées SVG (abscisses à 0 au coin haut gauche et croissantes de la gauche vers la droite, ordonnées 0 au coin haut et gauche et croissantes du bas vers le haut).

Le code de la fonction hilbert(A, B, C, prof, tabPoints) est assez facile à comprendre en regardant l’avant dernière figure ci-dessus.

La fonction rajoute à la liste points (vide avant les appels) les points créés au dernier niveau de récursion.
Cette liste est ensuite utilisée pour créer la ligne brisée finale.

Les fonctions hilbertNiv0, hilbertNiv1, hilbertNiv2, hilbertNiv3, hilbertNiv4 et hilbertNiv5 créent la ligne brisée finale aux niveaux de récursion 0, 1, 2, 3, 4 et 5.

Les lignes suivantes créent des boutons qui, lorsqu’on cliquera dessus, lanceront les fonctions ci-dessus :

btn0 = addActionButton('Hilbert prof = 0', hilbertNiv0, 10, 10, 'btn0')
btn1 = addActionButton('Hilbert prof = 1', hilbertNiv1, 10, 40, 'btn1')
btn2 = addActionButton('Hilbert prof = 2', hilbertNiv2, 10, 70, 'btn2')
btn3 = addActionButton('Hilbert prof = 3', hilbertNiv3, 10, 100, 'btn3')
btn4 = addActionButton('Hilbert prof = 4', hilbertNiv4, 10, 130, 'btn4')
btn5 = addActionButton('Hilbert prof = 5', hilbertNiv5, 10, 160, 'btn5')

Au-dessous de ces lignes les deux lignes suivantes :

W = addFreePoint(0, 0, 'W')
setHidden(W)

créent après ces boutons un point caché W dont la seule utilité est d’aider à détruire les objets créés après lui au début des fonctions hilbertNiv0 à hilbertNiv5.

Examinons par exemple le code de la fonction hilbertNiv5 :

def hilbertNiv5():
   deleteAfter('W')
   points = []
   hilbert(A, B, C, 5, points)
   addBrokenLine(points, 'blue')
   displayButtonsOnTop()

Elle commence par détruire les éventuels objets créés après le point W. Ces objets sont par exemple ceux qui ont été créé en cliquant précédemment sur un des boutons.
On initialise ensuite la liste points à une liste vide.
On lance l’exécution de la fonction hilbert sur les points A, B et C au niveau 5.
On crée ensuite la ligne brisée à partir de la liste points générée par la fonction hilbert.
On appelle ensuite la fonction displayButtonsOnTop.
Cette fonction reclasse la représentation graphique des boutons au-dessus de celle des objets générés par la fonction hilbert de façon à ce que ces boutons restent bien visibles une fois la fonction exécutée.

Examinons le code de cette fonction :

def displayButtonsOnTop():
   displayOnTop('btn0')
   displayOnTop('btn1')
   displayOnTop('btn2')
   displayOnTop('btn3')
   displayOnTop('btn4')
   displayOnTop('btn5')

Le premier bouton a par exemple été créé avec le code suivant : btn0 = addActionButton(’Hilbert prof = 0’, hilbertNiv0, 10, 10, ’btn0’)
Le dernier argument ’btn0’ est un tag MathGraph32 qui a été mis sur ce bouton.
C’est ce tag qui est passé en argument dans la ligne : displayOnTop(’btn0’)
Pourquoi ne pas avoir ici passé comme argument l’objet btn0 ? La raison est que le bouton est nécessairement créé après la fonction hilbertNiv0 qui elle-même utilise la fonction displayButtonsOnTop.
Comme on ne peut pas utiliser cet objet avec les règles usuelles de la programmation Python, on utilise le tag qui lui a été affecté, la chaîne de caractères ’btn0’