UNPKG

ephemeris

Version:

JavaScript implementation of Moshier's ephemeris calculations for sun, planets, comets, asteroids and stars.

283 lines (234 loc) 8.98 kB
var aberration = require('./aberration') var altaz = require('./altaz') var constant = require('./constant') var epsilon = require('./epsilon') var gplan = require('./gplan') var lonlat = require('./lonlat') var nutation = require('./nutation') var precess = require('./precess') var util = require('./util') var moshier = { body: require('./body') } var moon = { /** Right Ascension */ ra: 0.0, /** Declination */ dec: 0.0 } /** * Calculate geometric position of the Moon and apply * approximate corrections to find apparent position, * phase of the Moon, etc. for AA.ARC. */ moon.calc = function () { var moonpp = {}, moonpol = {} moshier.body.moon.position = { polar: {}, rect: {} } /** Geometric equatorial coordinates of the earth. */ var re = { longitude: moshier.body.earth.position.rect.longitude, latitude: moshier.body.earth.position.rect.latitude, distance: moshier.body.earth.position.rect.distance } /* Run the orbit calculation twice, at two different times, * in order to find the rate of change of R.A. and Dec. */ /* Calculate for 0.001 day ago */ this.calcll({julian: moshier.body.earth.position.date.julian - 0.001}, moonpp, moonpol) // TDT - 0.001 var ra0 = this.ra var dec0 = this.dec var lon0 = moonpol.longitude /* Calculate for present instant. */ moshier.body.moon.position.nutation = this.calcll(moshier.body.earth.position.date, moonpp, moonpol).nutation moshier.body.moon.position.geometric = { longitude: constant.RTD * moshier.body.moon.position.polar.longitude, latitude: constant.RTD * moshier.body.moon.position.polar.latitude, distance: constant.RTD * moshier.body.moon.position.polar.distance } /* * The rates of change. These are used by altaz () to * correct the time of rising, transit, and setting. */ constant.dradt = this.ra - ra0 if (constant.dradt >= Math.PI) { constant.dradt = constant.dradt - 2 * Math.PI } if (constant.dradt <= -Math.PI) { constant.dradt = constant.dradt + 2 * Math.PI } constant.dradt = 1000 * constant.dradt constant.ddecdt = 1000 * (this.dec - dec0) /* Rate of change in longitude, degrees per day * used for phase of the moon */ lon0 = 1000 * constant.RTD * (moonpol.longitude - lon0) /* Get apparent coordinates for the earth. */ var z = Math.sqrt(re.longitude * re.longitude + re.latitude * re.latitude + re.distance * re.distance ) re.longitude /= z re.latitude /= z re.distance /= z /* aberration of light. */ moshier.body.moon.position.annualAberration = aberration.calc(re) /* pe.longitude -= STR * (20.496/(RTS*pe.distance)); */ precess.calc(re, moshier.body.earth.position.date, -1) nutation.calc(moshier.body.earth.position.date, re) re.longitude *= z re.latitude *= z re.distance *= z var pe = lonlat.calc(re, moshier.body.earth.position.date, false) /* Find sun-moon-earth angles */ var qq = { longitude: re.longitude + moonpp.longitude, latitude: re.latitude + moonpp.latitude, distance: re.distance + moonpp.distance } util.angles(moonpp, qq, re) /* Display answers */ moshier.body.moon.position.apparentGeocentric = { longitude: moonpol.longitude, dLongitude: constant.RTD * moonpol.longitude, latitude: moonpol.latitude, dLatitude: constant.RTD * moonpol.latitude, distance: moonpol.distance / constant.Rearth } moshier.body.moon.position.apparentLongitude = moshier.body.moon.position.apparentGeocentric.dLongitude var dmsLongitude = util.dms(moshier.body.moon.position.apparentGeocentric.longitude) moshier.body.moon.position.apparentLongitudeString = dmsLongitude.degree + '\u00B0' + dmsLongitude.minutes + '\'' + Math.floor(dmsLongitude.seconds) + '"' moshier.body.moon.position.apparentLongitude30String = util.mod30(dmsLongitude.degree) + '\u00B0' + dmsLongitude.minutes + '\'' + Math.floor(dmsLongitude.seconds) + '"' moshier.body.moon.position.geocentricDistance = moonpol.distance / constant.Rearth var x = constant.Rearth / moonpol.distance moshier.body.moon.position.dHorizontalParallax = Math.asin(x) moshier.body.moon.position.horizontalParallax = util.dms(Math.asin(x)) x = 0.272453 * x + 0.0799 / constant.RTS /* AA page L6 */ moshier.body.moon.position.dSemidiameter = x moshier.body.moon.position.Semidiameter = util.dms(x) x = constant.RTD * Math.acos(-constant.ep) /* x = 180.0 - RTD * arcdot (re, pp); */ moshier.body.moon.position.sunElongation = x x = 0.5 * (1 + constant.pq) moshier.body.moon.position.illuminatedFraction = x /* Find phase of the Moon by comparing Moon's longitude * with Earth's longitude. * * The number of days before or past indicated phase is * estimated by assuming the true longitudes change linearly * with time. These rates are estimated for the date, but * do not stay constant. The error can exceed 0.15 day in 4 days. */ x = moonpol.longitude - pe.longitude x = util.modtp(x) * constant.RTD /* difference in longitude */ var y = Math.floor(x / 90) /* number of quarters */ x = x - y * 90 /* phase angle mod 90 degrees */ /* days per degree of phase angle */ z = moonpol.distance / (12.3685 * 0.00257357) if (x > 45) { moshier.body.moon.position.phaseDaysBefore = -(x - 90) * z y = (y + 1) & 3 } else { moshier.body.moon.position.phaseDaysPast = x * z } moshier.body.moon.position.phaseQuarter = y moshier.body.moon.position.apparent = { dRA: this.ra, dDec: this.dec, ra: util.hms(this.ra), dec: util.dms(this.dec) } /* Compute and display topocentric position (altaz.js) */ var pp = { longitude: this.ra, latitude: this.dec, distance: moonpol.distance } moshier.body.moon.position.altaz = altaz.calc(pp, moshier.body.earth.position.date) } /** * Calculate apparent latitude, longitude, and horizontal parallax * of the Moon at Julian date J. */ moon.calcll = function (date, rect, pol) { /* Compute obliquity of the ecliptic, coseps, and sineps. */ epsilon.calc(date) /* Get geometric coordinates of the Moon. */ gplan.moon(date, rect, pol) /* Post the geometric ecliptic longitude and latitude, in radians, * and the radius in au. */ constant.body.position.polar.longitude = pol.longitude constant.body.position.polar.latitude = pol.latitude constant.body.position.polar.distance = pol.distance /* Light time correction to longitude, * about 0.7". */ pol.longitude -= 0.0118 * constant.DTR * constant.Rearth / pol.distance /* convert to equatorial system of date */ var cosB = Math.cos(pol.latitude) var sinB = Math.sin(pol.latitude) var cosL = Math.cos(pol.longitude) var sinL = Math.sin(pol.longitude) rect.longitude = cosB * cosL rect.latitude = epsilon.coseps * cosB * sinL - epsilon.sineps * sinB rect.distance = epsilon.sineps * cosB * sinL + epsilon.coseps * sinB /* Rotate to J2000. */ precess.calc(rect, {julian: moshier.body.earth.position.date.julian}, 1) // TDT /* Find Euclidean vectors and angles between earth, object, and the sun */ var pp = { longitude: rect.longitude * pol.distance, latitude: rect.latitude * pol.distance, distance: rect.distance * pol.distance } var qq = { longitude: moshier.body.earth.position.rect.longitude + pp.longitude, latitude: moshier.body.earth.position.rect.latitude + pp.latitude, distance: moshier.body.earth.position.rect.distance + pp.distance } util.angles(pp, qq, moshier.body.earth.position.rect) /* Make rect a unit vector. */ /* rect.longitude /= EO; */ /* rect.latitude /= EO; */ /* rect.distance /= EO; */ /* Correct position for light deflection. (Ignore.) */ /* relativity(rect, qq, rearth); */ /* Aberration of light. The Astronomical Almanac (Section D, Daily Polynomial Coefficients) seems to omit this, even though the reference ephemeris is inertial. */ /* annuab (rect); */ /* Precess to date. */ precess.calc(rect, {julian: moshier.body.earth.position.date.julian}, -1) // TDT /* Correct for nutation at date TDT. */ var result = { nutation: nutation.calc({julian: moshier.body.earth.position.date.julian}, rect) // TDT } /* Apparent geocentric right ascension and declination. */ this.ra = util.zatan2(rect.longitude, rect.latitude) this.dec = Math.asin(rect.distance) /* For apparent ecliptic coordinates, rotate from the true equator into the ecliptic of date. */ cosL = Math.cos(epsilon.eps + nutation.nuto) sinL = Math.sin(epsilon.eps + nutation.nuto) var y = cosL * rect.latitude + sinL * rect.distance var z = -sinL * rect.latitude + cosL * rect.distance pol.longitude = util.zatan2(rect.longitude, y) pol.latitude = Math.asin(z) /* Restore earth-moon distance. */ rect.longitude *= constant.EO rect.latitude *= constant.EO rect.distance *= constant.EO return result } module.exports = moon