Rq: Il faut préalablement sélectionner la bibliothèque " Détermination de trajectoires "
Nous allons être amenés à travailler avec des points sous forme cartésienne, mais parfois, la représentation polaire se révèle être d'une certaine utilité. Par conséquent, il nous faut avoir une routine qui nous permette de passer de l'une à l'autre.
Nous définissons tout d'abord le type p_polaire
type p_polaire={r:float;ang:float};;
#Le type p_polaire est défini.
Ensuite, nous écrivons une routine qui renvoie, à partir d'un point quelconque, typé en p_polaire, le même point mais avec r
et ang![]()
let rec reduit_p_pol p_pol=
if (p_pol.r)<0. then reduit_p_pol {r=abs_float(p_pol.r);ang=((p_pol.ang)+.Pi)}
else match (p_pol.ang) with
|val when val<=.(-.Pi)->reduit_p_pol {r=p_pol.r;ang=((p_pol.ang)+.(2.*.Pi))}
|val when val>.(Pi)->reduit_p_pol {r=p_pol.r;ang=((p_pol.ang)-.(2.*.Pi))}
|val->{r=p_pol.r;ang=val};;
#reduit_p_pol : p_polaire -> p_polaire = <fun>
Enfin, nous créons les deux routines de conversion qui fonctionnent de la même façon que lorsque l'on convertit un entier en flottant et inversement (float_of_int et int_of_float).
let cart_of_pol p_pol={x=(p_pol.r)*.(cos(p_pol.ang));y=(p_pol.r)*.(sin(p_pol.ang))};;
#cart_of_pol : p_polaire -> p_repere = <fun>
let pol_of_cart p_rep=
let r=distance p_rep {x=0.;y=0.} in let (a,b)=((p_rep.x)/.r,(p_rep.y)/.r) in
match (a,b) with
|(a,b) when b>0. ->{r=r;ang=acos a}
|(a,b) when a>0. ->{r=r;ang=asin b}
|(_,_)->{r=r;ang=acos(abs_float a)+.Pi};;
#pol_of_cart : p_repere -> p_polaire = <fun>
Les comètes sont des corps réels en rotation autour d'un astre, le soleil. Par conséquent, elle peuvent tourner dans deux sens, le sens que nous qualifierons de direct et qui correspond à une progression dans le sens des angles croissants dans le plan polaire, ou le sens indirect (angles décroissants). Pour déterminer ce sens, la représentation des points en polaire est tout à fait utile.
Nous commençons par déterminer le type sens :
type sens=direct|indirect;;
#Le type sens est défini.
Ensuite pour déterminer le sens de déplacement, il ne reste plus qu'à faire une comparaison sur la valeur des angles.
(on renverra le sens ainsi que les trois points classés dans le sens direct).
let sens_deplacement m1 m2 m3=
let v1=((pol_of_cart m1).ang) and v2=((pol_of_cart m2).ang)
and v3=((pol_of_cart m3).ang) in
if ( v1<v2 or v2<v3 ) then (m1,m2,m3,direct) else
if ( v3<v2 or v2<v1 ) then (m3,m2,m1,indirect) else
failwith "vos points ne sont pas correctement classées";;
#sens_deplacement : p_repere -> p_repere -> p_repere -> p_repere * p_repere * p_repere * sens = <fun>
Remarque : l'exception failwith dans ce classement n'aura vraisemblablement jamais lieu. En effet, ce qui pour nous correspond à des points mal classés peu toujours se ramener à un cas où les points sont dans le sens direct ou indirect. Ainsi le programme ne détectera aucune erreur et continuera comme si de rien était. Ainsi, il est judicieux de toujours vérifier la valeur de l'approximation sur l'intersection des hyperboles que l'on est amené à tracer (cf. Chapitre sur la détermination de trajectoires.) ; de toute manière le rendu graphique sera incontestablement incohérent.
En des temps égaux, le rayon vecteur reliant le soleil à une autre planète balaie des aires égales. A l'aide de cette loi de Kepler, on va pouvoir évaluer la période de rotation de la comète. Pour cela il suffit d'affecter un temps à deux des positions observées. On choisira arbitrairement les positions 1 et 3, sachant tout de même que se sont en principe les deux positions les plus éloignées l'une de l'autre et que par conséquent, elles offrent une plus grande précision sur l'échelle de valeur considérée.
Pour calculer l'aire d'une conique, nous avons décidé de procéder par découpage en effectuant un nombre de découpe le plus grand possible afin d'obtenir une plus grande approximation. Comme il s'agit de l'aire balayée par un rayon vecteur, nous considérons l'arc de conique comme étant localement un arc de cercle de centre le soleil.
let aire equ a b=
let val x=(equ.p)/.(1.+.(equ.e)*.cos(x-.(equ.aap)))
and pas=(b-.a)/.25000. and res=ref (0.) in
for i=0 to 24999 do
res:=!res+.(val (a+.(float_of_int i)*.pas))
*.(val (a+.(float_of_int (i+1))*.pas))*.pas/.2.
done;
(!res);;
#aire : conique -> float -> float -> float = <fun>
| Calcul d'une aire: aire {e=0.12;p=25.;aap=2.5} 0. 0.5 ;; | |
| Valeur Caml : | 182.571171063 |
| Valeur Maple : | 182.5711700 |
Pour déterminer la période, il ne reste plus qu'à faire un rapport entre l'aire total de la conique et l'aire entre les positions 1 et 3 et multiplier le tout par la différence de temps. Soit la fonction periode qui prend en argument deux p_repere affecté d'un flottant (qui correspond au temps dans l'unité voulue), l'équation , et le sens de déplacement de la comète.
Remarque : Si la différence de temps est négative ou nulle, la période sera considérée comme étant nulle. Dans un tel cas, physiquement impossible, les programmes suivants ignoreront la période).
let periode (p1,t1) (p2,t2) equ sens=
let v1=((pol_of_cart p1).ang) and v2=((pol_of_cart p2).ang) in
let aire_balayée=
match sens with
| direct-> if v1<v2 then (aire equ v1 v2)
else (aire equ v1 (v2+.2.*.Pi))
|indirect -> if v2<v1 then (aire equ v2 v1)
else (aire equ v2 (v1+.2.*.Pi)) in
if (t2-.t1)<0. then 0.
else ((t2-.t1)*.(aire equ (0.) (2.*.Pi))/.(aire_balayée));;
#periode : p_repere * float -> p_repere * float -> conique -> sens -> float =<fun>
Caml permet d'afficher des chaînes de caractères dans la fenêtre graphique, mais pas des valeurs numériques. Pour remédier à cela, il suffit de convertir préalablement les valeurs numériques en chaînes de caractères. D'où les fonctions :
let draw_float n=draw_string(string_of_float n);;
#draw_float : float -> unit = <fun>
let draw_int n=draw_string(string_of_int n);;
#draw_int : int -> unit = <fun>
Tout le traitement des données se fait à l'aide de la fonction donnees.
let donnees m1 m2 m3 t1 t3=
let (n1,n2,n3,sens)=(sens_deplacement m1 m2 m3) in
let Sun={x=0.;y=0.} in
let equ1=(equ_hyperbole n1 n2 Sun)
and equ2=(equ_hyperbole n2 n3 Sun) in
let list1=(branche_hyperbole equ1 n2 5000)
and list2=(branche_hyperbole equ2 n3 5000) in
let (epsilon,f2)=(fusion_intersection list1 list2) in
let equ_fin=(equ_ellipse Sun f2 m1) in
let periode=(periode (m1,t1) (m3,t3) equ_fin sens) in
(m1,m2,m3,sens,(vision (0.,0.) 75.),(0.,0.),(75.),epsilon,f2,equ1,equ2,equ_fin,periode);;
#donnees : p_repere -> p_repere -> p_repere -> float -> float -> p_repere * p_repere * p_repere * sens * repere * (float * float) * float * float * p_repere * conique * conique * conique * float = <fun>
Elle prend en argument trois positions (typées en p_repere) et deux flottants (temps affectés aux positions 1 et 3) et renvoie 12 valeurs qui sont :
Dans notre programme, nous pourrons faire plusieurs choix :
Il faut donc fabriquer une fonction distance qui travaille sur un couple d'entiers.
let dist p1 p2= let (a,b)=p1 and (c,d)=p2 in
int_of_float(sqrt (float_of_int (((a-c)*(a-c))+((b-d)*(b-d)))));;
#dist : int * int -> int * int -> int = <fun>
![]() |
let rec deter_plein_point n=clear_graph();
fond_ecran black;
set_color yellow;
fill_circle 300 400 100;
set_color cyan;
fill_circle 500 200 100;
set_color black;
moveto 280 391;
draw_string "plein";
moveto 480 191;
draw_string "point";
let e=wait_next_event [Button_down] in
if (dist (e.mouse_x,e.mouse_y) (300,400))<100 then plein
else if (dist (e.mouse_x,e.mouse_y) (500,200))<100 then point
else deter_plein_point (n+1);;
#deter_plein_point : int -> plein_point = <fun>
C'est une fonction très simple qui prend en argument les valeurs renvoyées par la fonction " données " et qui affiche les valeurs qui nous intéressent dans la fenêtre graphique. Si la période est nulle, elle ne sera pas affichée et si l'approximation sur l'intersection (nommée plus simplement epsilon) est supérieure à 0,1, elle s'affiche en rouge.
let affiche_valeur (m1,m2,m3,_,_,_,_,epsilon,f2,_,_,equ_fin,periode)=
clear_graph();
set_color blue;
moveto 50 550;
draw_string "* points observés *";
moveto 55 530;
draw_string "* position 1:";
moveto 60 510;
draw_string "coordonnées cartésienne: (x=";
draw_float (m1.x);
draw_string ",y=";
draw_float (m1.y);
draw_string ")";
moveto 60 490;
draw_string "coordonnées polaires: (r=";
draw_float ((pol_of_cart m1).r);
draw_string ",ang=";
draw_float ((pol_of_cart m1).ang);
draw_string ")";
moveto 55 470;
draw_string "* position 2:";
moveto 60 450;
draw_string "coordonnées cartésienne: (x=";
draw_float (m2.x);
draw_string ",y=";
draw_float (m2.y);
draw_string ")";
moveto 60 430;
draw_string "coordonnées polaires: (r=";
draw_float ((pol_of_cart m2).r);
draw_string ",ang=";
draw_float ((pol_of_cart m2).ang);
draw_string ")";
moveto 55 410;
draw_string "* position 3:";
moveto 60 390;
draw_string "coordonnées cartésienne: (x=";
draw_float (m3.x);
draw_string ",y=";
draw_float (m3.y);
draw_string ")";
moveto 60 370;
draw_string "coordonnées polaires: (r=";
draw_float ((pol_of_cart m3).r);
draw_string ",ang=";
draw_float ((pol_of_cart m3).ang);
draw_string ")";
moveto 50 340;
draw_string "* approximation sur l'intersection = ";
begin if epsilon>(0.1) then (set_color red) end;
draw_float epsilon;
set_color blue;
moveto 50 310;
draw_string "* coordonnées du deuxiéme foyer:";
moveto 55 290;
draw_string "coordonnées cartésienne: (x=";
draw_float (f2.x);
draw_string ",y=";
draw_float (f2.y);
draw_string ")";
moveto 55 270;
draw_string "coordonnées polaires: (r=";
draw_float ((pol_of_cart f2).r);
draw_string ",ang=";
draw_float ((pol_of_cart f2).ang);
draw_string ")";
moveto 50 240;
draw_string"* équation polaire de la trajectoire :";
moveto 55 220;
draw_string "(exentricité/paramétre/angle axe polaire)=(";
draw_float (equ_fin.e);
draw_string "/";
draw_float (equ_fin.p);
draw_string "/";
draw_float (equ_fin.aap);
draw_string ")";
if periode<>0. then
begin
moveto 50 190;
draw_string "* Période de révolution : ";
draw_float periode;
draw_string " SI"
end;
while (not(key_pressed())) do done;;
#affiche_valeur : p_repere* p_repere * p_repere * 'a * 'b * 'c * 'd * float * p_repere * 'e * 'f * conique * float -> unit =<fun>

