@tubular/astronomy
Version:
Astronomical calculations for planetary positions, moon phases, eclipses, rise, transit, and set times, and more.
191 lines • 8.3 kB
JavaScript
import { ArrayBufferReader } from '@tubular/array-buffer-reader';
import { DateTime, tdtToUt } from '@tubular/time';
import { Angle, asin_deg, cos_deg, interpolateTabular, limitNeg1to1, sign, sin_deg, sqrt, squared, Unit } from '@tubular/math';
import { JD_J2000 } from './astro-constants';
export var DataQuality;
(function (DataQuality) {
DataQuality[DataQuality["GOOD"] = 1] = "GOOD";
DataQuality[DataQuality["FAIR"] = 2] = "FAIR";
DataQuality[DataQuality["POOR"] = 3] = "POOR";
})(DataQuality || (DataQuality = {}));
export class JupiterInfo {
constructor() {
this.cacheTime = Number.MAX_VALUE;
this.grsLong = JupiterInfo.DEFAULT_GRS_LONG;
}
static readGrsInfo(grsData) {
try {
const reader = new ArrayBufferReader(grsData);
this.preTableGRSDrift = Number(reader.readAnsiLine(true)) / 365.2425; // Convert degrees/year -> degrees/day
this.postTableGRSDrift = Number(reader.readAnsiLine(true)) / 365.2425;
this.interpolationSpan = Number(reader.readAnsiLine(true));
this.grsTimes = [];
this.grsLongs = [];
let line;
while ((line = reader.readAnsiLine(true)) !== null) {
const parts = line.split(/[-,]/);
if (parts.length === 4) {
const Y = parts[0];
const M = parts[1];
const D = parts[2];
const date = `${Y}-${M}-${D}`;
const lon = Number(parts[3]);
const year = Number(Y);
const month = Number(M);
const day = Number(D);
const jd = DateTime.julianDay_SGC(year, month, day, 0, 0, 0);
this.grsTimes.push(jd);
this.grsLongs.push(lon);
if (this.minGRSTableTime === undefined || this.minGRSTableTime > jd) {
this.firstGRSDate = date;
this.minGRSTableTime = jd;
this.grsLongAtMinTime = lon;
}
if (this.maxGRSTableTime === undefined || this.maxGRSTableTime < jd) {
this.lastGRSDate = date;
this.maxGRSTableTime = jd;
this.grsLongAtMaxTime = lon;
}
}
}
this.grsLongAtMaxTimeAngle = new Angle(this.grsLongAtMaxTime, Unit.DEGREES);
this.properlyInitialized = true;
}
catch (error) {
this.properlyInitialized = false;
}
}
static getJupiterInfo(astroDataService) {
if (this.properlyInitialized)
return Promise.resolve(new JupiterInfo());
else if (this.properlyInitialized === false)
return Promise.reject(new Error('Failed to initialize JupiterInfo'));
else {
return astroDataService.getGrsData().then((grsData) => {
this.readGrsInfo(grsData);
return this.getJupiterInfo(astroDataService);
}).catch((reason) => {
this.properlyInitialized = false;
return Promise.reject(new Error('Failed to initialize JupiterInfo: ' + reason));
});
}
}
static grsDataQuality(time_JDU) {
if (!this.properlyInitialized || time_JDU < this.minGRSTableTime - 730 || time_JDU > this.maxGRSTableTime + 730)
return DataQuality.POOR;
else if (time_JDU < this.minGRSTableTime - 365 || time_JDU > this.maxGRSTableTime + 365)
return DataQuality.FAIR;
else
return DataQuality.GOOD;
}
static getFirstGRSDate() {
return this.firstGRSDate;
}
static getLastGRSDate() {
return this.lastGRSDate;
}
static getLastKnownGRSLongitude() {
return this.grsLongAtMaxTimeAngle;
}
getSystemILongitude(time_JDE) {
if (this.cacheTime !== time_JDE) {
this.calculateLongitudes(time_JDE);
this.cacheTime = time_JDE;
}
return this.sys1Long;
}
getSystemIILongitude(time_JDE) {
if (this.cacheTime !== time_JDE) {
this.calculateLongitudes(time_JDE);
this.cacheTime = time_JDE;
}
return this.sys2Long;
}
getGRSLongitude(time_JDE) {
if (this.fixedGRSLong)
return this.fixedGRSLong;
else if (!JupiterInfo.properlyInitialized)
return JupiterInfo.DEFAULT_GRS_LONG;
else if (this.cacheTime !== time_JDE) {
this.calculateLongitudes(time_JDE);
this.cacheTime = time_JDE;
}
return this.grsLong;
}
getGRSCMOffset(time_JDE) {
if (this.cacheTime !== time_JDE) {
this.calculateLongitudes(time_JDE);
this.cacheTime = time_JDE;
}
return this.grsCMOffset;
}
setFixedGRSLongitude(longitude) {
if (typeof longitude === 'number')
this.fixedGRSLong = new Angle(longitude, Unit.DEGREES);
else
this.fixedGRSLong = longitude;
this.cacheTime = Number.MAX_VALUE;
}
getFixedGRSLongitude() {
return this.fixedGRSLong;
}
getEffectiveFixedGRSLongitude() {
if (this.fixedGRSLong)
return this.fixedGRSLong;
else if (JupiterInfo.properlyInitialized && JupiterInfo.minGRSTableTime === JupiterInfo.maxGRSTableTime &&
JupiterInfo.preTableGRSDrift === 0 && JupiterInfo.postTableGRSDrift === 0)
return new Angle(JupiterInfo.grsLongAtMinTime, Unit.DEGREES);
else
return JupiterInfo.DEFAULT_GRS_LONG;
}
clearFixedGRSLongitude() {
this.fixedGRSLong = undefined;
this.cacheTime = Number.MAX_VALUE;
}
calculateLongitudes(time_JDE) {
// This is an implementation of the low-accuracy calculation of Jupiter's
// rotational values from _Astronomical Algorithms, 2nd Ed._ by Jean Meeus,
// pp. 297-298.
const d = time_JDE - JD_J2000;
const V = 172.74 + 0.00111588 * d;
const M = 357.529 + 0.9856003 * d;
const N = 20.020 + 0.0830853 * d + 0.329 * sin_deg(V);
const J = 66.115 + 0.9025179 * d - 0.329 * sin_deg(V);
const A = 1.915 * sin_deg(M) + 0.020 * sin_deg(2 * M);
const B = 5.555 * sin_deg(N) + 0.168 * sin_deg(2 * N);
const K = J + A - B;
const R = 1.00014 - 0.01671 * cos_deg(M) - 0.00014 * cos_deg(2 * M);
const r = 5.20872 - 0.25208 * cos_deg(N) - 0.00611 * cos_deg(2 * N);
const Δ = sqrt(r ** 2 + R ** 2 - 2 * r * R * cos_deg(K));
const ψ = asin_deg(limitNeg1to1(R / Δ * sin_deg(K)));
const ω1 = 210.98 + 877.8169088 * (d - Δ / 173) + ψ - B;
const ω2 = 187.23 + 870.1869088 * (d - Δ / 173) + ψ - B;
const cfp = 57.3 * squared(sin_deg(ψ / 2)) * sign(sin_deg(K));
const cm1 = ω1 + cfp;
const cm2 = ω2 + cfp;
this.sys1Long = new Angle(cm1, Unit.DEGREES);
this.sys2Long = new Angle(cm2, Unit.DEGREES);
// And in addition to the above from Meeus...
if (this.fixedGRSLong)
this.grsLong = this.fixedGRSLong;
else if (JupiterInfo.properlyInitialized) {
let grs;
const time_JDU = tdtToUt(time_JDE);
if (time_JDE < JupiterInfo.minGRSTableTime)
grs = JupiterInfo.grsLongAtMinTime - (JupiterInfo.minGRSTableTime - time_JDU) * JupiterInfo.preTableGRSDrift;
else if (time_JDE > JupiterInfo.maxGRSTableTime)
grs = JupiterInfo.grsLongAtMaxTime + (time_JDU - JupiterInfo.maxGRSTableTime) * JupiterInfo.postTableGRSDrift;
else
grs = interpolateTabular(JupiterInfo.grsTimes, JupiterInfo.grsLongs, time_JDU, JupiterInfo.interpolationSpan);
this.grsLong = new Angle(grs, Unit.DEGREES);
}
else
this.grsLong = JupiterInfo.DEFAULT_GRS_LONG;
this.grsCMOffset = this.sys2Long.subtract(this.grsLong);
}
}
JupiterInfo.properlyInitialized = undefined;
JupiterInfo.grsTimes = [];
JupiterInfo.grsLongs = [];
JupiterInfo.DEFAULT_GRS_LONG = new Angle(-93, Unit.DEGREES);
//# sourceMappingURL=jupiter-info.js.map