private static DateTime Get_Soltice_Equinox_From_JDE0(double JDE0, double offset) { //Get Event Ch 27. double T = (JDE0 - 2451545.0) / 36525; double W = (35999.373 * Math.PI / 180) * T - (2.47 * Math.PI / 180); double ang = 1 + .0334 * Math.Cos(W) + .0007 * Math.Cos(2 * W); double sum = MeeusTables.Equinox_Solstice_Sum_of_S(T); double JDE = JDE0 + ((.00001) * sum / ang); DateTime?d = JulianConversions.GetDate_FromJulian(JDE); if (d.HasValue) { return(JulianConversions.GetDate_FromJulian(JDE).Value.AddHours(offset)); } return(new DateTime()); //Julian limit exceeded, return empty DateTime }
/// <summary> /// Gets times for additional solar times /// </summary> private static void getTimes(DateTime date, double lng, double lat, Celestial c) { //Get Julian double d = JulianConversions.GetJulian(date) - j2000 + .5; //LESS PRECISE JULIAN NEEDED double lw = rad * -lng; double phi = rad * lat; double n = julianCycle(d, lw); double ds = approxTransit(0, lw, n); double M = solarMeanAnomaly(ds); double L = eclipticLongitude(M); double dec = declination(L, 0); double Jnoon = solarTransitJ(ds, M, L); double Jset; double Jrise; DateTime?solarNoon = JulianConversions.GetDate_FromJulian(Jnoon); DateTime?nadir = JulianConversions.GetDate_FromJulian(Jnoon - 0.5); c.AdditionalSolarTimes = new AdditionalSolarTimes(); //Dusk and Dawn Jset = GetTime(-6 * rad, lw, phi, dec, n, M, L); Jrise = Jnoon - (Jset - Jnoon); c.AdditionalSolarTimes.CivilDawn = DayMatch(JulianConversions.GetDate_FromJulian(Jrise), date); c.AdditionalSolarTimes.CivilDusk = DayMatch(JulianConversions.GetDate_FromJulian(Jset), date); Jset = GetTime(-12 * rad, lw, phi, dec, n, M, L); Jrise = Jnoon - (Jset - Jnoon); c.AdditionalSolarTimes.NauticalDawn = DayMatch(JulianConversions.GetDate_FromJulian(Jrise), date); c.AdditionalSolarTimes.NauticalDusk = DayMatch(JulianConversions.GetDate_FromJulian(Jset), date); }
/// <summary> /// Gets time of event based on specified degree below horizon /// </summary> /// <param name="lw">Observer Longitude in radians</param> /// <param name="phi">Observer Latitude in radians</param> /// <param name="h">Angle in Degrees</param> /// <param name="date">Date of Event</param> /// <returns>DateTime?[]{rise, set}</returns> private static DateTime?[] Get_Event_Time(double lw, double phi, double h, DateTime date) { //Create arrays. Index 0 = Day -1, 1 = Day, 2 = Day + 1; //These will be used to find exact day event occurs for comparison DateTime?[] sets = new DateTime?[] { null, null, null, null, null }; DateTime?[] rises = new DateTime?[] { null, null, null, null, null }; //Iterate starting with day -1; for (int x = 0; x < 5; x++) { double d = JulianConversions.GetJulian(date.AddDays(x - 2)) - j2000 + .5; //LESS PRECISE JULIAN NEEDED double n = julianCycle(d, lw); double ds = approxTransit(0, lw, n); double M = solarMeanAnomaly(ds); double L = eclipticLongitude(M); double dec = declination(L, 0); double Jnoon = solarTransitJ(ds, M, L); double Jset; double Jrise; DateTime?solarNoon = JulianConversions.GetDate_FromJulian(Jnoon); DateTime?nadir = JulianConversions.GetDate_FromJulian(Jnoon - 0.5); //Rise Set Jset = GetTime(h * rad, lw, phi, dec, n, M, L); Jrise = Jnoon - (Jset - Jnoon); DateTime?rise = JulianConversions.GetDate_FromJulian(Jrise); DateTime?set = JulianConversions.GetDate_FromJulian(Jset); rises[x] = rise; sets[x] = set; } //Compare and send DateTime?tRise = null; for (int x = 0; x < 5; x++) { if (rises[x].HasValue) { if (rises[x].Value.Day == date.Day) { tRise = rises[x]; break; } } } DateTime?tSet = null; for (int x = 0; x < 5; x++) { if (sets[x].HasValue) { if (sets[x].Value.Day == date.Day) { tSet = sets[x]; break; } } } return(new DateTime?[] { tRise, tSet }); }
/// <summary> /// Gets time of event based on specified degree below specified altitude /// </summary> /// <param name="lw">Observer Longitude in radians</param> /// <param name="phi">Observer Latitude in radians</param> /// <param name="h">Angle in Degrees</param> /// <param name="date">Date of Event</param> /// <param name="offset">Offset hours</param> /// <param name="calculateNoon">Should solar noon iterate and return value</param> /// <returns>DateTime?[]{rise, set}</returns> internal static DateTime?[] Get_Event_Time(double lw, double phi, double h, DateTime date, double offset, bool calculateNoon) { double julianOffset = offset * .04166667; //Create arrays. Index 0 = Day -1, 1 = Day, 2 = Day + 1; //These will be used to find exact day event occurs for comparison DateTime?[] sets = new DateTime?[] { null, null, null, null, null }; DateTime?[] rises = new DateTime?[] { null, null, null, null, null }; DateTime?[] solarNoons = new DateTime?[] { null, null, null, null, null }; //Iterate starting with day -1; for (int x = 0; x < 5; x++) { double d = JulianConversions.GetJulian(date.AddDays(x - 2)) - j2000 + .5; //LESS PRECISE JULIAN NEEDED double n = julianCycle(d, lw); //var celC = Get_Solar_Coordinates(date); //Change and Test locs! double ds = approxTransit(0, lw, n); //M = celC.MeanAnomaly.ToRadians(); double M = solarMeanAnomaly(ds); double L = eclipticLongitude(M); double dec = declination(L, 0); double Jnoon = solarTransitJ(ds, M, L); //Rise Set double Jset = GetTime(h * rad, lw, phi, dec, n, M, L); double Jrise = Jnoon - (Jset - Jnoon); DateTime?rise = JulianConversions.GetDate_FromJulian(Jrise + julianOffset); //Adjusting julian for DT OFFSET MAY HELP WITH LOCAL TIME DateTime?set = JulianConversions.GetDate_FromJulian(Jset + julianOffset); //Adjusting julian for DT OFFSET MAY HELP WITH LOCAL TIME rises[x] = rise; sets[x] = set; if (calculateNoon) { solarNoons[x] = JulianConversions.GetDate_FromJulian(Jnoon + julianOffset); } } //Compare and send DateTime?tRise = Get_Event_Target_Date(rises, date); DateTime?tSet = Get_Event_Target_Date(sets, date); DateTime?tNoon = null; if (calculateNoon) { tNoon = Get_Event_Target_Date(solarNoons, date); } return(new DateTime?[] { tRise, tSet, tNoon }); }
//v1.1.3 Formulas //The following formulas are either additions //or conversions of SunCalcs formulas into Meeus /// <summary> /// Grabs Perigee or Apogee of Moon based on specified time. /// Results will return event just before, or just after specified DateTime /// </summary> /// <param name="d">DateTime</param> /// <param name="md">Event Type</param> /// <returns>PerigeeApogee</returns> private static PerigeeApogee MoonPerigeeOrApogee(DateTime d, MoonDistanceType md) { //Perigee & Apogee Algorithms from Jean Meeus Astronomical Algorithms Ch. 50 //50.1 //JDE = 2451534.6698 + 27.55454989 * k // -0.0006691 * Math.Pow(T,2) // -0.000.01098 * Math.Pow(T,3) // -0.0000000052 * Math.Pow(T,4) //50.2 //K approx = (yv - 1999.97)*13.2555 //yv is the year + percentage of days that have occured in the year. 1998 Oct 1 is approx 1998.75 //k ending in .0 represent perigee and .5 apogee. Anything > .5 is an error. //50.3 //T = k/1325.55 double yt = 365; //days in year if (DateTime.IsLeapYear(d.Year)) { yt = 366; } //days in year if leap year double f = d.DayOfYear / yt; //Get percentage of year that as passed double yv = d.Year + f; //add percentage of year passed to year. double k = (yv - 1999.97) * 13.2555; //find approximate k using formula 50.2 //Set k decimal based on apogee or perigee if (md == MoonDistanceType.Apogee) { k = Math.Floor(k) + .5; } else { k = Math.Floor(k); } //Find T using formula 50.3 double T = k / 1325.55; //Find JDE using formula 50.1 double JDE = 2451534.6698 + 27.55454989 * k - 0.0006691 * Math.Pow(T, 2) - 0.00001098 * Math.Pow(T, 3) - 0.0000000052 * Math.Pow(T, 4); //Find Moon's mean elongation at time JDE. double D = 171.9179 + 335.9106046 * k - 0.0100383 * Math.Pow(T, 2) - 0.00001156 * Math.Pow(T, 3) + 0.000000055 * Math.Pow(T, 4); //Find Sun's mean anomaly at time JDE double M = 347.3477 + 27.1577721 * k - 0.0008130 * Math.Pow(T, 2) - 0.0000010 * Math.Pow(T, 3); //Find Moon's argument of latitude at Time JDE double F = 316.6109 + 364.5287911 * k - 0.0125053 * Math.Pow(T, 2) - 0.0000148 * Math.Pow(T, 3); //Normalize DMF to a 0-360 degree number D %= 360; if (D < 0) { D += 360; } M %= 360; if (M < 0) { M += 360; } F %= 360; if (F < 0) { F += 360; } //Convert DMF to radians D = D * Math.PI / 180; M = M * Math.PI / 180; F = F * Math.PI / 180; double termsA; //Find Terms A from Table 50.A if (md == MoonDistanceType.Apogee) { termsA = MeeusTables.ApogeeTermsA(D, M, F, T); } else { termsA = MeeusTables.PerigeeTermsA(D, M, F, T); } JDE += termsA; double termsB; if (md == MoonDistanceType.Apogee) { termsB = MeeusTables.ApogeeTermsB(D, M, F, T); } else { termsB = MeeusTables.PerigeeTermsB(D, M, F, T); } //Convert julian back to date DateTime date = JulianConversions.GetDate_FromJulian(JDE).Value; //Obtain distance Distance dist = GetMoonDistance(date); PerigeeApogee ap = new PerigeeApogee(date, termsB, dist); return(ap); }