public SunAndMoonData GetData(DateTime dt, double lat, double lng, double TimeZoneDifferenceFromUTC) { SunAndMoonData data = new SunAndMoonData(); FindSunAndTwilightDataForDate(data, dt, TimeZoneDifferenceFromUTC, lng, lat); FindMoonRiseAndSet(data, dt, TimeZoneDifferenceFromUTC, lng, lat); TimeSpan ts = data.SunSet - data.SunRise; data.SolarNoon = data.SunRise.AddMilliseconds(ts.TotalMilliseconds / 2); return(data); }
private string FindMoonRiseAndSet(SunAndMoonData data, DateTime dt, double tz, double glong, double glat) { // // Im using a separate function for moonrise/set to allow for different tabulations // of moonrise and sun events ie weekly for sun and daily for moon. The logic of // the function is identical to find_sun_and_twi_events_for_date() // //alert(mjd); //alert(tz); //alert(glong); //alert(glat); double mjd = GetJulianDate(dt, 0); double sglong, sglat, sinho, cglat, date, ym, yz, utrise, utset, j; double yp, nz, hour, z1, z2, xe, ye, iobj, rads = 0.0174532925; bool rise, sett, above; double[] quadout = new double[4]; //var sinho; string always_up = " ****"; string always_down = " ...."; string outstring = ""; sinho = Math.Sin(rads * 8 / 60); //moonrise taken as centre of moon at +8 arcmin sglat = Math.Sin(rads * glat); cglat = Math.Cos(rads * glat); date = mjd - tz / 24; rise = false; sett = false; above = false; hour = 1.0; utrise = 0; utset = 0; ym = sin_alt(1, date, hour - 1.0, glong, cglat, sglat) - sinho; if (ym > 0.0) { above = true; } while (hour < 25 && (sett == false || rise == false)) { yz = sin_alt(1, date, hour, glong, cglat, sglat) - sinho; yp = sin_alt(1, date, hour + 1.0, glong, cglat, sglat) - sinho; quadout = quad(ym, yz, yp); nz = quadout[0]; z1 = quadout[1]; z2 = quadout[2]; xe = quadout[3]; ye = quadout[4]; // case when one event is found in the interval if (nz == 1) { if (ym < 0.0) { utrise = hour + z1; rise = true; } else { utset = hour + z1; sett = true; } } // end of nz = 1 case // case where two events are found in this interval // (rare but whole reason we are not using simple iteration) if (nz == 2) { if (ye < 0.0) { utrise = hour + z2; utset = hour + z1; } else { utrise = hour + z1; utset = hour + z2; } } // set up the next search interval ym = yp; hour += 2.0; } // end of while loop data.MoonRise = ((rise == true || sett == true)) ? (rise == true) ? ConvertToDateTime(dt, utrise) : DateTime.MinValue : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); data.MoonSet = ((rise == true || sett == true)) ? (sett == true) ? ConvertToDateTime(dt, utset) : DateTime.MinValue.AddDays(1) : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); if (rise == true || sett == true) { if (rise == true) { outstring += " " + hrsmin(utrise); } else { outstring += " No Rise"; } if (sett == true) { outstring += " " + hrsmin(utset); } else { outstring += " No Set"; } } else { if (above == true) { outstring += "above"; } else { outstring += "below"; } } return(outstring); }
private string FindSunAndTwilightDataForDate(SunAndMoonData data, DateTime dt, double tz, double glong, double glat) { // // this is my attempt to encapsulate most of the program in a function // then this function can be generalised to find all the Sun events. // // double mjd = GetJulianDate(dt, 0); double sglong, sglat, cglat, date, ym, yz, utrise = 0, utset = 0; double yp, nz, hour, xe, ye, z1, z2, iobj, rads = 0.0174532925; bool rise, sett, above; double[] quadout = new double[4]; double[] sinho = new double[4]; string always_up = " ****"; string always_down = " ...."; string outstring = ""; // // Set up the array with the 4 values of sinho needed for the 4 // kinds of sun event // sinho[0] = Math.Sin(rads * -0.833); //sunset upper limb simple refraction sinho[1] = Math.Sin(rads * -6.0); //civil twi sinho[2] = Math.Sin(rads * -12.0); //nautical twi sinho[3] = Math.Sin(rads * -18.0); //astro twi sglat = Math.Sin(rads * glat); cglat = Math.Cos(rads * glat); date = mjd - tz / 24; // // main loop takes each value of sinho in turn and finds the rise/set // events associated with that altitude of the Sun // for (int j = 0; j < 4; j++) { rise = false; sett = false; above = false; hour = 1.0; ym = sin_alt(2, date, hour - 1.0, glong, cglat, sglat) - sinho[j]; if (ym > 0.0) { above = true; } // // the while loop finds the sin(alt) for sets of three consecutive // hours, and then tests for a single zero crossing in the interval // or for two zero crossings in an interval or for a grazing event // The flags rise and sett are set accordingly // nz = 0; z1 = 0; z2 = 0; xe = 0; ye = 0; while (hour < 25 && (sett == false || rise == false)) { yz = sin_alt(2, date, hour, glong, cglat, sglat) - sinho[j]; yp = sin_alt(2, date, hour + 1.0, glong, cglat, sglat) - sinho[j]; quadout = quad(ym, yz, yp); nz = quadout[0]; z1 = quadout[1]; z2 = quadout[2]; xe = quadout[3]; ye = quadout[4]; // case when one event is found in the interval if (nz == 1) { if (ym < 0.0) { utrise = hour + z1; rise = true; } else { utset = hour + z1; sett = true; } } // end of nz = 1 case // case where two events are found in this interval // (rare but whole reason we are not using simple iteration) if (nz == 2) { if (ye < 0.0) { utrise = hour + z2; utset = hour + z1; } else { utrise = hour + z1; utset = hour + z2; } } // end of nz = 2 case // set up the next search interval ym = yp; hour += 2.0; } // end of while loop // // now search has completed, we compile the string to pass back // to the main loop. The string depends on several combinations // of the above flag (always above or always below) and the rise // and sett flags // switch (j) { case 0: // SunRise/SunSet //data.XXX = z2.ToString(); data.SunRise = ((rise == true || sett == true)) ? (rise == true) ? ConvertToDateTime(dt, utrise) : DateTime.MinValue : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); data.SunSet = ((rise == true || sett == true)) ? (sett == true) ? ConvertToDateTime(dt, utset) : DateTime.MinValue.AddDays(1) : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); break; case 1: // Civial Twilight data.CivalTwilightStart = ((rise == true || sett == true)) ? (rise == true) ? ConvertToDateTime(dt, utrise) : DateTime.MinValue : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); data.CivalTwilightEnd = ((rise == true || sett == true)) ? (sett == true) ? ConvertToDateTime(dt, utset) : DateTime.MinValue.AddDays(1) : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); break; case 2: // nautical Twilight data.NauticalTwilightStart = ((rise == true || sett == true)) ? (rise == true) ? ConvertToDateTime(dt, utrise) : DateTime.MinValue : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); data.NauticalTwilightEnd = ((rise == true || sett == true)) ? (sett == true) ? ConvertToDateTime(dt, utset) : DateTime.MinValue.AddDays(1) : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); break; case 3: // Astronomical Twilight data.AstronomicalTwilightStart = ((rise == true || sett == true)) ? (rise == true) ? ConvertToDateTime(dt, utrise) : DateTime.MinValue : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); data.AstronomicalTwilightEnd = ((rise == true || sett == true)) ? (sett == true) ? ConvertToDateTime(dt, utset) : DateTime.MinValue.AddDays(1) : (above == true) ? DateTime.MaxValue : DateTime.MaxValue.AddDays(-1); break; } if (rise == true || sett == true) { if (rise == true) { outstring += " " + hrsmin(utrise); } else { outstring += " No Rise"; } if (sett == true) { outstring += " " + hrsmin(utset); } else { outstring += " No Set"; } } else { if (above == true) { outstring += "above"; } else { outstring += "below"; } } } // end of for loop - next condition return(outstring); }