Dimanche 11 Mai 2008
~ Interface Graphique ~
Menu
> Accueil

Programmation
> Algorithmes de tri
> Java

Réseaux Telecom
> Logiciel Vigie

Dossiers
> Trajectoire de comètes
> Gestion d'emploi du temps
> Tracking d'internautes
> Référencement
> Open Office
> Multi-agents dans les EIAH

Divers
> Album Photo
> Citations
> Recettes
> Bibliothèque
> Logiciels
> Mini-Annuaire

A propos
> Mon CV
> Me contacter
Recherche
Google
Sur ce site
Sur le web
Annonces
Accueil > Trajectoire de comètes > Interface Graphique

Rq: Il faut préalablement sélectionner la bibliothèque " Détermination de trajectoires "

  1. Objectifs

    Le but est de créer un menu qui nous permette de déterminer les paramètres d'une comète dans son plan de révolution à partir de 3 positions observées et en supposant que le centre du repère est l'un des foyers. De plus, en affectant deux temps d'observation (sur les positions 1 et 3) nous allons pouvoir évaluer la période de révolution de la comète.
    Nous voulons pouvoir évoluer facilement dans le menu et pouvoir choisir un maximum de paramètres :
    • Le type de représentation voulu
    • La taille et la position du centre du repère graphique.
    • Pouvoir visualiser les données numériques.
    • Etc....
    Nous avons donc, pour ce faire choisit de réaliser un menu de navigation à l'aide de la souris et du clavier. Pour une évolution simple, on appuie sur une touche tandis que pour faire un choix, on clique sur l'objet choisit à l'aide de la souris.

  2. Création de quelques outils :

    1. Convertir des coordonnées cartésiennes en polaires, et réciproquement.

      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>

    2. Déterminer le sens de rotation de la comète dans le plan polaire

      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.

    3. Déterminer la période de rotation de la comète.

      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>

    4. Questions pratiques d'affichage de valeur numériques dans la fenêtre graphique.

      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>


  3. Traitement des données

    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 :

    • Les trois positions
    • Le sens de déplacement de la comète
    • Le repère du tracé
    • Le centre du repère par rapport au centre de l'écran
    • La largeur du repère
    • La valeur de l'approximation sur l'intersection des deux branches d'hyperbole qui nous ont servi à déterminer le second foyer.
    • Le deuxième foyer
    • Les équations des deux branches d'hyperbole
    • L'équation de la trajectoire
    • La période de révolution.
    Remarque : il ne sert à rien de s'affoler devant le nombre de valeurs renvoyées, il ne s'agit que d'une fonction intermédiaire.

  4. Les différentes options d'affichage :

    Dans notre programme, nous pourrons faire plusieurs choix :

    • Regarder les valeurs numériques (paramètres de la trajectoire)
    • Tracer la trajectoire de différentes manières ( 6 en tout )
    Chaque choix nécessite un programme différent.

    1. Notions de navigation :

      Si nous n'avons aucun choix à faire, pour progresser il faut appuyer sur une touche du clavier ; Sinon, il faut faire son choix en appuyant sur le bouton gauche de la souris. En réalité, le programme détecte la position de la souris et fait ce qu'il doit faire. En cliquant sur la souris, Caml renvoie un point de l'écran. Nous avons dessiné des cercles, si la souris au moment du clic est à l'intérieur d'un cercle, Caml exécute l'action voulue ; Sinon, il attend que l'on clique sur une autre zone de l'écran.

      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>

    2. Choix de l'option plein ou point

      Rendu graphique.




      Deux des menus de tracé offrent le choix du type de tracé : plein ou point. Il s'agit des menus " Tracé trajectoire " et " Tracé esthétique ". Le programme deter_plein_point permet de faire ce choix en toute simplicité à l'aide de la souris.
      Il prend en argument un entier qui permet de relancer le programme si l'on vise à coté des cercles.


      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>

    3. Affichage des paramètres de la conique

      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>



    4. Les différents types de tracés.

      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 ")

      1. Tracé montrant la détermination du deuxième foyer :
        • Il place les 3 points observés
        • Il trace les deux branches d'hyperbole dont l'intersection est le second foyer
        • Il trace la trajectoire de la comète
        Ces trois actions s'effectuent successivement après que l'on ait appuyé sur une touche.

        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>

        Exemple de tracé.

      2. Tracé de trajectoire " simple " :

        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>

        Exemple de tracé (en point).
      3. Tracé de trajectoires " esthétique "

        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>

        Exemple de tracé artistique (en plein).

      4. Tracé animé de trajectoires

        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>

        Exemple d'animation

  5. Problème de cadrage.

    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.

    Légende
    Couleurvaleur
    Bleu1
    Magenta5
    Jaune10
     
    menu de cadrage

    Pour effectuer ce sous menu de cadrage, on utilise la fonction new_param qui prend en argument les paramètres renvoyés par " donnees " et redonne les mêmes paramètres où les valeurs concernant le cadrage de l'écran ont été modifiées.

    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>

  6. Page d'accueil

    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>

    Interface utilisateur d'accueil

Accueil > Trajectoire de comètes > Interface Graphique