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
}
}