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

Stellarium / stellarium / 5807639274

pending completion
5807639274

Pull #3359

github

gzotti
Restore drawing of orbits on open KeplerOrbits.
Pull Request #3359: Restore drawing of orbits on open KeplerOrbits.

17 of 17 new or added lines in 3 files covered. (100.0%)

14813 of 124524 relevant lines covered (11.9%)

25621.71 hits per line

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

0.0
/src/core/modules/Orbit.hpp
1
// orbit.h
2
//
3
// Initial structure of orbit computation; EllipticalOrbit: Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
4
// CometOrbit: Copyright (c) 2007,2008 Johannes Gajdosik
5
//             Amendments (c) 2013 Georg Zotti
6
// Combination to KeplerOrbit, GimbalOrbit (c) 2020 Georg Zotti
7
//
8
// This program is free software; you can redistribute it and/or
9
// modify it under the terms of the GNU General Public License
10
// as published by the Free Software Foundation; either version 2
11
// of the License, or (at your option) any later version.
12

13
#ifndef ORBIT_HPP
14
#define ORBIT_HPP
15

16
#define USE_GIMBAL_ORBIT 1
17

18
#include "VecMath.hpp"
19
#include "StelUtils.hpp"
20

21
//! @internal
22
//! Orbit computations used for comets, minor planets and "simple" moons
23
class Orbit
24
{
25
public:
26
    Orbit(void) {}
×
27
    virtual ~Orbit(void) {}
×
28
    //! Return a position (XYZ in AU).
29
    //! @param JDE Julian Ephemeris Date
30
    //! @param v double array of at least 3 elements. The first three should be filled by the X/Y/Z data.
31
    virtual void positionAtTimevInVSOP87Coordinates(double JDE, double* v){Q_UNUSED(JDE) Q_UNUSED(v)}
×
32
    //! return speed value [AU/d]. (zero in the base class)
33
    virtual Vec3d getVelocity() const { return Vec3d(0.); }
×
34
    //! write speed value [AU/d] into first 3 elements of vel. (zero in the base class)
35
    virtual void getVelocity(double *vel) const { vel[0]=0.; vel[1]=0.; vel[2]=0.;}
×
36
    //! return semimajor axis. (zero in the base class)
37
    virtual double getSemimajorAxis() const { return 0.; }
×
38
    //! return orbit eccentricity. (zero in the base class)
39
    virtual double getEccentricity() const { return 0; }
×
40
    //! For planet moons which have orbits given in relation to their parent planet's equator.
41
    //! This is called by the constructor, and must be updated for parent planets when their axis changes over time.
42
    void setParentOrientation(const double parentRotObliquity, const double parentRotAscendingNode, const double parentRotJ2000Longitude);
43
private:
44
    Orbit(const Orbit&);
45
    const Orbit &operator=(const Orbit&);
46
protected:
47
    double rotateToVsop87[9]; //! Rotation matrix.
48
};
49

