Dimanche 11 Mai 2008
~ Détermination de trajectoires ~
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 > Détermination de trajectoires

Remarque : Il faut préalablement sélectionner la bibliothèque de tracé de trajectoires.

Les comètes sont des objets qui se déplacent, en première approximation, en respectant les lois de Kepler :
  • Dans un repère ayant pour origine le centre du soleil et des axes dirigés suivant des étoiles supposées fixes, les planètes décrivent des ellipses dont le soleil est l'un des foyers.
  • En des temps égaux, le rayon vecteur reliant le soleil à une autre planète balaie des aires égales.
  • Le carré de la période de révolution d'une planète autour du Soleil est proportionnel au cube du demi-grand-axe de son orbite. En vertu de ces trois lois on va pouvoir, à partir de trois points d'observation, déterminer la trajectoire des comètes (ou de planètes) ainsi qu'évaluer leur période de révolution.

  1. PRINCIPE

    Quatre points suffisent à la détermination de l'équation d'une conique. A partir de trois positions on peut donc déterminer la trajectoire de cette conique dans un plan si on en connaît déjà l'un des foyers.
    L'équation polaire d'une conique est du type r (t)=.
    Il faut donc déterminer :
    • P : paramètre de la conique
    • e : son excentricité
    • aap : angle que fait l'axe polaire avec l'axe des abscisses.
    Chaque position nous donne une valeur pour r (t) donc trois positions permettent de déterminer ces trois inconnues. Cependant, la résolution purement mathématique de cette équation est assez laborieuse, on utilise donc un autre principe. Si l'on trouve le deuxième foyer de la conique, il est très facile, à l'aide de sa définition bifocale d'en retrouver l'équation ( en se servant également de la position de l'un des points de sa trajectoire). Pour trouver l'équation de la conique, on est donc amené à déterminer son deuxième foyer. Pour cela, on utilise un autre résultat. Soit M1, M2 et M3 nos trois positions, les foyers sont l'intersection des deux branches des deux hyperboles de foyers respectifs (M1, M2) et (M2, M3). A l'aide de la définition bifocale des hyperboles, on peut alors déterminer leur trajectoire sachant que le premier foyer (que l'on connaît) appartient à cette trajectoire. Il ne reste plus alors qu'à trouver l'intersection des deux branches d'hyperbole qui ne passent pas par ce premier foyer pour déterminer la position du deuxième foyer.

    intersection des deux branches d'hyperbole

  2. Détermination de l'intersection de deux courbes.

    1. Comment avons nous procédé ?

      Le but est de déterminer l'intersection de deux courbes, connaissant leur équation et sachant qu'il n'existe qu'un seul et unique point d'intersection.
      La solution retenue est simple : On crée deux listes de coordonnées qui correspondent aux valeurs de chaque courbe en un nombre fini de points, puis on recherche les éléments qui sont les plus proches dans chaque liste.
      Pour réaliser cela, on est amené à comparer des valeurs en évoluant dans une liste. Il faut donc classer ces éléments pour faciliter la progression. La comparaison se fait sur deux coordonnées. On classera donc les valeurs (x, y) dans le sens des x croissants et, dans le cas ou les x sont égaux, dans le sens des y croissants. On utilise pour faire ce classement le tri fusion qui présente l'avantage d'avoir une complexité en (n*ln(n)) où n est le nombre d'éléments à trier.
      Une fois ce tri réalisé, on effectue des comparaisons sur les distances entre les points, tout en évoluant linéairement dans l'une ou l'autre des deux listes. Plusieurs références permettront de conserver en mémoire les deux points les moins éloignés ainsi que la distance entre eux (distance qui servira aux différentes comparaisons). C'est le fait que les listes soient classées qui assure que l'algorithme effectue bien une approximation sur l'intersection des deux listes. L'algorithme s'arrête quand l'une des deux listes a été totalement parcourue. Une fois l'algorithme effectué, il ne reste plus qu'à choisir l'un des deux points renvoyés : On choisira le milieu du segment définit par les deux points, tandis qu'une rapide observation de la valeur de la distance entre les deux points permettra de savoir si l'intersection est réellement pertinente.
      La complexité de cet algorithme est en (n+m) où n et m sont le nombre de valeurs dans chaque liste.

      Etude de complexité :
      Soit n le nombre de points calculés, la complexité pour la création de deux listes est donc 2*n
      le tri des deux listes 2*n*ln(n)
      la comparaison : 2*n
      Soit une complexité totale en O(4*n+2*n*ln(n)) : Complexité quasi linéaire.

      Remarques :
      Plus le nombre de points calculés est grand, plus l'approximation sur l'intersection risque d'être précise.
      Notre but est de résoudre un problème physique, une valeur mathématiquement exacte, même si elle est toujours préférable à une approximation, n'est donc pas nécessaire.

    2. Les programmes.

      1. le tri fusion.

        let rec divise =function
            |[]->([],[])
            |[e]->([e],[])
            |a::b::r->let (m1,m2)=divise r in (a::m1,b::m2);;

        #divise : 'a list -> 'a list * 'a list = <fun>

        let rec fusion_pts lista listb=match lista,listb with
            |l,[]->lista
            |[],l->listb
            |(a::r),(b::s)->
                  if (a.x)<>b.x then
                            if (a.x)<(b.x) then a::(fusion_pts r listb)
                                      else b::(fusion_pts lista s)
                  else if (a.y)<(b.y) then a::(fusion_pts r listb)
                                      else b::(fusion_pts lista s);;

        #fusion_pts : p_repere list -> p_repere list -> p_repere list = <fun>

        let rec tri_pts=fun
            |[]->[]
            |[e]->[e]
            |l->let (m1,m2)=divise l in
                             fusion_pts (tri_pts m1) (tri_pts m2);;

        #tri_pts : p_repere list -> p_repere list = <fun>

      2. L'intersection:

        On est souvent amené à calculer des distances, d'où la fonction distance, écrite une fois pour toute :

        let distance pa pb=sqrt((((pa.x)-.(pb.x))*.((pa.x)-.(pb.x)))+.(((pa.y)-.(pb.y))*.((pa.y)-.(pb.y))));;

        #distance : p_repere -> p_repere -> float = <fun>

        L'intersection en elle-même, qui renvoie les deux points issus des deux listes ainsi que la distance entre eux :

        let intersection lista listb=
            if lista=[] or listb=[] then
              failwith "liste vide"
            else
              let ha=ref(hd lista) and hb=ref(hd listb)
              and resulta=ref(hd lista) and resultb=ref(hd listb)
              and qa=ref(tl lista) and qb=ref(tl listb) in
              let epsilon=ref(distance (!ha) (!hb)) in
              while ((!qa)<>[] && (!qb)<>[]) do
                if ((!ha).x)<>((!hb).x) then
                
                  if ((!ha).x)<((!hb).x) then
                    
                    if (distance (!ha) (!hb))<(!epsilon) then
                      begin
                        epsilon:=(distance (!ha) (!hb));
                        resulta:=(!ha);
                        resultb:=(!hb);
                        ha:=(hd(!qa));
                        qa:=(tl(!qa));
                      end
                    else
                      begin
                        ha:=(hd(!qa));
                        qa:=(tl(!qa));
                      end
                    
                  else
                    
                    if (distance (!ha) (!hb))<(!epsilon) then
                      begin
                        epsilon:=(distance (!ha) (!hb));
                        resulta:=(!ha);
                        resultb:=(!hb);
                        hb:=(hd(!qb));
                        qb:=(tl(!qb));
                      end
                    else
                      begin
                        hb:=(hd(!qb));
                        qb:=(tl(!qb));
                      end
                
                else
                
                  if ((!ha).y)<=((!hb).y) then
                    
                    if (distance (!ha) (!hb))<(!epsilon) then
                      begin
                        epsilon:=(distance (!ha) (!hb));
                        resulta:=(!ha);
                        resultb:=(!hb);
                        ha:=(hd(!qa));
                        qa:=(tl(!qa));
                      end
                    else
                      begin
                        ha:=(hd(!qa));
                        qa:=(tl(!qa));
                      end
                      
                  else
                    
                    if (distance (!ha) (!hb))<(!epsilon) then
                      begin
                        epsilon:=(distance (!ha) (!hb));
                        resulta:=(!ha);
                        resultb:=(!hb);
                        hb:=(hd(!qb));
                        qb:=(tl(!qb));
                      end
                    else
                      begin
                        hb:=(hd(!qb));
                        qb:=(tl(!qb));
                      end;
              done;
            (!epsilon,(!resulta),(!resultb));;


        #intersection : p_repere list -> p_repere list -> float * p_repere * p_repere = <fun>

        Enfin le même tri qui renvoie un seul et unique point ainsi que l'approximation sur l'intersection:

        let fusion_intersection liste1 liste2=
            let (epsilon,p1,p2)=intersection (tri_pts liste1) (tri_pts liste2) in
                   (epsilon,{x=(((p1.x)+.(p2.x))/.2.);y=(((p1.y)+.(p2.y))/.2.)});;

        #fusion_intersection : p_repere list -> p_repere list -> float * p_repere = <fun>

  3. Détermination de l'équation des coniques.

    1. Fonctions utiles

      Pour déterminer l'équation d'une conique à l'aide de leur définition bifocale, il suffit d'avoir les coordonnées des deux foyers ainsi qu'un des points de la courbe.
      On peut ainsi déterminer l'équation d'une conique dans les cas de l'hyperbole et de l'ellipse. (Nous ne considérerons pas ici le cas de la parabole car il est peu probable, aux vues des approximations, que l'on rencontre un jour sur une excentricité strictement égale à 1).
      Soit alors les fonctions equ_hyperbole et equ_ellipse qui prennent en argument les deux foyers et le point appartenant à la trajectoire.

      let equ_hyperbole f1 f2 m=
            let c=((distance f1 f2)/.2.)
            and a=(abs_float((distance f1 m)-.(distance f2 m))/.2. )
            and aap=(atan( ((f2.y)-.(f1.y))/.((f2.x)-.(f1.x)) )) in
      {e=(c/.a);p=(abs_float( ((c*.c)-.(a*.a))/.a ));aap=aap};;

      #equ_hyperbole : p_repere -> p_repere -> p_repere -> conique = <fun>

      let equ_ellipse f1 f2 m =
            let c = ((distance f1 f2)/.2.)
            and a = (((distance f1 m)+.(distance f2 m))/.2.)
            and aap = ( atan( (f2.y)/.(f2.x) )) in
      {e=(c/.a);p=(abs_float( ((c*.c)-.(a*.a))/.a ));aap=aap};;

      #equ_ellipse : p_repere -> p_repere -> p_repere -> conique = <fun>



      Enfin, la fonction branche_hyperbole fabrique la liste des points d'une branche d'ellipse :
      Elle prend en argument une conique, la position du point de référence (qui servira au changement de repère), et le nombre de points à calculer ; elle renvoie une liste de points.

      let branche_hyperbole hyperbole foyer n =
           let p=hyperbole.p
           and e=hyperbole.e
           and aap=hyperbole.aap in
           let liste=ref[]
           and t=ref( (acos(-.1./.(e)))+.aap )
           and dt=( (2.*.(acos(-.1./.(e))))/.(float_of_int n) ) in
             for i=n downto 1 do
                let r = p/.(1. +. e*.(cos((!t)-.aap))) in
                let x = (r)*.(cos(!t))
                and y = (r)*.(sin(!t)) in
                liste := {x=(x+.(foyer.x));y=(y+.(foyer.y))}::(!liste);
                t := (!t)-.dt
             done;
      (!liste);;

      #branche_hyperbole : conique -> p_repere -> int -> p_repere list = <fun>

    2. Détermination de l'équation de la trajectoire.

      Hypothèses : On connaît trois points de la trajectoire finale et l'origine du repère est l'un des foyers de la conique.
      On détermine les équations des deux coniques de foyers (M1, M2) et(M2, M3) passant par l'origine, puis on crée les deux listes correspondant aux branches des hyperboles, on trouve leur intersection et enfin, on détermine l'équation finale à l'aide des fonctions ci-dessus.

Accueil > Trajectoire de comètes > Détermination de trajectoires