astronomia
Version:
An astronomical library
344 lines (321 loc) • 12.1 kB
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;