344 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			344 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
'use strict';
 | 
						||
 | 
						||
Object.defineProperty(exports, '__esModule', { value: true });
 | 
						||
 | 
						||
var base = require('./base.cjs');
 | 
						||
var coord = require('./coord.cjs');
 | 
						||
var moonposition = require('./moonposition.cjs');
 | 
						||
var nutation = require('./nutation.cjs');
 | 
						||
var solar = require('./solar.cjs');
 | 
						||
 | 
						||
/**
 | 
						||
 * @copyright 2013 Sonia Keys
 | 
						||
 * @copyright 2016 commenthol
 | 
						||
 * @license MIT
 | 
						||
 * @module moon
 | 
						||
 */
 | 
						||
 | 
						||
const { sin, cos, asin, atan2 } = Math;
 | 
						||
const D2R = Math.PI / 180;
 | 
						||
const _I = 1.54242 * D2R; // IAU value of inclination of mean lunar equator
 | 
						||
 | 
						||
const [sI, cI] = base["default"].sincos(_I);
 | 
						||
 | 
						||
/**
 | 
						||
 * Physical returns quantities useful for physical observation of the Moon.
 | 
						||
 *
 | 
						||
 * Returned l, b are librations in selenographic longitude and latitude.
 | 
						||
 * They represent combined optical and physical librations.  Topocentric
 | 
						||
 * librations are not considered.
 | 
						||
 *
 | 
						||
 * Returned P is the the position angle of the Moon's axis of rotation.
 | 
						||
 *
 | 
						||
 * Returned l0, b0 are the selenographic coordinates of the Sun.
 | 
						||
 *
 | 
						||
 * Returned values all in radians.
 | 
						||
 | 
						||
 * @param {number} jde - Julian ephemeris day
 | 
						||
 * @param {Planet} earth - VSOP87 Planet Earth
 | 
						||
 * @return {Array}
 | 
						||
 *    {base.Coord} cMoon - selenographic longitude, latitude of the Moon
 | 
						||
 *    {number} P - position angle of the Moon's axis of rotation
 | 
						||
 *    {base.Coord} cSun - selenographic longitude, latitude of the Sun.
 | 
						||
 */
 | 
						||
