Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

CelestialBody.cpp

Go to the documentation of this file.
00001 /*
00002  * CelestialBody.cpp
00003  *
00004  * Part of Fly! Legacy project
00005  *
00006  * This code was originally taken from SimGear 0.3.3; see
00007  *   the end of this file for the original SimGear comments.
00008  *
00009  * Copyright 2003 Chris Wallace
00010  *
00011  * Fly! Legacy is free software; you can redistribute it and/or modify
00012  *   it under the terms of the GNU General Public License as published by
00013  *   the Free Software Foundation; either version 2 of the License, or
00014  *   (at your option) any later version.
00015  *
00016  * Fly! Legacy is distributed in the hope that it will be useful,
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *   GNU General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU General Public License
00022  *   along with Fly! Legacy; if not, write to the Free Software
00023  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00024  *
00025  */
00026 
00034 #include <math.h>
00035 #include "../Include/Ephemeris.h"
00036 #include "../Include/Utility.h"
00037 
00038 
00039 /**************************************************************************
00040  * void CCelestialBody::updatePosition(double mjd, CSol *ourSun)
00041  *
00042  * Basically, this member function provides a general interface for 
00043  * calculating the right ascension and declinaion. This function is 
00044  * used for calculating the planetary positions. For the planets, an 
00045  * overloaded member function is provided to additionally calculate the
00046  * planet's magnitude. 
00047  * The sun and moon have their own overloaded updatePosition member, as their
00048  * position is calculated an a slightly different manner.  
00049  *
00050  * arguments:
00051  * double mjd: provides the modified julian date.
00052  * CSol *ourSun: the sun's position is needed to convert heliocentric 
00053  *               coordinates into geocentric coordinates.
00054  *
00055  * return value: none
00056  *
00057  *************************************************************************/
00058 void CCelestialBody::UpdatePosition(double mjd, CSol *ourSun)
00059 {
00060   double eccAnom, v, ecl, actTime, 
00061     xv, yv, xh, yh, zh, xg, yg, zg, xe, ye, ze;
00062 
00063   UpdateOrbElements(mjd);
00064   actTime = CalcActTime(mjd);
00065 
00066   // calcualate the angle bewteen ecliptic and equatorial coordinate system
00067   ecl = SGD_DEGREES_TO_RADIANS * (23.4393 - 3.563E-7 *actTime);
00068   
00069   eccAnom = CalcEccAnom(M, e);  //calculate the eccentric anomaly
00070   xv = a * (cos(eccAnom) - e);
00071   yv = a * (sqrt (1.0 - e * e) * sin(eccAnom));
00072   v = atan2(yv, xv);           // the planet's true anomaly
00073   r = sqrt (xv*xv + yv*yv);    // the planet's distance
00074   
00075   // calculate the planet's position in 3D space
00076   xh = r * (cos(N) * cos(v+w) - sin(N) * sin(v+w) * cos(i));
00077   yh = r * (sin(N) * cos(v+w) + cos(N) * sin(v+w) * cos(i));
00078   zh = r * (sin(v+w) * sin(i));
00079 
00080   // calculate the ecliptic longitude and latitude
00081   xg = xh + ourSun->getxs();
00082   yg = yh + ourSun->getys();
00083   zg = zh;
00084 
00085   lonEcl = atan2(yh, xh);
00086   latEcl = atan2(zh, sqrt(xh*xh+yh*yh));
00087 
00088   xe = xg;
00089   ye = yg * cos(ecl) - zg * sin(ecl);
00090   ze = yg * sin(ecl) + zg * cos(ecl);
00091   rightAscension = atan2(ye, xe);
00092   declination = atan2(ze, sqrt(xe*xe + ye*ye));
00093   /* SG_LOG(SG_GENERAL, SG_INFO, "Planet found at : " 
00094    << rightAscension << " (ra), " << declination << " (dec)" ); */
00095 
00096   //calculate some variables specific to calculating the magnitude 
00097   //of the planet
00098   R = sqrt (xg*xg + yg*yg + zg*zg);
00099   s = ourSun->getDistance();
00100 
00101   // It is possible from these calculations for the argument to acos
00102   // to exceed the valid range for acos(). So we do a little extra
00103   // checking.
00104 
00105   double tmp = (r*r + R*R - s*s) / (2*r*R);
00106   if ( tmp > 1.0) { 
00107       tmp = 1.0;
00108   } else if ( tmp < -1.0) {
00109       tmp = -1.0;
00110   }
00111 
00112   FV = SGD_RADIANS_TO_DEGREES * acos( tmp );
00113 }
00114 
00115 /****************************************************************************
00116  * double CCelestialBody::sgCalcEccAnom(double M, double e)
00117  * this private member calculates the eccentric anomaly of a celestial body, 
00118  * given its mean anomaly and eccentricity.
00119  * 
00120  * -Mean anomaly: the approximate angle between the perihelion and the current
00121  *  position. this angle increases uniformly with time.
00122  *
00123  * True anomaly: the actual angle between perihelion and current position.
00124  *
00125  * Eccentric anomaly: this is an auxilary angle, used in calculating the true
00126  * anomaly from the mean anomaly.
00127  * 
00128  * -eccentricity. Indicates the amount in which the orbit deviates from a 
00129  *  circle (0 = circle, 0-1, is ellipse, 1 = parabola, > 1 = hyperbola).
00130  *
00131  * This function is also known as solveKeplersEquation()
00132  *
00133  * arguments: 
00134  * M: the mean anomaly in radians
00135  * e: the eccentricity
00136  *
00137  * return value:
00138  * the eccentric anomaly in radians
00139  *
00140  ****************************************************************************/
00141 double CCelestialBody::CalcEccAnom(double M, double e)
00142 {
00143   double 
00144     eccAnom, E0, E1, diff;
00145   
00146   eccAnom = M + e * sin(M) * (1.0 + e * cos (M));
00147   // iterate to achieve a greater precision for larger eccentricities 
00148   if (e > 0.05)
00149     {
00150       E0 = eccAnom;
00151       do
00152   {
00153     E1 = E0 - (E0 - e * sin(E0) - M) / (1 - e *cos(E0));
00154     diff = fabs(E0 - E1);
00155     E0 = E1;
00156   }
00157       while (diff > (SGD_DEGREES_TO_RADIANS * 0.001));
00158       return E0;
00159     }
00160   return eccAnom;
00161 }
00162 
00163 /*****************************************************************************
00164  * CCelestialBody::CCelestialBody are the public constructors for a generic
00165  *   celestial body object.
00166  * Initializes the 6 primary orbital elements. The elements are:
00167  * N: longitude of the ascending node
00168  * i: inclination to the ecliptic
00169  * w: argument of perihelion
00170  * a: semi-major axis, or mean distance from the sun
00171  * e: eccenticity
00172  * M: mean anomaly
00173  * Each orbital element consists of a constant part and a variable part that 
00174  * gradually changes over time. 
00175  *
00176  * Argumetns:
00177  * the 13 arguments to the constructor constitute the first, constant 
00178  * ([NiwaeM]f) and the second variable ([NiwaeM]s) part of the orbital 
00179  * elements. The 13th argument is the current time. Note that the inclination
00180  * is written with a capital (If, Is), because 'if' is a reserved word in the 
00181  * C/C++ programming language.
00182  ***************************************************************************/ 
00183 CCelestialBody::CCelestialBody (double Nf, double If, double wf,
00184                 double af, double ef, double Mf,
00185                 double Ns, double Is, double ws,
00186                 double as, double es, double Ms,
00187                 double mjd)
00188 {
00189   SetElements (Nf, If, wf, af, ef, Mf, Ns, Is, ws, as, es, Ms, mjd);
00190 }
00191 
00192 CCelestialBody::CCelestialBody (double Nf, double If, double wf,
00193                 double af, double ef, double Mf,
00194                 double Ns, double Is, double ws,
00195                 double as, double es, double Ms)
00196 {
00197   SetElements (Nf, If, wf, af, ef, Mf, Ns, Is, ws, as, es, Ms);
00198 }
00199 
00200 
00201 /*****************************************************************************
00202  * CCelestialBody::SetElements re-initializes the orbital elements for
00203  *   a celestialBody object.  See constructor comments for details
00204  ***************************************************************************/ 
00205 void CCelestialBody::SetElements(double Nf, double If, double wf,
00206                  double af, double ef, double Mf,
00207                  double Ns, double Is, double ws,
00208                  double as, double es, double Ms,
00209                  double mjd)
00210 {
00211   this->Nf = Nf;
00212   this->If = If;
00213   this->wf = wf;
00214   this->af = af;
00215   this->ef = ef;
00216   this->Mf = Mf;
00217 
00218   this->Ns = Ns;
00219   this->Is = Is;
00220   this->ws = ws;
00221   this->as = as;
00222   this->es = es;
00223   this->Ms = Ms;
00224 
00225   UpdateOrbElements(mjd);
00226 }
00227 
00228 void CCelestialBody::SetElements(double Nf, double If, double wf,
00229                  double af, double ef, double Mf,
00230                  double Ns, double Is, double ws,
00231                  double as, double es, double Ms)
00232 {
00233   this->Nf = Nf;
00234   this->If = If;
00235   this->wf = wf;
00236   this->af = af;
00237   this->ef = ef;
00238   this->Mf = Mf;
00239 
00240   this->Ns = Ns;
00241   this->Is = Is;
00242   this->ws = ws;
00243   this->as = as;
00244   this->es = es;
00245   this->Ms = Ms;
00246 }
00247 
00248 
00249 /****************************************************************************
00250  * void CCelestialBody::updateOrbElements(double mjd)
00251  * given the current time, this private member calculates the actual 
00252  * orbital elements
00253  *
00254  * Arguments: double mjd: the current modified julian date:
00255  *
00256  * return value: none
00257  ***************************************************************************/
00258 void CCelestialBody::UpdateOrbElements(double mjd)
00259 {
00260   double actTime = CalcActTime(mjd);
00261 
00262   M = WrapTwoPi (SGD_DEGREES_TO_RADIANS * (Mf + (Ms * actTime)));
00263   w = WrapTwoPi (SGD_DEGREES_TO_RADIANS * (wf + (ws * actTime)));
00264   N = WrapTwoPi (SGD_DEGREES_TO_RADIANS * (Nf + (Ns * actTime)));
00265   i = WrapTwoPi (SGD_DEGREES_TO_RADIANS * (If + (Is * actTime)));
00266   e = ef + (es * actTime);
00267   a = af + (as * actTime);
00268 }
00269 
00270 /*****************************************************************************
00271  * double CCelestialBody::CalcActTime(double mjd)
00272  * this private member function returns the offset in days from the epoch for
00273  * wich the orbital elements are calculated (Jan, 1st, 2000).
00274  * 
00275  * Argument: the current time
00276  *
00277  * return value: the (fractional) number of days since Jan 1, 2000.
00278  ****************************************************************************/
00279 double CCelestialBody::CalcActTime(double mjd)
00280 {
00281 //  return (mjd - 36523.5);
00282   return (mjd - 51544);
00283 }
00284 
00285 /*****************************************************************************
00286  * inline void CCelestialBody::getPos(double* ra, double* dec)
00287  * gives public access to Right Ascension and declination
00288  *
00289  ****************************************************************************/
00290 void CCelestialBody::GetPos(double* ra, double* dec)
00291 {
00292   *ra  = rightAscension;
00293   *dec = declination;
00294 }
00295 
00296 /*****************************************************************************
00297  * inline void CCelestialBody::getPos(double* ra, double* dec, double* magnitude
00298  * gives public acces to the current Right ascension, declination, magnitude
00299  * and colour
00300  ****************************************************************************/
00301 void CCelestialBody::GetPos(double* ra, double* dec, double* magn)
00302 {
00303   *ra = rightAscension;
00304   *dec = declination;
00305   *magn = magnitude;
00306 }
00307 
00308 /*****************************************************************************
00309  * Public accessor methods for right ascension, declination, magnitude,
00310  *   colour, latitude and longitude
00311  ****************************************************************************/
00312 
00313 double CCelestialBody::GetRightAscension() { return rightAscension; }
00314 double CCelestialBody::GetDeclination() { return declination; }
00315 double CCelestialBody::GetMagnitude() { return magnitude; }
00316 double CCelestialBody::GetLon() { return lonEcl; }
00317 double CCelestialBody::GetLat() { return latEcl; }
00318 
00319 /**************************************************************************
00320  * celestialBody.cxx
00321  * Written by Durk Talsma. Originally started October 1997, for distribution  
00322  * with the FlightGear project. Version 2 was written in August and 
00323  * September 1998. This code is based upon algorithms and data kindly 
00324  * provided by Mr. Paul Schlyter. (pausch@saaf.se). 
00325  *
00326  * This library is free software; you can redistribute it and/or
00327  * modify it under the terms of the GNU Library General Public
00328  * License as published by the Free Software Foundation; either
00329  * version 2 of the License, or (at your option) any later version.
00330  *
00331  * This library is distributed in the hope that it will be useful,
00332  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00333  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00334  * Library General Public License for more details.
00335  *
00336  * You should have received a copy of the GNU Library General Public
00337  * License along with this library; if not, write to the
00338  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00339  * Boston, MA  02111-1307, USA.
00340  *
00341  **************************************************************************/
SourceForge.net Logo Documentation generated by doxygen