00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "SO3Astronomy.h"
00036
00037 namespace SO3
00038 {
00039
00040 const double SAstronomy::PI = 3.1415926535897932384626433832795029L;
00041 const double SAstronomy::J2000 = 2451545.0;
00042
00043 double SAstronomy::RadToDeg(double value)
00044 {
00045 return value * 180 / PI;
00046 }
00047
00048 double SAstronomy::DegToRad(double value)
00049 {
00050 return value * PI / 180;
00051 }
00052
00053 double SAstronomy::SinDeg(double x)
00054 {
00055 return std::sin(DegToRad(x));
00056 }
00057
00058 double SAstronomy::CosDeg(double x)
00059 {
00060 return std::cos(DegToRad(x));
00061 }
00062
00063 double SAstronomy::Atan2Deg(double y, double x)
00064 {
00065 return RadToDeg(std::atan2(y, x));
00066 }
00067
00068 double SAstronomy::NormalizeDegrees(double value)
00069 {
00070 value = fmod(value, 360);
00071 if (value < double(0))
00072 {
00073 value += double(360);
00074 }
00075 return value;
00076 }
00077
00078 void SAstronomy::ConvertEclipticToEquatorialRad(double lon, double lat, double& rasc, double& decl)
00079 {
00080 double ecl = SAstronomy::DegToRad(23.439281);
00081
00082 double x = cos(lon) * cos(lat);
00083 double y = cos(ecl) * sin(lon) * cos(lat) - sin(ecl) * sin(lat);
00084 double z = sin(ecl) * sin(lon) * cos(lat) + cos(ecl) * sin(lat);
00085
00086 double r = sqrt(x * x + y * y);
00087 rasc = atan2(y, x);
00088 decl = atan2(z, r);
00089 }
00090
00091 void SAstronomy::ConvertRectangularToSpherical(double x, double y, double z, double& rasc, double& decl, double& dist)
00092 {
00093 dist = sqrt (x * x + y * y + z * z);
00094 rasc = Atan2Deg(y, x);
00095 decl = Atan2Deg(z, sqrt (x * x + y * y));
00096 }
00097
00098 void SAstronomy::ConvertSphericalToRectangular(double rasc, double decl, double dist, double& x, double& y, double& z)
00099 {
00100 x = dist * CosDeg(rasc) * CosDeg(decl);
00101 y = dist * SinDeg(rasc) * CosDeg(decl);
00102 z = dist * SinDeg(decl);
00103 }
00104
00105 void SAstronomy::ConvertEquatorialToHorizontal(double jday, double longitude, double latitude, double rasc, double decl, double& azimuth, double& altitude)
00106 {
00107 double d = jday - 2451543.5;
00108 double w = double(282.9404 + 4.70935E-5 * d);
00109 double M = double(356.0470 + 0.9856002585 * d);
00110
00111
00112 double L = w + M;
00113
00114
00115 double UT = double(fmod(d, 1) * 360);
00116 double hourAngle = longitude + L + double(180) + UT - rasc;
00117
00118 double x = CosDeg(hourAngle) * CosDeg(decl);
00119 double y = SinDeg(hourAngle) * CosDeg(decl);
00120 double z = SinDeg(decl);
00121
00122 double xhor = x * SinDeg(latitude) - z * CosDeg(latitude);
00123 double yhor = y;
00124 double zhor = x * CosDeg(latitude) + z * SinDeg(latitude);
00125
00126 azimuth = Atan2Deg(yhor, xhor) + double(180);
00127 altitude = Atan2Deg (zhor, sqrt (xhor * xhor + yhor * yhor));
00128 }
00129
00130 void SAstronomy::GetEclipticSunMeanLongitude(double jday, double& sunlon)
00131 {
00132
00133
00134 double d = jday - 2451543.5;
00135
00136
00137
00138 double w = double(282.9404 + 4.70935E-5 * d);
00139
00140 double e = 0.016709 - 1.151E-9 * d;
00141
00142 double M = double(356.0470 + 0.9856002585 * d);
00143
00144
00145
00146
00147 double E = M + RadToDeg(e * SinDeg(M) * (1 + e * CosDeg(M)));
00148
00149
00150 double xv = CosDeg(E) - e;
00151 double yv = SinDeg(E) * sqrt(1 - e * e);
00152 sunlon = Atan2Deg(yv, xv) + w;
00153 }
00154
00155 void SAstronomy::GetEclipticSunPosition(double jday, double& lambda, double& beta)
00156 {
00157 double sunlon, sunlat = 0;
00158 GetEclipticSunMeanLongitude(jday, sunlon);
00159
00160 lambda = DegToRad(sunlon);
00161 beta = DegToRad(sunlat);
00162 }
00163
00164 void SAstronomy::GetEquatorialSunPosition(double jday, double& sunRightAscension, double& sunDeclinaison)
00165 {
00166 double lambda, beta;
00167 GetEclipticSunPosition(jday, lambda, beta);
00168 ConvertEclipticToEquatorialRad(lambda, beta, sunRightAscension, sunDeclinaison);
00169 sunRightAscension = RadToDeg(sunRightAscension);
00170 sunDeclinaison = RadToDeg(sunDeclinaison);
00171 }
00172
00173 void SAstronomy::GetHorizontalSunPosition(double jday, double longitude, double latitude, double& azimuth, double& altitude)
00174 {
00175
00176 double sunRightAscension, sunDeclinaison;
00177 GetEquatorialSunPosition(jday, sunRightAscension, sunDeclinaison);
00178 ConvertEquatorialToHorizontal(jday, longitude, latitude, sunRightAscension, sunDeclinaison, azimuth, altitude);
00179 }
00180
00181 void SAstronomy::GetHorizontalSunPosition(double jday, Ogre::Degree longitude, Ogre::Degree latitude, Ogre::Degree& azimuth, Ogre::Degree& altitude)
00182 {
00183 double az, al;
00184 GetHorizontalSunPosition(jday, longitude.valueDegrees(), latitude.valueDegrees(), az, al);
00185 azimuth = Ogre::Degree(static_cast<float>(az));
00186 altitude = Ogre::Degree(static_cast<float>(al));
00187 }
00188
00189 void SAstronomy::GetEclipticMoonPositionRad(double jday, double& lon, double& lat)
00190 {
00191
00192 double T = (jday - 2451545.0L) / 36525.0L;
00193 double lprim = 3.8104L + 8399.7091L * T;
00194 double mprim = 2.3554L + 8328.6911L * T;
00195 double m = 6.2300L + 648.3019L * T;
00196 double d = 5.1985L + 7771.3772L * T;
00197 double f = 1.6280L + 8433.4663L * T;
00198 lon = lprim
00199 + 0.1098L * sin(mprim)
00200 + 0.0222L * sin(2.0L * d - mprim)
00201 + 0.0115L * sin(2.0L * d)
00202 + 0.0037L * sin(2.0L * mprim)
00203 - 0.0032L * sin(m)
00204 - 0.0020L * sin(2.0L * f)
00205 + 0.0010L * sin(2.0L * d - 2.0L * mprim)
00206 + 0.0010L * sin(2.0L * d - m - mprim)
00207 + 0.0009L * sin(2.0L * d + mprim)
00208 + 0.0008L * sin(2.0L * d - m)
00209 + 0.0007L * sin(mprim - m)
00210 - 0.0006L * sin(d)
00211 - 0.0005L * sin(m + mprim);
00212
00213 lat = + 0.0895L * sin(f)
00214 + 0.0049L * sin(mprim + f)
00215 + 0.0048L * sin(mprim - f)
00216 + 0.0030L * sin(2.0L * d - f)
00217 + 0.0010L * sin(2.0L * d + f - mprim)
00218 + 0.0008 * sin(2.0L * d - f - mprim)
00219 + 0.0006L * sin(2.0L * d + f);
00220 }
00221
00222 void SAstronomy::GetHorizontalMoonPosition(double jday, double longitude, double latitude, double& azimuth, double& altitude)
00223 {
00224
00225 double lonecl, latecl;
00226 SAstronomy::GetEclipticMoonPositionRad(jday, lonecl, latecl);
00227
00228
00229 double rasc, decl;
00230 SAstronomy::ConvertEclipticToEquatorialRad(lonecl, latecl, rasc, decl);
00231
00232
00233 rasc = RadToDeg(rasc);
00234 decl = RadToDeg(decl);
00235
00236
00237 SAstronomy::ConvertEquatorialToHorizontal(jday, longitude, latitude, rasc, decl, azimuth, altitude);
00238 }
00239
00240 void SAstronomy::GetHorizontalMoonPosition(double jday, Ogre::Degree longitude, Ogre::Degree latitude, Ogre::Degree& azimuth, Ogre::Degree& altitude)
00241 {
00242 double az, al;
00243 GetHorizontalMoonPosition(jday, longitude.valueDegrees(), latitude.valueDegrees(), az, al);
00244 azimuth = Ogre::Degree(static_cast<float>(az));
00245 altitude = Ogre::Degree(static_cast<float>(al));
00246 }
00247
00248 void SAstronomy::GetMoonPhase(double jday, float& moonPhase)
00249 {
00250
00251 ScopedHighPrecissionFloatSwitch precissionSwitch;
00252 double T = (jday - 2454488.0665L) / 29.531026L;
00253
00254 T = fabs(fmod(T, 1));
00255 moonPhase = static_cast<float>(-fabs(-4 * T + 2) + 2);
00256 }
00257
00258 int SAstronomy::GetJulianDayFromGregorianDate(int year, int month, int day)
00259 {
00260
00261
00262
00263 int a = (14 - month) / 12;
00264 int y = year + 4800 - a;
00265 int m = month + 12 * a - 3;
00266 return day + (153 * m + 2) / 5 + 365 * y + y / 4 - y / 100 + y / 400 - 32045;
00267 }
00268
00269 double SAstronomy::GetJulianDayFromGregorianDateTime(int year, int month, int day, int hour, int minute, double second)
00270 {
00271 ScopedHighPrecissionFloatSwitch precissionSwitch;
00272 int jdn = GetJulianDayFromGregorianDate(year, month, day);
00273
00274
00275 double jd = jdn + (hour - 12) / 24.0 + minute / 1440.0 + second / 86400.0;
00276 return jd;
00277 }
00278
00279 double SAstronomy::GetJulianDayFromGregorianDateTime(int year, int month, int day, double secondsFromMidnight)
00280 {
00281 int jdn = GetJulianDayFromGregorianDate(year, month, day);
00282 double jd = jdn + secondsFromMidnight / 86400.0 - 0.5;
00283 return jd;
00284 }
00285
00286 void SAstronomy::GetGregorianDateFromJulianDay(int julianDay, int& year, int& month, int& day)
00287 {
00288
00289 int J = julianDay;
00290 int j = J + 32044;
00291 int g = j / 146097;
00292 int dg = j % 146097;
00293 int c = (dg / 36524 + 1) * 3 / 4;
00294 int dc = dg - c * 36524;
00295 int b = dc / 1461;
00296 int db = dc % 1461;
00297 int a = (db / 365 + 1) * 3 / 4;
00298 int da = db - a * 365;
00299 int y = g * 400 + c * 100 + b * 4 + a;
00300 int m = (da * 5 + 308) / 153 - 2;
00301 int d = da - (m + 4) * 153 / 5 + 122;
00302 year = y - 4800 + (m + 2) / 12;
00303 month = (m + 2) % 12 + 1;
00304 day = d + 1;
00305 }
00306
00307 void SAstronomy::GetGregorianDateTimeFromJulianDay(double julianDay, int& year, int& month, int& day, int& hour, int& minute, double& second)
00308 {
00309
00310
00311
00312 int ijd = static_cast<int>(floor(julianDay + 0.5));
00313 GetGregorianDateFromJulianDay(ijd, year, month, day);
00314
00315 double s = (julianDay + 0.5 - ijd) * 86400.0;
00316 hour = static_cast<int>(floor(s / 3600));
00317 s -= hour * 3600;
00318 minute = static_cast<int>(floor(s / 60));
00319 s -= minute * 60;
00320 second = s;
00321 }
00322
00323 void SAstronomy::GetGregorianDateFromJulianDay(double julianDay, int& year, int& month, int& day)
00324 {
00325 int hour;
00326 int minute;
00327 double second;
00328 GetGregorianDateTimeFromJulianDay(julianDay, year, month, day, hour, minute, second);
00329 }
00330
00331 #if (OGRE_PLATFORM == OGRE_PLATFORM_WIN32) && (OGRE_COMPILER == OGRE_COMPILER_MSVC)
00332 int SAstronomy::EnterHighPrecissionFloatingPointMode()
00333 {
00334 int oldMode = ::_controlfp (0, 0);
00335 ::_controlfp (_PC_64, _MCW_PC);
00336 return oldMode;
00337 }
00338
00339 void SAstronomy::RestoreFloatingPointMode(int oldMode)
00340 {
00341 ::_controlfp (oldMode, _MCW_PC);
00342 }
00343 #else
00344 int SAstronomy::EnterHighPrecissionFloatingPointMode()
00345 {
00346
00347 return 0xC0FFEE;
00348 }
00349
00350 void SAstronomy::RestoreFloatingPointMode(int oldMode)
00351 {
00352
00353 assert(oldMode == 0xC0FFEE);
00354 }
00355 #endif
00356
00357 }