Dendrite tridimensionnelle

Wikipedia : Ensemble de Julia, Julia set (EN), Dendrite (EN)

Volodia Nekrashevych's picture gallery : dendrites et graphes de Schreier

Introduction (et rappel) : la dendrite de Julia

Considérons un peu l'image ci-dessous. Il s'agit d'une représentation (imparfaite) d'un objet fractal remarquable parfois appelé la dendrite de Julia. Mathématiquement, une structure dendritique (ou dendrite) est un ensemble de points connexe (sans trou), d'intérieur vide (infiniment fin, de sorte qu'aucun disque, si minuscule soit-il, ne peut être inclus à l'intérieur1), donc de surface nulle, mais qui présente une infinité de ramifications, à tel point que la longueur de son pourtour est infinie ; de plus, cette courbe ne boucle pas sur elle-même.

Cette dendrite-ci possède de plus une symétrie remarquable, elle est (asymptotiquement seulement) auto-similaire, on retrouve (presque) la même structure à toutes les échelles.

frac-dendrite.jpg

Plus précisément en termes techniques, il s'agit d'une représentation de l'ensemble de Julia quadratique associé au paramètre complexe $C=i$. Ce paramètre est situé exactement sur la frontière de l'ensemble de Mandelbrot (à la pointe d'un des plus grands filaments latéraux), ce qui explique qu'il soit à la fois connexe et d'intérieur vide (voir la description des ensembles de Julia et Mandelbrot). Les algorithmes de type méthode d'itération inverse permettent de le dessiner très rapidement.

Il est très beau cet ensemble, mais, il est tout plat. La question semble naturelle, comment obtenir une telle structure mais en 3D ?
Soyons très précis, repartons de cette image, de la dendrite de Julia : peut-on imaginer une structure dendritique tridimensionnelle qui, sous un certain angle, aurait l'apparence de la dendrite de Julia ? (la réponse est oui, le lecteur devrait en être convaincu à la fin de cette page, c'est le comment qui est compliqué).

Construction d'une dendrite parfaitement auto-similaire qui ressemble à la dendrite de Julia

On présente ici une solution approchée. Il s'agit d'une tricherie : on ne va pas exactement considérer la dendrite de Julia, mais une dendrite exactement autosimilaire. On peut définir une telle structure par une formule de récurrence (comme la courbe du flocon de Von Koch). Ici on va considérer un motif à 5 branches, rien ne vaut un bon dessin :

dendrite_construction.jpg

On part d'un segment (étape 1), et on le transforme en un motif composé de 5 segments, (par translations, homothéties et rotations du segment original). On peut alors répéter "indéfiniment" cette opération, les 5 segments tracés à l'étape 2 donnent engendrent 25 nouveaux segments à l'étape 3, puis 125 à l'étape 4, etc :

dendrite2.jpg
dendrite3.jpg
dendrite4.jpg

Etape 2

Etape 3

Etape 4

A la limite, cette construction converge vers une dendrite parfaitement autosimilaire, et (en choisissant convenablement les proportions et les angles du motif initial) il faudrait une loupe pour remarquer qu'elle est sensiblement différente de la dendrite de Julia.

Nous avons donc reconstruit (approximativement) notre dendrite par une autre méthode très simple : la répétition de 5 transformations linéaires (celles qui transforment le grand segment initial en 5 plus petits). Or, cette méthode a l'avantage d'être facilement généralisable à une 3ème dimension.

Construction d'une dendrite auto-similaire tridimensionnelle

Imaginons qu'au lieu de transformer le segment initial en un motif plat, on utilise un motif dont les branches partent dans les 3 dimensions, comme illustré ci-dessous (dans cette figure, afin de représenter le relief, on utilise des couleurs claires pour les points proches et inversement). Un motif tridimensionnel, qui vu sous un certain angle, correspond au motif plat à 5 branches.

motif_3D.jpg

Vu d'un certain angle (la flèche gauche du repère tridimensionnel), lorsque les points $A$ et $B$ et les points $C$ et $D$ apparaissent confondus, on retrouve bien notre motif à 5 branches. Il est alors facile (pour un ordinateur surtout) de répéter la même construction, et obtient une belle dendrite tridimensionnelle qui, vue de ce même angle particulier, a exactement le même aspect que la dendrite plate de Julia. L'image suivante montre le résultat obtenu (au bout de 7 étapes), où un effet de relief est donné en coloriant les points proches en couleur claire et inversement.

dendrite_3d.png

Ci-dessous, le code Python permettant de générer cette image.

python-logo.gif
dendrite3d.py
"""
3D dendrite
"""
import datetime
timedebut = datetime.datetime.now()
 
