'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); /** * @copyright 2013 Sonia Keys * @copyright 2016 commenthol * @license MIT * @module base */ /** * Base: Functions and other definitions useful with multiple packages. * * Base contains various definitions and support functions useful in multiple * chapters. * * Bessellian and Julian Year * * Chapter 21, Precession actually contains these definitions. They are moved * here because of their general utility. * * Chapter 22, Nutation contains the function for Julian centuries since J2000. * * Phase angle functions * * Two functions, Illuminated and Limb, concern the illumnated phase of a body * and are given in two chapters, 41 an 48. They are collected here because * the identical functions apply in both chapters. * * General purpose math functions * * SmallAngle is recommended in chapter 17, p. 109. * * PMod addresses the issue on p. 7, chapter 1, in the section "Trigonometric * functions of large angles", but the function is not written to be specific * to angles and so has more general utility. * * Horner is described on p. 10, chapter 1. * * FloorDiv and FloorDiv64 are optimizations for the INT function described * on p. 60, chapter 7. */ // ---- constants ---- /** K is the Gaussian gravitational constant. */ const K = 0.01720209895; // K from ch 33, p. 228, for example /** AU is one astronomical unit in km. */ const AU = 149597870; // from Appendix I, p, 407. /** SOblJ2000 sine obliquity at J2000. */ const SOblJ2000 = 0.397777156; /** COblJ2000 cosine obliquity at J2000. */ const COblJ2000 = 0.917482062; // SOblJ2000, COblJ2000 from ch 33, p. 228, for example /** * lightTime returns time for light to travel a given distance. * `dist` is distance in to earth in AU. √(x² + y² + z²) * Result in seconds of time. * @param {Number} dist - distance in to earth in AU * @returns {Number} time for light to travel a given distance in days */ function lightTime (dist) { // Formula given as (33.3) p. 224. return 0.0057755183 * dist } // ---- julian ---- /** * Julian and Besselian years described in chapter 21, Precession. * T, Julian centuries since J2000 described in chapter 22, Nutation. */ /** JMod is the Julian date of the modified Julian date epoch. */ const JMod = 2400000.5; /** J2000 is the Julian date corresponding to January 1.5, year 2000. */ const J2000 = 2451545.0; // Julian days of common epochs. // B1900, B1950 from p. 133 /** Julian days of Julian epoch 1900 */ const J1900 = 2415020.0; /** Julian days of Besselian epoch 1900 */ const B1900 = 2415020.3135; /** Julian days of Besselian epoch 1950 */ const B1950 = 2433282.4235; // JulianYear and other common periods /** JulianYear in days */ const JulianYear = 365.25; // days /** JulianCentury in days */ const JulianCentury = 36525; // days /** BesselianYear in days; equals mean tropical year */ const BesselianYear = 365.2421988; // days /** Mean sidereal year */ const meanSiderealYear = 365.25636; // days /** * JulianYearToJDE returns the Julian ephemeris day for a Julian year. * @param {Number} jy - Julian year * @returns {Number} jde - Julian ephemeris day */ function JulianYearToJDE (jy) { return J2000 + JulianYear * (jy - 2000) } /** * JDEToJulianYear returns a Julian year for a Julian ephemeris day. * @param {Number} jde - Julian ephemeris day * @returns {Number} jy - Julian year */ function JDEToJulianYear (jde) { return 2000 + (jde - J2000) / JulianYear } /** * BesselianYearToJDE returns the Julian ephemeris day for a Besselian year. * @param {Number} by - Besselian year * @returns {Number} jde - Julian ephemeris day */ function BesselianYearToJDE (by) { return B1900 + BesselianYear * (by - 1900) } /** * JDEToBesselianYear returns the Besselian year for a Julian ephemeris day. * @param {Number} jde - Julian ephemeris day * @returns {Number} by - Besselian year */ function JDEToBesselianYear (jde) { return 1900 + (jde - B1900) / BesselianYear } /** * J2000Century returns the number of Julian centuries since J2000. * * The quantity appears as T in a number of time series. * @param {Number} jde - Julian ephemeris day * @returns {Number} number of Julian centuries since J2000 */ function J2000Century (jde) { // The formula is given in a number of places in the book, for example // (12.1) p. 87. // (22.1) p. 143. // (25.1) p. 163. return (jde - J2000) / JulianCentury } // ---- phase ---- /** * illuminated returns the illuminated fraction of a body's disk. * * The illuminated body can be the Moon or a planet. * * @param {Number} i - phase angle in radians. * @returns {Number} illuminated fraction of a body's disk. */ function illuminated (i) { // (41.1) p. 283, also (48.1) p. 345. return (1 + Math.cos(i)) * 0.5 } /** * celestial coordinates in right ascension and declination * or ecliptic coordinates in longitude and latitude */ class Coord { /** * celestial coordinates in right ascension and declination * or ecliptic coordinates in longitude and latitude * * @param {number} ra - right ascension (or longitude) * @param {number} dec - declination (or latitude) * @param {number} [range] - distance * @param {number} [elongation] - elongation */ constructor (ra, dec, range, elongation) { this._ra = ra || 0; this._dec = dec || 0; this.range = range; this.elongation = elongation; } /** * right ascension * @return {number} */ get ra () { return this._ra } set ra (ra) { this._ra = ra; } /** * declination * @return {number} */ get dec () { return this._dec } set dec (dec) { this._dec = dec; } /** * right ascension (or longitude) * @return {number} */ get lon () { return this._ra } set lon (ra) { this._ra = ra; } /** * declination (or latitude) * @return {number} */ get lat () { return this._dec } set lat (dec) { this._dec = dec; } } /** * Limb returns the position angle of the midpoint of an illuminated limb. * * The illuminated body can be the Moon or a planet. * * @param {Coord} equ - equatorial coordinates of the body `{ra, dec}` (in radians) * @param {Coord} appSun - apparent coordinates of the Sun `{ra, dec}` (In radians). * @returns {Number} position angle of the midpoint (in radians). */ function limb (equ, appSun) { const α = equ.ra; const δ = equ.dec; const α0 = appSun.ra; const δ0 = appSun.dec; // Mentioned in ch 41, p. 283. Formula (48.5) p. 346 const sδ = Math.sin(δ); const cδ = Math.cos(δ); const sδ0 = Math.sin(δ0); const cδ0 = Math.cos(δ0); const sα0α = Math.sin(α0 - α); const cα0α = Math.cos(α0 - α); let χ = Math.atan2(cδ0 * sα0α, (sδ0 * cδ - cδ0 * sδ * cα0α)); if (χ < 0) { χ += 2 * Math.PI; } return χ } // ---- math ---- // In chapter 17, p. 109, Meeus recommends 10′. /** * SmallAngle is threshold used by various routines for switching between * trigonometric functions and Pythagorean approximations. */ const SmallAngle = 10 * Math.PI / 180 / 60; // about .003 radians /** cosine of SmallAngle */ const CosSmallAngle = Math.cos(SmallAngle); // about .999996 /** * pmod returns a positive floating-point x mod y. * * For a positive argument y, it returns a value in the range [0,y). * * @param {Number} x * @param {Number} y * @returns {Number} x % y - The result may not be useful if y is negative. */ function pmod (x, y) { let r = x % y; if (r < 0) { r += y; } return r } /** * horner evaluates a polynomal with coefficients c at x. The constant * term is c[0]. * @param {Number} x * @param {Number[]} c - coefficients; c[0] may be of type Number[] * @returns {Number} */ function horner (x, ...c) { if (Array.isArray(c[0])) { c = c[0]; } let i = c.length - 1; let y = c[i]; while (i > 0) { i--; y = y * x + c[i]; } return y } /** * FloorDiv returns the integer floor of the fractional value (x / y). * @param {Number} x * @param {Number} y * @returns {Number} (int) */ function floorDiv (x, y) { const q = x / y; return Math.floor(q) } /** * Cmp compares two float64s and returns -1, 0, or 1 if a is <, ==, or > b, * respectively. * . * @param {Number} a * @param {Number} b * @returns {Number} comparison result */ function cmp (a, b) { if (a < b) return -1 if (a > b) return 1 return 0 } /** * shorthand function for Math.sin, Math.cos * @param {Number} ε * @returns {Number[]} [sin(ε), cos(ε)] */ function sincos (ε) { return [Math.sin(ε), Math.cos(ε)] } /** * Convert degrees to radians * @param {Number} deg - Angle in degrees * @return {Number} Angle in radians */ function toRad (deg) { return (Math.PI / 180.0) * deg } /** * Convert radians to degrees * @param {Number} rad - Angle in radians * @return {Number} Angle in degrees */ function toDeg (rad) { return (180.0 / Math.PI) * rad } /** * separate fix `i` from fraction `f` * @param {Number} float * @returns {Array} [i, f] * {Number} i - (int) fix value * {Number} f - (float) fractional portion; always > 1 */ function modf (float) { const i = Math.trunc(float); const f = Math.abs(float - i); return [i, f] } /** * Rounds `float` value by precision * @param {Number} float - value to round * @param {Number} [precision] - (int) number of post decimal positions * @return {Number} rounded `float` */ function round (float, precision = 14) { return parseFloat(float.toFixed(precision)) } function errorCode (msg, code) { const err = new Error(msg); // @ts-ignore err.code = code; return err } var base = { K, AU, SOblJ2000, COblJ2000, lightTime, JMod, J2000, J1900, B1900, B1950, JulianYear, JulianCentury, BesselianYear, meanSiderealYear, JulianYearToJDE, JDEToJulianYear, BesselianYearToJDE, JDEToBesselianYear, J2000Century, illuminated, Coord, limb, SmallAngle, CosSmallAngle, pmod, horner, floorDiv, cmp, sincos, toRad, toDeg, modf, round, errorCode }; exports.AU = AU; exports.B1900 = B1900; exports.B1950 = B1950; exports.BesselianYear = BesselianYear; exports.BesselianYearToJDE = BesselianYearToJDE; exports.COblJ2000 = COblJ2000; exports.Coord = Coord; exports.CosSmallAngle = CosSmallAngle; exports.J1900 = J1900; exports.J2000 = J2000; exports.J2000Century = J2000Century; exports.JDEToBesselianYear = JDEToBesselianYear; exports.JDEToJulianYear = JDEToJulianYear; exports.JMod = JMod; exports.JulianCentury = JulianCentury; exports.JulianYear = JulianYear; exports.JulianYearToJDE = JulianYearToJDE; exports.K = K; exports.SOblJ2000 = SOblJ2000; exports.SmallAngle = SmallAngle; exports.cmp = cmp; exports["default"] = base; exports.errorCode = errorCode; exports.floorDiv = floorDiv; exports.horner = horner; exports.illuminated = illuminated; exports.lightTime = lightTime; exports.limb = limb; exports.meanSiderealYear = meanSiderealYear; exports.modf = modf; exports.pmod = pmod; exports.round = round; exports.sincos = sincos; exports.toDeg = toDeg; exports.toRad = toRad;