astronomia
Version:
An astronomical library
155 lines (145 loc) • 4.99 kB
JavaScript
/**
* @copyright 2013 Sonia Keys
* @copyright 2016 commenthol
* @license MIT
* @module planetposition
*/
/**
* Planetposition: Chapter 32, Positions of the Planets.
*
* Incomplete:
*
* 1. The package does not implement algorithms that use appendix III,
* but instead implements a full VSOP87 solution. I do not have a copy
* of the supplimentary disk with appendix III in machine readable form
* and as the appendix is rather large, retyping it by hand is problematic.
* The full VSOP87 data set on the other hand is freely downloadable from
* the internet, so I implement here code that can use that data directly.
*
* 2. The formula for accuracy of results is not implemented. It is
* not needed for full VSOP87 solutions.
*
* 3. Polynomial expressions are not implemented. Again, implementation
* would involve typing rather large tables of numbers with associated
* risk of typographical errors.
*/
import base, { Coord } from './base.js' // eslint-disable-line no-unused-vars
import sexa from './sexagesimal.js'
import coord from './coord.js'
import precess from './precess.js'
function sum (t, series) {
const coeffs = []
Object.keys(series).forEach((x) => {
coeffs[x] = 0
let y = series[x].length - 1
for (y; y >= 0; y--) {
const term = {
a: series[x][y][0],
b: series[x][y][1],
c: series[x][y][2]
}
coeffs[x] += term.a * Math.cos(term.b + term.c * t)
}
})
const res = base.horner(t, ...coeffs)
return res
}
export class Planet {
/**
* VSOP87 representation of a Planet
* @constructs Planet
* @param {object} planet - planet data series
* @example
* ```js
* // for use in browser
* import {data} from 'astronomia'
* const earth = new planetposition.Planet(data.vsop87Bearth)
* ```
*/
constructor (planet) {
if (typeof planet !== 'object') throw new TypeError('need planet vsop87 data')
this.name = planet.name
this.type = planet.type || 'B'
this.series = planet
}
/**
* Position2000 returns ecliptic position of planets by full VSOP87 theory.
*
* @param {Number} jde - the date for which positions are desired.
* @returns {Coord} Results are for the dynamical equinox and ecliptic J2000.
* {Number} lon - heliocentric longitude in radians.
* {Number} lat - heliocentric latitude in radians.
* {Number} range - heliocentric range in AU.
*/
position2000 (jde) {
const T = base.J2000Century(jde)
const τ = T * 0.1
const lon = base.pmod(sum(τ, this.series.L), 2 * Math.PI)
const lat = sum(τ, this.series.B)
const range = sum(τ, this.series.R)
switch (this.type) {
case 'B':
return new base.Coord(lon, lat, range)
case 'D': {
const eclFrom = new coord.Ecliptic(lon, lat)
const epochFrom = base.JDEToJulianYear(jde)
const epochTo = 2000.0
const eclTo = precess.eclipticPosition(eclFrom, epochFrom, epochTo)
return new base.Coord(eclTo.lon, eclTo.lat, range)
}
}
}
/**
* Position returns ecliptic position of planets at equinox and ecliptic of date.
*
* @param {Number} jde - the date for which positions are desired.
* @returns {Coord} Results are positions consistent with those from Meeus's
* Apendix III, that is, at equinox and ecliptic of date.
* {Number} lon - heliocentric longitude in radians.
* {Number} lat - heliocentric latitude in radians.
* {Number} range - heliocentric range in AU.
*/
position (jde) {
const T = base.J2000Century(jde)
const τ = T * 0.1
const lon = base.pmod(sum(τ, this.series.L), 2 * Math.PI)
const lat = sum(τ, this.series.B)
const range = sum(τ, this.series.R)
switch (this.type) {
case 'B': {
const eclFrom = new coord.Ecliptic(lon, lat)
const epochFrom = 2000.0
const epochTo = base.JDEToJulianYear(jde)
const eclTo = precess.eclipticPosition(eclFrom, epochFrom, epochTo)
return new base.Coord(eclTo.lon, eclTo.lat, range)
}
case 'D':
return new base.Coord(lon, lat, range)
}
}
}
/**
* ToFK5 converts ecliptic longitude and latitude from dynamical frame to FK5.
*
* @param {Number} lon - ecliptic longitude in radians
* @param {Number} lat - ecliptic latitude in radians
* @param {Number} jde - Julian ephemeris day
* @return {Coord}
* {Number} lon - FK5 longitude
* {Number} lat - FK5 latitude
*/
export function toFK5 (lon, lat, jde) {
// formula 32.3, p. 219.
const T = base.J2000Century(jde)
// const Lp = lon - 1.397 * Math.PI / 180 * T - 0.00031 * Math.PI / 180 * T * T
const Lp = lon - sexa.angleFromDeg((1.397 + 0.00031 * T) * T)
const [sLp, cLp] = base.sincos(Lp)
// (32.3) p. 219
const L5 = lon + sexa.angleFromSec(-0.09033 + 0.03916 * (cLp + sLp) * Math.tan(lat))
const B5 = lat + sexa.angleFromSec(0.03916 * (cLp - sLp))
return new base.Coord(L5, B5)
}
export default {
Planet,
toFK5
}