from matplotlib.pyplot import  show, plot, clf, savefig, xlim, ylim,   figure, axes, subplot
from numpy import sqrt, empty, real, imag, pi, cos, sin, exp, sign, array
from cmath import polar, rect
 
print 
print"3D Dendrite"   
print
 
# #######################
# INITIALISATIONS
# #######################
 
# Some parameters
 
# initial pattern parameters
 
ordre=7
lgm = .5 
ptm = -pi*.15
pts = -pi*.25 
agd = pi*.15
 
# number of iteration
 
maxiter=7
 
# 3D display
 
echelle = .85 
profondeur = 2.0 
distance = 4.8
pointfuite = 0.0
 
# Functions definitions
 
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
 
def rotation(x,y,z,anglexy,anglexz,angleyz) :
    res1 = ( x + 1j * y ) * rect( 1, anglexy)
    res2 = ( real(res1)  + 1j*z ) * rect(1, anglexz)
    res3 = ( imag(res1) + 1j * imag(res2) ) * rect(1,angleyz)
    return array([real(res2), real(res3), imag(res3)])
 
# Variables and arrays initialisations
 
nbrpoints = ordre**(maxiter-1)
za = empty(maxiter* nbrpoints*3)
za.shape=(maxiter, nbrpoints, 3)
zb = empty(maxiter* nbrpoints*3)
zb.shape=(maxiter, nbrpoints, 3)
 
# Plot initialisation
 
clf()
subplot(1,1,1, axisbg=(0,0,0))
 
# ####################### 
# FRACTAL SET COMPUTATION
# #######################
 
# definition of the 2 initial points, beginning and end of the initial segment
 
za[0][0] = array([1.5,-1.0,0.0])
zb[0][0] = array([-1.5,1.0,0.0])
 
for iter in range(1,maxiter) :
 
# construction of the 7 new segments at the next iteration step, for each segments
 
    for antecedent in range(ordre**(iter-1)) :
 
        milieu = .5*(za[iter-1][antecedent]+zb[iter-1][antecedent])
        vec = za[iter-1][antecedent]-milieu
 
        za[iter][antecedent*ordre] =milieu +vecteur
        zb[iter][antecedent*ordre] =milieu +lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)
 
        za[iter][antecedent*ordre+1] =milieu +1.0*rotation(vec[0],vec[1],vec[2], pts, 0.0,-agd)
        zb[iter][antecedent*ordre+1] =milieu +lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)                
        za[iter][antecedent*ordre+2] =milieu +1.0*rotation(vec[0],vec[1],vec[2], pts, 0.0,agd)
        zb[iter][antecedent*ordre+2] =milieu +lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)                
 
        za[iter][antecedent*ordre+3] =milieu +lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)            
        zb[iter][antecedent*ordre+3] =milieu -lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)            
 
        zb[iter][antecedent*ordre+4] =milieu -1.0*rotation(vec[0],vec[1],vec[2], pts, 0.0,-agd)    
        za[iter][antecedent*ordre+4] =milieu -lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)            
        zb[iter][antecedent*ordre+5] =milieu -1.0*rotation(vec[0],vec[1],vec[2], pts, 0.0,agd)    
        za[iter][antecedent*ordre+5] =milieu -lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)            
 
        za[iter][antecedent*ordre+6] =milieu -lgm*rotation(vec[0],vec[1],vec[2], ptm, 0.0,0.0)    
        zb[iter][antecedent*ordre+6] =milieu -vecteur                        
 
# ####################### 
# IMAGE GENERATION
# #######################
 
# spatial rotation
 
x = za[maxiter-1,:,0]
y = za[maxiter-1,:,1]
h = za[maxiter-1,:,2]
res = rotation(x, y, h, 0.0*pi, -0.1*pi, -0.05*pi)
x = res[0]
y = res[1]
h = res[2]
 
# planar projection 
 
nuage = ( x+1j*y -pointfuite) * 20.0 *( distance - echelle * h)**-2 +pointfuite
dist =  ( distance - echelle * h )**2 + x**2 + y**2
 
# plot
 
for ind in range(2,50) :
    mask = ( sqrt(dist) < (50-ind)/27.0 + 4.75  )
    plot(real(nuage[mask]),imag(nuage[mask]),".", markersize=(1+ .5*(50-ind)*(50-ind)*(50-ind)/2500.0),  
                                       color=couleur(ind*ind*ind/250000.0), alpha=.1 )
xlim([-2.4,2.4])
ylim([-1.8,1.8])
savefig('dendrite_3D.png',facecolor=(0,0,0),edgecolor=(0,0,0), dpi=100)
 
timefin = datetime.datetime.now()
print "OK (",(timefin-timedebut).seconds,"s)"
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License