UNPKG

better-suncalc

Version:

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

135 lines (134 loc) 4.6 kB
/* mooncalc.ts Contains functions to calculate moon position, illumination, and rise/set times. Depends on suncalc.ts, constants.ts, and utils.ts for shared functions and constants. */ import { acos, atan, cos, PI, rad, sin, tan } from "./constants"; import { altitude, astroRefraction, azimuth, declination, rightAscension, siderealTime, sunCoords, } from "./suncalc"; import { hoursLater, toDays } from "./utils"; /* ==================== Moon calculations ==================== */ /** * Calculates moon coordinates for a given number of days since J2000. * @param d - Days since J2000 epoch. * @returns Object containing moon's right ascension, declination, and distance. */ export function moonCoords(d) { var L = rad * (218.316 + 13.176396 * d); var M = rad * (134.963 + 13.064993 * d); var F = rad * (93.272 + 13.22935 * d); var l = L + rad * 6.289 * sin(M); var b = rad * 5.128 * sin(F); var dt = 385001 - 20905 * cos(M); return { ra: rightAscension(l, b), dec: declination(l, b), dist: dt, }; } /** * Calculates moon position for provided 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 moon position data. */ export function getMoonPosition(date, lat, lng) { var lw = rad * -lng; var phi = rad * lat; var d = toDays(date); var c = moonCoords(d); var H = siderealTime(d, lw) - c.ra; var h = altitude(H, phi, c.dec); var pa = atan(sin(H), tan(phi) * cos(c.dec) - sin(c.dec) * cos(H)); h += astroRefraction(h); return { azimuth: azimuth(H, phi, c.dec), altitude: h, distance: c.dist, parallacticAngle: pa, }; } /** * Calculates moon illumination parameters. * @param date - Date/time of observation. * @returns Object containing illumination data. */ export function getMoonIllumination(date) { var d = toDays(date); var s = sunCoords(d); var m = moonCoords(d); var sdist = 149598000; var phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)); var inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)); var angle = atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) - cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)); return { fraction: (1 + cos(inc)) / 2, phase: 0.5 + (0.5 * inc * (angle < 0 ? -1 : 1)) / PI, angle: angle, }; } /** * Calculates moon rise and set times for given date and location. * @param date - Date of observation. * @param lat - Observer's latitude in degrees. * @param lng - Observer's longitude in degrees. * @param inUTC - Whether to use UTC time. * @returns Object containing moon times data. */ export function getMoonTimes(date, lat, lng, inUTC) { var t = new Date(date); if (inUTC) t.setUTCHours(0, 0, 0, 0); else t.setHours(0, 0, 0, 0); var hc = 0.133 * rad; var h0 = getMoonPosition(t, lat, lng).altitude - hc; var rise, set; var ye = 0; // Iterate through 2-hour increments to approximate sunrise/sunset. for (var i = 1; i <= 24; i += 2) { var h1 = getMoonPosition(hoursLater(t, i), lat, lng).altitude - hc; var h2 = getMoonPosition(hoursLater(t, i + 1), lat, lng).altitude - hc; var a = (h0 + h2) / 2 - h1; var b = (h2 - h0) / 2; var xe = -b / (2 * a); ye = (a * xe + b) * xe + h1; var d = b * b - 4 * a * h1; var roots = 0; var x1 = 0, x2 = 0; if (d >= 0) { var dx = Math.sqrt(d) / (2 * Math.abs(a)); x1 = xe - dx; x2 = xe + dx; if (Math.abs(x1) <= 1) roots++; if (Math.abs(x2) <= 1) roots++; if (x1 < -1) x1 = x2; } if (roots === 1) { if (h0 < 0) rise = i + x1; else set = i + x1; } else if (roots === 2) { rise = i + (ye < 0 ? x2 : x1); set = i + (ye < 0 ? x1 : x2); } if (rise !== undefined && set !== undefined) break; h0 = h2; } var result = {}; if (rise !== undefined) result.rise = hoursLater(t, rise); if (set !== undefined) result.set = hoursLater(t, set); if (rise === undefined && set === undefined) { result[ye > 0 ? "alwaysUp" : "alwaysDown"] = true; } return result; } //# sourceMappingURL=mooncalc.js.map