-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMandelBrot.cpp
More file actions
152 lines (119 loc) · 4.82 KB
/
Copy pathMandelBrot.cpp
File metadata and controls
152 lines (119 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include "../headers/MandelBrot.h"
// Construeur: on utilise celui de la classe parent
MandelBrot::MandelBrot(int h, int w) : ImagePNG::ImagePNG(h,w) {
// pour la plage des données on défini des valeurs par défaut
startx=-2.01;
endx=0.7;
starty=-1.2;
endy=1.2;
}
// Réglage de la zone qu'on veut dessiner
int MandelBrot::set_zoom(double sx, double ex, double sy, double ey){
startx = sx;
endx = ex;
starty = sy;
endy = ey;
// >= car on veut une zone de dessin non vide !
if((startx >= endx) || (starty >= endy)){
std::cout << "Mauvaises plages de données.\n";
std::cout << "Échec du dessin" << std::endl;
return 1; // sortie d'echec (utile pour ctest)
}
return 0;
}
// Fonction qui renvoie en sortie le nombre d'itérations pour que le complexe donné diverge
int MandelBrot::iter_mandel(const std::complex<double> c){
// Variables
int cmpt = 0;
std::complex<double> z(0,0);
// Boucle d'itération principale
while((std::abs(z) < 2.0) && (cmpt < MAX_ITER)){
// Fonction du Mandelbrot par défaut
z = z*z + c; // z = z^2 + c
++cmpt;
}
return cmpt;
}
// Fonction qui associe une couleur au degrée de divergence calculé
void MandelBrot::color_mandel(int x, int y, int degree, unsigned char color_selector(int rgb, int d)){
// On associe une couleur au degree
unsigned char r, g, b; //teinte=0; // Attention format RVBA (rouge, vert, bleu, alpha) !
if(degree == MAX_ITER){ // couleur noire OK
r = (unsigned char)(0);
g = (unsigned char)(0);
b = (unsigned char)(0);
}else{
r = color_selector(0,degree);
g = color_selector(1,degree);
b = color_selector(2,degree);
}
//std::cout << "x:" << x << ",y:" << y << " => " << degree << "\n"; // debug line
// On sauvegarde la couleur obtenue
image_px->at(y).at(x*4) = r;
image_px->at(y).at(x*4 + 1) = g;
image_px->at(y).at(x*4 + 2) = b;
image_px->at(y).at(x*4 + 3) = 255; // degre d'opacité maximal
}
// Fonction qui modifie le double vecteur de l'image pour obtenir le dessin du Mandelbrot
void MandelBrot::draw_mandel(){
// on calcule le pas avec lequel on doit itérer
double pas_x = fabs(endx - startx) / width;
double pas_y = fabs(endy - starty) / height;
// on defini les varaibles avec lequelles on calcule
std::complex<double> c;
int x, y;
// Double-boucle principale
for(y=0; y<height; y++){
for(x=0; x<width; x++){
// on identifie le complexe c associé au point x;y
c = std::complex<double>(startx + pas_x * x, starty + pas_y * y);
// On colorie selon le niveau de divergence et la fonction rentrée en paramétre en dernier !
color_mandel(x,y,iter_mandel(c), experience);
}
}
}
// Méthode pour faire plusieures images d'un seul appel
void MandelBrot::run(int const& n){
// Variables
std::string filename = "mz";
double sx, ex, sy, ey;
// on fixe un point de depart
const double orgzx=0.2509784563981121, orgzy=-0.00004652030450813527;
// et un zoom de départ (on tient compte ici du format de l'image: 4:3)
//sx = orgzx - (0.5 * width/height);
sx = 0.25097845639782700999376174877397716045379638671875;
//ex = orgzx + (0.5 * width/height);
ex = 0.25097845639839722053920922917313873767852783203125;
//sy = orgzy - 0.5;
sy = -4.6520304721948746e-05;
//ey = orgzy + 0.5;
ey = -4.652030429432179e-05;
// de combien on zoom pour chaque itération
double zoom = 0.25;
#ifndef NDEBUG
std::cout << "Itération\tPlage de données (en xmin,ymin - xmax,ymax)\tZoom = " << zoom << "\n";
#endif
// Boucle principale
for(int i=0; i<n; ++i){
// Debug output
#ifndef NDEBUG
std::cout << i << "\t\t" << "[" << printf("%.75f",sx) << ";" << std::format("{}",sy)
<< "] -> [" << printf("%.75f",ex) << ";" << std::format("{}",ey) << "]\n";
#endif
// test sur les plages des données !
if(!set_zoom(sx,ex,sy,ey)){
draw_mandel();
crea_png((filename + std::to_string(100+i)).c_str());
}else{
std::cout << "Erreur dans le zoom\n";
break;
}
// on redefini le zoom
/* Ici on regle le zoom par rapport à l'image precedente. On utilise fabs() pour avoir la distance entre
l'origine du zoom et les bors de l'image et on reduit cette distance de zoom fois. Avec zoom < 1 ! */
sx += fabs(orgzx - sx) * zoom;
ex -= fabs(orgzx - ex) * zoom;
sy += fabs(orgzy - sy) * zoom;
ey -= fabs(orgzy - ey) * zoom;
}
}