public GCEquatorialCoords getTopocentricEquatorial(GCEarthData obs, double jdate) { double u, h, delta_alpha; double rho_sin, rho_cos; const double b_a = 0.99664719; GCEquatorialCoords tec = new GCEquatorialCoords(); double altitude = 0; // geocentric position of observer on the earth surface // 10.1 - 10.3 u = GCMath.arcTanDeg(b_a * b_a * GCMath.tanDeg(obs.latitudeDeg)); rho_sin = b_a * GCMath.sinDeg(u) + altitude / 6378140.0 * GCMath.sinDeg(obs.latitudeDeg); rho_cos = GCMath.cosDeg(u) + altitude / 6378140.0 * GCMath.cosDeg(obs.latitudeDeg); // equatorial horizontal paralax // 39.1 double parallax = GCMath.arcSinDeg(GCMath.sinDeg(8.794 / 3600) / (radius / GCMath.AU)); // geocentric hour angle of the body h = GCEarthData.SiderealTimeGreenwich(jdate) + obs.longitudeDeg - rightAscension; // 39.2 delta_alpha = GCMath.arcTanDeg( (-rho_cos * GCMath.sinDeg(parallax) * GCMath.sinDeg(h)) / (GCMath.cosDeg(this.declination) - rho_cos * GCMath.sinDeg(parallax) * GCMath.cosDeg(h))); tec.rightAscension = rightAscension + delta_alpha; tec.declination = declination + GCMath.arcTanDeg( ((GCMath.sinDeg(declination) - rho_sin * GCMath.sinDeg(parallax)) * GCMath.cosDeg(delta_alpha)) / (GCMath.cosDeg(declination) - rho_cos * GCMath.sinDeg(parallax) * GCMath.cosDeg(h))); return(tec); }
/// <summary> /// /// </summary> /// <param name="julianDateUTC">Time in UT1 or for general use UTC. This should reflect also hours, minutes and seconds. When finding local sidereal time, /// this argument should contains time that is observed on Greenwich meridian. Use function GetJulianDetailed or GetGreenwichDateTime</param> /// <param name="longitudeDegrees"></param> /// <returns></returns> public static double SiderealTimeLocal(double julianDateUTC, double longitudeDegrees, double timezoneDegrees) { double julianDate2000, julianMillenium; double delta_phi = 0.0, epsilon = 0.0; julianDate2000 = julianDateUTC - 2451545.0; julianMillenium = julianDate2000 / 36525.0; GCEarthData.CalculateNutations(julianDateUTC, out delta_phi, out epsilon); return(GCMath.putIn360(280.46061837 + 360.98564736629 * julianDate2000 + julianMillenium * julianMillenium * (0.000387933 - julianMillenium / 38710000) + delta_phi * GCMath.cosDeg(epsilon) + longitudeDegrees - timezoneDegrees)); }
public static GCHourTime CalcSunrise(GregorianDateTime vct, GCEarthData earth) { double tempSunrise = 180.0; GCSunData sun = new GCSunData(); for (int i = 0; i < 3; i++) { sun.SunPosition(vct, earth, tempSunrise - 180.0); double x; // definition of event double eventdef = 0.01454; /* switch(ed.obs) * { * case 1: // civil twilight * eventdef = 0.10453; * break; * case 2: // nautical twilight * eventdef = 0.20791; * break; * case 3: // astronomical twilight * eventdef = 0.30902; * break; * default:// center of the sun on the horizont * eventdef = 0.01454; * break; * }*/ eventdef = (eventdef / GCMath.cosDeg(earth.latitudeDeg)) / GCMath.cosDeg(sun.declinationDeg); x = GCMath.tanDeg(earth.latitudeDeg) * GCMath.tanDeg(sun.declinationDeg) + eventdef; if ((x >= -1.0) && (x <= 1.0)) { // time of sunrise tempSunrise = 90.0 - earth.longitudeDeg - GCMath.arcSinDeg(x) + sun.equationOfTime; } else { // initial values for the case // that no rise no set for that day tempSunrise = -360.0; break; } } GCHourTime result = new GCHourTime(); result.longitude = sun.longitudeDeg; result.SetDegTime(tempSunrise + earth.OffsetUtcHours * 15.0); return(result); }
public static double SiderealTimeGreenwich(double date) { double jd, t; double delta_phi = 0.0, epsilon = 0.0; jd = date; t = (jd - 2451545.0) / 36525.0; GCEarthData.CalculateNutations(date, out delta_phi, out epsilon); return(GCMath.putIn360(280.46061837 + 360.98564736629 * (jd - 2451545.0) + t * t * (0.000387933 - t / 38710000) + delta_phi * GCMath.cosDeg(epsilon))); }
//================================================================================== // //================================================================================== public void calc_horizontal(double date, double longitude, double latitude) { double h; h = GCMath.putIn360(GCEarthData.SiderealTimeGreenwich(date) - this.rightAscension + longitude); this.azimuth = GCMath.rad2deg(Math.Atan2(GCMath.sinDeg(h), GCMath.cosDeg(h) * GCMath.sinDeg(latitude) - GCMath.tanDeg(this.declination) * GCMath.cosDeg(latitude))); this.elevation = GCMath.rad2deg(Math.Asin(GCMath.sinDeg(latitude) * GCMath.sinDeg(this.declination) + GCMath.cosDeg(latitude) * GCMath.cosDeg(this.declination) * GCMath.cosDeg(h))); }
public static double MoonDistance(double jdate) { double temp, t, d, m, ms, f, e, ls, sr;// : extended; t = (jdate - 2451545.0) / 36525.0; //(* mean elongation of the moon d = 297.8502042 + (445267.1115168 + (-0.0016300 + (1.0 / 545868 - 1.0 / 113065000 * t) * t) * t) * t; //(* mean anomaly of the sun m = 357.5291092 + (35999.0502909 + (-0.0001536 + 1.0 / 24490000 * t) * t) * t; //(* mean anomaly of the moon ms = 134.9634114 + (477198.8676313 + (0.0089970 + (1.0 / 69699 - 1.0 / 1471200 * t) * t) * t) * t; //(* argument of the longitude of the moon f = 93.2720993 + (483202.0175273 + (-0.0034029 + (-1.0 / 3526000 + 1.0 / 863310000 * t) * t) * t) * t; //(* correction term due to excentricity of the earth orbit e = 1.0 + (-0.002516 - 0.0000074 * t) * t; //(* mean longitude of the moon ls = 218.3164591 + (481267.88134236 + (-0.0013268 + (1.0 / 538841 - 1.0 / 65194000 * t) * t) * t) * t; sr = 0; int i; for (i = 0; i < 60; i++) { temp = sigma_r[i] * GCMath.cosDeg(arg_lr[i, 0] * d + arg_lr[i, 1] * m + arg_lr[i, 2] * ms + arg_lr[i, 3] * f); if (Math.Abs(arg_lr[i, 1]) == 1) { temp = temp * e; } if (Math.Abs(arg_lr[i, 1]) == 2) { temp = temp * e * e; } sr = sr + temp; } return(385000.56 + sr / 1000); }
/// <summary> /// /// </summary> /// <param name="julianDateUTC">This contains time UTC, that means time observed on Greenwich meridian. DateTime in other /// timezones should be converted into timezone UTC+0h before using in this method.</param> /// <returns></returns> public double GetAscendantDegrees(double julianDateUTC) { double A = GCEarthData.SiderealTimeLocal(julianDateUTC, longitudeDeg, OffsetUtcHours * 15.0); double E = 23.4392911; double ascendant = GCMath.arcTan2Deg(-GCMath.cosDeg(A), GCMath.sinDeg(A) * GCMath.cosDeg(E) + GCMath.tanDeg(latitudeDeg) * GCMath.sinDeg(E)); if (ascendant < 180) { ascendant += 180; } else { ascendant -= 180; } return(GCMath.putIn360(ascendant - GCAyanamsha.GetAyanamsa(julianDateUTC))); }
public static GCHorizontalCoords equatorialToHorizontalCoords(GCEquatorialCoords eqc, GCEarthData obs, double date) { double localHourAngle; GCHorizontalCoords hc; localHourAngle = GCMath.putIn360(GCEarthData.SiderealTimeGreenwich(date) - eqc.rightAscension + obs.longitudeDeg); hc.azimut = GCMath.rad2deg(Math.Atan2(GCMath.sinDeg(localHourAngle), GCMath.cosDeg(localHourAngle) * GCMath.sinDeg(obs.latitudeDeg) - GCMath.tanDeg(eqc.declination) * GCMath.cosDeg(obs.latitudeDeg))); hc.elevation = GCMath.rad2deg(Math.Asin(GCMath.sinDeg(obs.latitudeDeg) * GCMath.sinDeg(eqc.declination) + GCMath.cosDeg(obs.latitudeDeg) * GCMath.cosDeg(eqc.declination) * GCMath.cosDeg(localHourAngle))); return(hc); }
public static GCEquatorialCoords eclipticalToEquatorialCoords(ref GCEclipticalCoords ecc, double date) { //var GCEquatorialCoords eqc; double epsilon; double nutationLongitude; GCEarthData.CalculateNutations(date, out nutationLongitude, out epsilon); // formula from Chapter 21 ecc.longitude = GCMath.putIn360(ecc.longitude + nutationLongitude); // formulas from Chapter 12 eqc.rightAscension = GCMath.arcTan2Deg(GCMath.sinDeg(ecc.longitude) * GCMath.cosDeg(epsilon) - GCMath.tanDeg(ecc.latitude) * GCMath.sinDeg(epsilon), GCMath.cosDeg(ecc.longitude)); eqc.declination = GCMath.arcSinDeg(GCMath.sinDeg(ecc.latitude) * GCMath.cosDeg(epsilon) + GCMath.cosDeg(ecc.latitude) * GCMath.sinDeg(epsilon) * GCMath.sinDeg(ecc.longitude)); return(eqc); }
public static GCHourTime CalcSunset(GregorianDateTime vct, GCEarthData earth) { double tempSunset = 180.0; GCSunData sun = new GCSunData(); for (int i = 0; i < 3; i++) { sun.SunPosition(vct, earth, tempSunset - 180.0); double x; // definition of event double eventdef = GCSunData.RiseAngleLevel; eventdef = (eventdef / GCMath.cosDeg(earth.latitudeDeg)) / GCMath.cosDeg(sun.declinationDeg); x = GCMath.tanDeg(earth.latitudeDeg) * GCMath.tanDeg(sun.declinationDeg) + eventdef; if ((x >= -1.0) && (x <= 1.0)) { // time of sunset tempSunset = 270.0 - earth.longitudeDeg + GCMath.arcSinDeg(x) + sun.equationOfTime; } else { // initial values for the case // that no rise no set for that day tempSunset = -360.0; break; } } GCHourTime result = new GCHourTime(); result.longitude = sun.longitudeDeg; result.SetDegTime(tempSunset + earth.OffsetUtcHours * 15.0); return(result); }
public void CorrectEqatorialWithParallax(double jdate, double latitude, double longitude, double height) { double u, hourAngleBody, delta_alpha; double rho_sin, rho_cos; const double b_a = 0.99664719; // calculate geocentric longitude and latitude of observer u = GCMath.arcTanDeg(b_a * b_a * GCMath.tanDeg(latitude)); rho_sin = b_a * GCMath.sinDeg(u) + height / 6378140.0 * GCMath.sinDeg(latitude); rho_cos = GCMath.cosDeg(u) + height / 6378140.0 * GCMath.cosDeg(latitude); // calculate paralax this.parallax = GCMath.arcSinDeg(GCMath.sinDeg(8.794 / 3600) / (MoonDistance(jdate) / GCMath.AU)); // calculate correction of equatorial coordinates hourAngleBody = GCEarthData.SiderealTimeGreenwich(jdate) + longitude - this.rightAscension; delta_alpha = GCMath.arcTan2Deg(-rho_cos * GCMath.sinDeg(this.parallax) * GCMath.sinDeg(hourAngleBody), GCMath.cosDeg(this.declination) - rho_cos * GCMath.sinDeg(this.parallax) * GCMath.cosDeg(hourAngleBody)); this.rightAscension += delta_alpha; this.declination += GCMath.arcTan2Deg( (GCMath.sinDeg(this.declination) - rho_sin * GCMath.sinDeg(this.parallax)) * GCMath.cosDeg(delta_alpha), GCMath.cosDeg(this.declination) - rho_cos * GCMath.sinDeg(this.parallax) * GCMath.cosDeg(hourAngleBody)); }
public static GCEclipticalCoords CalculateEcliptical(double jdate) { double t, d, m, ms, f, e, ls; double sr, sl, sb, temp; // : extended; double a1, a2, a3; // : extended; int i; //: integer; t = (jdate - 2451545.0) / 36525.0; //(* mean elongation of the moon d = 297.8502042 + (445267.1115168 + (-0.0016300 + (1.0 / 545868 - 1.0 / 113065000 * t) * t) * t) * t; //(* mean anomaly of the sun m = 357.5291092 + (35999.0502909 + (-0.0001536 + 1.0 / 24490000 * t) * t) * t; //(* mean anomaly of the moon ms = 134.9634114 + (477198.8676313 + (0.0089970 + (1.0 / 69699 - 1.0 / 1471200 * t) * t) * t) * t; //(* argument of the longitude of the moon f = 93.2720993 + (483202.0175273 + (-0.0034029 + (-1.0 / 3526000 + 1.0 / 863310000 * t) * t) * t) * t; //(* correction term due to excentricity of the earth orbit e = 1.0 + (-0.002516 - 0.0000074 * t) * t; //(* mean longitude of the moon ls = 218.3164591 + (481267.88134236 + (-0.0013268 + (1.0 / 538841 - 1.0 / 65194000 * t) * t) * t) * t; //(* arguments of correction terms a1 = 119.75 + 131.849 * t; a2 = 53.09 + 479264.290 * t; a3 = 313.45 + 481266.484 * t; sr = 0; for (i = 0; i < 60; i++) { temp = sigma_r[i] * GCMath.cosDeg(arg_lr[i, 0] * d + arg_lr[i, 1] * m + arg_lr[i, 2] * ms + arg_lr[i, 3] * f); if (Math.Abs(arg_lr[i, 1]) == 1) { temp = temp * e; } if (Math.Abs(arg_lr[i, 1]) == 2) { temp = temp * e * e; } sr = sr + temp; } sl = 0; for (i = 0; i < 60; i++) { temp = sigma_l[i] * GCMath.sinDeg(arg_lr[i, 0] * d + arg_lr[i, 1] * m + arg_lr[i, 2] * ms + arg_lr[i, 3] * f); if (Math.Abs(arg_lr[i, 1]) == 1) { temp = temp * e; } if (Math.Abs(arg_lr[i, 1]) == 2) { temp = temp * e * e; } sl = sl + temp; } //(* correction terms sl = sl + 3958 * GCMath.sinDeg(a1) + 1962 * GCMath.sinDeg(ls - f) + 318 * GCMath.sinDeg(a2); sb = 0; for (i = 0; i < 60; i++) { temp = sigma_b[i] * GCMath.sinDeg(arg_b[i, 0] * d + arg_b[i, 1] * m + arg_b[i, 2] * ms + arg_b[i, 3] * f); if (Math.Abs(arg_b[i, 1]) == 1) { temp = temp * e; } if (Math.Abs(arg_b[i, 1]) == 2) { temp = temp * e * e; } sb = sb + temp; } //(* correction terms sb = sb - 2235 * GCMath.sinDeg(ls) + 382 * GCMath.sinDeg(a3) + 175 * GCMath.sinDeg(a1 - f) + 175 * GCMath.sinDeg(a1 + f) + 127 * GCMath.sinDeg(ls - ms) - 115 * GCMath.sinDeg(ls + ms); GCEclipticalCoords coords; coords.longitude = ls + sl / 1000000; coords.latitude = sb / 1000000; coords.distance = 385000.56 + sr / 1000; return(coords); }
/// <summary> /// This is implementation from Chapter 21, Astronomical Algorithms /// Nutation of longitude and Obliquity of ecliptic /// </summary> /// <param name="julianDateUTC"></param> /// <param name="nutationLongitude"></param> /// <param name="obliquity"></param> public static void CalculateNutations(double julianDateUTC, out double nutationLongitude, out double obliquity) { double t, omega; double d, m, ms, f, s, l, ls; int i; double meanObliquity, nutationObliquity; t = (julianDateUTC - 2451545.0) / 36525; // longitude of rising knot omega = GCMath.putIn360(125.04452 + (-1934.136261 + (0.0020708 + 1.0 / 450000 * t) * t) * t); if (LowPrecisionNutations) { // (*@/// delta_phi and delta_epsilon - low accuracy *) //(* mean longitude of sun (l) and moon (ls) *) l = 280.4665 + 36000.7698 * t; ls = 218.3165 + 481267.8813 * t; //(* correction due to nutation *) nutationObliquity = 9.20 * GCMath.cosDeg(omega) + 0.57 * GCMath.cosDeg(2 * l) + 0.10 * GCMath.cosDeg(2 * ls) - 0.09 * GCMath.cosDeg(2 * omega); //(* longitude correction due to nutation *) nutationLongitude = (-17.20 * GCMath.sinDeg(omega) - 1.32 * GCMath.sinDeg(2 * l) - 0.23 * GCMath.sinDeg(2 * ls) + 0.21 * GCMath.sinDeg(2 * omega)) / 3600; } else { // mean elongation of moon to sun d = GCMath.putIn360(297.85036 + (445267.111480 + (-0.0019142 + t / 189474) * t) * t); // mean anomaly of the sun m = GCMath.putIn360(357.52772 + (35999.050340 + (-0.0001603 - t / 300000) * t) * t); // mean anomaly of the moon ms = GCMath.putIn360(134.96298 + (477198.867398 + (0.0086972 + t / 56250) * t) * t); // argument of the latitude of the moon f = GCMath.putIn360(93.27191 + (483202.017538 + (-0.0036825 + t / 327270) * t) * t); nutationLongitude = 0; nutationObliquity = 0; for (i = 0; i < 31; i++) { s = arg_mul[i, 0] * d + arg_mul[i, 1] * m + arg_mul[i, 2] * ms + arg_mul[i, 3] * f + arg_mul[i, 4] * omega; nutationLongitude = nutationLongitude + (arg_phi[i, 0] + arg_phi[i, 1] * t * 0.1) * GCMath.sinDeg(s); nutationObliquity = nutationObliquity + (arg_eps[i, 0] + arg_eps[i, 1] * t * 0.1) * GCMath.cosDeg(s); } nutationLongitude = nutationLongitude * 0.0001 / 3600; nutationObliquity = nutationObliquity * 0.0001; } // angle of ecliptic meanObliquity = 84381.448 + (-46.8150 + (-0.00059 + 0.001813 * t) * t) * t; obliquity = (meanObliquity + nutationObliquity) / 3600; }
// this is not used effectovely // it is just try to have some alternative function for calculation sun position // but it needs to be fixed, because // it calculates correct ecliptical coordinates, but when transforming // into horizontal coordinates (azimut, elevation) it will do something wrong public static GCHorizontalCoords sunPosition(int year, int month, int day, int hour, int min, int sec, double lat, double longi) { double twopi = GCMath.PI2; double deg2rad = GCMath.PI2 / 180; int[] month_days = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30 }; for (int y2 = 0; y2 < month; y2++) { day += month_days[y2]; } if ((year % 4 == 0) && ((year % 400 == 0) || (year % 100 != 0)) && (day >= 60) && !(month == 2 & day == 60)) { day++; } //# Get Julian date - 2400000 double hourd = hour + min / 60.0 + sec / 3600.0; // hour plus fraction double delta = year - 1949; double leap = Math.Floor(delta / 4); // former leapyears double jd = 32916.5 + delta * 365 + leap + day + hourd / 24.0; // The input to the Atronomer's almanach is the difference between // the Julian date and JD 2451545.0 (noon, 1 January 2000) double time = jd - 51545.0; // Ecliptic coordinates // Mean longitude double mnlong = GCMath.putIn360(280.460 + .9856474 * time); // Mean anomaly double mnanom = GCMath.putIn360(357.528 + .9856003 * time); //mnanom <- mnanom * deg2rad // Ecliptic longitude and obliquity of ecliptic double eclong = mnlong + 1.915 * GCMath.sinDeg(mnanom) + 0.020 * GCMath.sinDeg(2 * mnanom); eclong = GCMath.putIn360(eclong); double oblqec = 23.439 - 0.0000004 * time; //-- eclong <- eclong * deg2rad //-- oblqec <- oblqec * deg2rad // Celestial coordinates // Right ascension and declination double num = GCMath.cosDeg(oblqec) * GCMath.sinDeg(eclong); double den = GCMath.cosDeg(eclong); double ra = GCMath.arcTan2Deg(num, den); while (ra < 0) { ra += 180; } //-- ra[den < 0] <- ra[den < 0] + pi if (den >= 0 && num < 0) { ra += 360; } double dec = GCMath.arcSinDeg(GCMath.sinDeg(oblqec) * GCMath.sinDeg(eclong)); // Local coordinates // Greenwich mean sidereal time double gmst = 6.697375 + .0657098242 * time + hourd; gmst = GCMath.putIn24(gmst); // Local mean sidereal time double lmst = gmst + longi / 15.0; lmst = GCMath.putIn24(lmst); lmst = lmst * 15.0; // Hour angle double ha = lmst - ra; ha = GCMath.putIn180(ha); // Azimuth and elevation double el = GCMath.arcSinDeg(GCMath.sinDeg(dec) * GCMath.sinDeg(lat) + GCMath.cosDeg(dec) * GCMath.cosDeg(lat) * GCMath.cosDeg(ha)); double az = GCMath.arcSinDeg(-GCMath.cosDeg(dec) * GCMath.sinDeg(ha) / GCMath.cosDeg(el)); //# ----------------------------------------------- //# New code //# Solar zenith angle double zenithAngle = GCMath.arccosDeg(GCMath.sinDeg(lat) * GCMath.sinDeg(dec) + GCMath.cosDeg(lat) * GCMath.cosDeg(dec) * GCMath.cosDeg(ha)); //# Solar azimuth az = GCMath.arccosDeg(((GCMath.sinDeg(lat) * GCMath.cosDeg(zenithAngle)) - GCMath.sinDeg(dec)) / (GCMath.cosDeg(lat) * GCMath.sinDeg(zenithAngle))); //# ----------------------------------------------- //# Azimuth and elevation el = GCMath.arcSinDeg(GCMath.sinDeg(dec) * GCMath.sinDeg(lat) + GCMath.cosDeg(dec) * GCMath.cosDeg(lat) * GCMath.cosDeg(ha)); //# ----------------------------------------------- //# New code if (ha > 0) { az += 180; } else { az = 540 - az; } az = GCMath.putIn360(az); // For logic and names, see Spencer, J.W. 1989. Solar Energy. 42(4):353 //cosAzPos <- (0 <= sin(dec) - sin(el) * sin(lat)) //sinAzNeg <- (sin(az) < 0) //az[cosAzPos & sinAzNeg] <- az[cosAzPos & sinAzNeg] + twopi //az[!cosAzPos] <- pi - az[!cosAzPos] /* * if (0 < GCMath.sinDeg(dec) - GCMath.sinDeg(el) * GCMath.sinDeg(lat)) * { * if(GCMath.sinDeg(az) < 0) * { * az = az + 360; * } * } * else * { * az = 180 - az; * } */ //el <- el / deg2rad //az <- az / deg2rad //lat <- lat / deg2rad GCHorizontalCoords coords; coords.azimut = az; coords.elevation = el; return(coords); }