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 (Int32 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 (Int32 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 (Int32 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 {
///
/// Initializes a Perigee or Apogee object
///
/// Date of Event
/// Horizontal Parallax
/// Distance
public PerigeeApogee(DateTime d, Double p, Distance dist) {
this.Date = d;
this.HorizontalParallax = p;
this.Distance = dist;
}
///
/// Date of event.
///
public DateTime Date { get; }
///
/// Horizontal Parallax.
///
public Double HorizontalParallax { get; }
///
/// Moon's distance at event.
///
public Distance Distance { get; }
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 readonly 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 = (Int32)(d.Year / 100.0);
Double B = 0;
//Gregorian Start Date
if (d >= new DateTime(1582, 10, 15)) {
B = 2 - A + (Int32)(A / 4.0);
}
Double JD = (Int32)(365.25 * (y + 4716)) + (Int32)(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) => GetJulian(d) - J2000;
///
/// Returns JD from epoch 1970.
/// Meeus Ch 7.
///
/// DateTime
/// JDE
public static Double GetJulian_Epoch1970(DateTime d) => 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 += .5;
Double Z = Math.Floor(j);
Double F = j - Z;
Double A = Z;
if (Z >= 2299161) {
Double a = (Int32)((Z - 1867216.25) / 36524.25);
A = Z + 1 + a - (Int32)(a / 4.0);
}
Double B = A + 1524;
Double C = (Int32)((B - 122.1) / 365.25);
Double D = (Int32)(365.25 * C);
Double E = (Int32)((B - D) / 30.6001);
Double day = B - D - (Int32)(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((Int32)year, (Int32)month, (Int32)day, (Int32)hours, (Int32)minutes, (Int32)seconds));
return date;
}
///
/// Returns date from Julian based on epoch 2000
/// Meeus ch. 7
///
/// Julian
/// DateTime
public static DateTime? GetDate_FromJulian_Epoch2000(Double j) => 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) => GetDate_FromJulian(j + J1970);
}
///
/// Contains last and next perigee
///
[Serializable]
public class Perigee {
///
/// Initializes an Perigee object.
///
///
///
public Perigee(PerigeeApogee last, PerigeeApogee next) {
this.LastPerigee = last;
this.NextPerigee = next;
}
///
/// Last perigee
///
public PerigeeApogee LastPerigee { get; }
///
/// Next perigee
///
public PerigeeApogee NextPerigee { get; }
internal void ConvertTo_Local_Time(Double offset) {
this.LastPerigee.Convert_To_Local_Time(offset);
this.NextPerigee.Convert_To_Local_Time(offset);
}
}
///
/// Contains last and next apogee
///
[Serializable]
public class Apogee {
///
/// Initializes an Apogee object.
///
///
///
public Apogee(PerigeeApogee last, PerigeeApogee next) {
this.LastApogee = last;
this.NextApogee = next;
}
///
/// Last apogee
///
public PerigeeApogee LastApogee { get; }
///
/// Next apogee
///
public PerigeeApogee NextApogee { get; }
internal void ConvertTo_Local_Time(Double offset) {
this.LastApogee.Convert_To_Local_Time(offset);
this.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.
this.CivilDawn = new DateTime();
this.CivilDusk = new DateTime();
this.NauticalDawn = new DateTime();
this.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() {
this.LastEclipse = new SolarEclipseDetails();
this.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) {
this.LastEclipse.Convert_To_Local_Time(offset);
this.NextEclipse.Convert_To_Local_Time(offset);
}
}
///
/// Class containing lunar eclipse information
///
[Serializable]
public class LunarEclipse {
///
/// Initialize a LunarEclipse object
///
public LunarEclipse() {
this.LastEclipse = new LunarEclipseDetails();
this.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) {
this.LastEclipse.Convert_To_Local_Time(offset);
this.NextEclipse.Convert_To_Local_Time(offset);
}
}
///
/// Class containing specific solar eclipse information
///
[Serializable]
public class SolarEclipseDetails {
///
/// Initialize a SolarEclipseDetails object
///
/// Solar Eclipse String Values
public SolarEclipseDetails(List values) {
//Eclipse has value
this.HasEclipseData = true;
//Set Eclipse Date
this.Date = Convert.ToDateTime(values[0]);
switch (values[1]) {
case "P":
this.Type = SolarEclipseType.Partial;
break;
case "A":
this.Type = SolarEclipseType.Annular;
break;
case "T":
this.Type = SolarEclipseType.Total;
break;
default:
break;
}
//Eclipse start
if (TimeSpan.TryParse(values[2], out TimeSpan ts)) {
this.PartialEclispeBegin = this.Date.Add(ts);
}
//A or T start
if (TimeSpan.TryParse(values[4], out ts)) {
this.AorTEclipseBegin = this.Date.Add(ts);
}
//Maximum Eclipse
if (TimeSpan.TryParse(values[5], out ts)) {
this.MaximumEclipse = this.Date.Add(ts);
}
//A or T ends
if (TimeSpan.TryParse(values[8], out ts)) {
this.AorTEclipseEnd = this.Date.Add(ts);
}
//Eclipse end
if (TimeSpan.TryParse(values[9], out ts)) {
this.PartialEclispeEnd = this.Date.Add(ts);
}
//A or T Duration
if (values[13] != "-") {
String s = values[13].Replace("m", ":").Replace("s", "");
String[] ns = s.Split(':');
Int32 secs = 0;
_ = Int32.TryParse(ns[0], out Int32 mins);
if (ns.Count() > 0) {
_ = Int32.TryParse(ns[1], out secs);
}
TimeSpan time = new TimeSpan(0, mins, secs);
this.AorTDuration = time;
} else {
this.AorTDuration = new TimeSpan();
}
this.Adjust_Dates();//Adjust dates if required (needed when eclipse crosses into next day).
}
///
/// Initialize an empty SolarEclipseDetails object
///
public SolarEclipseDetails() => this.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[] { this.PartialEclispeBegin, this.AorTEclipseBegin, this.MaximumEclipse, this.AorTEclipseEnd, this.PartialEclispeEnd };
DateTime baseTime = this.PartialEclispeEnd;
Boolean multiDay = false; //used to detrmine if eclipse crossed into next Z day
for (Int32 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:
this.AorTEclipseEnd = this.AorTEclipseEnd.AddDays(-1);
break;
case 2:
this.MaximumEclipse = this.MaximumEclipse.AddDays(-1);
break;
case 1:
this.AorTEclipseBegin = this.AorTEclipseBegin.AddDays(-1);
break;
case 0:
this.PartialEclispeBegin = this.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 Boolean HasEclipseData { get; }
///
/// Date of solar eclipse
///
public DateTime Date { get; private set; }
///
/// Solar eclipse type
///
public SolarEclipseType Type { get; }
///
/// DateTime when the partial eclipse begins
///
public DateTime PartialEclispeBegin { get; private set; }
///
/// DateTime when an Annular or Total eclipse begins (if applicable)
///
public DateTime AorTEclipseBegin { get; private set; }
///
/// DateTime when eclipse is at Maximum
///
public DateTime MaximumEclipse { get; private set; }
///
/// DateTime when the Annular or Total eclipse ends (if applicable)
///
public DateTime AorTEclipseEnd { get; private set; }
///
/// DateTime when the partial elipse ends
///
public DateTime PartialEclispeEnd { get; }
///
/// Duration of Annular or Total eclipse (if applicable)
///
public TimeSpan AorTDuration { get; }
///
/// Solat eclipse default string
///
/// Solar eclipse base date string
public override String ToString() => this.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);
}
}
}
this.Date = this.PartialEclispeBegin.Date;
}
}
///
/// Class containing specific lunar eclipse information
///
[Serializable]
public class LunarEclipseDetails {
///
/// Initialize a LunarEclipseDetails object
///
/// Lunar Eclipse String Values
public LunarEclipseDetails(List values) {
//Eclipse has value
this.HasEclipseData = true;
//Set Eclipse Date
this.Date = Convert.ToDateTime(values[0]);
switch (values[1]) {
case "T":
this.Type = LunarEclipseType.Total;
break;
case "P":
this.Type = LunarEclipseType.Partial;
break;
case "N":
this.Type = LunarEclipseType.Penumbral;
break;
default:
break;
}
//Penumbral Eclipse start
if (TimeSpan.TryParse(values[4], out TimeSpan ts)) {
this.PenumbralEclipseBegin = this.Date.Add(ts);
}
//PartialEclipse start
if (TimeSpan.TryParse(values[6], out ts)) {
this.PartialEclispeBegin = this.Date.Add(ts);
}
//Total start
if (TimeSpan.TryParse(values[8], out ts)) {
this.TotalEclipseBegin = this.Date.Add(ts);
}
//Mid Eclipse
if (TimeSpan.TryParse(values[10], out ts)) {
this.MidEclipse = this.Date.Add(ts);
}
//Total ends
if (TimeSpan.TryParse(values[12], out ts)) {
this.TotalEclipseEnd = this.Date.Add(ts);
}
//Partial Eclipse end
if (TimeSpan.TryParse(values[14], out ts)) {
this.PartialEclispeEnd = this.Date.Add(ts);
}
//Penumbral Eclipse end
if (TimeSpan.TryParse(values[16], out ts)) {
this.PenumbralEclispeEnd = this.Date.Add(ts);
}
this.Adjust_Dates();
}
///
/// Initialize an empty LunarEclipseDetails object
///
public LunarEclipseDetails() => this.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[] { this.PenumbralEclipseBegin, this.PartialEclispeBegin, this.TotalEclipseBegin, this.MidEclipse, this.TotalEclipseEnd, this.PartialEclispeEnd, this.PenumbralEclispeEnd };
Boolean multiDay = false; //used to detrmine if eclipse crossed into next Z day
DateTime baseTime = this.PenumbralEclipseBegin;
for (Int32 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:
this.PartialEclispeBegin = this.PartialEclispeBegin.AddDays(1);
break;
case 2:
this.TotalEclipseBegin = this.TotalEclipseBegin.AddDays(1);
break;
case 3:
this.MidEclipse = this.MidEclipse.AddDays(1);
break;
case 4:
this.TotalEclipseEnd = this.TotalEclipseEnd.AddDays(1);
break;
case 5:
this.PartialEclispeEnd = this.PartialEclispeEnd.AddDays(1);
break;
case 6:
this.PenumbralEclispeEnd = this.PenumbralEclispeEnd.AddDays(1);
break;
default:
break;
}
}
}
}
///
/// Determine if the LunarEclipseDetails object has been populated
///
public Boolean HasEclipseData { get; }
///
/// Date of lunar eclipse
///
public DateTime Date { get; private set; }
///
/// Lunar eclipse type
///
public LunarEclipseType Type { get; }
///
/// DateTime when the penumbral eclipse begins
///
public DateTime PenumbralEclipseBegin { get; }
///
/// DateTime when the partial eclipse begins (if applicable)
///
public DateTime PartialEclispeBegin { get; private set; }
///
/// DateTime when Total eclipse begins (if applicable)
///
public DateTime TotalEclipseBegin { get; private set; }
///
/// DateTime when eclipse is at Mid
///
public DateTime MidEclipse { get; private set; }
///
/// DateTime when Total eclipse ends (if applicable)
///
public DateTime TotalEclipseEnd { get; private set; }
///
/// DateTime when the partial elipse ends (if applicable)
///
public DateTime PartialEclispeEnd { get; private set; }
///
/// DateTime when the penumbral elipse ends
///
public DateTime PenumbralEclispeEnd { get; private set; }
///
/// Lunar eclipse default string
///
/// Lunar eclipse base date string
public override String ToString() => this.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);
}
}
}
this.Date = this.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
}
}