Code source de sapinNoel

#! /usr/bin/env python3
# -*- coding: utf-8; mode: python -*-
""" Cadeau de Noël.

Petit script Python pour tracer un sapin de Noël, rédigé par Arnaud Basson, pour le cours d'informatique pour tous en prépa MP au Lycée Lakanal.


- *Date :* Noël 2015 ! (24 décembre 2015),
- *Auteur :* Arnaud Basson, pour le cours d'informatique pour tous en prépa MP (http://perso.crans.org/besson/infoMP/),
- *Licence :* MIT Licence (http://lbesson.mit-license.org).
"""

from __future__ import print_function, division  # Python 2 compatibility

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.collections as coll
import matplotlib.animation as anim


[docs]def simil(u, v): r""" Similitude complexe, donné par ses paramètres u et v. - Renvoie une *fonction* :math:`f: z \mapsto a \times z + b.` """ # Si f(z) = a z + b # Par définition u = f(0) = b, v = f(i) = a*i + b # Alors b = u, a = (v-u)/i = i(u-v) b = u a = 1j*(u-v) def f(z): """ f(z) = a z + b """ return a * z + b return f
#: 5 similitudes pour le système itéré #: Première similitude du système itéré, #: :math:`u = 0.2i, v = 0.2i + 0.5 \mathrm{e}^{(i \pi / 7)}` f1 = simil(0.2j, 0.2j + 0.5*np.exp(1j*np.pi/7)) #: Seconde similitude du système itéré, #: :math:`u = 0.22i, v = 0.22i + 0.45 \mathrm{e}^{(60 i \pi / 180)}` f2 = simil(0.22j, 0.22j + 0.45j*np.exp(1j*60*np.pi/180)) #: Troisième similitude du système itéré, #: :math:`u = 0.55i, v = 0.55i + 0.35 \mathrm{e}^{(30 i \pi / 180)}` f3 = simil(0.55j, 0.55j + 0.35*np.exp(1j*30*np.pi/180)) #: Quatrième similitude du système itéré, #: :math:`u = 0.57i, v = 0.57i + 0.3 i \mathrm{e}^{(i \pi / 3)}` f4 = simil(0.57j, 0.57j + 0.3j*np.exp(1j*np.pi/3)) #: Cinquième similitude du système itéré, #: :math:`u = 0.7i, v = .0\mathrm{1} - 1.2i` f5 = simil(0.7j, 1.2j-0.01)
[docs]def iterer(n): """ Calculer n itérations du système complexes des 5 similitudes :py:func:`f1`, :py:func:`f2`, :py:func:`f3`, :py:func:`f4`, :py:func:`f5`. - Renvoie une liste d'affixes *complexes*. - Complexité temporelle et mémoire en :math:`O(5^n)` (attention à garder n petit !). """ L = [0, 0.7j] L1 = L[:] # Copie for _ in range(n): L2 = [] for f in [f1, f2, f3, f4, f5]: L2.extend([f(z) for z in L1]) L.extend(L2) L1 = L2 return L
[docs]def tracer(n): """ Tracer la courbe fractale obtenue par n itérations du F-système. .. warning:: Cette fonction est un peu complexe... Ce qui est utilisé dans cette fonction **dépasse complètement le cadre du programme officiel** ! Ne perdez pas trop de temps à comprendre son fonctionnement, et ne retenez aucune des astuces ou idées vues ici. """ global sca # Pour que clignoter marche facilement. # Affixes complexes L = iterer(n) pts = [(z.real, z.imag) for z in L] fig = plt.figure() # Afficher ces points comme des lignes vertes foncées (le sapin) segments = coll.LineCollection(zip(pts[::2], pts[1::2]), color='darkgreen') ax = plt.gca() ax.add_collection(segments) # Ajouter des boules clignotantes nb = 30 l = len(L) p = l//nb if l >= nb else 1 x = [z.real for z in L[1::p]] y = [z.imag for z in L[1::p]] # Alterner sur ces trois couleurs couleurs = ['red', 'blue', 'yellow'] c = [couleurs[k % len(couleurs)] for k in range(len(x))] # Afficher ces boules sca = plt.scatter(x, y, s=60, c=c, zorder=2) plt.axis('equal') plt.ylim(0, 1.45) plt.xticks([]) plt.yticks([]) # Lancer l'animation a = anim.FuncAnimation(fig, clignoter, interval=20, # nb itérations repeat=False, blit=True # True to only draw what have changed ) plt.show() # FIXME not working on Windows! # Conclude by saving the animation a.save('sapinNoel.mp4', fps=1, writer='ffmpeg') # And saving as a GIF file also works now :) a.save('sapinNoel.gif', fps=1, writer='imagemagick')
# Fin tracer
[docs]def clignoter(i): """ Fonction pour faire changer les boules de couleurs à chaque itération de l'animation !""" coul = sca.get_facecolor() # array N*4 (RGBA) coul2 = np.zeros_like(coul) coul2[:-1] = coul[1:] coul2[-1] = coul[0] sca.set_facecolor(coul2)
# On conclut par lancer l'animation ! if __name__ == '__main__': tracer(6) # Fin sapinNoel.py