470 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			470 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'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;
 |