static void ConvertEclipticToEquatorial(double jday, double lon, double lat, out double rasc, out double decl) { double d = jday - 2451543.5; double oblecl = 23.4393 - 3.563E-7 * d; double x = Degrees.Cos(lon) * Degrees.Cos(lat); double y = Degrees.Sin(lon) * Degrees.Cos(lat); double z = Degrees.Sin(lat); double xe = x; double ye = y * Degrees.Cos(oblecl) - z * Degrees.Sin(oblecl); double ze = y * Degrees.Sin(oblecl) + z * Degrees.Cos(oblecl); double r = Math.Sqrt(xe * xe + ye * ye); rasc = Degrees.Atan2(ye, xe); decl = Degrees.Atan2(ze, r); }
static void ConvertEquatorialToHorizontal(double jday, double longitude, double latitude, double rasc, double decl, out double azimuth, out double altitude) { double d = jday - 2451543.5; double w = 282.9404 + 4.70935E-5 * d; double M = 356.0470 + 0.9856002585 * d; double L = w + M; double UT = Degrees.Normalize(Math.IEEERemainder(d, 1.0) * 360.0); double hourAngle = Degrees.Normalize(longitude + L + 180.0 + UT - rasc); double x = Degrees.Cos(hourAngle) * Degrees.Cos(decl); double y = Degrees.Sin(hourAngle) * Degrees.Cos(decl); double z = Degrees.Sin(decl); double xhor = x * Degrees.Sin(latitude) - z * Degrees.Cos(latitude); double yhor = y; double zhor = x * Degrees.Cos(latitude) + z * Degrees.Sin(latitude); azimuth = Degrees.Atan2(yhor, xhor) + 180.0; altitude = Degrees.Atan2(zhor, Math.Sqrt(xhor * xhor + yhor * yhor)); }
public static Quaternion GetSunPosition(double jday, double longitude, double latitude) { double d = jday - 2451543.5; double w = 282.9404 + 4.70935E-5 * d; double e = 0.016709 - 1.151E-9 * d; double M = Degrees.Normalize(356.0470 + 0.9856002585 * d); double E = Degrees.Normalize(M + Radians.ToDegrees(e) * Degrees.Sin(M) * (1 + e * Degrees.Cos(M))); double xv = Degrees.Cos(E) - e; double yv = Degrees.Sin(E) * Math.Sqrt(1 - e * e); double r = Math.Sqrt(xv * xv + yv * yv); double lon = Degrees.Atan2(yv, xv) + w; double lat = 0; double rasc, decl; ConvertEclipticToEquatorial(jday, lon, lat, out rasc, out decl); ConvertEquatorialToHorizontal(jday, longitude, latitude, rasc, decl, out double azimuth, out double altitude); // convert to unity rotation azim, altitude y then x return(Quaternion.Euler(0f, (float)azimuth + 180.0f, 0f) * Quaternion.Euler((float)altitude, 0f, 0f)); }
static void GetEclipticMoonPosition(double jday, out double lon, out double lat, out double dist) { double d = jday - 2451543.5; double N = 125.1228 - 0.0529538083 * d; // long asc node double i = 5.1454; // inclination double wm = 318.0634 + 0.1643573223 * d; // arg of perigee double a = 60.2666; // mean distance double e = 0.054900; // eccentricity double ws = 282.9404 + 4.70935E-5 * d; double Ms = Degrees.Normalize(356.0470 + 0.9856002585 * d); // Sun's mean anomaly double Mm = Degrees.Normalize(115.3654 + 13.0649929505 * d); // Moon's mean anomaly double Ls = Degrees.Normalize(ws + Ms); // Sun's mean longitude double Lm = Degrees.Normalize(N + wm + Mm); // Moon's mean longitude double D = Degrees.Normalize(Lm - Ls); // Moon's mean elongation double F = Degrees.Normalize(Lm - N); // Moon's argument of latitude double E0 = Mm + e * Degrees.Sin(Mm) * (1.0 + e * Degrees.Cos(Mm)); double diff = 1.0; while (diff > 0.005) { double E1 = E0 - (E0 - e * Degrees.Sin(E0) - Mm) / (1.0 + e * Degrees.Cos(E0)); diff = Math.Abs(E0 - E1); E0 = E1; } // rectangular coordinates in the plane of lunar orbit double x = a * (Degrees.Cos(E0) - e); double y = a * Math.Sqrt(1.0 - e * e) * Degrees.Sin(E0); // distance and true anomaly double r = Math.Sqrt(x * x + y * y); double v = Degrees.Atan2(y, x); // position in ecliptic coordinates double xe = Degrees.Cos(N) * Degrees.Cos(v + wm) - Degrees.Sin(N) * Degrees.Sin(v + wm) * Degrees.Cos(i); double ye = Degrees.Sin(N) * Degrees.Cos(v + wm) + Degrees.Cos(N) * Degrees.Sin(v + wm) * Degrees.Cos(i); double ze = Degrees.Sin(v + wm) * Degrees.Sin(i); double longitude = Degrees.Atan2(ye, xe); double latitude = Degrees.Atan2(ze, Math.Sqrt(xe * xe + ye * ye)); lon = longitude - 1.274 * Degrees.Sin(Mm - 2 * D) // Evection + 0.658 * Degrees.Sin(2 * D) // Variation - 0.186 * Degrees.Sin(Ms) // Yearly equation - 0.059 * Degrees.Sin(2 * Mm - 2 * D) - 0.057 * Degrees.Sin(Mm - 2 * D + Ms) + 0.053 * Degrees.Sin(Mm + 2 * D) + 0.046 * Degrees.Sin(2 * D - Ms) + 0.041 * Degrees.Sin(Mm - Ms) - 0.035 * Degrees.Sin(D) // Parallactic equation - 0.031 * Degrees.Sin(Mm + Ms) - 0.015 * Degrees.Sin(2 * F - 2 * D) + 0.011 * Degrees.Sin(Mm - 4 * D); lat = latitude - 0.173 * Degrees.Sin(F - 2 * D) - 0.055 * Degrees.Sin(Mm - F - 2 * D) - 0.046 * Degrees.Sin(Mm + F - 2 * D) + 0.033 * Degrees.Sin(F + 2 * D) + 0.017 * Degrees.Sin(2 * Mm + F); dist = r - 0.58 * Degrees.Cos(Mm - 2 * D) - 0.46 * Degrees.Cos(2 * D); lon = Degrees.Normalize(lon); lat = Degrees.Normalize(lat); }
public static void GetSunRiseSet(TimeZoneInfo tz, DateTime dt, double longitude, double latitude, out float sunRiseStart, out float sunRiseEnd, out float sunSetStart, out float sunSetEnd) { // get julian day at noon var utcNoon = TimeZoneInfo.ConvertTimeToUtc(new DateTime(dt.Year, dt.Month, dt.Day, 12, 0, 0, DateTimeKind.Unspecified), tz); double jdayNoon = GetJulianDayFromGregorianDateTime(utcNoon); float sunUpperLimb = -0.833f; float sunLowerLimb = 3f; // more than lower limb at horizon to look better // magic double d = jdayNoon - 2451543.5; double w = 282.9404 + 4.70935E-5 * d; double e = 0.016709 - 1.151E-9 * d; double M = Degrees.Normalize(356.0470 + 0.9856002585 * d); double E = Degrees.Normalize(M + Radians.ToDegrees(e) * Degrees.Sin(M) * (1 + e * Degrees.Cos(M))); double xv = Degrees.Cos(E) - e; double yv = Degrees.Sin(E) * Math.Sqrt(1 - e * e); double lon = Degrees.Atan2(yv, xv) + w; double lat = 0; double rasc, decl; ConvertEclipticToEquatorial(jdayNoon, lon, lat, out rasc, out decl); double Ls = Degrees.Normalize(w + M); double GMST = Degrees.Normalize(Ls + 180); double UTSunInSouth = Degrees.Normalize(rasc - GMST - longitude) / 15.0f; var noonUtc = new DateTime(dt.Year, dt.Month, dt.Day, 12, 0, 0, DateTimeKind.Utc); var offset = tz.GetUtcOffset(noonUtc); double cosLHA = (Degrees.Sin(sunUpperLimb) - Degrees.Sin(latitude) * Degrees.Sin(decl)) / (Degrees.Cos(latitude) * Degrees.Cos(decl)); if (cosLHA < -1) { // never set sunRiseStart = 0; sunSetEnd = 24; } else if (cosLHA > 1) { // never rise sunRiseStart = 24; sunSetEnd = 0; } else { double LHA = Degrees.Acos(cosLHA); double convert = LHA / 15f; sunRiseStart = (float)(UTSunInSouth - convert + offset.TotalHours); sunSetEnd = (float)(UTSunInSouth + convert + offset.TotalHours); } cosLHA = (Degrees.Sin(sunLowerLimb) - Degrees.Sin(latitude) * Degrees.Sin(decl)) / (Degrees.Cos(latitude) * Degrees.Cos(decl)); if (cosLHA < -1) { // never set sunRiseEnd = 0; sunSetStart = 24; } else if (cosLHA > 1) { // never rise sunRiseEnd = 24; sunSetStart = 0; } else { double LHA = Degrees.Acos(cosLHA); double convert = LHA / 15f; sunRiseEnd = (float)(UTSunInSouth - convert + offset.TotalHours); sunSetStart = (float)(UTSunInSouth + convert + offset.TotalHours); } }