1 // orbit.h 2 // 3 // Copyright (C) 2001-2006, Chris Laurel <claurel@shatters.net> 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 #ifndef _CELENGINE_ORBIT_H_ 11 #define _CELENGINE_ORBIT_H_ 12 13 #include <celmath/vecmath.h> 14 15 class OrbitSampleProc; 16 17 class Orbit 18 { 19 public: ~Orbit()20 virtual ~Orbit() {}; 21 22 /*! Return the position in the orbit's reference frame at the specified 23 * time (TDB). Units are kilometers. 24 */ 25 virtual Point3d positionAtTime(double jd) const = 0; 26 27 /*! Return the orbital velocity in the orbit's reference frame at the 28 * specified time (TDB). Units are kilometers per day. If the method 29 * is not overridden, the velocity will be computed by differentiation 30 * of position. 31 */ 32 virtual Vec3d velocityAtTime(double) const; 33 34 virtual double getPeriod() const = 0; 35 virtual double getBoundingRadius() const = 0; 36 virtual void sample(double start, double t, 37 int nSamples, OrbitSampleProc& proc) const = 0; isPeriodic()38 virtual bool isPeriodic() const { return true; }; 39 40 // Return the time range over which the orbit is valid; if the orbit 41 // is always valid, begin and end should be equal. getValidRange(double & begin,double & end)42 virtual void getValidRange(double& begin, double& end) const 43 { begin = 0.0; end = 0.0; }; 44 }; 45 46 47 class EllipticalOrbit : public Orbit 48 { 49 public: 50 EllipticalOrbit(double, double, double, double, double, double, double, 51 double _epoch = 2451545.0); ~EllipticalOrbit()52 virtual ~EllipticalOrbit() {}; 53 54 // Compute the orbit for a specified Julian date 55 virtual Point3d positionAtTime(double) const; 56 virtual Vec3d velocityAtTime(double) const; 57 double getPeriod() const; 58 double getBoundingRadius() const; 59 virtual void sample(double, double, int, OrbitSampleProc&) const; 60 61 private: 62 double eccentricAnomaly(double) const; 63 Point3d positionAtE(double) const; 64 Vec3d velocityAtE(double) const; 65 66 double pericenterDistance; 67 double eccentricity; 68 double inclination; 69 double ascendingNode; 70 double argOfPeriapsis; 71 double meanAnomalyAtEpoch; 72 double period; 73 double epoch; 74 75 Mat3d orbitPlaneRotation; 76 }; 77 78 79 class OrbitSampleProc 80 { 81 public: ~OrbitSampleProc()82 virtual ~OrbitSampleProc() {}; 83 84 virtual void sample(double t, const Point3d&) = 0; 85 }; 86 87 88 89 /*! Custom orbit classes should be derived from CachingOrbit. The custom 90 * orbits can be expensive to compute, with more than 50 periodic terms. 91 * Celestia may need require position of a planet more than once per frame; in 92 * order to avoid redundant calculation, the CachingOrbit class saves the 93 * result of the last calculation and uses it if the time matches the cached 94 * time. 95 */ 96 class CachingOrbit : public Orbit 97 { 98 public: 99 CachingOrbit(); 100 virtual ~CachingOrbit(); 101 102 virtual Point3d computePosition(double jd) const = 0; 103 virtual Vec3d computeVelocity(double jd) const; 104 virtual double getPeriod() const = 0; 105 virtual double getBoundingRadius() const = 0; 106 107 Point3d positionAtTime(double jd) const; 108 Vec3d velocityAtTime(double jd) const; 109 110 virtual void sample(double, double, int, OrbitSampleProc& proc) const; 111 112 private: 113 mutable Point3d lastPosition; 114 mutable Vec3d lastVelocity; 115 mutable double lastTime; 116 mutable bool positionCacheValid; 117 mutable bool velocityCacheValid; 118 }; 119 120 121 /*! A mixed orbit is a composite orbit, typically used when you have a 122 * custom orbit calculation that is only valid over limited span of time. 123 * When a mixed orbit is constructed, it computes elliptical orbits 124 * to approximate the behavior of the primary orbit before and after the 125 * span over which it is valid. 126 */ 127 class MixedOrbit : public Orbit 128 { 129 public: 130 MixedOrbit(Orbit* orbit, double t0, double t1, double mass); 131 virtual ~MixedOrbit(); 132 133 virtual Point3d positionAtTime(double jd) const; 134 virtual Vec3d velocityAtTime(double jd) const; 135 virtual double getPeriod() const; 136 virtual double getBoundingRadius() const; 137 virtual void sample(double t0, double t1, 138 int nSamples, OrbitSampleProc& proc) const; 139 140 private: 141 Orbit* primary; 142 EllipticalOrbit* afterApprox; 143 EllipticalOrbit* beforeApprox; 144 double begin; 145 double end; 146 double boundingRadius; 147 }; 148 149 150 class Body; 151 152 // TODO: eliminate this once body-fixed reference frames are implemented 153 /*! An object in a synchronous orbit will always hover of the same spot on 154 * the surface of the body it orbits. Only equatorial orbits of a certain 155 * radius are stable in the real world. In Celestia, synchronous orbits are 156 * a convenient way to fix objects to a planet surface. 157 */ 158 class SynchronousOrbit : public Orbit 159 { 160 public: 161 SynchronousOrbit(const Body& _body, const Point3d& _position); 162 virtual ~SynchronousOrbit(); 163 164 virtual Point3d positionAtTime(double jd) const; 165 virtual double getPeriod() const; 166 virtual double getBoundingRadius() const; 167 virtual void sample(double, double, int, OrbitSampleProc& proc) const; 168 169 private: 170 const Body& body; 171 Point3d position; 172 }; 173 174 175 /*! A FixedOrbit is used for an object that remains at a constant 176 * position within its reference frame. 177 */ 178 class FixedOrbit : public Orbit 179 { 180 public: 181 FixedOrbit(const Point3d& pos); 182 virtual ~FixedOrbit(); 183 184 virtual Point3d positionAtTime(double) const; 185 //virtual Vec3d velocityAtTime(double) const; 186 virtual double getPeriod() const; 187 virtual bool isPeriodic() const; 188 virtual double getBoundingRadius() const; 189 virtual void sample(double, double, int, OrbitSampleProc&) const; 190 191 private: 192 Point3d position; 193 }; 194 195 196 #endif // _CELENGINE_ORBIT_H_ 197