00001 /************************************************************************** 00002 * moonpos.cxx 00003 * Written by Durk Talsma. Originally started October 1997, for distribution 00004 * with the FlightGear project. Version 2 was written in August and 00005 * September 1998. This code is based upon algorithms and data kindly 00006 * provided by Mr. Paul Schlyter. (pausch@saaf.se). 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Library General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Library General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 * 00022 * $Id: moonpos_8cxx_source.html,v 1.3 2010/02/23 22:10:15 curt Exp $ 00023 **************************************************************************/ 00024 00025 00026 #include <string.h> 00027 00028 #include <simgear/debug/logstream.hxx> 00029 00030 #include <math.h> 00031 00032 // #include <FDM/flight.hxx> 00033 00034 #include "moonpos.hxx" 00035 00036 00037 /************************************************************************* 00038 * MoonPos::MoonPos(double mjd) 00039 * Public constructor for class MoonPos. Initializes the orbital elements and 00040 * sets up the moon texture. 00041 * Argument: The current time. 00042 * the hard coded orbital elements for MoonPos are passed to 00043 * CelestialBody::CelestialBody(); 00044 ************************************************************************/ 00045 MoonPos::MoonPos(double mjd) : 00046 CelestialBody(125.1228, -0.0529538083, 00047 5.1454, 0.00000, 00048 318.0634, 0.1643573223, 00049 60.266600, 0.000000, 00050 0.054900, 0.000000, 00051 115.3654, 13.0649929509, mjd) 00052 { 00053 } 00054 00055 MoonPos::MoonPos() : 00056 CelestialBody(125.1228, -0.0529538083, 00057 5.1454, 0.00000, 00058 318.0634, 0.1643573223, 00059 60.266600, 0.000000, 00060 0.054900, 0.000000, 00061 115.3654, 13.0649929509) 00062 { 00063 } 00064 00065 00066 MoonPos::~MoonPos() 00067 { 00068 } 00069 00070 00071 /***************************************************************************** 00072 * void MoonPos::updatePosition(double mjd, Star *ourSun) 00073 * this member function calculates the actual topocentric position (i.e.) 00074 * the position of the moon as seen from the current position on the surface 00075 * of the moon. 00076 ****************************************************************************/ 00077 void MoonPos::updatePosition(double mjd, double lst, double lat, Star *ourSun) 00078 { 00079 double 00080 eccAnom, ecl, actTime, 00081 xv, yv, v, r, xh, yh, zh, xg, yg, zg, xe, ye, ze, 00082 Ls, Lm, D, F, mpar, gclat, rho, HA, g, 00083 geoRa, geoDec; 00084 00085 updateOrbElements(mjd); 00086 actTime = sgCalcActTime(mjd); 00087 00088 // calculate the angle between ecliptic and equatorial coordinate system 00089 // in Radians 00090 ecl = ((SGD_DEGREES_TO_RADIANS * 23.4393) - (SGD_DEGREES_TO_RADIANS * 3.563E-7) * actTime); 00091 eccAnom = sgCalcEccAnom(M, e); // Calculate the eccentric anomaly 00092 xv = a * (cos(eccAnom) - e); 00093 yv = a * (sqrt(1.0 - e*e) * sin(eccAnom)); 00094 v = atan2(yv, xv); // the moon's true anomaly 00095 r = sqrt (xv*xv + yv*yv); // and its distance 00096 00097 // estimate the geocentric rectangular coordinates here 00098 xh = r * (cos(N) * cos (v+w) - sin (N) * sin(v+w) * cos(i)); 00099 yh = r * (sin(N) * cos (v+w) + cos (N) * sin(v+w) * cos(i)); 00100 zh = r * (sin(v+w) * sin(i)); 00101 00102 // calculate the ecliptic latitude and longitude here 00103 lonEcl = atan2 (yh, xh); 00104 latEcl = atan2(zh, sqrt(xh*xh + yh*yh)); 00105 00106 /* Calculate a number of perturbatioin, i.e. disturbances caused by the 00107 * gravitational infuence of the sun and the other major planets. 00108 * The largest of these even have a name */ 00109 Ls = ourSun->getM() + ourSun->getw(); 00110 Lm = M + w + N; 00111 D = Lm - Ls; 00112 F = Lm - N; 00113 00114 lonEcl += SGD_DEGREES_TO_RADIANS * (-1.274 * sin (M - 2*D) 00115 +0.658 * sin (2*D) 00116 -0.186 * sin(ourSun->getM()) 00117 -0.059 * sin(2*M - 2*D) 00118 -0.057 * sin(M - 2*D + ourSun->getM()) 00119 +0.053 * sin(M + 2*D) 00120 +0.046 * sin(2*D - ourSun->getM()) 00121 +0.041 * sin(M - ourSun->getM()) 00122 -0.035 * sin(D) 00123 -0.031 * sin(M + ourSun->getM()) 00124 -0.015 * sin(2*F - 2*D) 00125 +0.011 * sin(M - 4*D) 00126 ); 00127 latEcl += SGD_DEGREES_TO_RADIANS * (-0.173 * sin(F-2*D) 00128 -0.055 * sin(M - F - 2*D) 00129 -0.046 * sin(M + F - 2*D) 00130 +0.033 * sin(F + 2*D) 00131 +0.017 * sin(2*M + F) 00132 ); 00133 r += (-0.58 * cos(M - 2*D) 00134 -0.46 * cos(2*D) 00135 ); 00136 // SG_LOG(SG_GENERAL, SG_INFO, "Running moon update"); 00137 xg = r * cos(lonEcl) * cos(latEcl); 00138 yg = r * sin(lonEcl) * cos(latEcl); 00139 zg = r * sin(latEcl); 00140 00141 xe = xg; 00142 ye = yg * cos(ecl) -zg * sin(ecl); 00143 ze = yg * sin(ecl) +zg * cos(ecl); 00144 00145 geoRa = atan2(ye, xe); 00146 geoDec = atan2(ze, sqrt(xe*xe + ye*ye)); 00147 00148 /* SG_LOG( SG_GENERAL, SG_INFO, 00149 "(geocentric) geoRa = (" << (SGD_RADIANS_TO_DEGREES * geoRa) 00150 << "), geoDec= (" << (SGD_RADIANS_TO_DEGREES * geoDec) << ")" ); */ 00151 00152 00153 // Given the moon's geocentric ra and dec, calculate its 00154 // topocentric ra and dec. i.e. the position as seen from the 00155 // surface of the earth, instead of the center of the earth 00156 00157 // First calculate the moon's parrallax, that is, the apparent size of the 00158 // (equatorial) radius of the earth, as seen from the moon 00159 mpar = asin ( 1 / r); 00160 // SG_LOG( SG_GENERAL, SG_INFO, "r = " << r << " mpar = " << mpar ); 00161 // SG_LOG( SG_GENERAL, SG_INFO, "lat = " << f->get_Latitude() ); 00162 00163 gclat = lat - 0.003358 * 00164 sin (2 * SGD_DEGREES_TO_RADIANS * lat ); 00165 // SG_LOG( SG_GENERAL, SG_INFO, "gclat = " << gclat ); 00166 00167 rho = 0.99883 + 0.00167 * cos(2 * SGD_DEGREES_TO_RADIANS * lat); 00168 // SG_LOG( SG_GENERAL, SG_INFO, "rho = " << rho ); 00169 00170 if (geoRa < 0) 00171 geoRa += SGD_2PI; 00172 00173 HA = lst - (3.8197186 * geoRa); 00174 /* SG_LOG( SG_GENERAL, SG_INFO, "t->getLst() = " << t->getLst() 00175 << " HA = " << HA ); */ 00176 00177 g = atan (tan(gclat) / cos ((HA / 3.8197186))); 00178 // SG_LOG( SG_GENERAL, SG_INFO, "g = " << g ); 00179 00180 rightAscension = geoRa - mpar * rho * cos(gclat) * sin(HA) / cos (geoDec); 00181 if (fabs(lat) > 0) { 00182 declination 00183 = geoDec - mpar * rho * sin (gclat) * sin (g - geoDec) / sin(g); 00184 } else { 00185 declination = geoDec; 00186 // cerr << "Geocentric vs. Topocentric position" << endl; 00187 // cerr << "RA (difference) : " 00188 // << SGD_RADIANS_TO_DEGREES * (geoRa - rightAscension) << endl; 00189 // cerr << "Dec (difference) : " 00190 // << SGD_RADIANS_TO_DEGREES * (geoDec - declination) << endl; 00191 } 00192 00193 /* SG_LOG( SG_GENERAL, SG_INFO, 00194 "Ra = (" << (SGD_RADIANS_TO_DEGREES *rightAscension) 00195 << "), Dec= (" << (SGD_RADIANS_TO_DEGREES *declination) << ")" ); */ 00196 }