File indexing completed on 2024-04-21 03:44:44

0001 /*
0002     SPDX-FileCopyrightText: 2001-2005 Jason Harris <jharris@30doradus.org>
0003     SPDX-FileCopyrightText: 2004-2005 Pablo de Vicente <p.devicente@wanadoo.es>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 
0010 #include "cachingdms.h"
0011 #include "kstarsdatetime.h"
0012 
0013 #include <QList>
0014 #ifndef KSTARS_LITE
0015 #include <QDBusArgument>
0016 #endif
0017 
0018 //#define PROFILE_COORDINATE_CONVERSION
0019 
0020 class KSNumbers;
0021 class KSSun;
0022 class GeoLocation;
0023 
0024 /**
0025  * @class SkyPoint
0026  *
0027  * The sky coordinates of a point in the sky.  The
0028  * coordinates are stored in both Equatorial (Right Ascension,
0029  * Declination) and Horizontal (Azimuth, Altitude) coordinate systems.
0030  * Provides set/get functions for each coordinate angle, and functions
0031  * to convert between the Equatorial and Horizon coordinate systems.
0032  *
0033  * Because the coordinate values change slowly over time (due to
0034  * precession, nutation), the "catalog coordinates" are stored
0035  * (RA0, Dec0), which were the true coordinates on Jan 1, 2000.
0036  * The true coordinates (RA, Dec) at any other epoch can be found
0037  * from the catalog coordinates using updateCoords().
0038  * @short Stores dms coordinates for a point in the sky.
0039  * for converting between coordinate systems.
0040  *
0041  * @author Jason Harris
0042  * @version 1.0
0043  */
0044 class SkyPoint
0045 {
0046     public:
0047         /**
0048          * Default constructor: Sets RA, Dec and RA0, Dec0 according
0049          * to arguments.  Does not set Altitude or Azimuth.
0050          *
0051          * @param r Right Ascension
0052          * @param d Declination
0053          */
0054         SkyPoint(const dms &r, const dms &d) : RA0(r), Dec0(d), RA(r), Dec(d), lastPrecessJD(J2000) {}
0055 
0056         SkyPoint(const CachingDms &r, const CachingDms &d) : RA0(r), Dec0(d), RA(r), Dec(d), lastPrecessJD(J2000) {}
0057 
0058         /**
0059          * Alternate constructor using double arguments, for convenience.
0060          * It behaves essentially like the default constructor.
0061          *
0062          * @param r Right Ascension, expressed as a double
0063          * @param d Declination, expressed as a double
0064          * @note This also sets RA0 and Dec0
0065          */
0066         //FIXME: this (*15.0) thing is somewhat hacky.
0067         explicit SkyPoint(double r, double d) : RA0(r * 15.0), Dec0(d), RA(r * 15.0), Dec(d), lastPrecessJD(J2000) {}
0068 
0069         /** @short Default constructor. Sets nonsense values for RA, Dec etc */
0070         SkyPoint();
0071 
0072         virtual ~SkyPoint() = default;
0073 
0074         ////
0075         //// 1.  Setting Coordinates
0076         //// =======================
0077 
0078         /**
0079          * @short Sets RA, Dec and RA0, Dec0 according to arguments.
0080          * Does not set Altitude or Azimuth.
0081          *
0082          * @param r Right Ascension
0083          * @param d Declination
0084          * @note This function also sets RA0 and Dec0 to the same values, so call at your own peril!
0085          * @note FIXME: This method must be removed, or an epoch argument must be added.
0086          */
0087         void set(const dms &r, const dms &d);
0088 
0089         /**
0090          * Sets RA0, the catalog Right Ascension.
0091          *
0092          * @param r catalog Right Ascension.
0093          */
0094         inline void setRA0(dms r)
0095         {
0096             RA0 = r;
0097         }
0098         inline void setRA0(CachingDms r)
0099         {
0100             RA0 = r;
0101         }
0102 
0103         /**
0104          * Overloaded member function, provided for convenience.
0105          * It behaves essentially like the above function.
0106          *
0107          * @param r Right Ascension, expressed as a double.
0108          */
0109         inline void setRA0(double r)
0110         {
0111             RA0.setH(r);
0112         }
0113 
0114         /**
0115          * Sets Dec0, the catalog Declination.
0116          *
0117          * @param d catalog Declination.
0118          */
0119         inline void setDec0(dms d)
0120         {
0121             Dec0 = d;
0122         }
0123         inline void setDec0(const CachingDms &d)
0124         {
0125             Dec0 = d;
0126         }
0127 
0128         /**
0129          * Overloaded member function, provided for convenience.
0130          * It behaves essentially like the above function.
0131          *
0132          * @param d Declination, expressed as a double.
0133          */
0134         inline void setDec0(double d)
0135         {
0136             Dec0.setD(d);
0137         }
0138 
0139         /**
0140          * Sets RA, the current Right Ascension.
0141          *
0142          * @param r Right Ascension.
0143          */
0144         inline void setRA(dms &r)
0145         {
0146             RA = r;
0147         }
0148         inline void setRA(const CachingDms &r)
0149         {
0150             RA = r;
0151         }
0152 
0153         /**
0154          * Overloaded member function, provided for convenience.
0155          * It behaves essentially like the above function.
0156          *
0157          * @param r Right Ascension, expressed as a double.
0158          */
0159         inline void setRA(double r)
0160         {
0161             RA.setH(r);
0162         }
0163 
0164         /**
0165          * Sets Dec, the current Declination
0166          *
0167          * @param d Declination.
0168          */
0169         inline void setDec(dms d)
0170         {
0171             Dec = d;
0172         }
0173         inline void setDec(const CachingDms &d)
0174         {
0175             Dec = d;
0176         }
0177 
0178         /**
0179          * Overloaded member function, provided for convenience.
0180          * It behaves essentially like the above function.
0181          *
0182          * @param d Declination, expressed as a double.
0183          */
0184         inline void setDec(double d)
0185         {
0186             Dec.setD(d);
0187         }
0188 
0189         /**
0190          * Sets Alt, the Altitude.
0191          *
0192          * @param alt Altitude.
0193          */
0194         inline void setAlt(dms alt)
0195         {
0196             Alt = alt;
0197         }
0198 
0199         /**
0200          * Sets the apparent altitude, checking whether refraction corrections are enabled
0201          *
0202          * @param alt_apparent Apparent altitude (subject to Options::useRefraction())
0203          */
0204         void setAltRefracted(dms alt_apparent);
0205 
0206         /**
0207          * Overloaded member function, provided for convenience.
0208          * It behaves essentially like the above function.
0209          *
0210          * @param alt_apparent Apparent altitude (subject to Options::useRefraction())
0211          */
0212         void setAltRefracted(double alt_apparent);
0213 
0214         /**
0215          * Overloaded member function, provided for convenience.
0216          * It behaves essentially like the above function.
0217          *
0218          * @param alt Altitude, expressed as a double.
0219          */
0220         inline void setAlt(double alt)
0221         {
0222             Alt.setD(alt);
0223         }
0224 
0225         /**
0226          * Sets Az, the Azimuth.
0227          *
0228          * @param az Azimuth.
0229          */
0230         inline void setAz(dms az)
0231         {
0232             Az = az;
0233         }
0234 
0235         /**
0236          * Overloaded member function, provided for convenience.
0237          * It behaves essentially like the above function.
0238          *
0239          * @param az Azimuth, expressed as a double.
0240          */
0241         inline void setAz(double az)
0242         {
0243             Az.setD(az);
0244         }
0245 
0246         ////
0247         //// 2. Returning coordinates.
0248         //// =========================
0249 
0250         /** @return a pointer to the catalog Right Ascension. */
0251         inline const CachingDms &ra0() const
0252         {
0253             return RA0;
0254         }
0255 
0256         /** @return a pointer to the catalog Declination. */
0257         inline const CachingDms &dec0() const
0258         {
0259             return Dec0;
0260         }
0261 
0262         /** @returns a pointer to the current Right Ascension. */
0263         inline const CachingDms &ra() const
0264         {
0265             return RA;
0266         }
0267 
0268         /** @return a pointer to the current Declination. */
0269         inline const CachingDms &dec() const
0270         {
0271             return Dec;
0272         }
0273 
0274         /** @return a pointer to the current Azimuth. */
0275         inline const dms &az() const
0276         {
0277             return Az;
0278         }
0279 
0280         /** @return a pointer to the current Altitude. */
0281         inline const dms &alt() const
0282         {
0283             return Alt;
0284         }
0285 
0286         /**
0287          * @return refracted altitude. This function uses
0288          * Options::useRefraction to determine whether refraction
0289          * correction should be applied
0290          */
0291         dms altRefracted() const;
0292 
0293         /** @return the JD for the precessed coordinates */
0294         inline double getLastPrecessJD() const
0295         {
0296             return lastPrecessJD;
0297         }
0298 
0299         /**
0300          * @return the airmass of the point. Convenience method.
0301          * @note Question: is it better to use alt or refracted alt? Minor difference, probably doesn't matter.
0302          */
0303         inline double airmass() const
0304         {
0305             return 1. / sin(alt().radians());
0306         }
0307 
0308         ////
0309         //// 3. Coordinate conversions.
0310         //// ==========================
0311 
0312         /**
0313          * Determine the (Altitude, Azimuth) coordinates of the
0314          * SkyPoint from its (RA, Dec) coordinates, given the local
0315          * sidereal time and the observer's latitude.
0316          * @param LST pointer to the local sidereal time
0317          * @param lat pointer to the geographic latitude
0318          */
0319         void EquatorialToHorizontal(const CachingDms *LST, const CachingDms *lat);
0320 
0321         // Deprecated method provided for compatibility
0322         void EquatorialToHorizontal(const dms *LST, const dms *lat);
0323 
0324         /**
0325          * Determine the (RA, Dec) coordinates of the
0326          * SkyPoint from its (Altitude, Azimuth) coordinates, given the local
0327          * sidereal time and the observer's latitude.
0328          *
0329          * @param LST pointer to the local sidereal time
0330          * @param lat pointer to the geographic latitude
0331          */
0332         void HorizontalToEquatorial(const dms *LST, const dms *lat);
0333 
0334         /**
0335          * Determine the Ecliptic coordinates of the SkyPoint, given the Julian Date.
0336          * The ecliptic coordinates are returned as reference arguments (since
0337          * they are not stored internally)
0338          */
0339         void findEcliptic(const CachingDms *Obliquity, dms &EcLong, dms &EcLat);
0340 
0341         /**
0342          * Set the current (RA, Dec) coordinates of the
0343          * SkyPoint, given pointers to its Ecliptic (Long, Lat) coordinates, and
0344          * to the current obliquity angle (the angle between the equator and ecliptic).
0345          */
0346         void setFromEcliptic(const CachingDms *Obliquity, const dms &EcLong, const dms &EcLat);
0347 
0348         /**
0349          * Computes galactic coordinates from equatorial coordinates referred to
0350          * epoch 1950. RA and Dec are, therefore assumed to be B1950 coordinates.
0351          */
0352         void Equatorial1950ToGalactic(dms &galLong, dms &galLat);
0353 
0354         /**
0355          * Computes equatorial coordinates referred to 1950 from galactic ones referred to
0356          * epoch B1950. RA and Dec are, therefore assumed to be B1950 coordinates.
0357          */
0358         void GalacticToEquatorial1950(const dms *galLong, const dms *galLat);
0359 
0360         ////
0361         //// 4. Coordinate update/corrections.
0362         //// =================================
0363 
0364         /**
0365          * Determine the current coordinates (RA, Dec) from the catalog
0366          * coordinates (RA0, Dec0), accounting for both precession and nutation.
0367          * @param num pointer to KSNumbers object containing current values of time-dependent variables.
0368          * @param includePlanets does nothing in this implementation (see KSPlanetBase::updateCoords()).
0369          * @param lat does nothing in this implementation (see KSPlanetBase::updateCoords()).
0370          * @param LST does nothing in this implementation (see KSPlanetBase::updateCoords()).
0371          * @param forceRecompute reapplies precession, nutation and aberration even if the time passed
0372          * since the last computation is not significant.
0373          */
0374         virtual void updateCoords(const KSNumbers *num, bool includePlanets = true, const CachingDms *lat = nullptr,
0375                                   const CachingDms *LST = nullptr, bool forceRecompute = false);
0376 
0377         /**
0378          * @brief updateCoordsNow Shortcut for updateCoords( const KSNumbers *num, false, nullptr, nullptr, true)
0379          *
0380          * @param num pointer to KSNumbers object containing current values of time-dependent variables.
0381          */
0382         virtual void updateCoordsNow(const KSNumbers *num)
0383         {
0384             updateCoords(num, false, nullptr, nullptr, true);
0385         }
0386 
0387         /**
0388          * Computes the apparent coordinates for this SkyPoint for any epoch,
0389          * accounting for the effects of precession, nutation, and aberration.
0390          * Similar to updateCoords(), but the starting epoch need not be
0391          * J2000, and the target epoch need not be the present time.
0392          *
0393          * @param jd0 Julian Day which identifies the original epoch
0394          * @param jdf Julian Day which identifies the final epoch
0395          */
0396         void apparentCoord(long double jd0, long double jdf);
0397 
0398         /**
0399          * Computes the J2000.0 catalogue coordinates for this SkyPoint using the epoch
0400          * removing aberration, nutation and precession
0401          * Catalogue coordinates are in Ra0, Dec0 as well as Ra, Dec and lastPrecessJD is set to J2000.0
0402          *
0403          * @FIXME We do not undo nutation and aberration
0404          * @brief catalogueCoord converts observed to J2000 using epoch jdf
0405          * @param jdf Julian Day which identifies the current epoch
0406          * @return SpyPoint containing J2000 coordinates
0407          */
0408 
0409         SkyPoint catalogueCoord(long double jdf);
0410 
0411 
0412         /**
0413          * Apply the effects of nutation to this SkyPoint.
0414          *
0415          * @param num pointer to KSNumbers object containing current values of
0416          * time-dependent variables.
0417          * @param reverse bool, if true the nutation is removed
0418          */
0419         void nutate(const KSNumbers *num, const bool reverse = false);
0420 
0421         /**
0422          * @short Check if this sky point is close enough to the sun for
0423          * gravitational lensing to be significant
0424          */
0425         bool checkBendLight();
0426 
0427         /**
0428          * Correct for the effect of "bending" of light around the sun for
0429          * positions near the sun.
0430          *
0431          * General Relativity tells us that a photon with an impact
0432          * parameter b is deflected through an angle 1.75" (Rs / b) where
0433          * Rs is the solar radius.
0434          *
0435          * @return: true if the light was bent, false otherwise
0436          */
0437         bool bendlight();
0438 
0439         /**
0440          * @short Obtain a Skypoint with RA0 and Dec0 set from the RA, Dec
0441          * of this skypoint. Also set the RA0, Dec0 of this SkyPoint if not
0442          * set already and the target epoch is J2000.
0443          */
0444         SkyPoint deprecess(const KSNumbers *num, long double epoch = J2000);
0445 
0446         /**
0447          * Determine the effects of aberration for this SkyPoint.
0448          *
0449          * @param num pointer to KSNumbers object containing current values of
0450          * time-dependent variables.
0451          * @param reverse bool, if true the aberration is removed.
0452          */
0453         void aberrate(const KSNumbers *num, bool reverse = false);
0454 
0455         /**
0456          * General case of precession. It precess from an original epoch to a
0457          * final epoch. In this case RA0, and Dec0 from SkyPoint object represent
0458          * the coordinates for the original epoch and not for J2000, as usual.
0459          *
0460          * @param jd0 Julian Day which identifies the original epoch
0461          * @param jdf Julian Day which identifies the final epoch
0462          */
0463         void precessFromAnyEpoch(long double jd0, long double jdf);
0464 
0465         /**
0466          * Determine the E-terms of aberration
0467          * In the past, the mean places of stars published in catalogs included
0468          * the contribution to the aberration due to the ellipticity of the orbit
0469          * of the Earth. These terms, known as E-terms were almost constant, and
0470          * in the newer catalogs (FK5) are not included. Therefore to convert from
0471          * FK4 to FK5 one has to compute these E-terms.
0472          */
0473         SkyPoint Eterms(void);
0474 
0475         /**
0476          * Exact precession from Besselian epoch 1950 to epoch J2000. The
0477          * coordinates referred to the first epoch are in the
0478          * FK4 catalog, while the latter are in the Fk5 one.
0479          *
0480          * Reference: Smith, C. A.; Kaplan, G. H.; Hughes, J. A.; Seidelmann,
0481          * P. K.; Yallop, B. D.; Hohenkerk, C. Y.
0482          * Astronomical Journal, vol. 97, Jan. 1989, p. 265-279
0483          *
0484          * This transformation requires 4 steps:
0485          * - Correct E-terms
0486          * - Precess from B1950 to 1984, January 1st, 0h, using Newcomb expressions
0487          * - Add zero point correction in right ascension for 1984
0488          * - Precess from 1984, January 1st, 0h to J2000
0489          */
0490         void B1950ToJ2000(void);
0491 
0492         /**
0493          * Exact precession from epoch J2000 Besselian epoch 1950. The coordinates
0494          * referred to the first epoch are in the FK4 catalog, while the
0495          * latter are in the Fk5 one.
0496          *
0497          * Reference: Smith, C. A.; Kaplan, G. H.; Hughes, J. A.; Seidelmann,
0498          * P. K.; Yallop, B. D.; Hohenkerk, C. Y.
0499          * Astronomical Journal, vol. 97, Jan. 1989, p. 265-279
0500          *
0501          * This transformation requires 4 steps:
0502          * - Precess from J2000 to 1984, January 1st, 0h
0503          * - Add zero point correction in right ascension for 1984
0504          * - Precess from 1984, January 1st, 0h, to B1950 using Newcomb expressions
0505          * - Correct E-terms
0506          */
0507         void J2000ToB1950(void);
0508 
0509         /**
0510          * Coordinates in the FK4 catalog include the effect of aberration due
0511          * to the ellipticity of the orbit of the Earth. Coordinates in the FK5
0512          * catalog do not include these terms. In order to convert from B1950 (FK4)
0513          * to actual mean places one has to use this function.
0514          */
0515         void addEterms(void);
0516 
0517         /**
0518          * Coordinates in the FK4 catalog include the effect of aberration due
0519          * to the ellipticity of the orbit of the Earth. Coordinates in the FK5
0520          * catalog do not include these terms. In order to convert from
0521          * FK5 coordinates to B1950 (FK4) one has to use this function.
0522          */
0523         void subtractEterms(void);
0524 
0525         /**
0526          * Computes the angular distance between two SkyObjects. The algorithm
0527          * to compute this distance is:
0528          * cos(distance) = sin(d1)*sin(d2) + cos(d1)*cos(d2)*cos(a1-a2)
0529          * where a1,d1 are the coordinates of the first object and a2,d2 are
0530          * the coordinates of the second object.
0531          * However this algorithm is not accurate when the angular separation is small.
0532          * Meeus provides a different algorithm in page 111 which we implement here.
0533          *
0534          * @param sp SkyPoint to which distance is to be calculated
0535          * @param positionAngle if a non-null pointer is passed, the position angle [E of N]
0536          * in degrees from this SkyPoint to sp is computed and stored in the passed variable.
0537          * @return dms angle representing angular separation.
0538          **/
0539         dms angularDistanceTo(const SkyPoint *sp, double *const positionAngle = nullptr) const;
0540 
0541         /** @return returns true if _current_ epoch RA / Dec match */
0542         inline bool operator==(SkyPoint &p) const
0543         {
0544             return (ra() == p.ra() && dec() == p.dec());
0545         }
0546 
0547         /**
0548          * Computes the velocity of the Sun projected on the direction of the source.
0549          *
0550          * @param jd Epoch expressed as julian day to which the source coordinates refer to.
0551          * @return Radial velocity of the source referred to the barycenter of the solar system in km/s
0552          **/
0553         double vRSun(long double jd);
0554 
0555         /**
0556          * Computes the radial velocity of a source referred to the solar system barycenter
0557          * from the radial velocity referred to the
0558          * Local Standard of Rest, aka known as VLSR. To compute it we need the coordinates of the
0559          * source the VLSR and the epoch for the source coordinates.
0560          *
0561          * @param vlsr radial velocity of the source referred to the LSR in km/s
0562          * @param jd Epoch expressed as julian day to which the source coordinates refer to.
0563          * @return Radial velocity of the source referred to the barycenter of the solar system in km/s
0564          **/
0565         double vHeliocentric(double vlsr, long double jd);
0566 
0567         /**
0568          * Computes the radial velocity of a source referred to the Local Standard of Rest, also known as VLSR
0569          * from the radial velocity referred to the solar system barycenter
0570          *
0571          * @param vhelio radial velocity of the source referred to the LSR in km/s
0572          * @param jd Epoch expressed as julian day to which the source coordinates refer to.
0573          * @return Radial velocity of the source referred to the barycenter of the solar system in km/s
0574          **/
0575         double vHelioToVlsr(double vhelio, long double jd);
0576 
0577         /**
0578          * Computes the velocity of any object projected on the direction of the source.
0579          *
0580          * @param jd0 Julian day for which we compute the direction of the source
0581          * @return velocity of the Earth projected on the direction of the source kms-1
0582          */
0583         double vREarth(long double jd0);
0584 
0585         /**
0586          * Computes the radial velocity of a source referred to the center of the earth
0587          * from the radial velocity referred to the solar system barycenter
0588          *
0589          * @param vhelio radial velocity of the source referred to the barycenter of the
0590          *               solar system in km/s
0591          * @param jd     Epoch expressed as julian day to which the source coordinates refer to.
0592          * @return Radial velocity of the source referred to the center of the Earth in km/s
0593          **/
0594         double vGeocentric(double vhelio, long double jd);
0595 
0596         /**
0597          * Computes the radial velocity of a source referred to the solar system barycenter
0598          * from the velocity referred to the center of the earth
0599          *
0600          * @param vgeo   radial velocity of the source referred to the center of the Earth [km/s]
0601          * @param jd     Epoch expressed as julian day to which the source coordinates refer to.
0602          * @return Radial velocity of the source referred to the solar system barycenter in km/s
0603          **/
0604         double vGeoToVHelio(double vgeo, long double jd);
0605 
0606         /**
0607          * Computes the velocity of any object (observer's site) projected on the
0608          * direction of the source.
0609          *
0610          * @param vsite velocity of that object in cartesian coordinates
0611          * @return velocity of the object projected on the direction of the source kms-1
0612          */
0613         double vRSite(double vsite[3]);
0614 
0615         /**
0616          * Computes the radial velocity of a source referred to the observer site on the surface
0617          * of the earth from the geocentric velocity and the velocity of the site referred to the center
0618          * of the Earth.
0619          *
0620          * @param vgeo radial velocity of the source referred to the center of the earth in km/s
0621          * @param vsite Velocity at which the observer moves referred to the center of the earth.
0622          * @return Radial velocity of the source referred to the observer's site in km/s
0623          **/
0624         double vTopocentric(double vgeo, double vsite[3]);
0625 
0626         /**
0627          * Computes the radial velocity of a source referred to the center of the Earth from
0628          * the radial velocity referred to an observer site on the surface of the earth
0629          *
0630          * @param vtopo radial velocity of the source referred to the observer's site in km/s
0631          * @param vsite Velocity at which the observer moves referred to the center of the earth.
0632          * @return Radial velocity of the source referred the center of the earth in km/s
0633          **/
0634         double vTopoToVGeo(double vtopo, double vsite[3]);
0635 
0636         /**
0637          * Find the SkyPoint obtained by moving distance dist
0638          * (arcseconds) away from the givenSkyPoint
0639          *
0640          * @param dist Distance to move through in arcseconds
0641          * @param from The SkyPoint to move away from
0642          * @return a SkyPoint that is at the dist away from this SkyPoint in the direction away from
0643          */
0644         SkyPoint moveAway(const SkyPoint &from, double dist) const;
0645 
0646         /** @short Check if this point is circumpolar at the given geographic latitude */
0647         bool checkCircumpolar(const dms *gLat) const;
0648 
0649         /** Calculate refraction correction. Parameter and return value are in degrees */
0650         static double refractionCorr(double alt);
0651 
0652         /**
0653          * @short Apply refraction correction to altitude, depending on conditional
0654          *
0655          * @param alt altitude to be corrected, in degrees
0656          * @param conditional an optional boolean to decide whether to apply the correction or not
0657          * @note If conditional is false, this method returns its argument unmodified. This is a convenience feature as it is often needed to gate these corrections.
0658          * @return altitude after refraction correction (if applicable), in degrees
0659          */
0660         static double refract(const double alt, bool conditional = true);
0661 
0662         /**
0663          * @short Remove refraction correction, depending on conditional
0664          *
0665          * @param alt altitude from which refraction correction must be removed, in degrees
0666          * @param conditional an optional boolean to decide whether to undo the correction or not
0667          * @return altitude without refraction correction, in degrees
0668          * @note If conditional is false, this method returns its argument unmodified. This is a convenience feature as it is often needed to gate these corrections.
0669          */
0670         static double unrefract(const double alt, bool conditional = true);
0671 
0672         /**
0673          * @short Apply refraction correction to altitude. Overloaded method using
0674          * dms provided for convenience
0675          * @see SkyPoint::refract( const double alt )
0676          */
0677         static inline dms refract(const dms alt, bool conditional = true)
0678         {
0679             return dms(refract(alt.Degrees(), conditional));
0680         }
0681 
0682         /**
0683          * @short Remove refraction correction. Overloaded method using
0684          * dms provided for convenience
0685          * @see SkyPoint::unrefract( const double alt )
0686          */
0687         static inline dms unrefract(const dms alt, bool conditional = true)
0688         {
0689             return dms(unrefract(alt.Degrees(), conditional));
0690         }
0691 
0692         /**
0693          * @short Compute the altitude of a given skypoint hour hours from the given date/time
0694          *
0695          * @param p SkyPoint whose altitude is to be computed (const pointer, the method works on a clone)
0696          * @param dt Date/time that corresponds to 0 hour
0697          * @param geo GeoLocation object specifying the location
0698          * @param hour double specifying offset in hours from dt for which altitude is to be found
0699          * @return a dms containing (unrefracted?) altitude of the object at dt + hour hours at the given location
0700          *
0701          * @note This method is used in multiple places across KStars
0702          * @todo Fix code duplication in AltVsTime and KSAlmanac by using this method instead! FIXME.
0703          */
0704         static dms findAltitude(const SkyPoint *p, const KStarsDateTime &dt, const GeoLocation *geo, const double hour = 0);
0705 
0706         /**
0707          * @short returns a time-transformed SkyPoint. See SkyPoint::findAltitude() for details
0708          * @todo Fix this documentation.
0709          */
0710         static SkyPoint timeTransformed(const SkyPoint *p, const KStarsDateTime &dt, const GeoLocation *geo,
0711                                         const double hour = 0);
0712 
0713         /**
0714          * @short Critical height for atmospheric refraction
0715          * corrections. Below this, the height formula produces meaningless
0716          * results and the correction value is just interpolated.
0717          */
0718         static const double altCrit;
0719 
0720         /**
0721          * @short Return the object's altitude at the upper culmination for the given latitude
0722          *
0723          * @return the maximum altitude in degrees
0724          */
0725         double maxAlt(const dms &lat) const;
0726 
0727         /**
0728          * @short Return the object's altitude at the lower culmination for the given latitude
0729          *
0730          * @return the minimum altitude in degrees
0731          */
0732         double minAlt(const dms &lat) const;
0733 
0734         /**
0735          * @short Return the Parallactic Angle
0736          *
0737          * The parallactic angle is the angle between "up" and
0738          * "north". See Jean Meeus' "Astronomical Algorithms" second
0739          * edition, Chapter 14 for more details (especially Fig 4 on Pg
0740          * 99). The angle returned in this case, between a vector of
0741          * increasing altitude and a vector of increasing declination, is
0742          * measured in the clockwise sense as seen on the sky.
0743          *
0744          * @param LST Local Sidereal Time
0745          * @param lat Latitude
0746          *
0747          * @note EquatorialToHorizontal() need not be called before
0748          * invoking this, but it is wise to call updateCoords() to ensure
0749          * ra() and dec() refer to the right epoch.
0750          *
0751          * @return the parallactic angle in the clockwise sense
0752          */
0753         dms parallacticAngle(const CachingDms &LST, const CachingDms &lat);
0754 
0755 #ifdef PROFILE_COORDINATE_CONVERSION
0756         static double cpuTime_EqToHz;
0757         static long unsigned eqToHzCalls;
0758 #endif
0759         static bool implementationIsLibnova;
0760 
0761     protected:
0762         /**
0763          * Precess this SkyPoint's catalog coordinates to the epoch described by the
0764          * given KSNumbers object.
0765          *
0766          * @param num pointer to a KSNumbers object describing the target epoch.
0767          */
0768         void precess(const KSNumbers *num);
0769 
0770 #ifdef UNIT_TEST
0771         friend class TestSkyPoint; // Test class
0772 #endif
0773 
0774     private:
0775         CachingDms RA0, Dec0; //catalog coordinates
0776         CachingDms RA, Dec;   //current true sky coordinates
0777         dms Alt, Az;
0778         static KSSun *m_Sun;
0779 
0780 
0781         // long version of these epochs
0782 #define J2000L          2451545.0L   //Julian Date for noon on Jan 1, 2000 (epoch J2000)
0783 #define B1950L          2433282.4235L // Julian date for Jan 0.9235, 1950
0784 
0785     protected:
0786         double lastPrecessJD { 0 }; // JD at which the last coordinate  (see updateCoords) for this SkyPoint was done
0787 };
0788 
0789 #ifndef KSTARS_LITE
0790 Q_DECLARE_METATYPE(SkyPoint)
0791 QDBusArgument &operator<<(QDBusArgument &argument, const SkyPoint &source);
0792 const QDBusArgument &operator>>(const QDBusArgument &argument, SkyPoint &dest);
0793 #endif