• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 15793453064

21 Jun 2025 06:37AM UTC coverage: 11.767% (-0.002%) from 11.769%
15793453064

push

github

10110111
Add support for touch clicks and moves

0 of 30 new or added lines in 1 file covered. (0.0%)

1336 existing lines in 5 files now uncovered.

14700 of 124924 relevant lines covered (11.77%)

18313.08 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.93
/src/core/StelUtils.hpp
1
/*
2
 * Stellarium
3
 * Copyright (C) 2002 Fabien Chereau
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 STELUTILS_HPP
21
#define STELUTILS_HPP
22

23
#include <cmath>
24
#include "VecMath.hpp"
25

26
#include <QVariantMap>
27
#include <QDateTime>
28
#include <QString>
29

30
// astronomical unit (km)
31
#define AU 149597870.691
32
#define AUf 149597870.691f
33
#define AU_KM (1.0/149597870.691)
34
#define AU_KMf (1.0f/149597870.691f)
35
// Parsec (km)
36
#define PARSEC 30.857e12
37
// Parsec (LY)
38
#define PARSEC_LY 3.261563777
39
// speed of light (km/sec)
40
#define SPEED_OF_LIGHT 299792.458
41
// Ecliptic obliquity of J2000.0, degrees
42
#define EPS_0 23.4392803055555555555556
43
// Equatorial radius of the Earth in km (WGS-84)
44
#define EARTH_RADIUS 6378.1366
45
// Equatorial radius of the Sun in km
46
#define SUN_RADIUS 696000.
47
// Equatorial radius of the Moon in km
48
#define MOON_RADIUS 1738.
49
// 1 mas to 1 radian, is M_PI / (3600000. * 180.)
50
#define MAS2RAD 4.8481368110953594e-9
51
// julian year in seconds that is 365.25 * 86400.
52
#define JYEAR_SECONDS 31557600.0
53

54
// Add a few frequently used extra math-type literals
55
#ifndef M_PI_180
56
        #define M_PI_180    (M_PI/180.)
57
#endif
58
#ifndef M_180_PI
59
        #define M_180_PI    (180./M_PI)
60
#endif
61
// Add some math literals in float version to avoid many static_casts
62
#ifndef M_PIf
63
        #define M_PIf       3.14159265358979323846f   // pi
64
#endif
65
#ifndef M_PI_2f
66
        #define M_PI_2f     1.57079632679489661923f   // pi/2
67
#endif
68
#ifndef M_PI_4f
69
        #define M_PI_4f     0.785398163397448309616f  // pi/4
70
#endif
71
#ifndef M_1_PIf
72
        #define M_1_PIf     0.318309886183790671538f  // 1/pi
73
#endif
74
#ifndef M_2_PIf
75
        #define M_2_PIf     0.636619772367581343076f  // 2/pi
76
#endif
77
#ifndef M_PI_180f
78
        #define M_PI_180f   (M_PIf/180.f)
79
#endif
80
#ifndef M_180_PIf
81
        #define M_180_PIf   (180.f/M_PIf)
82
#endif
83

84
#define stelpow10f(x) std::exp((x) * 2.3025850930f)
85

86
#define L1S(x) QLatin1String(x)
87

88
// Allow parallel evaluation of std::transform_reduce(std::execution::par, ...) or
89
// std::sort(std::execution::par, ...) where known. Not all compilers know it.
90
// Use std::transform_reduce(STD_EXECUTION_PAR_COMMA ...) for the general case.
91
#if STD_EXECUTION_KNOWN
92
# define STD_EXECUTION_PAR_COMMA std::execution::par,
93
#else
94
# define STD_EXECUTION_PAR_COMMA
95
#endif
96

97
constexpr double DEFAULT_FONT_SIZE = 13;
98

99
//! @namespace StelUtils contains general purpose utility functions.
100
namespace StelUtils
101
{
102
        static inline constexpr double J2000 = 2451545.0;
103

104
        //! Return the full name of stellarium, i.e. "Stellarium 23.1"
105
        QString getApplicationName();
106

107
        //! Return the version of stellarium, i.e. "23.1.0"
108
        QString getApplicationVersion();
109

110
        //! Return the public version of stellarium, i.e. "23.1"
111
        QString getApplicationPublicVersion();
112

113
        //! Return the series of stellarium, i.e. "23.0"
114
        QString getApplicationSeries();
115

116
        //! Return the name and the version of operating system, i.e. "macOS 12.5"
117
        QString getOperatingSystemInfo();
118

119
        //! Return the user agent name, i.e. "Stellarium/0.15.0 (Linux)"
120
        QString getUserAgentString();
121

122
        //! Return the addressing mode string, i.e. "64-bit"
123
        QString getAddressingMode();
124

125
        /*! \brief Get a long integer from a JSON value
126
         *
127
         *  QJsonValue stores JSON numbers as double-precision floating-point values. This means
128
         *  that numbers greater than 2^53-1 will be rounded, which is unacceptable for e.g. ids
129
         *  like those of the Gaia catalog.
130
         *  This function supports, in addition to normal JSON numbers, also representations of
131
         *  numbers by JSON strings. If the value passed is a JSON string, it will be parsed to a
132
         *  number. If it's a JSON number less than 2^53, it will be returned as is. Otherwise it
133
         *  will return 0, as QJsonValue's getters would in case of a type mismatch.
134
         */
135
        qint64 getLongLong(const class QJsonValue& v);
136

137
        inline const QString getEndLineChar() {
1✔
138
                #ifdef Q_OS_WIN
139
                const QString stelEndl="\r\n";
140
                #else
141
                const QString stelEndl="\n";
1✔
142
                #endif
143
                return stelEndl;
1✔
144
        }
145

146
        //! Convert hours, minutes, seconds to decimal hours
147
        inline double hmsToHours(const unsigned int h, const unsigned int m, const double s){
43✔
148
                return static_cast<double>(h)+static_cast<double>(m)/60.+s/3600.;
43✔
149
        }
150

151
        //! Convert an angle in hms format to radian.
152
        //! @param h hour component
153
        //! @param m minute component
154
        //! @param s second component
155
        //! @return angle in radian
156
        inline double hmsToRad(const unsigned int h, const unsigned int m, const double s){
15✔
157
                return hmsToHours(h, m, s)*M_PI/12.;
15✔
158
        }
159

160
        //! Convert an angle in +-dms format to radian.
161
        //! @param d degree component
162
        //! @param m arcmin component
163
        //! @param s arcsec component
164
        //! @return angle in radian
165
        inline double dmsToRad(const int d, const unsigned int m, const double s){
41✔
166
                double rad = M_PI_180*qAbs(d)+M_PI/10800.*m+s*M_PI/648000.;
41✔
167
                return (d<0 ? -rad : rad);
41✔
168
        }
169

170
        //! Convert an angle in radian to hms format.
171
        //! @param rad input angle in radian
172
        //! @param h hour component
173
        //! @param m minute component
174
        //! @param s second component
175
        void radToHms(double rad, unsigned int& h, unsigned int& m, double& s);
176

177
        //! Convert an angle in radian to +-dms format.
178
        //! @param rad input angle in radian
179
        //! @param sign true if positive, false otherwise
180
        //! @param d degree component
181
        //! @param m minute component
182
        //! @param s second component
183
        void radToDms(double rad, bool& sign, unsigned int& d, unsigned int& m, double& s);
184

185
        //! Convert an angle in radian to decimal degree.
186
        //! @param rad input angle in radian
187
        //! @param sign true if positive, false otherwise
188
        //! @param deg decimal degree