50
//! KeplerOrbit describes an undisturbed orbit in a two-body system.
51
//! This is used for minor bodies orbiting the sun, but also for planet moons.
52
//! Orbital elements are considered valid for a relatively short time span (orbitGood)
53
//! around epoch only and should be updated periodically,
54
//! because the other planets perturbate the orbiting bodies.
55
//! To avoid using outdated elements, the KeplerOrbit object can be queried
56
//! using objectDateValid(JDE) whether it makes sense to assume the retrieved positions
57
//! are close enough to reality to find the object in a telescope. Another test is
58
//! objectDateGoodEnoughForOrbits(JDE), which test a bit more relaxed, for the sake
59
//! of retrieving positions for graphics.
60
//! @note This class was called CometOrbit previously, but was now recombined
61
//! with the former EllipticalOrbit class. They did almost the same.
62
//! @note Algorithms from:
63
//!   - Meeus: Astronomical Algorithms 1998
64
//!   - Heafner: Fundamental Ephemeris Computations 1999
65
//! @todo Add state vector equations from Heafner to create orbits from position+velocity,
66
//! or change orbits from velocity changes.
67
class KeplerOrbit : public Orbit {
68
public:
69
    //! Constructor.
70
    //! @param epochJDE                JDE epoch of orbital elements.
71
    //! @param pericenterDistance      [AU] pericenter distance
72
    //! @param eccentricity            0..>1 (>>1 for Interstellar objects)
73
    //! @param inclination             [radians]
74
    //! @param ascendingNode           [radians]
75
    //! @param argOfPerhelion          [radians]
76
    //! @param timeAtPerihelion        JDE
77
    //! @param orbitGoodDays           [earth days] can be used to exclude computation for dates too far outside epoch.
78
    //!                                 0: always good (use that for planet moons. Not really correct, but most users won't care)
79
    //!                                -1: signal "auto-compute to 1/2 the orbital period or 1000 days if there is no period [e>=1]")
80
    //! @param meanMotion              [radians/day] for parabolics, this is W/dt in Heafner's lettering
81
    //! @param parentRotObliquity      [radians] Comets/Minor Planets only have parent==sun, no need for these? --> Oh yes, these relate VSOP/J2000 eq frames!
82
    //! @param parentRotAscendingnode  [radians]
83
    //! @param parentRotJ2000Longitude [radians]
84
    //! @param centralMass central mass in Solar masses. Velocity value depends on this!
85
        KeplerOrbit(double epochJDE,
86
                    double pericenterDistance,
87
                    double eccentricity,
88
                    double inclination,
89
                    double ascendingNode,
90
                    double argOfPerhelion,
91
                    double timeAtPerihelion,
92
                    double orbitGoodDays,
93
                    double meanMotion,
94
                    double parentRotObliquity,
95
                    double parentRotAscendingnode,
96
                    double parentRotJ2000Longitude,
97
                    double centralMass = 1.0
98
                   );
99
        //! Compute the object position for a specified Julian day.
100
        //! @param JDE Julian Ephemeris Day
101
        //! @param v double vector of at least 3 elements. The first three will receive X/Y/Z values in AU.
102
        virtual void positionAtTimevInVSOP87Coordinates(double JDE, double* v) Q_DECL_OVERRIDE;
103
        //! updating comet tails is a bit expensive. try not to overdo it.
104
        bool getUpdateTails() const { return updateTails; }
×
105
        void setUpdateTails(const bool update){ updateTails=update; }
×
106
        //! return speed value [AU/d] last computed by positionAtTimevInVSOP87Coordinates(JDE, v)
107
        virtual Vec3d getVelocity() const Q_DECL_OVERRIDE { return rdot; }
×
108
        virtual void getVelocity(double *vel) const Q_DECL_OVERRIDE { vel[0]=rdot[0]; vel[1]=rdot[1]; vel[2]=rdot[2];}
×
109
        //! Returns semimajor axis [AU] for elliptic orbit, 0 for a parabolic orbit, and a negative value [AU] for hyperbolic orbit.
110
        virtual double getSemimajorAxis() const Q_DECL_OVERRIDE { return (e==1. ? 0. : q / (1.-e)); }
×
111
        virtual double getEccentricity() const Q_DECL_OVERRIDE { return e; }
×
112
        //! return whether a position returned for JDE can be regarded accurate enough for telescope use.
113
        //! This is limited to dates within 1 year or epoch, or within orbitGood around epoch, whichever is smaller.
114
        //! If orbitGood is zero, this is always true.
115
        //! @note This will still return false positives after close encounters with major masses which change orbital parameters.
116
        //! However, it should catch the usual case of outdated orbital elements which should be updated at least yearly.
117
        bool objectDateValid(const double JDE) const { return ((orbitGood==0.) || (fabs(epochJDE-JDE)<qMin(orbitGood, 365.0))); }
×
118
        //! return whether a position returned for JDE would be good enough for at least plotting the orbit.
119
        //! This is true for dates within orbitGood around epoch.
120
        //! If orbitGood is zero, this is always true.
121
        //! @note This relieves conditions of objectDateValid(JDE) somewhat, for the sake of illustratory completeness.
122
        bool objectDateGoodEnoughForOrbits(const double JDE) const { return ((orbitGood==0.) || (fabs(epochJDE-JDE)<orbitGood)); }
×
123
        //! Return minimal and maximal JDE values where this orbit should be used.
124
        //! @returns the limits where objectDateValid returns true
125
        Vec2d objectDateValidRange(const bool strict) const;
126
        //! Calculate sidereal period in days from semi-major axis and central mass. If SMA<=0 (hyperbolic orbit), return 0.
127
        double calculateSiderealPeriod() const;
128
        //! @param semiMajorAxis in AU. If SMA<=0 (hyperbolic orbit), return 0.
129
        //! @param centralMass in units of Solar masses
130
        static double calculateSiderealPeriod(const double semiMajorAxis, const double centralMass);
131
        double getEpochJDE() const { return epochJDE; }
×
132
        double getOrbitGood() const {return orbitGood; }
×
133

134
private:
135
        const double epochJDE; //!< epoch (date of validity) of the elements.
136
        const double q;  //!< pericenter distance [AU]
137
        const double e;  //!< eccentricity
138
        const double i;  //!< inclination [radians]
139
        const double Om; //!< longitude of ascending node [radians]
140
        const double w;  //!< argument of perihel [radians]
141
        const double t0; //!< time of perihel, JDE
142
        const double n;  //!< mean motion (for parabolic orbits: W/dt in Heafner's presentation, ch5.5) [radians/day]
143
        const double centralMass; //!< Mass in Solar masses. Velocity depends on this.
144
        double orbitGood; //!< orb. elements are only valid for this time from perihel [days]. Don't draw the object outside. Values <=0 mean "always good" (objects on undisturbed elliptic orbit)
145
        Vec3d rdot;       //!< velocity vector. Caches velocity from last position computation, [AU/d]
146
        bool updateTails; //!< flag to signal that comet tails must be recomputed.
147
        void InitEll(const double dt, double &rCosNu, double &rSinNu);
148
        void InitPar(const double dt, double &rCosNu, double &rSinNu);
149
        void InitHyp(const double dt, double &rCosNu, double &rSinNu);
150
};
151

