Documente Academic
Documente Profesional
Documente Cultură
Iulia Comşa
Clasa a XII-a C
Profesor îndrumător: Laura Niţulescu
2008
1. Motivarea alegerii temei. Utilitatea aplicaţiei.
„De ce este geometria considerată „rece” şi „seacă”? Unul dintre motive constă în
incapacitatea ei de a descrie forma unui nor, a unui munte, a unui ţărm sau a unui copac.
Copacii nu sunt sfere, munţii nu sunt conuri, ţărmurile nu sunt cercuri, coroanele arborilor
nu sunt netede şi nici fulgerele nu călătoresc în linie dreaptă..”
Astfel îşi începea Benoît Mandelbrot lucrarea „Geometria Fractală a Naturii” (1975),
subliniind necesitatea unei noi abordări matematice a studierii formelor şi mişcărilor din
natură şi din univers. Scopul lui era acela de a pune bazele unei teorii care să studieze
modelele neregulate şi fragmentate. Pentru aceasta, a definit o „familie de forme” numite
„fractali”.
Termenul ”fractal” provine din limba latină, „fractus” însemnând „spart”, „fracturat”.
Caracteristicile fractalilor sunt, în general, următoarele:
structura fină la orice scară;
regăsirea, la scară mai mică, a modelului privit de la scară mare (autosimilitudine);
definiţia simplă, recursivă, ce dă naştere la forme prea complexe pentru a putea fi
descrise în detaliu cu ajutorul geometriei euclidiene.
Mandelbrot a folosit geometria fractală atât în topologie, descriind suprefeţe neregulate (de
exemplu, coasta de ţărm a Marii Britanii), cât şi în astronomie, prezentând dispoziţia roiurilor
de stele în univers. Fractalii cu cea mai mare aplicabilitate folosiţi de el se bazează pe hazard,
regularităţile şi iregularităţile lor fiind statistice.
Cu toate că doar cei iniţiaţi în detalii matematice pot lucra în mod practic cu fractali,
frumuseţea, simetria şi perfecţiunea matematică a acestora este fascinantă pentru publicul
larg. Am ales fractalii ca temă pentru lucrarea de atestat în primul rând pentru a înţelege baza
matematică a frumuseţii celebrei imagini a fractalului Mandelbrot şi a altor fractali, dar şi
pentru a mă obişnui cu generarea graficii în Visual C++, partea vizuală fiind foarte
importantă – uneori chiar definitorie pentru o aplicaţie – în programare. De asemenea, este o
ocazie de a populariza fractalii, ca pe manifestari ale artei matematice.
Aplicaţia construieşte fractali generaţi prin metoda Divide-et-Impera şi mulţimi de tip
Mandelbrot şi Julia, dând utilizatorului posibilitatea de a seta anumiţi paramentri ai funcţiilor
de calcul al poziţiei/culorii punctelor. Având în vedere numărul infinit de fractali ce pot fi
creaţi şi complexitatea acestora, acest program are ca scop ilustrarea tipurilor de bază de
fractali şi deschiderea orizontului utilizatorului pentru fractali mai complecşi.
Am încercat realizarea unei interfeţe cât mai plăcute şi uşor de folosit din punctul de vedere
al utilizatorului şi sper că am reuşit acest lucru.
Aplicaţia este centrată pe meniul principal, ce constă într-un form ce conţine informaţii
despre autor şi două butoane, însoţite de etichete ce enumeră tipurile de fractali spre care fac
legatura butoanele. Acestea deschid câte un form ce conţine câte o listă derulantă
(comboBox) ce permite selecţia tipului de fractal, un buton pentru desenarea fractalului şi o
casetă pentru imagine, în care va fi reprezentat fractalul la apăsarea butonului „Desenare”.
Figura 1.2: fractalul de tip Koch triunghiular. Aşezarea a trei braţe în formă de triunghi duce la
celebra formă de fulg de nea.
Figura 1.3: fractalul de tip Koch pătratic. Poate fi folosită în „umplerea” spaţiilor.
Figura 1.4: fractalul de tip Sierpinski. Fiecare triunghi mai mic este copia triunghiului iniţial la
scara mai mică.
O casetă de text îi permite utilizatorului să introducă numărul de iteraţii („încreţituri”, )
folosite în construirea fractalului. Acest număr va defini „adâncimea” fractalului, fiind de
asemenea responsabil de timpul în care acesta va fi desenat.
b) Seturile Julia şi Mandelbrot sunt reprezentări ale punctelor dintr-un planul numerelor
complexe cu proprietatea că şirul xn+1= xn2+C este mărginit.
Pentru fractalii de tip iterativ, este posibilă mărirea unei porţiuni din imagine. Selecţia
porţiunii dorite se face cu mouse-ul. Raportul dintre lungimea şi lăţimea ariei selectate va fi
constrâns la raportul dintre lungimea şi lăţimea casetei imaginii, pentru a evita „tăierea”
ulterioară a unei porţiuni din selecţie e ce nu va „încăpea” în casetă. La eliberarea mouse-ului,
în cazul în care selecţia are o arie mai mare decât 0, utilizatorul este întrebat, printr-un mesaj,
dacă doreşte să mărească zona selectată. În cazul unui răspuns pozitiv, aria selectată este
desenată în caseta de imagine. În noul desen, utilizatorul poate mări din nou orice porţiune
dorită, respectând raportul dintre lungime şi lăţime. Pentru a desena din nou fractalul iniţial,
se va apăsa pe butonul „Desenare”.
Dorind să aleg o paletă de culori cât mai frumoasă şi experimentând în acest sens, am găsit o
serie de seturi cromatice ce pot fi utilizate în desenarea fractalilor Mandelbrot şi Julia.
Neputând să aleg una singură, deoacere fiecare era frumoasă în felul ei, am adăugat un buton
ce pemite schimbarea culorii. Seturile cromatice se schimbă ciclic.
La apăsarea unuia dintre cele două butoane de pe formul principal, se creează o nouă
instanţă a formului corespunzător (am numit cele două formuri „sierpinsky.h” şi
„mandelbrot.h”, după numele unuia dintre fractali):
“ShowDialog()” asigură dezactivarea meniului principal atâta timp cât formul al doilea este
deschis, prevenind astfel deschiderea mai multor ferestre de acelaşi tip.
a) Fractalii de tip Divide-et-Impera sunt construiţi, după cum sugerează numele, prin
„spargerea” componentei principale în mai multe părţi şi aplicarea „spargerii” asupra
componentelor mai „mici” rezultate, până când se ajunge la cazul (componenta) de bază. La
aceasta se ajunge efectuând un număr de apeluri ale funcţiei recursive egal cu numărul
introdus în caseta de text – în cazul în care utilizatorul a introdus un număr natural. În caz
contrar, este afişat un mesaj:
int n;
try
{
n=Convert::ToInt32(textBox1->Text);
}
catch(...)
{
MessageBox::Show("Valoare imposibila.\nVa rugam reveniti cu
numere naturale.", "Mai incercati!");
return;
}
Graphics *g;
g=Graphics::FromImage(b);
g->DrawLine(new Pen(Color::Blue,2),
Point(x0,y0),Point(x1,y1));
g->Dispose();
pictureBox1->Refresh();
arbore(x1,y1,l*4/7,u-Math::PI/4,n-1);
arbore(x1,y1,l*4/7,u+Math::PI/4,n-1);
}
}
Ca şi în cazul arborelui, fractalul Sierpinski este construit prin adăugarea de linii la imaginea
generată până în acel moment, până când nivelul devine mai mic decât n. Se porneşte de la
un triunghi în care au fost desenate liniile mijlocii şi se desenează liniile mijlocii ale
triunghiurilor mai mici marginale formate:
if(n>=0)
{
Graphics *g;
g=Graphics::FromImage(b);
double x2=x1+l/2;
double y2=y1-l*Math::Sqrt(3)/2;
double x3=x1-l/2;
double y3=y2;
g->DrawLine(new Pen(Color::DarkTurquoise,2),
Point(x1,y1),Point(x2,y2));
g->DrawLine(new Pen(Color::DarkTurquoise,2),
Point(x2,y2),Point(x3,y3));
g->DrawLine(new Pen(Color::DarkTurquoise,2),
Point(x3,y3),Point(x1,y1));
g->Dispose();
pictureBox1->Refresh();
triunghi(n-1,x1,y2,l/2);
triunghi(n-1,x2,y1,l/2);
triunghi(n-1,x3,y1,l/2);
}
}
La fractalul de tip Koch triunghiular, coordonatele care ne interesează se află la prima treime,
a doua treime şi jumătatea segmentului. La fiecare dintre acestea, unghiul de desenare se
modifică cu 60o, -120o, respectiv 60o. Iată funcţia:
void koch(int n,double x1,double y1,double l,double u)
{
if(n==0)
{
double x2,y2;
x2=x1+l*Math::Cos(u);
y2=y1-l*Math::Sin(u);
Graphics *g;
g=Graphics::FromImage(b);
g->DrawLine(new Pen(Color::Color::DarkBlue,2),
Point(x1,y1),Point (x2,y2));
g->Dispose();
pictureBox1->Refresh();
else
{
double x2,y2,x3,y3,x4,y4;
x2=x1+(l/3)*Math::Cos(u);
y2=y1-(l/3)*Math::Sin(u);
x4=x1+(2*l/3)*Math::Cos(u);
y4=y1-(2*l/3)*Math::Sin(u);
x3=x2+(l/3)*Math::Cos(u+Math::PI/3);
y3=y2-(l/3)*Math::Sin(u+Math::PI/3);
koch(n-1,x1,y1,l/3,u);
koch(n-1,x2,y2,l/3,u+Math::PI/3);
koch(n-1,x3,y3,l/3,u-Math::PI/3);
koch(n-1,x4,y4,l/3,u);
}
}
Fractalul de tip Koch pătratic este similar cu fractalul Koch triunghiular, cu excepţia faptului
că ne interesează punctele ce marchează un sfert din lungimea segmentului, iar unghiurile se
schimbă cu ±90o:
x2=x0+l*Math::Cos(u);
y2=y0-l*Math::Sin(u);
u+=Math::PI/2;
koch_q(n-1,x2,y2,l,u);
x2+=l*Math::Cos(u);
y2-=l*Math::Sin(u);
u-=Math::PI/2;
koch_q(n-1,x2,y2,l,u);
x2+=l*Math::Cos(u);
y2-=l*Math::Sin(u);
u-=Math::PI/2;
koch_q(n-1,x2,y2,l*2,u);
x2+=l*2*Math::Cos(u);
y2-=l*2*Math::Sin(u);
u+=Math::PI/2;
koch_q(n-1,x2,y2,l,u);
x2+=l*Math::Cos(u);
y2-=l*Math::Sin(u);
u+=Math::PI/2;
koch_q(n-1,x2,y2,l,u);
x2+=l*Math::Cos(u);
y2-=l*Math::Sin(u);
u-=Math::PI/2;
koch_q(n-1,x2,y2,l,u);
}
}
b) Fractalii de tip iterativ (Mandelbrot şi Julia) sunt construiţi prin iteraţii succesive ale
fiecărui punct din planul considerat după formula xn+1= xn2+C.
Fiecărui număr de iteraţii necesar unui punct pentru ca, prin iteraţii succesive, modului său să
scape din intervalul [0,2] îi corespunde o culoare. De acees, numărul maxim de culori trebuie
să fie egal cu numărul maxim de iteraţii efectuate pe un număr pentru a testa limita şirului.
Am notat această constantă cu NMAXC, iniţializată cu 2560. Culoarea neagră corespunde
mulţimii punctelor ce nu ies din intervalul [0,2] după NMAXC iteraţii.
Punctele interesante din setul Mandelbrot se află aproximativ în intervalul [-2,1] pe axa Ox şi
[-1,2] pe Oy. Am reţinut în patru variabile coordonatele din planul complex ce vor mărgini
suprafaţa: xmin=-2.2, xmax=1, ymin=-1.2, ymax=1.2 (astfel încât W/H=(xmax-
xmin)/(ymax-ymin)=3/2, unde H reprezintă înălţimea, iar W – lungimea casetei imaginii).
Parcurgerea casetei de imagine se face cu variabilele xe şi ye, iar variabilele xf şi yf reţin
transformarea coordonatelor xe şi ye în coordonatele corespunzătoare în intervalele
[xmin,xmax] şi [ymax,ymax].
Pentru fiecare punct de coordonate xf şi yf, se efectuează iteraţii atâta timp cât modulul
numărului complex este mai mic decât 2 (pătratul său este mai mic decât 4) sau atâta timp cât
nu am depăşit numărul maxim de iteraţii. La ieşirea din instrucţiunea while, numărul iteraţiei
(reţinut în variabila ic) va da indicele culorii: dacă s-a ieşit din while pentru că numărul de
iteraţii a depăşit numărul maxim de culori, înseamnă că şirul x n nu a scăpat spre infinit, iar
punctul este colorat în negru; altfel, xf a avut nevoie de ic iteraţii pentru a depăşi, în modul,
valoarea 2, prin urmare primeşte culoarea cu indicele ic.
int xe,ye;
double xf,yf,x,y,xnew,ynew,ic;
for(ye=0;ye<H;ye++)
{
for(xe=0;xe<W;xe++)
{
xf=(xmax-xmin)/W*xe+xmin;
yf=(ymin-ymax)/H*ye+ymax;
x=0;y=0;
ic=0;
while(x*x+y*y<4&&ic<=NMAXC)
{
ic++;
xnew=x*x-y*y+xf;
ynew=2*x*y+yf;
x=xnew;y=ynew;
}
if(ic>NMAXC) ic=0;
b->SetPixel(xe,ye,c[ic]);
}
pictureBox1->Refresh();
}
Cazul setului Julia este similar, cu excepţia coordonatelor xmin=-1.6, xmax=1.6, ymin=-1.2,
ymax=1.2 şi a instrucţiunii while, unde xc şi yc sunt coordonatele constantei introduse de
utilizator în casetele numerice (numericUpDowns):
while(x*x+y*y<4&&ic<=NMAXC)
{
ic++;
xnew=x*x-y*y+xc;
ynew=2*x*y+yc;
x=xnew;y=ynew;
}
Valoarile minime şi maxime ce pot fi introduse în casetele numerice sunt -1, respectiv 1. În
afara acestor valori nu apar imagini interesante.
Trebuie avute în vedere toate cazurile de direcţie a selecţiei. Am stabilit ca xsel şi ysel să fie
întotdeauna colţul din dreapa sus ale dreptunghiului ce marchează selecţia, iar xsel1 şi ysel1,
colţul din stânga jos. De asemenea, selecţia este condiţionată de păstrarea raportului dintre
lungimea şi lăţimea selecţiei egal cu raportul dintre lungimea şi lăţimea imaginii.
int x,y,h,w;
x=xsel<xsel1?xsel:xsel1;
y=ysel<ysel1?ysel:ysel1;
double rap=(double)b->Width/b->Height;
w=Math::Abs(xsel-xsel1);
h=Math::Abs(ysel-ysel1);
if(h*w==0)w=h=0;
else if((double)w/h>rap)
w=rap*h;
else
h=w/rap;
if(xsel>xsel1) x=xsel-w;
if(ysel>ysel1) y=ysel-h;
La eliberarea mouse-ului, utilizatorul este întrebat dacă doreşte mărirea zonei selectate. În
cazul unui răspuns afirmativ, coordonatele minime şi maxime sunt recalculate, iar fractalul
este desenat din nou:
double xmin1,xmax1,ymin1,ymax1;
xmin1=(xmax-xmin)*lastx/W+xmin;
xmax1=(xmax-xmin)*(lastx+lastw)/W+xmin;
ymin1=ymax-(ymax-ymin)*(lasty+lasth)/H;
ymax1=ymax-(ymax-ymin)*(lasty)/H;
xmin=xmin1;
xmax=xmax1;
ymin=ymin1;
ymax=ymax1;
Oricât am mări porţiuni din fractal, vom găsi întotdeauna o arie similară fractalului văzut de
la scară mai mare, după cum se observă în imaginile de la pagina alăturată.
Pentru evidenţierea zonelor fractalului într-un mod cât mai plăcut din punct de vedere
estetic, am creat câteva palete de culori. Acestea sunt formate din două sau mai multe culori
în gradaţie, reţinute într-un şir. Fiecărui set şi fiecărei măriri i se potriveşte mai bine o
anumită culoare. Experimentaţi cu ele!
De asemenea, experimentaţi diverse valori ale constantei setului Julia. Câteva dintre cele mai
interesante valori pe care le-am găsit, cu excepţia valorilor aflate iniţial în casetele numerice,
sunt:
-3.8+0.62i 0.19-0.56i
-0.70+0.096i -0.39+0,596i
4. Resurse hardware şi software compatibile
5. Posibilităţi de dezvoltare
Există nenumărate tipuri de fractali; cei prezentaţi prin această aplicaţie sunt doar cei mai
cunoscuţi. Programul ar putea genera şi alte tipuri de fractali construiţi prin Divide-et-
Impera, sau setul Julia şi Mandelbrot pentru şirul definit prin relaţia de recurenţă
xn+1=xnk+1, cu k – un număr natural mai mare decât 1 introdus de utilizator.
http://www.tjhsst.edu/~dhyatt/supercomp/n106.html
http://en.wikipedia.org/wiki/Fractal
http://en.wikipedia.org/wiki/Koch_snowflake
http://en.wikipedia.org/wiki/Sierpinski_triangle
http://en.wikipedia.org/wiki/Mandelbrot_set
http://en.wikipedia.org/wiki/Julia_set