File indexing completed on 2024-07-21 09:22:22

0001 /*
0002     SPDX-FileCopyrightText: 2002 Mark Hollomon <mhh@mindspring.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "trailobject.h"
0010 #include "kstarsdata.h"
0011 
0012 #include <QColor>
0013 #include <QDebug>
0014 #include <QImage>
0015 #include <QList>
0016 
0017 class KSNumbers;
0018 
0019 /**
0020  * @class EclipticPosition
0021  * @short The ecliptic position of a planet (Longitude, Latitude, and distance from Sun).
0022  * @author Mark Hollomon
0023  * @version 1.0
0024  */
0025 class EclipticPosition
0026 {
0027   public:
0028     dms longitude;
0029     dms latitude;
0030     double radius;
0031 
0032     /**Constructor. */
0033     explicit EclipticPosition(dms plong = dms(), dms plat = dms(), double prad = 0.0)
0034         : longitude(plong), latitude(plat), radius(prad)
0035     {
0036     }
0037 };
0038 
0039 /**
0040  * @class KSPlanetBase
0041  * A subclass of TrailObject that provides additional information needed for most solar system
0042  * objects. This is a base class for KSSun, KSMoon, KSPlanet, KSAsteroid and KSComet.
0043  * Those classes cover all solar system objects except planetary moons, which are
0044  * derived directly from TrailObject
0045  * @short Provides necessary information about objects in the solar system.
0046  * @author Mark Hollomon
0047  * @version 1.0
0048  */
0049 class KSPlanetBase : public TrailObject
0050 {
0051   public:
0052     /**
0053      * Constructor.  Calls SkyObject constructor with type=2 (planet),
0054      * coordinates=0.0, mag=0.0, primary name s, and all other QStrings empty.
0055      * @param s Name of planet
0056      * @param image_file filename of the planet's image
0057      * @param c color of the symbol to use for this planet
0058      * @param pSize the planet's physical size, in km
0059      */
0060     explicit KSPlanetBase(const QString &s = i18n("unnamed"), const QString &image_file = QString(),
0061                           const QColor &c = Qt::white, double pSize = 0);
0062 
0063     /** Destructor (empty) */
0064     ~KSPlanetBase() override = default;
0065 
0066     void init(const QString &s, const QString &image_file, const QColor &c, double pSize);
0067 
0068     //enum Planets { MERCURY=0, VENUS=1, MARS=2, JUPITER=3, SATURN=4, URANUS=5, NEPTUNE=6, PLUTO=7, SUN=8, MOON=9, UNKNOWN_PLANET };
0069     enum Planets
0070     {
0071         MERCURY = 0,
0072         VENUS   = 1,
0073         MARS    = 2,
0074         JUPITER = 3,
0075         SATURN  = 4,
0076         URANUS  = 5,
0077         NEPTUNE = 6,
0078         SUN     = 7,
0079         MOON    = 8,
0080         EARTH_SHADOW = 9,
0081         UNKNOWN_PLANET
0082     };
0083 
0084     static KSPlanetBase *createPlanet(int n);
0085 
0086     static QVector<QColor> planetColor;
0087 
0088     virtual bool loadData() = 0;
0089 
0090     /** @return pointer to Ecliptic Longitude coordinate */
0091     const dms &ecLong() const { return ep.longitude; }
0092 
0093     /** @return pointer to Ecliptic Latitude coordinate */
0094     const dms &ecLat() const { return ep.latitude; }
0095 
0096     /**
0097      * @short Set Ecliptic Geocentric Longitude according to argument.
0098      * @param elong Ecliptic Longitude
0099      */
0100     void setEcLong(dms elong) { ep.longitude = elong; }
0101 
0102     /**
0103      * @short Set Ecliptic Geocentric Latitude according to argument.
0104      * @param elat Ecliptic Latitude
0105      */
0106     void setEcLat(dms elat) { ep.latitude = elat; }
0107 
0108     /** @return pointer to Ecliptic Heliocentric Longitude coordinate */
0109     const dms &helEcLong() const { return helEcPos.longitude; }
0110 
0111     /** @return pointer to Ecliptic Heliocentric Latitude coordinate */
0112     const dms &helEcLat() const { return helEcPos.latitude; }
0113 
0114     /**
0115      * @short Convert Ecliptic longitude/latitude to Right Ascension/Declination.
0116      * @param Obliquity current Obliquity of the Ecliptic (angle from Equator)
0117      */
0118     void EclipticToEquatorial(const CachingDms *Obliquity);
0119 
0120     /**
0121      * @short Convert Right Ascension/Declination to Ecliptic longitude/latitude.
0122      * @param Obliquity current Obliquity of the Ecliptic (angle from Equator)
0123      */
0124     void EquatorialToEcliptic(const CachingDms *Obliquity);
0125 
0126     /** @return pointer to this planet's texture */
0127     const QImage &image() const { return m_image; }
0128 
0129     /** @return distance from Sun, in Astronomical Units (1 AU is Earth-Sun distance) */
0130     double rsun() const { return ep.radius; }
0131 
0132     /**
0133      * @short Set the solar distance in AU.
0134      * @param r the new solar distance in AU
0135      */
0136     void setRsun(double r) { ep.radius = r; }
0137 
0138     /** @return distance from Earth, in Astronomical Units (1 AU is Earth-Sun distance) */
0139     double rearth() const { return Rearth; }
0140 
0141     /**
0142      * @short Set the distance from Earth, in AU.
0143      * @param r the new earth-distance in AU
0144      */
0145     void setRearth(double r) { Rearth = r; }
0146 
0147     /**
0148      * @short compute and set the distance from Earth, in AU.
0149      * @param Earth pointer to the Earth from which to calculate the distance.
0150      */
0151     void setRearth(const KSPlanetBase *Earth);
0152 
0153     /**
0154      * Update position of the planet (reimplemented from SkyPoint)
0155      * @param num current KSNumbers object
0156      * @param includePlanets this function does nothing if includePlanets=false
0157      * @param lat pointer to the geographic latitude; if nullptr, we skip localizeCoords()
0158      * @param LST pointer to the local sidereal time; if nullptr, we skip localizeCoords()
0159      * @param forceRecompute defines whether the data should be recomputed forcefully
0160      */
0161     void updateCoords(const KSNumbers *num, bool includePlanets = true, const CachingDms *lat = nullptr,
0162                       const CachingDms *LST = nullptr, bool forceRecompute = false) override;
0163 
0164     /**
0165      * @short Find position, including correction for Figure-of-the-Earth.
0166      * @param num KSNumbers pointer for the target date/time
0167      * @param lat pointer to the geographic latitude; if nullptr, we skip localizeCoords()
0168      * @param LST pointer to the local sidereal time; if nullptr, we skip localizeCoords()
0169      * @param Earth pointer to the Earth (not used for the Moon)
0170      */
0171     void findPosition(const KSNumbers *num, const CachingDms *lat = nullptr, const CachingDms *LST = nullptr,
0172                       const KSPlanetBase *Earth = nullptr);
0173 
0174     /** @return the Planet's position angle. */
0175     double pa() const override { return PositionAngle; }
0176 
0177     /**
0178      * @short Set the Planet's position angle.
0179      * @param p the new position angle
0180      */
0181     void setPA(double p) { PositionAngle = p; }
0182 
0183     /** @return the Planet's angular size, in arcminutes */
0184     double angSize() const { return AngularSize; }
0185 
0186     /** @short set the planet's angular size, in km.
0187          * @param size the planet's size, in km
0188          */
0189     void setAngularSize(double size) { AngularSize = size; }
0190 
0191     /** @return the Planet's physical size, in km */
0192     double physicalSize() const { return PhysicalSize; }
0193 
0194     /** @short set the planet's physical size, in km.
0195          * @param size the planet's size, in km
0196          */
0197     void setPhysicalSize(double size) { PhysicalSize = size; }
0198 
0199     /** @return the phase angle of this planet */
0200     inline dms phase() { return dms(Phase); }
0201 
0202     /** @return the color for the planet symbol */
0203     QColor &color() { return m_Color; }
0204 
0205     /** @short Set the color for the planet symbol */
0206     void setColor(const QColor &c) { m_Color = c; }
0207 
0208     /** @return true if the KSPlanet is one of the eight major planets */
0209     bool isMajorPlanet() const;
0210 
0211     /** @return the pixel distance for offseting the object's name label */
0212     double labelOffset() const override;
0213 
0214   protected:
0215     /** Big object. Planet, Moon, Sun. */
0216     static const UID UID_SOL_BIGOBJ;
0217     /** Asteroids */
0218     static const UID UID_SOL_ASTEROID;
0219     /** Comets */
0220     static const UID UID_SOL_COMET;
0221 
0222     /** Compute high 32-bits of UID. */
0223     inline UID solarsysUID(UID type) const { return (SkyObject::UID_SOLARSYS << 60) | (type << 56); }
0224 
0225     /**
0226      * @short find the object's current geocentric equatorial coordinates (RA and Dec)
0227      * This function is pure virtual; it must be overloaded by subclasses.
0228      * This function is private; it is called by the public function findPosition()
0229      * which also includes the figure-of-the-earth correction, localizeCoords().
0230      * @param num pointer to current KSNumbers object
0231      * @param Earth pointer to planet Earth (needed to calculate geocentric coords)
0232      * @return true if position was successfully calculated.
0233      */
0234     virtual bool findGeocentricPosition(const KSNumbers *num, const KSPlanetBase *Earth = nullptr) = 0;
0235 
0236     /**
0237      * @short Computes the visual magnitude for the major planets.
0238      * @param num pointer to a ksnumbers object. Needed for the saturn rings contribution to
0239      * saturn's magnitude.
0240      */
0241     virtual void findMagnitude(const KSNumbers *num) = 0;
0242 
0243     /**
0244      * Determine the position angle of the planet for a given date
0245      * (used internally by findPosition() )
0246      */
0247     void findPA(const KSNumbers *num);
0248 
0249     /** Determine the phase of the planet. */
0250     virtual void findPhase();
0251 
0252     virtual double findAngularSize() { return  asin(physicalSize() / Rearth / AU_KM) * 60. * 180. / dms::PI; }
0253     // Geocentric ecliptic position, but distance to the Sun
0254     EclipticPosition ep;
0255 
0256     // Heliocentric ecliptic position referred to the equinox of the epoch
0257     // as obtained from VSOP.
0258     EclipticPosition helEcPos;
0259     double Rearth {NaN::d};
0260     double Phase {NaN::d};
0261     QImage m_image;
0262 
0263   private:
0264     /**
0265      * @short correct the position for the fact that the location is not at the center of the Earth,
0266      * but a position on its surface.  This causes a small parallactic shift in a solar system
0267      * body's apparent position.  The effect is most significant for the Moon.
0268      * This function is private, and should only be called from the public findPosition() function.
0269      * @param num pointer to a ksnumbers object for the target date/time
0270      * @param lat pointer to the geographic latitude of the location.
0271      * @param LST pointer to the local sidereal time.
0272      */
0273     void localizeCoords(const KSNumbers *num, const CachingDms *lat, const CachingDms *LST);
0274 
0275     double PositionAngle, AngularSize, PhysicalSize;
0276     QColor m_Color;
0277 };