189
        Q_DECL_DEPRECATED_X("just use rad*M_180_PI instead")
190
        void radToDecDeg(double rad, bool& sign, double& deg);
191

192
        //! Convert an angle in radian to a decimal degree string.
193
        //! @param angle input angle in radian
194
        //! @param precision
195
        //! @param useD Define if letter "d" must be used instead of deg sign
196
        //! @param positive Define if function should use 0-360 degrees
197
        QString radToDecDegStr(const double angle, const int precision = 4, const bool useD=false, const bool positive=false);
198

199
        //! Convert an angle in radian to a hms formatted string.
200
        //! If the second, minute part is == 0, it is not output
201
        //! @param angle input angle in radian
202
        QString radToHmsStrAdapt(const double angle);
203

204
        //! Convert an angle in radian to a hms formatted string.
205
        //! @param angle input angle in radian
206
        //! @param decimal output decimal second value
207
        QString radToHmsStr(const double angle, const bool decimal=false);
208

209
        //! Convert an angle in radian to a dms formatted string.
210
        //! If the second, minute part is == 0, it is not output
211
        //! @param angle input angle in radian
212
        //! @param useD Define if letter "d" must be used instead of deg sign
213
        QString radToDmsStrAdapt(const double angle, const bool useD=false);
214

215
        //! Convert an angle in radian to a dms formatted string.
216
        //! @param angle input angle in radian        
217
        //! @param decimal output second value with decimal fraction
218
        //! @param useD Define if letter "d" must be used instead of deg sign
219
        QString radToDmsStr(const double angle, const bool decimal=false, const bool useD=false);
220

221
        //! Convert an angle in radian to a dms formatted string.
222
        //! @param angle input angle in radian
223
        //! @param precision
224
        //! @param useD Define if letter "d" must be used instead of deg sign
225
        QString radToDmsPStr(const double angle, const int precision = 0, const bool useD=false);
226

227
        //! Convert an angle in decimal degree to +-dms format.
228
        //! @param angle input angle in decimal degree
229
        //! @param sign true if positive, false otherwise
230
        //! @param d degree component
231
        //! @param m minute component
232
        //! @param s second component
233
        void decDegToDms(double angle, bool& sign, unsigned int& d, unsigned int& m, double& s);
234

235
        //! Convert an angle in decimal degrees to a dms formatted string.
236
        //! @param angle input angle in decimal degrees
237
        QString decDegToDmsStr(const double angle);
238

239
        //! Convert latitude in decimal degrees to a dms formatted string or use decimal values.
240
        //! @param latitude in decimal degrees
241
        //! @param dms set true to use DMS formatted string
242
        QString decDegToLatitudeStr(const double latitude, bool dms = true);
243

244
        //! Convert longitude in decimal degrees to a dms formatted string.
245
        //! @param longitude in decimal degrees
246
        //! @param eastPositive set true to counting East direction positive
247
        //! @param semiSphere set true to use -180..180 degrees range (0..360 degrees otherwise)
248
        //! @param dms set true to use DMS formatted string
249
        QString decDegToLongitudeStr(const double longitude, bool eastPositive = true, bool semiSphere = true, bool dms = true);
250

251
        //! Convert a dms formatted string to an angle in radian
252
        //! @param s The input string
253
        double dmsStrToRad(const QString& s);
254

255
        //! Convert from spherical coordinates to Rectangular direction.
256
        //! @param lng longitude in radian
257
        //! @param lat latitude in radian
258
        //! @param v the resulting 3D unit vector
259
        inline void spheToRect(const double lng, const double lat, Vec3d& v){
629✔
260
                const double cosLat = cos(lat);
629✔
261
                v.set(cos(lng) * cosLat, sin(lng) * cosLat, sin(lat));
629✔
262
        }
629✔
263

264
        //! Convert from spherical coordinates to Rectangular direction.
265
        //! @param lng longitude in radian
266
        //! @param lat latitude in radian
267
        //! @param v the resulting 3D unit vector
268
        inline void spheToRect(const float lng, const float lat, Vec3f& v){
83✔
269
                const double dlng = static_cast<double>(lng), dlat = static_cast<double>(lat), cosLat = cos(dlat);
83✔
270
                v.set(static_cast<float>(cos(dlng) * cosLat), static_cast<float>(sin(dlng) * cosLat), sinf(lat));
83✔
271
        }
83✔
272

273
        //! Convert from spherical coordinates to Rectangular direction.
274
        //! @param lng longitude in radian
275
        //! @param lat latitude in radian
276
        //! @param v the resulting 3D unit vector
277
        inline void spheToRect(const double lng, const double lat, Vec3f& v){
278
                const float cosLat = cos(static_cast<float>(lat));
279
                v.set(cos(static_cast<float>(lng)) * cosLat, sin(static_cast<float>(lng)) * cosLat, sin(static_cast<float>(lat)));
280
        }
281

282
        //! Convert from spherical coordinates to Rectangular direction.
283
        //! @param lng longitude in radian
284
        //! @param lat latitude in radian
285
        //! @param v the resulting 3D unit vector
286
        inline void spheToRect(const float lng, const float lat, Vec3d& v){
7✔
287
                const double dlng = static_cast<double>(lng), dlat = static_cast<double>(lat), cosLat = cos(dlat);
7✔
288
                v.set(cos(dlng) * cosLat, sin(dlng) * cosLat, sin(dlat));
7✔
289
        }
7✔
290

291
        //! Convert from Rectangular direction to spherical coordinate components.
292
        //! @param lng double* to store longitude in radian [-pi, pi]
293
        //! @param lat double* to store latitude in radian
294
        //! @param v the input 3D vector
295
        inline void rectToSphe(double *lng, double *lat, const Vec3d& v){
93✔
296
                *lat = atan2(v[2], sqrt(v[0]*v[0] + v[1]*v[1]));
93✔
297
                *lng = atan2(v[1],v[0]);
93✔
298
        }
93✔
299

300
        //! Convert from Rectangular direction to spherical coordinate components.
301
        //! @param lng float* to store longitude in radian [-pi, pi]
302
        //! @param lat float* to store latitude in radian
303
        //! @param v the input 3D vector
304
        inline void rectToSphe(float *lng, float *lat, const Vec3d& v){
5✔
305
                *lng = static_cast<float>(atan2(v[1],v[0]));
5✔
306
                *lat = atan2(v[2], sqrt(v[0]*v[0] + v[1]*v[1]));
5✔
307
        }
5✔
308

309

310
        //! Convert from Rectangular direction to spherical coordinate components.
311
        //! @param lng float* to store longitude in radian [-pi, pi]
312
        //! @param lat float* to store latitude in radian
313
        //! @param v the input 3D vector
314
        inline void rectToSphe(float *lng, float *lat, const Vec3f& v){
81✔
315
                *lat = atan2(v[2], sqrt(v[0]*v[0] + v[1]*v[1]));
81✔
316
                *lng = atan2f(v[1],v[0]);
81✔
317
        }
81✔
318

319
        //! Convert from Rectangular direction to spherical coordinate components.
320
        //! @param lng double* to store longitude in radian [-pi, pi]
321
        //! @param lat double* to store latitude in radian
322
        //! @param v the input 3D vector
323
        inline void rectToSphe(double *lng, double *lat, const Vec3f &v){
5✔
324
                *lat = atan2(static_cast<double>(v[2]), sqrt(static_cast<double>(v[0]*v[0] + v[1]*v[1])));
5✔
325
                *lng = atan2(static_cast<double>(v[1]),static_cast<double>(v[0]));
5✔
326
        }
5✔
327

