fractale — Tracé de fractale itératif et infini

../_images/koch.png

Introduction

La manière la plus simple de tracer les fractales de type flocon de Koch (voir ci-dessus) est sans doute la manière récursive suivante

import turtle

def koch(profondeur):
    if profondeur == 0:
        turtle.forward(10)
    else:
        koch(profondeur - 1)
        turtle.left(60)
        koch(profondeur - 1)
        turtle.right(120)
        koch(profondeur - 1)
        turtle.left(60)
        koch(profondeur - 1)

koch(5)

L’unique problème que je vois avec cette méthode est qu’il faut définir à l’avance la profondeur de la fractale. La méthode itérative que je propose continue à dessiner la fractale tant que l’utilisateur ne l’arrête pas.

Mettons nous bien d’accord : je pense que la méthode itérative mise en œuvre ici est moins bonne que la méthode récursive habituelle (notamment, je n’ai pas réussi à dessiner une fractale de type courbe du dragon ; c’est possible, mais très technique). Mais j’avais envie de voir ce que ça donnerait.

Description

La fonction effectuant le tracé (ou, selon le point de vue, dirigeant la tortue) est la fonction trace(), dont le cœur peut être réduit à

fractale = Fractale(angles)
for angle in fractale:
    turtle.left(angle)
    turtle.forward(1)

La partie intéressante est donc dans l’itérateur de la classe Fractale, dont le code est :

 1    def __iter__(self):
 2        """Itérateur sur les angles à prendre pour tracer la fractale"""
 3        while True:
 4            index = 0
 5            retenue = 1
 6            angle = 0
 7            while retenue != 0:
 8                self.compteur[index] += 1
 9                angle += self.angles[self.compteur[index]]
10                if self.compteur[index] == self.base:
11                    self.compteur[index] = 0
12                    if index == (len(self.compteur) - 1):
13                        self.compteur.append(0)
14                    angle += self.angles[self.compteur[index]]
15                    index += 1
16                    retenue = 1
17                else:
18                    retenue = 0
19            yield angle

Un fractale est une imbrication d’une infinité de motifs de base imbriqués les uns dans les autres. L’objet Fractale.compteur est une liste indiquant à quelle étape du motif de base est en cours de dessin, suivant la profondeur du motif considéré.

../_images/etapes.png

Par exemple (sur la figure ci-contre), ce compteur valant [1, 3, 2] indique que la fractale en est à :

  • la seconde étape (1) du motif le plus profond (en bleu),

  • la quatrième étape (3) du motif supérieur (en vert),

  • la troisième étape (2) du plus grand motif (en rouge).

  • et, implicitement, la première étape (0) de tous les motifs de taille supérieure.

Le calcul de l’angle pris par la tortue à chaque étape se fait alors simplement en ajoutant les angles des étapes des motifs ayant évolué.

Usage

usage: fractale [-h] [--version] [-f] [-t NAME] [angle ...]

Positional Arguments

angle

Angles of the base drawing of the frarctal.

Named Arguments

--version

show program’s version number and exit

-f, --fast

Fast drawing.

Default: False

-t, --type

Possible choices: koch

Predefined fractals: “koch”: Koch snowflake,