1 /*
2  * Navigational Stars plug-in
3  * Copyright (C) 2020 Andy Kirkham
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
18  */
19 
20 #ifndef NAVSTARSCALCULATOR_HPP
21 #define NAVSTARSCALCULATOR_HPP
22 
23 /*! @defgroup navigationalStars Navigational Stars Plug-in
24 @{
25 The Navigational Stars plugin marks a set of navigational stars.
26 
27 The NavStars class is the main class of the plug-in. It manages the list of
28 navigational stars and manipulate show/hide markers of them. Markers
29 are not objects!
30 
31 The plugin is also an example of a custom plugin that just marks existing stars.
32 
33 <b>Configuration</b>
34 
35 The plug-ins' configuration data is stored in Stellarium's main configuration
36 file (section [NavigationalStars]).
37 
38 @}
39 */
40 
41 #include <cmath>
42 
43 #include <QMap>
44 #include <QString>
45 
46 #ifndef DEG2RAD
47 #define DEG2RAD(x) ((x * M_PI) / 180.)
48 #endif
49 
50 #ifndef RAD2DEG
51 #define RAD2DEG(x) ((x * 180.) / M_PI)
52 #endif
53 
54 //! Forward declaration for UT inputter.
55 struct NavStarCalculatorDegreeInputs;
56 
57 //! @class NavStarsCalculator
58 //! @author Andy Kirkham
59 //! @ingroup navigationalStars
60 class NavStarsCalculator
61 {
62 public:
63 	NavStarsCalculator();
64 	NavStarsCalculator(const NavStarCalculatorDegreeInputs* ip);
65 	~NavStarsCalculator();
66 
67 	//! Calculate intermediates.
68 	void execute();
69 
70 	//! Get a string that represents degrees and decimal minutes of an angle.
71 	//! Format is as per the standard Nautical Almanac, +/-DDDMM.m
72 	//! @param double rad The angle in radians.
73 	//! @param QString pos Use + or N or E.
74 	//! @param QString neg Use - or S or W.
75 	//! @return QString the representation of angle rad.
76 	static QString radToDm(double rad, const QString &pos = "+", const QString &neg = "-");
77 
78 
79 	//! Ensure the supplied angle, in radians, is with 0 to 2PI.
80 	//! @param double d The angle in radians.
81 	//! @return The wrapped value.
82 	static double wrap2pi(double d);
83 
84 	//! Ensure the supplied angle, in degrees, is with 0 to 360.
85 	//! @param double d The angle in degrees.
86 	//! @return The wrapped value.
87 	static double wrap360(double d);
88 
89 	static bool useExtraDecimals;
90 	static bool useDecimalDegrees;
91 
92 private:
93 	QString utc;
94 public:
95 	NavStarsCalculator& setUTC(const QString& s);
getUTC()96 	QString getUTC() {	return utc; }
97 
98 	QMap<QString, QString> printable();
99 
100 private:
101 	double lmst;
102 	double lmst_rad;
103 public:
lmstDegreesPrintable()104 	QString lmstDegreesPrintable()
105 	{
106 		QString sign = lmst < 0. ? "-" : "+";
107 		return QString("%1%2%3").arg(sign).arg(QString::number(lmst, 'f', 3)).arg("&deg;");
108 	}
lmstPrintable()109 	QString lmstPrintable() { return radToDm(lmst_rad); }
110 
111 private:
112 	double sha_rad;
113 public:
shaPrintable()114 	QString shaPrintable() { return radToDm(sha_rad); }
115 
116 private:
117 	double lha;
118 public:
lhaPrintable()119 	QString lhaPrintable() { return radToDm(lha); }
120 
121 private:
122 	double hc_rad;
123 public:
hcPrintable()124 	QString hcPrintable() { return radToDm(hc_rad); }
125 
126 private:
127 	double zn_rad;
128 public:
znPrintable()129 	QString znPrintable() { return radToDm(zn_rad); }
130 
131 private:
132 	double gha_rad;
133 public:
ghaPrintable()134 	QString ghaPrintable() { return (radToDm(gha_rad)); }
135 
136 private:
137 	double gmst;
138 	double gmst_rad;
139 public:
getGmst()140 	double getGmst() { return gmst;  }
setGmst(double d)141 	NavStarsCalculator& setGmst(double d)
142 	{
143 		gmst = wrap360(d);
144 		return *this;
145 	}
gmstDegreesPrintable()146 	QString gmstDegreesPrintable() {
147 		QString sign = gmst < 0. ? "-" : "+";
148 		return QString("%1%2%3").arg(sign).arg(QString::number(gmst, 'f', 3)).arg("&deg;");
149 	}
gmstPrintable()150 	QString gmstPrintable() { return radToDm(gmst_rad); }
151 
152 private:
153 	double lat_deg;
154 	double lat_rad;
155 public:
setLatDeg(double d)156 	NavStarsCalculator& setLatDeg(double d)
157 	{
158 		lat_deg = d;
159 		lat_rad = DEG2RAD(d);
160 		return *this;
161 	}
latPrintable()162 	QString latPrintable() { return radToDm(lat_rad, "N", "S"); }
163 
164 private:
165 	double lon_deg;
166 	double lon_rad;
167 public:
setLonDeg(double d)168 	NavStarsCalculator& setLonDeg(double d)
169 	{
170 		lon_deg = d;
171 		lon_rad = DEG2RAD(d);
172 		return *this;
173 	}
lonPrintable()174 	QString lonPrintable() { return radToDm(lon_rad, "E", "W");  }
175 
176 private:
177 	double gp_lat_deg;
178 	double gp_lat_rad;
179 public:
setGpLatRad(double d)180 	NavStarsCalculator& setGpLatRad(double d)
181 	{
182 		gp_lat_rad = d;
183 		gp_lat_deg = DEG2RAD(d);
184 		return *this;
185 	}
gplatPrintable()186 	QString gplatPrintable() { return radToDm(gp_lat_rad, "N", "S"); }
187 
188 private:
189 	double gp_lon_deg;
190 	double gp_lon_rad;
191 public:
setGpLonRad(double d)192 	NavStarsCalculator& setGpLonRad(double d)
193 	{
194 		gp_lon_rad = d;
195 		gp_lon_deg = DEG2RAD(d);
196 		return *this;
197 	}
gplonPrintable()198 	QString gplonPrintable() { return radToDm(gp_lon_rad, "E", "W"); }
199 
200 private:
201 	double az_rad;
202 public:
setAzRad(double d)203 	NavStarsCalculator& setAzRad(double d)
204 	{
205 		az_rad = d;
206 		return *this;
207 	}
208 
209 private:
210 	double alt_rad;
211 public:
setAltRad(double d)212 	NavStarsCalculator& setAltRad(double d)
213 	{
214 		alt_rad = d;
215 		return *this;
216 	}
217 
218 private:
219 	double az_app_rad;
220 public:
setAzAppRad(double d)221 	NavStarsCalculator& setAzAppRad(double d)
222 	{
223 		az_app_rad = d;
224 		return *this;
225 	}
azAppPrintable()226 	QString azAppPrintable() { return radToDm(az_app_rad); }
227 
228 private:
229 	double alt_app_rad;
230 public:
setAltAppRad(double d)231 	NavStarsCalculator& setAltAppRad(double d)
232 	{
233 		alt_app_rad = d;
234 		return *this;
235 	}
altAppPrintable()236 	QString altAppPrintable() { return radToDm(alt_app_rad); }
addAltAppRad(double d)237 	NavStarsCalculator& addAltAppRad(double d)
238 	{
239 		alt_app_rad += d;
240 		return *this;
241 	}
242 
243 private:
244 	double jd;
245 public:
getJd()246 	double getJd() { return jd; }
setJd(double d)247 	NavStarsCalculator& setJd(double d)
248 	{
249 		jd = d;
250 		return *this;
251 	}
252 
253 private:
254 	double jde;
255 public:
getJde()256 	double getJde() { return jde; }
setJde(double d)257 	NavStarsCalculator& setJde(double d)
258 	{
259 		jde = d;
260 		return *this;
261 	}
262 
263 private:
264 	double dec_rad;
265 public:
setDecRad(double d)266 	NavStarsCalculator& setDecRad(double d)
267 	{
268 		dec_rad = d;
269 		return *this;
270 	}
decPrintable()271 	QString decPrintable() { return radToDm(dec_rad); }
272 
273 private:
274 	double ra_rad;
275 public:
setRaRad(double d)276 	NavStarsCalculator& setRaRad(double d)
277 	{
278 		ra_rad = d;
279 		sha_rad = (2. * M_PI) - ra_rad;
280 		return *this;
281 	}
282 };
283 
284 // When exactly does code to support Unit Testing become intrusive?
285 // I've done worse than this before so it's not all that bad.
286 // See specialized constructor above.
287 struct NavStarCalculatorDegreeInputs
288 {
289 	QString utc;
290 	double ra;
291 	double dec;
292 	double lat;
293 	double lon;
294 	double jd;
295 	double jde;
296 	double gmst;
297 	double az;
298 	double alt;
299 	double az_app;
300 	double alt_app;
301 };
302 
303 #endif /* NAVSTARSCALCULATOR_HPP */
304