Skip to content

Commit f464766

Browse files
authored
Merge pull request #241 from Tronald/develop
2.24.1.1
2 parents b04af81 + e125668 commit f464766

File tree

7 files changed

+281
-43
lines changed

7 files changed

+281
-43
lines changed

CoordinateSharp.Magnetic/CoordinateSharp.Magnetic.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ For more information, please contact Signature Group, LLC at this address: sales
4747
<TargetFrameworks>net40; netstandard1.3; netstandard1.4; netstandard2.0; netstandard2.1; net50; net60; net70; net80</TargetFrameworks>
4848
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
4949
<GenerateDocumentationFile>true</GenerateDocumentationFile>
50-
<Version>1.1.13.0</Version>
50+
<Version>1.1.14.0</Version>
5151
<Authors>Signature Group, LLC</Authors>
5252
<Company />
5353
<PackageProjectUrl>https://github.com/Tronald/CoordinateSharp</PackageProjectUrl>
@@ -61,7 +61,7 @@ For more information, please contact Signature Group, LLC at this address: sales
6161
<PackageIconUrl></PackageIconUrl>
6262
<PackageId>CoordinateSharp.Magnetic</PackageId>
6363
<Title>CoordinateSharp.Magnetic</Title>
64-
<AssemblyVersion>1.1.13.0</AssemblyVersion>
64+
<AssemblyVersion>1.1.14.0</AssemblyVersion>
6565
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
6666
<SignAssembly>true</SignAssembly>
6767
<PackageIcon>128x128.png</PackageIcon>