328
        //! Convert from spherical coordinates (including distance) to Rectangular direction.
329
        //! @param lng longitude in radian
330
        //! @param lat latitude in radian
331
        //! @param r length of radius vector (distance)
332
        //! @param v the resulting 3D unit vector
333
        inline void spheToRect(const double lng, const double lat, const double r, Vec3d& v){
7✔
334
                const double cosLat = cos(lat);
7✔
335
                v.set(cos(lng) * cosLat * r, sin(lng) * cosLat * r, sin(lat) * r);
7✔
336
        }
7✔
337

338
        //! Convert from Rectangular direction to spherical coordinate components (including distance).
339
        //! @param lng double* to store longitude in radian [-pi, pi]
340
        //! @param lat double* to store latitude in radian
341
        //! @param r double*   length of radius vector (distance)
342
        //! @param v the input 3D vector
343
        inline void rectToSphe(double *lng, double *lat, double *r, const Vec3d& v){
5✔
344
                *r = v.norm();
5✔
345
                *lat = atan2(v[2], sqrt(v[0]*v[0] + v[1]*v[1]));
5✔
346
                *lng = atan2(v[1],v[0]);
5✔
347
        }
5✔
348

349
        //! Coordinate Transformation from equatorial to ecliptical
350
        inline void equToEcl(const double raRad, const double decRad, const double eclRad, double *lambdaRad, double *betaRad){
5✔
351
                *lambdaRad=std::atan2(std::sin(raRad)*std::cos(eclRad)+std::tan(decRad)*std::sin(eclRad), std::cos(raRad));
5✔
352
                *betaRad=std::asin(std::sin(decRad)*std::cos(eclRad)-std::cos(decRad)*std::sin(eclRad)*std::sin(raRad));
5✔
353
        }
5✔
354

355
        //! Coordinate Transformation from ecliptical to equatorial
356
        inline void eclToEqu(const double lambdaRad, const double betaRad, const double eclRad, double *raRad, double *decRad){
5✔
357
                *raRad = std::atan2(std::sin(lambdaRad)*std::cos(eclRad)-std::tan(betaRad)*std::sin(eclRad), std::cos(lambdaRad));
5✔
358
                *decRad = std::asin(std::sin(betaRad)*std::cos(eclRad)+std::cos(betaRad)*std::sin(eclRad)*std::sin(lambdaRad));
5✔
359
        }
5✔
360

361
        //! Convert a string longitude, latitude, RA or declination angle
362
        //! to radians.
363
        //! @param str the angle in a format according to:
364
        //!   angle ::= [sign¹] ( real [degs | mins | secs]
365
        //!                     | [integer degs] ( [integer mins] real secs
366
        //!                                       | real mins )
367
        //!                     ) [cardinal¹]            
368
        //!   sign ::= + | -
369
        //!   digit := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
370
        //!   integer ::= digit [digits]
371
        //!   real ::= integer [. integer]
372
        //!   degs ::= d | h² | U+00B0 | U+00BA³
373
        //!   mins ::= m | '
374
        //!   secs ::= s | "
375
        //!   cardinal ::= N² | S² | E | W
376
        //!   ¹) A cardinal point overrides any sign. N and E result in a positive,
377
        //!      W and S in a negative angle.
378
        //!   ²) The use of the cardinal points N and S together with the hour sign
379
        //!      'H' or 'h' is forbidden.
380
        //!   ³) The MASCULINE ORDINAL INDICATOR U+00BA is accepted, considering
381
        //!      Spanish QWERTY keyboards.
382
        //! The string is parsed without regarding to case, except that, after a
383
        //! single real, a solitary 's' indicates seconds whereas an 'S' indicates South.
384
        //! It is highly recommended to use lower case for hdms and upper case for NSEW.
385
        //! Latitude: North is positive, South is negative.
386
        //! Longitude: East is positive, West is negative.
387
        //! @return the angle in radians.
388
        double getDecAngle(const QString& str);
389

390
        //! Check if a number is a power of 2.
391
        inline bool isPowerOfTwo(const int value){
10✔
392
                return (value & -value) == value;
10✔
393
        }
394

395
        //! Return the smallest power of two greater than or equal to the given value.
396
        int getBiggerPowerOfTwo(int value);
397

398
        //! Return the largest power of two smaller than or equal to the given value
399
        int getSmallerPowerOfTwo(const int value);
400

401
        //! Return the inverse sinus hyperbolic of z.
402
        inline double asinh(const double z){
403
                return (z>0 ? std::log(z + std::sqrt(z*z+1)) :
404
                             -std::log(-z + std::sqrt(z*z+1)));
405
        }
406

407
        //! Integer modulo where the result is always nonnegative. [0..b-1]
408
        inline int imod(const int a, const int b){
13,839✔
409
                int ret = a % b;
13,839✔
410
                if(ret < 0)
13,839✔
411
                        ret+=b;
269✔
412
                return ret;
13,839✔
413
        }
414
        //! Integer modulo where the result is always positive. [1..b]
415
        inline int amod(const int a, const int b){
580✔
416
                int ret = a % b;
580✔
417
                if(ret <= 0)
580✔
418
                        ret+=b;
126✔
419
                return ret;
580✔
420
        }
421
        //! Integer interval modulo. [a..b)
422
        inline int amod(const int x, const int a, const int b){
×
423
                if (a==b)
×
UNCOV
424
                        return x;
×
UNCOV
425
                int ret = imod(x-a, b-a);
×
UNCOV
426
                return ret+a;
×
427
        }
428
        //! Double modulo where the result is always nonnegative. [0..(b
429
        inline double fmodpos(const double a, const double b){
21,823✔
430
                double ret = fmod(a, b);
21,823✔
431
                if(ret < 0)
21,823✔
432
                        ret+=b;
1,321✔
433
                return ret;
21,823✔
434
        }
435
        //! Float modulo where the result is always nonnegative. [0..(b
436
        inline float fmodpos(const float a, const float b){
6✔
437
                float ret = fmodf(a, b);
6✔
438
                if(ret < 0)
6✔
439
                        ret+=b;
1✔
440
                return ret;
6✔
441
        }
442

443
        //! Floor integer division provides truncating to the next lower integer, also for negative numerators.
444
        //! https://stackoverflow.com/questions/2622441/c-integer-floor-function
445
        //! @returns floor(num/den)
446
        inline int intFloorDiv (int num, int den)
22,311✔
447
        {
448
          if (0 < (num^den)) // lgtm [cpp/bitwise-sign-check]
22,311✔
449
            return num/den;
21,594✔
450
          else
451
            {
452
              ldiv_t res = ldiv(num,den);
717✔
453
              return (res.rem)? res.quot-1
1,382✔
454
                              : res.quot;
717✔
455
            }
456
        }
457

458
        //! version of intFloorDiv() for large integers.
459
        inline int intFloorDivLL(qint64 num, qint64 den)
137✔
460
        {
461
          if (0 < (num^den)) // lgtm [cpp/bitwise-sign-check]
137✔
462
            return int(num/den);
107✔
463
          else
464
            {
465
              lldiv_t res = lldiv(num,den);
30✔
466
              qint64 ret= (res.rem)? res.quot-1
30✔
467
                              : res.quot;
468
              return int(ret);
30✔
469
            }
470
        }
471

472
        ///////////////////////////////////////////////////
473
        // New Qt based General Calendar Functions.
474
        //! Extract from julianDay a year, month, day for the Julian Date julianDay represents.
475
        //! @attention Under rare circumstances with a rounded result where julianDay=*.49999999xyz this will still round off whereas the time is less than a fraction from midnight of the next day.
