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