Wikipedia : Ensemble de Mandelbrot, Ensemble de Julia, Mandelbulb, IIM : Inverse Iteration Method (EN).
Les fractales "classiques" de type Julia ou Mandelbrot, obtenues par itération d'une fonction complexe, sont planes par construction. Une grande question encore très ouverte est :
Comment obtenir des fractales "aussi belles", mais en 3 dimensions, en volume ?
On sait obtenir des généralisations en dimension 4 (notamment en remplaçant les nombres complexes par les quaternions), mais il n'est pas évident de généraliser ce type de construction à la dimension 3, d'une certaine manière il faut tricher, et déjà imposer une forme a priori.
Une manière célèbre consiste à construire une algèbre en dimension 31, et conduit à une famille de fractales très esthétiques appelées "Mandelbulb".
Ici on présente une autre manière, assez directe, qui consiste à considérer une superposition de fractales planes, empilées selon une troisième dimension, comme si elles étaient chacunes dessinées sur les pages (transparentes) d'un livre fermé.
Par exemple, plus précisément, on peut construire un volume où chaque plan horizontal est un Julia pour un certain paramètre qui varie continûment avec la hauteur2. D'un point de vue graphique, le choix des ensembles de Julia est pratique car on peut alors appliquer la méthode rapide d'itération inverse.
Il s'agit bien d'une tricherie, dans le sens où les tranches horizontales de cet ensemble sont fractales, mais pas les tranches verticales, qui présentent des courbes régulières (tant qu'on fait varier le paramètre du Julia de manière régulière avec la hauteur).
A titre d'exemple, l'image suivante est une superposition de Julia (vue du dessus) dont le paramètre varie le long du demi-cercle unité droit3. Chaque Julia est tracé dans une teinte différente, qui va du bleu foncé au voisinage du point $-i$, en passant par le blanc au voisinage du point $1$, jusqu'au beige foncé au voisinage du point $i$. Les couleurs sont légèrement transparentes et on applique un effet de rétrécissement en fonction de l'éloignement (de bleu, près, à beige, loin). On voit comme les Julia se déforment en suivant des courbes douces (par opposition à fractale), en réponse à la régularité du demi-cercle.
(cliquez sur l'image pour l'agrandir)
Ci-dessous, le code Python permettant de générer cette image (en une petite minute).
""" Fractal Julia Set - inverse iteration method """ import datetime timedebut = datetime.datetime.now() print print"Julia superposition" print from matplotlib.pyplot import show, plot, clf, savefig, xlim, ylim, figure, axes, subplot from numpy import sqrt, empty, real, imag, pi, cos, sin, exp from cmath import polar, rect # Some parameters # Julia set order (Z -> Z^ordre + C) # this code only works 2 and 3 ordre=2 # Number of polynomial iterations maxiter=12 # 3D alpha = .7 profondeur = 2.0 # number of Julia planes resolution = 800 def couleur(ind) : if ind<=.5 : couleur1=4.0*ind*ind couleur2=2.0*ind couleur3=1-(4.0*(.5-ind)*(.5-ind)) else : couleur1= 1.333*(1.0-ind*ind) couleur2= 2.0*(1-ind) couleur3= (1-ind)*(1-ind)*4.0 return couleur1,couleur2,couleur3 nbrpoints = ordre**(maxiter-1) print nbrpoints,"*",resolution,"=",nbrpoints*resolution,"points" print z = empty(maxiter* nbrpoints,dtype='complex') z.shape=(maxiter, nbrpoints) z[0][0]=complex(0.0,0.0) clf() subplot(1,1,1, axisbg=(0,0,0)) for dec in range(resolution,-1,-1) : ind= float(dec)/float(resolution) # variation of the parameter C=rect(1.0, -2.0* pi*(ind-.5)) for iter in range(1,maxiter) : for antecedent in range(ordre**(iter-1)) : r,phi = polar(z[iter-1][antecedent]-C) if (ordre==2) : z[iter][antecedent*2] = rect(sqrt(r),phi*.5) z[iter][antecedent*2+1] = - z[iter][antecedent*2] else : z[iter][antecedent*3] = rect(r**(1.0/3.0),phi/3.0) z[iter][antecedent*3+1] = rect(r**(1.0/3.0),phi/3.0+2.0*pi/3.0) z[iter][antecedent*3+2] = rect(r**(1.0/3.0),phi/3.0-2.0*pi/3.0) # 3D display # rotation around the vertical axis angle = 0.0 x=real(z[maxiter-1])* cos(angle) - profondeur*(ind-.5) *sin(angle) y=imag(z[maxiter-1]) h=real(z[maxiter-1])* sin(angle) + profondeur*(ind-.5)*cos(angle) pointfuite = 0.0 nuage = ( x+1j*y -pointfuite) * exp( - alpha * h) +pointfuite plot(real(nuage),imag(nuage), ".", markersize=1, color=couleur(ind), alpha=ind*(1-ind)*ind*(1-ind) ) xlim([-3.0,3.0]) ylim([-2.25,2.25]) savefig('SuperpJulia.png',facecolor=(0,0,0),edgecolor=(0,0,0), dpi=175) timefin = datetime.datetime.now() print "OK (",(timefin-timedebut).seconds,"s)"