476
        //! Depending on circumstances this may matter or not. If you need a full decoding of a Julian day number, prefer to use getDateTimeFromJulianDay()
477
        void getDateFromJulianDay(const double julianDay, int *year, int *month, int *day);
478

479
        //! Extract from julianDay an hour, minute, second.
480
        //! @attention Under rare circumstances with a rounded result where julianDay=*.49999999xyz this will lead to a factual result for *.5000000abc, i.e. not 24 but 0 hours, and wrapDay will be true.
481
        //! Depending on circumstances this may matter or not. If you need a full decoding of a Julian day number, prefer to use getDateTimeFromJulianDay()
482
        void getTimeFromJulianDay(const double julianDay, int *hour, int *minute, int *second, int *millis=Q_NULLPTR, bool *wrapDay=Q_NULLPTR);
483

484
        //! Extract from julianDay a year, month, day, hour, minute, second and (optional) millisecond for the Julian Day julianDay represents.
485
        //! This is the preferred method of complete decoding of a Julian day number.
486
        void getDateTimeFromJulianDay(const double julianDay, int *year, int *month, int *day, int *hour, int *minute, int *second, int *millis=Q_NULLPTR);
487

488
        //! Make hours (decimal format) from julianDay
489
        double getHoursFromJulianDay(const double julianDay);
490

491
        //! Parse an ISO8601 date string.
492
        //! Also handles negative and distant years.
493
        bool getDateTimeFromISO8601String(const QString& iso8601Date, int* y, int* m, int* d, int* h, int* min, float* s);
494
        
495
        //! Format the given Julian Day in (UTC) ISO8601 date string.
496
        //! Also handles negative and distant years.
497
        QString julianDayToISO8601String(const double jd, bool addMS = false);
498

499
        //! Return the Julian Date matching the ISO8601 date string.
500
        //! Also handles negative and distant years.
501
        double getJulianDayFromISO8601String(const QString& iso8601Date, bool* ok);
502
        
503
        //! Format the date and day-of-week per the format in fmt
504
        //! (see QDateTime::toString()). Uses the @b system locale, not
505
        //! the one set in Stellarium.
506
        //! @return QString representing the formatted date
507
        QString localeDateString(const int year, const int month, const int day, const int dayOfWeek, const QString &fmt);
508

509
        //! Format the date and day-of-week per the @b system locale's
510
        //! QLocale::ShortFormat.
511
        //! @return QString representing the formatted date
512
        QString localeDateString(const int year, const int month, const int day, const int dayOfWeek);
513

514
        //! Return a day number of week for date
515
        //! @return number of day: 0 - sunday, 1 - monday,..
516
        int getDayOfWeek(int year, int month, int day);
517
        inline int getDayOfWeek(double JD)
6✔
518
        {
519
                double d= fmodpos(JD+1.5, 7);
6✔
520
                return std::lround(floor(d));
6✔
521
        }
522

523
        //! Format the discovery date
524
        //! @return QString representing the formatted date
525
        QString localeDiscoveryDateString(const QString& discovery);
526

527
        //! Get the current Julian Date from system time.
528
        //! @return the current Julian Date
529
        double getJDFromSystem();
530

531
        //! Get the Julian Day Number (JD) from Besselian epoch.
532
        //! @param epoch Besselian epoch, expressed as year with decimal fraction
533
        //! @return Julian Day number (JD) for B<Year>
534
        double getJDFromBesselianEpoch(const double epoch);
535

536
        //! Get the Julian Day Number (JD) from Julian epoch.
537
        //! @param epoch Julian epoch, expressed as year with decimal fraction
538
        //! @return Julian Day number (JD) for J<Year>
539
        double getJDFromJulianEpoch(const double epoch);
540

541
        //! Convert a time of day to the fraction of a Julian Day.
542
        //! Note that a Julian Day starts at 12:00, not 0:00, and
543
        //! so 12:00 == 0.0 and 0:00 == 0.5
544
        double qTimeToJDFraction(const QTime& time);
545

546
        //! Convert a fraction of a Julian Day to a QTime
547
        QTime jdFractionToQTime(const double jd);
548

549
        //! Convert a QT QDateTime class to julian day.
550
        //! @param dateTime the UTC QDateTime to convert
551
        //! @result the matching decimal Julian Day
552
        inline double qDateTimeToJd(const QDateTime& dateTime){
6✔
553
                Q_ASSERT(dateTime.timeSpec()==Qt::UTC);
6✔
554
                return dateTime.date().toJulianDay()+static_cast<double>(1./(24*60*60*1000))*QTime(0, 0, 0, 0).msecsTo(dateTime.time())-0.5;
6✔
555
        }
556

557
        //! Convert a Julian Day number to a QDateTime.
558
        //! @param jd Julian Day number (with fractions) to convert
559
        //! @param timeSpec a @c Qt::TimeSpec constant. Meaningful in this context seem only Qt::UTC (preferred) and Qt::LocalTime (useful in some GUI contexts).
560
        //! @note From 2008 to 2022-05 this converted to local time zone, not to UTC as specified and intended.
561
        //!        The old behaviour is kept with @p timeSpec set to Qt::LocalTime.
562
        //! If you use Qt::LocalTime, you should add StelCore::getUTCOffset(jd)/24 to the current JD before calling this to have @p jd as a "local time zone corrected JD" before conversion.
563
        //! @result the matching QDateTime
564
        //! @note QDate has no year zero. This and other idiosyncrasies of QDateTime may limit the applicability of program parts which use this method to positive years or may cause other issues.
565
        QDateTime jdToQDateTime(const double& jd, const Qt::TimeSpec timeSpec);
566

567
        //! Compute Julian day number from calendar date.
568
        //! Uses QDate functionality if possible, but also works for negative JD.
569
        //! Dates before 1582-10-15 are in the Julian Calendar.
570
        //! @param newjd pointer to JD
571
        //! @param y Calendar year.
572
        //! @param m month, 1=January ... 12=December
573
        //! @param d day
574
        //! @param h hour
575
        //! @param min minute
576
        //! @param s second
577
        //! @result true in all conceivable cases.
578
        bool getJDFromDate(double* newjd, const int y, const int m, const int d, const int h, const int min, const float s);
579

580
        int numberOfDaysInMonthInYear(const int month, const int year);
581
        //! @result true if year is a leap year. Observes 1582 switch from Julian to Gregorian Calendar.
582
        bool isLeapYear(const int year);
583
        //! Find day number for date in year.
584
        //! Meeus, Astronomical Algorithms 2nd ed., 1998, ch.7, p.65
585
        int dayInYear(const int year, const int month, const int day);
586
        //! Find date from day number within year and the year.
587
        //! Meeus, AA 2nd, 1998, ch.7 p.66
588
        //! @returns Vec3i(year, month, day)
589
        Vec3i dateFromDayYear(const int day, const int year);
590
        //! Return a fractional year like YYYY.ddddd. For negative years, the year number is decreased. E.g. -500.5 occurs in -501.
591
        double yearFraction(const int year, const int month, const double day);
592

593
        bool changeDateTimeForRollover(int oy, int om, int od, int oh, int omin, int os,
594
                                       int* ry, int* rm, int* rd, int* rh, int* rmin, int* rs);
595

596
        //! Output a QVariantMap to qDebug().  Formats like a tree where there are nested objects.
597
        void debugQVariantMap(const QVariant& m, const QString& indent="", const QString& key="");
598

599

600
        /// Compute acos(x)
601
        //! The taylor serie is not accurate around x=1 and x=-1
602
        inline float fastAcos(const float x)