152
//! A pseudo-orbit for "observers" linked to a planet's sphere. It allows setting distance and longitude/latitude in the VSOP87 frame.
153
//! This class is currently in an experimental state. rotateToVsop87 may need to be set up correctly.
154
//! The view frame for an observer is correctly oriented when the observer is located on the pseudo-planet's North pole.
155
//! Positional changes are currently performed with keyboard interaction (see @class StelMovementMgr)
156
class GimbalOrbit : public Orbit {
157
public:
158
        //! Constructor. @param distance in AU, @param longitude in radians, @param latitude in radians.
159
        GimbalOrbit(double distance, double longitude, double latitude);
160
        //! Compute position for a (unused) Julian day.
161
        virtual void positionAtTimevInVSOP87Coordinates(double JDE, double* v) Q_DECL_OVERRIDE;
162
        //! Returns (pseudo) semimajor axis [AU] of a circular "orbit", i.e., distance.
163
        double getSemimajorAxis() const Q_DECL_OVERRIDE { return distance; }
×
164

165
        //! Set minimum distance for observers (may depend on central object)
166
        void setMinDistance(double dist) {minDistance=dist; distance=qMax(distance, minDistance);}
×
167

168
        //! Retrieve observer's longitude in degrees
169
        double getLongitude() const { return longitude*M_180_PI;}
170
        //! Retrieve observer's latitude in degrees
171
        double getLatitude()  const { return latitude*M_180_PI;}
172
        //! Retrieve observer's distance in AU
173
        double getDistance()  const { return distance;}
×
174
        //! Set observer's longitude in degrees
175
        void setLongitude(const double lng){ longitude=lng*M_PI_180;}
176
        //! Set observer's latitude in degrees
177
        void setLatitude(const double lat) { latitude=lat*M_PI_180;}
178
        //! Set observer's distance in AU
179
        void setDistance(const double dist){ distance=dist;}
180
        //! Incrementally change longitude by @param dlong degrees
181
        void addToLongitude(const double dlong){ longitude+=dlong*M_PI_180; }
×
182
        //! Incrementally change latitude by @param dlat degrees. Clamped to |lat|<(90-delta) with a small delta at the poles.
183
        void addToLatitude(const double dlat);
184
        //! Incrementally change distance by @param ddist AU. Clamped to minDistance...50 AU.
185
        void addToDistance(const double ddist) { distance=qBound(minDistance, distance+ddist, 50.);}
×
186

187
private:
188
        double distance;   //! distance to parent planet center, AU
189
        double longitude;  //! longitude [radians]
190
        double latitude;   //! latitude [radians]
191
        double minDistance; //! minimum distance. May depend on size of observed object
192
};
193
#endif // ORBIT_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