You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
2.1 KiB
110 lines
2.1 KiB
using Toybox.Math as Math; |
|
using Toybox.Time as Time; |
|
|
|
enum { |
|
NIGHT_END, |
|
NAUTICAL_DAWN, |
|
DAWN, |
|
BLUE_HOUR_AM, |
|
SUNRISE, |
|
SUNRISE_END, |
|
GOLDEN_HOUR_AM, |
|
NOON, |
|
GOLDEN_HOUR_PM, |
|
SUNSET_START, |
|
SUNSET, |
|
BLUE_HOUR_PM, |
|
DUSK, |
|
NAUTICAL_DUSK, |
|
NIGHT, |
|
NUM_RESULTS |
|
} |
|
|
|
class SunCalc { |
|
|
|
hidden const PI = Math.PI, |
|
RAD = Math.PI / 180.0, |
|
PI2 = Math.PI * 2.0, |
|
DAYS = Time.Gregorian.SECONDS_PER_DAY, |
|
J1970 = 2440588, |
|
J2000 = 2451545, |
|
J0 = 0.0009; |
|
|
|
hidden const TIMES = [ |
|
-18 * RAD, |
|
-12 * RAD, |
|
-6 * RAD, |
|
-4 * RAD, |
|
-0.833 * RAD, |
|
-0.3 * RAD, |
|
6 * RAD, |
|
null, |
|
6 * RAD, |
|
-0.3 * RAD, |
|
-0.833 * RAD, |
|
-4 * RAD, |
|
-6 * RAD, |
|
-12 * RAD, |
|
-18 * RAD |
|
]; |
|
|
|
var lastD, lastLng; |
|
var n, ds, M, sinM, C, L, sin2L, dec, Jnoon; |
|
|
|
function initialize() { |
|
lastD = null; |
|
lastLng = null; |
|
} |
|
|
|
function fromJulian(j) { |
|
return new Time.Moment((j + 0.5 - J1970) * DAYS); |
|
} |
|
|
|
function round(a) { |
|
if (a > 0) { |
|
return (a + 0.5).toNumber().toFloat(); |
|
} else { |
|
return (a - 0.5).toNumber().toFloat(); |
|
} |
|
} |
|
|
|
// lat and lng in radians |
|
function calculate(moment, lat, lng, what) { |
|
var d = moment.value().toDouble() / DAYS - 0.5 + J1970 - J2000; |
|
if (lastD != d || lastLng != lng) { |
|
n = round(d - J0 + lng / PI2); |
|
// ds = J0 - lng / PI2 + n; |
|
ds = J0 - lng / PI2 + n - 1.1574e-5 * 68; |
|
M = 6.240059967 + 0.0172019715 * ds; |
|
sinM = Math.sin(M); |
|
C = (1.9148 * sinM + 0.02 * Math.sin(2 * M) + 0.0003 * Math.sin(3 * M)) * RAD; |
|
L = M + C + 1.796593063 + PI; |
|
sin2L = Math.sin(2 * L); |
|
dec = Math.asin( 0.397783703 * Math.sin(L) ); |
|
Jnoon = J2000 + ds + 0.0053 * sinM - 0.0069 * sin2L; |
|
lastD = d; |
|
lastLng = lng; |
|
} |
|
|
|
if (what == NOON) { |
|
return fromJulian(Jnoon); |
|
} |
|
|
|
var x = (Math.sin(TIMES[what]) - Math.sin(lat) * Math.sin(dec)) / (Math.cos(lat) * Math.cos(dec)); |
|
|
|
if (x > 1.0 || x < -1.0) { |
|
return null; |
|
} |
|
|
|
var ds = J0 + (Math.acos(x) - lng) / PI2 + n - 1.1574e-5 * 68; |
|
|
|
var Jset = J2000 + ds + 0.0053 * sinM - 0.0069 * sin2L; |
|
if (what > NOON) { |
|
return fromJulian(Jset); |
|
} |
|
|
|
var Jrise = Jnoon - (Jset - Jnoon); |
|
|
|
return fromJulian(Jrise); |
|
} |
|
}
|
|
|