1 ------------------------------------------------------------------------------------------------
2 -- Nom : Power_Calculator / fait partie du programme Power Fractal --
4 -- Auteurs : Gregory Burri & Adrien Crivelli --
5 ------------------------------------------------------------------------------------------------
6 -- But : Outils de calculs des fractals ainsi que de l'antialiasing --
7 ------------------------------------------------------------------------------------------------
9 with Ada
.Numerics
; use Ada
.Numerics
;
10 with Ada
.Numerics
.Generic_Elementary_Functions
; --Fonctions mathematiques avancees
11 with Ada
.Numerics
.Generic_Complex_Types
;
14 package body Power_Calculator
is
16 ------------------------------------------------------------------------------------------------
17 -- Nom : Calcul_Antialiasing --
18 -- But : Contracter une matrice en une autre 4 fois plus petite --
20 -- Parametres ----------------------------------------------------------------------------------
21 -- In : La matrice a antialiasinger --
23 -- return : La matrice traitee --
24 ------------------------------------------------------------------------------------------------
25 function Calcul_Antialiasing(Matrice_Antialiasing
: T_Matrice_Tampon
) return T_Matrice_Tampon
is
27 X
, Y
: Natural; --Variables pour le parcours de la matrice
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
35 --Parcours toutes les colonnes impaires
36 while X
<= Matrice_Antialiasing
'Last(1) - 1 loop
38 --Parcours toutes les lignes impaires
39 while Y
<= Matrice_Antialiasing
'Last(2) - 1 loop
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
))
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
))
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
))
65 return Matrice_Retour
; --retourne la matrice quatre fois plus petite
69 ------------------------------------------------------------------------------------------------
70 -- Nom : Change_Angle --
71 -- But : Changer l'angle d'un nombre complexe par rapport au centre de l'ecran --
73 -- Parametres ----------------------------------------------------------------------------------
74 -- In : * La fractal, --
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
81 Rayon
: Long_Float; --Le rayon du nombre complexe
82 Phi
: Long_Float; --Le nouvel angle calcule
84 --L'angle en parametre est converti en radian
85 Angle_Rad
: Long_Float := Pi
* Fractal
.Angle
/ 180.0;
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
;
94 --Ramene l'origine du nombre complexe au centre de l'ecran
95 A
:= A
- Fractal
.Centre
.X
;
96 B
:= B
- Fractal
.Centre
.Y
;
98 --Pour eviter la division par zero
101 --Si 'A' est negatif => (l'angle est compris entre : 90 < angle < -90)
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
;
106 Phi
:= Arctan( B
/ A
) + Angle_Rad
;
112 --si l'angle est compris entre : 180 < angle < 360 alors
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
;
117 Phi
:= Pi
/ 2.0 + Angle_Rad
;
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
127 --Ramene l'origine du nombre comples au centre (0,0)
128 A
:= A
+ Fractal
.Centre
.X
;
129 B
:= B
+ Fractal
.Centre
.Y
;
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 --
143 -- return : * Une matrice contenant la fractal sous forme de nombre d'iteration pour chaque --
145 ------------------------------------------------------------------------------------------------
146 function Mandel_Gen (Largeur_Zone
, Hauteur_Zone
: Natural; Fractal
: Cara_Fractal
)
147 return T_Matrice_Iteration
is
149 ------Nombre complexe : Z = A + Bj------
151 package Complex_Long_Float
is new Ada
.Numerics
.Generic_Complex_Types(Long_Float);
152 use Complex_Long_Float
;
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)
164 Nb_Iteration
: Float; --Pour compter le nombre d'iteration
166 --La matrice est cree et retournee
167 Matrice_Retour
: T_Matrice_Iteration (0..Largeur_Zone
, 0..Hauteur_Zone
);
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
);
173 --Variable precalculee pour ne pas avoir a la calculer a chaque iteration
174 Pre_Calcul
: Long_Float;
178 Pre_Calcul
:= (2.0 * Largeur_Zone_Tmp_Float
) * Fractal
.Zoom
;
180 --Parcours toute la dimension X de l'affichage (pixel)
181 for X
in 0..Largeur_Zone
loop
183 --Parcours toute la dimension Y de l'affichage (pixel)
184 for Y
in 0..Hauteur_Zone
loop
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
;
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
;
195 Change_Angle(Ao
, Bo
, Fractal
);
197 Zo
:= Compose_From_Cartesian(Ao
, Bo
);
200 Nb_Iteration
:= 0.0; --Initialise le compteur d'iteration a 0
203 --Boucle calculant la divergence d'un point du plan
207 Pas
:= Zs
/Long_Float(N
) - Za
/Long_Float(N
);
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
);
221 --Za := Zs; --a enlever
222 exit when Nb_Iteration
>= Float(Fractal
.Nb_Iteration_Max
);
226 --Enregistre le point calcule dans la matrice d'iteration (Global)
227 Matrice_Retour(X
,Y
) := Nb_Iteration
;
228 --Put(Float'Image(Nb_Iteration));
233 for I
in Matrice_Retour
'range(1) loop
235 Put_Line(Float'Image(Matrice_Retour(I
,0)));
240 return Matrice_Retour
; --Retourne la matrice
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 --
252 -- return : * Une matrice contenant la fractal sous forme de nombre d'iteration pour chaque --
254 ------------------------------------------------------------------------------------------------
255 function Julia_Gen (Largeur_Zone
, Hauteur_Zone
: Natural; Fractal
: Cara_Fractal
)
256 return T_Matrice_Iteration
is
259 ------Nombre complexe : Z = A + Bj------
261 package Complex_Long_Float
is new Ada
.Numerics
.Generic_Complex_Types(Long_Float);
262 use Complex_Long_Float
;
268 C
: Complex
:= Compose_From_Cartesian (Fractal
.Cx
, Fractal
.Cy
);
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)
274 Nb_Iteration
: Float; --Pour compter le nombre d'iteration
276 --La matrice est cree et retournee
277 Matrice_Retour
: T_Matrice_Iteration (0..Largeur_Zone
, 0..Hauteur_Zone
);
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
);
283 --Variable precalculee pour ne pas avoir a la calculer a chaque iteration
284 Pre_Calcul
: Long_Float;
288 Pre_Calcul
:= (2.0 * Largeur_Zone_Tmp_Float
) * Fractal
.Zoom
;
290 --Parcours toute la dimension X de l'affichage (pixel)
291 for X
in 0..Largeur_Zone
loop
293 --Parcours toute la dimension Y de l'affichage (pixel)
294 for Y
in 0..Hauteur_Zone
loop
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
;
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
;
305 Change_Angle(Ao
, Bo
, Fractal
);
307 Za
:= Compose_From_Cartesian(Ao
, Bo
);
309 Nb_Iteration
:= 0.0; --Initialise le compteur d'iteration a 0
312 --Boucle calculant la divergence d'un point du plan
316 Pas
:= Zs
/Long_Float(N
) - Za
/Long_Float(N
);
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
);
332 Za
:= Zs
; --a enlever
333 exit when Nb_Iteration
>= Float(Fractal
.Nb_Iteration_Max
);
337 --Enregistre le point calcule dans la matrice d'iteration (Global)
338 Matrice_Retour(X
,Y
) := Nb_Iteration
;
339 --Put(Float'Image(Nb_Iteration));
343 --Put(Float'Image(Matrice_Retour(0,0)));
344 return Matrice_Retour
; --Retourne la matrice
346 end Power_Calculator
;