function physical (jde, earth) {
 | 
						||
  const { lon, lat, range } = moonposition["default"].position(jde); // (λ without nutation)
 | 
						||
  // [λ, β, Δ]
 | 
						||
  const m = new Moon(jde);
 | 
						||
  const [l, b] = m.lib(lon, lat);
 | 
						||
  const P = m.pa(lon, lat, b);
 | 
						||
  const [l0, b0] = m.sun(lon, lat, range, earth);
 | 
						||
  const cMoon = new base["default"].Coord(l, b);
 | 
						||
  const cSun = new base["default"].Coord(l0, b0);
 | 
						||
  return [cMoon, P, cSun]
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * Quantities computed for a jde and used in computing return values of
 | 
						||
 * physical().  Computations are broken into several methods to organize
 | 
						||
 * the code.
 | 
						||
 */
 | 
						||
class Moon {
 | 
						||
  constructor (jde) {
 | 
						||
    this.jde = jde;
 | 
						||
    // Δψ, F, Ω, p. 372.0
 | 
						||
    const [Δψ, Δε] = nutation["default"].nutation(jde);
 | 
						||
    this.Δψ = Δψ;
 | 
						||
    const T = base["default"].J2000Century(jde);
 | 
						||
    const F = this.F = base["default"].horner(T, 93.272095 * D2R, 483202.0175233 * D2R, -0.0036539 * D2R, -D2R / 3526000, D2R / 863310000);
 | 
						||
    this.Ω = base["default"].horner(T, 125.0445479 * D2R, -1934.1362891 * D2R, 0.0020754 * D2R,
 | 
						||
      D2R / 467441, -D2R / 60616000);
 | 
						||
    // true ecliptic
 | 
						||
    this.ε = nutation["default"].meanObliquity(jde) + Δε;
 | 
						||
    this.sε = sin(this.ε);
 | 
						||
    this.cε = cos(this.ε);
 | 
						||
    // ρ, σ, τ, p. 372,373
 | 
						||
    const D = base["default"].horner(T, 297.8501921 * D2R, 445267.1114034 * D2R, -0.0018819 * D2R, D2R / 545868, -D2R / 113065000);
 | 
						||
    const M = base["default"].horner(T, 357.5291092 * D2R, 35999.0502909 * D2R, -0.0001536 * D2R, D2R / 24490000);
 | 
						||
    const M_ = base["default"].horner(T, 134.9633964 * D2R, 477198.8675055 * D2R,
 | 
						||
      0.0087414 * D2R, D2R / 69699, -D2R / 14712000);
 | 
						||
    const E = base["default"].horner(T, 1, -0.002516, -0.0000074);
 | 
						||
    const K1 = 119.75 * D2R + 131.849 * D2R * T;
 | 
						||
    const K2 = 72.56 * D2R + 20.186 * D2R * T;
 | 
						||
    this.ρ = -0.02752 * D2R * cos(M_) +
 | 
						||
      -0.02245 * D2R * sin(F) +
 | 
						||
      0.00684 * D2R * cos(M_ - 2 * F) +
 | 
						||
      -0.00293 * D2R * cos(2 * F) +
 | 
						||
      -0.00085 * D2R * cos(2 * (F - D)) +
 | 
						||
      -0.00054 * D2R * cos(M_ - 2 * D) +
 | 
						||
      -0.0002 * D2R * sin(M_ + F) +
 | 
						||
      -0.0002 * D2R * cos(M_ + 2 * F) +
 | 
						||
      -0.0002 * D2R * cos(M_ - F) +
 | 
						||
      0.00014 * D2R * cos(M_ + 2 * (F - D));
 | 
						||
    this.σ = -0.02816 * D2R * sin(M_) +
 | 
						||
      0.02244 * D2R * cos(F) +
 | 
						||
      -0.00682 * D2R * sin(M_ - 2 * F) +
 | 
						||
      -0.00279 * D2R * sin(2 * F) +
 | 
						||
      -0.00083 * D2R * sin(2 * (F - D)) +
 | 
						||
      0.00069 * D2R * sin(M_ - 2 * D) +
 | 
						||
      0.0004 * D2R * cos(M_ + F) +
 | 
						||
      -0.00025 * D2R * sin(2 * M_) +
 | 
						||
      -0.00023 * D2R * sin(M_ + 2 * F) +
 | 
						||
      0.0002 * D2R * cos(M_ - F) +
 | 
						||
      0.00019 * D2R * sin(M_ - F) +
 | 
						||
      0.00013 * D2R * sin(M_ + 2 * (F - D)) +
 | 
						||
      -0.0001 * D2R * cos(M_ - 3 * F);
 | 
						||
    this.τ = 0.0252 * D2R * sin(M) * E +
 | 
						||
      0.00473 * D2R * sin(2 * (M_ - F)) +
 | 
						||
      -0.00467 * D2R * sin(M_) +
 | 
						||
      0.00396 * D2R * sin(K1) +
 | 
						||
      0.00276 * D2R * sin(2 * (M_ - D)) +
 | 
						||
      0.00196 * D2R * sin(this.Ω) +
 | 
						||
      -0.00183 * D2R * cos(M_ - F) +
 | 
						||
      0.00115 * D2R * sin(M_ - 2 * D) +
 | 
						||
      -0.00096 * D2R * sin(M_ - D) +
 | 
						||
      0.00046 * D2R * sin(2 * (F - D)) +
 | 
						||
      -0.00039 * D2R * sin(M_ - F) +
 | 
						||
      -0.00032 * D2R * sin(M_ - M - D) +
 | 
						||
      0.00027 * D2R * sin(2 * (M_ - D) - M) +
 | 
						||
      0.00023 * D2R * sin(K2) +
 | 
						||
      -0.00014 * D2R * sin(2 * D) +
 | 
						||
      0.00014 * D2R * cos(2 * (M_ - F)) +
 | 
						||
      -0.00012 * D2R * sin(M_ - 2 * F) +
 | 
						||
      -0.00012 * D2R * sin(2 * M_) +
 | 
						||
      0.00011 * D2R * sin(2 * (M_ - M - D));
 | 
						||
  }
 | 
						||
 | 
						||
  /**
 | 
						||
   * lib() curiously serves for computing both librations and solar coordinates,
 | 
						||
   * depending on the coordinates λ, β passed in.  Quantity A not described in
 | 
						||
   * the book, but clearly depends on the λ, β of the current context and so
 | 
						||
   * does not belong in the moon struct.  Instead just return it from optical
 | 
						||
   * and pass it along to physical.
 | 
						||
   */
 | 
						||
  lib (λ, β) {
 | 
						||
    const [l_, b_, A] = this.optical(λ, β);
 | 
						||
    const [l$, b$] = this.physical(A, b_);
 | 
						||
    let l = l_ + l$;
 | 
						||
    if (l > Math.PI) {
 | 
						||
      l -= 2 * Math.PI;
 | 
						||
    }
 | 
						||
    const b = b_ + b$;
 | 
						||
    return [l, b]
 | 
						||
  }
 | 
						||
 | 
						||
  optical (λ, β) {
 | 
						||
    // (53.1) p. 372
 | 
						||
    const W = λ - this.Ω; // (λ without nutation)
 | 
						||
    const [sW, cW] = base["default"].sincos(W);
 | 
						||
    const [sβ, cβ] = base["default"].sincos(β);
 | 
						||
    const A = atan2(sW * cβ * cI - sβ * sI, cW * cβ);
 | 
						||
    const l_ = base["default"].pmod(A - this.F, 2 * Math.PI);
 | 
						||
    const b_ = asin(-sW * cβ * sI - sβ * cI);
 | 
						||
    return [l_, b_, A]
 | 
						||
  }
 | 
						||
 | 
						||
  physical (A, b_) {
 | 
						||
    // (53.2) p. 373
 | 
						||
    const [sA, cA] = base["default"].sincos(A);
 | 
						||
    const l$ = -this.τ + (this.ρ * cA + this.σ * sA) * Math.tan(b_);
 | 
						||
    const b$ = this.σ * cA - this.ρ * sA;
 | 
						||
    return [l$, b$]
 | 
						||
  }
 | 
						||
 | 
						||
  pa (λ, β, b) {
 | 
						||
    const V = this.Ω + this.Δψ + this.σ / sI;
 | 
						||
    const [sV, cV] = base["default"].sincos(V);
 | 
						||
    const [sIρ, cIρ] = base["default"].sincos(_I + this.ρ);
 | 
						||
    const X = sIρ * sV;
 | 
						||
    const Y = sIρ * cV * this.cε - cIρ * this.sε;
 | 
						||
    const ω = Math.atan2(X, Y);
 | 
						||
    const ecl = new coord["default"].Ecliptic(λ + this.Δψ, β).toEquatorial(this.ε); // eslint-disable-line no-unused-vars
 | 
						||
    let P = asin(Math.hypot(X, Y) * cos(ecl.ra - ω) / cos(b));
 | 
						||
    if (P < 0) {
 | 
						||
      P += 2 * Math.PI;
 | 
						||
    }
 | 
						||
    return P
 | 
						||
  }
 | 
						||
 | 
						||
  sun (λ, β, Δ, earth) {
 | 
						||
    const { lon, lat, range } = solar["default"].apparentVSOP87(earth, this.jde); // eslint-disable-line no-unused-vars
 | 
						||
    const ΔR = Δ / (range * base["default"].AU);
 | 
						||
    const λH = lon + Math.PI + 57.296 * D2R * ΔR * cos(β) * sin(lon - λ);
 | 
						||
    const βH = ΔR * β;
 | 
						||
    return this.lib(λH, βH)
 | 
						||
  }
 | 
						||
}
 | 
						||
 | 
						||
/* commented out for lack of test data
 | 
						||
export function Topocentric (jde, ρsφ_, ρcφ_, L) { // (jde, ρsφ_, ρcφ_, L float64)  (l, b, P float64)
 | 
						||
  λ, β, Δ := moonposition.Position(jde) // (λ without nutation)
 | 
						||
  Δψ, Δε := nutation.Nutation(jde)
 | 
						||
  sε, cε := base.sincos(nutation.MeanObliquity(jde) + Δε)
 | 
						||
  α, δ := coord.EclToEq(λ+Δψ, β, sε, cε)
 | 
						||
  α, δ = parallax.Topocentric(α, δ, Δ/base.AU, ρsφ_, ρcφ_, L, jde)
 | 
						||
  λ, β = coord.EqToEcl(α, δ, sε, cε)
 | 
						||
  const m = newMoon(jde)
 | 
						||
  l, b = m.lib(λ, β)
 | 
						||
  P = m.pa(λ, β, b)
 | 
						||
  return
 | 
						||
}
 | 
						||
 | 
						||
export function TopocentricCorrections (jde, b, P, φ, δ, H, π) { // (jde, b, P, φ, δ, H, π float64)  (Δl, Δb, ΔP float64)
 | 
						||
  sφ, cφ := base.sincos(φ)
 | 
						||
  sH, cH := base.sincos(H)
 | 
						||
  sδ, cδ := base.sincos(δ)
 | 
						||
  const Q = Math.atan(cφ * sH / (cδ*sφ - sδ*cφ*cH))
 | 
						||
  const z = Math.acos(sδ*sφ + cδ*cφ*cH)
 | 
						||
  const π_ = π * (sin(z) + 0.0084*sin(2*z))
 | 
						||
  sQP, cQP := base.sincos(Q - P)
 | 
						||
  Δl = -π_ * sQP / cos(b)
 | 
						||
  Δb = π_ * cQP
 | 
						||
  ΔP = Δl*sin(b+Δb) - π_*sin(Q)*Math.tan(δ)
 | 
						||
  return
 | 
						||
}
 | 
						||
*/
 | 
						||
 | 
						||
/**
 | 
						||
 * SunAltitude returns altitude of the Sun above the lunar horizon.
 | 
						||
 *
 | 
						||
 * @param {Coord} cOnMoon - selenographic longitude and latitude of a site on the Moon
 | 
						||
 * @param {Coord} cSun - selenographic coordinates of the Sun (as returned by physical(), for example.)
 | 
						||
 * @return altitude in radians.
 | 
						||
 */
 | 
						||
function sunAltitude (cOnMoon, cSun) { // (η, θ, l0, b0 float64)  float64
 | 
						||
  const c0 = Math.PI / 2 - cSun.lon;
 | 
						||
  const [sb0, cb0] = base["default"].sincos(cSun.lat);
 | 
						||
  const [sθ, cθ] = base["default"].sincos(cOnMoon.lat);
 | 
						||
  return asin(sb0 * sθ + cb0 * cθ * sin(c0 + cOnMoon.lon))
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * Sunrise returns time of sunrise for a point on the Moon near the given date.
 | 
						||
 *
 | 
						||
 * @param {Coord} cOnMoon - selenographic longitude and latitude of a site on the Moon
 | 
						||
 * @param {Number} jde - Julian ephemeris day
 | 
						||
 * @param {Planet} earth - VSOP87 Planet Earth
 | 
						||
 * @return time of sunrise as a jde nearest the given jde.
 | 
						||
 */
 | 
						||
function sunrise (cOnMoon, jde, earth) { // (η, θ, jde float64, earth *pp.V87Planet)  float64
 | 
						||
  jde -= srCorr(cOnMoon, jde, earth);
 | 
						||
  return jde - srCorr(cOnMoon, jde, earth)
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * Sunset returns time of sunset for a point on the Moon near the given date.
 | 
						||
 *
 | 
						||
 * @param {Coord} cOnMoon - selenographic longitude and latitude of a site on the Moon
 | 
						||
 * @param {Number} jde - Julian ephemeris day
 | 
						||
 * @param {Planet} earth - VSOP87 Planet Earth
 | 
						||
 * @return time of sunset as a jde nearest the given jde.
 | 
						||
 */
 | 
						||
function sunset (cOnMoon, jde, earth) { // (η, θ, jde float64, earth *pp.V87Planet)  float64
 | 
						||
  jde += srCorr(cOnMoon, jde, earth);
 | 
						||
  return jde + srCorr(cOnMoon, jde, earth)
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * @private
 | 
						||
 */
 | 
						||
function srCorr (cOnMoon, jde, earth) {
 | 
						||
  const phy = physical(jde, earth);
 | 
						||
  const h = sunAltitude(cOnMoon, phy[2]);
 | 
						||
  return h / (12.19075 * D2R * cos(cOnMoon.lat))
 | 
						||
}
 | 
						||
 | 
						||
const lunarCoord = (η, θ) => new base["default"].Coord(η * D2R, θ * D2R);
 | 
						||
/**
 | 
						||
 * selenographic coordinates of some lunar features
 | 
						||
 * Table 53.A
 | 
						||
 */
 | 
						||
const selenographic = {
 | 
						||
  archimedes: lunarCoord(-3.9, 29.7),
 | 
						||
  aristarchus: lunarCoord(-47.5, 23.7),
 | 
						||
  aristillus: lunarCoord(1.2, 33.9),
 | 
						||
  aristoteles: lunarCoord(17.3, 50.1),
 | 
						||
  arzachel: lunarCoord(-1.9, -17.7),
 | 
						||
  autolycus: lunarCoord(1.5, 30.7),
 | 
						||
  billy: lunarCoord(-50, -13.8),
 | 
						||
  birt: lunarCoord(-8.5, -22.3),
 | 
						||
  campanus: lunarCoord(-27.7, -28),
 | 
						||
  censorinus: lunarCoord(32.7, -0.4),
 | 
						||
  clavius: lunarCoord(-14, -58),
 | 
						||
  copernicus: lunarCoord(-20, 9.7),
 | 
						||
  delambre: lunarCoord(17.5, -1.9),
 | 
						||
  dionysius: lunarCoord(17.3, 2.8),
 | 
						||
  endymion: lunarCoord(56.4, 53.6),
 | 
						||
  eratosthenes: lunarCoord(-11.3, 14.5),
 | 
						||
  eudoxus: lunarCoord(16.3, 44.3),
 | 
						||
  fracastorius: lunarCoord(33.2, -21),
 | 
						||
  fraMauro: lunarCoord(-17, -6),
 | 
						||
  gassendi: lunarCoord(-39.9, -17.5),
 | 
						||
  goclenius: lunarCoord(45, -10.1),
 | 
						||
  grimaldi: lunarCoord(-68.5, -5.8),
 | 
						||
  harpalus: lunarCoord(-43.4, 52.6),
 | 
						||
  horrocks: lunarCoord(5.9, -4),
 | 
						||
  kepler: lunarCoord(-38, 8.1),
 | 
						||
  langrenus: lunarCoord(60.9, -8.9),
 | 
						||
  lansberg: lunarCoord(-26.6, -0.3),
 | 
						||
  letronne: lunarCoord(-43, -10),
 | 
						||
  macrobius: lunarCoord(46, 21.2),
 | 
						||
  manilius: lunarCoord(9.1, 14.5),
 | 
						||
  menelaus: lunarCoord(16, 16.3),
 | 
						||
  messier: lunarCoord(47.6, -1.9),
 | 
						||
  petavius: lunarCoord(61, -25),
 | 
						||
  pico: lunarCoord(-8.8, 45.8),
 | 
						||
  pitatus: lunarCoord(-13.5, -29.8),
 | 
						||
  piton: lunarCoord(-0.8, 40.8),
 | 
						||
  plato: lunarCoord(-9.2, 51.4),
 | 
						||
  plinius: lunarCoord(23.6, 15.3),
 | 
						||
  posidonius: lunarCoord(30, 31.9),
 | 
						||
  proclus: lunarCoord(46.9, 16.1),
 | 
						||
  ptolemeusA: lunarCoord(-0.8, -8.5),
 | 
						||
  pytheas: lunarCoord(-20.6, 20.5),
 | 
						||
  reinhold: lunarCoord(-22.8, 3.2),
 | 
						||
  riccioli: lunarCoord(-74.3, -3.2),
 | 
						||
  schickard: lunarCoord(-54.5, -44),
 | 
						||
  schiller: lunarCoord(-39, -52),
 | 
						||
  tauruntius: lunarCoord(46.5, 5.6),
 | 
						||
  theophilus: lunarCoord(26.5, -11.4),
 | 
						||
  timocharis: lunarCoord(-13.1, 26.7),
 | 
						||
  tycho: lunarCoord(-11, -43.2),
 | 
						||
  vitruvius: lunarCoord(31.3, 17.6),
 | 
						||
  walter: lunarCoord(1, -33)
 | 
						||
};
 | 
						||
 | 
						||
var moon = {
 | 
						||
  physical,
 | 
						||
  Moon,
 | 
						||
  // Topocentric,
 | 
						||
  // TopocentricCorrections,
 | 
						||
  sunAltitude,
 | 
						||
  sunrise,
 | 
						||
  sunset,
 | 
						||
  selenographic
 | 
						||
};
 | 
						||
 | 
						||
exports.Moon = Moon;
 | 
						||
exports["default"] = moon;
 | 
						||
exports.physical = physical;
 | 
						||
exports.selenographic = selenographic;
 | 
						||
exports.sunAltitude = sunAltitude;
 | 
						||
exports.sunrise = sunrise;
 | 
						||
exports.sunset = sunset;
 |