7✔
603
        {
604
                return static_cast<float>(M_PI_2) - (x + x*x*x * (1.f/6.f + x*x * (3.f/40.f + 5.f/112.f * x*x)) );
7✔
605
        }
606

607
        //! Compute exp(x) for small exponents x
608
        inline float fastExp(const float x)
9✔
609
        {
610
                return (x>=0)?
9✔
611
                        (1.f + x*(1.f+ x/2.f*(1.f+ x/3.f*(1.f+x/4.f*(1.f+x/5.f))))):
5✔
612
                                1.f / (1.f -x*(1.f -x/2.f*(1.f- x/3.f*(1.f-x/4.f*(1.f-x/5.f)))));
9✔
613
        }
614

615
        // Calculate and return sidereal period in days from semi-major axis (in AU)
616
        //double calculateSiderealPeriod(const double SemiMajorAxis);  MOVED TO Orbit.h
617

618
        //! Convert decimal hours to hours, minutes, seconds
619
        //! Format for:
620
        //! @p colonFormat        |      false     |   true
621
        //! ----------------------|----------------|----------
622
        //! @p minutesOnly=false  |  "HhMMmSS.Ss"  | "HHhMMm"
623
        //! @p minutesOnly=true   |  "H:MM:SS.S"   | "HH:MM"
624
        QString hoursToHmsStr(const double hours, const bool minutesOnly = false, const bool colonFormat=false);
625
        QString hoursToHmsStr(const float hours, const bool minutesOnly = false, const bool colonFormat=false);
626

627
        //! Convert JD to hours and minutes
628
        QString getHoursMinutesFromJulianDay(const double julianDay);
629

630
        //! Convert a hms formatted string to decimal hours
631
        double hmsStrToHours(const QString& s);
632

633
        //! Convert days (float) to a time string
634
        QString daysFloatToDHMS(float days);
635

636
        //! The method to splitting the text by substrings by some limit of string length
637
        QString wrapText(const QString& s, const int limit = 52);
638

639
        //! Get Delta-T estimation for a given date.
640
        //! This is just an "empty" correction function, returning 0.
641
        double getDeltaTwithoutCorrection(const double jDay);
642

643
        //! Get Delta-T estimation for a given date.
644
        //! Note that this method is recommended for the year range:
645
        //! -1999 to +3000. It gives details for -500...+2150.
646
        //! Implementation of algorithm by Espenak & Meeus (2006) for DeltaT computation
647
        //! @param jDay the date and time expressed as a Julian day
648
        //! @return Delta-T in seconds
649
        double getDeltaTByEspenakMeeus(const double jDay);
650

651
        //! Get Delta-T estimation for a given date.
652
        //! Note that this method is recommended for the year range:
653
        //! -1999 to +3000. It gives details for -500...+2150.
654
        //! Implementation of algorithm by Espenak & Meeus (2006) with modified formulae for DeltaT computation
655
        //! @param jDay the date and time expressed as a Julian day
656
        //! @return Delta-T in seconds
657
        double getDeltaTByEspenakMeeusModified(const double jDay);
658

659
        //! Get Delta-T estimation for a given date.
660
        //! Implementation of algorithm by Schoch (1931) for DeltaT computation,
661
        //! outdated but may be useful for science-historical purposes.
662
        //! Source: Schoch, C. (1931). Die sekulare Accelaration des Mondes und der Sonne.
663
        //! Astronomische Abhandlungen, Ergnzungshefte zu den Astronomischen Nachrichten,
664
        //! Band 8, B2. Kiel.
665
        //! @param jDay the date and time expressed as a Julian day
666
        //! @return Delta-T in seconds
667
        double getDeltaTBySchoch(const double jDay);
668

669
        //! Get Delta-T estimation for a given date.
670
        //! Implementation of algorithm by Clemence (1948) for DeltaT computation,
671
        //! outdated but may be useful for science-historical purposes.
672
        //! Source: On the system of astronomical constants.
673
        //! Clemence, G. M.
674
        //! Astronomical Journal, Vol. 53, p. 169
675
        //! 1948AJ.....53..169C [http://adsabs.harvard.edu/abs/1948AJ.....53..169C]
676
        //! @param jDay the date and time expressed as a Julian day
677
        //! @return Delta-T in seconds
678
        double getDeltaTByClemence(const double jDay);
679

680
        //! Get Delta-T estimation for a given date.
681
        //! Implementation of algorithm by IAU (1952) for DeltaT computation,
682
        //! outdated but may be useful for science-historical purposes.
683
        //! Source: Spencer Jones, H., "The Rotation of the Earth, and the Secular Accelerations of the Sun, Moon and Planets",
684
        //! Monthly Notices of the Royal Astronomical Society, 99 (1939), 541-558
685
        //! http://adsabs.harvard.edu/abs/1939MNRAS..99..541S
686
        //! @param jDay the date and time expressed as a Julian day
687
        //! @return Delta-T in seconds
688
        double getDeltaTByIAU(const double jDay);
689

690
        //! Get Delta-T estimation for a given date.
691
        //! Implementation of algorithm by Astronomical Ephemeris (1960) for DeltaT computation.
692
        //! Sources: Spencer Jones, H., "The Rotation of the Earth, and the Secular Accelerations of the Sun, Moon and Planets",
693
        //! Monthly Notices of the Royal Astronomical Society, 99 (1939), 541-558
694
        //! http://adsabs.harvard.edu/abs/1939MNRAS..99..541S
695
        //! or Explanatory Supplement to the Astr. Ephemeris, 1961, p.87.
696
        //! Also used by Mucke&Meeus, Canon of Solar Eclipses, Vienna 1983.
697
        //! @param jDay the date and time expressed as a Julian day
698
        //! @return Delta-T in seconds
699
        double getDeltaTByAstronomicalEphemeris(const double jDay);
700

701
        //! Get Delta-T estimation for a given date.
702
        //! Implementation of algorithm by Tuckerman (1962, 1964) & Goldstine (1973) for DeltaT computation
703
        //! @param jDay the date and time expressed as a Julian day
704
        //! @return Delta-T in seconds
705
        double getDeltaTByTuckermanGoldstine(const double jDay);
706

707
        //! Get Delta-T estimation for a given date.
708
        //! Implementation of algorithm by Muller & Stephenson (1975) for DeltaT computation.
709
        //! Source: The accelerations of the earth and moon from early astronomical observations
710
        //! Muller, P. M.; Stephenson, F. R.
711
        //! Growth rhythms and the history of the earth's rotation; Proceedings of the Interdisciplinary
712
        //! Winter Conference on Biological Clocks and Changes in the Earth's Rotation: Geophysical and
713
        //! Astronomical Consequences, Newcastle-upon-Tyne, England, January 8-10, 1974. (A76-18126 06-46)
714
        //! London, Wiley-Interscience, 1975, p. 459-533; Discussion, p. 534.
715
        //! 1975grhe.conf..459M [http://adsabs.harvard.edu/abs/1975grhe.conf..459M]
716
        //! @param jDay the date and time expressed as a Julian day
717
        //! @return Delta-T in seconds
718
        double getDeltaTByMullerStephenson(const double jDay);
719

720
        //! Get Delta-T estimation for a given date.
721
        //! Implementation of algorithm by Stephenson (1978) for DeltaT computation.
722
        //! Source: Pre-Telescopic Astronomical Observations
723
        //! Stephenson, F. R.
724
        //! Tidal Friction and the Earth's Rotation, Proceedings of a Workshop, held in Bielefeld,
