astronomy-bundle
Version:
Bundle for astronomical calculations such as position of moon, sun and planets, sunrise, sunset or solar eclipses. Most of the calculations are based on Jean Meeus 'Astronomical Algorithms' book and the VSOP87 theory.
129 lines (128 loc) • 6.84 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTimeLocationCircumstancesC4 = exports.getTimeLocationCircumstancesC3 = exports.getTimeLocationCircumstancesC2 = exports.getTimeLocationCircumstancesC1 = exports.getTimeLocationCircumstancesMaxEclipse = void 0;
const math_1 = require("../../utils/math");
const solarEclipseEvents_1 = require("../constants/solarEclipseEvents");
const solarEclipseTypes_1 = require("../constants/solarEclipseTypes");
const circumstancesCalc_1 = require("./circumstancesCalc");
const observationalCircumstancesCalc_1 = require("./observationalCircumstancesCalc");
function getTimeLocationCircumstancesMaxEclipse(besselianElements, location) {
const circumstances = iterateCircumstancesMax(besselianElements, location);
validateCircumstances(circumstances, location, solarEclipseEvents_1.SolarEclipseEventType.Mid);
return circumstances;
}
exports.getTimeLocationCircumstancesMaxEclipse = getTimeLocationCircumstancesMaxEclipse;
function getTimeLocationCircumstancesC1(besselianElements, location) {
const circumstances = iterateCircumstancesMax(besselianElements, location);
validateCircumstances(circumstances, location, solarEclipseEvents_1.SolarEclipseEventType.C1);
return iterateCircumstancesForContact(besselianElements, location, solarEclipseEvents_1.SolarEclipseEventType.C1);
}
exports.getTimeLocationCircumstancesC1 = getTimeLocationCircumstancesC1;
function getTimeLocationCircumstancesC2(besselianElements, location) {
const circumstances = iterateCircumstancesMax(besselianElements, location);
validateCircumstances(circumstances, location, solarEclipseEvents_1.SolarEclipseEventType.C2);
return iterateCircumstancesForContact(besselianElements, location, solarEclipseEvents_1.SolarEclipseEventType.C2);
}
exports.getTimeLocationCircumstancesC2 = getTimeLocationCircumstancesC2;
function getTimeLocationCircumstancesC3(besselianElements, location) {
const circumstances = iterateCircumstancesMax(besselianElements, location);
validateCircumstances(circumstances, location, solarEclipseEvents_1.SolarEclipseEventType.C3);
return iterateCircumstancesForContact(besselianElements, location, solarEclipseEvents_1.SolarEclipseEventType.C3);
}
exports.getTimeLocationCircumstancesC3 = getTimeLocationCircumstancesC3;
function getTimeLocationCircumstancesC4(besselianElements, location) {
const circumstances = iterateCircumstancesMax(besselianElements, location);
validateCircumstances(circumstances, location, solarEclipseEvents_1.SolarEclipseEventType.C4);
return iterateCircumstancesForContact(besselianElements, location, solarEclipseEvents_1.SolarEclipseEventType.C4);
}
exports.getTimeLocationCircumstancesC4 = getTimeLocationCircumstancesC4;
function iterateCircumstancesMax(besselianElements, location) {
let t = 0;
let tau = 1;
let cnt = 0;
let circumstances = (0, circumstancesCalc_1.getTimeLocationCircumstances)(besselianElements, location, t);
while (Math.abs(tau) > 0.000001 && cnt < 50) {
const { u, v, a, b, n2 } = circumstances;
tau = (u * a + v * b) / n2;
t -= tau;
circumstances = (0, circumstancesCalc_1.getTimeLocationCircumstances)(besselianElements, location, t);
cnt++;
}
return circumstances;
}
function iterateCircumstancesForContact(besselianElements, location, eventType) {
const circumstancesMax = getTimeLocationCircumstancesMaxEclipse(besselianElements, location);
let t = getTForContacts(circumstancesMax, eventType);
const sign = getSign(circumstancesMax, eventType);
let circumstances = (0, circumstancesCalc_1.getTimeLocationCircumstances)(besselianElements, location, t);
let tau = 1;
let cnt = 0;
while (Math.abs(tau) > 0.000001 && cnt < 50) {
const { u, v, a, b, n2 } = circumstances;
const lParamDerived = getLDerived(circumstances, eventType);
const n = Math.sqrt(n2);
tau = (v * a - u * b) / (n * lParamDerived);
if (Math.abs(tau) <= 1.0) {
tau = sign * Math.sqrt(1.0 - Math.pow(tau, 2)) * lParamDerived / n;
}
else {
tau = 0.0;
}
t -= (u * a + v * b) / n2 - tau;
circumstances = (0, circumstancesCalc_1.getTimeLocationCircumstances)(besselianElements, location, t);
cnt++;
}
return circumstances;
}
function getTForContacts(circumstancesMax, eventType) {
const { t, l2Derived } = circumstancesMax;
const tauD = getTauForEclipseContacts(circumstancesMax, eventType);
if (eventType === solarEclipseEvents_1.SolarEclipseEventType.C2 || eventType === solarEclipseEvents_1.SolarEclipseEventType.C3) {
if (l2Derived < 0.0) {
return t + tauD;
}
}
return t - tauD;
}
function getTauForEclipseContacts(circumstancesMax, eventType) {
const { u, v, a, b, n2 } = circumstancesMax;
const lDerived = getLDerived(circumstancesMax, eventType);
const n = Math.sqrt(n2);
const tau = (v * a - u * b) / (n * lDerived);
if (Math.abs(tau) > 1.0) {
return 0.0;
}
return Math.sqrt(1.0 - Math.pow(tau, 2)) * lDerived / n;
}
function getSign(circumstancesMax, eventType) {
const sign = eventType === solarEclipseEvents_1.SolarEclipseEventType.C1 || eventType === solarEclipseEvents_1.SolarEclipseEventType.C2 ? -1 : 1;
if (eventType === solarEclipseEvents_1.SolarEclipseEventType.C2 || eventType === solarEclipseEvents_1.SolarEclipseEventType.C3) {
const { l2Derived } = circumstancesMax;
if (l2Derived < 0.0) {
return -1 * sign;
}
}
return sign;
}
function getLDerived(circumstances, eventType) {
const { l1Derived, l2Derived } = circumstances;
if (eventType === solarEclipseEvents_1.SolarEclipseEventType.C1 || eventType === solarEclipseEvents_1.SolarEclipseEventType.C4) {
return l1Derived;
}
return l2Derived;
}
function validateCircumstances(circumstances, location, eventType) {
const { lat, lon } = location;
const eclipseType = (0, observationalCircumstancesCalc_1.getEclipseType)(circumstances);
if (eclipseType === solarEclipseTypes_1.SolarEclipseType.None) {
throw new Error(`No eclipse visible at ${(0, math_1.round)(lat, 5)}, ${(0, math_1.round)(lon, 5)}`);
}
if (eclipseType === solarEclipseTypes_1.SolarEclipseType.Partial) {
if (eventType === solarEclipseEvents_1.SolarEclipseEventType.C2) {
throw new Error(`No C2 possible. Eclipse is only partial at ${(0, math_1.round)(lat, 5)}, ${(0, math_1.round)(lon, 5)}`);
}
if (eventType === solarEclipseEvents_1.SolarEclipseEventType.C3) {
throw new Error(`No C3 possible. Eclipse is only partial at ${(0, math_1.round)(lat, 5)}, ${(0, math_1.round)(lon, 5)}`);
}
}
}