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
12 package body Power_Calculator
is
14 ------------------------------------------------------------------------------------------------
15 -- Nom : Calcul_Antialiasing --
16 -- But : Contracter une matrice en une autre 4 fois plus petite --
18 -- Parametres ----------------------------------------------------------------------------------
19 -- In : La matrice a antialiasinger --
21 -- return : La matrice traitee --
22 ------------------------------------------------------------------------------------------------
23 function Calcul_Antialiasing(Matrice_Antialiasing
: T_Matrice_Tampon
) return T_Matrice_Tampon
is
25 X
, Y
: Natural; --Variables pour le parcours de la matrice
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
33 --Parcours toutes les colonnes impaires
34 while X
<= Matrice_Antialiasing
'Last(1) - 1 loop
36 --Parcours toutes les lignes impaires
37 while Y
<= Matrice_Antialiasing
'Last(2) - 1 loop
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
))
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
))
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
))
63 return Matrice_Retour
; --retourne la matrice quatre fois plus petite
67 ------------------------------------------------------------------------------------------------
68 -- Nom : Change_Angle --
69 -- But : Changer l'angle d'un nombre complexe par rapport au centre de l'ecran --
71 -- Parametres ----------------------------------------------------------------------------------
72 -- In : * La fractal, --
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
79 Rayon
: Long_Float; --Le rayon du nombre complexe
80 Phi
: Long_Float; --Le nouvel angle calcule
82 --L'angle en parametre est converti en radian
83 Angle_Rad
: Long_Float := Pi
* Fractal
.Angle
/ 180.0;
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
;
92 --Ramene l'origine du nombre complexe au centre de l'ecran
93 A
:= A
- Fractal
.Centre
.X
;
94 B
:= B
- Fractal
.Centre
.Y
;
96 --Pour eviter la division par zero
99 --Si 'A' est negatif => (l'angle est compris entre : 90 < angle < -90)
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
;
104 Phi
:= Arctan( B
/ A
) + Angle_Rad
;
110 --si l'angle est compris entre : 180 < angle < 360 alors
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
;
115 Phi
:= Pi
/ 2.0 + Angle_Rad
;
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
125 --Ramene l'origine du nombre comples au centre (0,0)
126 A
:= A
+ Fractal
.Centre
.X
;
127 B
:= B
+ Fractal
.Centre
.Y
;
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 --
141 -- return : * Une matrice contenant la fractal sous forme de nombre d'iteration pour chaque --
143 ------------------------------------------------------------------------------------------------
144 function Mandel_Gen (Largeur_Zone
, Hauteur_Zone
: Natural; Fractal
: Cara_Fractal
)
145 return T_Matrice_Iteration
is
147 ------Nombre complexe : Z = A + Bj------
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)
152 Temp
: Long_Float; --Une variable temporaire
154 Nb_Iteration
: Natural; --Pour compter le nombre d'iteration
156 --La matrice est cree et retournee
157 Matrice_Retour
: T_Matrice_Iteration (0..Largeur_Zone
, 0..Hauteur_Zone
);
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
);
163 --Variable precalculee pour ne pas avoir a la calculer a chaque iteration
164 Pre_Calcul
: Long_Float;
168 Pre_Calcul
:= (2.0 * Largeur_Zone_Tmp_Float
) * Fractal
.Zoom
;
170 --Parcours toute la dimension X de l'affichage (pixel)
171 for X
in 0..Largeur_Zone
loop
173 --Parcours toute la dimension Y de l'affichage (pixel)
174 for Y
in 0..Hauteur_Zone
loop
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
;
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
;
185 Change_Angle(Ao
, Bo
, Fractal
);
187 Nb_Iteration
:= 0; --Initialise le compteur d'iteration a 0
189 --initialise le nombre complexe avec Z(o)
194 --Boucle calculant la divergence d'un point du plan
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
;
204 --Le compteur d'iteration est incemente
205 Nb_Iteration
:= Integer'Succ(Nb_Iteration
);
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
;
215 --Enregistre le point calcule dans la matrice d'iteration (Global)
216 Matrice_Retour(X
,Y
) := Nb_Iteration
;
221 return Matrice_Retour
; --Retourne la matrice
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 --
233 -- return : * Une matrice contenant la fractal sous forme de nombre d'iteration pour chaque --
235 ------------------------------------------------------------------------------------------------
236 function Julia_Gen (Largeur_Zone
, Hauteur_Zone
: Natural; Fractal
: Cara_Fractal
)
237 return T_Matrice_Iteration
is
239 A
, B
, -- La valeur reel et imaginaire courante lors du calcul Z en fonction de n : Z(n)
241 Temp
: Long_Float; --Une variable temporaire
243 Nb_Iteration
: Natural; --Pour compter le nombre d'iteration
245 --La matrice est cree et retournee
246 Matrice_Retour
: T_Matrice_Iteration (0..Largeur_Zone
, 0..Hauteur_Zone
);
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
);
252 --Variable precalculee pour ne pas avoir a la calculer a chaque iteration
253 Pre_Calcul
: Long_Float;
257 Pre_Calcul
:= (2.0 * Largeur_Zone_Tmp_Float
) * Fractal
.Zoom
;
259 --Parcours toute la dimension X de l'affichage (pixel)
260 for X
in 0..Largeur_Zone
loop
262 --Parcours toute la dimension Y de l'affichage (pixel)
263 for Y
in 0..Hauteur_Zone
loop
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
;
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
;
274 Change_Angle(A
, B
, Fractal
); --Change l'angle de la fractal
276 Nb_Iteration
:= 0; --Initialise le compteur d'iteration a 0
278 --Boucle calculant la divergence d'un point du plan
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
;
288 --Le compteur d'iteration est incemente
289 Nb_Iteration
:= Integer'Succ(Nb_Iteration
);
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
;
300 --Enregistre le point calcule dans la matrice d'iteration (Global)
301 Matrice_Retour(X
,Y
) := Nb_Iteration
;
306 return Matrice_Retour
;--Retourne la matrice
309 end Power_Calculator
;