725
        //! September 26-30, 1977, Edited by P. Brosche, and J. Sundermann. Berlin: Springer-Verlag, 1978, p.5
726
        //! 1978tfer.conf....5S [http://adsabs.harvard.edu/abs/1978tfer.conf....5S]
727
        //! @param jDay the date and time expressed as a Julian day
728
        //! @return Delta-T in seconds
729
        double getDeltaTByStephenson1978(const double jDay);
730

731
        //! Get Delta-T estimation for a given date.
732
        //! Implementation of algorithm by Stephenson (1997) for DeltaT computation.
733
        //! Source: Book "Historical Eclipses and Earth's Rotation" by F. R. Stephenson (1997)
734
        //! http://ebooks.cambridge.org/ebook.jsf?bid=CBO9780511525186
735
        //! @param jDay the date and time expressed as a Julian day
736
        //! @return Delta-T in seconds
737
        double getDeltaTByStephenson1997(const double jDay);
738

739
        //! Get Delta-T estimation for a given date.
740
        //! Implementation of algorithm by Schmadel & Zech (1979) for DeltaT computation.
741
        //! Outdated, but may be useful for science-historical purposes.
742
        //! Source: Polynomial approximations for the correction delta T E.T.-U.T. in the period 1800-1975
743
        //! Schmadel, L. D.; Zech, G.
744
        //! Acta Astronomica, vol. 29, no. 1, 1979, p. 101-104.
745
        //! 1979AcA....29..101S [http://adsabs.harvard.edu/abs/1979AcA....29..101S]
746
        //! @param jDay the date and time expressed as a Julian day
747
        //! @return Delta-T in seconds
748
        //! @note The polynome is strictly applicable 1800...1975 only! Delivers values for the nearer edge (1800/1989) if jDay is outside.
749
        double getDeltaTBySchmadelZech1979(const double jDay);
750

751
        //! Get Delta-T estimation for a given date.
752
        //! Implementation of algorithm by Morrison & Stephenson (1982) for DeltaT computation
753
        //! @param jDay the date and time expressed as a Julian day
754
        //! @return Delta-T in seconds
755
        double getDeltaTByMorrisonStephenson1982(const double jDay);
756

757
        //! Get Delta-T estimation for a given date.
758
        //! Implementation of algorithm by Stephenson & Morrison (1984) for DeltaT computation
759
        //! Source: Long-term changes in the rotation of the earth - 700 B.C. to A.D. 1980.
760
        //! Stephenson, F. R.; Morrison, L. V.
761
        //! Philosophical Transactions, Series A (ISSN 0080-4614), vol. 313, no. 1524, Nov. 27, 1984, p. 47-70.
762
        //! 1984RSPTA.313...47S [http://adsabs.harvard.edu/abs/1984RSPTA.313...47S]
763
        //! @param jDay the date and time expressed as a Julian day
764
        //! @return Delta-T in seconds or Zero if date outside years -391..1600
765
        double getDeltaTByStephensonMorrison1984(const double jDay);
766

767
        //! Get Delta-T estimation for a given date.
768
        //! Implementation of algorithm by Stephenson & Morrison (1995) for DeltaT computation
769
        //! Source: Long-Term Fluctuations in the Earth's Rotation: 700 BC to AD 1990.
770
        //! Stephenson, F. R.; Morrison, L. V.
771
        //! Philosophical Transactions: Physical Sciences and Engineering, Volume 351, Issue 1695, pp. 165-202
772
        //! 1995RSPTA.351..165S [http://adsabs.harvard.edu/abs/1995RSPTA.351..165S]
773
        //! @param jDay the date and time expressed as a Julian day
774
        //! @return Delta-T in seconds
775
        double getDeltaTByStephensonMorrison1995(const double jDay);
776

777
        //! Get Delta-T estimation for a given date.
778
        //! Implementation of algorithm by Stephenson & Houlden (1986) for DeltaT computation
779
        //! Source: STEPHENSON F.R and HOULDEN M.A. - Atlas of Historical Eclipse Maps - Cambridge Univ.Press. (1986)
780
        //! [https://assets.cambridge.org/97805212/67236/frontmatter/9780521267236_frontmatter.pdf]
781
        //! @param jDay the date and time expressed as a Julian day
782
        //! @return Delta-T in seconds or 0 if year > 1600
783
        double getDeltaTByStephensonHoulden(const double jDay);
784

785
        //! Get Delta-T estimation for a given date.
786
        //! Implementation of algorithm by Espenak (1987, 1989) for DeltaT computation.
787
        //! This relation should not be used before around 1950 or after around 2100 (Espenak, pers. comm.).
788
        //! @param jDay the date and time expressed as a Julian day
789
        //! @return Delta-T in seconds
790
        double getDeltaTByEspenak(const double jDay);
791

792
        //! Get Delta-T estimation for a given date.
793
        //! Implementation of algorithm by Borkowski (1988) for DeltaT computation.
794
        //! Source: ELP 2000-85 and the dynamic time-universal time relation
795
        //! Borkowski, K. M.
796
        //! Astronomy and Astrophysics (ISSN 0004-6361), vol. 205, no. 1-2, Oct. 1988, p. L8-L10.
797
        //! 1988A&A...205L...8B [http://adsabs.harvard.edu/abs/1988A&A...205L...8B]
798
        //! @param jDay the date and time expressed as a Julian day
799
        //! @return Delta-T in seconds
800
        double getDeltaTByBorkowski(const double jDay);
801

802
        //! Get Delta-T estimation for a given date.
803
        //! Implementation of algorithm by Schmadel & Zech (1988) for DeltaT computation.
804
        //! Source: Empirical Transformations from U.T. to E.T. for the Period 1800-1988
805
        //! Schmadel, L. D.; Zech, G.
806
        //! Astronomische Nachrichten 309, 219-221
807
        //! 1988AN....309..219S [http://adsabs.harvard.edu/abs/1988AN....309..219S]
808
        //! @param jDay the date and time expressed as a Julian day
809
        //! @return Delta-T in seconds
810
        //! @note The polynome is strictly applicable 1800...1988 only! Delivers values for the nearer edge (1800/1989) if jDay is outside.
811
        double getDeltaTBySchmadelZech1988(const double jDay);
812

813
        //! Get Delta-T estimation for a given date.
814
        //! Implementation of algorithm by Chapront-Touzé & Chapront (1991) for DeltaT computation
815
        //! @param jDay the date and time expressed as a Julian day
816
        //! @return Delta-T in seconds or 0 if year not in -391..1600
817
        double getDeltaTByChaprontTouze(const double jDay);        
818

819
        //! Get Delta-T estimation for a given date.
820
        //! Implementation of the "historical" part of the algorithm by JPL Horizons for DeltaT computation.
821
        //! @param jDay the date and time expressed as a Julian day
822
        //! @return Delta-T in seconds or 0 if year not in -2999..1620 (!)
823
        double getDeltaTByJPLHorizons(const double jDay);
824

825
        //! Get Delta-T estimation for a given date.
826
        //! Implementation of algorithm by Morrison & Stephenson (2004, 2005) for DeltaT computation.
827
        //! Sources: Historical values of the Earth's clock error ΔT and the calculation of eclipses
828
        //! Morrison, L. V.; Stephenson, F. R.
829
        //! Journal for the History of Astronomy (ISSN 0021-8286), Vol. 35, Part 3, No. 120, p. 327 - 336 (2004)
830
        //! 2004JHA....35..327M [http://adsabs.harvard.edu/abs/2004JHA....35..327M]
831
        //! Addendum: Historical values of the Earth's clock error
832
        //! Morrison, L. V.; Stephenson, F. R.
