1 /*****************************************************************************\
2  * Lunar.h
3  *
4  * Lunar is a class that can calculate lunar fundmentals for any reasonable
5  * time.
6  *
7  * author: mark huss (mark@mhuss.com)
8  * Based on Bill Gray's open-source code at projectpluto.com
9  *
10 \*****************************************************************************/
11 
12 #if !defined( LUNAR__H )
13 #define LUNAR__H
14 
15 #include <math.h>
16 #include "AstroOps.h"
17 
18 // A struct to hold the fundmental elements
19 // The member names should be familiar to Meeus fans ;-)
20 //
21 struct LunarFundamentals {
22   double Lp;
23   double D;
24   double M;
25   double Mp;
26   double F;
27   double A1;
28   double A2;
29   double A3;
30   double T;
31 
LunarFundamentalsLunarFundamentals32   LunarFundamentals():Lp(0.),D(0.),M(0.),Mp(0.),F(0.),A1(0.),A2(0.),A3(0.),T(0.) {}
33 };
34 
35 // terms for longitude & radius
36 //
37 static const int N_LTERM1 = 60;
38 struct LunarTerms1 {
39   char d, m, mp, f;
40   long sl, sr;
41 };
42 
43 // terms for latitude
44 //
45 static const int N_LTERM2 = 60;
46 struct LunarTerms2 {
47   char d, m, mp, f;
48   long sb;
49 };
50 
51 // our main class -- calculates Lunar fundamentals, lat, lon & distance
52 //
53 class Lunar {
54 public:
55   // default c'tor
Lunar()56   Lunar() : m_initialized( false ), m_lon(-1.), m_lat(-1.), m_r(-1.)
57   {}
58 
59   // data & time c'tor
60   // t = decimal julian centuries
Lunar(double t)61   Lunar( double t )
62   {
63      calcFundamentals( t );
64   }
65 
66   static const double SYNODIC_MONTH = 29.530588861;
67 
68   double illuminatedFraction();
69 
70   static double ageOfMoonInDays( double jd );
71 
72 
73 
74   // calculates the fundamanentals given the time
75   // t = decimal julian centuries
76   //
77   void calcFundamentals( double t );
78 
79   //
80   // NOTE: calcFundamentals() must be called before calling the functions
81   //       below, or an invalid result (-1.) will be returned.
82   //
83 
84   double phaseAngle();
85   // returns lunar latitude
86   double latitude();         // returns -1 if not initialized
latitudeRadians()87   double latitudeRadians() {  // returns -1 if not initialized
88     return ( m_initialized ) ? Astro::toRadians( latitude() ) : -1.;
89   }
90 
91   // returns lunar longitude
longitude()92   double longitude()         // returns -1 if not initialized
93   {
94     if ( m_lon < 0. )
95       calcLonRad();
96     return m_lon;
97   }
98 
longitudeRadians()99   double longitudeRadians()  // returns -1 if not initialized
100   {
101     return ( m_initialized ) ? Astro::toRadians( longitude() ) : -1.;
102   }
103 
104   // returns lunar distance
radius()105   double radius()     // returns -1 if not initialized
106   {
107     if ( m_r < 0. )
108       calcLonRad();
109     return m_r;
110   }
111 
112   // calculate all three location elements of the spec'd body at the given time
113   //
calcAllLocs(double & lon,double & lat,double & rad,double t)114   void calcAllLocs(
115       double& lon,            // returned longitude
116       double& lat,            // returned latitude
117       double& rad,            // returned radius vector
118       double t)               // time in decimal centuries
119   {
120     calcFundamentals( t );
121     lon = longitudeRadians();
122     lat = latitudeRadians();
123     rad = radius();
124   }
125 
126 private:
127   // reduce (0 < d < 360) a positive angle and convert to radians
128   //
normalize(double d)129   double normalize( double d ) {
130     return Astro::toRadians( AstroOps::normalizeDegrees( d ) );
131   }
132 
133   // calculate an individual fundimental
134   //  tptr - points to array of doubles
135   //  t - time in decimal Julian centuries
136   //
137   double getFund( const double* tptr, double t );
138 
139   // calculate longitude and radius
140   //
141   // NOTE: calcFundamentals() must have been called first
142   //
143   void calcLonRad();
144 
145   // ***** data  *****
146 
147   // our calculated fundmentals
148   //
149   LunarFundamentals m_f;
150 
151   // true if calcFundamentals has been called
152   bool m_initialized;
153 
154   // longitude, latitude, and radius (stored in _degrees_)
155   double m_lon, m_lat, m_r;
156 };
157 
158 #endif  /* #if !defined( LUNAR__H ) */
159