Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Astronomie] Période synodique de la lune

Modèle mathématique

    14 juillet 2011 à 15:01:23

    Bonjour à tous,
    voilà, je souhaiterais trouver le modèle mathématique le plus proche de la réalité pour calculer les phases de la lune. Pour ce faire il faut connaître la période synodique de la lune (la durée séparant deux nouvelles lunes).

    On sait qu'elle est en moyenne de 29 jours, 12 heures, 44 minutes et 2,9 secondes, mais elle varie. Elle varie, car les orbites de la Terre autour du soleil et de la Lune autour de la Terre ne sont pas des cercles mais des ellipses. Cela implique qu'il y a des moments où la Terre est très proche du soleil (périhélie), sa vitesse est donc plus élevée car la force d'attraction du soleil est plus importante. De même il y a des moments où la Lune est le plus loin possible de la Terre (apogée).
    Lorsque c'est le cas (Terre en périhélie et Lune en apogée), la période synodique de la Lune (durée entre deux nouvelles lunes) est la plus longue possible.
    Lorsque c'est l'inverse (Terre en aphélie et Lune en périgée), la période synodique de la Lune est la plus courte possible.

    Dans tous les cas, elle est supérieure à 29 jours. Bref, elle oscille très régulièrement entre un maximum et un minimum, le milieu (moyenne) étant comme précédemment dit de 29 jours, 12 heures, 44 minutes et 2,9 secondes. Il me semble que cette oscillation a lieu tous les neuf ans (j'ai lu ça sur un article technique).


    Variations de la période synodique de la Lune


    Bref, puisque la NASA arrive à planifier si bien les phases de la lune ( http://eclipse.gsfc.nasa.gov/phase/phases2001.html ), je me dis qu'il ne doit pas être si compliqué que ça de trouver le modèle mathématique pour pouvoir calculer longtemps à l'avance.

    J'ai fait un programme pour tenter de calculer la prochaine pleine Lune. On donne une date de pleine Lune connue (j'en donne une de la NASA), et ça ajoute 29 jours, 12 heures, 44 minutes et 2,9 secondes. Ça n'est pas exact puisque la période varie, mais comme c'est une moyenne, on est toujours sur le bon jour ou vraiment pas loin (je veux dire l'imprécision ne fait pas que croître, après ça redevient précis puis imprécis, etc. Bref, on ne reste pas loin de la précision, puisque la courbe sinusoïdale tourne toujours autour de la droite centrale).



    Donc ma question est : quel est le modèle mathématique le plus précis à l'heure actuelle pour calculer la durée de la période synodique ?

    Je remercie d'avance les gens qui se pencheront sur mon problème. :)
    Bonne journée,
    DJ Fox
    • Partager sur Facebook
    • Partager sur Twitter
    Anonyme
      15 juillet 2011 à 11:55:52

      Bonjour,

      Citation


      Bref, puisque la NASA arrive à planifier si bien les phases de la lune ( http://eclipse.gsfc.nasa.gov/phase/phases2001.html ), je me dis qu'il ne doit pas être si compliqué que ça de trouver le modèle mathématique pour pouvoir calculer longtemps à l'avance.



      affirmation un peu rapide
      car contrairement à ce que l'on a souvent tendance à croire, le calcul des éphémérides de la lune est bien plus compliqué que celui des planètes. C'est parce que le problème Terre-Lune -Soleil est l'archétype du problème trois corps avec des interactions réciproques du même ordre de grandeur .
      On ne peut donc le traiter comme une orbite Képlerienne perturbée .
      Il n'y a aucune solution analytique simple même si on ne cherche pas une précision du type de celle visée par la NASA!
      Le calcul numérique utilise des développements en séries trigonométriques où les arguments sont fonction des variables moyennes et pour avoir une haute précision à long terme , on doit calcule plusieurs milliers de termes !
      Si on a une ambition plus modeste d'une prévision sur coutre période , on peut se contenter de quelques termes que l'on trouve dans certains ouvrages de mécanique céleste.
      Par exemple:
      Astronomie fondamentale
      Astronomie de position et mécanique céleste
      Gianni Pascoli chez Dunod

      Astronomy on the Personal computer
      Oliver Montenbruck
      Thomas Pfleger editions Springer
      ( lorsque je l'ai acheté il y a assez longtemps, en allemand ou en anglais seulement)
      Cet ouvrage est adapté pour un utilisateur qui veut aller assez loin dans sa propre programmation.
      Il founit de nombreux sous-programmes en turbo Pascal, avec CD associé
      A ce jour, j'ignore totalement si on le trouve toujours et avec le même support.
      Pour la lune les calculs n'atteignent pas la précision de la NASA mais il vont beaucoup plus loin que le précédent ouvrage

      Enfin selon ce que l'on veut faire, on peut toujours se référer aux éphémarides du Bureau des Longitudes , qui sont d'une trés haute précision .
      • Partager sur Facebook
      • Partager sur Twitter
        15 juillet 2011 à 12:20:37

        Bonjour,
        merci pour ta réponse. En fait j'ai trouvé hier ce que je cherchais : un algorithme assez précis avec lequel je trouve exactement les mêmes résultats que le site de la NASA. :)
        Et c'est exactement ce dont tu parles : il y a des développements trigonométriques. Par contre ce ne sont pas des milliers de termes. Il y en a moins de 100. On pourrait être encore plus précis en mettant des milliers de termes, mais ça devient ridicule. Je veux dire qu'avec cet algorithme j'ai déjà une précision de l'ordre de la minute pendant plus de cent ans.

        L'algorithme est expliqué ici : http://zpag.net/Calendrier/phase_moon_Algorithms.pdf
        Il s'agit du chapitre 47 du livre Astronomical algorithms de Jean Meeus.
        Ce PDF n'est qu'un extrait du livre et ne contient que le chapitre 47. Or, pour cet algorithme, pour pouvoir calculer E on a besoin de la formule 45.6, qui est au chapitre 45. J'ai été bloqué car je n'avais pas le chapitre 45, mais en fait j'ai trouvé le livre complet au format numérique.
        Si ça intéresse quelqu'un je poste ici cette formule 45.6 :
        <math>\(E = 1 - 0.002516 T - 0.0000074 T^2\)</math>


        L'algorithme a des facteurs de corrections différents pour calculer la nouvelle lune, le premier quartier, la pleine lune et le troisième quartier.

        C'est assez fastidieux à implémenter l'algorithme (absolument pas compliqué, mais c'est du recopiage fastidieux et on peut facilement faire une erreur).
        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          15 juillet 2011 à 14:43:20

          Bonjour,
          Tout dépend de ce que l'on cherche.
          Pour un usage personnel , quelques dizaine de termes sont effectivement suffisants pour une prévision correcte sur les durées que tu indiques.
          Mais sans parler de la NASA, les logiciels d'astronomie modernes pour le grand public ( j'utilise Redshift) ont des périodes de validité de plusieurs milliers d'années et leurs algorithmes lunaires contiennent trés certainement des milliers de termes pour rester dans une précision inférieur à la minute sur une telle durée!
          • Partager sur Facebook
          • Partager sur Twitter
            27 juillet 2011 à 21:08:34

            On ne pourrait pas trouver une valeur moyenne de sa période synodique très précises, du style à la milliseconde et qui permettrait d'approximer sa période pour un bon bout de temps ?

            Merci pour ces précisions qui m'intéressait aussi :) .

            DJ Fox, si tu t'intéresse de plus près à la Lune, j'avais fait un gros travail de recherche sur sa formation, enfin sa naissance :) .
            • Partager sur Facebook
            • Partager sur Twitter
            Id quad factum est, factum est.
            Anonyme
              27 juillet 2011 à 22:35:34

              Bonsoir,

              Citation

              On ne pourrait pas trouver une valeur moyenne de sa période synodique très précises, du style à la milliseconde et qui permettrait d'approximer sa période pour un bon bout de temps ?



              a priori la réponse est non
              La valeur moyenne n'est pas une donnée mais soit un résultat obtenu aprés l'étude du comportement du système, soit un résultat de mesure.
              La période moyenne est déjà connue avec une grande précison.
              On trouve dans les éphémérides 29,5305889j (! ) mais une moyenne, même à la milliseconde n'a jamais permis de remonter aux valeurs qui servent à la calculer.
              ( pour être imagé, ce n'est pas parce que l'on connaît au 1/10 de seconde sa vitesse moyenne sur un trajet en voiture que l'on est capable, avec cette seule information, de dire où on se trouvait à un instant donné du voyage)

              Mais les valeurs moyennes des principales périodes du mouvement (il y a aussi la rotation de la ligne des noeuds, la variation de l'inclinaison de l'orbite etc...) sont les arguments des fonctions trigonométriques des développements en série de fourier dont il est question dans les posts précédents.
              • Partager sur Facebook
              • Partager sur Twitter
                28 juillet 2011 à 1:33:09

                Merci pour cette explication, heureux d'en apprendre toujours plus :) .

                Une autre question me vient : le nombre de facteurs extérieurs pouvant déformer sa trajectoire n'est pas énorme, non :euh: ? Car dans ce cas je ne comprends pas pourquoi de tels algorithmes sont si lourd si on veut rentrer dans la précision.

                Bonne soirée :)
                • Partager sur Facebook
                • Partager sur Twitter
                Id quad factum est, factum est.
                Anonyme
                  28 juillet 2011 à 9:44:49

                  Bonjour,

                  Citation : Rafrite

                  Une autre question me vient : le nombre de facteurs extérieurs pouvant déformer sa trajectoire n'est pas énorme, non :euh: ? Car dans ce cas je ne comprends pas pourquoi de tels algorithmes sont si lourd si on veut rentrer dans la précision.

                  Bonne soirée :)

                  .


                  deux facteurs seulement, la terre et le soleil, cela suffit ! :p

                  explication: :euh:
                  En fait, pour obtenir ces complications, il suffit de considérer 3 corps en interaction gravitationnelle dans des conditions où on ne peut faire des simplifications acceptables.

                  Si on prend une planéte du système solaire, son mouvement est trés proche de celui obtenu par résolution du mouvement "deux corps" où on ne tient comte que de l'attraction solaire prépondérante . Les lois de Kepler découlent de cette hypothèse qui se ramène à un problème 2D résoluble analytiqement.
                  Compte tenu des masses et distances en jeu, l'influence des autres planètes sur la trajectoire est faible et peut être traitée par des méthodes de perturbations sur l'équation principale.
                  On obtient alors sans trop de difficultés un raffinement du calcul principal.(... c'est quand même lourd si on veut tenir compte de toutes les perturbabtions )

                  Avec la lune rien de tel, simplement parce que, compte tenu des masses et distances respectives en jeu , un simple calul avec la loi de l'attraction universelle montre que la lune subit des forces du même ordre de grandeur de la part de la terre et du soleil.

                  En se ramenant dans un référentiel centré sur le soleil, le mouvement se modélise par un système différentiel d'équations non linéaires couplées et aucune simplification acceptable ne permet de se ramener à une situation simple.

                  Le raffinement précédent pour les planétes ne marche pas. Si on se contente de traiter la lune comme en mouvement képlerien perturbé par le soleil, on obtient des résultats grossièrement faux. l'influence du soleil ne peut être considéré comme une perturbation.
                  Il résulte de tout cela que les paramètres de l'orbite lunaire sont en permanente évolution chacun avec des périodes spécifiques ( on parle des inégamités lunaires)

                  Les premiers calculs précis du mouvement lunaire datent du début du XXème siècle à une époque où il n'y avait pas d'orinateurs. Des centaines de termes de développement ont été calculés ...à la main.
                  En conclusion,
                  Comme il a été dit dans les posts précédents , l'importance des développements nécessaires dépend de la précision que l'on cherche.
                  Ecrire un logiciel avec quelques termes va donner sur une courte période une précision disons de 1' d'arc qui est a priori suffisante à l'astronome amateur pour retrouver la lune au bon endroit dans le ciel!
                  Sur une même période , les programmes les plus poussés vont donner une précision ingérieure à 1" d'arc, qui paraît superfétatoire !
                  application concréte: Un bon logiciel d'astronomie du commerce permet de trouver la configuration céleste sur des milliers d'années.
                  Avec la précision de 1', la lune ne sera certainement pas là où elle était si on observe le ciel à l'époque des pharaons ! :D
                  • Partager sur Facebook
                  • Partager sur Twitter
                    4 octobre 2011 à 4:56:12

                    Bonjour,

                    J'ai adapté un algorithme trouvé sur le net tiré de Jean Meeus.
                    J'obtiens donc les quatre principales phases de la lune.
                    Pour continuer mon programme, j'ai besoin de déterminer l'apogée, périgée, nœuds lunaires ainsi que les phases montantes/descendante pour un mois/année donné mais je ne trouve rien:(
                    (Ces informations sont destinées à des jardiniers)

                    Savez-vous si je peux déduire ces informations d'une des quatre phases?

                    Où puis-je trouver ces algorithmes?

                    J'ai également une autre question.
                    Je n'arrive pas à comprendre comment ce même algorithme peut déduire l'heure des phases lunaires sans qu'on lui indique notre position.

                    Merci
                    • Partager sur Facebook
                    • Partager sur Twitter
                      4 octobre 2011 à 9:36:11

                      Salut à tous,
                      si ça vous intéresse, je vous file mon programme que j'ai écrit en août dernier.
                      Je me suis simplement basé sur les formules du chapitre 47 du livre Astronomical algorithms de Jean Meeus. :)

                      //package moon;
                      
                      import java.io.IOException;
                      import java.util.Calendar;
                      import java.util.Locale;
                      import java.util.TimeZone;
                      
                      public class Moon
                      {
                          private static double NEW_MOON = 0, FIRST_QUARTER = 0.25, FULL_MOON = 0.5, LAST_QUARTER = 0.75;
                          
                          private static double k(double year, double phase)
                          {
                              if(phase != NEW_MOON && phase != FIRST_QUARTER && phase != FULL_MOON && phase != LAST_QUARTER)
                                  throw new IllegalArgumentException();
                              
                              return Math.round((year - 2000) * 12.3685) + phase;
                          }
                          
                          private static double T(double k)
                          {
                              return k / 1236.85;
                          }
                          
                          private static double initJDE(double k, double T)
                          {
                              return 2451550.09765 + 29.530588853 * k + 0.0001337 * Math.pow(T, 2) - 0.000000150 * Math.pow(T, 3) + 0.00000000073 * Math.pow(T, 4);
                          }
                          
                          private static double E(double T)
                          {
                              return 1 - 0.002516 * T - 0.0000074 * Math.pow(T, 2);
                          }
                          
                          private static double M(double k, double T)
                          {
                              double M = (2.5534 + 29.10535669 * k - 0.0000218 * Math.pow(T, 2) - 0.00000011 * Math.pow(T, 3)) % 360;
                              return (M < 0) ? M + 360 : M;
                          }
                          
                          private static double Mprime(double k, double T)
                          {
                              double Mprime = (201.5643 + 385.81693528 * k + 0.0107438 * Math.pow(T, 2) + 0.00001239 * Math.pow(T, 3) - 0.000000058 * Math.pow(T, 4)) % 360;
                              return (Mprime < 0) ? Mprime + 360 : Mprime;
                          }
                          
                          private static double F(double k, double T)
                          {
                              double F = (160.7108 + 390.67050274 * k - 0.0016341 * Math.pow(T, 2) - 0.00000227 * Math.pow(T, 3) + 0.000000011 * Math.pow(T, 4)) % 360;
                              return (F < 0) ? F + 360 : F;
                          }
                          
                          private static double omega(double k, double T)
                          {
                              double omega = (124.7746 - 1.56375580 * k + 0.0020691 * Math.pow(T, 2) + 0.00000215 * Math.pow(T, 3)) % 360;
                              return (omega < 0) ? omega + 360 : omega;
                          }
                          
                          private static double correctionNewMoon(double E, double Mprime, double F, double M, double omega)
                          {
                              double correction;
                              correction = -0.40720 *                     Math.sin(Math.toRadians(Mprime));
                              correction += 0.17241 * E *                 Math.sin(Math.toRadians(M));
                              correction += 0.01608 *                     Math.sin(2 * Math.toRadians(Mprime));
                              correction += 0.01039 *                     Math.sin(2 * Math.toRadians(F));
                              correction += 0.00739 * E *                 Math.sin(Math.toRadians(Mprime - M));
                              correction -= 0.00514 * E *                 Math.sin(Math.toRadians(Mprime + M));
                              correction += 0.00208 * Math.pow(E, 2) *    Math.sin(2 * Math.toRadians(M));
                              correction -= 0.00111 *                     Math.sin(Math.toRadians(Mprime) - 2 * Math.toRadians(F));
                              correction -= 0.00057 *                     Math.sin(Math.toRadians(Mprime) + 2 * Math.toRadians(F));
                              correction += 0.00056 * E *                 Math.sin(2 * Math.toRadians(Mprime) + Math.toRadians(M));
                              correction -= 0.00042 *                     Math.sin(3 * Math.toRadians(Mprime));
                              correction += 0.00042 * E *                 Math.sin(Math.toRadians(M) + 2 * Math.toRadians(F));
                              correction += 0.00038 * E *                 Math.sin(Math.toRadians(M) - 2 * Math.toRadians(F));
                              correction -= 0.00024 * E *                 Math.sin(2 * Math.toRadians(Mprime) - Math.toRadians(M));
                              correction -= 0.00017 *                     Math.sin(Math.toRadians(omega));
                              correction -= 0.00007 *                     Math.sin(Math.toRadians(Mprime) + 2 * Math.toRadians(M));
                              correction += 0.00004 *                     Math.sin(2 * Math.toRadians(Mprime) - 2 * Math.toRadians(F));
                              correction += 0.00004 *                     Math.sin(3 * Math.toRadians(M));
                              correction += 0.00003 *                     Math.sin(Math.toRadians(Mprime) + Math.toRadians(M) - 2 * Math.toRadians(F));
                              correction += 0.00003 *                     Math.sin(2 * Math.toRadians(Mprime) + 2 * Math.toRadians(F));
                              correction -= 0.00003 *                     Math.sin(Math.toRadians(Mprime) + Math.toRadians(M) + 2 * (Math.toRadians(F)));
                              correction += 0.00003 *                     Math.sin(Math.toRadians(Mprime) - Math.toRadians(M) + 2 * (Math.toRadians(F)));
                              correction -= 0.00002 *                     Math.sin(Math.toRadians(Mprime) - Math.toRadians(M) - 2 * (Math.toRadians(F)));
                              correction -= 0.00002 *                     Math.sin(3 * Math.toRadians(Mprime) + Math.toRadians(M));
                              correction += 0.00002 *                     Math.sin(4 * Math.toRadians(Mprime));
                              return correction;
                          }
                          
                          private static double correctionFullMoon(double E, double Mprime, double F, double M, double omega)
                          {
                              double correction;
                              correction = -0.40614 *                     Math.sin(Math.toRadians(Mprime));
                              correction += 0.17302 * E *                 Math.sin(Math.toRadians(M));
                              correction += 0.01614 *                     Math.sin(2 * Math.toRadians(Mprime));
                              correction += 0.01043 *                     Math.sin(2 * Math.toRadians(F));
                              correction += 0.00734 * E *                 Math.sin(Math.toRadians(Mprime - M));
                              correction -= 0.00515 * E *                 Math.sin(Math.toRadians(Mprime + M));
                              correction += 0.00209 * Math.pow(E, 2) *    Math.sin(2 * Math.toRadians(M));
                              correction -= 0.00111 *                     Math.sin(Math.toRadians(Mprime) - 2 * Math.toRadians(F));
                              correction -= 0.00057 *                     Math.sin(Math.toRadians(Mprime) + 2 * Math.toRadians(F));
                              correction += 0.00056 * E *                 Math.sin(2 * Math.toRadians(Mprime) + Math.toRadians(M));
                              correction -= 0.00042 *                     Math.sin(3 * Math.toRadians(Mprime));
                              correction += 0.00042 * E *                 Math.sin(Math.toRadians(M) + 2 * Math.toRadians(F));
                              correction += 0.00038 * E *                 Math.sin(Math.toRadians(M) - 2 * Math.toRadians(F));
                              correction -= 0.00024 * E *                 Math.sin(2 * Math.toRadians(Mprime) - Math.toRadians(M));
                              correction -= 0.00017 *                     Math.sin(Math.toRadians(omega));
                              correction -= 0.00007 *                     Math.sin(Math.toRadians(Mprime) + 2 * Math.toRadians(M));
                              correction += 0.00004 *                     Math.sin(2 * Math.toRadians(Mprime) - 2 * Math.toRadians(F));
                              correction += 0.00004 *                     Math.sin(3 * Math.toRadians(M));
                              correction += 0.00003 *                     Math.sin(Math.toRadians(Mprime) + Math.toRadians(M) - 2 * Math.toRadians(F));
                              correction += 0.00003 *                     Math.sin(2 * Math.toRadians(Mprime) + 2 * Math.toRadians(F));
                              correction -= 0.00003 *                     Math.sin(Math.toRadians(Mprime) + Math.toRadians(M) + 2 * (Math.toRadians(F)));
                              correction += 0.00003 *                     Math.sin(Math.toRadians(Mprime) - Math.toRadians(M) + 2 * (Math.toRadians(F)));
                              correction -= 0.00002 *                     Math.sin(Math.toRadians(Mprime) - Math.toRadians(M) - 2 * (Math.toRadians(F)));
                              correction -= 0.00002 *                     Math.sin(3 * Math.toRadians(Mprime) + Math.toRadians(M));
                              correction += 0.00002 *                     Math.sin(4 * Math.toRadians(Mprime));
                              return correction;
                          }
                          
                          private static double correctionFirstLastQuarter(double E, double Mprime, double F, double M, double omega)
                          {
                              double correction;
                              correction = -0.62801 *                     Math.sin(Math.toRadians(Mprime));
                              correction += 0.17172 * E *                 Math.sin(Math.toRadians(M));
                              correction -= 0.01183 * E *                 Math.sin(Math.toRadians(Mprime) + Math.toRadians(M));
                              correction += 0.00862 *                     Math.sin(2 * Math.toRadians(Mprime));
                              correction += 0.00804 *                     Math.sin(2 * Math.toRadians(F));
                              correction += 0.00454 * E *                 Math.sin(Math.toRadians(Mprime - M));
                              correction += 0.00204 * Math.pow(E, 2) *    Math.sin(2 * Math.toRadians(M));
                              correction -= 0.00180 *                     Math.sin(Math.toRadians(Mprime) - 2 * Math.toRadians(F));
                              correction -= 0.00070 *                     Math.sin(Math.toRadians(Mprime) + 2 * Math.toRadians(F));
                              correction -= 0.00040 *                     Math.sin(3 * Math.toRadians(Mprime));
                              correction -= 0.00034 * E *                 Math.sin(2 * Math.toRadians(Mprime) - Math.toRadians(M));
                              correction += 0.00032 * E *                 Math.sin(Math.toRadians(M) + 2 * Math.toRadians(F));
                              correction += 0.00032 * E *                 Math.sin(Math.toRadians(M) - 2 * Math.toRadians(F));
                              correction -= 0.00028 * Math.pow(E, 2) *    Math.sin(Math.toRadians(Mprime) + 2 * Math.toRadians(M));
                              correction += 0.00027 * E *                 Math.sin(2 * Math.toRadians(Mprime) + Math.toRadians(M));
                              correction -= 0.00017 *                     Math.sin(Math.toRadians(omega));
                              correction -= 0.00005 *                     Math.sin(Math.toRadians(Mprime) - Math.toRadians(M) - 2 * Math.toRadians(F));
                              correction += 0.00004 *                     Math.sin(2 * Math.toRadians(Mprime) + 2 * Math.toRadians(F));
                              correction -= 0.00004 *                     Math.sin(Math.toRadians(Mprime) + Math.toRadians(M) + 2 * Math.toRadians(F));
                              correction += 0.00004 *                     Math.sin(Math.toRadians(Mprime) - 2 * Math.toRadians(M));
                              correction += 0.00003 *                     Math.sin(Math.toRadians(Mprime) + Math.toRadians(M) - 2 * (Math.toRadians(F)));
                              correction += 0.00003 *                     Math.sin(3 * Math.toRadians(M));
                              correction += 0.00002 *                     Math.sin(2 * Math.toRadians(Mprime) - 2 * (Math.toRadians(F)));
                              correction += 0.00002 *                     Math.sin(Math.toRadians(Mprime) - Math.toRadians(M) + 2 * Math.toRadians(F));
                              correction -= 0.00002 *                     Math.sin(3 * Math.toRadians(Mprime) + Math.toRadians(M));
                              return correction;
                          }
                          
                          private static double w(double E, double M, double Mprime, double F)
                          {
                              return 0.00306 - 0.00038 * E * Math.cos(Math.toRadians(M)) + 0.00026 * Math.cos(Math.toRadians(Mprime)) - 0.00002 * Math.cos(Math.toRadians(Mprime - M)) + 0.00002 * Math.cos(Math.toRadians(Mprime + M)) + 0.00002 * Math.cos(2 * Math.toRadians(F));
                          }
                          
                          private static double globalCorrection(double k, double T)
                          {
                              double A1  = 299.77 + 0.107408 * k - 0.009173 * Math.pow(T, 2);
                              double A2 = 251.88 + 0.016321 * k;
                              double A3 = 251.83 + 26.651886 * k;
                              double A4 = 349.42 + 36.412478 * k;
                              double A5 = 84.66 + 18.206239 * k;
                              double A6 = 141.74 + 53.303771 * k;
                              double A7 = 207.14 + 2.453732 * k;
                              double A8 = 154.84 + 7.306860 * k;
                              double A9 = 34.52 + 27.261239 * k;
                              double A10 = 207.19 + 0.121824 * k;
                              double A11 = 291.34 + 1.844379 * k;
                              double A12 = 161.72 + 24.198154 * k;
                              double A13 = 239.56 + 25.513099 * k;
                              double A14 = 331.55 + 3.592518 * k;
                              
                              double correction = 0;
                              correction += 0.000325 * Math.sin(Math.toRadians(A1));
                              correction += 0.000165 * Math.sin(Math.toRadians(A2));
                              correction += 0.000164 * Math.sin(Math.toRadians(A3));
                              correction += 0.000126 * Math.sin(Math.toRadians(A4));
                              correction += 0.000110 * Math.sin(Math.toRadians(A5));
                              correction += 0.000062 * Math.sin(Math.toRadians(A6));
                              correction += 0.000060 * Math.sin(Math.toRadians(A7));
                              
                              correction += 0.000056 * Math.sin(Math.toRadians(A8));
                              correction += 0.000047 * Math.sin(Math.toRadians(A9));
                              correction += 0.000042 * Math.sin(Math.toRadians(A10));
                              correction += 0.000040 * Math.sin(Math.toRadians(A11));
                              correction += 0.000037 * Math.sin(Math.toRadians(A12));
                              correction += 0.000035 * Math.sin(Math.toRadians(A13));
                              correction += 0.000023 * Math.sin(Math.toRadians(A14));
                              
                              return correction;
                          }
                          
                          public static int deltaT(int year)
                          {
                              double t = (double)(year - 1820) / (double)100;
                              double deltaT = -20 + 32 * Math.pow(t, 2);
                              return (int)Math.round(deltaT);
                          }
                          
                          public static Calendar getMoonPhaseNearDate(int year, int month, double phase)
                          {
                              double finalYear = year + (double)(month - 1) / (double)12;
                              
                              double k = k(finalYear, phase);
                              double T = T(k);
                              double initJDE = initJDE(k, T);
                              double E = E(T);
                              double M = M(k, T);
                              double Mprime = Mprime(k, T);
                              double F = F(k, T);
                              double omega = omega(k, T);
                              
                              double correction = 0;
                              if(phase == NEW_MOON)
                                  correction += correctionNewMoon(E, Mprime, F, M, omega);
                              else if(phase == FULL_MOON)
                                  correction += correctionFullMoon(E, Mprime, F, M, omega);
                              else
                              {
                                  correction += correctionFirstLastQuarter(E, Mprime, F, M, omega);
                                  double w = w(E, M, Mprime, F);
                                  if(phase == FIRST_QUARTER)
                                      correction += w;
                                  else if(phase == LAST_QUARTER)
                                      correction -= w;
                                  else
                                      throw new IllegalArgumentException();
                              }
                              
                              correction += Moon.globalCorrection(k, T);
                      
                              return julien2Date(initJDE + correction);
                          }
                              
                          private static Calendar julien2Date(double JJ)
                          {
                               int aaaa = 0;
                               int mm = 0;
                               int jj = 0;
                               int hh = 0;
                               int mn = 0;
                               int ss = 0;
                               int A = 0;
                               double w = JJ + 0.5;
                               int Z = (int)w;
                               double F = w - Z;
                               
                               if (Z < 2299161)
                               {
                                   A = Z;
                               }
                               else
                               {
                                   int alpha = (int)((Z - 1867216.25) / 36524.25);
                                   A = Z + 1 + alpha - (int)(alpha / 4.0);
                               }
                               
                               int B = A + 1524;
                               int C = (int)((B - 122.1) / 365.25);
                               int D = (int)(365.25 * C);
                               int E = (int)((B - D) / 30.6001);
                               // jour du mois en décimales
                               double jjd = B - D - (int)(30.6001 * E) + F;
                               jj = (int)jjd;
                               // Calcul heure
                               double hhd = jjd - jj;
                               hh = (int)(24 * hhd);
                               // Calcul minutes
                               double mnd = (24 * hhd) - hh;
                               mn = (int)(60 * mnd);
                               // Calcul secondes
                               double ssd = (60 * mnd) - mn;
                               ss = (int)(60 * ssd);
                               // Calcul mois
                               if (E < 13.5)
                               {
                                   mm = E - 1;
                               }
                               else
                               {
                                   mm = E - 13;
                               }
                               // Calcul année
                               if (mm > 2.5)
                               {
                                   aaaa = C - 4716;
                               }
                               else
                               {
                                   aaaa = C - 4715;
                               }
                               
                               Calendar myCalendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
                               myCalendar.set(aaaa, mm - 1, jj, hh, mn, ss);
                               return myCalendar;
                           }
                          
                          public static void displayCalendar(Calendar calendar)
                          {
                              System.out.print(calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.FRENCH));
                              System.out.print(" ");
                              
                              System.out.print(calendar.get(Calendar.DAY_OF_MONTH));
                              System.out.print(" ");
                              
                              System.out.print(calendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.FRENCH));
                              System.out.print(" ");
                              
                              System.out.print(calendar.get(Calendar.YEAR));
                              System.out.print(" ");
                              
                              System.out.print((calendar.get(Calendar.HOUR_OF_DAY) < 10) ? "0" + calendar.get(Calendar.HOUR_OF_DAY) : calendar.get(Calendar.HOUR_OF_DAY));
                              System.out.print("H");
                              
                              System.out.print((calendar.get(Calendar.MINUTE) < 10) ? "0" + calendar.get(Calendar.MINUTE) : calendar.get(Calendar.MINUTE));
                              System.out.print(":");
                              
                              System.out.print((calendar.get(Calendar.SECOND) < 10) ? "0" + calendar.get(Calendar.SECOND) : calendar.get(Calendar.SECOND));
                          }
                          
                          public static void displayCalendarln(Calendar calendar)
                          {
                              displayCalendar(calendar);
                              System.out.println();
                          }
                          
                          private static Calendar[] getPhasesDate(Calendar now)
                          {
                              Calendar[] result = new Calendar[5];
                              
                              Calendar nextMonth = (Calendar)now.clone();
                              nextMonth.add(Calendar.MONTH, 1);
                              
                              Calendar newMoonUTC = Moon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, Moon.NEW_MOON);
                              Calendar firstQuarterUTC = Moon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, Moon.FIRST_QUARTER);
                              Calendar fullMoonUTC = Moon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, Moon.FULL_MOON);
                              Calendar lastQuarterUTC = Moon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH) + 1, Moon.LAST_QUARTER);
                              Calendar nextNewMoonUTC = Moon.getMoonPhaseNearDate(nextMonth.get(Calendar.YEAR), nextMonth.get(Calendar.MONTH) + 1, Moon.NEW_MOON);
                              
                              result[0] = Calendar.getInstance(); result[0].setTimeInMillis(newMoonUTC.getTimeInMillis());
                              result[1] = Calendar.getInstance(); result[1].setTimeInMillis(firstQuarterUTC.getTimeInMillis());
                              result[2] = Calendar.getInstance(); result[2].setTimeInMillis(fullMoonUTC.getTimeInMillis());
                              result[3] = Calendar.getInstance(); result[3].setTimeInMillis(lastQuarterUTC.getTimeInMillis());
                              result[4] = Calendar.getInstance(); result[4].setTimeInMillis(nextNewMoonUTC.getTimeInMillis());
                              
                              if(now.before(result[0]))
                              {
                                  Calendar nowCopy = (Calendar)now.clone();
                                  nowCopy.add(Calendar.DAY_OF_MONTH, -1);
                                  result = getPhasesDate(nowCopy);
                              }
                              else if(now.after(result[4]))
                              {
                                  Calendar nowCopy = (Calendar)now.clone();
                                  nowCopy.add(Calendar.DAY_OF_MONTH, +1);
                                  result = getPhasesDate(nowCopy);
                              }
                              
                              return result;
                          }
                          
                          private static String getPhaseText(Calendar now, Calendar[] phases)
                          {
                              if(now.get(Calendar.DAY_OF_MONTH) == phases[0].get(Calendar.DAY_OF_MONTH) || now.get(Calendar.DAY_OF_MONTH) == phases[0].get(Calendar.DAY_OF_MONTH))
                                  return "Nouvelle Lune";
                              else if(now.get(Calendar.DAY_OF_MONTH) == phases[1].get(Calendar.DAY_OF_MONTH))
                                  return "Premier quartier";
                              else if(now.get(Calendar.DAY_OF_MONTH) == phases[2].get(Calendar.DAY_OF_MONTH))
                                  return "Pleine Lune";
                              else if(now.get(Calendar.DAY_OF_MONTH) == phases[3].get(Calendar.DAY_OF_MONTH))
                                  return "Dernier quartier";
                              else if(now.get(Calendar.DAY_OF_MONTH) == phases[4].get(Calendar.DAY_OF_MONTH))
                                  return "Nouvelle Lune";
                      
                              else if(now.after(phases[0]) && now.before(phases[1]))
                                  return "Premier croissant";
                              else if(now.after(phases[1]) && now.before(phases[2]))
                                  return "Gibbeuse croissante";
                              else if(now.after(phases[2]) && now.before(phases[3]))
                                  return "Gibbeuse décroissante";
                              else if(now.after(phases[3]) && now.before(phases[4]))
                                  return "Dernier croissant";
                              else
                                  throw new IllegalArgumentException();
                          }
                          
                          private static String getAgeText(long phaseElaspedTime)
                          {
                              long numerateurCopy = phaseElaspedTime;
                              
                              int ageJour = (int)Math.floor((double)phaseElaspedTime / (double)(1000 * 60 * 60 * 24));
                              numerateurCopy -= (ageJour * 24 * 60 * 60 * 1000);
                              int ageHeures = (int)Math.floor((double)numerateurCopy / (double)(1000 * 60 * 60));
                              numerateurCopy -= (ageHeures * 60 * 60 * 1000);
                              int ageMinutes = (int)Math.floor((double)numerateurCopy / (double)(1000 * 60));
                              numerateurCopy -= (ageMinutes * 60 * 1000);
                              int ageSecondes = (int)Math.floor((double)numerateurCopy / (double)(1000));
                              
                              return "Âge : " + ageJour + "j " + ageHeures + "h " + ageMinutes + "min " + ageSecondes + "s";
                          }
                              
                          private static double getPercentage(Calendar now, Calendar[] phaseDates)
                          {
                              double percentage = 0;
                              
                              if(now.after(phaseDates[0]) && now.before(phaseDates[1]))
                                  percentage = 0 + (double)(now.getTime().getTime() - phaseDates[0].getTime().getTime()) / (double)(phaseDates[1].getTime().getTime() - phaseDates[0].getTime().getTime()) * 25;
                              else if(now.after(phaseDates[1]) && now.before(phaseDates[2]))
                                  percentage = 25 + (double)(now.getTime().getTime() - phaseDates[1].getTime().getTime()) / (double)(phaseDates[2].getTime().getTime() - phaseDates[1].getTime().getTime()) * 25;
                              else if(now.after(phaseDates[2]) && now.before(phaseDates[3]))
                                  percentage = 50 + (double)(now.getTime().getTime() - phaseDates[2].getTime().getTime()) / (double)(phaseDates[3].getTime().getTime() - phaseDates[2].getTime().getTime()) * 25;
                              else if(now.after(phaseDates[3]) && now.before(phaseDates[4]))
                                  percentage = 75 + (double)(now.getTime().getTime() - phaseDates[3].getTime().getTime()) / (double)(phaseDates[4].getTime().getTime() - phaseDates[3].getTime().getTime()) * 25;
                              
                              return percentage;
                          }
                          
                          private static double getPercentageIlluminated(double percentage)
                          {
                              percentage *= 2;
                              if(percentage > 100)
                                  percentage = 100 - percentage % 100;
                              
                              return percentage;
                          }
                          
                          public static void displayInformations()
                          {
                              displayInformations(Calendar.getInstance());
                          }
                          
                          public static void displayInformations(Calendar now)
                          {
                              Calendar[] phases = getPhasesDate(now);
                              
                              System.out.print("Date courante : "); displayCalendarln(now); System.out.println();
                              
                              System.out.println("Phase en cours : " + getPhaseText(now, phases));
                              System.out.println("Pourcentage : " + getPercentage(now, phases));
                              System.out.println("Pourcentage illuminé de la face visible : " + getPercentageIlluminated(getPercentage(now, phases)));
                              System.out.println(getAgeText(now.getTime().getTime() - phases[0].getTime().getTime())); System.out.println();
                              
                              System.out.print("Nouvelle Lune : "); displayCalendarln(phases[0]);
                              System.out.print("Premier quartier : "); displayCalendarln(phases[1]);
                              System.out.print("Pleine Lune : "); displayCalendarln(phases[2]);
                              System.out.print("Dernier quartier : "); displayCalendarln(phases[3]);
                              System.out.print("Prochaine nouvelle Lune : "); displayCalendarln(phases[4]); System.out.println();
                          }
                      
                          public static void main(String args[]) throws InterruptedException, IOException
                          {
                              Calendar myCalendar = Calendar.getInstance();
                              myCalendar.set(2011, 6, 15, 22, 40, 57);
                              Moon.displayInformations(myCalendar);
                              /*while(true)
                              {
                                  Moon.displayInformations(myCalendar);
                                  Thread.sleep(500);
                                  System.out.println(((char) 27)+"[2J");
                              }*/
                          }
                      }
                      
                      • Partager sur Facebook
                      • Partager sur Twitter
                        4 octobre 2011 à 21:26:24

                        Merci beaucoup pour ce source.

                        Testé et vraiment nickel (1 minute de diff. avec la NASA parfois).
                        Propre, prêt à l'emploi, très bon travail.

                        Seul regret, ne pas y trouver les informations qu'il me manque.

                        Plusieurs sites de jardinage arrivent à afficher l'apogée, périgée, nœuds lunaires ainsi que les phases montantes/descendante, comment font-ils?
                        • Partager sur Facebook
                        • Partager sur Twitter
                          5 octobre 2011 à 13:23:27

                          D'ailleurs comme le signale marcelo95, il y a une erreur dans le code. Ce n'est pas bien grave mais l'âge de la Lune ressemble parfois à ceci : 28j 1204h 71585min 4295020s.

                          Ça n'est pas bien important et devrait pouvoir se corriger facilement.

                          Aucune idée pour les détails que tu demandes de calculer. Il faudrait creuser dans des livres ou éventuellement sur des articles scientifiques sur Internet.
                          • Partager sur Facebook
                          • Partager sur Twitter
                            7 octobre 2011 à 0:05:41

                            Salut,

                            pour corriger l'erreur, remplacer la méthode phaseElaspedTime par :
                            private static String getAgeText(long phaseElaspedTime)
                                {
                                    long numerateurCopy = phaseElaspedTime;
                            
                            	long ageJour = numerateurCopy / (1000 * 60 * 60 * 24);
                            	numerateurCopy -= ageJour * 24 * 60 * 60 * 1000;
                            	
                            	long ageHeures = numerateurCopy / (1000 * 60 * 60);
                            	numerateurCopy -= ageHeures * 60 * 60 * 1000;
                            	
                            	long ageMinutes = numerateurCopy / (1000 * 60);
                            	numerateurCopy -= ageMinutes * 60 * 1000;
                            
                            	long ageSecondes = numerateurCopy / 1000;
                            	numerateurCopy -= ageSecondes * 1000;
                                    
                                    return "Âge : " + ageJour + "j " + ageHeures + "h " + ageMinutes + "min " + ageSecondes + "s";
                                }
                            


                            On notera une faute d'inattention pour le mot « elasped » qui n'existe pas en anglais. :-°
                            • Partager sur Facebook
                            • Partager sur Twitter
                              13 juin 2013 à 16:23:03

                              Merci pour ce code, juste pour apporter ma mini pierre à l'édifice, certains problèmes de prévisions surviennent à certaines dates, exemple avec la date lundi 2 avril 2012 22H40:57 par exemple

                              On trouve:

                              Nouvelle Lune : mardi 21 février 2012 23H35:51

                              Premier quartier : jeudi 1 mars 2012 02H22:42

                              Pleine Lune : jeudi 8 mars 2012 10H40:37

                              Dernier quartier : jeudi 15 mars 2012 02H26:14

                              Prochaine nouvelle Lune : samedi 21 avril 2012 09H19:34

                              Au lieu de :

                              Nouvelle Lune : jeudi 22 mars 2012 15H38:17

                              Premier quartier : vendredi 30 mars 2012 21H41:58

                              Pleine Lune : vendredi 6 avril 2012 21H19:44

                              Dernier quartier : vendredi 13 avril 2012 12H50:44

                              Prochaine nouvelle Lune : samedi 21 avril 2012 09H19:34

                              Le fix est de passer le nombre de jour relatif par an au lieu du nombre de mois

                                   
                              
                                      Calendar newMoonUTC =  JavaApplicationTestMoon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.DAY_OF_YEAR),  JavaApplicationTestMoon.NEW_MOON);
                              
                                      Calendar firstQuarterUTC =  JavaApplicationTestMoon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.DAY_OF_YEAR),  JavaApplicationTestMoon.FIRST_QUARTER);
                              
                                      Calendar fullMoonUTC =  JavaApplicationTestMoon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.DAY_OF_YEAR),  JavaApplicationTestMoon.FULL_MOON);
                              
                                      Calendar lastQuarterUTC =  JavaApplicationTestMoon.getMoonPhaseNearDate(now.get(Calendar.YEAR), now.get(Calendar.DAY_OF_YEAR),  JavaApplicationTestMoon.LAST_QUARTER);
                              
                                      Calendar nextNewMoonUTC =  JavaApplicationTestMoon.getMoonPhaseNearDate(nextMonth.get(Calendar.YEAR), nextMonth.get(Calendar.DAY_OF_YEAR),  JavaApplicationTestMoon.NEW_MOON);
                              
                                       
                              
                              .... // et modifier la fonction
                              
                              
                              
                              
                                  public static Calendar getMoonPhaseNearDate(int year, int day_of_year, double phase)
                              
                                  {
                              
                                      double finalYear = year + (double)(day_of_year - 1) / (double)365;
                              
                              

                              Super code en tout cas, merci pour le partage

                              Précis à +-1 min avec les prévisions de la NASA

                              Ti-R

                              -
                              Edité par WhiteDragon 13 juin 2013 à 16:27:53

                              • Partager sur Facebook
                              • Partager sur Twitter

                              [Astronomie] Période synodique de la lune

                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                              • Editeur
                              • Markdown