using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace CoordinateSharp { //CURRENT ALTITUDE IS SET CONSTANT AT 100M. POSSIBLY NEED TO ADJUST TO ALLOW USER PASS. //Altitude adjustments appear to have minimal effect on eclipse timing. These were mainly used //to signify eclipses that had already started during rise and set times on the NASA calculator //SOME TIMES AND ALTS WERE RETURNED WITH COLOR AND STYLING. DETERMINE WHY AND ADJUST VALUE AS REQUIRED. SEARCH "WAS ITALIC". //ELLIPSOID ADJUSTMENT //6378140.0 Ellipsoid is used in the NASA Calculator //WGS84 Ellipsoid is 6378137.0. Adjustments to the ellipsoid appear to effect eclipse seconds in fractions. //This can be modified if need to allow users to pass custom number with the Coordinate SetDatum() functions. //CURRENT RANGE 1601-2600. internal class SolarEclipseCalc { public static List> CalculateSolarEclipse(DateTime d, double latRad, double longRad) { return Calculate(d, latRad, longRad, null); } public static List CalculateSolarEclipse(DateTime d, double latRad, double longRad, double[] events) { List> evs = Calculate(d, latRad, longRad, events); List deetsList = new List(); foreach(List ls in evs) { SolarEclipseDetails deets = new SolarEclipseDetails(ls); deetsList.Add(deets); } return deetsList; } public static List> CalculateSolarEclipse(DateTime d, Coordinate coord) { return Calculate(d, coord.Latitude.ToRadians(), coord.Longitude.ToRadians(), null); } private static List> Calculate(DateTime d, double latRad, double longRad, double[] ev) { //Declare storage arrays double[] obsvconst = new double[7]; double[] mid = new double[41];//Check index to see if array needs to be this size double[] c1 = new double[41]; double[] c2 = new double[41]; double[] c3 = new double[41]; double[] c4 = new double[41]; List> events = new List>(); double[] el; if (ev == null) { el = Eclipse.SolarData.SolarDateData(d);//Get 100 year solar data; } else { el = ev; } events = new List>(); ReadData(latRad, longRad, obsvconst); for (int i = 0; i < el.Length; i += 28) { obsvconst[6] = i; GetAll(el, obsvconst, mid,c1,c2,c3,c4); // Is there an event... if (mid[39] > 0) { List values = new List(); values.Add(GetDate(el, mid, obsvconst)); if (mid[39] == 1) { values.Add("P"); } else if (mid[39] == 2) { values.Add("A"); } else { values.Add("T"); } // Partial eclipse start if (c1[40] == 4) { values.Add("-"); values.Add(" "); } else { // Partial eclipse start time values.Add(GetTime(el, c1, obsvconst)); values.Add(GetAlt(c1)); } // Central eclipse time if ((mid[39] > 1) && (c2[40] != 4)) { values.Add(GetTime(el, c2, obsvconst)); } else { values.Add("-"); } //Mid Time values.Add(GetTime(el, mid, obsvconst)); // Maximum eclipse alt values.Add(GetAlt(mid)); // Maximum eclipse azi values.Add(GetAzi(mid)); // Central eclipse ends if ((mid[39] > 1) && (c3[40] != 4)) { values.Add(GetTime(el, c3, obsvconst)); } else { values.Add("-"); } // Partial eclipse ends if (c4[40] == 4) { values.Add("-"); values.Add(" "); } else { // Partial eclipse ends values.Add(GetTime(el, c4, obsvconst)); // ... sun alt values.Add(GetAlt(c4)); } // Eclipse magnitude values.Add(GetMagnitude(mid)); // Coverage values.Add(GetCoverage(mid)); // Central duration if (mid[39] > 1) { values.Add(GetDuration(mid,c2,c3)); } else { values.Add("-"); } events.Add(values); } } return events; } //Populates the obsvcont array private static void ReadData(double latRad, double longRad, double[] obsvconst) { // Get the latitude obsvconst[0] = latRad; //// Get the longitude obsvconst[1] = -1 * longRad; //PASS REVERSE RADIAN. // Get the altitude obsvconst[2] = 100; //CHANGE TO ALLOW USER TO PASS. // Get the time zone obsvconst[3] = 0; //ALWAYS GMT // Get the observer's geocentric position double tmp = Math.Atan(0.99664719 * Math.Tan(obsvconst[0])); obsvconst[4] = 0.99664719 * Math.Sin(tmp) + (obsvconst[2] / 6378140.0) * Math.Sin(obsvconst[0]); obsvconst[5] = Math.Cos(tmp) + (obsvconst[2] / 6378140.0 * Math.Cos(obsvconst[0])); } // Populate the c1, c2, mid, c3 and c4 arrays private static void GetAll(double[] elements, double[] obsvconst, double[] mid, double[] c1, double[] c2,double[] c3, double[] c4) { GetMid(elements, obsvconst, mid); MidObservational(obsvconst, mid); if (mid[37] > 0.0) { Getc1c4(elements, obsvconst, mid,c1,c2,c3,c4); if ((mid[36] < mid[29]) || (mid[36] < -mid[29])) { Getc2c3(elements, obsvconst, mid,c2,c3); if (mid[29] < 0.0) { mid[39] = 3; // Total eclipse } else { mid[39] = 2; // Annular eclipse } Observational(c1, obsvconst, mid); Observational(c2, obsvconst, mid); Observational(c3, obsvconst, mid); Observational(c4, obsvconst, mid); c2[36] = 999.9; c3[36] = 999.9; // Calculate how much of the eclipse is above the horizon double pattern = 0; if (c1[40] == 0) { pattern += 10000; } if (c2[40] == 0) { pattern += 1000; } if (mid[40] == 0) { pattern += 100; } if (c3[40] == 0) { pattern += 10; } if (c4[40] == 0) { pattern += 1; } // Now, time to make sure that all my Observational[39] and Observational[40] are OK if (pattern == 11110) { GetSunset(elements, c4, obsvconst); Observational(c4, obsvconst, mid); c4[40] = 3; } else if (pattern == 11100) { GetSunset(elements, c3, obsvconst); Observational(c3, obsvconst, mid); c3[40] = 3; CopyCircumstances(c3, c4); } else if (pattern == 11000) { c3[40] = 4; GetSunset(elements, mid, obsvconst); MidObservational(obsvconst, mid); mid[40] = 3; CopyCircumstances(mid, c4); } else if (pattern == 10000) { mid[39] = 1; GetSunset(elements, mid, obsvconst); MidObservational(obsvconst, mid); mid[40] = 3; CopyCircumstances(mid, c4); } else if (pattern == 1111) { GetSunrise(elements, c1, obsvconst); Observational(c1, obsvconst, mid); c1[40] = 2; } else if (pattern == 111) { GetSunrise(elements, c2, obsvconst); Observational(c2, obsvconst, mid); c2[40] = 2; CopyCircumstances(c2, c1); } else if (pattern == 11) { c2[40] = 4; GetSunrise(elements, mid, obsvconst); MidObservational(obsvconst, mid); mid[40] = 2; CopyCircumstances(mid, c1); } else if (pattern == 1) { mid[39] = 1; GetSunrise(elements, mid, obsvconst); MidObservational(obsvconst, mid); mid[40] = 2; CopyCircumstances(mid, c1); } else if (pattern == 0) { mid[39] = 0; } // There are other patterns, but those are the only ones we're covering! } else { mid[39] = 1; // Partial eclipse double pattern = 0; Observational(c1, obsvconst, mid); Observational(c4, obsvconst, mid); if (c1[40] == 0) { pattern += 100; } if (mid[40] == 0) { pattern += 10; } if (c4[40] == 0) { pattern += 1; } if (pattern == 110) { GetSunset(elements, c4, obsvconst); Observational(c4, obsvconst, mid); c4[40] = 3; } else if (pattern == 100) { GetSunset(elements, mid, obsvconst); MidObservational(obsvconst, mid); mid[40] = 3; CopyCircumstances(mid, c4); } else if (pattern == 11) { GetSunrise(elements, c1, obsvconst); Observational(c1, obsvconst, mid); c1[40] = 2; } else if (pattern == 1) { GetSunrise(elements, mid, obsvconst); MidObservational(obsvconst, mid); mid[40] = 2; CopyCircumstances(mid, c1); } else if (pattern == 0) { mid[39] = 0; } // There are other patterns, but those are the only ones we're covering! } } else { mid[39] = 0; // No eclipse } // Magnitude for total and annular eclipse is moon/sun ratio if ((mid[39] == 2) || (mid[39] == 3)) { mid[37] = mid[38]; } } // Calculate mid eclipse private static void GetMid(double[] elements, double[] obsvconst, double[] mid) { double iter, tmp; mid[0] = 0; mid[1] = 0.0; iter = 0; tmp = 1.0; TimeLocDependent(elements, mid, obsvconst); while (((tmp > 0.000001) || (tmp < -0.000001)) && (iter < 50)) { tmp = (mid[24] * mid[26] + mid[25] * mid[27]) / mid[30]; mid[1] = mid[1] - tmp; iter++; TimeLocDependent(elements, mid, obsvconst); } } // Populate the circumstances array with the time and location dependent circumstances private static double[] TimeLocDependent(double[] elements, double[] circumstances, double[] obsvconst) { double index, type; TimeDependent(elements, circumstances, obsvconst); index = obsvconst[6]; // Calculate h, sin h, cos h circumstances[16] = circumstances[7] - obsvconst[1] - (elements[(int)index + 5] / 13713.44); circumstances[17] = Math.Sin(circumstances[16]); circumstances[18] = Math.Cos(circumstances[16]); // Calculate xi circumstances[19] = obsvconst[5] * circumstances[17]; // Calculate eta circumstances[20] = obsvconst[4] * circumstances[6] - obsvconst[5] * circumstances[18] * circumstances[5]; // Calculate zeta circumstances[21] = obsvconst[4] * circumstances[5] + obsvconst[5] * circumstances[18] * circumstances[6]; // Calculate dxi circumstances[22] = circumstances[13] * obsvconst[5] * circumstances[18]; // Calculate deta circumstances[23] = circumstances[13] * circumstances[19] * circumstances[5] - circumstances[21] * circumstances[12]; // Calculate u circumstances[24] = circumstances[2] - circumstances[19]; // Calculate v circumstances[25] = circumstances[3] - circumstances[20]; // Calculate a circumstances[26] = circumstances[10] - circumstances[22]; // Calculate b circumstances[27] = circumstances[11] - circumstances[23]; // Calculate l1' type = circumstances[0]; if ((type == -2) || (type == 0) || (type == 2)) { circumstances[28] = circumstances[8] - circumstances[21] * elements[26 + (int)index]; } // Calculate l2' if ((type == -1) || (type == 0) || (type == 1)) { circumstances[29] = circumstances[9] - circumstances[21] * elements[27 + (int)index]; } // Calculate n^2 circumstances[30] = circumstances[26] * circumstances[26] + circumstances[27] * circumstances[27]; return circumstances; } // Populate the circumstances array with the time-only dependent circumstances (x, y, d, m, ...) private static double[] TimeDependent(double[] elements, double[] circumstances, double[] obsvconst) { double type, t, ans; t = circumstances[1]; int index = (int)obsvconst[6]; // Calculate x ans = elements[9 + index] * t + elements[8 + index]; ans = ans * t + elements[7 + index]; ans = ans * t + elements[6 + index]; circumstances[2] = ans; // Calculate dx ans = 3.0 * elements[9 + index] * t + 2.0 * elements[8 + index]; ans = ans * t + elements[7 + index]; circumstances[10] = ans; // Calculate y ans = elements[13 + index] * t + elements[12 + index]; ans = ans * t + elements[11 + index]; ans = ans * t + elements[10 + index]; circumstances[3] = ans; // Calculate dy ans = 3.0 * elements[13 + index] * t + 2.0 * elements[12 + index]; ans = ans * t + elements[11 + index]; circumstances[11] = ans; // Calculate d ans = elements[16 + index] * t + elements[15 + index]; ans = ans * t + elements[14 + index]; ans = ans * Math.PI / 180.0; circumstances[4] = ans; // sin d and cos d circumstances[5] = Math.Sin(ans); circumstances[6] = Math.Cos(ans); // Calculate dd ans = 2.0 * elements[16 + index] * t + elements[15 + index]; ans = ans * Math.PI / 180.0; circumstances[12] = ans; // Calculate m ans = elements[19 + index] * t + elements[18 + index]; ans = ans * t + elements[17 + index]; if (ans >= 360.0) { ans = ans - 360.0; } ans = ans * Math.PI / 180.0; circumstances[7] = ans; // Calculate dm ans = 2.0 * elements[19 + index] * t + elements[18 + index]; ans = ans * Math.PI / 180.0; circumstances[13] = ans; // Calculate l1 and dl1 type = circumstances[0]; if ((type == -2) || (type == 0) || (type == 2)) { ans = elements[22 + index] * t + elements[21 + index]; ans = ans * t + elements[20 + index]; circumstances[8] = ans; circumstances[14] = 2.0 * elements[22 + index] * t + elements[21 + index]; } // Calculate l2 and dl2 if ((type == -1) || (type == 0) || (type == 1)) { ans = elements[25 + index] * t + elements[24 + index]; ans = ans * t + elements[23 + index]; circumstances[9] = ans; circumstances[15] = 2.0 * elements[25 + index] * t + elements[24 + index]; } return circumstances; } // Get the observational circumstances for mid eclipse private static void MidObservational(double[] obsvconst, double[] mid) { Observational(mid, obsvconst, mid); // Calculate m, magnitude and moon/sun mid[36] = Math.Sqrt(mid[24] * mid[24] + mid[25] * mid[25]); mid[37] = (mid[28] - mid[36]) / (mid[28] + mid[29]); mid[38] = (mid[28] - mid[29]) / (mid[28] + mid[29]); } // Get the observational circumstances private static void Observational(double[] circumstances, double[] obsvconst, double[] mid) { double contacttype, coslat, sinlat; // We are looking at an "external" contact UNLESS this is a total eclipse AND we are looking at // c2 or c3, in which case it is an INTERNAL contact! Note that if we are looking at mid eclipse, // then we may not have determined the type of eclipse (mid[39]) just yet! if (circumstances[0] == 0) { contacttype = 1.0; } else { if ((mid[39] == 3) && ((circumstances[0] == -1) || (circumstances[0] == 1))) { contacttype = -1.0; } else { contacttype = 1.0; } } // Calculate p circumstances[31] = Math.Atan2(contacttype * circumstances[24], contacttype * circumstances[25]); // Calculate alt sinlat = Math.Sin(obsvconst[0]); coslat = Math.Cos(obsvconst[0]); circumstances[32] = Math.Asin(circumstances[5] * sinlat + circumstances[6] * coslat * circumstances[18]); // Calculate q circumstances[33] = Math.Asin(coslat * circumstances[17] / Math.Cos(circumstances[32])); if (circumstances[20] < 0.0) { circumstances[33] = Math.PI - circumstances[33]; } // Calculate v circumstances[34] = circumstances[31] - circumstances[33]; // Calculate azi circumstances[35] = Math.Atan2(-1.0 * circumstances[17] * circumstances[6], circumstances[5] * coslat - circumstances[18] * sinlat * circumstances[6]); // Calculate visibility if (circumstances[32] > -0.00524) { circumstances[40] = 0; } else { circumstances[40] = 1; } } // Get C1 and C4 data // Entry conditions - // 1. The mid array must be populated // 2. The magnitude at mid eclipse must be > 0.0 private static void Getc1c4(double[] elements, double[] obsvconst, double[] mid, double[] c1, double[] c2, double[] c3, double[] c4) { double tmp, n; n = Math.Sqrt(mid[30]); tmp = mid[26] * mid[25] - mid[24] * mid[27]; tmp = tmp / n / mid[28]; tmp = Math.Sqrt(1.0 - tmp * tmp) * mid[28] / n; c1[0] = -2; c4[0] = 2; c1[1] = mid[1] - tmp; c4[1] = mid[1] + tmp; c1c4iterate(elements, c1, obsvconst); c1c4iterate(elements, c4, obsvconst); } // Iterate on C1 or C4 private static double[] c1c4iterate(double[] elements, double[] circumstances, double[] obsvconst) { double sign, iter, tmp, n; TimeLocDependent(elements, circumstances, obsvconst); if (circumstances[0] < 0) { sign = -1.0; } else { sign = 1.0; } tmp = 1.0; iter = 0; while (((tmp > 0.000001) || (tmp < -0.000001)) && (iter < 50)) { n = Math.Sqrt(circumstances[30]); tmp = circumstances[26] * circumstances[25] - circumstances[24] * circumstances[27]; tmp = tmp / n / circumstances[28]; tmp = sign * Math.Sqrt(1.0 - tmp * tmp) * circumstances[28] / n; tmp = (circumstances[24] * circumstances[26] + circumstances[25] * circumstances[27]) / circumstances[30] - tmp; circumstances[1] = circumstances[1] - tmp; TimeLocDependent(elements, circumstances, obsvconst); iter++; } return circumstances; } // Get C2 and C3 data // Entry conditions - // 1. The mid array must be populated // 2. There must be either a total or annular eclipse at the location! private static void Getc2c3(double[] elements, double[] obsvconst, double[] mid, double[] c2, double[] c3) { double tmp, n; n = Math.Sqrt(mid[30]); tmp = mid[26] * mid[25] - mid[24] * mid[27]; tmp = tmp / n / mid[29]; tmp = Math.Sqrt(1.0 - tmp * tmp) * mid[29] / n; c2[0] = -1; c3[0] = 1; if (mid[29] < 0.0) { c2[1] = mid[1] + tmp; c3[1] = mid[1] - tmp; } else { c2[1] = mid[1] - tmp; c3[1] = mid[1] + tmp; } c2c3iterate(elements, c2, obsvconst, mid); c2c3iterate(elements, c3, obsvconst, mid); } // Iterate on C2 or C3 private static double[] c2c3iterate(double[] elements, double[] circumstances, double[] obsvconst, double[] mid) { double sign, iter, tmp, n; TimeLocDependent(elements, circumstances, obsvconst); if (circumstances[0] < 0) { sign = -1.0; } else { sign = 1.0; } if (mid[29] < 0.0) { sign = -sign; } tmp = 1.0; iter = 0; while (((tmp > 0.000001) || (tmp < -0.000001)) && (iter < 50)) { n = Math.Sqrt(circumstances[30]); tmp = circumstances[26] * circumstances[25] - circumstances[24] * circumstances[27]; tmp = tmp / n / circumstances[29]; tmp = sign * Math.Sqrt(1.0 - tmp * tmp) * circumstances[29] / n; tmp = (circumstances[24] * circumstances[26] + circumstances[25] * circumstances[27]) / circumstances[30] - tmp; circumstances[1] = circumstances[1] - tmp; TimeLocDependent(elements, circumstances, obsvconst); iter++; } return circumstances; } // Get the date of an event private static string GetDate(double[] elements, double[] circumstances, double[] obsvconst) { string[] month = new string[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; double t, jd, a, b, c, d, e, index; string ans = ""; index = obsvconst[6]; // Calculate the JD for noon (TDT) the day before the day that contains T0 jd = Math.Floor(elements[(int)index] - (elements[1 + (int)index] / 24.0)); // Calculate the local time (ie the offset in hours since midnight TDT on the day containing T0). t = circumstances[1] + elements[1 + (int)index] - obsvconst[3] - (elements[4 + (int)index] - 0.5) / 3600.0; if (t < 0.0) { jd--; } if (t >= 24.0) { jd++; } if (jd >= 2299160.0) { a = Math.Floor((jd - 1867216.25) / 36524.25); a = jd + 1 + a - Math.Floor(a / 4.0); } else { a = jd; } b = a + 1525.0; c = Math.Floor((b - 122.1) / 365.25); d = Math.Floor(365.25 * c); e = Math.Floor((b - d) / 30.6001); d = b - d - Math.Floor(30.6001 * e); if (e < 13.5) { e = e - 1; } else { e = e - 13; } double year; if (e > 2.5) { ans = c - 4716 + "-"; year = c - 4716; } else { ans = c - 4715 + "-"; year = c - 4715; } string m = month[(int)e - 1]; ans += m + "-"; if (d < 10) { ans = ans + "0"; } ans = ans + d; //Leap Year Integrity Check if(m =="Feb" && d ==29 && !DateTime.IsLeapYear((int)year)) { ans = year.ToString() + "-Mar-01"; } return ans; } // Calculate the time of sunset private static void GetSunset(double[] elements, double[] circumstances, double[] obsvconst) { GetSunriset(elements, circumstances, 1.0, obsvconst); } // Calculate the time of sunrise private static void GetSunrise(double[] elements, double[] circumstances, double[] obsvconst) { GetSunriset(elements, circumstances, -1.0, obsvconst); } // Calculate the time of sunrise or sunset private static void GetSunriset(double[] elements, double[] circumstances, double riset, double[] obsvconst) { double h0, diff, iter; diff = 1.0; iter = 0; while ((diff > 0.00001) || (diff < -0.00001)) { iter++; if (iter == 4) { return; } h0 = Math.Acos((Math.Sin(-0.00524) - Math.Sin(obsvconst[0]) * circumstances[5]) / Math.Cos(obsvconst[0]) / circumstances[6]); diff = (riset * h0 - circumstances[16]) / circumstances[13]; while (diff >= 12.0) { diff -= 24.0; } while (diff <= -12.0) { diff += 24.0; } circumstances[1] += diff; TimeLocDependent(elements, circumstances, obsvconst); } } // Copy a set of circumstances private static void CopyCircumstances(double[] circumstancesfrom, double[] circumstancesto) { for (int i = 1; i < 41; i++) { circumstancesto[i] = circumstancesfrom[i]; } } // Get the local time of an event private static string GetTime(double[] elements, double[] circumstances, double[] obsvconst) { string ans = ""; int index = (int)obsvconst[6]; double t = circumstances[1] + elements[1 + index] - obsvconst[3] - (elements[4 + index] - 0.5) / 3600.0; if (t < 0.0) { t = t + 24.0; } if (t >= 24.0) { t = t - 24.0; } if (t < 10.0) { ans = ans + "0"; } ans = ans + Math.Floor(t) + ":"; t = (t * 60.0) - 60.0 * Math.Floor(t); if (t < 10.0) { ans = ans + "0"; } ans = ans + Math.Floor(t); if (circumstances[40] <= 1) { // not sunrise or sunset ans = ans + ":"; t = (t * 60.0) - 60.0 * Math.Floor(t); if (t < 10.0) { ans = ans + "0"; } ans = ans + Math.Floor(t); } if (circumstances[40] == 1) { //WAS ITALIC return ans; } else if (circumstances[40] == 2) { //Rise (CHANGED FROM NASA CALC THE INDICATES (r) WITH STRING, INVESTIGATE REMOVAL) return ans; } else if (circumstances[40] == 3) { //Set (CHANGED FROM NASA CALC THE INDICATES (s) WITH STRING, INVESTIGATE REMOVAL) return ans; } else { return ans; } } // Get the altitude private static string GetAlt(double[] circumstances) { double t; string ans = ""; if (circumstances[40] == 2) { return "0(r)"; } if (circumstances[40] == 3) { return "0(s)"; } if ((circumstances[32] < 0.0) && (circumstances[32] >= -0.00524)) { // Crude correction for refraction (and for consistency's sake) t = 0.0; } else { t = circumstances[32] * 180.0 / Math.PI; } if (t < 0.0) { ans = "-"; t = -t; } else { ans = ""; } t = Math.Floor(t + 0.5); if (t < 10.0) { ans = ans + "0"; } ans = ans + t; if (circumstances[40] == 1) { //WAS ITALIC return ans; } else { return ans; } } // Get the azimuth private static string GetAzi(double[] circumstances) { string ans = ""; double t = circumstances[35] * 180.0 / Math.PI; if (t < 0.0) { t = t + 360.0; } if (t >= 360.0) { t = t - 360.0; } t = Math.Floor(t + 0.5); if (t < 100.0) { ans = ans + "0"; } if (t < 10.0) { ans = ans + "0"; } ans = ans + t; if (circumstances[40] == 1) { //WAS ITALIC return ans; } else { return ans; } } // Get the magnitude private static string GetMagnitude(double[] mid) { double a = Math.Floor(1000.0 * mid[37] + 0.5) / 1000.0; string ans = a.ToString(); if (mid[40] == 1) { return ans; } if (mid[40] == 2) { ans = a.ToString() + "(r)"; } if (mid[40] == 3) { ans = a.ToString() + "(s)"; } return ans; } // Get the coverage private static string GetCoverage(double[] mid) { double a=0, b, c; string ans = ""; if (mid[37] <= 0.0) { ans = "0.0"; } else if (mid[37] >= 1.0) { ans = "1.000"; } else { if (mid[39] == 2) { c = mid[38] * mid[38]; } else { c = Math.Acos((mid[28] * mid[28] + mid[29] * mid[29] - 2.0 * mid[36] * mid[36]) / (mid[28] * mid[28] - mid[29] * mid[29])); b = Math.Acos((mid[28] * mid[29] + mid[36] * mid[36]) / mid[36] / (mid[28] + mid[29])); a = Math.PI - b - c; c = ((mid[38] * mid[38] * a + b) - mid[38] * Math.Sin(c)) / Math.PI; } a = Math.Floor(1000.0 * c + 0.5) / 1000.0; ans = a.ToString(); } if (mid[40] == 1) { //WAS ITALIC return ans; } if (mid[40] == 2) { ans = a.ToString() + "(r)"; } if (mid[40] == 3) { ans = a + "(s)"; } return ans; } // Get the duration in mm:ss.s format // Adapted from code written by Stephen McCann - 27/04/2001 private static string GetDuration(double[] mid, double[] c2, double[] c3) { double tmp; string ans; if (c3[40] == 4) { tmp = mid[1] - c2[1]; } else if (c2[40] == 4) { tmp = c3[1] - mid[1]; } else { tmp = c3[1] - c2[1]; } if (tmp < 0.0) { tmp = tmp + 24.0; } else if (tmp >= 24.0) { tmp = tmp - 24.0; } tmp = (tmp * 60.0) - 60.0 * Math.Floor(tmp) + 0.05 / 60.0; ans = Math.Floor(tmp) + "m"; tmp = (tmp * 60.0) - 60.0 * Math.Floor(tmp); if (tmp < 10.0) { ans = ans + "0"; } ans += Math.Floor(tmp) + "s"; return ans; } } }