UNPKG

better-suncalc

Version:

A tiny TypeScript library for calculating sun/moon positions and phases.

221 lines (220 loc) 7.23 kB
/* suncalc.ts Contains functions to calculate sun and moon positions, times, and illumination. Depends on constants.ts and utils.ts for shared constants and common operations. */ import { acos, asin, atan, cos, e, J0, J2000, PI, rad, sin, tan, } from "./constants"; import { fromJulian, toDays } from "./utils"; /* ==================== Sun calculations ==================== */ /** * Calculates right ascension from ecliptic coordinates. * @param l - Ecliptic longitude in radians. * @param b - Ecliptic latitude in radians. * @returns Right ascension in radians. */ export function rightAscension(l, b) { return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); } /** * Calculates declination from ecliptic coordinates. * @param l - Ecliptic longitude in radians. * @param b - Ecliptic latitude in radians. * @returns Declination in radians. */ export function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } /** * Calculates azimuth angle for a celestial body. * @param H - Hour angle in radians. * @param phi - Observer's latitude in radians. * @param dec - Declination of the celestial body in radians. * @returns Azimuth angle in radians (clockwise from north). */ export function azimuth(H, phi, dec) { return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); } /** * Calculates altitude angle for a celestial body. * @param H - Hour angle in radians. * @param phi - Observer's latitude in radians. * @param dec - Declination of celestial body in radians. * @returns Altitude angle in radians. */ export function altitude(H, phi, dec) { return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); } /** * Calculates sidereal time for given Julian days. * @param d - Days since J2000 epoch. * @param lw - Longitude west in radians. * @returns Sidereal time in radians. */ export function siderealTime(d, lw) { return rad * (280.16 + 360.9856235 * d) - lw; } /** * Corrects altitude for atmospheric refraction. * @param h - Altitude angle in radians (geometric). * @returns Refraction correction in radians. */ export function astroRefraction(h) { if (h < 0) h = 0; return 0.0002967 / Math.tan(h + 0.00312536 / (h + 0.08901179)); } /** * Calculates the solar mean anomaly. * @param d - Days since J2000 epoch. * @returns Solar mean anomaly in radians. */ export function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } /** * Calculates ecliptic longitude from solar mean anomaly. * @param M - Solar mean anomaly in radians. * @returns Ecliptic longitude in radians. */ export function eclipticLongitude(M) { var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)); var P = rad * 102.9372; return M + C + P + PI; } /** * Calculates sun coordinates for given days since J2000. * @param d - Days since J2000 epoch. * @returns Object containing sun's declination and right ascension. */ export function sunCoords(d) { var M = solarMeanAnomaly(d); var L = eclipticLongitude(M); return { dec: declination(L, 0), ra: rightAscension(L, 0), }; } /** * Calculates sun position for given date and location. * @param date - Date/time of observation. * @param lat - Observer's latitude in degrees. * @param lng - Observer's longitude in degrees. * @returns Object containing azimuth and altitude in radians. */ export function getPosition(date, lat, lng) { var lw = rad * -lng; var phi = rad * lat; var d = toDays(date); var c = sunCoords(d); var H = siderealTime(d, lw) - c.ra; return { azimuth: azimuth(H, phi, c.dec), altitude: altitude(H, phi, c.dec), }; } // Sun times configuration: [angle in degrees, "riseName", "setName"]. var times = [ [-0.833, "sunrise", "sunset"], [-0.3, "sunriseEnd", "sunsetStart"], [-6, "dawn", "dusk"], [-12, "nauticalDawn", "nauticalDusk"], [-18, "nightEnd", "night"], [6, "goldenHourEnd", "goldenHour"], ]; /** * Adds a custom time definition to sun time calculations. * @param angle - Altitude angle in degrees. * @param riseName - Name for the rise time property. * @param setName - Name for the set time property. */ export function addTime(angle, riseName, setName) { times.push([angle, riseName, setName]); } /** * Calculates Julian cycle for given days and longitude. * @param d - Days since J2000 epoch. * @param lw - Longitude west in radians. * @returns Julian cycle number. */ export function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } /** * Approximates the transit time. * @param Ht - Hour angle. * @param lw - Longitude west in radians. * @param n - Julian cycle number. * @returns Approximate transit time in Julian days. */ export function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } /** * Calculates the precise solar transit time. * @param ds - Days since J2000 epoch. * @param M - Solar mean anomaly. * @param L - Ecliptic longitude. * @returns Julian date of solar transit. */ export function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } /** * Calculates the hour angle for a given altitude. * @param h - Altitude angle in radians. * @param phi - Observer's latitude in radians. * @param dec - Sun declination in radians. * @returns Hour angle in radians. */ export function hourAngle(h, phi, dec) { // Consider clamping value between -1 and 1 if necessary: var inner = (sin(h) - sin(phi) * sin(dec)) / (cos(phi) * cos(dec)); return acos(inner); } /** * Calculates the Julian date for a sun altitude event. * @param h - Altitude angle in radians. * @param lw - Longitude west in radians. * @param phi - Observer's latitude in radians. * @param dec - Sun declination in radians. * @param n - Julian cycle number. * @param M - Solar mean anomaly. * @param L - Ecliptic longitude. * @returns Julian date of the event. */ export function getSetJ(h, lw, phi, dec, n, M, L) { var w = hourAngle(h, phi, dec); var a = approxTransit(w, lw, n); return solarTransitJ(a, M, L); } /** * Calculates sun times (e.g., sunrise, sunset, dawn etc.) for given date and location. * @param date - Date of observation. * @param lat - Observer's latitude in degrees. * @param lng - Observer's longitude in degrees. * @returns Object containing calculated sun times as Date objects. */ export function getTimes(date, lat, lng) { var lw = rad * -lng; var phi = rad * lat; var d = toDays(date); var n = julianCycle(d, lw); var ds = approxTransit(0, lw, n); var M = solarMeanAnomaly(ds); var L = eclipticLongitude(M); var dec = declination(L, 0); var Jnoon = solarTransitJ(ds, M, L); var result = { solarNoon: fromJulian(Jnoon), nadir: fromJulian(Jnoon + 0.5), }; for (var i = 0; i < times.length; i++) { var time = times[i]; var Jset = getSetJ(time[0] * rad, lw, phi, dec, n, M, L); var Jrise = Jnoon - (Jset - Jnoon); result[time[1]] = fromJulian(Jrise); result[time[2]] = fromJulian(Jset); } return result; } //# sourceMappingURL=suncalc.js.map