833
        //! Journal for the History of Astronomy (ISSN 0021-8286), Vol. 36, Part 3, No. 124, p. 339 (2005)
834
        //! 2005JHA....36..339M [http://adsabs.harvard.edu/abs/2005JHA....36..339M]
835
        //! @param jDay the date and time expressed as a Julian day
836
        //! @return Delta-T in seconds
837
        double getDeltaTByMorrisonStephenson2004(const double jDay);
838

839
        //! Get Delta-T estimation for a given date.
840
        //! Implementation of algorithm by Reijs (2006) for DeltaT computation
841
        //! Details: http://www.iol.ie/~geniet/eng/DeltaTeval.htm
842
        //! @param jDay the date and time expressed as a Julian day
843
        //! @return Delta-T in seconds
844
        double getDeltaTByReijs(const double jDay);
845

846
        //! Get Delta-T estimation for a given date.
847
        //! Implementation of algorithm by Chapront, Chapront-Touze & Francou (1997) & Meeus (1998) for DeltaT computation
848
        //! @param jDay the date and time expressed as a Julian day
849
        //! @return Delta-T in seconds
850
        double getDeltaTByChaprontMeeus(const double jDay);
851

852
        //! Get Delta-T estimation for a given date.
853
        //! Implementation of algorithm by Meeus & Simons (2000) for DeltaT computation.
854
        //! Source: Polynomial approximations to Delta T, 1620-2000 AD
855
        //! Meeus, J.; Simons, L.
856
        //! Journal of the British Astronomical Association, vol.110, no.6, 323
857
        //! 2000JBAA..110..323M [http://adsabs.harvard.edu/abs/2000JBAA..110..323M]
858
        //! @param jDay the date and time expressed as a Julian day
859
        //! @return Delta-T in seconds or 0 if year not in 1620..2000
860
        double getDeltaTByMeeusSimons(const double jDay);
861

862
        //! Get Delta-T estimation for a given date.
863
        //! Implementation of algorithm by Montenbruck & Pfleger (2000) for DeltaT computation,
864
        //! a data fit through the table of values found in Meeus, Astronomical algorithms (1991).
865
        //! Book "Astronomy on the Personal Computer" by O. Montenbruck & T. Pfleger (4th ed., 2000), p.181-182
866
        //! @param jDay the date and time expressed as a Julian day
867
        //! @return Delta-T in seconds or 0 if not 1825<=year<2005
868
        double getDeltaTByMontenbruckPfleger(const double jDay);
869

870
        //! Get Delta-T estimation for a given date.
871
        //! Implementation of algorithm by Reingold & Dershowitz (1997, 2001, 2002, 2007, 2018) for DeltaT computation.
872
        //! This is again mostly a data fit based on the table in Meeus, Astronomical Algorithms (1991).
873
        //! This is the version given in the 4th edition ("the ultimate edition"; 2018) which added the fit
874
        //! for -500..1699 and 2006..2150 omitted from previous editions.
875
        //! Calendrical Calculations: The Ultimate Edition / Edward M. Reingold, Nachum Dershowitz - 4th Edition,
876
        //! Cambridge University Press, 2018. - 660p. ISBN: 9781107057623, DOI: 10.1017/9781107415058
877
        //! @param jDay the date and time expressed as a Julian day
878
        //! @return Delta-T in seconds
879
        double getDeltaTByReingoldDershowitz(const double jDay);
880

881
        //! Get Delta-T estimation for a given date.
882
        //! Implementation of algorithm by Banjevic (2006) for DeltaT computation.
883
        //! Source: Ancient eclipses and dating the fall of Babylon
884
        //! Banjevic, B.
885
        //! Publications of the Astronomical Observatory of Belgrade, Vol. 80, p. 251-257 (2006)
886
        //! 2006POBeo..80..251B [http://adsabs.harvard.edu/abs/2006POBeo..80..251B]
887
        //! @param jDay the date and time expressed as a Julian day
888
        //! @return Delta-T in seconds
889
        double getDeltaTByBanjevic(const double jDay);
890

891
        //! Get Delta-T estimation for a given date.
892
        //! Implementation of algorithm by Islam, Sadiq & Qureshi (2008 + revisited 2013) for DeltaT computation.
893
        //! Source: Error Minimization of Polynomial Approximation of DeltaT
894
        //! Islam, S. & Sadiq, M. & Qureshi, M. S.
895
        //! Journal of Astrophysics & Astronomy, Vol. 29, p. 363-366 (2008)
896
        //! http://www.ias.ac.in/jaa/dec2008/JAA610.pdf
897
        //! Note: These polynomials are based on the uncorrected deltaT table from the Astronomical Almanac, thus
898
        //! ndot = -26.0 arcsec/cy^2. Meeus & Simons (2000) corrected the deltaT table for years before 1955.5 using
899
        //! ndot = -25.7376 arcsec/cy^2. Therefore the accuracies stated by Meeus & Simons are correct and cannot be
900
        //! compared with accuracies from Islam & Sadiq & Qureshi.
901
        //! @param jDay the date and time expressed as a Julian day
902
        //! @return Delta-T in seconds
903
        double getDeltaTByIslamSadiqQureshi(const double jDay);
904

905
        //! Get Delta-T estimation for a given date.
906
        //! Implementation of polynomial approximation of time period 1620-2013 for DeltaT by M. Khalid, Mariam Sultana and Faheem Zaidi (2014).
907
        //! Source: Delta T: Polynomial Approximation of Time Period 1620-2013
908
        //! Journal of Astrophysics, Vol. 2014, Article ID 480964
909
        //! https://doi.org/10.1155/2014/480964
910
        //! @param jDay the date and time expressed as a Julian day
911
        //! @return Delta-T in seconds
912
        double getDeltaTByKhalidSultanaZaidi(const double jDay);
913

914
        //! Get Delta-T estimation for a given date.
915
        //! Implementation of a spline approximation for time period -720-2019.0 for DeltaT by Stephenson, Morrison and Hohenkerk (2016).
916
        //! Source: Measurement of the Earth's rotation: 720 BC to AD 2015, published in 2016 in the Royal Society's
917
        //! Proceedings A 472, and made freely available via Open Access, by Stephenson, F.R., Morrison, L.V. and
918
        //! Hohenkerk, C.Y..
919
        //! https://doi.org/10.1098/rspa.2016.0404
920
        //! Addendum 2020 to "Measurement of the Earth's Rotation: 720 BC to AD 2015", published in 2021 February
921
        //! in the Royal Society's Proceedings A 478, by Morrison, L. V., Stephenson, F.R., Hohenkerk, C.Y. and
922
        //! M. Zawilski, M..
923
        //! https://doi.org/10.1098/rspa.2020.0776
924
        //! @param jDay the date and time expressed as a Julian day
925
        //! @return Delta-T in seconds. For times outside the limits, return result from the fitting parabola.
926
        double getDeltaTByStephensonMorrisonHohenkerk2016(const double jDay);
927

928
        //! Get Secular Acceleration estimation for a given year.
929
        //! Method described is here: http://eclipse.gsfc.nasa.gov/SEcat5/secular.html
930
        //! For adapting from -26 to -25.858, use -0.91072 * (-25.858 + 26.0) = -0.12932224
931
        //! For adapting from -26 to -23.895, use -0.91072 * (-23.895 + 26.0) = -1.9170656
932
        //! @param jDay the JD
933
        //! @param ndot value of n-dot (secular acceleration of the Moon) which should be used in the lunar ephemeris instead of the default values.
