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