diff --git a/CoordinateSharp.Magnetic/CoordinateSharp.Magnetic.csproj b/CoordinateSharp.Magnetic/CoordinateSharp.Magnetic.csproj index 891084a7..af728234 100644 --- a/CoordinateSharp.Magnetic/CoordinateSharp.Magnetic.csproj +++ b/CoordinateSharp.Magnetic/CoordinateSharp.Magnetic.csproj @@ -47,7 +47,7 @@ For more information, please contact Signature Group, LLC at this address: sales net40; netstandard1.3; netstandard1.4; netstandard2.0; netstandard2.1; net50; net60; net70 true true - 1.1.8.0 + 1.1.9.0 Signature Group, LLC https://github.com/Tronald/CoordinateSharp @@ -61,7 +61,7 @@ For more information, please contact Signature Group, LLC at this address: sales CoordinateSharp.Magnetic CoordinateSharp.Magnetic - 1.1.7.0 + 1.1.9.0 true true 128x128.png diff --git a/CoordinateSharp/Celestial/Celestial.Coordinates.cs b/CoordinateSharp/Celestial/Celestial.Coordinates.cs index 0b9a8b86..ce265a4c 100644 --- a/CoordinateSharp/Celestial/Celestial.Coordinates.cs +++ b/CoordinateSharp/Celestial/Celestial.Coordinates.cs @@ -54,6 +54,7 @@ namespace CoordinateSharp public class SolarCoordinates { //Test Against https://www.timeanddate.com/worldclock/sunearth.html + internal double trueLongitude; internal double trueLatitude; internal double julianDayDecimal; @@ -64,7 +65,7 @@ public class SolarCoordinates internal double rightAscension; internal double declination; internal double geometricMeanLongitude; - + internal double obliquityOfEcliptic; /// /// Radius Vector (expressed in astronomical units). @@ -96,6 +97,11 @@ public class SolarCoordinates /// public double GeometricMeanLongitude { get { return geometricMeanLongitude; } } + /// + /// Obliquity of the Ecliptic + /// + public double ObliquityOfEcliptic { get { return obliquityOfEcliptic; } } + /// /// Subsolar Latitude. The point at which the sun is perceived to be directly overhead of the Earth (at the zenith). /// diff --git a/CoordinateSharp/Celestial/Solar/SunCalculations.cs b/CoordinateSharp/Celestial/Solar/SunCalculations.cs index 40e29e2b..7e8cca02 100644 --- a/CoordinateSharp/Celestial/Solar/SunCalculations.cs +++ b/CoordinateSharp/Celestial/Solar/SunCalculations.cs @@ -433,7 +433,7 @@ public static SolarCoordinates Get_Solar_Coordinates(DateTime d, double offset) double tdec = Math.Asin(Math.Sin(E.ToRadians()) * Math.Sin(trueLongitude.ToRadians())); //25.7 True declination. Asin used in liu of sin. - double CE = E + .00256 * Math.Cos(ascendingNode.ToRadians());//22.2 Obliquity of the ecliptic + double CE = E + .00256 * Math.Cos(ascendingNode.ToRadians());//25.6 & 25.7 Apparent position of the sun. double ara = Math.Atan2(Math.Cos(CE.ToRadians()) * Math.Sin(apparentLongitude.ToRadians()), Math.Cos(apparentLongitude.ToRadians())); //25.8 Apparent Right Ascensions. Using Atan2 we can move tan to the right side of the function with Numerator, Denominator double adec = Math.Asin(Math.Sin(CE.ToRadians()) * Math.Sin(apparentLongitude.ToRadians())); //25.8 Apparent declination. Asin used in liu of sin. @@ -443,6 +443,7 @@ public static SolarCoordinates Get_Solar_Coordinates(DateTime d, double offset) //Set to degrees //celC.trueRightAscension = tra.ToDegrees(); //celC.trueDeclination = tdec.ToDegrees(); + var tr = tra.ToDegrees().NormalizeDegrees360(); celC.rightAscension = ara.ToDegrees().NormalizeDegrees360(); celC.declination = adec.ToDegrees(); celC.julianDayDecimal = JD-.5 - Math.Floor(JD-.5); @@ -450,7 +451,8 @@ public static SolarCoordinates Get_Solar_Coordinates(DateTime d, double offset) celC.longitude = apparentLongitude.NormalizeDegrees360(); celC.radiusVector = R; celC.geometricMeanLongitude = L0.NormalizeDegrees360(); - //Latitude is always 0 for sun as perturbations no accounted for in low accuracy formulas + celC.obliquityOfEcliptic = E.NormalizeDegrees360(); + //Latitude is always 0 for sun as perturbations not accounted for in low accuracy formulas celC.latitude = 0; celC.trueLatitude = 0; diff --git a/CoordinateSharp/CoordinateSharp.csproj b/CoordinateSharp/CoordinateSharp.csproj index d5629e12..02216362 100644 --- a/CoordinateSharp/CoordinateSharp.csproj +++ b/CoordinateSharp/CoordinateSharp.csproj @@ -50,29 +50,27 @@ Please visit http://coordinatesharp.com/licensing or contact Signature Group, LL net40; netstandard1.3; netstandard1.4; netstandard2.0; netstandard2.1; net50; net60; net70 true true - 2.18.1.1 + 2.19.1.1 Signature Group, LLC https://github.com/Tronald/CoordinateSharp Copyright 2023 CoordinateSharp is a high powered, lightweight .NET library that can convert geographical coordinates, perform distance logic, and calculate location based sun, moon, and magnetic information with minimal code. - -Improves UTM and MGRS conversion efficiency by 13x. --Adds ability create geofence from a specified GEOREF coordinate and precision level. --Adds ability to locate GEOREF box corners based on a given precision level. --Restricts GEOREF easting and northing minutes and seconds to 59.999... to comply with library standards. + -Fixes "Leap Year Bug" impacting celestial calculations and Julian date conversions prior to 1582 (pre-Gregorian). +-Exposes the Obliquity of Ecliptic value within the SolarCoordinate class. Conversion; Latitude; Longitude; Coordinates; Geography; Sun; Moon; Solar; Lunar; Time; MGRS; UTM; EPSG:3857; ECEF; GEOREF; Web Mercator; License.txt CoordinateSharp CoordinateSharp - 2.17.1.1 + 2.19.1.1 true true 128x128.png CoordinateSharp Strong Name.snk false - 2.17.1.1 + 2.19.1.1 https://github.com/Tronald/CoordinateSharp README.md snupkg diff --git a/CoordinateSharp/Julian/Julian.cs b/CoordinateSharp/Julian/Julian.cs index 8e6c8b3d..71d35b43 100644 --- a/CoordinateSharp/Julian/Julian.cs +++ b/CoordinateSharp/Julian/Julian.cs @@ -43,6 +43,8 @@ or shipping CoordinateSharp with a closed source product. Please visit http://coordinatesharp.com/licensing or contact Signature Group, LLC to purchase a commercial license, or for any questions regarding the AGPL 3.0 license requirements or free use license: sales@signatgroup.com. */ using System; +using System.Diagnostics; + namespace CoordinateSharp { /// @@ -125,6 +127,10 @@ public static double GetJulian_Epoch1970(DateTime d) /// Returns date from Julian /// Meeus ch. 7 /// + /// + /// The Gregorian calendar (started in 1582) contains different leap year rules than the Julian calendar. To avoid exceptions, any invalid pre-1582 Gregorian leap year conversions of + /// February 29th will shift to March 1st. As such you may see two consecutive Julian to Gregorian conversions produce a date of March 1st on rare occasions. + /// /// Julian date /// DateTime /// @@ -136,7 +142,7 @@ public static double GetJulian_Epoch1970(DateTime d) /// public static DateTime? GetDate_FromJulian(double j) { - if (Double.IsNaN(j)) { return null; } //No Event Occured + if (Double.IsNaN(j)) { return null; } //No Event Occurred j = j + .5; double Z = Math.Floor(j); @@ -176,6 +182,19 @@ public static double GetJulian_Epoch1970(DateTime d) hours = Math.Floor(hours); minutes = Math.Floor(minutes); + //Leap year safety check due to differences in Julian and Gregorian calendars. + //This limitation of CoordinateSharp is documented. Safety check implemented to prevent breakage. + if (month == 2 && day == 29) + { + if (year / 100 == (int)(year / 100) && year / 400 != (int)(year / 400)) + { + Debug.WriteLine($"CAUTION: Julian date {j} does not exist on the Gregorian calendar (29-FEB-{year}). Shifting to next Gregorian day (1-MAR-{year})."); + month++; + day = 1; + + } + } + DateTime? date = new DateTime?(new DateTime((int)year, (int)month, (int)day, (int)hours, (int)minutes, (int)seconds)); return date; } @@ -183,6 +202,10 @@ public static double GetJulian_Epoch1970(DateTime d) /// Returns date from Julian based on epoch 2000 /// Meeus ch. 7 /// + /// + /// The Gregorian calendar (started in 1582) contains different leap year rules than the Julian calendar. To avoid exceptions, any invalid pre-1582 Gregorian leap year conversions of + /// February 29th will shift to March 1st. As such you may see two consecutive Julian to Gregorian conversions produce a date of March 1st on rare occasions. + /// /// Julian date (epoch 2000) /// DateTime /// @@ -200,6 +223,10 @@ public static double GetJulian_Epoch1970(DateTime d) /// Returns date from Julian based on epoch 1970 /// Meeus ch. 7 /// + /// + /// The Gregorian calendar (started in 1582) contains different leap year rules than the Julian calendar. To avoid exceptions, any invalid pre-1582 Gregorian leap year conversions of + /// February 29th will shift to March 1st. As such you may see two consecutive Julian to Gregorian conversions produce a date of March 1st on rare occasions. + /// /// Julian date (epoch 1970) /// DateTime /// diff --git a/CoordinateSharp_UnitTests/Formatters.cs b/CoordinateSharp_UnitTests/Formatters.cs index 9a057971..257a2aa9 100644 --- a/CoordinateSharp_UnitTests/Formatters.cs +++ b/CoordinateSharp_UnitTests/Formatters.cs @@ -6,6 +6,8 @@ using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Threading; +using NuGet.Frameworks; + namespace CoordinateSharp_UnitTests { [TestClass] @@ -116,6 +118,24 @@ public void Normalize360() Assert.AreEqual(201.80720, Format.NormalizeDegrees360(signed),.000000001); } + [TestMethod] + public void JulianLeapYearSafetyCheck() + { + //Ensure no throws due to calendar differences + JulianConversions.GetDate_FromJulian(1757641.5); + + for (int x = 100; x < 2400; x += 100) + { + Celestial.CalculateCelestialTimes(39, -72, new DateTime(x, 2, 26)); + Celestial.CalculateCelestialTimes(39, -72, new DateTime(x, 4, 21, 10, 10, 12)); + } + + + + } + + + /// /// Ensures Coordinate and serialize in binary and deserialze properly ///