using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace CoordinateSharp { internal partial class MeeusTables { /// /// Returns Moon Periodic Value Er /// /// Moon's mean elongation /// Sun's mean anomaly /// Moon's mean anomaly /// Moon's argument of latitude /// Dynamic time /// Er public static double Moon_Periodic_Er(double D, double M, double N, double F, double T) { //Table 47A contains 60 lines to sum double[] values = new double[] { D, M, N, F }; double sum = 0; for (int x = 0; x < 60; x++) { sum += Get_Table47A_Values(values, x, T, false); } return sum; } /// /// Returns Moon Periodic Value El /// /// Moon's mean longitude /// Moon's mean elongation /// Sun's mean anomaly /// Moon's mean anomaly /// Moon's argument of latitude /// Dynamic time /// El public static double Moon_Periodic_El(double L, double D, double M, double N, double F, double T) { //Table 47A contains 60 lines to sum double[] values = new double[] { D, M, N, F }; double sum = 0; for (int x = 0; x < 60; x++) { sum += Get_Table47A_Values(values, x, T, true); } //Planetary adjustments double A1 = 119.75 + 131.849 * T; double A2 = 53.09 + 479264.290 * T; //Normalize 0-360 degree number A1 %= 360; if (A1 < 0) { A1 += 360; } A2 %= 360; if (A2 < 0) { A2 += 360; } //Convert DMF to radians A1 = A1 * Math.PI / 180; A2 = A2 * Math.PI / 180; //L TO RADIANS L %= 360; if (L < 0) { L += 360; } //Convert DMF to radians L = L * Math.PI / 180; sum += 3958 * Math.Sin(A1); sum += 1962 * Math.Sin(L - F); sum += 318 * Math.Sin(A2); return sum; } /// /// Returns Moon Periodic Value Eb /// /// Moon's mean longitude /// Moon's mean elongation /// Sun's mean anomaly /// Moon's mean anomaly /// Moon's argument of latitude /// Dynamic time /// Eb public static double Moon_Periodic_Eb(double L, double D, double M, double N, double F, double T) { //Table 47B contains 60 lines to sum double[] values = new double[] { D, M, N, F }; double sum = 0; for (int x = 0; x < 60; x++) { sum += Get_Table47B_Values(values, x, T); } //Planetary adjustments double A1 = 119.75 + 131.849 * T; double A3 = 313.45 + 481266.484 * T; //Normalize 0-360 degree number A1 %= 360; if (A1 < 0) { A1 += 360; } A3 %= 360; if (A3 < 0) { A3 += 360; } //Convert DMF to radians A1 = A1 * Math.PI / 180; A3 = A3 * Math.PI / 180; //L TO RADIANS L %= 360; if (L < 0) { L += 360; } //Convert DMF to radians L = L * Math.PI / 180; sum += -2235 * Math.Sin(L); sum += 382 * Math.Sin(A3); sum += 175 * Math.Sin(A1 - F); sum += 175 * Math.Sin(A1 + F); sum += 127 * Math.Sin(L - M); sum += -115 * Math.Sin(L + M); return sum; } //Ch 50 /// /// Sum of Apogee Terms from Jean Meeus Astronomical Algorithms Table 50.A /// /// Moom's mean elongation at time JDE /// Sun's mean anomaly /// Moon's arguement f latitude /// Time in Julian centuries since epoch 2000 /// double public static double ApogeeTermsA(double D, double M, double F, double T) { double sum; sum = Math.Sin(2 * D) * 0.4392; sum += Math.Sin(4 * D) * 0.0684; sum += Math.Sin(M) * .0456 - 0.00011 * T; sum += Math.Sin(2 * D - M) * .0426 - 0.00011 * T; sum += Math.Sin(2 * F) * .0212; sum += Math.Sin(D) * -0.0189; sum += Math.Sin(6 * D) * .0144; sum += Math.Sin(4 * D - M) * .0113; sum += Math.Sin(2 * D + 2 * F) * .0047; sum += Math.Sin(D + M) * .0036; sum += Math.Sin(8 * D) * .0035; sum += Math.Sin(6 * D - M) * .0034; sum += Math.Sin(2 * D - 2 * F) * -0.0034; sum += Math.Sin(2 * D - 2 * M) * .0022; sum += Math.Sin(3 * D) * -.0017; sum += Math.Sin(4 * D + 2 * F) * 0.0013; sum += Math.Sin(8 * D - M) * .0011; sum += Math.Sin(4 * D - 2 * M) * .0010; sum += Math.Sin(10 * D) * .0009; sum += Math.Sin(3 * D + M) * .0007; sum += Math.Sin(2 * M) * .0006; sum += Math.Sin(2 * D + M) * .0005; sum += Math.Sin(2 * D + 2 * M) * .0005; sum += Math.Sin(6 * D + 2 * F) * .0004; sum += Math.Sin(6 * D - 2 * M) * .0004; sum += Math.Sin(10 * D - M) * .0004; sum += Math.Sin(5 * D) * -0.0004; sum += Math.Sin(4 * D - 2 * F) * -0.0004; sum += Math.Sin(2 * F + M) * .0003; sum += Math.Sin(12 * D) * .0003; sum += Math.Sin(2 * D + 2 * F - M) * 0.0003; sum += Math.Sin(D - M) * -0.0003; return sum; } /// /// Sum of Perigee Terms from Jean Meeus Astronomical Algorithms Table 50.A /// /// Moom's mean elongation at time JDE /// Sun's mean anomaly /// Moon's arguement f latitude /// Time in Julian centuries since epoch 2000 /// double public static double PerigeeTermsA(double D, double M, double F, double T) { double sum; sum = Math.Sin(2 * D) * -1.6769; sum += Math.Sin(4 * D) * .4589; sum += Math.Sin(6 * D) * -.1856; sum += Math.Sin(8 * D) * .0883; sum += Math.Sin(2 * D - M) * -.0773 + .00019 * T; sum += Math.Sin(M) * .0502 - .00013 * T; sum += Math.Sin(10 * D) * -.0460; sum += Math.Sin(4 * D - M) * .0422 - .00011 * T; sum += Math.Sin(6 * D - M) * -.0256; sum += Math.Sin(12 * D) * .0253; sum += Math.Sin(D) * .0237; sum += Math.Sin(8 * D - M) * .0162; sum += Math.Sin(14 * D) * -.0145; sum += Math.Sin(2 * F) * .0129; sum += Math.Sin(3 * D) * -.0112; sum += Math.Sin(10 * D - M) * -.0104; sum += Math.Sin(16 * D) * .0086; sum += Math.Sin(12 * D - M) * .0069; sum += Math.Sin(5 * D) * .0066; sum += Math.Sin(2 * D + 2 * F) * -.0053; sum += Math.Sin(18 * D) * -.0052; sum += Math.Sin(14 * D - M) * -.0046; sum += Math.Sin(7 * D) * -.0041; sum += Math.Sin(2 * D + M) * .0040; sum += Math.Sin(20 * D) * .0032; sum += Math.Sin(D + M) * -.0032; sum += Math.Sin(16 * D - M) * .0031; sum += Math.Sin(4 * D + M) * -.0029; sum += Math.Sin(9 * D) * .0027; sum += Math.Sin(4 * D + 2 * F) * .0027; sum += Math.Sin(2 * D - 2 * M) * -.0027; sum += Math.Sin(4 * D - 2 * M) * .0024; sum += Math.Sin(6 * D - 2 * M) * -.0021; sum += Math.Sin(22 * D) * -.0021; sum += Math.Sin(18 * D - M) * -.0021; sum += Math.Sin(6 * D + M) * .0019; sum += Math.Sin(11 * D) * -.0018; sum += Math.Sin(8 * D + M) * -.0014; sum += Math.Sin(4 * D - 2 * F) * -.0014; sum += Math.Sin(6 * D + 2 * F) * -.0014; sum += Math.Sin(3 * D + M) * .0014; sum += Math.Sin(5 * D + M) * -.0014; sum += Math.Sin(13 * D) * .0013; sum += Math.Sin(20 * D - M) * .0013; sum += Math.Sin(3 * D + 2 * M) * .0011; sum += Math.Sin(4 * D + 2 * F - 2 * M) * -.0011; sum += Math.Sin(D + 2 * M) * -.0010; sum += Math.Sin(22 * D - M) * -.0009; sum += Math.Sin(4 * F) * -.0008; sum += Math.Sin(6 * D - 2 * F) * .0008; sum += Math.Sin(2 * D - 2 * F + M) * .0008; sum += Math.Sin(2 * M) * .0007; sum += Math.Sin(2 * F - M) * .0007; sum += Math.Sin(2 * D + 4 * F) * .0007; sum += Math.Sin(2 * F - 2 * M) * -.0006; sum += Math.Sin(2 * D - 2 * F + 2 * M) * -.0006; sum += Math.Sin(24 * D) * .0006; sum += Math.Sin(4 * D - 4 * F) * .0005; sum += Math.Sin(2 * D + 2 * M) * .0005; sum += Math.Sin(D - M) * -.0004; return sum; } /// /// Sum of Apogee Terms from Jean Meeus Astronomical Algorithms Table 50.B /// /// Moom's mean elongation at time JDE /// Sun's mean anomaly /// Moon's arguement f latitude /// Time in Julian centuries since epoch 2000 /// double public static double ApogeeTermsB(double D, double M, double F, double T) { double sum = 3245.251; sum += Math.Cos(2 * D) * -9.147; sum += Math.Cos(D) * -.841; sum += Math.Cos(2 * F) * .697; sum += Math.Cos(M) * -0.656 + .0016 * T; sum += Math.Cos(4 * D) * .355; sum += Math.Cos(2 * D - M) * .159; sum += Math.Cos(D + M) * .127; sum += Math.Cos(4 * D - M) * .065; sum += Math.Cos(6 * D) * .052; sum += Math.Cos(2 * D + M) * .043; sum += Math.Cos(2 * D + 2 * F) * .031; sum += Math.Cos(2 * D - 2 * F) * -.023; sum += Math.Cos(2 * D - 2 * M) * .022; sum += Math.Cos(2 * D + 2 * M) * .019; sum += Math.Cos(2 * M) * -.016; sum += Math.Cos(6 * D - M) * .014; sum += Math.Cos(8 * D) * .010; return sum; } /// /// Sum of Perigee Terms from Jean Meeus Astronomical Algorithms Table 50.B /// /// Moom's mean elongation at time JDE /// Sun's mean anomaly /// Moon's arguement f latitude /// Time in Julian centuries since epoch 2000 /// double public static double PerigeeTermsB(double D, double M, double F, double T) { //Sum of Perigee Terms from Jean Meeus Astronomical Algorithms Table 50.B double sum = 3629.215; sum += Math.Cos(2 * D) * 63.224; sum += Math.Cos(4 * D) * -6.990; sum += Math.Cos(2 * D - M) * 2.834 - .0071 * T; sum += Math.Cos(6 * D) * 1.927; sum += Math.Cos(D) * -1.263; sum += Math.Cos(8 * D) * -.702; sum += Math.Cos(M) * .696 - .0017 * T; sum += Math.Cos(2 * F) * -.690; sum += Math.Cos(4 * D - M) * -.629 + .0016 * T; sum += Math.Cos(2 * D - 2 * F) * -.392; sum += Math.Cos(10 * D) * .297; sum += Math.Cos(6 * D - M) * .260; sum += Math.Cos(3 * D) * .201; sum += Math.Cos(2 * D + M) * -.161; sum += Math.Cos(D + M) * .157; sum += Math.Cos(12 * D) * -.138; sum += Math.Cos(8 * D - M) * -.127; sum += Math.Cos(2 * D + 2 * F) * .104; sum += Math.Cos(2 * D - 2 * M) * .104; sum += Math.Cos(5 * D) * -.079; sum += Math.Cos(14 * D) * .068; sum += Math.Cos(10 * D - M) * .067; sum += Math.Cos(4 * D + M) * .054; sum += Math.Cos(12 * D - M) * -.038; sum += Math.Cos(4 * D - 2 * M) * -.038; sum += Math.Cos(7 * D) * .037; sum += Math.Cos(4 * D + 2 * F) * -.037; sum += Math.Cos(16 * D) * -.035; sum += Math.Cos(3 * D + M) * -.030; sum += Math.Cos(D - M) * .029; sum += Math.Cos(6 * D + M) * -.025; sum += Math.Cos(2 * M) * .023; sum += Math.Cos(14 * D - M) * .023; sum += Math.Cos(2 * D + 2 * M) * -.023; sum += Math.Cos(6 * D - 2 * M) * .022; sum += Math.Cos(2 * D - 2 * F - M) * -.021; sum += Math.Cos(9 * D) * -.020; sum += Math.Cos(18 * D) * .019; sum += Math.Cos(6 * D + 2 * F) * .017; sum += Math.Cos(2 * F - M) * .014; sum += Math.Cos(16 * D - M) * -.014; sum += Math.Cos(4 * D - 2 * F) * .013; sum += Math.Cos(8 * D + M) * .012; sum += Math.Cos(11 * D) * .011; sum += Math.Cos(5 * D + M) * .010; sum += Math.Cos(20 * D) * -.010; return sum; } } internal class MeeusFormulas { public static double Get_Sidereal_Time(double JD) { //Ch. 12 //T = Dynamic Time //Oo = mean sidereal time at Greenwich at 0h UT double T = (JD - 2451545) / 36525; double Oo = 280.46061837 + 360.98564736629 * (JD - 2451545) + .000387933 * Math.Pow(T, 2) - Math.Pow(T, 3) / 38710000; return Oo; } } /// /// Used to display a celestial condition for a specified date. /// [Serializable] public enum CelestialStatus { /// /// Celestial body rises and sets on the set day. /// RiseAndSet, /// /// Celestial body is down all day /// DownAllDay, /// /// Celestial body is up all day /// UpAllDay, /// /// Celestial body rises, but does not set on the set day /// NoRise, /// /// Celestial body sets, but does not rise on the set day /// NoSet } /// /// moon perigee or apogee indicator /// internal enum MoonDistanceType { /// /// Moon's perigee /// Perigee, /// /// Moon's apogee /// Apogee } /// /// Moon Illumination Information /// [Serializable] public class MoonIllum { /// /// Moon's fraction /// public double Fraction { get; internal set; } /// /// Moon's Angle /// public double Angle { get; internal set; } /// /// Moon's phase /// public double Phase { get; internal set; } /// /// Moon's phase name for the specified day /// public string PhaseName { get; internal set; } } /// /// Stores Perigee or Apogee values /// [Serializable] public class PerigeeApogee { private DateTime date; private double horizontalParallax; private Distance distance; /// /// Initializes a Perigee or Apogee object /// /// Date of Event /// Horizontal Parallax /// Distance public PerigeeApogee(DateTime d, double p, Distance dist) { date = d; horizontalParallax = p; distance = dist; } /// /// Date of event. /// public DateTime Date { get { return date; } } /// /// Horizontal Parallax. /// public double HorizontalParallax { get { return horizontalParallax; } } /// /// Moon's distance at event. /// public Distance Distance { get { return distance; } } internal void Convert_To_Local_Time(double offset) { FieldInfo[] fields = typeof(PerigeeApogee).GetFields(BindingFlags.NonPublic | BindingFlags.Instance); foreach (FieldInfo field in fields) { if (field.FieldType == typeof(DateTime)) { DateTime d = (DateTime)field.GetValue(this); if (d > new DateTime()) { d = d.AddHours(offset); field.SetValue(this, d); } } } } } /// /// Julian date conversions /// public class JulianConversions { //1.1.3.1 private static double J1970 = 2440588, J2000 = 2451545; /// /// Returns JD. /// Meeus Ch 7. /// /// DateTime /// JDE public static double GetJulian(DateTime d) { double y = d.Year; double m = d.Month; double dy = d.Day + (d.TimeOfDay.TotalHours / 24); //If month is Jan or Feb add 12 to month and reduce year by 1. if(m <= 2) { m += 12; y -= 1; } double A = (int)(d.Year / 100.0); double B = 0; //Gregorian Start Date if(d >= new DateTime(1582,10,15)) { B = 2 - A + (int)(A / 4.0); } double JD = (int)(365.25 * (y + 4716)) + (int)(30.6001 * (m + 1)) + dy + B - 1524.5; return JD; } /// /// Returns JD from epoch 2000. /// Meeus Ch 7. /// /// DateTime /// JDE public static double GetJulian_Epoch2000(DateTime d) { return GetJulian(d) - J2000; } /// /// Returns JD from epoch 1970. /// Meeus Ch 7. /// /// DateTime /// JDE public static double GetJulian_Epoch1970(DateTime d) { return GetJulian(d) - J1970; } /// /// Returns date from Julian /// Meeus ch. 7 /// /// Julian /// DateTime public static DateTime? GetDate_FromJulian(double j) { if (Double.IsNaN(j)) { return null; } //No Event Occured j = j + .5; double Z = Math.Floor(j); double F = j - Z; double A = Z; if (Z >= 2299161) { double a = (int)((Z - 1867216.25) / 36524.25); A = Z + 1 + a - (int)(a / 4.0); } double B = A + 1524; double C = (int)((B - 122.1) / 365.25); double D = (int)(365.25 * C); double E = (int)((B - D) / 30.6001); double day = B - D - (int)(30.6001 * E) + F; //Month is E-1 if month is < 14 or E-13 if month is 14 or 15 double month = E-1; if (E > 13) { month -= 12; } //year is C-4716 if month>2 and C-4715 if month is 1 or 2 double year = C - 4715; if(month >2) { year -= 1; } double hours = day - Math.Floor(day); hours *= 24; double minutes = hours - Math.Floor(hours); minutes *= 60; double seconds = minutes - Math.Floor(minutes); seconds *= 60; day = Math.Floor(day); hours = Math.Floor(hours); minutes = Math.Floor(minutes); DateTime? date = new DateTime?(new DateTime((int)year, (int)month, (int)day, (int)hours, (int)minutes, (int)seconds)); return date; } /// /// Returns date from Julian based on epoch 2000 /// Meeus ch. 7 /// /// Julian /// DateTime public static DateTime? GetDate_FromJulian_Epoch2000(double j) { return GetDate_FromJulian(j+J2000); } /// /// Returns date from Julian based on epoch 1970 /// Meeus ch. 7 /// /// Julian /// DateTime public static DateTime? GetDate_FromJulian_Epoch1970(double j) { return GetDate_FromJulian(j + J1970); } } /// /// Contains last and next perigee /// [Serializable] public class Perigee { private PerigeeApogee lastPerigee; private PerigeeApogee nextPerigee; /// /// Initializes an Perigee object. /// /// /// public Perigee(PerigeeApogee last, PerigeeApogee next) { lastPerigee = last; nextPerigee = next; } /// /// Last perigee /// public PerigeeApogee LastPerigee { get { return lastPerigee; } } /// /// Next perigee /// public PerigeeApogee NextPerigee { get { return nextPerigee; } } internal void ConvertTo_Local_Time(double offset) { LastPerigee.Convert_To_Local_Time(offset); NextPerigee.Convert_To_Local_Time(offset); } } /// /// Contains last and next apogee /// [Serializable] public class Apogee { private PerigeeApogee lastApogee; private PerigeeApogee nextApogee; /// /// Initializes an Apogee object. /// /// /// public Apogee(PerigeeApogee last, PerigeeApogee next) { lastApogee = last; nextApogee = next; } /// /// Last apogee /// public PerigeeApogee LastApogee { get { return lastApogee; } } /// /// Next apogee /// public PerigeeApogee NextApogee { get { return nextApogee; } } internal void ConvertTo_Local_Time(double offset) { LastApogee.Convert_To_Local_Time(offset); NextApogee.Convert_To_Local_Time(offset); } } /// /// Astrological Signs /// [Serializable] public class AstrologicalSigns { /// /// Astrological Zodiac Sign /// public string MoonName { get; internal set; } /// /// Astrological Moon Sign /// public string MoonSign { get; internal set; } /// /// Astrological Zodiac Sign /// public string ZodiacSign { get; internal set; } } /// /// Additional Solar Time Information /// [Serializable] public class AdditionalSolarTimes { /// /// Create an AdditionalSolarTimes object. /// public AdditionalSolarTimes() { //Set dates to avoid null errors. If year return 1900 event did not occur. CivilDawn = new DateTime(); CivilDusk = new DateTime(); NauticalDawn = new DateTime(); NauticalDusk = new DateTime(); } /// /// Returns Civil Dawn Time /// public DateTime? CivilDawn { get; internal set; } /// /// Returns Civil Dusk Time /// public DateTime? CivilDusk { get; internal set; } /// /// Returns Nautical Dawn Time /// public DateTime? NauticalDawn { get; internal set; } /// /// Returns Nautical Dusk Time /// public DateTime? NauticalDusk { get; internal set; } /// /// Returns Astronomical Dawn Time /// public DateTime? AstronomicalDawn { get; internal set; } /// /// Returns Astronomical Dusk Time /// public DateTime? AstronomicalDusk { get; internal set; } /// /// Returns the time when the bottom of the solar disc touches the horizon after sunrise /// public DateTime? SunriseBottomDisc{ get; internal set; } /// /// Returns the time when the bottom of the solar disc touches the horizon before sunset /// public DateTime? SunsetBottomDisc { get; internal set; } internal void Convert_To_Local_Time(double offset) { FieldInfo[] fields = typeof(AdditionalSolarTimes).GetFields(BindingFlags.NonPublic | BindingFlags.Instance); foreach (FieldInfo field in fields) { if (field.FieldType == typeof(DateTime?)) { DateTime? d = (DateTime?)field.GetValue(this); if (d.HasValue) { if (d > new DateTime()) { d = d.Value.AddHours(offset); field.SetValue(this, d); } } } } } } /// /// Class containing solar eclipse information /// [Serializable] public class SolarEclipse { /// /// Initialize a SolarEclipse object /// public SolarEclipse() { LastEclipse = new SolarEclipseDetails(); NextEclipse = new SolarEclipseDetails(); } /// /// Details about the previous solar eclipse /// public SolarEclipseDetails LastEclipse { get; internal set; } /// /// Details about the next solar eclipse /// public SolarEclipseDetails NextEclipse { get; internal set; } internal void ConvertTo_LocalTime(double offset) { LastEclipse.Convert_To_Local_Time(offset); NextEclipse.Convert_To_Local_Time(offset); } } /// /// Class containing lunar eclipse information /// [Serializable] public class LunarEclipse { /// /// Initialize a LunarEclipse object /// public LunarEclipse() { LastEclipse = new LunarEclipseDetails(); NextEclipse = new LunarEclipseDetails(); } /// /// Details about the previous lunar eclipse /// public LunarEclipseDetails LastEclipse { get; internal set; } /// /// Details about the next lunar eclipse /// public LunarEclipseDetails NextEclipse { get; internal set; } internal void ConvertTo_LocalTime(double offset) { LastEclipse.Convert_To_Local_Time(offset); NextEclipse.Convert_To_Local_Time(offset); } } /// /// Class containing specific solar eclipse information /// [Serializable] public class SolarEclipseDetails { private DateTime date; private SolarEclipseType type; private DateTime partialEclispeBegin; private DateTime aorTEclipseBegin; private DateTime maximumEclipse; private DateTime aorTEclipseEnd; private DateTime partialEclispeEnd; private TimeSpan aorTDuration; private bool hasEclipseData; /// /// Initialize a SolarEclipseDetails object /// /// Solar Eclipse String Values public SolarEclipseDetails(List values) { //Eclipse has value hasEclipseData = true; //Set Eclipse Date date = Convert.ToDateTime(values[0]); switch (values[1]) { case "P": type = SolarEclipseType.Partial; break; case "A": type = SolarEclipseType.Annular; break; case "T": type = SolarEclipseType.Total; break; default: break; } TimeSpan ts; //Eclipse start if (TimeSpan.TryParse(values[2], out ts)) { partialEclispeBegin = date.Add(ts); } //A or T start if (TimeSpan.TryParse(values[4], out ts)) { aorTEclipseBegin = date.Add(ts); } //Maximum Eclipse if (TimeSpan.TryParse(values[5], out ts)) { maximumEclipse = date.Add(ts); } //A or T ends if (TimeSpan.TryParse(values[8], out ts)) { aorTEclipseEnd = date.Add(ts); } //Eclipse end if (TimeSpan.TryParse(values[9], out ts)) { partialEclispeEnd = date.Add(ts); } //A or T Duration if (values[13] != "-") { string s = values[13].Replace("m", ":").Replace("s", ""); string[] ns = s.Split(':'); int mins = 0; int secs = 0; int.TryParse(ns[0], out mins); if (ns.Count() > 0) { int.TryParse(ns[1], out secs); } TimeSpan time = new TimeSpan(0, mins, secs); aorTDuration = time; } else { aorTDuration = new TimeSpan(); } Adjust_Dates();//Adjust dates if required (needed when eclipse crosses into next day). } /// /// Initialize an empty SolarEclipseDetails object /// public SolarEclipseDetails() { hasEclipseData = false; } /// /// JS Eclipse Calc formulas didn't account for Z time calculation. /// Iterate through and adjust Z dates where eclipse is passed midnight. /// private void Adjust_Dates() { //Load array in reverse event order DateTime[] dateArray = new DateTime[] { partialEclispeBegin, aorTEclipseBegin, maximumEclipse, aorTEclipseEnd, partialEclispeEnd }; DateTime baseTime = partialEclispeEnd; bool multiDay = false; //used to detrmine if eclipse crossed into next Z day for (int x = 4; x >= 0; x--) { DateTime d = dateArray[x]; //Check if date exist if (d > new DateTime()) { //Adjust if time is less than then baseTime. if (d > baseTime) { switch (x) { case 3: aorTEclipseEnd = aorTEclipseEnd.AddDays(-1); break; case 2: maximumEclipse = maximumEclipse.AddDays(-1); break; case 1: aorTEclipseBegin = aorTEclipseBegin.AddDays(-1); break; case 0: partialEclispeBegin = partialEclispeBegin.AddDays(-1); break; default: break; } multiDay = true;//Set true to change base date value. } } } if (multiDay) { this.date = this.date.AddDays(-1); //Shave day off base date if multiday. } } /// /// Determine if the SolarEclipseDetails object has been populated /// public bool HasEclipseData { get { return hasEclipseData; } } /// /// Date of solar eclipse /// public DateTime Date { get { return date; } } /// /// Solar eclipse type /// public SolarEclipseType Type { get { return type; } } /// /// DateTime when the partial eclipse begins /// public DateTime PartialEclispeBegin { get { return partialEclispeBegin; } } /// /// DateTime when an Annular or Total eclipse begins (if applicable) /// public DateTime AorTEclipseBegin { get { return aorTEclipseBegin; } } /// /// DateTime when eclipse is at Maximum /// public DateTime MaximumEclipse { get { return maximumEclipse; } } /// /// DateTime when the Annular or Total eclipse ends (if applicable) /// public DateTime AorTEclipseEnd { get { return aorTEclipseEnd; } } /// /// DateTime when the partial elipse ends /// public DateTime PartialEclispeEnd { get { return partialEclispeEnd; } } /// /// Duration of Annular or Total eclipse (if applicable) /// public TimeSpan AorTDuration { get { return aorTDuration; } } /// /// Solat eclipse default string /// /// Solar eclipse base date string public override string ToString() { return date.ToString("dd-MMM-yyyy"); } internal void Convert_To_Local_Time(double offset) { FieldInfo[] fields = typeof(SolarEclipseDetails).GetFields(BindingFlags.NonPublic | BindingFlags.Instance); foreach (FieldInfo field in fields) { if (field.FieldType == typeof(DateTime)) { DateTime d = (DateTime)field.GetValue(this); if (d > new DateTime()) { d = d.AddHours(offset); field.SetValue(this, d); } } } date = partialEclispeBegin.Date; } } /// /// Class containing specific lunar eclipse information /// [Serializable] public class LunarEclipseDetails { private DateTime date; private LunarEclipseType type; private DateTime penumbralEclipseBegin; private DateTime partialEclispeBegin; private DateTime totalEclipseBegin; private DateTime midEclipse; private DateTime totalEclipseEnd; private DateTime partialEclispeEnd; private DateTime penumbralEclipseEnd; private bool hasEclipseData; /// /// Initialize a LunarEclipseDetails object /// /// Lunar Eclipse String Values public LunarEclipseDetails(List values) { //Eclipse has value hasEclipseData = true; //Set Eclipse Date date = Convert.ToDateTime(values[0]); switch (values[1]) { case "T": type = LunarEclipseType.Total; break; case "P": type = LunarEclipseType.Partial; break; case "N": type = LunarEclipseType.Penumbral; break; default: break; } TimeSpan ts; //Penumbral Eclipse start if (TimeSpan.TryParse(values[4], out ts)) { penumbralEclipseBegin = date.Add(ts); } //PartialEclipse start if (TimeSpan.TryParse(values[6], out ts)) { partialEclispeBegin = date.Add(ts); } //Total start if (TimeSpan.TryParse(values[8], out ts)) { totalEclipseBegin = date.Add(ts); } //Mid Eclipse if (TimeSpan.TryParse(values[10], out ts)) { midEclipse = date.Add(ts); } //Total ends if (TimeSpan.TryParse(values[12], out ts)) { totalEclipseEnd = date.Add(ts); } //Partial Eclipse end if (TimeSpan.TryParse(values[14], out ts)) { partialEclispeEnd = date.Add(ts); } //Penumbral Eclipse end if (TimeSpan.TryParse(values[16], out ts)) { penumbralEclipseEnd = date.Add(ts); } Adjust_Dates(); } /// /// Initialize an empty LunarEclipseDetails object /// public LunarEclipseDetails() { hasEclipseData = false; } /// /// JS Eclipse Calc formulas didn't account for Z time calculation. /// Iterate through and adjust Z dates where eclipse is passed midnight. /// private void Adjust_Dates() { //Load array in squential order. DateTime[] dateArray = new DateTime[] { penumbralEclipseBegin, partialEclispeBegin, totalEclipseBegin, midEclipse, totalEclipseEnd, partialEclispeEnd, penumbralEclipseEnd }; DateTime baseTime = partialEclispeEnd; bool multiDay = false; //used to detrmine if eclipse crossed into next Z day baseTime = penumbralEclipseBegin; for (int x = 0; x < dateArray.Count(); x++) { DateTime d = dateArray[x]; //Check if date exist if (d > new DateTime()) { if (d < baseTime) { multiDay = true; } } baseTime = dateArray[x]; if (multiDay == true) { switch (x) { case 1: partialEclispeBegin = partialEclispeBegin.AddDays(1); break; case 2: totalEclipseBegin = totalEclipseBegin.AddDays(1); break; case 3: midEclipse = midEclipse.AddDays(1); break; case 4: totalEclipseEnd = totalEclipseEnd.AddDays(1); break; case 5: partialEclispeEnd = partialEclispeEnd.AddDays(1); break; case 6: penumbralEclipseEnd = penumbralEclipseEnd.AddDays(1); break; default: break; } } } } /// /// Determine if the LunarEclipseDetails object has been populated /// public bool HasEclipseData { get { return hasEclipseData; } } /// /// Date of lunar eclipse /// public DateTime Date { get { return date; } } /// /// Lunar eclipse type /// public LunarEclipseType Type { get { return type; } } /// /// DateTime when the penumbral eclipse begins /// public DateTime PenumbralEclipseBegin { get { return penumbralEclipseBegin; } } /// /// DateTime when the partial eclipse begins (if applicable) /// public DateTime PartialEclispeBegin { get { return partialEclispeBegin; } } /// /// DateTime when Total eclipse begins (if applicable) /// public DateTime TotalEclipseBegin { get { return totalEclipseBegin; } } /// /// DateTime when eclipse is at Mid /// public DateTime MidEclipse { get { return midEclipse; } } /// /// DateTime when Total eclipse ends (if applicable) /// public DateTime TotalEclipseEnd { get { return totalEclipseEnd; } } /// /// DateTime when the partial elipse ends (if applicable) /// public DateTime PartialEclispeEnd { get { return partialEclispeEnd; } } /// /// DateTime when the penumbral elipse ends /// public DateTime PenumbralEclispeEnd { get { return penumbralEclipseEnd; } } /// /// Lunar eclipse default string /// /// Lunar eclipse base date string public override string ToString() { return date.ToString("dd-MMM-yyyy"); } internal void Convert_To_Local_Time(double offset) { FieldInfo[] fields = typeof(LunarEclipseDetails).GetFields(BindingFlags.NonPublic |BindingFlags.Instance); foreach (FieldInfo field in fields) { if (field.FieldType == typeof(DateTime)) { DateTime d = (DateTime)field.GetValue(this); if (d > new DateTime()) { d = d.AddHours(offset); field.SetValue(this, d); } } } date = penumbralEclipseBegin.Date; } } internal class MoonTimes { public DateTime set { get; internal set; } public DateTime rise { get; internal set; } public CelestialStatus status { get; internal set; } } internal class MoonPosition { public double Azimuth { get; internal set; } public double Altitude { get; internal set; } public Distance Distance { get; internal set; } public double ParallacticAngle { get; internal set; } public double ParallaxCorection { get; internal set; } } internal class CelCoords { public double ra { get; internal set; } public double dec { get; internal set; } public double dist { get; internal set; } } /// /// Solar eclipse type /// [Serializable] public enum SolarEclipseType { /// /// Partial Eclipse /// Partial, /// /// Annular Eclipse /// Annular, /// /// Total Eclipse...of the heart... /// Total } /// /// Lunar eclipse type /// [Serializable] public enum LunarEclipseType { /// /// Penumbral Eclipse /// Penumbral, /// /// Partial Eclipse /// Partial, /// /// Total Eclipse...of the heart... /// Total } }