/// <summary> /// Creates a Celestial object based on a location and specified date. /// </summary> /// <param name="lat">Latitude</param> /// <param name="longi">Longitude</param> /// <param name="geoDate">DateTime (UTC)</param> /// <param name="offset">UTC offset in hours</param> /// <param name="el">EagerLoad</param> /// <remarks> /// Celestial information is normally populated within the Coordinate classes CelestialInfo property. /// However, you may choose to work directly within the Celestial class. /// </remarks> /// <example> /// The following example demonstrates how to get the sunset time at Seattle on 19-Mar-2019 /// directly from a Celestial object in local time populated only with solar cycle information. /// <code> /// //Create EagerLoading object to load only solar cycle data for maximum efficiency. /// EagerLoad el = new EagerLoad(EagerLoadType.Celestial); /// el.Extensions = new EagerLoad_Extensions(EagerLoad_ExtensionsType.Solar_Cycle); /// /// //Create a Celestial object the calculates from Seattle's signed lat/long on /// //19-Mar-2019 (UTC) Date. Seattle is -7 UTC on this date. /// Celestial cel = new Celestial(47.60357, -122.32945, new DateTime(2019, 3, 19), -7, el); /// /// //Check if a sunset will occur on the specified day. /// if(cel.SunSet.HasValue) /// { /// Console.WriteLine(cel.SunSet.Value); //3/19/2019 7:20:56 PM /// } /// </code> /// </example> public Celestial(double lat, double longi, DateTime geoDate, double offset, EagerLoad el) { DateTime d = new DateTime(geoDate.Year, geoDate.Month, geoDate.Day, geoDate.Hour, geoDate.Minute, geoDate.Second, DateTimeKind.Utc); Create_Properties(); CalculateCelestialTime(lat, longi, d, el, offset); }
/// <summary> /// Creates a Celestial object based on a location and specified date. /// </summary> /// <param name="lat">Latitude</param> /// <param name="longi">Longitude</param> /// <param name="geoDate">DateTime (UTC)</param> /// <param name="offset">UTC offset in hours</param> /// <param name="el">EagerLoad</param> /// <remarks> /// Celestial information is normally populated within the Coordinate classes CelestialInfo property. /// However, you may choose to work directly within the Celestial class. /// </remarks> /// <example> /// The following example demonstrates how to get the sunset time at Seattle on 19-Mar-2019 /// directly from a Celestial object in local time populated only with solar cycle information. /// <code> /// //Create EagerLoading object to load only solar cycle data for maximum efficiency. /// EagerLoad el = new EagerLoad(EagerLoadType.Celestial); /// el.Extensions = new EagerLoad_Extensions(EagerLoad_ExtensionsType.Solar_Cycle); /// /// //Create a Celestial object the calculates from Seattle's signed lat/long on /// //19-Mar-2019 (UTC) Date. Seattle is -7 UTC on this date. /// Celestial cel = new Celestial(47.60357, -122.32945, new DateTime(2019, 3, 19), -7, el); /// /// //Check if a sunset will occur on the specified day. /// if(cel.SunSet.HasValue) /// { /// Console.WriteLine(cel.SunSet.Value); //3/19/2019 7:20:56 PM /// } /// </code> /// </example> public Celestial(double lat, double longi, DateTime geoDate, double offset, EagerLoad el) { DateTime d = new DateTime(geoDate.Year, geoDate.Month, geoDate.Day, geoDate.Hour, geoDate.Minute, geoDate.Second, DateTimeKind.Utc); astrologicalSigns = new AstrologicalSigns(); lunarEclipse = new LunarEclipse(); solarEclipse = new SolarEclipse(); CalculateCelestialTime(lat, longi, d, el, offset); }
/// <summary> /// Parses a string into a Coordinate with a specified Cartesian system type and eager loading settings. /// </summary> /// <param name="value">Coordinate string</param> /// <param name="cartesianType">Cartesian Type</param> /// <param name="eagerLoad">Eager loading options</param> /// <returns>Coordinate</returns> /// <example> /// The following example parses an ECEF formatted coordinate string. /// Because this is an ECEF Cartesian type coordinate, we will specify the Cartesian system type. /// Eager loading options have been specified for efficiency. /// <code> /// EagerLoad el = new EagerLoad(EagerLoadType.Cartesian); /// Coordinate c = Coordinate.Parse("5242.097 km, 2444.43 km, 2679.074 km", CartesianType.Cartesian, el); /// </code> /// </example> public static Coordinate Parse(string value, CartesianType cartesianType, EagerLoad eagerLoad) { Coordinate coordinate = null; if (TryParse(value, cartesianType, eagerLoad, out coordinate)) { return(coordinate); } throw new FormatException(string.Format("Input Coordinate \"{0}\" was not in a correct format.", value)); }
/// <summary> /// Attempts to parse a string into a Coordinate with a specified date and eager loading settings. /// </summary> /// <param name="value">Coordinate string</param> /// <param name="geoDate">GeoDate</param> /// <param name="eagerLoad">Eager loading options</param> /// <param name="coordinate">Coordinate</param> /// <returns>boolean</returns> /// <example> /// The following example parses a decimal degree formatted geodetic coordinate string, with a provided GeoDate. /// Eager loading is set to load celestial calculations only. /// <code> /// Coordinate c; /// EagerLoad el = new EagerLoad(EagerLoadType.Celestial); /// if(Coordinate.TryParse("N 32.891º W 64.872º", new DateTime(2018,7,7), el, out c)) /// { /// Console.WriteLine(c); //N 32º 53' 28.212" W 64º 52' 20.914" /// } /// </code> /// </example> public static bool TryParse(string value, DateTime geoDate, EagerLoad eagerLoad, out Coordinate coordinate) { coordinate = null; if (FormatFinder.TryParse(value, CartesianType.Cartesian, out coordinate)) { Parse_Format_Type pft = coordinate.Parse_Format; coordinate = new Coordinate(coordinate.Latitude.ToDouble(), coordinate.Longitude.ToDouble(), geoDate, eagerLoad); //Reset with specified eager load options. coordinate.parse_Format = pft; return(true); } return(false); }
/// <summary> /// Creates a Coordinate object with default values and a custom datum. /// </summary> /// <remarks> /// Default Coordinate objects will initialize with a latitude and longitude of 0 degrees, /// a GeoDate of 1900-1-1 00:00:00. All properties will be set to EagerLoaded. /// </remarks> internal Coordinate(double equatorialRadius, double inverseFlattening, bool t) { FormatOptions = new CoordinateFormatOptions(); geoDate = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc); latitude = new CoordinatePart(CoordinateType.Lat); longitude = new CoordinatePart(CoordinateType.Long); latitude.parent = this; longitude.parent = this; celestialInfo = new Celestial(); utm = new UniversalTransverseMercator(latitude.ToDouble(), longitude.ToDouble(), this, equatorialRadius, inverseFlattening); mgrs = new MilitaryGridReferenceSystem(utm); cartesian = new Cartesian(this); ecef = new ECEF(this); EagerLoadSettings = new EagerLoad(); Set_Datum(equatorialRadius, inverseFlattening); }
/// <summary> /// Attempts to parse a string into a Coordinate with a specified Cartesian system type and eager loading settings. /// </summary> /// <param name="value">Coordinate string</param> /// <param name="cartesianType">Cartesian Type</param> /// <param name="eagerLoad">Eager loading options</param> /// <param name="coordinate">Coordinate</param> /// <returns>boolean</returns> /// <example> /// The following example parses an ECEF formatted coordinate string. /// Because this is an ECEF Cartesian type coordinate, we will specify the Cartesian system type. /// Eager loading options have been specified for efficiency. /// <code> /// Coordinate c; /// EagerLoad el = new EagerLoad(EagerLoadType.Cartesian); /// if(Coordinate.TryParse("5242.097 km, 2444.43 km, 2679.074 km", CartesianType.Cartesian, el, out c)) /// { /// Console.WriteLine(c); //N 24º 59' 59.987" E 25º 0' 0.001" /// } /// </code> /// </example> public static bool TryParse(string value, CartesianType cartesianType, EagerLoad eagerLoad, out Coordinate coordinate) { coordinate = null; if (FormatFinder.TryParse(value, cartesianType, out coordinate)) { Parse_Format_Type pft = coordinate.Parse_Format; if (cartesianType == CartesianType.ECEF) { Distance h = coordinate.ecef.GeoDetic_Height; coordinate = new Coordinate(coordinate.Latitude.ToDouble(), coordinate.Longitude.ToDouble(), eagerLoad); //Reset with eager load options specified. coordinate.ecef.Set_GeoDetic_Height(coordinate, h); } else { coordinate = new Coordinate(coordinate.Latitude.ToDouble(), coordinate.Longitude.ToDouble(), eagerLoad); //Reset with eager load options specified. } coordinate.parse_Format = pft; return(true); } return(false); }
/// <summary> /// Converts UTM coordinate to Lat/Long /// </summary> /// <param name="utm">utm</param> /// <param name="eagerLoad">EagerLoad</param> /// <returns>Coordinate</returns> /// <example> /// The following example creates (converts to) a geodetic Coordinate object based on a UTM object. /// Performance is maximized by turning off EagerLoading. /// <code> /// EagerLoad el = new EagerLoad(false); /// UniversalTransverseMercator utm = new UniversalTransverseMercator("T", 32, 233434, 234234); /// Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm, el); /// Console.WriteLine(c); //N 2º 7' 2.332" E 6º 36' 12.653" /// </code> /// </example> public static Coordinate ConvertUTMtoLatLong(UniversalTransverseMercator utm, EagerLoad eagerLoad) { bool southhemi = false; Regex upsCheck = new Regex("[AaBbYyZz]"); if (upsCheck.IsMatch(utm.latZone)) { return(UPS.UPS_To_Geodetic(utm, eagerLoad)); } Regex regex = new Regex("[CcDdEeFfGgHhJjKkLlMm]"); if (regex.IsMatch(utm.latZone)) { southhemi = true; } double cmeridian; double x = utm.Easting - 500000.0; double UTMScaleFactor = 0.9996; x /= UTMScaleFactor; /* If in southern hemisphere, adjust y accordingly. */ double y = utm.Northing; if (southhemi) { y -= 10000000.0; } y /= UTMScaleFactor; cmeridian = UTMCentralMeridian(utm.LongZone); Coordinate c = UTMtoLatLong(x, y, cmeridian, utm.equatorial_radius, utm.inverse_flattening, eagerLoad); return(c); }
private static Coordinate UTMtoLatLong(double x, double y, double zone, double equatorialRadius, double flattening, EagerLoad el) { //x easting //y northing //http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html double phif, Nf, Nfpow, nuf2, ep2, tf, tf2, tf4, cf; double x1frac, x2frac, x3frac, x4frac, x5frac, x6frac, x7frac, x8frac; double x2poly, x3poly, x4poly, x5poly, x6poly, x7poly, x8poly; double sm_a = equatorialRadius; double sm_b = equatorialRadius * (1 - (1.0 / flattening)); //Polar Radius /* Get the value of phif, the footpoint latitude. */ phif = FootpointLatitude(y, equatorialRadius, flattening); /* Precalculate ep2 */ ep2 = (Math.Pow(sm_a, 2.0) - Math.Pow(sm_b, 2.0)) / Math.Pow(sm_b, 2.0); /* Precalculate cos (phif) */ cf = Math.Cos(phif); /* Precalculate nuf2 */ nuf2 = ep2 * Math.Pow(cf, 2.0); /* Precalculate Nf and initialize Nfpow */ Nf = Math.Pow(sm_a, 2.0) / (sm_b * Math.Sqrt(1 + nuf2)); Nfpow = Nf; /* Precalculate tf */ tf = Math.Tan(phif); tf2 = tf * tf; tf4 = tf2 * tf2; /* Precalculate fractional coefficients for x**n in the equations * below to simplify the expressions for latitude and longitude. */ x1frac = 1.0 / (Nfpow * cf); Nfpow *= Nf; /* now equals Nf**2) */ x2frac = tf / (2.0 * Nfpow); Nfpow *= Nf; /* now equals Nf**3) */ x3frac = 1.0 / (6.0 * Nfpow * cf); Nfpow *= Nf; /* now equals Nf**4) */ x4frac = tf / (24.0 * Nfpow); Nfpow *= Nf; /* now equals Nf**5) */ x5frac = 1.0 / (120.0 * Nfpow * cf); Nfpow *= Nf; /* now equals Nf**6) */ x6frac = tf / (720.0 * Nfpow); Nfpow *= Nf; /* now equals Nf**7) */ x7frac = 1.0 / (5040.0 * Nfpow * cf); Nfpow *= Nf; /* now equals Nf**8) */ x8frac = tf / (40320.0 * Nfpow); /* Precalculate polynomial coefficients for x**n. * -- x**1 does not have a polynomial coefficient. */ x2poly = -1.0 - nuf2; x3poly = -1.0 - 2 * tf2 - nuf2; x4poly = 5.0 + 3.0 * tf2 + 6.0 * nuf2 - 6.0 * tf2 * nuf2 - 3.0 * (nuf2 * nuf2) - 9.0 * tf2 * (nuf2 * nuf2); x5poly = 5.0 + 28.0 * tf2 + 24.0 * tf4 + 6.0 * nuf2 + 8.0 * tf2 * nuf2; x6poly = -61.0 - 90.0 * tf2 - 45.0 * tf4 - 107.0 * nuf2 + 162.0 * tf2 * nuf2; x7poly = -61.0 - 662.0 * tf2 - 1320.0 * tf4 - 720.0 * (tf4 * tf2); x8poly = 1385.0 + 3633.0 * tf2 + 4095.0 * tf4 + 1575 * (tf4 * tf2); /* Calculate latitude */ double nLat = phif + x2frac * x2poly * (x * x) + x4frac * x4poly * Math.Pow(x, 4.0) + x6frac * x6poly * Math.Pow(x, 6.0) + x8frac * x8poly * Math.Pow(x, 8.0); /* Calculate longitude */ double nLong = zone + x1frac * x + x3frac * x3poly * Math.Pow(x, 3.0) + x5frac * x5poly * Math.Pow(x, 5.0) + x7frac * x7poly * Math.Pow(x, 7.0); double dLat = RadToDeg(nLat); double dLong = RadToDeg(nLong); if (dLat > 90) { dLat = 90; } if (dLat < -90) { dLat = -90; } if (dLong > 180) { dLong = 180; } if (dLong < -180) { dLong = -180; } Coordinate c = new Coordinate(dLat, dLong, el, equatorialRadius, flattening); return(c); }
/// <summary> /// Returns a populated MGRS_GridBox details based on the MGRS coordinate. /// This can be useful for grid zone junction adjacent partial boxes or when needing /// Lat/Long coordinates at the corners of the MGRS square. /// </summary> /// <param name="el">EagerLoad</param> /// <returns>MGRS_GridBox</returns> /// <example> /// The following example will create an MGRS_GridBox that will allow us to determine /// The MGRS Point at the bottom left of the current 100km grid square and convert it to Lat/Long. /// <code> /// MilitaryGridReferenceSystem mgrs = new MilitaryGridReferenceSystem("N", 21, "SA", 66037, 61982); /// EagerLoad el = new EagerLoad(EagerLoadType.UTM_MGRS); //Only eager load UTM MGRS data for efficiency /// var box = mgrs.Get_Box_Boundaries(); /// /// //Check if created MGRS coordinate is valid /// if(!box.IsBoxValid){return;} //MGRS Coordinate GZD and Identifier are not standard. Box cannot be determined. /// /// Console.WriteLine("BL: " + gb.Bottom_Left_MGRS_Point); //21N SA 66022 00000 /// Console.WriteLine("BL: " + gb.Bottom_Left_Coordinate_Point); //N 0º 0' 0" W 59º 59' 59.982" /// </code> /// </example> public MGRS_GridBox Get_Box_Boundaries(EagerLoad el) { return(new MGRS_GridBox(this, el)); }
private static Coordinate MGRS_Polar_ToLatLong(MilitaryGridReferenceSystem mgrs, EagerLoad el) { //WORKING bool isNorth = true; if (mgrs.latZone.ToUpper() == "A" || mgrs.latZone.ToUpper() == "B") { isNorth = false; } string latz = mgrs.LatZone; string digraph = mgrs.Digraph; char eltr = digraph[0]; char nltr = digraph[1]; string digraphLettersE; if (!isNorth) { digraphLettersE = "KLPQRSTUXYZABCFGH"; } else { digraphLettersE = "RSTUXYZABCFGHJ"; } string digraphLettersN; if (!isNorth) { digraphLettersN = "VWXYBCDEFGHJKLMNPQRSTUVWXYZ"; } else { digraphLettersN = "ABCDEFGHJKLMNP"; } string digraphLettersAll = ""; for (int lt = 1; lt < 31; lt++) { digraphLettersAll += digraphLettersN; } var eidx = digraphLettersE.IndexOf(eltr); //Offsets are set due to less Easting Identifiers. //North has 4 less than S double offset = 9; if (isNorth) { offset = 13; } if (mgrs.latZone == "B" && eidx < offset && mgrs.easting != 0) { eidx += 18; } double subbase = eidx + offset; var ebase = 100000 * subbase; var latBand = digraphLettersE.IndexOf(latz); var latBandLow = 8 * latBand - 96; var latBandHigh = 8 * latBand - 88; if (!isNorth) { latBandLow = -90; latBandHigh = -80; } else { latBandLow = 84; latBandHigh = 90; } var lowLetter = Math.Floor(100 + 1.11 * latBandLow); var highLetter = Math.Round(100 + 1.11 * latBandHigh); string latBandLetters = null; int l = Convert.ToInt32(lowLetter); int h = Convert.ToInt32(highLetter + 7); if (mgrs.LongZone / 2.0 == Math.Floor(mgrs.LongZone / 2.0)) { latBandLetters = digraphLettersAll.Substring(l + 5, h + 5).ToString(); } else { latBandLetters = digraphLettersAll.Substring(l, h).ToString(); } //North offset + 4 due to lower band count. double nOffset = 13; if (!isNorth) { nOffset = 10; } else { latBandLetters = digraphLettersN; } int index = latBandLetters.IndexOf(nltr); if (index == -1 && nltr == 'A') { index -= 1; } //ALPHA PATCH //int subset = 0; //if ((latz == "Y" || latz == "Z") && (nOffset+index)>25 && (ebase> 2100000 || ebase<2000000) && ebase!= 2000000) { subset = -14; } var nbase = 100000 * (index + nOffset); var x = ebase + mgrs.Easting; var y = nbase + mgrs.Northing; if (mgrs.systemType != MGRS_Type.MGRS_Polar) { if (y > 10000000) { y = y - 10000000; } if (nbase >= 10000000) { y = nbase + mgrs.northing - 10000000; } } // Debug.WriteLine("MGRS {0} {1}", x, y); UniversalTransverseMercator utm = new UniversalTransverseMercator(mgrs.LatZone, mgrs.LongZone, x, y, true); utm.equatorial_radius = mgrs.equatorialRadius; utm.inverse_flattening = mgrs.inverseFlattening; Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm, el); c.Set_Datum(mgrs.equatorialRadius, mgrs.inverseFlattening); return(c); }
public static void CalculateSunTime(double lat, double longi, DateTime date, Celestial c, EagerLoad el, double offset = 0) { if (date.Year == 0001) { return; } //Return if date value hasn't been established. if (el.Extensions.Solar_Cycle) { DateTime actualDate = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc); ////Sun Time Calculations //Get Julian double lw = rad * -longi; double phi = rad * lat; //Rise Set DateTime?[] evDate = Get_Event_Time(lw, phi, -.8333, actualDate); c.sunRise = evDate[0]; c.sunSet = evDate[1]; c.sunCondition = CelestialStatus.RiseAndSet; //Azimuth and Altitude CalculateSunAngle(date, longi, lat, c); // neither sunrise nor sunset if ((!c.SunRise.HasValue) && (!c.SunSet.HasValue)) { if (c.SunAltitude < 0) { c.sunCondition = CelestialStatus.DownAllDay; } else { c.sunCondition = CelestialStatus.UpAllDay; } } // sunrise or sunset else { if (!c.SunRise.HasValue) { // No sunrise this date c.sunCondition = CelestialStatus.NoRise; } else if (!c.SunSet.HasValue) { // No sunset this date c.sunCondition = CelestialStatus.NoSet; } } //Additional Times c.additionalSolarTimes = new AdditionalSolarTimes(); //Dusk and Dawn //Civil evDate = Get_Event_Time(lw, phi, -6, actualDate); c.AdditionalSolarTimes.civilDawn = evDate[0]; c.AdditionalSolarTimes.civilDusk = evDate[1]; //Nautical evDate = Get_Event_Time(lw, phi, -12, actualDate); c.AdditionalSolarTimes.nauticalDawn = evDate[0]; c.AdditionalSolarTimes.nauticalDusk = evDate[1]; //Astronomical evDate = Get_Event_Time(lw, phi, -18, actualDate); c.AdditionalSolarTimes.astronomicalDawn = evDate[0]; c.AdditionalSolarTimes.astronomicalDusk = evDate[1]; //BottomDisc evDate = Get_Event_Time(lw, phi, -.2998, actualDate); c.AdditionalSolarTimes.sunriseBottomDisc = evDate[0]; c.AdditionalSolarTimes.sunsetBottomDisc = evDate[1]; } if (el.Extensions.Solar_Eclipse) { CalculateSolarEclipse(date, lat, longi, c); } }
/*PARSER METHODS*/ /// <summary> /// Attempts to parse a string into a Coordinate. /// </summary> /// <param name="value">Coordinate string</param> /// <param name="coordinate">Coordinate</param> /// <returns>boolean</returns> /// <example> /// The following example parses a decimal degree formatted geodetic coordinate string. /// <code> /// Coordinate c; /// if(Coordinate.TryParse("N 32.891º W 64.872º", e, out c)) /// { /// Console.WriteLine(c); //N 32º 53' 28.212" W 64º 52' 20.914" /// } /// </code> /// </example> public static bool TryParse(string value, out Coordinate coordinate) { var eagerLoad = new EagerLoad(); return(TryParse(value, eagerLoad, out coordinate)); }
/// <summary> /// Calculates all celestial data. Coordinates will notify as changes occur /// </summary> /// <param name="lat">Decimal format latitude</param> /// <param name="longi">Decimal format longitude</param> /// <param name="date">Geographic DateTime</param> /// <param name="el">EagerLoading Info for Auto-Calculations</param> internal void CalculateCelestialTime(double lat, double longi, DateTime date, EagerLoad el) { CalculateCelestialTime(lat, longi, date, el, 0); }
/// <summary> /// Creates a populated Coordinate object with specified eager load options, assigned GeoDate and Earth Shape. Should only be called when Coordinate /// is create from another system. /// </summary> /// <param name="lat">signed latitude</param> /// <param name="longi">signed longitude</param> /// <param name="eagerLoad">Eager loading options</param> /// <param name="equatorialRadius">Semi Major Axis or Equatorial Radius of the Earth</param> /// <param name="inverseFlattening">Inverse of Flattening of the Earth</param> internal Coordinate(double lat, double longi, EagerLoad eagerLoad, double equatorialRadius, double inverseFlattening) { Coordinate_Builder(lat, longi, new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc), eagerLoad); equatorial_radius = equatorialRadius; inverse_flattening = inverseFlattening; }
/// <summary> /// Coordinate build logic goes here. /// </summary> /// <param name="lat">Signed latitude</param> /// <param name="longi">Signed longitude</param> /// <param name="date">Date at location</param> /// <param name="eagerLoad">Eagerloading settings</param> private void Coordinate_Builder(double lat, double longi, DateTime date, EagerLoad eagerLoad) { FormatOptions = new CoordinateFormatOptions(); //Use default constructor if signed degree is 0 for performance. if (lat == 0) { latitude = new CoordinatePart(CoordinateType.Lat); } else { latitude = new CoordinatePart(lat, CoordinateType.Lat); } if (longi == 0) { longitude = new CoordinatePart(CoordinateType.Long); } else { longitude = new CoordinatePart(longi, CoordinateType.Long); } //Set CoordinatePart parents latitude.parent = this; longitude.parent = this; //Set UTC date at location geoDate = date; //LOAD NEW COORDINATE SYSTEMS HERE //Load Celestial if (eagerLoad.Celestial) { celestialInfo = new Celestial(lat, longi, date); } //Load UTM MGRS if (eagerLoad.UTM_MGRS) { utm = new UniversalTransverseMercator(lat, longi, this); mgrs = new MilitaryGridReferenceSystem(utm); } //Load CARTESIAN if (eagerLoad.Cartesian) { cartesian = new Cartesian(this); } //Load ECEF if (eagerLoad.ECEF) { ecef = new ECEF(this); } //SET EagerLoading Setting EagerLoadSettings = eagerLoad; //Set Ellipsoid equatorial_radius = 6378137.0; inverse_flattening = 298.257223563; }
/// <summary> /// Creates a populated Coordinate object with specified eager load options and an assigned GeoDate. /// </summary> /// <param name="lat">signed latitude</param> /// <param name="longi">signed longitude</param> /// <param name="date">DateTime you wish to use for celestial calculation</param> /// <param name="eagerLoad">Eager loading options</param> /// <example> /// The following example demonstrates how to create a defined Coordinate object with defined /// eager loading options and a GeoDate. /// <code> /// //Create a new EagerLoading object set to only /// //eager load celestial calculations. /// EagerLoading el = new EagerLoading(EagerLoadType.Celestial); /// DateTime geoDate = new DateTime(2018, 2, 5, 10, 38, 22); /// /// Coordinate c = new Coordinate(25, 25, geoDate, el); /// </code> /// </example> public Coordinate(double lat, double longi, DateTime date, EagerLoad eagerLoad) { Coordinate_Builder(lat, longi, date, eagerLoad); }
/// <summary> /// Creates a populated Coordinate object with specified eager loading options. /// </summary> /// <remarks> /// Geodate will default to 1900-01-01. /// </remarks> /// <param name="lat">signed latitude</param> /// <param name="longi">signed longitude</param> /// <param name="eagerLoad">Eager loading options</param> /// <example> /// The following example demonstrates how to create a defined Coordinate object with defined /// eager loading options. /// <code> /// //Create a new EagerLoading object set to only /// //eager load celestial calculations. /// EagerLoading el = new EagerLoading(EagerLoadType.Celestial); /// /// Coordinate c = new Coordinate(25, 25, el); /// </code> /// </example> public Coordinate(double lat, double longi, EagerLoad eagerLoad) { Coordinate_Builder(lat, longi, new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc), eagerLoad); }
/// <summary> /// Creates an empty Coordinates object with specified eager loading options. /// </summary> /// <remarks> /// Coordinate will initialize with a latitude and longitude of 0 degrees and /// a GeoDate of 1900-1-1. /// </remarks> /// <param name="eagerLoad">Eager loading options</param> /// <example> /// The following example demonstrates how to create a default Coordinate object with defined /// eager loading options /// <code> /// //Create a new EagerLoading object set to only /// //eager load celestial calculations. /// EagerLoading el = new EagerLoading(EagerLoadType.Celestial); /// /// Coordinate c = new Coordinate(el); /// </code> /// </example> public Coordinate(EagerLoad eagerLoad) { Coordinate_Builder(0, 0, new DateTime(1900, 1, 1, 0, 0, 0, DateTimeKind.Utc), eagerLoad); }
/// <summary> /// Calculate celestial data based on latitude, longitude and UTC date with hours offset at the location. /// </summary> /// <param name="lat">Decimal format latitude</param> /// <param name="longi">Decimal format longitude</param> /// <param name="date">Geographic DateTime</param> /// <param name="el">EagerLoad</param> /// <param name="offset">Offset hours</param> /// <returns>Celestial</returns> /// <example> /// The following example demonstrates how to create a fully populated Celestial object in local time /// using static functions using solar cycle only eager loading. /// <code> /// // Set EagerLoading parameters to only load solar cycle data for maximum efficiency /// EagerLoad el = new EagerLoad(EagerLoadType.Celestial); /// el.Extensions = new EagerLoad_Extensions(EagerLoad_ExtensionsType.Solar_Cycle); /// /// //Get Celestial data at N 39, W 72 on 19-Mar-2019 10:10:12 Local using Pacific Standard Time offset in hours (-7) /// Celestial cel = Celestial.CalculateCelestialTimes(39, -72, new DateTime(2019, 3, 19, 10, 10, 12), el, -7); /// Console.WriteLine(cel.SunRise); //03:54:50 AM /// /// </code> /// </example> public static Celestial CalculateCelestialTimes(double lat, double longi, DateTime date, EagerLoad el, double offset) { Celestial c = new Celestial(lat, longi, date, offset, el); return(c); }
//Add main to Coordinate and tunnel to Format class. Add private methods to format. //WHEN PARSING NO EXCPETIONS FOR OUT OF RANGE ARGS WILL BE THROWN public static bool TryParse(string coordString, out CoordinatePart cp) { //Turn of eagerload for efficiency EagerLoad eg = new EagerLoad(); int type = 0; //0 = unspecifed, 1 = lat, 2 = long; eg.Cartesian = false; eg.Celestial = false; eg.UTM_MGRS = false; cp = null; Coordinate c = new Coordinate(eg); string s = coordString; s = s.Trim(); //Trim all spaces before and after string double[] d; if (s[0] == ',') { type = 2; s = s.Replace(",", ""); s = s.Trim(); } if (s[0] == '*') { type = 1; s = s.Replace("*", ""); s = s.Trim(); } if (TrySignedDegree(s, type, out d)) { try { switch (type) { case 0: //Attempt Lat first (default for signed) try { cp = new CoordinatePart(d[0], CoordinateType.Lat); c.Parse_Format = Parse_Format_Type.Signed_Degree; return(true); } catch { cp = new CoordinatePart(d[0], CoordinateType.Long); c.Parse_Format = Parse_Format_Type.Signed_Degree; return(true); } case 1: //Attempt Lat cp = new CoordinatePart(d[0], CoordinateType.Lat); c.Parse_Format = Parse_Format_Type.Signed_Degree; return(true); case 2: //Attempt long cp = new CoordinatePart(d[0], CoordinateType.Long); c.Parse_Format = Parse_Format_Type.Signed_Degree; return(true); } } catch { //silent fail } } //SIGNED DEGREE FAILED, REMOVE DASHES FOR OTHER FORMATS s = s.Replace("-", " "); //All other formats should contain 1 letter. if (Regex.Matches(s, @"[a-zA-Z]").Count != 1) { return(false); } //Should only contain 1 letter. //Get Coord Direction int direction = Find_Position(s); if (direction == -1) { return(false); //No direction found } //If Coordinate type int specified, look for mismatch if (type == 1 && (direction == 1 || direction == 3)) { return(false); //mismatch } if (type == 2 && (direction == 0 || direction == 2)) { return(false); //mismatch } CoordinateType t; if (direction == 0 || direction == 2) { t = CoordinateType.Lat; } else { t = CoordinateType.Long; } s = Regex.Replace(s, "[^0-9. ]", ""); //Remove directional character s = s.Trim(); //Trim all spaces before and after string //Try Decimal Degree with Direction if (TryDecimalDegree(s, direction, out d)) { try { cp = new CoordinatePart(d[0], t); c.Parse_Format = Parse_Format_Type.Decimal_Degree; return(true); } catch {//Parser failed try next method } } //Try DDM if (TryDegreeDecimalMinute(s, out d)) { try { //0 Degree //1 Minute //2 Direction (0 = N, 1 = E, 2 = S, 3 = W) cp = new CoordinatePart((int)d[0], d[1], (CoordinatesPosition)direction); c.Parse_Format = Parse_Format_Type.Degree_Decimal_Minute; return(true); } catch { //Parser failed try next method } } //Try DMS if (TryDegreeMinuteSecond(s, out d)) { try { //0 Degree //1 Minute //2 Second //3 Direction (0 = N, 1 = E, 2 = S, 3 = W) cp = new CoordinatePart((int)d[0], (int)d[1], d[2], (CoordinatesPosition)direction); c.Parse_Format = Parse_Format_Type.Degree_Minute_Second; return(true); } catch {//Parser failed try next method } } return(false); }
//Add main to Coordinate and tunnel to Format class. Add private methods to format. //WHEN PARSING NO EXCPETIONS FOR OUT OF RANGE ARGS WILL BE THROWN public static bool TryParse(string coordString, out Coordinate c) { //Turn of eagerload for efficiency EagerLoad eg = new EagerLoad(); eg.Cartesian = false; eg.Celestial = false; eg.UTM_MGRS = false; c = new Coordinate(eg); string s = coordString; s = s.Trim(); //Trim all spaces before and after string double[] d; //Try Signed Degree if (TrySignedDegree(s, out d)) { try { c = new Coordinate(d[0], d[1], eg); return(true); } catch {//Parser failed try next method } } //Try Decimal Degree if (TryDecimalDegree(s, out d)) { try { c = new Coordinate(d[0], d[1], eg); return(true); } catch {//Parser failed try next method } } //Try DDM if (TryDegreeDecimalMinute(s, out d)) { try { //0 Lat Degree //1 Lat Minute //2 Lat Direction (0 = N, 1 = S) //3 Long Degree //4 Long Minute //5 Long Direction (0 = E, 1 = W) CoordinatesPosition latP = CoordinatesPosition.N; CoordinatesPosition lngP = CoordinatesPosition.E; if (d[2] != 0) { latP = CoordinatesPosition.S; } if (d[5] != 0) { lngP = CoordinatesPosition.W; } CoordinatePart lat = new CoordinatePart((int)d[0], d[1], latP, c); CoordinatePart lng = new CoordinatePart((int)d[3], d[4], lngP, c); c = new Coordinate(eg); c.Latitude = lat; c.Longitude = lng; return(true); } catch {//Parser failed try next method } } //Try DMS if (TryDegreeMinuteSecond(s, out d)) { try { //0 Lat Degree //1 Lat Minute //2 Lat Second //3 Lat Direction (0 = N, 1 = S) //4 Long Degree //5 Long Minute //6 Long Second //7 Long Direction (0 = E, 1 = W) CoordinatesPosition latP = CoordinatesPosition.N; CoordinatesPosition lngP = CoordinatesPosition.E; if (d[3] != 0) { latP = CoordinatesPosition.S; } if (d[7] != 0) { lngP = CoordinatesPosition.W; } CoordinatePart lat = new CoordinatePart((int)d[0], (int)d[1], d[2], latP, c); CoordinatePart lng = new CoordinatePart((int)d[4], (int)d[5], d[6], lngP, c); c = new Coordinate(eg); c.Latitude = lat; c.Longitude = lng; return(true); } catch {//Parser failed try next method } } string[] um; //Try MGRS if (TryMGRS(s, out um)) { try { double zone = Convert.ToDouble(um[0]); double easting = Convert.ToDouble(um[3]); double northing = Convert.ToDouble(um[4]); MilitaryGridReferenceSystem mgrs = new MilitaryGridReferenceSystem(um[1], (int)zone, um[2], easting, northing); c = MilitaryGridReferenceSystem.MGRStoLatLong(mgrs); return(true); } catch {//Parser failed try next method } } //Try UTM if (TryUTM(s, out um)) { try { double zone = Convert.ToDouble(um[0]); double easting = Convert.ToDouble(um[2]); double northing = Convert.ToDouble(um[3]); UniversalTransverseMercator utm = new UniversalTransverseMercator(um[1], (int)zone, easting, northing); c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm); return(true); } catch {//Parser failed try next method } } if (TryCartesian(s, out d)) { try { Cartesian cart = new Cartesian(d[0], d[1], d[2]); c = Cartesian.CartesianToLatLong(cart); return(true); } catch {//Parser failed try next method } } //Try Cartesian return(false); }
public static void CalculateSunTime(double lat, double longi, DateTime date, Celestial c, EagerLoad el, double offset) { if (date.Year == 0001) { return; } //Return if date value hasn't been established. if (el.Extensions.Solar_Cycle) { DateTime actualDate = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc); ////Sun Time Calculations //Get solar coordinate info and feed //Get Julian double lw = rad * -longi; double phi = rad * lat; //Rise Set DateTime?[] evDate = Get_Event_Time(lw, phi, -.8333, actualDate, offset, true); //ADDED OFFSET TO ALL Get_Event_Time calls. c.sunRise = evDate[0]; c.sunSet = evDate[1]; c.solarNoon = evDate[2]; c.sunCondition = CelestialStatus.RiseAndSet; //Get Solar Coordinate var celC = Get_Solar_Coordinates(date, -offset); c.solarCoordinates = celC; //Azimuth and Altitude CalculateSunAngle(date.AddHours(-offset), longi, lat, c, celC); //SUBTRACT OFFSET TO CALC IN Z TIME AND ADJUST SUN ANGLE DURING LOCAL CALCULATIONS. // neither sunrise nor sunset if ((!c.SunRise.HasValue) && (!c.SunSet.HasValue)) { if (c.SunAltitude < 0) { c.sunCondition = CelestialStatus.DownAllDay; } else { c.sunCondition = CelestialStatus.UpAllDay; } } // sunrise or sunset else { if (!c.SunRise.HasValue) { // No sunrise this date c.sunCondition = CelestialStatus.NoRise; } else if (!c.SunSet.HasValue) { // No sunset this date c.sunCondition = CelestialStatus.NoSet; } } //Additional Times c.additionalSolarTimes = new AdditionalSolarTimes(); //Dusk and Dawn //Civil evDate = Get_Event_Time(lw, phi, -6, actualDate, offset, false); c.AdditionalSolarTimes.civilDawn = evDate[0]; c.AdditionalSolarTimes.civilDusk = evDate[1]; //Nautical evDate = Get_Event_Time(lw, phi, -12, actualDate, offset, false); c.AdditionalSolarTimes.nauticalDawn = evDate[0]; c.AdditionalSolarTimes.nauticalDusk = evDate[1]; //Astronomical evDate = Get_Event_Time(lw, phi, -18, actualDate, offset, false); c.AdditionalSolarTimes.astronomicalDawn = evDate[0]; c.AdditionalSolarTimes.astronomicalDusk = evDate[1]; //BottomDisc evDate = Get_Event_Time(lw, phi, -.2998, actualDate, offset, false); c.AdditionalSolarTimes.sunriseBottomDisc = evDate[0]; c.AdditionalSolarTimes.sunsetBottomDisc = evDate[1]; } if (el.Extensions.Solstice_Equinox) { Calculate_Soltices_Equinoxes(date, c, offset); } if (el.Extensions.Solar_Eclipse) { CalculateSolarEclipse(date, lat, longi, c); } }
/// <summary> /// Calculates all celestial data. Coordinates will notify as changes occur /// </summary> /// <param name="lat">Decimal format latitude</param> /// <param name="longi">Decimal format longitude</param> /// <param name="date">Geographic DateTime</param> /// <param name="el">EagerLoading Info for Auto-Calculations</param> /// <param name="offset">UTC offset in hours</param> internal void CalculateCelestialTime(double lat, double longi, DateTime date, EagerLoad el, double offset) { if (offset < -12 || offset > 12) { throw new ArgumentOutOfRangeException("Time offsets cannot be greater than 12 or less than -12."); } date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc); if (el.Extensions.Solar_Cycle || el.Extensions.Solar_Eclipse) { SunCalc.CalculateSunTime(lat, longi, date, this, el, offset); } if (el.Extensions.Lunar_Cycle) { MoonCalc.GetMoonTimes(date, lat, longi, this, offset); MoonCalc.GetMoonDistance(date, this, offset); perigee = MoonCalc.GetPerigeeEvents(date); apogee = MoonCalc.GetApogeeEvents(date); //Shift perigee / apogee is working outside UTC if (offset != 0) { perigee.ConvertTo_Local_Time(offset); apogee.ConvertTo_Local_Time(offset); } } if (el.Extensions.Lunar_Cycle || el.Extensions.Zodiac || el.Extensions.Lunar_Eclipse) { MoonCalc.GetMoonIllumination(date, this, lat, longi, el, offset); } if (el.Extensions.Zodiac) { SunCalc.CalculateZodiacSign(date, this); MoonCalc.GetMoonSign(date, this); } if (el.Extensions.Lunar_Cycle || el.Extensions.Solar_Cycle) { Calculate_Celestial_IsUp_Booleans(date, this); } //Shift eclipses if eagerloaded and offset is not 0 if (el.Extensions.Lunar_Eclipse && offset != 0) { lunarEclipse.ConvertTo_LocalTime(offset); } if (el.Extensions.Solar_Eclipse && offset != 0) { solarEclipse.ConvertTo_LocalTime(offset); } }
/// <summary> /// Attempts to parse a string into a Coordinate with specified DateTime /// </summary> /// <param name="value">Coordinate string</param> /// <param name="geoDate">GeoDate</param> /// <param name="coordinate">Coordinate</param> /// <param name="cartesianType">Cartesian Type</param> /// <returns>boolean</returns> /// <example> /// The following example parses an ECEF formatted coordinate string, with an included GeoDate. /// Because this is an ECEF Cartesian type coordinate, we will specify the Cartesian system type. /// <code> /// Coordinate c; /// if(Coordinate.TryParse("5242.097 km, 2444.43 km, 2679.074 km", new DateTime(2018,7,7), CartesianType.ECEF, out c)) /// { /// Console.WriteLine(c); //N 24º 59' 59.987" E 25º 0' 0.001" /// } /// </code> /// </example> public static bool TryParse(string value, DateTime geoDate, CartesianType cartesianType, out Coordinate coordinate) { var eagerLoad = new EagerLoad(); return(TryParse(value, geoDate, cartesianType, eagerLoad, out coordinate)); }
//Add main to Coordinate and tunnel to Format class. Add private methods to format. //WHEN PARSING NO EXCPETIONS FOR OUT OF RANGE ARGS WILL BE THROWN public static bool TryParse(string coordString, CartesianType ct, out Coordinate c) { try { //Turn of eagerload for efficiency EagerLoad eg = new EagerLoad(); eg.Cartesian = false; eg.Celestial = false; eg.UTM_MGRS = false; c = new Coordinate(eg); if (string.IsNullOrEmpty(coordString)) { return(false); } string s = coordString; s = s.Trim(); //Trim all spaces before and after string double[] d; //Try Signed Degree if (TrySignedDegree(s, out d)) { try { c = new Coordinate(d[0], d[1], eg); c.Parse_Format = Parse_Format_Type.Signed_Degree; return(true); } catch {//Parser failed try next method } } //Try Decimal Degree if (TryDecimalDegree(s, out d)) { try { c = new Coordinate(d[0], d[1], eg); c.Parse_Format = Parse_Format_Type.Decimal_Degree; return(true); } catch {//Parser failed try next method } } //Try DDM if (TryDegreeDecimalMinute(s, out d)) { try { //0 Lat Degree //1 Lat Minute //2 Lat Direction (0 = N, 1 = S) //3 Long Degree //4 Long Minute //5 Long Direction (0 = E, 1 = W) CoordinatesPosition latP = CoordinatesPosition.N; CoordinatesPosition lngP = CoordinatesPosition.E; if (d[2] != 0) { latP = CoordinatesPosition.S; } if (d[5] != 0) { lngP = CoordinatesPosition.W; } CoordinatePart lat = new CoordinatePart((int)d[0], d[1], latP); CoordinatePart lng = new CoordinatePart((int)d[3], d[4], lngP); c = new Coordinate(eg); c.Latitude = lat; c.Longitude = lng; c.Parse_Format = Parse_Format_Type.Degree_Decimal_Minute; return(true); } catch {//Parser failed try next method } } //Try DMS if (TryDegreeMinuteSecond(s, out d)) { try { //0 Lat Degree //1 Lat Minute //2 Lat Second //3 Lat Direction (0 = N, 1 = S) //4 Long Degree //5 Long Minute //6 Long Second //7 Long Direction (0 = E, 1 = W) CoordinatesPosition latP = CoordinatesPosition.N; CoordinatesPosition lngP = CoordinatesPosition.E; if (d[3] != 0) { latP = CoordinatesPosition.S; } if (d[7] != 0) { lngP = CoordinatesPosition.W; } CoordinatePart lat = new CoordinatePart((int)d[0], (int)d[1], d[2], latP); CoordinatePart lng = new CoordinatePart((int)d[4], (int)d[5], d[6], lngP); c = new Coordinate(eg); c.Latitude = lat; c.Longitude = lng; c.Parse_Format = Parse_Format_Type.Degree_Minute_Second; return(true); } catch {//Parser failed try next method } } string[] um; //Try MGRS if (TryMGRS(s, out um) || TryMGRS_Polar(s, out um)) { try { double zone = Convert.ToDouble(um[0]); double easting = Convert.ToDouble(um[3]); double northing = Convert.ToDouble(um[4]); MilitaryGridReferenceSystem mgrs = new MilitaryGridReferenceSystem(um[1], (int)zone, um[2], easting, northing); c = MilitaryGridReferenceSystem.MGRStoLatLong(mgrs); c.Parse_Format = Parse_Format_Type.MGRS; return(true); } catch {//Parser failed try next method } } //Try UTM if (TryUTM(s, out um) || TryUPS(s, out um)) { try { double zone = Convert.ToDouble(um[0]); double easting = Convert.ToDouble(um[2]); double northing = Convert.ToDouble(um[3]); UniversalTransverseMercator utm = new UniversalTransverseMercator(um[1], (int)zone, easting, northing); c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm); c.Parse_Format = Parse_Format_Type.UTM; return(true); } catch {//Parser failed try next method } } //Try Cartesian if (TryCartesian(s.ToUpper().Replace("KM", "").Replace("X", "").Replace("Y", "").Replace("Z", ""), out d)) { if (ct == CartesianType.Cartesian) { try { Cartesian cart = new Cartesian(d[0], d[1], d[2]); c = Cartesian.CartesianToLatLong(cart); c.Parse_Format = Parse_Format_Type.Cartesian_Spherical; return(true); } catch {//Parser failed try next method } } if (ct == CartesianType.ECEF) { try { ECEF ecef = new ECEF(d[0], d[1], d[2]); c = ECEF.ECEFToLatLong(ecef); c.Parse_Format = Parse_Format_Type.Cartesian_ECEF; return(true); } catch {//Parser failed try next method } } } } catch (Exception ex) { //Parser exception has occurred Debug.WriteLine("PARSER EXCEPTION HANDLED: " + ex.ToString()); } c = null; return(false); }
public static void GetMoonIllumination(DateTime date, Celestial c, double lat, double lng, EagerLoad el, double offset) { //Moon Illum must be done for both the Moon Name and Phase so either will trigger it to load if (el.Extensions.Lunar_Cycle || el.Extensions.Zodiac) { date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc); offset *= -1; double julianOffset = offset * .04166667; SolarCoordinates s = SunCalc.Get_Solar_Coordinates(date, offset); double JDE = JulianConversions.GetJulian(date) + julianOffset; //Get julian double T = (JDE - 2451545) / 36525; //Get dynamic time. double[] LDMNF = Get_Moon_LDMNF(T); LunarCoordinates m = GetMoonCoords(LDMNF, T, JDE); double sdist = 149598000, phi = Math.Acos(Math.Sin(s.declination.ToRadians()) * Math.Sin(m.declination.ToRadians()) + Math.Cos(s.declination.ToRadians()) * Math.Cos(m.declination.ToRadians()) * Math.Cos(s.rightAscension.ToRadians() - m.rightAscension.ToRadians())), inc = Math.Atan2(sdist * Math.Sin(phi), 0 - sdist * Math.Cos(phi)), angle = Math.Atan2(Math.Cos(s.declination.ToRadians()) * Math.Sin(s.rightAscension.ToRadians() - m.rightAscension.ToRadians()), Math.Sin(s.declination.ToRadians()) * Math.Cos(m.declination.ToRadians()) - Math.Cos(s.declination.ToRadians()) * Math.Sin(m.declination.ToRadians()) * Math.Cos(s.rightAscension.ToRadians() - m.rightAscension.ToRadians())); MoonIllum mi = new MoonIllum(); mi.Fraction = (1 + Math.Cos(inc)) / 2; mi.Phase = 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI; mi.Angle = angle; c.moonIllum = mi; string moonName = ""; int moonDate = 0; //GET PHASE NAME //CHECK MOON AT BEGINNING AT END OF DAY TO GET DAY PHASE DateTime dMon = new DateTime(date.Year, date.Month, 1); for (int x = 1; x <= date.Day; x++) { DateTime nDate = new DateTime(dMon.Year, dMon.Month, x, 0, 0, 0, DateTimeKind.Utc); s = SunCalc.Get_Solar_Coordinates(date, offset); JDE = JulianConversions.GetJulian(nDate) + julianOffset; //Get julian T = (JDE - 2451545) / 36525; //Get dynamic time. LDMNF = Get_Moon_LDMNF(T); m = GetMoonCoords(LDMNF, T, JDE); phi = Math.Acos(Math.Sin(s.declination.ToRadians()) * Math.Sin(m.declination.ToRadians()) + Math.Cos(s.declination.ToRadians()) * Math.Cos(m.declination.ToRadians()) * Math.Cos(s.rightAscension.ToRadians() - m.rightAscension.ToRadians())); inc = Math.Atan2(sdist * Math.Sin(phi), 0 - sdist * Math.Cos(phi)); angle = Math.Atan2(Math.Cos(s.declination.ToRadians()) * Math.Sin(s.rightAscension.ToRadians() - m.rightAscension.ToRadians()), Math.Sin(s.declination.ToRadians()) * Math.Cos(m.declination.ToRadians()) - Math.Cos(s.declination.ToRadians()) * Math.Sin(m.declination.ToRadians()) * Math.Cos(s.rightAscension.ToRadians() - m.rightAscension.ToRadians())); double startPhase = 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI; nDate = new DateTime(dMon.Year, dMon.Month, x, 23, 59, 59, DateTimeKind.Utc); s = SunCalc.Get_Solar_Coordinates(date, offset); JDE = JulianConversions.GetJulian(nDate) + julianOffset; //Get julian T = (JDE - 2451545) / 36525; //Get dynamic time. LDMNF = Get_Moon_LDMNF(T); m = GetMoonCoords(LDMNF, T, JDE); phi = Math.Acos(Math.Sin(s.declination.ToRadians()) * Math.Sin(m.declination.ToRadians()) + Math.Cos(s.declination.ToRadians()) * Math.Cos(m.declination.ToRadians()) * Math.Cos(s.rightAscension.ToRadians() - m.rightAscension.ToRadians())); inc = Math.Atan2(sdist * Math.Sin(phi), 0 - sdist * Math.Cos(phi)); angle = Math.Atan2(Math.Cos(s.declination.ToRadians()) * Math.Sin(s.rightAscension.ToRadians() - m.rightAscension.ToRadians()), Math.Sin(s.declination.ToRadians()) * Math.Cos(m.declination.ToRadians()) - Math.Cos(s.declination.ToRadians()) * Math.Sin(m.declination.ToRadians()) * Math.Cos(s.rightAscension.ToRadians() - m.rightAscension.ToRadians())); double endPhase = 0.5 + 0.5 * inc * (angle < 0 ? -1 : 1) / Math.PI; //Determine Moon Name. if (startPhase <= .5 && endPhase >= .5) { moonDate = x; moonName = GetMoonName(dMon.Month, moonName); } //Get Moon Name (month, string); //Get Moon Phase Name if (date.Day == x) { if (startPhase > endPhase) { mi.PhaseName = "New Moon"; break; } if (startPhase <= .25 && endPhase >= .25) { mi.PhaseName = "First Quarter"; break; } if (startPhase <= .5 && endPhase >= .5) { mi.PhaseName = "Full Moon"; break; } if (startPhase <= .75 && endPhase >= .75) { mi.PhaseName = "Last Quarter"; break; } if (startPhase > 0 && startPhase < .25 && endPhase > 0 && endPhase < .25) { mi.PhaseName = "Waxing Crescent"; break; } if (startPhase > .25 && startPhase < .5 && endPhase > .25 && endPhase < .5) { mi.PhaseName = "Waxing Gibbous"; break; } if (startPhase > .5 && startPhase < .75 && endPhase > .5 && endPhase < .75) { mi.PhaseName = "Waning Gibbous"; break; } if (startPhase > .75 && startPhase < 1 && endPhase > .75 && endPhase < 1) { mi.PhaseName = "Waning Crescent"; break; } } } if (date.Day == moonDate) { if (el.Extensions.Zodiac) { c.AstrologicalSigns.moonName = moonName; } } else { if (el.Extensions.Zodiac) { c.AstrologicalSigns.moonName = ""; } } } if (el.Extensions.Lunar_Eclipse) { CalculateLunarEclipse(date, lat, lng, c); } }
/// <summary> /// Calculates all celestial data. Coordinates will notify as changes occur /// </summary> /// <param name="lat">Decimal format latitude</param> /// <param name="longi">Decimal format longitude</param> /// <param name="date">Geographic DateTime</param> /// <param name="el">EagerLoading Info for Auto-Calculations</param> internal void CalculateCelestialTime(double lat, double longi, DateTime date, EagerLoad el) { date = new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc); SunCalc.CalculateSunTime(lat, longi, date, this, el); if (el.Extensions.Lunar_Cycle) { MoonCalc.GetMoonTimes(date, lat, longi, this); MoonCalc.GetMoonDistance(date, this); perigee = MoonCalc.GetPerigeeEvents(date); apogee = MoonCalc.GetApogeeEvents(date); } MoonCalc.GetMoonIllumination(date, this, lat, longi, el); if (el.Extensions.Zodiac) { SunCalc.CalculateZodiacSign(date, this); MoonCalc.GetMoonSign(date, this); } Calculate_Celestial_IsUp_Booleans(date, this); }
/// <summary> /// Creates a Coordinate object from an MGRS/NATO UTM Coordinate /// </summary> /// <param name="mgrs">MilitaryGridReferenceSystem</param> /// <param name="eagerLoad">EagerLoad</param> /// <returns>Coordinate object</returns> /// <example> /// The following example creates (converts to) a geodetic Coordinate object based on a MGRS object. /// <code> /// MilitaryGridReferenceSystem mgrs = new MilitaryGridReferenceSystem("N", 21, "SA", 66037, 61982); /// Coordinate c = MilitaryGridReferenceSystem.MGRStoLatLong(mgrs, new EagerLoad(false)); /// Console.WriteLine(c); //N 0º 33' 35.988" W 60º 0' 0.01" /// </code> /// </example> public static Coordinate MGRStoLatLong(MilitaryGridReferenceSystem mgrs, EagerLoad eagerLoad) { if (mgrs.systemType == MGRS_Type.MGRS_Polar) { return(MGRS_Polar_ToLatLong(mgrs, eagerLoad)); } string latz = mgrs.LatZone; string digraph = mgrs.Digraph; char eltr = digraph[0]; char nltr = digraph[1]; string digraphLettersE = "ABCDEFGHJKLMNPQRSTUVWXYZ"; string digraphLettersN = "ABCDEFGHJKLMNPQRSTUV"; string digraphLettersAll = ""; for (int lt = 1; lt < 25; lt++) { digraphLettersAll += digraphLettersN; } var eidx = digraphLettersE.IndexOf(eltr); var pbase = 100000; double fl = Math.Floor(Convert.ToDouble(eidx) / 8); double subbase = 1 + eidx - 8 * fl; var ebase = pbase * subbase; var latBand = digraphLettersE.IndexOf(latz); var latBandLow = 8 * latBand - 96; var latBandHigh = 8 * latBand - 88; if (latBand < 2) { latBandLow = -90; latBandHigh = -80; } else if (latBand == 21) { latBandLow = 72; latBandHigh = 84; } else if (latBand > 21) { latBandLow = 84; latBandHigh = 90; } var lowLetter = Math.Floor(100 + 1.11 * latBandLow); var highLetter = Math.Round(100 + 1.11 * latBandHigh); string latBandLetters = null; int l = Convert.ToInt32(lowLetter); int h = Convert.ToInt32(highLetter); if (mgrs.LongZone / 2.0 == Math.Floor(mgrs.LongZone / 2.0)) { latBandLetters = digraphLettersAll.Substring(l + 5, h + 5).ToString(); } else { latBandLetters = digraphLettersAll.Substring(l, h).ToString(); } var nbase = 100000 * (lowLetter + latBandLetters.IndexOf(nltr)); //latBandLetters.IndexOf(nltr) value causing incorrect Northing below -80 var x = ebase + mgrs.Easting; var y = nbase + mgrs.Northing; if (mgrs.systemType != MGRS_Type.MGRS_Polar) { if (y > 10000000) { y = y - 10000000; } if (nbase >= 10000000) { y = nbase + mgrs.northing - 10000000; } } UniversalTransverseMercator utm = new UniversalTransverseMercator(mgrs.LatZone, mgrs.LongZone, x, y, true); utm.equatorial_radius = mgrs.equatorialRadius; utm.inverse_flattening = mgrs.inverseFlattening; Coordinate c = UniversalTransverseMercator.ConvertUTMtoLatLong(utm, eagerLoad); c.Set_Datum(mgrs.equatorialRadius, mgrs.inverseFlattening); return(c); }
public static Coordinate UPS_To_Geodetic(UniversalTransverseMercator utm, EagerLoad el) { //INTERNATIONAL ELLIPSOID double f = 1 / utm.Inverse_Flattening; //Flattening (convert from Inverse that CoordinateSharp works in) double a = utm.Equatorial_Radius; //Semi-Major Axis double b = a * (1 - f); //Semi Minor Axis a(1-f) double E2 = (2 * f) - Math.Pow(f, 2); //Eccentricity Squared double E = Math.Sqrt(E2); //Eccentricity //CONVERT BACK double x = utm.Easting; double y = utm.Northing; //STEP 1 double Xps = (x - 2000000) / .994; double Yps = (y - 2000000) / .994; // 001116144; double tPS = Yps; //Used for true longi calcs. if (Yps == 0) { Yps = 1; } //STEP 2 //ATAN = ARCTAN bool southernHemi = true; if (utm.LatZone.ToUpper() == "Z" || utm.LatZone.ToUpper() == "Y") { southernHemi = false; } double longRad; double longRadForCalcs; //USED FOR LAT CALCS. LongRad is will LongRad. This is needed to due exact 90 issues. if (southernHemi) { longRad = Math.PI + Math.Atan(Xps / tPS); longRadForCalcs = Math.PI + Math.Atan(Xps / Yps); } else { longRad = Math.PI - Math.Atan(Xps / tPS); longRadForCalcs = Math.PI - Math.Atan(Xps / Yps); } //STEP 3 double K = (2 * Math.Pow(a, 2) / b) * Math.Pow(((1 - E) / (1 + E)), (E / 2)); //STEP 4 double absYps = Math.Abs(Yps); double kCos = K * Math.Abs(Math.Cos(longRadForCalcs)); double q = Math.Log(absYps / kCos) / Math.Log(Math.E) * -1; //STEP 5 double estLat = 2 * Math.Atan(Math.Pow(Math.E, q)) - (Math.PI / 2); double lat = 0; while (Math.Abs(estLat - lat) > .0000001) { if (double.IsInfinity(estLat)) { break; } lat = estLat; //STEP 6 double bracket = (1 + Math.Sin(estLat)) / (1 - Math.Sin(estLat)) * Math.Pow((1 - E * Math.Sin(estLat)) / (1 + E * Math.Sin(estLat)), E); double fLat = -q + 1 / 2.0 * Math.Log(bracket); double fLat2 = (1 - Math.Pow(E, 2)) / ((1 - Math.Pow(E, 2) * Math.Pow(Math.Sin(estLat), 2)) * Math.Cos(estLat)); //STEP 7 estLat = estLat - fLat / fLat2; } if (!double.IsInfinity(estLat)) { lat = estLat; } //NaN signals poles double latDeg; if (double.IsNaN(lat)) { latDeg = 90; } else { latDeg = lat * (180 / Math.PI); //Radians to Degrees } if (southernHemi) { latDeg *= -1; } double longDeg; if (double.IsNaN(longRad)) { longDeg = 0; } else { longDeg = (longRad) * (180 / Math.PI); } if (utm.Easting < 2000000) { longDeg = 180 - longDeg % 180; //Normalize to 180 degrees longDeg *= -1; //Set Western Hemi } else if (longDeg > 180) { longDeg -= 180; } else if (longDeg < -180) { longDeg += 180; } if (utm.Northing >= 2000000 && Xps == 0 && southernHemi) { longDeg = 0; } // SET TO 0 or it will equate to 180 if (utm.Northing < 2000000 && Xps == 0 && !southernHemi) { longDeg = 0; } // SET TO 0 or it will equate to 180 return(new Coordinate(latDeg, longDeg, el)); }
private Coordinate ClosestPointOnSegment(Point a, Point b, Coordinate p, DateTime dt, EagerLoad eg) { var d = new Point { Longitude = b.Longitude - a.Longitude, Latitude = b.Latitude - a.Latitude, }; double number = (p.Longitude.ToDouble() - a.Longitude) * d.Longitude + (p.Latitude.ToDouble() - a.Latitude) * d.Latitude; if (number <= 0.0) { return(new Coordinate(a.Latitude, a.Longitude, dt, eg)); } double denom = d.Longitude * d.Longitude + d.Latitude * d.Latitude; if (number >= denom) { return(new Coordinate(b.Latitude, b.Longitude, dt, eg)); } return(new Coordinate(a.Latitude + (number / denom) * d.Latitude, a.Longitude + (number / denom) * d.Longitude, dt, eg)); }