1 | #include <libnova/solar.h>
|
---|
2 | #include <libnova/lunar.h>
|
---|
3 | #include <libnova/rise_set.h>
|
---|
4 | #include <libnova/transform.h>
|
---|
5 |
|
---|
6 | #include "Time.h"
|
---|
7 | #include "Configuration.h"
|
---|
8 |
|
---|
9 | using namespace std;
|
---|
10 |
|
---|
11 | // ------------------------------------------------------------------------
|
---|
12 |
|
---|
13 | class Moon
|
---|
14 | {
|
---|
15 | public:
|
---|
16 | Time time;
|
---|
17 |
|
---|
18 | double ra;
|
---|
19 | double dec;
|
---|
20 |
|
---|
21 | double zd;
|
---|
22 | double az;
|
---|
23 |
|
---|
24 | double disk;
|
---|
25 |
|
---|
26 | bool visible;
|
---|
27 |
|
---|
28 | Time fRise;
|
---|
29 | Time fTransit;
|
---|
30 | Time fSet;
|
---|
31 |
|
---|
32 | int state;
|
---|
33 |
|
---|
34 | Moon() : time(Time::none)
|
---|
35 | {
|
---|
36 | }
|
---|
37 |
|
---|
38 | // Could be done more efficient: Only recalcuate if
|
---|
39 | // the current time exceeds at least on of the stored times
|
---|
40 | Moon(double lon, double lat, const Time &t=Time()) : time(t)
|
---|
41 | {
|
---|
42 | const double JD = time.JD();
|
---|
43 |
|
---|
44 | ln_lnlat_posn observer;
|
---|
45 | observer.lng = lon;
|
---|
46 | observer.lat = lat;
|
---|
47 |
|
---|
48 | ln_rst_time moon;
|
---|
49 | ln_get_lunar_rst(JD-0.5, &observer, &moon);
|
---|
50 |
|
---|
51 | fRise = Time(moon.rise);
|
---|
52 | fTransit = Time(moon.transit);
|
---|
53 | fSet = Time(moon.set);
|
---|
54 |
|
---|
55 | //visible =
|
---|
56 | // ((JD>moon.rise && JD<moon.set ) && moon.rise<moon.set) ||
|
---|
57 | // ((JD<moon.set || JD>moon.rise) && moon.rise>moon.set);
|
---|
58 |
|
---|
59 | const bool is_up = JD>moon.rise;
|
---|
60 | const bool is_sinking = JD>moon.transit;
|
---|
61 | const bool is_dn = JD>moon.set;
|
---|
62 |
|
---|
63 | ln_get_lunar_rst(JD+0.5, &observer, &moon);
|
---|
64 | if (is_up)
|
---|
65 | fRise = Time(moon.rise);
|
---|
66 | if (is_sinking)
|
---|
67 | fTransit = Time(moon.transit);
|
---|
68 | if (is_dn)
|
---|
69 | fSet = Time(moon.set);
|
---|
70 |
|
---|
71 | ln_equ_posn pos;
|
---|
72 | ln_get_lunar_equ_coords(JD, &pos);
|
---|
73 |
|
---|
74 | ln_hrz_posn hrz;
|
---|
75 | ln_get_hrz_from_equ (&pos, &observer, JD, &hrz);
|
---|
76 | az = hrz.az;
|
---|
77 | zd = 90-hrz.alt;
|
---|
78 |
|
---|
79 | ra = pos.ra/15;
|
---|
80 | dec = pos.dec;
|
---|
81 |
|
---|
82 | disk = ln_get_lunar_disk(JD)*100;
|
---|
83 | state = 0;
|
---|
84 | if (fRise <fTransit && fRise <fSet) state = 0; // not visible
|
---|
85 | if (fTransit<fSet && fTransit<fRise) state = 1; // before culm
|
---|
86 | if (fSet <fRise && fSet <fTransit) state = 2; // after culm
|
---|
87 |
|
---|
88 | visible = state!=0;
|
---|
89 |
|
---|
90 | // 0: not visible
|
---|
91 | // 1: visible before cul
|
---|
92 | // 2: visible after cul
|
---|
93 | }
|
---|
94 |
|
---|
95 | double Angle(double r, double d) const
|
---|
96 | {
|
---|
97 | const double theta0 = M_PI/2-d*M_PI/180;
|
---|
98 | const double phi0 = r*M_PI/12;
|
---|
99 |
|
---|
100 | const double theta1 = M_PI/2-dec*M_PI/180;
|
---|
101 | const double phi1 = ra*M_PI/12;
|
---|
102 |
|
---|
103 | const double x0 = sin(theta0) * cos(phi0);
|
---|
104 | const double y0 = sin(theta0) * sin(phi0);
|
---|
105 | const double z0 = cos(theta0);
|
---|
106 |
|
---|
107 | const double x1 = sin(theta1) * cos(phi1);
|
---|
108 | const double y1 = sin(theta1) * sin(phi1);
|
---|
109 | const double z1 = cos(theta1);
|
---|
110 |
|
---|
111 | double arg = x0*x1 + y0*y1 + z0*z1;
|
---|
112 | if(arg > 1.0) arg = 1.0;
|
---|
113 | if(arg < -1.0) arg = -1.0;
|
---|
114 |
|
---|
115 | return acos(arg) * 180/M_PI;
|
---|
116 | }
|
---|
117 | };
|
---|
118 |
|
---|
119 | // ========================================================================
|
---|
120 | // ========================================================================
|
---|
121 | // ========================================================================
|
---|
122 |
|
---|
123 | void SetupConfiguration(Configuration &conf)
|
---|
124 | {
|
---|
125 | po::options_description control("Smart FACT");
|
---|
126 | control.add_options()
|
---|
127 | ("ra", var<double>(), "Source right ascension")
|
---|
128 | ("dec", var<double>(), "Source declination")
|
---|
129 | ("date-time", var<string>()
|
---|
130 | #if BOOST_VERSION >= 104200
|
---|
131 | ->required()
|
---|
132 | #endif
|
---|
133 | , "SQL time (UTC)")
|
---|
134 | ;
|
---|
135 |
|
---|
136 | po::positional_options_description p;
|
---|
137 | p.add("date-time", 1); // The first positional options
|
---|
138 |
|
---|
139 | conf.AddOptions(control);
|
---|
140 | conf.SetArgumentPositions(p);
|
---|
141 | }
|
---|
142 |
|
---|
143 | void PrintUsage()
|
---|
144 | {
|
---|
145 | cout <<
|
---|
146 | "moon - The moon calculator\n"
|
---|
147 | "\n"
|
---|
148 | "Usage: moon sql-datetime [--ra={ra} --dec={dec}]\n";
|
---|
149 | cout << endl;
|
---|
150 | }
|
---|
151 |
|
---|
152 | int main(int argc, const char* argv[])
|
---|
153 | {
|
---|
154 | Configuration conf(argv[0]);
|
---|
155 | conf.SetPrintUsage(PrintUsage);
|
---|
156 | SetupConfiguration(conf);
|
---|
157 |
|
---|
158 | if (!conf.DoParse(argc, argv))
|
---|
159 | return 127;
|
---|
160 |
|
---|
161 | if (conf.Has("ra")^conf.Has("dec"))
|
---|
162 | {
|
---|
163 | cout << "ERROR - Either --ra or --dec missing." << endl;
|
---|
164 | return 1;
|
---|
165 | }
|
---|
166 |
|
---|
167 | Time time;
|
---|
168 | time.SetFromStr(conf.Get<string>("date-time"));
|
---|
169 |
|
---|
170 | ln_lnlat_posn observer;
|
---|
171 | observer.lng = -(17.+53./60+26.525/3600);
|
---|
172 | observer.lat = 28.+45./60+42.462/3600;
|
---|
173 |
|
---|
174 | Moon moon(observer.lng, observer.lat, time);
|
---|
175 |
|
---|
176 | cout << setprecision(15);
|
---|
177 | cout << time.GetAsStr() << '\n';
|
---|
178 |
|
---|
179 | ln_equ_posn pos;
|
---|
180 | ln_hrz_posn hrz;
|
---|
181 | ln_get_solar_equ_coords(time.JD(), &pos);
|
---|
182 | ln_get_hrz_from_equ(&pos, &observer, time.JD(), &hrz);
|
---|
183 | cout << 90-hrz.alt << '\n';
|
---|
184 |
|
---|
185 | const double kSynMonth = 29.53058868; // synodic month (new Moon to new Moon)
|
---|
186 | const double kEpoch0 = 44240.37917; // First full moon after 1980/1/1
|
---|
187 | const double kInstall = 393; // Moon period if FACT installation
|
---|
188 | const uint32_t period = floor(((time.Mjd()-kEpoch0)/kSynMonth-kInstall));
|
---|
189 |
|
---|
190 | cout << period << '\n';
|
---|
191 | cout << moon.visible << '\n';
|
---|
192 | cout << moon.disk << '\n';
|
---|
193 | cout << moon.zd << '\n';
|
---|
194 |
|
---|
195 | if (conf.Has("ra") && conf.Has("dec"))
|
---|
196 | {
|
---|
197 | pos.ra = conf.Get<double>("ra")*15;
|
---|
198 | pos.dec = conf.Get<double>("dec");
|
---|
199 |
|
---|
200 | cout << moon.Angle(pos.ra/15, pos.dec) << '\n';
|
---|
201 |
|
---|
202 | // Trick 17
|
---|
203 | moon.ra = pos.ra;
|
---|
204 | moon.dec = pos.dec;
|
---|
205 |
|
---|
206 | // Sun distance
|
---|
207 | cout << moon.Angle(pos.ra/15, pos.dec) << '\n';
|
---|
208 | }
|
---|
209 |
|
---|
210 | cout << endl;
|
---|
211 |
|
---|
212 | return 0;
|
---|
213 | }
|
---|