CoordinateSharp/Celestial/Celestial.StaticMethods.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1147,7 +1147,7 @@ public static AltitudeEvents Get_Time_at_Solar_Altitude(double lat, double longi
11471147
double lw = rad * -longi;
11481148
double phi = rad * lat;
11491149

1150-
var events = SunCalc.Get_Event_Time(lw, phi, alt, date, offset, false);
1150+
var events = SunCalc.Get_Event_Time(lat, longi, lw, phi, alt, date, offset, false);
11511151

11521152
var altE = new AltitudeEvents() { Rising = events[0], Setting = events[1] };
11531153

CoordinateSharp/Celestial/Solar/SunCalculations.cs

Lines changed: 169 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ or shipping CoordinateSharp with a closed source product.
4545
using System;
4646
using System.Collections.Generic;
4747
using System.Diagnostics;
48+
using System.Linq;
4849
using CoordinateSharp.Formatters;
4950
namespace CoordinateSharp
5051
{
@@ -57,81 +58,88 @@ public static void CalculateSunTime(double lat, double lng, DateTime date, Celes
5758
if (el.Extensions.Solar_Cycle)
5859
{
5960
DateTime actualDate = new DateTime(date.Year, date.Month, date.Day, 0, 0, 0, DateTimeKind.Utc);
61+
6062

63+
6164
////Sun Time Calculations
6265
//Get solar coordinate info and feed
6366
//Get Julian
6467
double lw = rad * -lng;
6568
double phi = rad * lat;
6669

6770
//Rise Set
68-
DateTime?[] evDate = Get_Event_Time(lw, phi, -.8333, actualDate, offset,true); //ADDED OFFSET TO ALL Get_Event_Time calls.
71+
DateTime?[] evDate = Get_Event_Time(lat, lng, lw, phi, -.8333, actualDate, offset,true); //ADDED OFFSET TO ALL Get_Event_Time calls.
6972

7073
c.sunRise = evDate[0];
7174
c.sunSet = evDate[1];
7275
c.solarNoon = evDate[2];
73-
74-
c.sunCondition = CelestialStatus.RiseAndSet;
7576

7677
//Get Solar Coordinate
7778
var celC = Get_Solar_Coordinates(date, -offset);
7879
c.solarCoordinates = celC;
7980
//Azimuth and Altitude
8081
CalculateSunAngle(date.AddHours(-offset), lng, lat, c, celC); //SUBTRACT OFFSET TO CALC IN Z TIME AND ADJUST SUN ANGLE DURING LOCAL CALCULATIONS.
82+
83+
//SET SUN CONDITION
84+
c.sunCondition = CelestialStatus.RiseAndSet;
85+
8186
// neither sunrise nor sunset
8287
if ((!c.SunRise.HasValue) && (!c.SunSet.HasValue))
8388
{
84-
if (c.SunAltitude < 0)
89+
//Check sun altitude at apex (solar noon) to ensure accurate logic.
90+
//Previous logic determined of user time passed (c.sunAltitude), but due to Meeus limitation in 15.1, it could cause a misreport.
91+
//https://github.com/Tronald/CoordinateSharp/issues/167
92+
93+
var safety = new Celestial();
94+
CalculateSunAngle(c.solarNoon.Value, lng, lat, safety, celC);
95+
96+
if (safety.sunAltitude <= -.8333)
8597
{
8698
c.sunCondition = CelestialStatus.DownAllDay;
87-
8899
}
89100
else
90101
{
91-
c.sunCondition = CelestialStatus.UpAllDay;
102+
c.sunCondition = CelestialStatus.UpAllDay;
92103
}
93104
}
94105
// sunrise or sunset
95106
else
96107
{
97108
if (!c.SunRise.HasValue)
98109
{
99-
// No sunrise this date
100110
c.sunCondition = CelestialStatus.NoRise;
101-
102111
}
103112
else if (!c.SunSet.HasValue)
104113
{
105-
// No sunset this date
106114
c.sunCondition = CelestialStatus.NoSet;
107-
}
115+
}
108116
}
109-
117+
110118
//Sat day and night time spans within 24 hours period
111119
Set_DayNightSpan(c);
112120

113121
//Additional Times
114122
c.additionalSolarTimes = new AdditionalSolarTimes();
115123
//Dusk and Dawn
116124
//Civil
117-
evDate = Get_Event_Time(lw, phi, -6, actualDate, offset,false);
125+
evDate = Get_Event_Time(lat, lng, lw, phi, -6, actualDate, offset,false);
118126
c.AdditionalSolarTimes.civilDawn = evDate[0];
119127
c.AdditionalSolarTimes.civilDusk = evDate[1];
120128

121129

122130
//Nautical
123-
evDate = Get_Event_Time(lw, phi, -12, actualDate, offset, false);
131+
evDate = Get_Event_Time(lat, lng, lw, phi, -12, actualDate, offset, false);
124132
c.AdditionalSolarTimes.nauticalDawn = evDate[0];
125133
c.AdditionalSolarTimes.nauticalDusk = evDate[1];
126134

127135
//Astronomical
128-
evDate = Get_Event_Time(lw, phi, -18, actualDate, offset, false);
136+
evDate = Get_Event_Time(lat, lng, lw, phi, -18, actualDate, offset, false);
129137

130138
c.AdditionalSolarTimes.astronomicalDawn = evDate[0];
131139
c.AdditionalSolarTimes.astronomicalDusk = evDate[1];
132140

133141
//BottomDisc
134-
evDate = Get_Event_Time(lw, phi, -.2998, actualDate, offset, false);
142+
evDate = Get_Event_Time(lat, lng, lw, phi, -.2998, actualDate, offset, false);
135143
c.AdditionalSolarTimes.sunriseBottomDisc = evDate[0];
136144
c.AdditionalSolarTimes.sunsetBottomDisc = evDate[1];
137145

@@ -141,17 +149,30 @@ public static void CalculateSunTime(double lat, double lng, DateTime date, Celes
141149
if (el.Extensions.Solstice_Equinox){ Calculate_Solstices_Equinoxes(date, c, offset); }
142150
if (el.Extensions.Solar_Eclipse) { CalculateSolarEclipse(date, lat, lng, c); }
143151
}
152+
153+
private static double GetAltitude(DateTime date, double offset, double lat, double lng)
154+
{
155+
var safety = new Celestial();
156+
157+
var celC = Get_Solar_Coordinates(date, offset);
158+
CalculateSunAngle(date.AddHours(-offset), lng, lat, safety, celC);
159+
160+
return safety.sunAltitude;
161+
}
162+
144163
/// <summary>
145164
/// Gets time of event based on specified degree below specified altitude
146165
/// </summary>
166+
/// <param name="lat">Observer Latitude in degrees</param>
167+
/// <param name="lng">Observer Longitude in degrees</param>
147168
/// <param name="lw">Observer Longitude in radians</param>
148169
/// <param name="phi">Observer Latitude in radians</param>
149170
/// <param name="h">Angle in Degrees</param>
150171
/// <param name="date">Date of Event</param>
151172
/// <param name="offset">Offset hours</param>
152173
/// <param name="calculateNoon">Should solar noon iterate and return value</param>
153174
/// <returns>DateTime?[]{rise, set}</returns>
154-
internal static DateTime?[] Get_Event_Time(double lw, double phi, double h, DateTime date, double offset, bool calculateNoon)
175+
internal static DateTime?[] Get_Event_Time(double lat, double lng, double lw, double phi, double h, DateTime date, double offset, bool calculateNoon)
155176
{
156177
double julianOffset = offset * .04166667;
157178

@@ -167,16 +188,10 @@ public static void CalculateSunTime(double lat, double lng, DateTime date, Celes
167188
double d = JulianConversions.GetJulian(date.AddDays(x-2)) - j2000 + .5; //LESS PRECISE JULIAN NEEDED
168189
double n = julianCycle(d, lw);
169190

170-
//var celC = Get_Solar_Coordinates(date); //Change and Test locs!
171-
172-
double ds = approxTransit(0, lw, n);
173-
174-
//M = celC.MeanAnomaly.ToRadians();
191+
double ds = approxTransit(0, lw, n);
175192

176193
double M = solarMeanAnomaly(ds);
177194

178-
179-
180195
double L = eclipticLongitude(M);
181196

182197
double dec = declination(L, 0);
@@ -200,16 +215,144 @@ public static void CalculateSunTime(double lat, double lng, DateTime date, Celes
200215
}
201216
}
202217

218+
DateTime? tNoon = null;
219+
if (calculateNoon)
220+
{
221+
tNoon = Get_Event_Target_Date(solarNoons, date);
222+
solarEventsCorrection(lat, lng, date, offset, rises, sets, tNoon);
223+
}
224+
203225
//Compare and send
204226
DateTime? tRise = Get_Event_Target_Date(rises, date);
205227
DateTime? tSet = Get_Event_Target_Date(sets, date);
206228

207-
DateTime? tNoon = null;
208-
if (calculateNoon){tNoon = Get_Event_Target_Date(solarNoons, date); }
229+
209230

210231
return new DateTime?[] { tRise, tSet, tNoon};
211232
}
212233

234+
/// <summary>
235+
/// Corrects near horizon miss calculations that may occur on rare occasion due to Meeus 15.1 limitation.
236+
/// May cause slight efficiency decrease during transition from rise/set to up or down all day.
237+
/// Occurs rare so delay should be negligent in most instances.
238+
/// </summary>
239+
/// <param name="lat">latitude</param>
240+
/// <param name="lng">longitude</param>
241+
/// <param name="target">target date</param>
242+
/// <param name="offset">timezone offset</param>
243+
/// <param name="rises">sun rises</param>
244+
/// <param name="sets">sun sets</param>
245+
///<param name="solarNoon">solar noon time</param>
246+
private static void solarEventsCorrection(double lat, double lng, DateTime target, double offset, DateTime?[] rises, DateTime?[] sets, DateTime? solarNoon)
247+
{
248+
if (!solarNoon.HasValue) { return; }//can't check
249+
if (!datesContainNull(rises) && !datesContainNull(sets)) { return; }
250+
251+
DateTime? tRise = Get_Event_Target_Date(rises, target);
252+
DateTime? tSet = Get_Event_Target_Date(sets, target);
253+
254+
int? setIndex = null;
255+
int? riseIndex = null;
256+
257+
//Determine if this can be passed through a top level call in future for efficiency. This is a duplicate call, but original may not return correct value
258+
var solarAltitude = GetAltitude(solarNoon.Value, offset, lat, lng);
259+
260+
if (tRise.HasValue && tSet.HasValue)
261+
{
262+
setIndex = targetEventIndex(sets, tSet.Value);
263+
riseIndex = targetEventIndex(rises, tRise.Value);
264+
265+
if(setIndex==null || riseIndex==null) { return; }
266+
267+
//SEE IF NEXT DAY HAS DUPLICATE NULLS. SIGNALS ALL DAY EVENT OCCURING
268+
if (setIndex != 4 && riseIndex != 4 && !sets[setIndex.Value + 1].HasValue && !rises[riseIndex.Value + 1].HasValue)
269+
{
270+
271+
272+
//IF RISE AFTER SET AND DOWN ALL DAY ZERO OUT RISE
273+
if (solarAltitude<=-0.8333 && sets[setIndex.Value].Value < rises[riseIndex.Value].Value)
274+
{
275+
rises[riseIndex.Value] = null;
276+
}
277+
////IF SET IS AFTER RISE AND UP ALL DAY, ZERO OUT SET
278+
else if (solarAltitude> -0.8333 && sets[setIndex.Value].Value > rises[riseIndex.Value].Value)
279+
{
280+
sets[setIndex.Value] = null;
281+
}
282+
283+
284+
}
285+
//SEE IF PREVIOUS DAY HAS DUPLICATE NULLS
286+
else if (setIndex != 0 && riseIndex != 0 && !sets[setIndex.Value - 1].HasValue && !rises[riseIndex.Value - 1].HasValue)
287+
{
288+
289+
////IF RISE IS BEFORE SET AND DOWN ALL DAY ZERO OUT RISE
290+
if (solarAltitude <= -0.8333 && sets[setIndex.Value].Value > rises[riseIndex.Value].Value)
291+
{
292+
rises[riseIndex.Value] = null;
293+
}
294+
////IF SET IS BEFORE RISE AND UP ALL DAY, ZERO OUT SET
295+
else if (solarAltitude> -0.8333 && sets[setIndex.Value].Value < rises[riseIndex.Value].Value)
296+
{
297+
sets[setIndex.Value] = null;
298+
}
299+
}
300+
}
301+
else if(tRise.HasValue && !tSet.HasValue)
302+
{
303+
riseIndex = targetEventIndex(rises, tRise.Value);
304+
if (riseIndex == null) { return; }
305+
306+
//IF NEXT DAY IS UP DOWN ALL DAY SCRATCH THIS TIME BECAUSE THE SUN HAS TO SET FIRST
307+
if(riseIndex != 4 && !rises[riseIndex.Value + 1].HasValue && solarAltitude <= -0.8333)
308+
{
309+
rises[riseIndex.Value] = null;
310+
}
311+
//IF PREVIOUS DAY IS UP ALL DAY SCRATCH AS THIS HAS TO SET FIRST
312+
else if (riseIndex != 0 && !rises[riseIndex.Value - 1].HasValue && solarAltitude > -0.8333)
313+
{
314+
rises[riseIndex.Value] = null;
315+
}
316+
317+
318+
}
319+
else if (!tRise.HasValue && tSet.HasValue)
320+
{
321+
setIndex = targetEventIndex(sets, tSet.Value);
322+
if (setIndex == null) { return; }
323+
324+
//IF NEXT DAY IS UP ALL DAY SCRATCH THIS TIME BECAUSE THE SUN HAS TO RISE FIRST
325+
if (setIndex != 4 && !sets[setIndex.Value + 1].HasValue && solarAltitude > -0.8333)
326+
{
327+
sets[setIndex.Value] = null;
328+
}
329+
//IF PREVIOUS DAY IS DOWN ALL DAY SCRATCH AS THIS HAS TO RISE FIRST
330+
else if (setIndex != 0 && !sets[setIndex.Value - 1].HasValue && solarAltitude <= -0.8333)
331+
{
332+
sets[setIndex.Value] = null;
333+
}
334+
}
335+
336+
}
337+
private static bool datesContainNull(DateTime?[] dates)
338+
{
339+
foreach(var d in dates)
340+
{
341+
if (!d.HasValue) { return true; }
342+
}
343+
return false;
344+
}
345+
346+
private static int? targetEventIndex(DateTime?[] dates, DateTime target)
347+
{
348+
int x = 0;
349+
foreach(var d in dates)
350+
{
351+
if(d.HasValue && d.Value == target) { return x; }
352+
x++;
353+
}
354+
return null;
355+
}
213356
/// <summary>
214357
/// Iterates stored events and extracts the one that occurs on the target date.
215358
/// </summary>
@@ -527,7 +670,7 @@ private static double approxTransit(double Ht, double lw, double n)
527670
private static double GetTime(double h, double lw, double phi, double dec, double n,double M, double L)
528671
{
529672
double approxTime = hourAngle(h, phi, dec); //Ch15 Formula 15.1
530-
673+
531674
double a = approxTransit(approxTime, lw, n);
532675
double st = solarTransitJ(a, M, L);
533676

CoordinateSharp/CoordinateSharp.csproj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,26 +50,27 @@ Please visit http://coordinatesharp.com/licensing or contact Signature Group, LL
5050
<TargetFrameworks>net40; netstandard1.3; netstandard1.4; netstandard2.0; netstandard2.1; net50; net60; net70; net80</TargetFrameworks>
5151
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
5252
<GenerateDocumentationFile>true</GenerateDocumentationFile>
53-
<Version>2.23.1.1</Version>
53+
<Version>2.24.1.1</Version>
5454
<Authors>Signature Group, LLC</Authors>
5555
<Company />
5656
<PackageProjectUrl>https://github.com/Tronald/CoordinateSharp</PackageProjectUrl>
5757
<PackageLicenseUrl></PackageLicenseUrl>
5858
<Copyright>Copyright 2024</Copyright>
5959
<Description>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.</Description>
60-
<PackageReleaseNotes>-Adds the ability to densify polylines to mitigate geofence spherical distortions over long distances.</PackageReleaseNotes>
60+
<PackageReleaseNotes>-Fixes bug causing incorrect sun condition to report in circumpolar regions during slow transition at horizon.
61+
-Adds feature to allow custom specification of earth shape during point densification.</PackageReleaseNotes>
6162
<PackageTags>Conversion; Latitude; Longitude; Coordinates; Geography; Sun; Moon; Solar; Lunar; Time; MGRS; UTM; EPSG:3857; ECEF; GEOREF; Web Mercator;</PackageTags>
6263
<!-- <PackageLicenseExpression>AGPL-3.0-or-later</PackageLicenseExpression>-->
6364
<PackageLicenseFile>License.txt</PackageLicenseFile> <PackageIconUrl></PackageIconUrl>
6465
<PackageId>CoordinateSharp</PackageId>
6566
<Title>CoordinateSharp</Title>
66-
<AssemblyVersion>2.23.1.1</AssemblyVersion>
67+
<AssemblyVersion>2.24.1.1</AssemblyVersion>
6768
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
6869
<SignAssembly>true</SignAssembly>
6970
<PackageIcon>128x128.png</PackageIcon>
7071
<AssemblyOriginatorKeyFile>CoordinateSharp Strong Name.snk</AssemblyOriginatorKeyFile>
7172
<DelaySign>false</DelaySign>
72-
<FileVersion>2.23.1.1</FileVersion>
73+
<FileVersion>2.24.1.1</FileVersion>
7374
<RepositoryUrl>https://github.com/Tronald/CoordinateSharp</RepositoryUrl>
7475
<PackageReadmeFile>README.md</PackageReadmeFile>
7576
<SymbolPackageFormat>snupkg</SymbolPackageFormat>

0 commit comments

Comments
 (0)