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); }
protected internal override void Tick() { Twilight2 T = new Twilight2(); Data = T.GetData(DateTime.Now, Settings.Default.Lat, Settings.Default.Lng, (DateTime.Now - DateTime.UtcNow).TotalHours); int Current = DateTime.Now.Hour * 60 + DateTime.Now.Minute; int Sunrise = Data.SunRise.Hour * 60 + Data.SunRise.Minute; int Sunset = Data.SunSet.Hour * 60 + Data.SunSet.Minute; // Messy, but this will lerp the background from night->day->night, with one-hour transitions centered on the sunrise/sunset times. if (Current < Sunrise - 30) { LerpAmt = 0; } else if (Math.Abs(Current - Sunrise) <= 30) { int Test = Current - (Sunrise - 30); LerpAmt = (float)Test / 60; } else if (Current < Sunset - 30) { LerpAmt = 1; } else if (Math.Abs(Current - Sunset) <= 30) { int Test = Current - (Sunset - 30); LerpAmt = 1 - ((float)Test / 60); } else { LerpAmt = 0; } Vector4 Colour1Day = new Vector4(0.171875f, 0.37109375f, 0.92578125f, 1.0f); Vector4 Colour1Night = new Vector4(0.0f, 0.0f, 0.0f, 1.0f); Vector4 Colour2Day = new Vector4(0.3828125f, 0.765625f, 0.95703125f, 1.0f); Vector4 Colour2Night = new Vector4(0.11328125f, 0.01953125f, 0.1015625f, 1.0f); Vector4 Colour3Day = new Vector4(0.23828125f, 0.81640625f, 0.94921875f, 1.0f); Vector4 Colour3Night = new Vector4(0.19921875f, 0.0859375f, 0.19140625f, 1.0f); // Lerp all positions and colours from day to night (or back) float Position1 = Lerp(56f, 76f, LerpAmt); float Position2 = Lerp(20f, 30f, LerpAmt); Vector4 Colour1 = Colour1Night + (Colour1Day - Colour1Night) * LerpAmt; Vector4 Colour2 = Colour2Night + (Colour2Day - Colour2Night) * LerpAmt; Vector4 Colour3 = Colour3Night + (Colour3Day - Colour3Night) * LerpAmt; // Now set vertex heights/colours Vertexes[6].Position.Y = Vertexes[7].Position.Y = Vertexes[8].Position.Y = Vertexes[9].Position.Y = Program.Configuration.Height * Position1 / 100; Vertexes[2].Position.Y = Vertexes[3].Position.Y = Vertexes[4].Position.Y = Vertexes[5].Position.Y = Program.Configuration.Height * Position2 / 100; Vertexes[0].Color = Vertexes[1].Color = Colour3; Vertexes[2].Color = Vertexes[3].Color = Vertexes[4].Color = Vertexes[5].Color = Colour2; Vertexes[6].Color = Vertexes[7].Color = Vertexes[8].Color = Vertexes[9].Color = Vertexes[10].Color = Vertexes[11].Color = Colour1; }
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 sglat, sinho, cglat, date, ym, yz, utrise, utset; double yp, nz, hour, z1, z2, xe, ye, rads = 0.0174532925; bool rise, sett, above; double[] quadout = new double[4]; //var sinho; 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 sglat, cglat, date, ym, yz, utrise = 0, utset = 0; double yp, nz, hour, xe, ye, z1, z2, rads = 0.0174532925; bool rise, sett, above; double[] quadout = new double[4]; double[] sinho = new double[4]; 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); }