@@ -50,13 +50,23 @@ public class NOAACalculator : AstronomicalCalculator {
50
50
public init ( geoLocation: GeoLocation ) {
51
51
NOAACalculator . geoLocation = geoLocation
52
52
}
53
+
54
+ /**
55
+ * An enum to indicate what type of solar event is being calculated.
56
+ */
57
+ enum SolarEvent {
58
+ /**SUNRISE A solar event related to sunrise*/case SUNRISE
59
+ /**SUNSET A solar event related to sunset*/case SUNSET
60
+ // possibly add the following in the future, if added, an IllegalArgumentException should be thrown in getSunHourAngle
61
+ // /**NOON A solar event related to noon*/NOON, /**MIDNIGHT A solar event related to midnight*/MIDNIGHT
62
+ }
53
63
54
64
/**
55
65
* Returns the name of the algorithm.
56
66
* @return the descriptive name of the algorithm.
57
67
*/
58
68
public func getCalculatorName( ) -> String {
59
- return " US National Oceanic and Atmospheric Administration Algorithm " ;
69
+ return " US National Oceanic and Atmospheric Administration Algorithm " ; // Implementation of the Jean Meeus algorithm
60
70
}
61
71
62
72
/**
@@ -72,8 +82,7 @@ public class NOAACalculator : AstronomicalCalculator {
72
82
public override func getUTCSunrise( date: Date , geoLocation: GeoLocation , zenith: Double , adjustForElevation: Bool ) -> Double {
73
83
let elevation = adjustForElevation ? geoLocation. getElevation ( ) : 0 ;
74
84
let adjustedZenith = adjustZenith ( zenith: zenith, elevation: elevation) ;
75
-
76
- var sunrise = NOAACalculator . getSunriseUTC ( julianDay: NOAACalculator . getJulianDay ( date: date) , latitude: geoLocation. getLatitude ( ) , longitude: - geoLocation. getLongitude ( ) , zenith: adjustedZenith) ;
85
+ var sunrise = NOAACalculator . getSunRiseSetUTC ( julianDay: NOAACalculator . getJulianDay ( date: date) , latitude: geoLocation. getLatitude ( ) , longitude: - geoLocation. getLongitude ( ) , zenith: adjustedZenith, solarEvent: SolarEvent . SUNRISE) ;
77
86
sunrise = sunrise / 60 ;
78
87
79
88
// ensure that the time is >= 0 and < 24
@@ -111,7 +120,7 @@ public class NOAACalculator : AstronomicalCalculator {
111
120
let elevation = adjustForElevation ? geoLocation. getElevation ( ) : 0 ;
112
121
let adjustedZenith = adjustZenith ( zenith: zenith, elevation: elevation) ;
113
122
114
- var sunset = NOAACalculator . getSunsetUTC ( julianDay: NOAACalculator . getJulianDay ( date: date) , latitude: geoLocation. getLatitude ( ) , longitude: - geoLocation. getLongitude ( ) , zenith: adjustedZenith) ;
123
+ var sunset = NOAACalculator . getSunRiseSetUTC ( julianDay: NOAACalculator . getJulianDay ( date: date) , latitude: geoLocation. getLatitude ( ) , longitude: - geoLocation. getLongitude ( ) , zenith: adjustedZenith, solarEvent : SolarEvent . SUNSET ) ;
115
124
sunset = sunset / 60 ;
116
125
117
126
// ensure that the time is >= 0 and < 24
@@ -360,28 +369,9 @@ public class NOAACalculator : AstronomicalCalculator {
360
369
return toDegrees ( radians: equationOfTime) * 4.0 ; // in minutes of time
361
370
}
362
371
363
- /**
364
- * Return the <a href="https://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun in
365
- * <a href="https://en.wikipedia.org/wiki/Radian">radians</a> at sunrise for the latitude.
366
- *
367
- * @param lat
368
- * the latitude of observer in degrees
369
- * @param solarDec
370
- * the declination angle of sun in degrees
371
- * @param zenith
372
- * the zenith
373
- * @return hour angle of sunrise in <a href="https://en.wikipedia.org/wiki/Radian">radians</a>
374
- */
375
- private static func getSunHourAngleAtSunrise( lat: Double , solarDec: Double , zenith: Double ) -> Double {
376
- let latRad = toRadians ( degrees: lat) ;
377
- let sdRad = toRadians ( degrees: solarDec) ;
378
-
379
- return acos ( cos ( toRadians ( degrees: zenith) ) / ( cos ( latRad) * cos( sdRad) ) - tan( latRad) * tan( sdRad) ) ; // in radians
380
- }
381
-
382
372
/**
383
373
* Returns the <a href="https://en.wikipedia.org/wiki/Hour_angle">hour angle</a> of the sun in <a href=
384
- * "https://en.wikipedia.org/wiki/Radian">radians</a>at sunset for the latitude.
374
+ * "https://en.wikipedia.org/wiki/Radian">radians</a>at for the latitude.
385
375
* @todo use - {@link #getSunHourAngleAtSunrise(double, double, double)} implementation to avoid duplication of code.
386
376
*
387
377
* @param lat
@@ -390,14 +380,19 @@ public class NOAACalculator : AstronomicalCalculator {
390
380
* the declination angle of sun in degrees
391
381
* @param zenith
392
382
* the zenith
383
+ * @param solarEvent
384
+ * If the hour angle is for sunrise or sunset
393
385
* @return the hour angle of sunset in <a href="https://en.wikipedia.org/wiki/Radian">radians</a>
394
386
*/
395
- private static func getSunHourAngleAtSunset( lat: Double , solarDec: Double , zenith: Double ) -> Double {
396
- let latRad = toRadians ( degrees: lat) ;
397
- let sdRad = toRadians ( degrees: solarDec) ;
398
-
399
- let hourAngle = ( acos ( cos ( toRadians ( degrees: zenith) ) / ( cos ( latRad) * cos( sdRad) ) - tan( latRad) * tan( sdRad) ) ) ;
400
- return - hourAngle; // in radians
387
+ private static func getSunHourAngle( latitude: Double , solarDeclination: Double , zenith: Double , solarEvent: SolarEvent ) -> Double {
388
+ let latRad = toRadians ( degrees: latitude) ;
389
+ let sdRad = toRadians ( degrees: solarDeclination) ;
390
+
391
+ var hourAngle = ( acos ( cos ( toRadians ( degrees: zenith) ) / ( cos ( latRad) * cos( sdRad) ) - tan( latRad) * tan( sdRad) ) ) ;
392
+ if ( solarEvent == SolarEvent . SUNSET) {
393
+ hourAngle = - hourAngle;
394
+ }
395
+ return hourAngle;
401
396
}
402
397
403
398
/**
@@ -474,52 +469,6 @@ public class NOAACalculator : AstronomicalCalculator {
474
469
return toDegrees ( radians: atan ( sin ( hourAngle_rad) / ( ( cos ( hourAngle_rad) * sin( lat_rad) ) - ( tan ( dec_rad) * cos( lat_rad) ) ) ) ) + 180.0 ;
475
470
476
471
}
477
-
478
- /**
479
- * Return the <a href="https://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
480
- * of sunrise for the given day at the given location on earth.
481
- *
482
- * @param julianDay
483
- * the Julian day
484
- * @param latitude
485
- * the latitude of observer in degrees
486
- * @param longitude
487
- * the longitude of observer in degrees
488
- * @param zenith
489
- * the zenith
490
- * @return the time in minutes from zero UTC
491
- */
492
- private static func getSunriseUTC( julianDay: Double , latitude: Double , longitude: Double , zenith: Double ) -> Double {
493
- let julianCenturies = getJulianCenturiesFromJulianDay ( julianDay: julianDay) ;
494
-
495
- // Find the time of solar noon at the location, and use that declination. This is better than start of the
496
- // Julian day
497
-
498
- let noonmin = getSolarNoonUTC ( julianCenturies: julianCenturies, longitude: longitude) ;
499
- let tnoon = getJulianCenturiesFromJulianDay ( julianDay: julianDay + noonmin / 1440.0 ) ;
500
-
501
- // First pass to approximate sunrise (using solar noon)
502
-
503
- var eqTime = getEquationOfTime ( julianCenturies: tnoon) ;
504
- var solarDec = getSunDeclination ( julianCenturies: tnoon) ;
505
- var hourAngle = getSunHourAngleAtSunrise ( lat: latitude, solarDec: solarDec, zenith: zenith) ;
506
-
507
- var delta = longitude - toDegrees( radians: hourAngle) ;
508
- var timeDiff = 4 * delta; // in minutes of time
509
- var timeUTC = 720 + timeDiff - eqTime; // in minutes
510
-
511
- // Second pass includes fractional Julian Day in gamma calc
512
-
513
- let newt = getJulianCenturiesFromJulianDay ( julianDay: getJulianDayFromJulianCenturies ( julianCenturies: julianCenturies) + timeUTC
514
- / 1440.0 ) ;
515
- eqTime = getEquationOfTime ( julianCenturies: newt) ;
516
- solarDec = getSunDeclination ( julianCenturies: newt) ;
517
- hourAngle = getSunHourAngleAtSunrise ( lat: latitude, solarDec: solarDec, zenith: zenith) ;
518
- delta = longitude - toDegrees( radians: hourAngle) ;
519
- timeDiff = 4 * delta;
520
- timeUTC = 720 + timeDiff - eqTime; // in minutes
521
- return timeUTC;
522
- }
523
472
524
473
/**
525
474
* Return the <a href="https://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
@@ -572,7 +521,7 @@ public class NOAACalculator : AstronomicalCalculator {
572
521
* @see #getUTCNoon(Calendar, GeoLocation)
573
522
*/
574
523
private static func getSolarNoonUTC( julianCenturies: Double , longitude: Double ) -> Double {
575
- // First pass uses approximate solar noon to calculate equation of time
524
+ // Only 1 pass for approximate solar noon to calculate equation of time
576
525
let tnoon = getJulianCenturiesFromJulianDay ( julianDay: getJulianDayFromJulianCenturies ( julianCenturies: julianCenturies) + longitude / 360.0 ) ;
577
526
var eqTime = getEquationOfTime ( julianCenturies: tnoon) ;
578
527
let solNoonUTC = 720 + ( longitude * 4 ) - eqTime; // min
@@ -586,7 +535,7 @@ public class NOAACalculator : AstronomicalCalculator {
586
535
587
536
/**
588
537
* Return the <a href="https://en.wikipedia.org/wiki/Universal_Coordinated_Time">Universal Coordinated Time</a> (UTC)
589
- * of sunset for the given day at the given location on earth.
538
+ * of sunrise or sunset for the given day at the given location on earth.
590
539
*
591
540
* @param julianDay
592
541
* the Julian day
@@ -596,13 +545,15 @@ public class NOAACalculator : AstronomicalCalculator {
596
545
* longitude of observer in degrees
597
546
* @param zenith
598
547
* zenith
548
+ * @param solarEvent
549
+ * Is the calculation for sunrise or sunset
599
550
* @return the time in minutes from zero Universal Coordinated Time (UTC)
600
551
*/
601
- private static func getSunsetUTC ( julianDay: Double , latitude: Double , longitude: Double , zenith: Double ) -> Double {
552
+ private static func getSunRiseSetUTC ( julianDay: Double , latitude: Double , longitude: Double , zenith: Double , solarEvent : SolarEvent ) -> Double {
602
553
let julianCenturies = getJulianCenturiesFromJulianDay ( julianDay: julianDay) ;
603
554
604
- // Find the time of solar noon at the location, and use that declination. This is better than start of the
605
- // Julian day
555
+ // Find the time of solar noon at the location, and use that declination.
556
+ // This is better than start of the Julian day
606
557
607
558
let noonmin = getSolarNoonUTC ( julianCenturies: julianCenturies, longitude: longitude) ;
608
559
let tnoon = getJulianCenturiesFromJulianDay ( julianDay: julianDay + noonmin / 1440.0 ) ;
@@ -611,7 +562,7 @@ public class NOAACalculator : AstronomicalCalculator {
611
562
612
563
var eqTime = getEquationOfTime ( julianCenturies: tnoon) ;
613
564
var solarDec = getSunDeclination ( julianCenturies: tnoon) ;
614
- var hourAngle = getSunHourAngleAtSunset ( lat : latitude, solarDec : solarDec, zenith: zenith) ;
565
+ var hourAngle = getSunHourAngle ( latitude : latitude, solarDeclination : solarDec, zenith: zenith, solarEvent : solarEvent ) ;
615
566
616
567
var delta = longitude - toDegrees( radians: hourAngle) ;
617
568
var timeDiff = 4 * delta;
@@ -623,7 +574,7 @@ public class NOAACalculator : AstronomicalCalculator {
623
574
/ 1440.0 ) ;
624
575
eqTime = getEquationOfTime ( julianCenturies: newt) ;
625
576
solarDec = getSunDeclination ( julianCenturies: newt) ;
626
- hourAngle = getSunHourAngleAtSunset ( lat : latitude, solarDec : solarDec, zenith: zenith) ;
577
+ hourAngle = getSunHourAngle ( latitude : latitude, solarDeclination : solarDec, zenith: zenith, solarEvent : solarEvent ) ;
627
578
628
579
delta = longitude - toDegrees( radians: hourAngle) ;
629
580
timeDiff = 4 * delta;
0 commit comments