Videos de fractales de mandelbrot

Description

Programme qui creer des videos de fractales (pour l'instant
que des fractales de l'ensemble de Mandelbrot).

Les videos sont enregistrees dans des fichiers .vid, le format est non-standart :
c'est fait personnellement, donc une amelioration serait de faire des .avi ...
Il y a 4 formats de videos :
- bitmap : enregistre image par image sans compression, pixel par pixel,
les fichiers sont gros, mais la compression est rapide !
- Diff. : enregistre la premier image en bitmap, puis pour les images
suivantes, enregistre seulement les pixels qui different de l'image
precedente; peu utile pour des images fractales ...
- RLE : compression RLE : on regroupe les memes pixels (memes couleurs)
- Huffman : compression de chaque image par l'algorithme de Huffman
(statique), cf http://www.cppfrance.com/codes/HUFFMAN-CPPFRANCE_38961.aspx

Un lecteur de video est bien-sur integrer dans le programme.

L'interface pour creer la video est assez simple d'utilisation :
A gauche la visualisation, le dessin de Mandelbrot avec
les options de coloriage courant.
Les informations de chaque pixel s'affiche a bas, et il y a :
sa position (x,y), sa couleur (RGB), et 4 parametres
de coloriage : iteration, attacteur, potentiel, angle

A droite il y a trois parties :
  • en haut les outils pour definir la position de la camera

au cours du temps. Il y a une pile de "vue" associee a
un temps. Par exemple : le programme s'ouvre sur l'ensemble
de Mandelbrot, et le temps est a 0ms, donc la video commencera
par cette image, ensuite zoomer sur une partie interessante
et metter le tempsa 5000ms, ainsi la camera va passer
lineairement de la position initiale, a la position de la partie
choisie en 5 secondes (soit 5000 milli-secondes), et ainsi de
suite, vous pouvez ajouter des "vues". Les vues se visualisent
par des rectangles dans l'image a gauche. Pour enlever
une vur, cliquer sur la croix. La logique est celle d'une pile
donc "ajouter" <=> pusher et "X" <=> poper
  • au milieu la partie creation de la video

il faut choisir un format video (bitamp,diff,RLE,huffman)
il faut choisir un nom de fichier *.vid
il faut choisir la taille de la video (cx,cy)
(NB cette taille sera arrondie sur un mutiple de 4 superieur)
il faut choisir le nombre d'images affichees par secondes,
(NB par trop grande, votre PC ne suivera pas,
par exemple 5 ca saccade, alors que 10 c'est assez fluide)
Puis il suffit de cliquer sur "Creer", alors vous pouvez
voir l'evolution de la creation grace a deux 'progress bars' :
celle du haut la progression du calcule de l'image courante,
celle dubas, la progression du calcule totale de la video.
Vous pouvez apres cliquez sur "Voir" pour lancer une fenere
de lecture de la video.
  • en bas la partie des parametres de coloriage

il y a 4 facons dans ce programme de colorier
Pour les comprendre revenons sur l'ensemble de Mandelbrot :
La definition est la suivante, un peu abstraitre, mais bon ...
c'est l'ensemble des nombres complexes (donc point du plan)
tel que "la suite" ne diverge pas (i.e. module de u(n) < 2
pour tout n)
"Le suite" est definie par l'iteration suivante :
soit Z le complexe dont on cherche la couleur :
U(0) = Z
u(N+1) = u(n)^2 + Z

En faite on peut voir cela comme une suite de polynome en Z :
P[0](Z) = Z
P[1](Z) = Z²+Z
P[2](Z) = (Z²+Z)² + Z = Z^4 + 2.Z^3 + Z^2 + Z
...

Maintenant on peut definir l'iteration :
c'est l'indice a partir duquel la suite diverge, i.e.
en terme pompeux : minimum de l'ensemble des 'n'
tel que |u(n)|>=2
Pour les points n'appartenant pas a l'ensemble, ce minimum
existe, et permet d'avoir un jolie fractale.
Les points de l'ensemble de Mandelbrot sont colorier en noir.
Ensuite la il faut faire appelle a l'artiste, car dans
les fractales, une des choses les plus difficile c'est
le choix des couleurs. On a un parametre, il a plus qu'a
definir une fonction de coloriage.
Pour calculer ce parametre, il nous faut un "maxIter",
qui definit les points de l'ensemble de Mandelbrot :
en mathematique c'est tres simple : l'iteration
est infinie, mais en informatique il nous faut une borne.
Donc on ne trace qu'une approximation de l'ensemble.
La fonction de coloriage est toujours une sinusoide
tu parametres : il y a apres pour chaque composante RGB
trois parametres : pulsation (w) dephasage (phi) et
l'amplitude (A) : composante = A*(sin(w.ITER+phi)
avec ITER comme definit plus haut.

L'inconveniant de l'iteration, c'est que c'est un paremtres
discret, et non continue, ce qui serait mieux pour le coloriage.
Pour cela on peut calculer le potentiel de Douady-Hubbard.
Je vais l'introduire de facon tres tres simple :
P[n](Z) c'est en gros du Z^(2^n)) (le terme dominant)
car en elevant au carre on double le degre, donc
elever n fois, car fait multiplier n fois par 2, d'ou
le degre 2^n.
Si on s'interesse au log2 du module, alors il evolue en 2^n
maintenant on s'interesse au log2 du log2 du module, alors
il evolue en n, donc ASYMPTOTIQUEMENT, log2(log2(|P[n](Z)|))
c'est une droite de pente 1 en n : n+V avec V l'ordonne
a l'origine de la droite. Bon alors la c'est fini,
il est montre (merci Douady et Hubbard !) que V etait
justement un potentiel (bon alors c'est pas du tout rigoureux)
mais V est continue, c'est ce qui nous suffit de savoir.
Donc en calculant V=log2(log2(|P[n](Z)|)) - n
on a un parametre de coloriage en plus.
Cependant il est tres lie a l'iteration, c'est en fait
"l'extension continue" de l'iteration

Definition maintenant l'angle : c'est l'argument
(enfin soyons ici rigoureux : 'un' argument) du complexe
P(Z)/P'(Z), alors notons ici un probleme numerique :
P(Z) est relativement gentil avant de diverder (sans blague ! :))
mais le probleme vient de P'(Z), il y a un coefficient 2^n devant
donc pour le calculer pour des zooms tres grands (i.e. iteration grande)
ca peut poser des problemes...
Ce coloriage en fonction de cette angle donne un effet de relief.
(attention ici pour les pulsations, il faut qu'elles soient ENTIERE car
sinon il y aura des problemes de raccordements, alors que si c'est des
entiers sin(w.ANGLE) sera contine !

Le dernier parametre est ce que j'ai appele l'attracteur (c'est pas moi
qui l'est inventer, mais je ne connais pas son nom...).
Il est interessant de s'interresant aux racines des polynomes
successifs (P[0] P[1] P[2] ...), car la grosse figure noire du debut
se repete partout dans le plan mais en plus petite (d'ou le nom de
fractale d'ailleurs...), car a ces zeros la (les racines) correspondent
aux figures noires comme au debut. Et plus le degres du polynome est grand
plus les figures sont petites, mais plus elles sont nombreuses car
il y en a 2^n.
Donc pour un nombre complex Z, il utile de s'interesser a quel polyome
on annule "le plus", en gros on regarde l'indice du plus petit terme
dans la suite en module.
En gros au debut tout les points s'annule le plus le premier polynome
que les suivants, donc ATTRACTEUR=1, mais ensuite au voisinage des petites
figures, on annule plus le polynome dont la racine de la petite figure
correspond a ce polynome. Bon c'est pour cela que ca forme en gros des
cercles centres sur les petites figures.

Bon je donne seulement le code de calcul des differents parametres :

Source / Exemple :


//-------------------------------------------------
void computingM(P_COLOR_M c,P_PIXEL pixel,P_COMPLEX p)
{
double    re,im,a,b,aPrime,bPrime;
double    _a,_b,_aPrime,_bPrime;
U32       nbIter,maxIter,iMinModule2;
double    minModule2;

nbIter  = 0;
maxIter = c->nbIterMax;

a = re      = p->re;
b = im      = p->im;
aPrime      = 0;
bPrime      = 0;
minModule2  = a*a + b*b;
iMinModule2 = 0;

do
  {
  double r2;
  // P(z)^2 + Z
  _a      = a*a - b*b + re;
  _b      = 2.*a*b + im;
  // 2.P'(Z).P(Z) + 1
  _aPrime = 2.*(a*aPrime-b*bPrime) + 1.;
  _bPrime = 2.*(a*bPrime+b*aPrime);

  a      = _a;
  b      = _b;
  aPrime = _aPrime;
  bPrime = _bPrime;
  nbIter ++;

  r2 = a*a + b*b;
  if(minModule2 > r2)
    {
    minModule2  = r2;
    iMinModule2 = nbIter;
    }

  }while((nbIter < maxIter) && (a*a + b*b < 4.));

if(nbIter < maxIter)
  {
  U32     k,n;         //                   _
  double  reDiv,imDiv; // P(Z)/P'(Z) = P(Z).P'(Z)/|P'(Z)|² , on oublie le <module2> car pour l'angle c'est pas utile
  //double  module2;

  n = 5;// ca commence a diverger, faisons-le diverger un peu plus (5 fois)
// pour pouvoir etre sur la droite n+V
  for(k=0;k<n;k++)
    {
    // P(z)^2 + Z
    _a      = a*a - b*b + re;
    _b      = 2.*a*b + im;
    // 2.P'(Z).P(Z) + 1
    _aPrime = 2.*(a*aPrime-b*bPrime) + 1.;
    _bPrime = 2.*(a*bPrime+b*aPrime);

    a      = _a;
    b      = _b;
    aPrime = _aPrime;
    bPrime = _bPrime;
    }

  //module2 = aPrime*aPrime + bPrime*bPrime;
  reDiv   = a*aPrime+b*bPrime;
  imDiv   = a*bPrime-b*aPrime;

  pixel->nbIter = nbIter;
  pixel->attrac = iMinModule2;
  pixel->V      = -(float)(log(0.5*log(a*a + b*b)/log(2))/log(2) - nbIter - n);
  pixel->A      = (float)atan2(imDiv,reDiv);
  }
else
  {
  pixel->nbIter = (U32)(-1);
  }
} // computingM()

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.