Premier commit
[powerfractal.git] / CD / Src / Power_calculator.adb
1 ------------------------------------------------------------------------------------------------
2 -- Nom : Power_Calculator / fait partie du programme Power Fractal --
3 -- --
4 -- Auteurs : Gregory Burri & Adrien Crivelli --
5 ------------------------------------------------------------------------------------------------
6 -- But : Outils de calculs des fractals ainsi que de l'antialiasing --
7 ------------------------------------------------------------------------------------------------
8
9 with Ada.Numerics; use Ada.Numerics;
10 with Ada.Numerics.Generic_Elementary_Functions; --Fonctions mathematiques avancees
11
12 package body Power_Calculator is
13
14 ------------------------------------------------------------------------------------------------
15 -- Nom : Calcul_Antialiasing --
16 -- But : Contracter une matrice en une autre 4 fois plus petite --
17 -- --
18 -- Parametres ----------------------------------------------------------------------------------
19 -- In : La matrice a antialiasinger --
20 -- --
21 -- return : La matrice traitee --
22 ------------------------------------------------------------------------------------------------
23 function Calcul_Antialiasing(Matrice_Antialiasing : T_Matrice_Tampon) return T_Matrice_Tampon is
24
25 X, Y : Natural; --Variables pour le parcours de la matrice
26
27 --La matrice de retour, qui est evidement 2 fois plus petite que celle en entrer
28 Matrice_Retour : T_Matrice_Tampon ( 0..(Matrice_Antialiasing'Last(1) - 1) / 2,
29 0..(Matrice_Antialiasing'Last(2) - 1) / 2 );
30 begin --Calcul_Antialiasing
31
32 X := 0;
33 --Parcours toutes les colonnes impaires
34 while X <= Matrice_Antialiasing'Last(1) - 1 loop
35 Y:=0;
36 --Parcours toutes les lignes impaires
37 while Y <= Matrice_Antialiasing'Last(2) - 1 loop
38
39 --Fait la moyenne de quatre points pour n'en former qu'un seul
40 Matrice_Retour(X/2, Y/2).R := Byte ((Integer(Matrice_Antialiasing(X, Y).R)
41 + Integer(Matrice_Antialiasing(X + 1,Y).R)
42 + Integer(Matrice_Antialiasing(X, Y + 1).R)
43 + Integer(Matrice_Antialiasing(X + 1, Y + 1).R))
44 / 4);
45
46 Matrice_Retour(X/2, Y/2).G := Byte ((Integer(Matrice_Antialiasing(X, Y).G)
47 + Integer(Matrice_Antialiasing(X + 1,Y).G)
48 + Integer(Matrice_Antialiasing(X,Y + 1).G)
49 + Integer(Matrice_Antialiasing(X + 1, Y + 1).G))
50 / 4);
51
52 Matrice_Retour(X/2, Y/2).B := Byte ((Integer(Matrice_Antialiasing(X, Y).B)
53 + Integer(Matrice_Antialiasing(X + 1,Y).B)
54 + Integer(Matrice_Antialiasing(X, Y + 1).B)
55 + Integer(Matrice_Antialiasing(X + 1, Y + 1).B))
56 / 4);
57 Y:=Y+2;
58 end loop;
59
60 X:=X+2;
61 end loop;
62
63 return Matrice_Retour; --retourne la matrice quatre fois plus petite
64 end;
65
66
67 ------------------------------------------------------------------------------------------------
68 -- Nom : Change_Angle --
69 -- But : Changer l'angle d'un nombre complexe par rapport au centre de l'ecran --
70 -- --
71 -- Parametres ----------------------------------------------------------------------------------
72 -- In : * La fractal, --
73 -- --
74 -- In out : * Partie reel du nb complexe : A --
75 -- * Partie imaginaire du nb complexe : B --
76 ------------------------------------------------------------------------------------------------
77 procedure Change_Angle (A, B : in out Long_Float; Fractal : Cara_Fractal) is
78
79 Rayon : Long_Float; --Le rayon du nombre complexe
80 Phi : Long_Float; --Le nouvel angle calcule
81
82 --L'angle en parametre est converti en radian
83 Angle_Rad : Long_Float := Pi * Fractal.Angle / 180.0;
84
85 --Pour pouvoir faire des operations (sin cos etc..) sur des Long_Float
86 package Elementary_Functions_Long_Float
87 is new Ada.Numerics.Generic_Elementary_Functions (Long_Float);
88 use Elementary_Functions_Long_Float;
89
90 begin
91
92 --Ramene l'origine du nombre complexe au centre de l'ecran
93 A := A - Fractal.Centre.X;
94 B := B - Fractal.Centre.Y;
95 --
96 --Pour eviter la division par zero
97 if A /= 0.0 then
98
99 --Si 'A' est negatif => (l'angle est compris entre : 90 < angle < -90)
100 if A < 0.0 then
101 --Calcul de l'angle en additionnant a l'angle de base l'angle que l'on veut
102 Phi := Arctan( B / A ) + Angle_Rad + Pi;
103 else
104 Phi := Arctan( B / A ) + Angle_Rad;
105 --
106 end if;
107
108 else
109
110 --si l'angle est compris entre : 180 < angle < 360 alors
111 if B < 0.0 then
112 --Calcul de l'angle en additionnant a Pi/2.0 l'angle que l'on veut
113 Phi := Pi / 2.0 + Angle_Rad + Pi;
114 else
115 Phi := Pi / 2.0 + Angle_Rad;
116 --
117 end if;
118
119 end if;
120
121 Rayon := Sqrt( A**2 + B**2 ); --Calcul le rayon (module)
122 A := Rayon * Cos( Phi ); --Calcul la partie reel
123 B := Rayon * Sin( Phi ); --Calcul la partie imaginaire
124
125 --Ramene l'origine du nombre comples au centre (0,0)
126 A := A + Fractal.Centre.X;
127 B := B + Fractal.Centre.Y;
128 --
129
130 end Change_Angle;
131
132
133 ------------------------------------------------------------------------------------------------
134 -- Nom : Mandel_Gen --
135 -- But : Genere une matrice d'iteration selon l' ensemble de Mandelbrot --
136 -- Z(n+1) = Z(n)^2 + Z(o) --
137 -- Parametres ----------------------------------------------------------------------------------
138 -- In : * Largeur_Zone et Hauteur_Zone : Dimension de la zone de calcul --
139 -- * Fractal : L'ensemble des caracteristiques de la fractal --
140 -- --
141 -- return : * Une matrice contenant la fractal sous forme de nombre d'iteration pour chaque --
142 -- point --
143 ------------------------------------------------------------------------------------------------
144 function Mandel_Gen (Largeur_Zone, Hauteur_Zone : Natural; Fractal : Cara_Fractal)
145 return T_Matrice_Iteration is
146
147 ------Nombre complexe : Z = A + Bj------
148
149 A,B, -- La valeur reel et imaginaire courante lors du calcul Z en fonction de n : Z(n)
150 Ao,Bo,-- la valeur reel et imaginaire du point en cours de traitement : Z(o)
151
152 Temp : Long_Float; --Une variable temporaire
153
154 Nb_Iteration : Natural; --Pour compter le nombre d'iteration
155
156 --La matrice est cree et retournee
157 Matrice_Retour : T_Matrice_Iteration (0..Largeur_Zone, 0..Hauteur_Zone);
158
159 --la hauteur et la largeur en long float
160 Largeur_Zone_Tmp_Float : Long_Float := Long_Float(Largeur_Zone);
161 Hauteur_Zone_Tmp_Float : Long_Float := Long_Float(Hauteur_Zone);
162
163 --Variable precalculee pour ne pas avoir a la calculer a chaque iteration
164 Pre_Calcul : Long_Float;
165
166 begin -- Mandel_Gen
167
168 Pre_Calcul := (2.0 * Largeur_Zone_Tmp_Float) * Fractal.Zoom;
169
170 --Parcours toute la dimension X de l'affichage (pixel)
171 for X in 0..Largeur_Zone loop
172
173 --Parcours toute la dimension Y de l'affichage (pixel)
174 for Y in 0..Hauteur_Zone loop
175
176 --Convertie la valeur x du point a l'ecran(pixel) en valeur reel sur la fractal
177 --Voir la doc pour plus d'informations
178 Ao := ((Long_Float(X) / Largeur_Zone_Tmp_Float) - 0.5 ) /
179 Fractal.Zoom + Fractal.Centre.X ;
180
181 --Convertie la valeur y du point a l'ecran(pixel) en valeur reel sur la fractal
182 --Voir la doc pour plus d'informations
183 Bo := (-2.0 * Long_Float(Y) + Hauteur_Zone_Tmp_Float) / Pre_Calcul + Fractal.Centre.Y;
184
185 Change_Angle(Ao, Bo, Fractal);
186
187 Nb_Iteration := 0; --Initialise le compteur d'iteration a 0
188
189 --initialise le nombre complexe avec Z(o)
190 A:=Ao;
191 B:=Bo;
192 --
193
194 --Boucle calculant la divergence d'un point du plan
195 loop
196
197 --Calcul effectue sur le nombre complexe : Z(n+1) = Z(n)^2 + Z(o)
198 --Nos variables A + Bj = (A + Bj)^2 + (Ao + Boj)
199 Temp := A**2 - B**2 + Ao;
200 B := 2.0 * A * B + Bo;
201 A := Temp;
202 --
203
204 --Le compteur d'iteration est incemente
205 Nb_Iteration := Integer'Succ(Nb_Iteration);
206
207 --Sort si le nombre maximale d'iteration a ete atteind
208 --ou si le module du nb complexe a dapasse la limite de divergence.
209 --Astuce : la limite represente en fait le carre du module,
210 --ce qui permet de faire moins de calculs
211 exit when Nb_Iteration = Fractal.NB_Iteration_Max or else (A**2 + B**2)
212 > Fractal.C_Diverge_Limite ;
213 end loop;
214
215 --Enregistre le point calcule dans la matrice d'iteration (Global)
216 Matrice_Retour(X,Y) := Nb_Iteration;
217
218 end loop;
219 end loop;
220
221 return Matrice_Retour; --Retourne la matrice
222
223 end Mandel_Gen;
224
225 ------------------------------------------------------------------------------------------------
226 -- Nom : Julia_Gen --
227 -- But : Genere une matrice d'iteration selon l' ensemble de Julia --
228 -- Z(n+1) = Z(n)^2 + c 'c' etant une constante arbitraire --
229 -- Parametres ----------------------------------------------------------------------------------
230 -- In : * Largeur_zone et Hauteur_Zone : Dimension de la zone de calcul --
231 -- * Fractal : L'ensemble des caracteristiques de la fractal --
232 -- --
233 -- return : * Une matrice contenant la fractal sous forme de nombre d'iteration pour chaque --
234 -- point --
235 ------------------------------------------------------------------------------------------------
236 function Julia_Gen (Largeur_Zone, Hauteur_Zone : Natural; Fractal : Cara_Fractal)
237 return T_Matrice_Iteration is
238
239 A, B, -- La valeur reel et imaginaire courante lors du calcul Z en fonction de n : Z(n)
240
241 Temp : Long_Float; --Une variable temporaire
242
243 Nb_Iteration : Natural; --Pour compter le nombre d'iteration
244
245 --La matrice est cree et retournee
246 Matrice_Retour : T_Matrice_Iteration (0..Largeur_Zone, 0..Hauteur_Zone);
247
248 --la hauteur et la largeur en long float
249 Largeur_Zone_Tmp_Float : Long_Float := Long_Float(Largeur_Zone);
250 Hauteur_Zone_Tmp_Float : Long_Float := Long_Float(Hauteur_Zone);
251
252 --Variable precalculee pour ne pas avoir a la calculer a chaque iteration
253 Pre_Calcul : Long_Float;
254
255 begin -- Julia_Gen
256
257 Pre_Calcul := (2.0 * Largeur_Zone_Tmp_Float) * Fractal.Zoom;
258
259 --Parcours toute la dimension X de l'affichage (pixel)
260 for X in 0..Largeur_Zone loop
261
262 --Parcours toute la dimension Y de l'affichage (pixel)
263 for Y in 0..Hauteur_Zone loop
264
265 --Convertie la valeur X du point a l'ecran(pixel) en valeur reel sur la fractal
266 --Voir la doc pour plus d'informations
267 A := ( (Long_Float(X) / Largeur_Zone_Tmp_Float) - 0.5 ) /
268 Fractal.Zoom + Fractal.Centre.X ;
269
270 --Convertie la valeur Y du point a l'ecran(pixel) en valeur reel sur la fractal
271 --Voir la doc pour plus d'informations
272 B := ( -2.0 * Long_Float(Y) + Hauteur_Zone_Tmp_Float) / Pre_Calcul + Fractal.Centre.Y;
273
274 Change_Angle(A, B, Fractal); --Change l'angle de la fractal
275
276 Nb_Iteration := 0; --Initialise le compteur d'iteration a 0
277
278 --Boucle calculant la divergence d'un point du plan
279 loop
280
281 --Calcul effectue sur le nombre complexe : Z(n+1) = Z(n)^2 + c
282 --Nos variables A + Bj = (A + Bj)^2 + (c.x + c.yj)
283 Temp := A**2 - B**2 + Fractal.Cx;
284 B := 2.0 * A * B + Fractal.Cy;
285 A := Temp;
286 --
287
288 --Le compteur d'iteration est incemente
289 Nb_Iteration := Integer'Succ(Nb_Iteration);
290
291 --Sort si le nombre maximale d'iteration a ete atteind
292 --ou si le module du nb complexe a dapasse la limite de divergence.
293 --Astuce : la limite represente en fait le carre du module,
294 --ce qui permet de faire moins de calculs
295 exit when Nb_Iteration = Fractal.NB_Iteration_Max or else (A**2 + B**2)
296 > Fractal.C_Diverge_Limite ;
297
298 end loop;
299
300 --Enregistre le point calcule dans la matrice d'iteration (Global)
301 Matrice_Retour(X,Y) := Nb_Iteration;
302
303 end loop;
304 end loop;
305
306 return Matrice_Retour;--Retourne la matrice
307
308 end Julia_Gen;
309 end Power_Calculator;