astronomia
Version:
An astronomical library
325 lines (301 loc) • 9.24 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var apparent = require('./apparent.cjs');
var base = require('./base.cjs');
var coord = require('./coord.cjs');
var kepler = require('./kepler.cjs');
var nutation = require('./nutation.cjs');
var planetposition = require('./planetposition.cjs');
var solarxyz = require('./solarxyz.cjs');
/**
* @copyright 2013 Sonia Keys
* @copyright 2016 commenthol
* @license MIT
* @module elliptic
*/
/**
* Position returns observed equatorial coordinates of a planet at a given time.
*
* Argument p must be a valid V87Planet object for the observed planet.
* Argument earth must be a valid V87Planet object for Earth.
*
* Results are right ascension and declination, α and δ in radians.
*/
function position (planet, earth, jde) { // (p, earth *pp.V87Planet, jde float64) (α, δ float64)
let x = 0;
let y = 0;
let z = 0;
const posEarth = earth.position(jde);
const [L0, B0, R0] = [posEarth.lon, posEarth.lat, posEarth.range];
const [sB0, cB0] = base["default"].sincos(B0);
const [sL0, cL0] = base["default"].sincos(L0);
function pos (τ = 0) {
const pos = planet.position(jde - τ);
const [L, B, R] = [pos.lon, pos.lat, pos.range];
const [sB, cB] = base["default"].sincos(B);
const [sL, cL] = base["default"].sincos(L);
x = R * cB * cL - R0 * cB0 * cL0;
y = R * cB * sL - R0 * cB0 * sL0;
z = R * sB - R0 * sB0;
}
pos();
const Δ = Math.sqrt(x * x + y * y + z * z); // (33.4) p. 224
const τ = base["default"].lightTime(Δ);
// repeating with jde-τ
pos(τ);
let λ = Math.atan2(y, x); // (33.1) p. 223
let β = Math.atan2(z, Math.hypot(x, y)); // (33.2) p. 223
const [Δλ, Δβ] = apparent["default"].eclipticAberration(λ, β, jde);
const fk5 = planetposition["default"].toFK5(λ + Δλ, β + Δβ, jde);
λ = fk5.lon;
β = fk5.lat;
const [Δψ, Δε] = nutation["default"].nutation(jde);
λ += Δψ;
const ε = nutation["default"].meanObliquity(jde) + Δε;
return new coord["default"].Ecliptic(λ, β).toEquatorial(ε)
// Meeus gives a formula for elongation but doesn't spell out how to
// obtaion term λ0 and doesn't give an example solution.
}
/**
* Elements holds keplerian elements.
*/
class Elements {
/*
Axis float64 // Semimajor axis, a, in AU
Ecc float64 // Eccentricity, e
Inc float64 // Inclination, i, in radians
ArgP float64 // Argument of perihelion, ω, in radians
Node float64 // Longitude of ascending node, Ω, in radians
TimeP float64 // Time of perihelion, T, as jde
*/
constructor (axis, ecc, inc, argP, node, timeP) {
let o = {};
if (typeof axis === 'object') {
o = axis;
}
this.axis = o.axis || axis;
this.ecc = o.ecc || ecc;
this.inc = o.inc || inc;
this.argP = o.argP || argP;
this.node = o.node || node;
this.timeP = o.timeP || timeP;
}
/**
* Position returns observed equatorial coordinates of a body with Keplerian elements.
*
* Argument e must be a valid V87Planet object for Earth.
*
* Results are right ascension and declination α and δ, and elongation ψ,
* all in radians.
*/
position (jde, earth) { // (α, δ, ψ float64) {
// (33.6) p. 227
const n = base["default"].K / this.axis / Math.sqrt(this.axis);
const sε = base["default"].SOblJ2000;
const cε = base["default"].COblJ2000;
const [sΩ, cΩ] = base["default"].sincos(this.node);
const [si, ci] = base["default"].sincos(this.inc);
// (33.7) p. 228
const F = cΩ;
const G = sΩ * cε;
const H = sΩ * sε;
const P = -sΩ * ci;
const Q = cΩ * ci * cε - si * sε;
const R = cΩ * ci * sε + si * cε;
// (33.8) p. 229
const A = Math.atan2(F, P);
const B = Math.atan2(G, Q);
const C = Math.atan2(H, R);
const a = Math.hypot(F, P);
const b = Math.hypot(G, Q);
const c = Math.hypot(H, R);
const f = (jde) => { // (x, y, z float64) {
const M = n * (jde - this.timeP);
let E;
try {
E = kepler["default"].kepler2b(this.ecc, M, 15);
} catch (e) {
E = kepler["default"].kepler3(this.ecc, M);
}
const ν = kepler["default"].trueAnomaly(E, this.ecc);
const r = kepler["default"].radius(E, this.ecc, this.axis);
// (33.9) p. 229
const x = r * a * Math.sin(A + this.argP + ν);
const y = r * b * Math.sin(B + this.argP + ν);
const z = r * c * Math.sin(C + this.argP + ν);
return { x, y, z }
};
return astrometricJ2000(f, jde, earth)
}
}
/**
* AstrometricJ2000 is a utility function for computing astrometric coordinates.
*
* It is used internally and only exported so that it can be used from
* multiple packages. It is not otherwise expected to be used.
*
* Argument f is a function that returns J2000 equatorial rectangular
* coodinates of a body.
*
* Results are J2000 right ascention, declination, and elongation.
*/
function astrometricJ2000 (f, jde, earth) { // (f func(float64) (x, y, z float64), jde float64, e *pp.V87Planet) (α, δ, ψ float64)
const sol = solarxyz["default"].positionJ2000(earth, jde);
const [X, Y, Z] = [sol.x, sol.y, sol.z];
let ξ = 0;
let η = 0;
let ζ = 0;
let Δ = 0;
function fn (τ = 0) {
// (33.10) p. 229
const { x, y, z } = f(jde - τ);
ξ = X + x;
η = Y + y;
ζ = Z + z;
Δ = Math.sqrt(ξ * ξ + η * η + ζ * ζ);
}
fn();
const τ = base["default"].lightTime(Δ);
fn(τ);
let α = Math.atan2(η, ξ);
if (α < 0) {
α += 2 * Math.PI;
}
const δ = Math.asin(ζ / Δ);
const R0 = Math.sqrt(X * X + Y * Y + Z * Z);
const ψ = Math.acos((ξ * X + η * Y + ζ * Z) / R0 / Δ);
return new base["default"].Coord(α, δ, undefined, ψ)
}
/**
* Velocity returns instantaneous velocity of a body in elliptical orbit around the Sun.
*
* Argument a is the semimajor axis of the body, r is the instaneous distance
* to the Sun, both in AU.
*
* Result is in Km/sec.
*/
function velocity (a, r) { // (a, r float64) float64
return 42.1219 * Math.sqrt(1 / r - 0.5 / a)
}
/**
* Velocity returns the velocity of a body at aphelion.
*
* Argument a is the semimajor axis of the body in AU, e is eccentricity.
*
* Result is in Km/sec.
*/
function vAphelion (a, e) { // (a, e float64) float64
return 29.7847 * Math.sqrt((1 - e) / (1 + e) / a)
}
/**
* Velocity returns the velocity of a body at perihelion.
*
* Argument a is the semimajor axis of the body in AU, e is eccentricity.
*
* Result is in Km/sec.
*/
function vPerihelion (a, e) { // (a, e float64) float64
return 29.7847 * Math.sqrt((1 + e) / (1 - e) / a)
}
/**
* Length1 returns Ramanujan's approximation for the length of an elliptical
* orbit.
*
* Argument a is semimajor axis, e is eccentricity.
*
* Result is in units used for semimajor axis, typically AU.
*/
function length1 (a, e) { // (a, e float64) float64
const b = a * Math.sqrt(1 - e * e);
return Math.PI * (3 * (a + b) - Math.sqrt((a + 3 * b) * (3 * a + b)))
}
/**
* Length2 returns an alternate approximation for the length of an elliptical
* orbit.
*
* Argument a is semimajor axis, e is eccentricity.
*
* Result is in units used for semimajor axis, typically AU.
*/
function length2 (a, e) { // (a, e float64) float64
const b = a * Math.sqrt(1 - e * e);
const s = a + b;
const p = a * b;
const A = s * 0.5;
const G = Math.sqrt(p);
const H = 2 * p / s;
return Math.PI * (21 * A - 2 * G - 3 * H) * 0.125
}
/**
* Length3 returns the length of an elliptical orbit.
*
* Argument a is semimajor axis, e is eccentricity.
*
* Result is exact, and in units used for semimajor axis, typically AU.
*/
/* As Meeus notes, Length4 converges faster. There is no reason to use
this function
export function length3 (a, e) { // (a, e float64) float64
const sum0 = 1.0
const e2 = e * e
const term = e2 * 0.25
const sum1 = 1.0 - term
const nf = 1.0
const df = 2.0
while (sum1 !== sum0) {
term *= nf
nf += 2
df += 2
term *= nf * e2 / (df * df)
sum0 = sum1
sum1 -= term
}
return 2 * Math.PI * a * sum0
} */
/**
* Length4 returns the length of an elliptical orbit.
*
* Argument a is semimajor axis, e is eccentricity.
*
* Result is exact, and in units used for semimajor axis, typically AU.
*/
function length4 (a, e) { // (a, e float64) float64
const b = a * Math.sqrt(1 - e * e);
const m = (a - b) / (a + b);
const m2 = m * m;
let sum0 = 1.0;
let term = m2 * 0.25;
let sum1 = 1.0 + term;
let nf = -1.0;
let df = 2.0;
while (sum1 !== sum0) {
nf += 2;
df += 2;
term *= nf * nf * m2 / (df * df);
sum0 = sum1;
sum1 += term;
}
return 2 * Math.PI * a * sum0 / (1 + m)
}
var elliptic = {
position,
Elements,
astrometricJ2000,
velocity,
vAphelion,
vPerihelion,
length1,
length2,
// length3,
length4
};
exports.Elements = Elements;
exports.astrometricJ2000 = astrometricJ2000;
exports["default"] = elliptic;
exports.length1 = length1;
exports.length2 = length2;
exports.length4 = length4;
exports.position = position;
exports.vAphelion = vAphelion;
exports.vPerihelion = vPerihelion;
exports.velocity = velocity;