Il existe quatre types de tracés donc quatre fonctions (qui prennent tous en argument les paramètres renvoyés par la fonction " données ")
let Menu_deter_foyers param=
let (m1,m2,m3,sens,R,_,_,_,f2,equ1,equ2,equ_fin,_)=param in
clear_graph();
trace_rep R 1 black;
set_color blue;
point_rep m1 R;
point_rep m2 R;
point_rep m3 R;
set_color black;
moveto (((rep_to_ecr m1 R).X)+15) (((rep_to_ecr m1 R).Y)+15);
draw_string "M1";
moveto (((rep_to_ecr m2 R).X)+15) (((rep_to_ecr m2 R).Y)+15);
draw_string "M2";
moveto (((rep_to_ecr m3 R).X)+15) (((rep_to_ecr m3 R).Y)+15);
draw_string "M3";
while not(key_pressed()) do done;
let (val1,val2)=match sens with
|direct ->(m2,m3)
|indirect->(m2,m1); in
trace_comete {equ=equ1;foyer=soleil}
{O={X=(R.O.X)+(int_of_float((float_of_int(R.I))*.(val1.x)));
Y=(R.O.Y)+(int_of_float((float_of_int(R.J))*.(val1.y)))};I=R.I;J=R.J} plein 500 [|cyan|];
trace_comete {equ=equ2;foyer=soleil}
{O={X=(R.O.X)+(int_of_float((float_of_int(R.I))*.(val2.x)));
Y=(R.O.Y)+(int_of_float((float_of_int(R.J))*.(val2.y)))};I=R.I;J=R.J} plein 500 [|green|];
set_color black;
moveto (((rep_to_ecr f2 R).X)+15) (((rep_to_ecr f2 R).Y)+15);
draw_string "F2";
set_color blue;
point_rep f2 R;
while not(key_pressed()) do done;
trace_comete {equ=equ_fin;foyer=autre} R plein 750 [|red|];
while not(key_pressed()) do done;;
#Menu_deter_foyers : p_repere * p_repere * p_repere * sens * repere * 'a * 'b * 'c * p_repere * conique * conique * conique * 'd -> unit = <fun>
![]() |
Ce tracé est le plus simple : il trace la trajectoire après nous avoir préalablement demandé si nous désirions un tracé en plein ou en point.
let Menu_trace param=
let (m1,m2,m3,_,R,_,_,_,_,_,_,equ_fin,_)=param
and pp=(deter_plein_point 0) in
clear_graph();
trace_rep R 1 black;
set_color red;
point_rep m1 R;
point_rep m2 R;
point_rep m3 R;
set_color black;
moveto (((rep_to_ecr m1 R).X)+15) (((rep_to_ecr m1 R).Y)+15);
draw_string "M1";
moveto (((rep_to_ecr m2 R).X)+15) (((rep_to_ecr m2 R).Y)+15);
draw_string "M2";
moveto (((rep_to_ecr m3 R).X)+15) (((rep_to_ecr m3 R).Y)+15);
draw_string "M3";
while not(key_pressed()) do done;
if pp=plein then
trace_comete {equ=equ_fin;foyer=soleil} R plein 750 [|blue|]
else trace_comete {equ=equ_fin;foyer=soleil} R point 150 [|blue|];
while not(key_pressed()) do done;;
#Menu_trace : p_repere * p_repere * p_repere * 'a * repere * 'b * 'c * 'd * 'e * 'f * 'g * conique * 'h -> unit = <fun>
![]() |
Cette fonction à globalement le même comportement que la fonction précédente à la différence prés qu'il crée un fond d'écran avec des étoiles, place le soleil et ajoute de la couleur au tracé.
let Menu_artistique param= let (m1,m2,m3,_,R,_,_,_,_,_,_,equ_fin,_)=param
and pp=(deter_plein_point 0) and tr_ce (a,b) c=(draw_circle a b c) in
fond_ecran black;
ciel2 300;
trace_rep R 1 blue;
astre_solaire (equ_fin.p/.5.) R;
while not(key_pressed()) do done;
set_color red;
move_rep m1 R;
tr_ce (current_point()) 5;
move_rep m2 R;
tr_ce (current_point()) 5;
move_rep m3 R;
tr_ce (current_point()) 5;
moveto (((rep_to_ecr m1 R).X)+15) (((rep_to_ecr m1 R).Y)+15);
draw_string "M1";
moveto (((rep_to_ecr m2 R).X)+15) (((rep_to_ecr m2 R).Y)+15);
draw_string "M2";
moveto (((rep_to_ecr m3 R).X)+15) (((rep_to_ecr m3 R).Y)+15);
draw_string "M3";
while not(key_pressed()) do done;
if pp=plein then
trace_comete {equ=equ_fin;foyer=soleil} R plein 750 [|yellow;green;cyan;magenta;white|]
else trace_comete {equ=equ_fin;foyer=soleil} R point 150 [|yellow;green;cyan;magenta;white|];
while not(key_pressed()) do done;;
#Menu_artistique : p_repere * p_repere * p_repere * 'a * repere * 'b * 'c * 'd * 'e * 'f * 'g * conique * 'h -> unit = <fun>
![]() |
Ce programme ne trace pas réellement la trajectoire mais il permet de visualiser le parcours de la comète. Si la période est non nulle, on peu également visualiser l'évolution du temps. Ce programme, construit comme un petit dessin animé est particulièrement intéressant car il permet de visualiser effectivement la cinétique de la comète.
Remarque : pour arrêter l'évolution de la comète, il faut maintenir une touche enfoncée.
let Menu_animation param=let (_,_,_,sens,R,_,_,_,_,_,_,equ_fin,periode)=param in
fond_ecran black;
ciel2 300;
astre_solaire (equ_fin.p/.5.) R;
while not(key_pressed()) do done;
moveto 10 (size_y()-20);
draw_string "maitenir une touche enfoncée jusqu'à l'arret complet de la comète";
let signe=match sens with
|direct ->(1.)
|indirect->(-.1.); in
let valeur teta=let v t=(equ_fin.p)/.(1.+.((equ_fin.e)*.cos(teta-.(equ_fin.aap))))
in {x=(v teta)*.(cos teta);y=(v teta)*.(sin teta)};
and co_ce m=(move_rep m R);
let (a,b)=(current_point()) in
fill_circle a b 8;
and ang n=signe*.(Pi/.1000.*.(float_of_int n))
and i=ref 1000 and j=ref (0.)
in while not(key_pressed()) do
if (((!i) mod 1000)=0) && (periode<>0.) then
begin moveto 10 (size_y()-39);
draw_string "temps : ";
draw_float (!j);
draw_string "*";
draw_float periode;
draw_string "=";
draw_float (!j*.periode);
draw_string " SI";
j:=(!j+.0.5)
end;
set_color magenta;
co_ce (valeur (ang !i));
segment_rep (valeur ((ang !i)+.Pi)) (valeur ((ang (!i+1))+.Pi)) R;
set_color black;
co_ce (valeur (ang !i));
i:=(!i+1);
done;;
#Menu_animation : 'a * 'b * 'c * sens * repere * 'd * 'e * 'f * 'g * 'h * 'i * conique * float -> unit = <fun>
![]() |
Nous souhaitons pouvoir faire évoluer les paramètres de la fenêtre d'observation ( sa taille et son centre) sans avoir à quitter l'application graphique. Pour cela nous allons donc procéder comme pour les autres menus impliquant un choix. Après avoir tracé une trajectoire, l'utilisateur sera donc amené à choisir entre recadrer la fenêtre ou revenir au sommaire. Ensuite, il pourra effectuer les changements qu'il désire dans les paramètres de la fenêtre.
Remarque : X et Y représentent la position du centre du repère par rapport au centre de l'écran.
|
|
let new_param paramétres=
set_color black;
fill_rect 200 100 400 400;
moveto 264 475;
draw_string "Choisissez vos nouveaux paramétres";
moveto 376 450;
draw_string "centre";
moveto 372 300;
draw_string "largeur";
set_color yellow;
fill_circle 260 430 15;
fill_circle 540 430 15;
fill_circle 260 360 15;
fill_circle 540 360 15;
fill_circle 260 290 15;
fill_circle 540 290 15;
set_color magenta;
fill_circle 280 425 15;
fill_circle 520 425 15;
fill_circle 280 355 15;
fill_circle 520 355 15;
fill_circle 280 285 15;
fill_circle 520 285 15;
set_color cyan;
fill_circle 300 420 15;
fill_circle 500 420 15;
fill_circle 300 350 15;
fill_circle 500 350 15;
fill_circle 300 280 15;
fill_circle 500 280 15;
set_color blue;
fill_circle 400 200 50;
moveto 296 411;
draw_string "-";
moveto 496 411;
draw_string "+";
moveto 296 341;
draw_string "-";
moveto 496 341;
draw_string "+";
moveto 296 271;
draw_string "-";
moveto 496 271;
draw_string "+";
set_color black;
moveto 388 191;
draw_string "Fin";
let rec result param=
let (a,b,c,d,R,(cx,cy),lar,e,f,g,h,i,j)=param in
moveto 383 411;
draw_string "X=";
moveto 400 411;
draw_float cx;
moveto 383 341;
draw_string "Y=";
moveto 400 341;
draw_float cy;
moveto 390 271;
draw_float lar;
let q=wait_next_event [Button_down] in
match (q.mouse_x,q.mouse_y) with
|val when (dist val (400,200))<50->(a,b,c,d,(vision (cx,cy) lar),(cx,cy),lar,e,f,g,h,i,j)
|val when (dist val (300,420))<15->result (a,b,c,d,R,((cx-.1.),cy),lar,e,f,g,h,i,j)
|val when (dist val (500,420))<15->result (a,b,c,d,R,((cx+.1.),cy),lar,e,f,g,h,i,j)
|val when (dist val (300,350))<15->result (a,b,c,d,R,(cx,(cy-.1.)),lar,e,f,g,h,i,j)
|val when (dist val (500,350))<15->result (a,b,c,d,R,(cx,(cy+.1.)),lar,e,f,g,h,i,j)
|val when (dist val (300,280))<15->if (lar)<=.10. then result param
else result (a,b,c,d,R,(cx,cy),(lar-.1.),e,f,g,h,i,j)
|val when (dist val (500,285))<15->result (a,b,c,d,R,(cx,cy),(lar+.1.),e,f,g,h,i,j)
|val when (dist val (280,425))<15->result (a,b,c,d,R,((cx-.5.),cy),lar,e,f,g,h,i,j)
|val when (dist val (520,425))<15->result (a,b,c,d,R,((cx+.5.),cy),lar,e,f,g,h,i,j)
|val when (dist val (280,355))<15->result (a,b,c,d,R,(cx,(cy-.5.)),lar,e,f,g,h,i,j)
|val when (dist val (520,355))<15->result (a,b,c,d,R,(cx,(cy+.5.)),lar,e,f,g,h,i,j)
|val when (dist val (280,285))<15->if (lar)<=.14. then result param
else result (a,b,c,d,R,(cx,cy),(lar-.5.),e,f,g,h,i,j)
|val when (dist val (520,285))<15->result (a,b,c,d,R,(cx,cy),(lar+.5.),e,f,g,h,i,j)
|val when (dist val (260,430))<15->result (a,b,c,d,R,((cx-.10.),cy),lar,e,f,g,h,i,j)
|val when (dist val (540,430))<15->result (a,b,c,d,R,((cx+.10.),cy),lar,e,f,g,h,i,j)
|val when (dist val (260,360))<15->result (a,b,c,d,R,(cx,(cy-.10.)),lar,e,f,g,h,i,j)
|val when (dist val (540,360))<15->result (a,b,c,d,R,(cx,(cy+.10.)),lar,e,f,g,h,i,j)
|val when (dist val (260,290))<15->if (lar)<=.19. then result param
else result (a,b,c,d,R,(cx,cy),(lar-.10.),e,f,g,h,i,j)
|val when (dist val (540,290))<15->result (a,b,c,d,R,(cx,cy),(lar+.10.),e,f,g,h,i,j)
|_->result param;
in result paramétres;;
#new_param : 'a * 'b * 'c * 'd * 'e * (float * float) * float * 'f * 'g * 'h * 'i * 'j * 'k ->
'a * 'b * 'c * 'd * repere * (float * float) * float * 'f * 'g * 'h * 'i * 'j * 'k = <fun>
Ce programme est lancé à partir d'une autre fonction qui nous propose, soi de retourner au sommaire, soi d'effectuer un recadrage de la fenêtre d'observation à l'aide du programme défini précédemment.
let ch_contex paramétres=
let rec valeur n=set_color yellow;
fill_circle 300 400 100;
set_color cyan;
fill_circle 500 200 100;
set_color black;
moveto 268 391;
draw_string "Sommaire";
moveto 472 191;
draw_string "cadrage";
let e=wait_next_event [Button_down] in
if (dist (e.mouse_x,e.mouse_y) (300,400))<100 then true
else if (dist (e.mouse_x,e.mouse_y) (500,200))<100 then false
else valeur (n+1); in
match (valeur 0) with
|true->(true,paramétres)
|false->(false,(new_param paramétres));;
#ch_contex : 'a * 'b * 'c * 'd * repere * (float * float) * float * 'e * 'f * 'g * 'h * 'i * 'j ->
bool * ('a * 'b * 'c * 'd * repere * (float * float) * float * 'e * 'f * 'g * 'h * 'i * 'j) = <fun>
La page d'accueil nécessite tout d'abord deux autres petites routines :
La première, appelée page_sommaire, dessine la page. Elle n'a qu'une utilité graphique. La seconde est la page de fin, elle permet de quitter le programme. (A la fin du programme, on récupère les données essentielles du problème qui peuvent ainsi être utilisées dans une autre application).
let page_sommaire n=clear_graph () ;
set_color red ;
moveto 400 400 ;
draw_string "Les Cométes";
set_color blue ;
fill_circle 150 350 5 ;
moveto 175 340 ;
draw_string "Détermination des foyers" ;
fill_circle 150 300 5 ;
moveto 175 290 ;
draw_string "Tracé trajectoire" ;
fill_circle 150 250 5 ;
moveto 175 240 ;
draw_string "Tracé esthétique" ;
fill_circle 150 200 5 ;
moveto 175 190 ;
draw_string "Tracé Animé" ;
set_color yellow;
fill_circle 150 480 40;
set_color cyan;
fill_circle 655 490 100;
set_color black;
draw_circle 150 480 40;
draw_circle 655 490 100;
moveto 138 471;
draw_string "FIN";
moveto 587 480;
draw_string "données numériques";;
#page_sommaire : 'a -> unit = <fun>
let ecran_fin param=
let (m1,m2,m3,_,_,_,_,epsilon,f2,_,_,equ_fin,periode)=param in
clear_graph();
for i=1 to 750 do
set_color (rgb (int 255) (int 255) (int 255));
moveto (int (size_x())) (int (size_y()));
draw_string "FIN"
done;
while not(key_pressed()) do done;
print_string "* * * * Merci de votre visite * * * *";
print_newline();
print_string "(m1,m2,m3,f2,equ_fin,epsilon,periode)=";
print_newline();
(m1,m2,m3,f2,equ_fin,epsilon,periode);;
#ecran_fin : 'a * 'b * 'c * 'd * 'e * 'f * 'g * 'h * 'i * 'j * 'k * 'l * 'm -> 'a * 'b * 'c * 'i * 'l * 'h * 'm = <fun>
Enfin le menu principal permet de gérer tout le menu de navigation de la page principale. C'est aussi le centre névralgique de tout le système puisque c'est la première page que l'on voit apparaître et c'est par elle que l'on passe pour quitter le programme. Menu prend en argument les trois positions et les temps affectés aux positions 1 et 3.
let menu m1 m2 m3 t1 t3=
let paramétres=(donnees m1 m2 m3 t1 t3) in
let rec sommaire param= page_sommaire 0;
let e=wait_next_event [Button_down] in
if abs(e.mouse_y-340)<10 then (menu 1 param)
else
if abs(e.mouse_y-290)<10 then (menu 2 param)
else
if abs(e.mouse_y-240)<10 then (menu 3 param)
else
if abs(e.mouse_y-190)<10 then (menu 4 param)
else
if (dist (e.mouse_x,e.mouse_y) (150,480))<40 then
(ecran_fin param)
else
if (dist (e.mouse_x,e.mouse_y) (655,490))<100 then
(menu_num param)
else(sommaire param);
and menu_num param=
affiche_valeur param;
sommaire param;
and menu n param=if n=1 then Menu_deter_foyers param
else if n=2 then Menu_trace param
else if n=3 then Menu_artistique param
else if n=4 then Menu_animation param;
choix_contextuel n param;
and choix_contextuel n param=
let (valeur,parame)=(ch_contex param) in
match valeur with
|true->(sommaire param)
|false->(menu n parame);
in
sommaire paramétres;;
#menu : p_repere -> p_repere -> p_repere -> float -> float ->
p_repere * p_repere * p_repere * p_repere * conique * float * float = <fun>
![]() |