public void NearestPhase() { // 1 second error double error = 1.0 / (24 * 60 * 60); { // New Moon takes place in February 1977 Date date = new Date(1977, 2, 15); double jd = date.ToJulianEphemerisDay(); double jdNewMoon = LunarEphem.NearestPhase(jd, MoonPhase.NewMoon); Assert.AreEqual(2443192.65118, jdNewMoon, error); } { // First last quarter of 2044 Date date = new Date(2044, 1, 1); double jd = date.ToJulianEphemerisDay(); double jdLastQuarter = LunarEphem.NearestPhase(jd, MoonPhase.LastQuarter); Assert.AreEqual(2467636.49186, jdLastQuarter, error); } }
/// <summary> /// Calculates instants of first sighting of lunar crescent on the evening sky, i.e. noumenia events. /// </summary> /// <remarks> /// The method is based on work of B.D.Yallop, /// see the work there: https://webspace.science.uu.nl/~gent0113/islam/downloads/naotn_69.pdf. /// As it noted in the work (see page 12): /// From observers reports it has been found that in general q = 0 /// is close to the lower limit for first visibility under /// perfect atmospheric conditions at sea level without requiring optical aid. /// Also lunar altitude should be checked: 2 degrees above horizon is an empyric value. /// So, the condition of the event used there is "q > 0 && alt > 0" /// </remarks> private ICollection <AstroEvent> Noumenia(AstroEventsContext context) { List <AstroEvent> events = new List <AstroEvent>(); double jd = 0; jd = context.From; while (jd < context.To) { if (context.CancelToken?.IsCancellationRequested == true) { return(new AstroEvent[0]); } else { double jdNewMoon = LunarEphem.NearestPhase(jd, MoonPhase.NewMoon); for (int day = 0; day <= 7; day++) { var ctx = new SkyContext(jdNewMoon + day, context.GeoLocation, preferFast: true); double jdMidnight = ctx.JulianDayMidnight; var rtsSun = ctx.Get(solarCalc.RiseTransitSet); var rtsMoon = ctx.Get(lunarCalc.RiseTransitSet); var sunSet = double.IsNaN(rtsSun.Set) ? 1 : rtsSun.Set; var moonSet = double.IsNaN(rtsMoon.Set) ? 1 : rtsMoon.Set; double jdBestTime = jdMidnight + sunSet + 4.0 / 9.0 * (moonSet - sunSet); ctx = new SkyContext(jdBestTime, context.GeoLocation, preferFast: true); double alt = ctx.Get(lunarCalc.Horizontal).Altitude; double q = ctx.Get(lunarCalc.CrescentQ); if (q > 0 && alt > 2) { events.Add(new AstroEvent(jdBestTime, Text.Get("MoonEvents.Noumenia.Text"), lunarCalc.Moon)); break; } } jd = jdNewMoon + LunarEphem.SINODIC_PERIOD; } } return(events); }
/// <summary> /// Calculates dates of lunar phases within specified range /// </summary> private ICollection <AstroEvent> Phases(AstroEventsContext context) { List <AstroEvent> events = new List <AstroEvent>(); double jd = 0; jd = context.From; while (jd < context.To) { jd = LunarEphem.NearestPhase(jd, MoonPhase.NewMoon); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.NewMoon"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } jd = context.From; while (jd < context.To) { jd = LunarEphem.NearestPhase(jd, MoonPhase.FirstQuarter); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.FirstQuarter"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } jd = context.From; while (jd < context.To) { jd = LunarEphem.NearestPhase(jd, MoonPhase.FullMoon); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.FullMoon"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } jd = context.From; while (jd < context.To) { jd = LunarEphem.NearestPhase(jd, MoonPhase.LastQuarter); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.LastQuarter"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } return(events); }
/// <summary> /// Calculates dates of lunar phases within specified range /// </summary> private ICollection <AstroEvent> Phases(AstroEventsContext context) { List <AstroEvent> events = new List <AstroEvent>(); double jd = 0; jd = context.From; while (jd < context.To) { if (context.CancelToken?.IsCancellationRequested == true) { return(new AstroEvent[0]); } else { jd = LunarEphem.NearestPhase(jd, MoonPhase.NewMoon); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.NewMoon"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } } jd = context.From; while (jd < context.To) { if (context.CancelToken?.IsCancellationRequested == true) { return(new AstroEvent[0]); } else { jd = LunarEphem.NearestPhase(jd, MoonPhase.FirstQuarter); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.FirstQuarter"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } } jd = context.From; while (jd < context.To) { if (context.CancelToken?.IsCancellationRequested == true) { return(new AstroEvent[0]); } else { jd = LunarEphem.NearestPhase(jd, MoonPhase.FullMoon); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.FullMoon"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } } jd = context.From; while (jd < context.To) { if (context.CancelToken?.IsCancellationRequested == true) { return(new AstroEvent[0]); } else { jd = LunarEphem.NearestPhase(jd, MoonPhase.LastQuarter); events.Add(new AstroEvent(jd, Text.Get("MoonEvents.Phases.LastQuarter"), lunarCalc.Moon)); jd += LunarEphem.SINODIC_PERIOD; } } return(events); }
/// <summary> /// Gets nearest phase date /// </summary> private Date NearestPhase(SkyContext c, MoonPhase p) { return(c.GetDate(LunarEphem.NearestPhase(c.JulianDay, p))); }