934
        //! @param useDE4xx true if function should adapt calculation of the secular acceleration of the Moon to the DE43x/DE44x ephemerides
935
        //! @return SecularAcceleration in seconds
936
        //! @note n-dot for secular acceleration of the Moon in ELP2000-82B is -23.8946 "/cy/cy and for DE43x/DE44x is -25.8 "/cy/cy
937
        double getMoonSecularAcceleration(const double jDay, const double ndot, const bool useDE4xx);
938

939
        //! Get the standard error (sigma) for the value of DeltaT
940
        //! @param jDay the JD
941
        //! @return sigma in seconds
942
        double getDeltaTStandardError(const double jDay);
943

944
        //! Get value of the Moon fluctuation
945
        //! Source: The Rotation of the Earth, and the Secular Accelerations of the Sun, Moon and Planets
946
        //! Spencer Jones, H.
947
        //! Monthly Notices of the Royal Astronomical Society, 99 (1939), 541-558
948
        //! 1939MNRAS..99..541S [http://adsabs.harvard.edu/abs/1939MNRAS..99..541S]
949
        //! @param jDay the JD
950
        //! @return fluctuation in seconds
951
        double getMoonFluctuation(const double jDay);
952

953
        //! Sign function from http://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
954
        template <typename T> int sign(T val)
63,010✔
955
        {
956
                return (T(0) < val) - (val < T(0));
63,010✔
957
        }
958
        
959
        //! Compute cosines and sines around a circle which is split in "slices" parts.
960
        //! Values are stored in the global static array cos_sin_theta.
961
        //! Used for the sin/cos values along a latitude circle, equator, etc. for a spherical mesh.
962
        //! @param slices number of partitions (elsewhere called "segments") for the circle
963
        float *ComputeCosSinTheta(const unsigned int slices);
964
        
965
        //! Compute cosines and sines around a half-circle which is split in "segments" parts.
966
        //! Values are stored in the global static array cos_sin_rho.
967
        //! Used for the sin/cos values along a meridian for a spherical mesh.
968
        //! @param segments number of partitions (elsewhere called "stacks") for the half-circle
969
        float *ComputeCosSinRho(const unsigned int segments);
970
        
971
        //! Compute cosines and sines around part of a circle (from top to bottom) which is split in "segments" parts.
972
        //! Values are stored in the global static array cos_sin_rho.
973
        //! Used for the sin/cos values along a meridian.
974
        //! This allows leaving away pole caps. The array now contains values for the region minAngle+segments*phi
975
        //! @param dRho a difference angle between the stops
976
        //! @param segments number of segments
977
        //! @param minAngle start angle inside the half-circle. maxAngle=minAngle+segments*phi
978
        float* ComputeCosSinRhoZone(const float dRho, const unsigned int segments, const float minAngle);
979

980
        //! Calculate fixed days (R.D.) from Gregorian date (proleptic Gregorian calendar)
981
        //! @param year
982
        //! @param month
983
        //! @param day
984
        //! @return days from Rata Die
985
        int getFixedFromGregorian(const int year, const int month, const int day);
986

987
        //! Comparison two string versions and return a result in range -1,0,1
988
        //! @param v1 string for version 1
989
        //! @param v2 string for version 2
990
        //! @return result (-1: v1<v2; 0: v1==v2; 1: v1>v2)
991
        int compareVersions(const QString v1, const QString v2);
992

993
        //! Uncompress gzip or zlib compressed data.
994
        QByteArray uncompress(const QByteArray& data);
995

996
        //! Uncompress (gzip/zlib) data from this QIODevice, which must be open and readable.
997
        //! @param device The device to read from, must already be opened with an OpenMode supporting reading
998
        //! @param maxBytes The max. amount of bytes to read from the device, or -1 to read until EOF.  Note that it
999
        //! always stops when inflate() returns Z_STREAM_END. Positive values can be used for interleaving compressed data
1000
        //! with other data.
1001
        QByteArray uncompress(QIODevice &device, qint64 maxBytes=-1);
1002

1003
        //! Greatest Common Divisor (Euclid's algorithm)
1004
        //! @param a first number
1005
        //! @param b second number
1006
        //! @return Greatest Common Divisor
1007
        int gcd(int a, int b);
1008

1009
        //! Least Common Multiple
1010
        //! @param a first number
1011
        //! @param b second number
1012
        //! @return Least Common Multiple
1013
        int lcm(int a, int b);
1014

1015
        //! Given regularly spaced steps x1, x2, x3 and curve values y1, y2, y3,
1016
        //! calculate an intermediate value of the 3 arguments for the given interpolation point n.
1017
        //! @param n Interpolation factor: steps from x2
1018
        //! @param y1 Argument 1
1019
        //! @param y2 Argument 2
1020
        //! @param y3 Argument 3
1021
        //! @return interpolation value
1022
        template<class T> T interpolate3(T n, T y1, T y2, T y3)
3✔
1023
        {
1024
                // See "Astronomical Algorithms" by J. Meeus
1025

1026
                // Equation 3.2
1027
                T a = y2-y1;
3✔
1028
                T b = y3-y2;
3✔
1029
                T c = b-a;
3✔
1030

1031
                // Equation 3.3
1032
                return y2 + n * 0.5f * (a + b + n * c);
3✔
1033
        }
1034

1035
        //! Given regularly spaced steps x1, x2, x3, x4, x5 and curve values y1, y2, y3, y4, y5,
1036
        //! calculate an intermediate value of the 5 arguments for the given interpolation point n.
1037
        //! @param n Interpolation factor: steps from x3
1038
        //! @param y1 Argument 1
1039
        //! @param y2 Argument 2
1040
        //! @param y3 Argument 3
1041
        //! @param y4 Argument 4
1042
        //! @param y5 Argument 5
1043
        //! @return interpolation value
1044
        template<class T> T interpolate5(T n, T y1, T y2, T y3, T y4, T y5)
1✔
1045
        {
1046
                // See "Astronomical Algorithms" by J. Meeus
1047
                // Eq. 3.8
1048
                T A=y2-y1; T B=y3-y2; T C=y4-y3; T D=y5-y4;
1✔
1049
                T E=B-A; T F=C-B; T G=D-C;
1✔
1050
                T H=F-E; T J=G-F;
1✔
1051
                T K=J-H;
1✔
1052

1053
                return (((K*(1.0/24.0)*n + (H+J)/12.0)*n  + (F*0.5-K/24.0))*n + ((B+C)*0.5 - (H+J)/12.0))*n +y3;
1✔
1054
        }
1055

1056
        //! Interval test. This checks whether @p value is within [@p low, @p high]
1057
        template <typename T> bool isWithin(const T& value, const T& low, const T& high)
8✔
1058
        {
1059
                return !(value < low) && !(high < value);
8✔
1060
        }
1061

1062
        template <class Arg1, class Arg2, class Result>
1063
        struct binary_function
1064
        {
1065
                typedef Arg1 first_argument_type;
1066
                typedef Arg2 second_argument_type;
1067
                typedef Result result_type;
1068
        };
1069

1070

1071
#ifdef _MSC_BUILD
1072
        inline double trunc(double x)
1073
        {
1074
                return (x < 0 ? std::ceil(x) : std::floor(x));
1075
        }
1076
        inline float trunc(float x)
1077
        {
1078
                return (x < 0 ? std::ceil(x) : std::floor(x));
1079
        }
1080
#else
1081
        inline double trunc(double x) { return ::trunc(x); }
6✔
1082
        inline float trunc(float x) { return ::trunc(x); }
6✔
1083
#endif
1084
}
1085

1086
#endif // STELUTILS_HPP
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc