const DEGREES_TO_RADIANS = Math.PI / 180; const DAY_IN_MS = 1000 * 60 * 60 * 24; const JD1970 = 2440588; // Julian Day year 1970 const JD2000 = 2451545; // Julian Day year 2000 // This angle ε [epsilon] is called the obliquity of the ecliptic and its value at the beginning of 2000 was 23.4397° const e = DEGREES_TO_RADIANS * 23.4397; // obliquity of the Earth // Refer https://www.aa.quae.nl/en/reken/zonpositie.html // "The Mean Anomaly" section for explanation const M0 = 357.5291; // Earth mean anomaly on start day const M1 = 0.98560028; // Earth angle traverses on average per day seen from the sun const THETA0 = 280.147; // The sidereal time (in degrees) at longitude 0° at the instant defined by JD2000 const THETA1 = 360.9856235; // The rate of change of the sidereal time, in degrees per day. /** * Calculate sun position * based on https://www.aa.quae.nl/en/reken/zonpositie.html * inspired by https://github.com/mourner/suncalc/blob/master/suncalc.js */ export function getSunPosition(timestamp, latitude, longitude) { const longitudeWestInRadians = DEGREES_TO_RADIANS * -longitude; const phi = DEGREES_TO_RADIANS * latitude; const d = toDays(timestamp); const c = getSunCoords(d); // hour angle const H = getSiderealTime(d, longitudeWestInRadians) - c.rightAscension; return { azimuth: getAzimuth(H, phi, c.declination), altitude: getAltitude(H, phi, c.declination) }; } export function getSunDirection(timestamp, latitude, longitude) { const { azimuth, altitude } = getSunPosition(timestamp, latitude, longitude); // solar position to light direction return [ Math.sin(azimuth) * Math.cos(altitude), Math.cos(azimuth) * Math.cos(altitude), -Math.sin(altitude) ]; } function toJulianDay(timestamp) { const ts = typeof timestamp === 'number' ? timestamp : timestamp.getTime(); return ts / DAY_IN_MS - 0.5 + JD1970; } function toDays(timestamp) { return toJulianDay(timestamp) - JD2000; } function getRightAscension(eclipticLongitude, b) { const lambda = eclipticLongitude; return Math.atan2(Math.sin(lambda) * Math.cos(e) - Math.tan(b) * Math.sin(e), Math.cos(lambda)); } function getDeclination(eclipticLongitude, b) { const lambda = eclipticLongitude; return Math.asin(Math.sin(b) * Math.cos(e) + Math.cos(b) * Math.sin(e) * Math.sin(lambda)); } function getAzimuth(hourAngle, latitudeInRadians, declination) { const H = hourAngle; const phi = latitudeInRadians; const delta = declination; return Math.atan2(Math.sin(H), Math.cos(H) * Math.sin(phi) - Math.tan(delta) * Math.cos(phi)); } function getAltitude(hourAngle, latitudeInRadians, declination) { const H = hourAngle; const phi = latitudeInRadians; const delta = declination; return Math.asin(Math.sin(phi) * Math.sin(delta) + Math.cos(phi) * Math.cos(delta) * Math.cos(H)); } // https://www.aa.quae.nl/en/reken/zonpositie.html // "The Observer section" function getSiderealTime(dates, longitudeWestInRadians) { return DEGREES_TO_RADIANS * (THETA0 + THETA1 * dates) - longitudeWestInRadians; } function getSolarMeanAnomaly(days) { return DEGREES_TO_RADIANS * (M0 + M1 * days); } function getEclipticLongitude(meanAnomaly) { const M = meanAnomaly; // equation of center const C = DEGREES_TO_RADIANS * (1.9148 * Math.sin(M) + 0.02 * Math.sin(2 * M) + 0.0003 * Math.sin(3 * M)); // perihelion of the Earth const P = DEGREES_TO_RADIANS * 102.9372; return M + C + P + Math.PI; } function getSunCoords(dates) { const M = getSolarMeanAnomaly(dates); const L = getEclipticLongitude(M); return { declination: getDeclination(L, 0), rightAscension: getRightAscension(L, 0) }; } //# sourceMappingURL=suncalc.js.map