From 098eb3ac7a7288647fc3998163b42dfbd15a3e26 Mon Sep 17 00:00:00 2001 From: Don Cross Date: Wed, 23 Nov 2022 11:16:56 -0500 Subject: [PATCH] Optimized HelioDistance for user-defined stars. Because we instantly know the heliocentric distance of a user-defined star, there is no need to convert it into a vector and then take the length of the vector. All of the HelioDistance functions now return the distance directly, as an optimization. Also, I decided it didn't make sense to have a default definition for user-defined stars. If the caller doesn't define a star, it should be treated as an invalid body. --- README.md | 2 +- demo/browser/astronomy.browser.js | 58 ++-- demo/nodejs/astronomy.js | 58 ++-- demo/nodejs/calendar/astronomy.ts | 67 ++-- demo/python/astronomy.py | 58 ++-- generate/template/astronomy.c | 79 +++-- generate/template/astronomy.cs | 47 ++- generate/template/astronomy.kt | 34 +- generate/template/astronomy.py | 58 ++-- generate/template/astronomy.ts | 67 ++-- source/c/README.md | 4 +- source/c/astronomy.c | 79 +++-- source/csharp/README.md | 8 +- source/csharp/astronomy.cs | 47 ++- source/js/README.md | 8 +- source/js/astronomy.browser.js | 58 ++-- source/js/astronomy.browser.min.js | 312 +++++++++--------- source/js/astronomy.d.ts | 8 +- source/js/astronomy.js | 58 ++-- source/js/astronomy.min.js | 10 +- source/js/astronomy.ts | 67 ++-- source/js/esm/astronomy.js | 58 ++-- source/kotlin/doc/define-star.md | 2 +- source/kotlin/doc/helio-distance.md | 2 +- .../github/cosinekitty/astronomy/astronomy.kt | 34 +- source/python/README.md | 8 +- source/python/astronomy/astronomy.py | 58 ++-- 27 files changed, 709 insertions(+), 640 deletions(-) diff --git a/README.md b/README.md index 12761a8a..e8cdbdf6 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ of complexity. So I decided to create Astronomy Engine with the following engine - Support JavaScript, C, C#, and Python with the same algorithms, and verify them to produce identical results. (Kotlin support was added in 2022.) - No external dependencies! The code must not require anything outside the standard library for each language. -- Minified JavaScript code less than 120K. (The current size is 119423 bytes.) +- Minified JavaScript code less than 120K. (The current size is 119438 bytes.) - Accuracy always within 1 arcminute of results from NOVAS. - It would be well documented, relatively easy to use, and support a wide variety of common use cases. diff --git a/demo/browser/astronomy.browser.js b/demo/browser/astronomy.browser.js index 9a2fdb9f..4867d7cd 100644 --- a/demo/browser/astronomy.browser.js +++ b/demo/browser/astronomy.browser.js @@ -290,15 +290,23 @@ const StarList = [ ]; ; const StarTable = [ - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, ]; +function GetStar(body) { + const index = StarList.indexOf(body); + return (index >= 0) ? StarTable[index] : null; +} +function UserDefinedStar(body) { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -307,10 +315,8 @@ const StarTable = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -332,8 +338,8 @@ const StarTable = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ function DefineStar(body, ra, dec, distanceLightYears) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body); + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); VerifyNumber(dec); @@ -344,7 +350,9 @@ function DefineStar(body, ra, dec, distanceLightYears) { throw `Invalid declination for star: ${dec}`; if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * exports.AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * exports.AU_PER_LY; } exports.DefineStar = DefineStar; var PrecessDirection; @@ -2483,7 +2491,7 @@ function Horizon(date, observer, ra, dec, refraction) { const coszd = Math.cos(zd * exports.DEG2RAD); const sinzd0 = Math.sin(zd0 * exports.DEG2RAD); const coszd0 = Math.cos(zd0 * exports.DEG2RAD); - var pr = []; + const pr = []; for (let j = 0; j < 3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0) * sinzd + uz[j] * coszd); } @@ -3662,12 +3670,6 @@ exports.JupiterMoons = JupiterMoons; */ function HelioVector(body, date) { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); - return VectorFromSphere(sphere, time); - } if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -3689,6 +3691,11 @@ function HelioVector(body, date) { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; } exports.HelioVector = HelioVector; @@ -3704,7 +3711,7 @@ exports.HelioVector = HelioVector; * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -3713,6 +3720,9 @@ exports.HelioVector = HelioVector; * The heliocentric distance in AU. */ function HelioDistance(body, date) { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -3860,7 +3870,7 @@ class BodyPosition extends PositionFunction { function BackdatePosition(date, observerBody, targetBody, aberration) { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/demo/nodejs/astronomy.js b/demo/nodejs/astronomy.js index ebf23a8d..2e17a42f 100644 --- a/demo/nodejs/astronomy.js +++ b/demo/nodejs/astronomy.js @@ -289,15 +289,23 @@ const StarList = [ ]; ; const StarTable = [ - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, ]; +function GetStar(body) { + const index = StarList.indexOf(body); + return (index >= 0) ? StarTable[index] : null; +} +function UserDefinedStar(body) { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -306,10 +314,8 @@ const StarTable = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -331,8 +337,8 @@ const StarTable = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ function DefineStar(body, ra, dec, distanceLightYears) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body); + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); VerifyNumber(dec); @@ -343,7 +349,9 @@ function DefineStar(body, ra, dec, distanceLightYears) { throw `Invalid declination for star: ${dec}`; if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * exports.AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * exports.AU_PER_LY; } exports.DefineStar = DefineStar; var PrecessDirection; @@ -2482,7 +2490,7 @@ function Horizon(date, observer, ra, dec, refraction) { const coszd = Math.cos(zd * exports.DEG2RAD); const sinzd0 = Math.sin(zd0 * exports.DEG2RAD); const coszd0 = Math.cos(zd0 * exports.DEG2RAD); - var pr = []; + const pr = []; for (let j = 0; j < 3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0) * sinzd + uz[j] * coszd); } @@ -3661,12 +3669,6 @@ exports.JupiterMoons = JupiterMoons; */ function HelioVector(body, date) { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); - return VectorFromSphere(sphere, time); - } if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -3688,6 +3690,11 @@ function HelioVector(body, date) { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; } exports.HelioVector = HelioVector; @@ -3703,7 +3710,7 @@ exports.HelioVector = HelioVector; * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -3712,6 +3719,9 @@ exports.HelioVector = HelioVector; * The heliocentric distance in AU. */ function HelioDistance(body, date) { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -3859,7 +3869,7 @@ class BodyPosition extends PositionFunction { function BackdatePosition(date, observerBody, targetBody, aberration) { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/demo/nodejs/calendar/astronomy.ts b/demo/nodejs/calendar/astronomy.ts index b41761fc..93def0e4 100644 --- a/demo/nodejs/calendar/astronomy.ts +++ b/demo/nodejs/calendar/astronomy.ts @@ -320,32 +320,41 @@ export enum Body { Star8 = 'Star8', } - const StarList = [ Body.Star1, Body.Star2, Body.Star3, Body.Star4, Body.Star5, Body.Star6, Body.Star7, Body.Star8 ]; - interface StarDef { ra: number, // EQJ right ascension dec: number, // EQJ declination dist: number // heliocentric distance in AU }; - const StarTable: StarDef[] = [ - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star1 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star2 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star3 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star4 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star5 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star6 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star7 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star8 + { ra: 0, dec: 0, dist: 0 }, // Body.Star1 + { ra: 0, dec: 0, dist: 0 }, // Body.Star2 + { ra: 0, dec: 0, dist: 0 }, // Body.Star3 + { ra: 0, dec: 0, dist: 0 }, // Body.Star4 + { ra: 0, dec: 0, dist: 0 }, // Body.Star5 + { ra: 0, dec: 0, dist: 0 }, // Body.Star6 + { ra: 0, dec: 0, dist: 0 }, // Body.Star7 + { ra: 0, dec: 0, dist: 0 }, // Body.Star8 ]; +function GetStar(body: Body): StarDef | null { + const index = StarList.indexOf(body); + return (index >= 0) ? StarTable[index] : null; +} + + +function UserDefinedStar(body: Body): StarDef | null { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} + + /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -354,10 +363,8 @@ const StarTable: StarDef[] = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -379,8 +386,8 @@ const StarTable: StarDef[] = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ export function DefineStar(body: Body, ra: number, dec: number, distanceLightYears: number) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body) + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); @@ -396,7 +403,9 @@ export function DefineStar(body: Body, ra: number, dec: number, distanceLightYea if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * AU_PER_LY; } @@ -2707,7 +2716,7 @@ export function Horizon(date: FlexibleDateTime, observer: Observer, ra: number, const coszd = Math.cos(zd * DEG2RAD); const sinzd0 = Math.sin(zd0 * DEG2RAD); const coszd0 = Math.cos(zd0 * DEG2RAD); - var pr = []; + const pr: number[] = []; for (let j=0; j<3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0)*sinzd + uz[j]*coszd); } @@ -4092,13 +4101,6 @@ export function JupiterMoons(date: FlexibleDateTime): JupiterMoonsInfo { export function HelioVector(body: Body, date: FlexibleDateTime): Vector { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15*star.ra, star.dist); - return VectorFromSphere(sphere, time); - } - if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -4120,6 +4122,12 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15*star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; }; @@ -4134,7 +4142,7 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -4143,6 +4151,9 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { * The heliocentric distance in AU. */ export function HelioDistance(body: Body, date: FlexibleDateTime): number { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -4312,7 +4323,7 @@ export function BackdatePosition( ): Vector { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/demo/python/astronomy.py b/demo/python/astronomy.py index 960fcfd6..c2e327f0 100644 --- a/demo/python/astronomy.py +++ b/demo/python/astronomy.py @@ -355,27 +355,23 @@ class Body(enum.Enum): Star8 = 108 class _StarDef: - def __init__(self, ra, dec, dist): - self.ra = ra - self.dec = dec - self.dist = dist + def __init__(self): + self.ra = 0.0 + self.dec = 0.0 + self.dist = 0.0 # signals that the star has not yet been defined -_StarTable = [ - _StarDef(0.0, 0.0, AU_PER_LY), # Star1 - _StarDef(0.0, 0.0, AU_PER_LY), # Star2 - _StarDef(0.0, 0.0, AU_PER_LY), # Star3 - _StarDef(0.0, 0.0, AU_PER_LY), # Star4 - _StarDef(0.0, 0.0, AU_PER_LY), # Star5 - _StarDef(0.0, 0.0, AU_PER_LY), # Star6 - _StarDef(0.0, 0.0, AU_PER_LY), # Star7 - _StarDef(0.0, 0.0, AU_PER_LY), # Star8 -] +_StarTable = [_StarDef() for _ in range(8)] -def _IsUserDefinedStar(body): - return Body.Star1.value <= body.value <= Body.Star8.value +def _GetStar(body): + if Body.Star1.value <= body.value <= Body.Star8.value: + return _StarTable[body.value - Body.Star1.value] + return None -def _GetUserDefinedStar(body): - return _StarTable[body.value - Body.Star1.value] if _IsUserDefinedStar(body) else None +def _UserDefinedStar(body): + star = _GetStar(body) + if star and (star.dist > 0.0): + return star + return None def DefineStar(body, ra, dec, distanceLightYears): """Assign equatorial coordinates to a user-defined star. @@ -385,10 +381,8 @@ def DefineStar(body, ra, dec, distanceLightYears): This function assigns a right ascension, declination, and distance to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. - A star that has not been defined through a call to `DefineStar` - defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - Once defined, the star keeps the given coordinates until - a subsequent call to `DefineStar` replaces the coordinates with new values. + Stars are not valid until defined. Once defined, they retain their + definition until re-defined by another call to `DefineStar`. Parameters ---------- @@ -407,9 +401,9 @@ def DefineStar(body, ra, dec, distanceLightYears): If you don't know the distance to the star, using a large value like 1000 will generally work well. The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. """ - star = _GetUserDefinedStar(body) + star = _GetStar(body) if star is None: - raise Error('Body must be a user-defined star, not {}.'.format(body)) + raise InvalidBodyError(body) if not (0.0 <= ra < 24.0): raise Error('Invalid right ascension: {}'.format(ra)) if not (-90.0 <= dec <= +90.0): @@ -4537,8 +4531,8 @@ def HelioVector(body, time): if body == Body.SSB: return _CalcSolarSystemBarycenter(time) - star = _GetUserDefinedStar(body) - if star is not None: + star = _UserDefinedStar(body) + if star: return VectorFromSphere(Spherical(star.dec, 15.0*star.ra, star.dist), time) raise InvalidBodyError(body) @@ -4557,7 +4551,7 @@ def HelioDistance(body, time): ---------- body : Body A body for which to calculate a heliocentric distance: - the Sun, Moon, or any of the planets. + the Sun, Moon, any of the planets, or a user-defined star. time : Time The date and time for which to calculate the heliocentric distance. @@ -4572,6 +4566,10 @@ def HelioDistance(body, time): if 0 <= body.value < len(_vsop): return _VsopHelioDistance(_vsop[body.value], time) + star = _UserDefinedStar(body) + if star: + return star.dist + return HelioVector(body, time).Length() @@ -4727,7 +4725,7 @@ def BackdatePosition(time, observerBody, targetBody, aberration): Its `t` field holds the time that light left the observed body to arrive at the observer at the observation time. """ - if _IsUserDefinedStar(targetBody): + if _UserDefinedStar(targetBody): # This is a user-defined star, which must be treated as a special case. # First, we assume its heliocentric position does not change with time. # Second, we assume its heliocentric position has already been corrected @@ -4958,7 +4956,7 @@ def HelioState(body, time): time ) - if _IsUserDefinedStar(body): + if _UserDefinedStar(body): vec = HelioVector(body, time) return StateVector(vec.x, vec.y, vec.z, 0.0, 0.0, 0.0, time) @@ -6668,7 +6666,7 @@ def _MaxAltitudeSlope(body, latitude): elif body in [Body.Jupiter, Body.Saturn, Body.Uranus, Body.Neptune, Body.Pluto]: deriv_ra = -0.2 deriv_dec = +0.2 - elif _IsUserDefinedStar(body): + elif _UserDefinedStar(body): # The minimum allowed heliocentric distance of a user-defined star # is one light-year. This can cause a tiny amount of parallax (about 0.001 degrees). # Also, including stellar aberration (22 arcsec = 0.006 degrees), we provide a diff --git a/generate/template/astronomy.c b/generate/template/astronomy.c index e3d004e0..8904d042 100644 --- a/generate/template/astronomy.c +++ b/generate/template/astronomy.c @@ -121,25 +121,19 @@ stardef_t; /** @endcond */ #define NSTARS 8 -static stardef_t StarTable[NSTARS] = -{ - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR1 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR2 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR3 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR4 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR5 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR6 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR7 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR8 -}; +static stardef_t StarTable[NSTARS]; -#define IsUserDefinedStar(body) (((body) >= BODY_STAR1) && ((body) <= BODY_STAR8)) +#define GetStarPointer(body) (((body) >= BODY_STAR1) && ((body) <= BODY_STAR8) ? &StarTable[(body) - BODY_STAR1] : NULL) -static stardef_t *StarDef(astro_body_t body) +static stardef_t *UserDefinedStar(astro_body_t body) { - return IsUserDefinedStar(body) ? &StarTable[body - BODY_STAR1] : NULL; + stardef_t *star = GetStarPointer(body); + if (star != NULL && star->dist > 0.0) + return star; + return NULL; } + /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -148,10 +142,8 @@ static stardef_t *StarDef(astro_body_t body) * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `BODY_STAR1` .. `BODY_STAR8`. * - * A star that has not been defined through a call to `Astronomy_DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `Astronomy_DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `Astronomy_DefineStar`. * * @param body * One of the eight user-defined star identifiers: `BODY_STAR1` .. `BODY_STAR8`. @@ -177,7 +169,7 @@ static stardef_t *StarDef(astro_body_t body) */ astro_status_t Astronomy_DefineStar(astro_body_t body, double ra, double dec, double distanceLightYears) { - stardef_t *star = StarDef(body); + stardef_t *star = GetStarPointer(body); if (star == NULL) return ASTRO_INVALID_BODY; @@ -3747,7 +3739,7 @@ astro_vector_t Astronomy_HelioVector(astro_body_t body, astro_time_t time) body_state_t bstate; stardef_t *star; - star = StarDef(body); + star = UserDefinedStar(body); if (star != NULL) { astro_spherical_t sphere; @@ -3826,7 +3818,8 @@ astro_vector_t Astronomy_HelioVector(astro_body_t body, astro_time_t time) * more efficient than calling #Astronomy_HelioVector followed by #Astronomy_VectorLength. * * @param body - * A body for which to calculate a heliocentric distance: the Sun, Moon, or any of the planets. + * A body for which to calculate a heliocentric distance: + * the Sun, Moon, any of the planets, or a user-defined star. * * @param time * The date and time for which to calculate the heliocentric distance. @@ -3840,6 +3833,15 @@ astro_func_result_t Astronomy_HelioDistance(astro_body_t body, astro_time_t time { astro_vector_t vector; astro_func_result_t result; + stardef_t *star; + + star = UserDefinedStar(body); + if (star != NULL) + { + result.status = ASTRO_SUCCESS; + result.value = star->dist; + return result; + } switch (body) { @@ -4040,7 +4042,7 @@ astro_vector_t Astronomy_BackdatePosition( astro_body_t targetBody, astro_aberration_t aberration) { - if (IsUserDefinedStar(targetBody)) + if (UserDefinedStar(targetBody)) { /* This is a user-defined star, which must be treated as a special case. @@ -4307,7 +4309,7 @@ astro_state_vector_t Astronomy_HelioState(astro_body_t body, astro_time_t time) major_bodies_t bary; body_state_t planet, earth; - if (IsUserDefinedStar(body)) + if (UserDefinedStar(body)) { astro_vector_t vec = Astronomy_HelioVector(body, time); state.x = vec.x; @@ -6752,6 +6754,7 @@ static astro_func_result_t MaxAltitudeSlope(astro_body_t body, double latitude) Conservatively, we round d(RA)/dt down, d(DEC)/dt up. Then calculate the resulting maximum possible altitude change rate. */ + switch (body) { case BODY_MOON: @@ -6793,25 +6796,19 @@ static astro_func_result_t MaxAltitudeSlope(astro_body_t body, double latitude) result.status = ASTRO_EARTH_NOT_ALLOWED; return result; - case BODY_STAR1: - case BODY_STAR2: - case BODY_STAR3: - case BODY_STAR4: - case BODY_STAR5: - case BODY_STAR6: - case BODY_STAR7: - case BODY_STAR8: - /* - The minimum allowed heliocentric distance of a user-defined star - is one light-year. This can cause a tiny amount of parallax (about 0.001 degrees). - Also, including stellar aberration (22 arcsec = 0.006 degrees), we provide a - generous safety buffer of 0.008 degrees. - */ - deriv_ra = -0.008; - deriv_dec = +0.008; - break; - default: + if (UserDefinedStar(body)) + { + /* + The minimum allowed heliocentric distance of a user-defined star + is one light-year. This can cause a tiny amount of parallax (about 0.001 degrees). + Also, including stellar aberration (22 arcsec = 0.006 degrees), we provide a + generous safety buffer of 0.008 degrees. + */ + deriv_ra = -0.008; + deriv_dec = +0.008; + break; + } result.value = NAN; result.status = ASTRO_INVALID_BODY; return result; diff --git a/generate/template/astronomy.cs b/generate/template/astronomy.cs index 19610afb..bcd83d54 100644 --- a/generate/template/astronomy.cs +++ b/generate/template/astronomy.cs @@ -2778,13 +2778,6 @@ $ASTRO_ADDSOL() public double ra; // heliocentric right ascension in EQJ public double dec; // heliocentric declination in EQJ public double dist; // heliocentric distance in AU - - public StarDef() - { - ra = 0.0; - dec = 0.0; - dist = AU_PER_LY; - } }; private static readonly StarDef[] StarTable = InitStarTable(); @@ -2797,11 +2790,17 @@ $ASTRO_ADDSOL() return table; } - private static bool IsUserDefinedStar(Body body) => - (body >= Body.Star1) && (body <= Body.Star8); + private static StarDef GetStar(Body body) => + ((body >= Body.Star1) && (body <= Body.Star8)) ? StarTable[(int)body - (int)Body.Star1] : null; - private static StarDef GetUserDefinedStar(Body body) => - IsUserDefinedStar(body) ? StarTable[(int)body - (int)Body.Star1] : null; + private static StarDef UserDefinedStar(Body body) + { + if (GetStar(body) is StarDef star) + if (star.dist > 0.0) // has the star been defined yet? + return star; + + return null; + } /// /// Assign equatorial coordinates to a user-defined star. @@ -2812,10 +2811,8 @@ $ASTRO_ADDSOL() /// This function assigns a right ascension, declination, and distance /// to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. /// - /// A star that has not been defined through a call to `DefineStar` - /// defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - /// Once defined, the star keeps the given coordinates until - /// a subsequent call to `DefineStar` replaces the coordinates with new values. + /// Stars are not valid until defined. Once defined, they retain their + /// definition until re-defined by another call to `DefineStar`. /// /// /// One of the eight user-defined star identifiers: `Body.Star1`, `Body.Star2`, ..., `Body.Star8`. @@ -2837,9 +2834,7 @@ $ASTRO_ADDSOL() /// public static void DefineStar(Body body, double ra, double dec, double distanceLightYears) { - StarDef star = GetUserDefinedStar(body); - if (star == null) - throw new ArgumentException($"Body must be a user-defined star, not {body}."); + StarDef star = GetStar(body) ?? throw new InvalidBodyException(body); if (!isfinite(ra) || ra < 0.0 || ra >= 24.0) throw new ArgumentException($"Invalid right ascension for star: {ra}"); @@ -4420,9 +4415,6 @@ $ASTRO_IAU_DATA() /// A heliocentric position vector of the center of the given body. public static AstroVector HelioVector(Body body, AstroTime time) { - if (GetUserDefinedStar(body) is StarDef star) - return VectorFromSphere(new Spherical(star.dec, 15*star.ra, star.dist), time); - AstroVector earth, geomoon; switch (body) @@ -4458,6 +4450,8 @@ $ASTRO_IAU_DATA() return CalcSolarSystemBarycenter(time); default: + if (UserDefinedStar(body) is StarDef star) + return VectorFromSphere(new Spherical(star.dec, 15*star.ra, star.dist), time); throw new InvalidBodyException(body); } } @@ -4474,7 +4468,7 @@ $ASTRO_IAU_DATA() /// /// /// A body for which to calculate a heliocentric distance: - /// the Sun, Moon, EMB, SSB, or any of the planets. + /// the Sun, Moon, EMB, SSB, any of the planets, or a user-defined star. /// /// /// The date and time for which to calculate the heliocentric distance. @@ -4500,7 +4494,10 @@ $ASTRO_IAU_DATA() return VsopFormulaCalc(vsop[(int)body].rad, time.tt / DAYS_PER_MILLENNIUM, false); default: - // For non-VSOP objects, fall back to taking the length of the heliocentric vector. + if (UserDefinedStar(body) is StarDef star) + return star.dist; + + // Fall back to taking the length of the heliocentric vector. return HelioVector(body, time).Length(); } } @@ -4649,7 +4646,7 @@ $ASTRO_IAU_DATA() Body targetBody, Aberration aberration) { - if (IsUserDefinedStar(targetBody)) + if (null != UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. @@ -4915,7 +4912,7 @@ $ASTRO_IAU_DATA() ); default: - if (IsUserDefinedStar(body)) + if (null != UserDefinedStar(body)) { AstroVector vec = HelioVector(body, time); return new StateVector(vec.x, vec.y, vec.z, 0.0, 0.0, 0.0, time); diff --git a/generate/template/astronomy.kt b/generate/template/astronomy.kt index 4a479306..15eb9c16 100644 --- a/generate/template/astronomy.kt +++ b/generate/template/astronomy.kt @@ -381,9 +381,9 @@ enum class Body( private class StarDef { - public var ra: Double = 0.0 // heliocentric right ascension in EQJ - public var dec: Double = 0.0 // heliocentric declination in EQJ - public var dist: Double = AU_PER_LY // heliocentric distance in AU + public var ra: Double = 0.0 // heliocentric right ascension in EQJ + public var dec: Double = 0.0 // heliocentric declination in EQJ + public var dist: Double = 0.0 // heliocentric distance in AU } private val starTable = arrayOf( @@ -397,7 +397,7 @@ private val starTable = arrayOf( StarDef() // Star8 ) -private fun getUserDefinedStar(body: Body): StarDef? = +private fun getStar(body: Body): StarDef? = when (body) { Body.Star1 -> starTable[0] Body.Star2 -> starTable[1] @@ -410,8 +410,13 @@ private fun getUserDefinedStar(body: Body): StarDef? = else -> null } -private fun isUserDefinedStar(body: Body): Boolean = - (getUserDefinedStar(body) != null) +private fun userDefinedStar(body: Body): StarDef? { + val star = getStar(body) + return if (star != null && star.dist > 0.0) // has the star been defined? + star + else + null +} /** @@ -422,10 +427,8 @@ private fun isUserDefinedStar(body: Body): Boolean = * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. * - * A star that has not been defined through a call to `defineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `defineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `defineStar`. * * @param body * One of the eight user-defined star identifiers: `Body.Star1`, `Body.Star2`, ..., `Body.Star8`. @@ -446,7 +449,7 @@ private fun isUserDefinedStar(body: Body): Boolean = * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ public fun defineStar(body: Body, ra: Double, dec: Double, distanceLightYears: Double) { - val star = getUserDefinedStar(body) ?: throw InvalidBodyException(body) + val star = getStar(body) ?: throw InvalidBodyException(body) if (!ra.isFinite() || ra < 0.0 || ra >= 24.0) throw IllegalArgumentException("Invalid right ascension: $ra") if (!dec.isFinite() || dec < -90.0 || dec > +90.0) throw IllegalArgumentException("Invalid declination: $dec") if (!distanceLightYears.isFinite() || distanceLightYears < 1.0) throw IllegalArgumentException("Invalid distance: $distanceLightYears") @@ -4835,7 +4838,7 @@ private fun solarSystemBarycenterState(time: Time): StateVector { * @return The heliocentric position vector of the center of the given body. */ fun helioVector(body: Body, time: Time): Vector { - val star = getUserDefinedStar(body) + val star = userDefinedStar(body) if (star != null) return Spherical(star.dec, 15.0*star.ra, star.dist).toVector(time) @@ -4860,7 +4863,7 @@ fun helioVector(body: Body, time: Time): Vector { * * @param body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, EMB, SSB, or any of the planets. + * the Sun, Moon, EMB, SSB, any of the planets, or a user-defined star. * * @param time * The date and time for which to calculate the distance. @@ -4870,6 +4873,9 @@ fun helioVector(body: Body, time: Time): Vector { fun helioDistance(body: Body, time: Time): Double { if (body == Body.Sun) return 0.0 + val star = userDefinedStar(body) + if (star != null) + return star.dist val vm = optionalVsopModel(body) return if (vm != null) vsopDistance(vm, time) @@ -4906,7 +4912,7 @@ fun helioDistance(body: Body, time: Time): Double { * The velocities are expressed in AU/day. */ fun helioState(body: Body, time: Time): StateVector { - if (isUserDefinedStar(body)) { + if (null != userDefinedStar(body)) { val vec = helioVector(body, time) return StateVector(vec.x, vec.y, vec.z, 0.0, 0.0, 0.0, time) } diff --git a/generate/template/astronomy.py b/generate/template/astronomy.py index 887aea47..4e68d224 100644 --- a/generate/template/astronomy.py +++ b/generate/template/astronomy.py @@ -355,27 +355,23 @@ class Body(enum.Enum): Star8 = 108 class _StarDef: - def __init__(self, ra, dec, dist): - self.ra = ra - self.dec = dec - self.dist = dist + def __init__(self): + self.ra = 0.0 + self.dec = 0.0 + self.dist = 0.0 # signals that the star has not yet been defined -_StarTable = [ - _StarDef(0.0, 0.0, AU_PER_LY), # Star1 - _StarDef(0.0, 0.0, AU_PER_LY), # Star2 - _StarDef(0.0, 0.0, AU_PER_LY), # Star3 - _StarDef(0.0, 0.0, AU_PER_LY), # Star4 - _StarDef(0.0, 0.0, AU_PER_LY), # Star5 - _StarDef(0.0, 0.0, AU_PER_LY), # Star6 - _StarDef(0.0, 0.0, AU_PER_LY), # Star7 - _StarDef(0.0, 0.0, AU_PER_LY), # Star8 -] +_StarTable = [_StarDef() for _ in range(8)] -def _IsUserDefinedStar(body): - return Body.Star1.value <= body.value <= Body.Star8.value +def _GetStar(body): + if Body.Star1.value <= body.value <= Body.Star8.value: + return _StarTable[body.value - Body.Star1.value] + return None -def _GetUserDefinedStar(body): - return _StarTable[body.value - Body.Star1.value] if _IsUserDefinedStar(body) else None +def _UserDefinedStar(body): + star = _GetStar(body) + if star and (star.dist > 0.0): + return star + return None def DefineStar(body, ra, dec, distanceLightYears): """Assign equatorial coordinates to a user-defined star. @@ -385,10 +381,8 @@ def DefineStar(body, ra, dec, distanceLightYears): This function assigns a right ascension, declination, and distance to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. - A star that has not been defined through a call to `DefineStar` - defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - Once defined, the star keeps the given coordinates until - a subsequent call to `DefineStar` replaces the coordinates with new values. + Stars are not valid until defined. Once defined, they retain their + definition until re-defined by another call to `DefineStar`. Parameters ---------- @@ -407,9 +401,9 @@ def DefineStar(body, ra, dec, distanceLightYears): If you don't know the distance to the star, using a large value like 1000 will generally work well. The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. """ - star = _GetUserDefinedStar(body) + star = _GetStar(body) if star is None: - raise Error('Body must be a user-defined star, not {}.'.format(body)) + raise InvalidBodyError(body) if not (0.0 <= ra < 24.0): raise Error('Invalid right ascension: {}'.format(ra)) if not (-90.0 <= dec <= +90.0): @@ -2495,8 +2489,8 @@ def HelioVector(body, time): if body == Body.SSB: return _CalcSolarSystemBarycenter(time) - star = _GetUserDefinedStar(body) - if star is not None: + star = _UserDefinedStar(body) + if star: return VectorFromSphere(Spherical(star.dec, 15.0*star.ra, star.dist), time) raise InvalidBodyError(body) @@ -2515,7 +2509,7 @@ def HelioDistance(body, time): ---------- body : Body A body for which to calculate a heliocentric distance: - the Sun, Moon, or any of the planets. + the Sun, Moon, any of the planets, or a user-defined star. time : Time The date and time for which to calculate the heliocentric distance. @@ -2530,6 +2524,10 @@ def HelioDistance(body, time): if 0 <= body.value < len(_vsop): return _VsopHelioDistance(_vsop[body.value], time) + star = _UserDefinedStar(body) + if star: + return star.dist + return HelioVector(body, time).Length() @@ -2685,7 +2683,7 @@ def BackdatePosition(time, observerBody, targetBody, aberration): Its `t` field holds the time that light left the observed body to arrive at the observer at the observation time. """ - if _IsUserDefinedStar(targetBody): + if _UserDefinedStar(targetBody): # This is a user-defined star, which must be treated as a special case. # First, we assume its heliocentric position does not change with time. # Second, we assume its heliocentric position has already been corrected @@ -2916,7 +2914,7 @@ def HelioState(body, time): time ) - if _IsUserDefinedStar(body): + if _UserDefinedStar(body): vec = HelioVector(body, time) return StateVector(vec.x, vec.y, vec.z, 0.0, 0.0, 0.0, time) @@ -4626,7 +4624,7 @@ def _MaxAltitudeSlope(body, latitude): elif body in [Body.Jupiter, Body.Saturn, Body.Uranus, Body.Neptune, Body.Pluto]: deriv_ra = -0.2 deriv_dec = +0.2 - elif _IsUserDefinedStar(body): + elif _UserDefinedStar(body): # The minimum allowed heliocentric distance of a user-defined star # is one light-year. This can cause a tiny amount of parallax (about 0.001 degrees). # Also, including stellar aberration (22 arcsec = 0.006 degrees), we provide a diff --git a/generate/template/astronomy.ts b/generate/template/astronomy.ts index 8fbce5f1..c8b426e6 100644 --- a/generate/template/astronomy.ts +++ b/generate/template/astronomy.ts @@ -320,32 +320,41 @@ export enum Body { Star8 = 'Star8', } - const StarList = [ Body.Star1, Body.Star2, Body.Star3, Body.Star4, Body.Star5, Body.Star6, Body.Star7, Body.Star8 ]; - interface StarDef { ra: number, // EQJ right ascension dec: number, // EQJ declination dist: number // heliocentric distance in AU }; - const StarTable: StarDef[] = [ - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star1 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star2 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star3 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star4 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star5 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star6 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star7 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star8 + { ra: 0, dec: 0, dist: 0 }, // Body.Star1 + { ra: 0, dec: 0, dist: 0 }, // Body.Star2 + { ra: 0, dec: 0, dist: 0 }, // Body.Star3 + { ra: 0, dec: 0, dist: 0 }, // Body.Star4 + { ra: 0, dec: 0, dist: 0 }, // Body.Star5 + { ra: 0, dec: 0, dist: 0 }, // Body.Star6 + { ra: 0, dec: 0, dist: 0 }, // Body.Star7 + { ra: 0, dec: 0, dist: 0 }, // Body.Star8 ]; +function GetStar(body: Body): StarDef | null { + const index = StarList.indexOf(body); + return (index >= 0) ? StarTable[index] : null; +} + + +function UserDefinedStar(body: Body): StarDef | null { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} + + /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -354,10 +363,8 @@ const StarTable: StarDef[] = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -379,8 +386,8 @@ const StarTable: StarDef[] = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ export function DefineStar(body: Body, ra: number, dec: number, distanceLightYears: number) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body) + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); @@ -396,7 +403,9 @@ export function DefineStar(body: Body, ra: number, dec: number, distanceLightYea if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * AU_PER_LY; } @@ -1896,7 +1905,7 @@ export function Horizon(date: FlexibleDateTime, observer: Observer, ra: number, const coszd = Math.cos(zd * DEG2RAD); const sinzd0 = Math.sin(zd0 * DEG2RAD); const coszd0 = Math.cos(zd0 * DEG2RAD); - var pr = []; + const pr: number[] = []; for (let j=0; j<3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0)*sinzd + uz[j]*coszd); } @@ -3086,13 +3095,6 @@ export function JupiterMoons(date: FlexibleDateTime): JupiterMoonsInfo { export function HelioVector(body: Body, date: FlexibleDateTime): Vector { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15*star.ra, star.dist); - return VectorFromSphere(sphere, time); - } - if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -3114,6 +3116,12 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15*star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; }; @@ -3128,7 +3136,7 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -3137,6 +3145,9 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { * The heliocentric distance in AU. */ export function HelioDistance(body: Body, date: FlexibleDateTime): number { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -3306,7 +3317,7 @@ export function BackdatePosition( ): Vector { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/source/c/README.md b/source/c/README.md index a575e777..7daa9574 100644 --- a/source/c/README.md +++ b/source/c/README.md @@ -490,7 +490,7 @@ Uses the computer's system clock to find the current UTC date and time with 1-se Some Astronomy Engine functions allow their `body` parameter to be a user-defined fixed point in the sky, loosely called a "star". This function assigns a right ascension, declination, and distance to one of the eight user-defined stars `BODY_STAR1` .. `BODY_STAR8`. -A star that has not been defined through a call to `Astronomy_DefineStar` defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. Once defined, the star keeps the given coordinates until a subsequent call to `Astronomy_DefineStar` replaces the coordinates with new values. +Stars are not valid until defined. Once defined, they retain their definition until re-defined by another call to `Astronomy_DefineStar`. @@ -1065,7 +1065,7 @@ Given a date and time, this function calculates the distance between the center | Type | Parameter | Description | | --- | --- | --- | -| [`astro_body_t`](#astro_body_t) | `body` | A body for which to calculate a heliocentric distance: the Sun, Moon, or any of the planets. | +| [`astro_body_t`](#astro_body_t) | `body` | A body for which to calculate a heliocentric distance: the Sun, Moon, any of the planets, or a user-defined star. | | [`astro_time_t`](#astro_time_t) | `time` | The date and time for which to calculate the heliocentric distance. | diff --git a/source/c/astronomy.c b/source/c/astronomy.c index 4b44a6a1..2fd96be9 100644 --- a/source/c/astronomy.c +++ b/source/c/astronomy.c @@ -127,25 +127,19 @@ stardef_t; /** @endcond */ #define NSTARS 8 -static stardef_t StarTable[NSTARS] = -{ - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR1 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR2 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR3 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR4 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR5 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR6 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR7 - { 0.0, 0.0, AU_PER_LY }, // BODY_STAR8 -}; +static stardef_t StarTable[NSTARS]; -#define IsUserDefinedStar(body) (((body) >= BODY_STAR1) && ((body) <= BODY_STAR8)) +#define GetStarPointer(body) (((body) >= BODY_STAR1) && ((body) <= BODY_STAR8) ? &StarTable[(body) - BODY_STAR1] : NULL) -static stardef_t *StarDef(astro_body_t body) +static stardef_t *UserDefinedStar(astro_body_t body) { - return IsUserDefinedStar(body) ? &StarTable[body - BODY_STAR1] : NULL; + stardef_t *star = GetStarPointer(body); + if (star != NULL && star->dist > 0.0) + return star; + return NULL; } + /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -154,10 +148,8 @@ static stardef_t *StarDef(astro_body_t body) * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `BODY_STAR1` .. `BODY_STAR8`. * - * A star that has not been defined through a call to `Astronomy_DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `Astronomy_DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `Astronomy_DefineStar`. * * @param body * One of the eight user-defined star identifiers: `BODY_STAR1` .. `BODY_STAR8`. @@ -183,7 +175,7 @@ static stardef_t *StarDef(astro_body_t body) */ astro_status_t Astronomy_DefineStar(astro_body_t body, double ra, double dec, double distanceLightYears) { - stardef_t *star = StarDef(body); + stardef_t *star = GetStarPointer(body); if (star == NULL) return ASTRO_INVALID_BODY; @@ -4986,7 +4978,7 @@ astro_vector_t Astronomy_HelioVector(astro_body_t body, astro_time_t time) body_state_t bstate; stardef_t *star; - star = StarDef(body); + star = UserDefinedStar(body); if (star != NULL) { astro_spherical_t sphere; @@ -5065,7 +5057,8 @@ astro_vector_t Astronomy_HelioVector(astro_body_t body, astro_time_t time) * more efficient than calling #Astronomy_HelioVector followed by #Astronomy_VectorLength. * * @param body - * A body for which to calculate a heliocentric distance: the Sun, Moon, or any of the planets. + * A body for which to calculate a heliocentric distance: + * the Sun, Moon, any of the planets, or a user-defined star. * * @param time * The date and time for which to calculate the heliocentric distance. @@ -5079,6 +5072,15 @@ astro_func_result_t Astronomy_HelioDistance(astro_body_t body, astro_time_t time { astro_vector_t vector; astro_func_result_t result; + stardef_t *star; + + star = UserDefinedStar(body); + if (star != NULL) + { + result.status = ASTRO_SUCCESS; + result.value = star->dist; + return result; + } switch (body) { @@ -5279,7 +5281,7 @@ astro_vector_t Astronomy_BackdatePosition( astro_body_t targetBody, astro_aberration_t aberration) { - if (IsUserDefinedStar(targetBody)) + if (UserDefinedStar(targetBody)) { /* This is a user-defined star, which must be treated as a special case. @@ -5546,7 +5548,7 @@ astro_state_vector_t Astronomy_HelioState(astro_body_t body, astro_time_t time) major_bodies_t bary; body_state_t planet, earth; - if (IsUserDefinedStar(body)) + if (UserDefinedStar(body)) { astro_vector_t vec = Astronomy_HelioVector(body, time); state.x = vec.x; @@ -7991,6 +7993,7 @@ static astro_func_result_t MaxAltitudeSlope(astro_body_t body, double latitude) Conservatively, we round d(RA)/dt down, d(DEC)/dt up. Then calculate the resulting maximum possible altitude change rate. */ + switch (body) { case BODY_MOON: @@ -8032,25 +8035,19 @@ static astro_func_result_t MaxAltitudeSlope(astro_body_t body, double latitude) result.status = ASTRO_EARTH_NOT_ALLOWED; return result; - case BODY_STAR1: - case BODY_STAR2: - case BODY_STAR3: - case BODY_STAR4: - case BODY_STAR5: - case BODY_STAR6: - case BODY_STAR7: - case BODY_STAR8: - /* - The minimum allowed heliocentric distance of a user-defined star - is one light-year. This can cause a tiny amount of parallax (about 0.001 degrees). - Also, including stellar aberration (22 arcsec = 0.006 degrees), we provide a - generous safety buffer of 0.008 degrees. - */ - deriv_ra = -0.008; - deriv_dec = +0.008; - break; - default: + if (UserDefinedStar(body)) + { + /* + The minimum allowed heliocentric distance of a user-defined star + is one light-year. This can cause a tiny amount of parallax (about 0.001 degrees). + Also, including stellar aberration (22 arcsec = 0.006 degrees), we provide a + generous safety buffer of 0.008 degrees. + */ + deriv_ra = -0.008; + deriv_dec = +0.008; + break; + } result.value = NAN; result.status = ASTRO_INVALID_BODY; return result; diff --git a/source/csharp/README.md b/source/csharp/README.md index d35e8d87..99d762d1 100644 --- a/source/csharp/README.md +++ b/source/csharp/README.md @@ -445,10 +445,8 @@ be a user-defined fixed point in the sky, loosely called a "star". This function assigns a right ascension, declination, and distance to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. -A star that has not been defined through a call to `DefineStar` -defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. -Once defined, the star keeps the given coordinates until -a subsequent call to `DefineStar` replaces the coordinates with new values. +Stars are not valid until defined. Once defined, they retain their +definition until re-defined by another call to `DefineStar`. | Type | Parameter | Description | | --- | --- | --- | @@ -702,7 +700,7 @@ of the resulting vector. | Type | Parameter | Description | | --- | --- | --- | -| [`Body`](#Body) | `body` | A body for which to calculate a heliocentric distance: the Sun, Moon, EMB, SSB, or any of the planets. | +| [`Body`](#Body) | `body` | A body for which to calculate a heliocentric distance: the Sun, Moon, EMB, SSB, any of the planets, or a user-defined star. | | [`AstroTime`](#AstroTime) | `time` | The date and time for which to calculate the heliocentric distance. | **Returns:** The heliocentric distance in AU. diff --git a/source/csharp/astronomy.cs b/source/csharp/astronomy.cs index f39b5c05..6b18518c 100644 --- a/source/csharp/astronomy.cs +++ b/source/csharp/astronomy.cs @@ -2883,13 +2883,6 @@ namespace CosineKitty public double ra; // heliocentric right ascension in EQJ public double dec; // heliocentric declination in EQJ public double dist; // heliocentric distance in AU - - public StarDef() - { - ra = 0.0; - dec = 0.0; - dist = AU_PER_LY; - } }; private static readonly StarDef[] StarTable = InitStarTable(); @@ -2902,11 +2895,17 @@ namespace CosineKitty return table; } - private static bool IsUserDefinedStar(Body body) => - (body >= Body.Star1) && (body <= Body.Star8); + private static StarDef GetStar(Body body) => + ((body >= Body.Star1) && (body <= Body.Star8)) ? StarTable[(int)body - (int)Body.Star1] : null; - private static StarDef GetUserDefinedStar(Body body) => - IsUserDefinedStar(body) ? StarTable[(int)body - (int)Body.Star1] : null; + private static StarDef UserDefinedStar(Body body) + { + if (GetStar(body) is StarDef star) + if (star.dist > 0.0) // has the star been defined yet? + return star; + + return null; + } /// /// Assign equatorial coordinates to a user-defined star. @@ -2917,10 +2916,8 @@ namespace CosineKitty /// This function assigns a right ascension, declination, and distance /// to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. /// - /// A star that has not been defined through a call to `DefineStar` - /// defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - /// Once defined, the star keeps the given coordinates until - /// a subsequent call to `DefineStar` replaces the coordinates with new values. + /// Stars are not valid until defined. Once defined, they retain their + /// definition until re-defined by another call to `DefineStar`. /// /// /// One of the eight user-defined star identifiers: `Body.Star1`, `Body.Star2`, ..., `Body.Star8`. @@ -2942,9 +2939,7 @@ namespace CosineKitty /// public static void DefineStar(Body body, double ra, double dec, double distanceLightYears) { - StarDef star = GetUserDefinedStar(body); - if (star == null) - throw new ArgumentException($"Body must be a user-defined star, not {body}."); + StarDef star = GetStar(body) ?? throw new InvalidBodyException(body); if (!isfinite(ra) || ra < 0.0 || ra >= 24.0) throw new ArgumentException($"Invalid right ascension for star: {ra}"); @@ -5632,9 +5627,6 @@ namespace CosineKitty /// A heliocentric position vector of the center of the given body. public static AstroVector HelioVector(Body body, AstroTime time) { - if (GetUserDefinedStar(body) is StarDef star) - return VectorFromSphere(new Spherical(star.dec, 15*star.ra, star.dist), time); - AstroVector earth, geomoon; switch (body) @@ -5670,6 +5662,8 @@ namespace CosineKitty return CalcSolarSystemBarycenter(time); default: + if (UserDefinedStar(body) is StarDef star) + return VectorFromSphere(new Spherical(star.dec, 15*star.ra, star.dist), time); throw new InvalidBodyException(body); } } @@ -5686,7 +5680,7 @@ namespace CosineKitty /// /// /// A body for which to calculate a heliocentric distance: - /// the Sun, Moon, EMB, SSB, or any of the planets. + /// the Sun, Moon, EMB, SSB, any of the planets, or a user-defined star. /// /// /// The date and time for which to calculate the heliocentric distance. @@ -5712,7 +5706,10 @@ namespace CosineKitty return VsopFormulaCalc(vsop[(int)body].rad, time.tt / DAYS_PER_MILLENNIUM, false); default: - // For non-VSOP objects, fall back to taking the length of the heliocentric vector. + if (UserDefinedStar(body) is StarDef star) + return star.dist; + + // Fall back to taking the length of the heliocentric vector. return HelioVector(body, time).Length(); } } @@ -5861,7 +5858,7 @@ namespace CosineKitty Body targetBody, Aberration aberration) { - if (IsUserDefinedStar(targetBody)) + if (null != UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. @@ -6127,7 +6124,7 @@ namespace CosineKitty ); default: - if (IsUserDefinedStar(body)) + if (null != UserDefinedStar(body)) { AstroVector vec = HelioVector(body, time); return new StateVector(vec.x, vec.y, vec.z, 0.0, 0.0, 0.0, time); diff --git a/source/js/README.md b/source/js/README.md index 7b9a9f43..59e10383 100644 --- a/source/js/README.md +++ b/source/js/README.md @@ -1340,10 +1340,8 @@ be a user-defined fixed point in the sky, loosely called a "star". This function assigns a right ascension, declination, and distance to one of the eight user-defined stars `Star1`..`Star8`. -A star that has not been defined through a call to `DefineStar` -defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. -Once defined, the star keeps the given coordinates until -a subsequent call to `DefineStar` replaces the coordinates with new values. +Stars are not valid until defined. Once defined, they retain their +definition until re-defined by another call to `DefineStar`. | Param | Type | Description | | --- | --- | --- | @@ -1590,7 +1588,7 @@ of the resulting vector. | Param | Type | Description | | --- | --- | --- | -| body | [Body](#Body) | A body for which to calculate a heliocentric distance: the Sun, Moon, or any of the planets. | +| body | [Body](#Body) | A body for which to calculate a heliocentric distance: the Sun, Moon, any of the planets, or a user-defined star. | | date | [FlexibleDateTime](#FlexibleDateTime) | The date and time for which to calculate the heliocentric distance. | diff --git a/source/js/astronomy.browser.js b/source/js/astronomy.browser.js index 9a2fdb9f..4867d7cd 100644 --- a/source/js/astronomy.browser.js +++ b/source/js/astronomy.browser.js @@ -290,15 +290,23 @@ const StarList = [ ]; ; const StarTable = [ - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, - { ra: 0, dec: 0, dist: exports.AU_PER_LY }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, ]; +function GetStar(body) { + const index = StarList.indexOf(body); + return (index >= 0) ? StarTable[index] : null; +} +function UserDefinedStar(body) { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -307,10 +315,8 @@ const StarTable = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -332,8 +338,8 @@ const StarTable = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ function DefineStar(body, ra, dec, distanceLightYears) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body); + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); VerifyNumber(dec); @@ -344,7 +350,9 @@ function DefineStar(body, ra, dec, distanceLightYears) { throw `Invalid declination for star: ${dec}`; if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * exports.AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * exports.AU_PER_LY; } exports.DefineStar = DefineStar; var PrecessDirection; @@ -2483,7 +2491,7 @@ function Horizon(date, observer, ra, dec, refraction) { const coszd = Math.cos(zd * exports.DEG2RAD); const sinzd0 = Math.sin(zd0 * exports.DEG2RAD); const coszd0 = Math.cos(zd0 * exports.DEG2RAD); - var pr = []; + const pr = []; for (let j = 0; j < 3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0) * sinzd + uz[j] * coszd); } @@ -3662,12 +3670,6 @@ exports.JupiterMoons = JupiterMoons; */ function HelioVector(body, date) { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); - return VectorFromSphere(sphere, time); - } if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -3689,6 +3691,11 @@ function HelioVector(body, date) { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; } exports.HelioVector = HelioVector; @@ -3704,7 +3711,7 @@ exports.HelioVector = HelioVector; * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -3713,6 +3720,9 @@ exports.HelioVector = HelioVector; * The heliocentric distance in AU. */ function HelioDistance(body, date) { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -3860,7 +3870,7 @@ class BodyPosition extends PositionFunction { function BackdatePosition(date, observerBody, targetBody, aberration) { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/source/js/astronomy.browser.min.js b/source/js/astronomy.browser.min.js index f637a49a..a9265a32 100644 --- a/source/js/astronomy.browser.min.js +++ b/source/js/astronomy.browser.min.js @@ -42,122 +42,122 @@ $jscomp.polyfill("Reflect.setPrototypeOf",function(r){if(r)return r;if($jscomp.s $jscomp.polyfill("Math.hypot",function(r){return r?r:function(t){if(2>arguments.length)return arguments.length?Math.abs(arguments[0]):0;var e,A,y;for(e=y=0;ey){if(!y)return y;for(e=A=0;et?-e:e}},"es6","es3"); -(function(r){"object"===typeof exports&&"undefined"!==typeof module?module.exports=r():"function"===typeof define&&define.amd?define([],r):("undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:this).Astronomy=r()})(function(){return function(){function r(t,e,A){function y(N,R){if(!e[N]){if(!t[N]){var Ga="function"==typeof require&&require;if(!R&&Ga)return Ga(N,!0);if(w)return w(N,!0);R=Error("Cannot find module '"+N+"'");throw R.code="MODULE_NOT_FOUND", -R;}R=e[N]={exports:{}};t[N][0].call(R.exports,function(v){return y(t[N][1][v]||v)},R,R.exports,r,t,e,A)}return e[N].exports}for(var w="function"==typeof require&&require,Q=0;QMath.abs(c))throw"AngleBetween: first vector is too short.";var d=b.x*b.x+b.y*b.y+b.z*b.z;if(1E-8>Math.abs(d))throw"AngleBetween: second vector is too short.";a=(a.x*b.x+a.y*b.y+a.z*b.z)/Math.sqrt(c*d);return-1>=a?180:1<=a?0:e.RAD2DEG*Math.acos(a)}function R(a){var b=2E3+(a-14)/365.24217;if(-500>b)return a=(b-1820)/100,-20+32*a*a;if(500>b){a=b/100;b=a*a;var c=a*b;return 10583.6-1014.41*a+33.78311*b-5.952053*c-.1798452*b*b+.022174192* -b*c+.0090316521*c*c}if(1600>b)return a=(b-1E3)/100,b=a*a,c=a*b,1574.2-556.01*a+71.23472*b+.319781*c-.8503463*b*b-.005050998*b*c+.0083572073*c*c;if(1700>b)return a=b-1600,b=a*a,120-.9808*a-.01532*b+a*b/7129;if(1800>b)return a=b-1700,b=a*a,8.83+.1603*a-.0059285*b+1.3336E-4*a*b-b*b/1174E3;if(1860>b){a=b-1800;b=a*a;c=a*b;var d=b*b;return 13.72-.332447*a+.0068612*b+.0041116*c-3.7436E-4*d+1.21272E-5*b*c-1.699E-7*c*c+8.75E-10*c*d}if(1900>b)return a=b-1860,b=a*a,c=a*b,7.62+.5737*a-.251754*b+.01680668*c-4.473624E-4* -b*b+b*c/233174;if(1920>b)return a=b-1900,b=a*a,-2.79+1.494119*a-.0598939*b+.0061966*a*b-1.97E-4*b*b;if(1941>b)return a=b-1920,b=a*a,21.2+.84493*a-.0761*b+.0020936*a*b;if(1961>b)return a=b-1950,b=a*a,29.07+.407*a-b/233+a*b/2547;if(1986>b)return a=b-1975,b=a*a,45.45+1.067*a-b/260-a*b/718;if(2005>b)return a=b-2E3,b=a*a,c=a*b,63.86+.3345*a-.060374*b+.0017275*c+6.51814E-4*b*b+2.373599E-5*b*c;if(2050>b)return a=b-2E3,62.92+.32217*a+.005589*a*a;if(2150>b)return a=(b-1820)/100,-20+32*a*a-.5628*(2150-b);a= -(b-1820)/100;return-20+32*a*a}function Ga(a){return a+Wb(a)/86400}function v(a){return a instanceof O?a:new O(a)}function Xb(a){a=a.tt/36525;return(((((-4.34E-8*a-5.76E-7)*a+.0020034)*a-1.831E-4)*a-46.836769)*a+84381.406)/3600}function Wa(a){var b;if(!Xa||1E-6=F;++F)0!==D[F]&&g(K.x,K.y,c(z,D[F],F),c(x,D[F],F), -function(pa,qa){return K.x=pa,K.y=qa});return K}function k(D,F,P,ea,K,pa,qa,sb){K=l(K,pa,qa,sb);q+=D*K.y;u+=F*K.y;Ya+=P*K.x;ra+=ea*K.x}++e.CalcMoonCount;a=a.tt/36525;var n,p,q,u,z=b(-6,6,1,4),x=b(-6,6,1,4);var B=a*a;var Ya=u=q=0;var ra=3422.7;var ia=h(.19833+.05611*a);var fa=h(.27869+.04508*a);var V=h(.16827-.36903*a);var aa=h(.34734-5.37261*a);var Ha=h(.10498-5.37899*a);var Za=h(.42681-.41855*a),kd=h(.14943-5.37511*a);var $a=.84*ia+.31*fa+14.27*V+7.26*aa+.28*Ha+.24*Za;var ub=2.94*ia+.31*fa+14.27* -V+9.34*aa+1.12*Ha+.83*Za;var ab=-6.4*ia-1.89*Za;fa=.21*ia+.31*fa+14.27*V-88.7*aa-15.3*Ha+.24*Za-1.86*kd;V=$a-ab;ia=-3.332E-6*h(.59734-5.37261*a)-5.39E-7*h(.35498-5.37899*a)-6.4E-8*h(.39943-5.37511*a);$a=S*Q(.60643382+1336.85522467*a-3.13E-6*B)+$a/ha;ub=S*Q(.37489701+1325.55240982*a+2.565E-5*B)+ub/ha;ab=S*Q(.99312619+99.99735956*a-4.4E-7*B)+ab/ha;fa=S*Q(.25909118+1342.2278298*a-8.92E-6*B)+fa/ha;Ha=S*Q(.82736186+1236.85308708*a-3.97E-6*B)+V/ha;for(n=1;4>=n;++n){switch(n){case 1:V=ub;B=4;aa=1.000002208; -break;case 2:V=ab;B=3;aa=.997504612-.002495388*a;break;case 3:V=fa;B=4;aa=1.000002708+139.978*ia;break;case 4:V=Ha;B=6;aa=1;break;default:throw"Internal error: I = "+n;}d(0,n,1);d(1,n,Math.cos(V)*aa);f(0,n,0);f(1,n,Math.sin(V)*aa);for(p=2;p<=B;++p)g(c(z,p-1,n),c(x,p-1,n),c(z,1,n),c(x,1,n),function(D,F){return d(p,n,D),f(p,n,F)});for(p=1;p<=B;++p)d(-p,n,c(z,p,n)),f(-p,n,-c(x,p,n))}k(13.902,14.06,-.001,.2607,0,0,0,4);k(.403,-4.01,.394,.0023,0,0,0,3);k(2369.912,2373.36,.601,28.2333,0,0,0,2);k(-125.154, --112.79,-.725,-.9781,0,0,0,1);k(1.979,6.98,-.445,.0433,1,0,0,4);k(191.953,192.72,.029,3.0861,1,0,0,2);k(-8.466,-13.51,.455,-.1093,1,0,0,1);k(22639.5,22609.07,.079,186.5398,1,0,0,0);k(18.609,3.59,-.094,.0118,1,0,0,-1);k(-4586.465,-4578.13,-.077,34.3117,1,0,0,-2);k(3.215,5.44,.192,-.0386,1,0,0,-3);k(-38.428,-38.64,.001,.6008,1,0,0,-4);k(-.393,-1.43,-.092,.0086,1,0,0,-6);k(-.289,-1.59,.123,-.0053,0,1,0,4);k(-24.42,-25.1,.04,-.3,0,1,0,2);k(18.023,17.93,.007,.1494,0,1,0,1);k(-668.146,-126.98,-1.302,-.3997, -0,1,0,0);k(.56,.32,-.001,-.0037,0,1,0,-1);k(-165.145,-165.06,.054,1.9178,0,1,0,-2);k(-1.877,-6.46,-.416,.0339,0,1,0,-4);k(.213,1.02,-.074,.0054,2,0,0,4);k(14.387,14.78,-.017,.2833,2,0,0,2);k(-.586,-1.2,.054,-.01,2,0,0,1);k(769.016,767.96,.107,10.1657,2,0,0,0);k(1.75,2.01,-.018,.0155,2,0,0,-1);k(-211.656,-152.53,5.679,-.3039,2,0,0,-2);k(1.225,.91,-.03,-.0088,2,0,0,-3);k(-30.773,-34.07,-.308,.3722,2,0,0,-4);k(-.57,-1.4,-.074,.0109,2,0,0,-6);k(-2.921,-11.75,.787,-.0484,1,1,0,2);k(1.267,1.52,-.022,.0164, -1,1,0,1);k(-109.673,-115.18,.461,-.949,1,1,0,0);k(-205.962,-182.36,2.056,1.4437,1,1,0,-2);k(.233,.36,.012,-.0025,1,1,0,-3);k(-4.391,-9.66,-.471,.0673,1,1,0,-4);k(.283,1.53,-.111,.006,1,-1,0,4);k(14.577,31.7,-1.54,.2302,1,-1,0,2);k(147.687,138.76,.679,1.1528,1,-1,0,0);k(-1.089,.55,.021,0,1,-1,0,-1);k(28.475,23.59,-.443,-.2257,1,-1,0,-2);k(-.276,-.38,-.006,-.0036,1,-1,0,-3);k(.636,2.27,.146,-.0102,1,-1,0,-4);k(-.189,-1.68,.131,-.0028,0,2,0,2);k(-7.486,-.66,-.037,-.0086,0,2,0,0);k(-8.096,-16.35,-.74, -.0918,0,2,0,-2);k(-5.741,-.04,0,-9E-4,0,0,2,2);k(.255,0,0,0,0,0,2,1);k(-411.608,-.2,0,-.0124,0,0,2,0);k(.584,.84,0,.0071,0,0,2,-1);k(-55.173,-52.14,0,-.1052,0,0,2,-2);k(.254,.25,0,-.0017,0,0,2,-3);k(.025,-1.67,0,.0031,0,0,2,-4);k(1.06,2.96,-.166,.0243,3,0,0,2);k(36.124,50.64,-1.3,.6215,3,0,0,0);k(-13.193,-16.4,.258,-.1187,3,0,0,-2);k(-1.187,-.74,.042,.0074,3,0,0,-4);k(-.293,-.31,-.002,.0046,3,0,0,-6);k(-.29,-1.45,.116,-.0051,2,1,0,2);k(-7.649,-10.56,.259,-.1038,2,1,0,0);k(-8.627,-7.59,.078,-.0192, -2,1,0,-2);k(-2.74,-2.54,.022,.0324,2,1,0,-4);k(1.181,3.32,-.212,.0213,2,-1,0,2);k(9.703,11.67,-.151,.1268,2,-1,0,0);k(-.352,-.37,.001,-.0028,2,-1,0,-1);k(-2.494,-1.17,-.003,-.0017,2,-1,0,-2);k(.36,.2,-.012,-.0043,2,-1,0,-4);k(-1.167,-1.25,.008,-.0106,1,2,0,0);k(-7.412,-6.12,.117,.0484,1,2,0,-2);k(-.311,-.65,-.032,.0044,1,2,0,-4);k(.757,1.82,-.105,.0112,1,-2,0,2);k(2.58,2.32,.027,.0196,1,-2,0,0);k(2.533,2.4,-.014,-.0212,1,-2,0,-2);k(-.344,-.57,-.025,.0036,0,3,0,-2);k(-.992,-.02,0,0,1,0,2,2);k(-45.099, --.02,0,-.001,1,0,2,0);k(-.179,-9.52,0,-.0833,1,0,2,-2);k(-.301,-.33,0,.0014,1,0,2,-4);k(-6.382,-3.37,0,-.0481,1,0,-2,2);k(39.528,85.13,0,-.7136,1,0,-2,0);k(9.366,.71,0,-.0112,1,0,-2,-2);k(.202,.02,0,0,1,0,-2,-4);k(.415,.1,0,.0013,0,1,2,0);k(-2.152,-2.26,0,-.0066,0,1,2,-2);k(-1.44,-1.3,0,.0014,0,1,-2,2);k(.384,-.04,0,0,0,1,-2,-2);k(1.938,3.6,-.145,.0401,4,0,0,0);k(-.952,-1.58,.052,-.013,4,0,0,-2);k(-.551,-.94,.032,-.0097,3,1,0,0);k(-.482,-.57,.005,-.0045,3,1,0,-2);k(.681,.96,-.026,.0115,3,-1,0,0); -k(-.297,-.27,.002,-9E-4,2,2,0,-2);k(.254,.21,-.003,0,2,-2,0,-2);k(-.25,-.22,.004,.0014,1,3,0,-2);k(-3.996,0,0,4E-4,2,0,2,0);k(.557,-.75,0,-.009,2,0,2,-2);k(-.459,-.38,0,-.0053,2,0,-2,2);k(-1.298,.74,0,4E-4,2,0,-2,0);k(.538,1.14,0,-.0141,2,0,-2,-2);k(.263,.02,0,0,1,1,2,0);k(.426,.07,0,-6E-4,1,1,-2,-2);k(-.304,.03,0,3E-4,1,-1,2,0);k(-.372,-.19,0,-.0027,1,-1,-2,2);k(.418,0,0,0,0,0,4,0);k(-.33,-.04,0,0,3,0,2,0);B=-526.069*l(0,0,1,-2).y;B+=-3.352*l(0,0,1,-4).y;B+=44.297*l(1,0,1,-2).y;B+=-6*l(1,0,1,-4).y; -B+=20.599*l(-1,0,1,0).y;B+=-30.598*l(-1,0,1,-2).y;B+=-24.649*l(-2,0,1,0).y;B+=-2*l(-2,0,1,-2).y;B+=-22.571*l(0,1,1,-2).y;B+=10.985*l(0,-1,1,-2).y;q+=.82*h(.7736-62.5512*a)+.31*h(.0466-125.1025*a)+.35*h(.5785-25.1042*a)+.66*h(.4591+1335.8075*a)+.64*h(.313-91.568*a)+1.14*h(.148+1331.2898*a)+.21*h(.5918+1056.5859*a)+.44*h(.5784+1322.8595*a)+.24*h(.2275-5.7374*a)+.28*h(.2965+2.6929*a)+.33*h(.3132+6.3368*a);a=fa+u/ha;a=(1.000002708+139.978*ia)*(18518.511+1.189+Ya)*Math.sin(a)-6.24*Math.sin(3*a)+B;return{geo_eclip_lon:S* -Q(($a+q/ha)/S),geo_eclip_lat:Math.PI/648E3*a,distance_au:ha*ld/(.999953253*ra)}}function ac(a,b){return[a.rot[0][0]*b[0]+a.rot[1][0]*b[1]+a.rot[2][0]*b[2],a.rot[0][1]*b[0]+a.rot[1][1]*b[1]+a.rot[2][1]*b[2],a.rot[0][2]*b[0]+a.rot[1][2]*b[1]+a.rot[2][2]*b[2]]}function Ia(a,b,c){b=Ja(b,c);return ac(b,a)}function Ja(a,b){a=a.tt/36525;var c=84381.406,d=((((3.337E-7*a-4.67E-7)*a-.00772503)*a+.0512623)*a-.025754)*a+c;c*=4.84813681109536E-6;var f=((((-9.51E-8*a+1.32851E-4)*a-.00114045)*a-1.0790069)*a+5038.481507)* -a*4.84813681109536E-6;d*=4.84813681109536E-6;var g=((((-5.6E-8*a+1.70663E-4)*a-.00121197)*a-2.3814292)*a+10.556403)*a*4.84813681109536E-6;a=Math.sin(c);c=Math.cos(c);var h=Math.sin(-f);f=Math.cos(-f);var l=Math.sin(-d);d=Math.cos(-d);var k=Math.sin(g),n=Math.cos(g);g=n*f-h*k*d;var p=n*h*c+k*d*f*c-a*k*l,q=n*h*a+k*d*f*a+c*k*l,u=-k*f-h*n*d,z=-k*h*c+n*d*f*c-a*n*l;k=-k*h*a+n*d*f*a+c*n*l;h*=l;n=-l*f*c-a*d;a=-l*f*a+d*c;if(b===G.Into2000)return new L([[g,p,q],[u,z,k],[h,n,a]]);if(b===G.From2000)return new L([[g, -u,h],[p,z,n],[q,k,a]]);throw"Invalid precess direction";}function ba(a){if(!bb||bb.tt!==a.tt){var b=a.tt/36525,c=15*Wa(a).ee,d=(.779057273264+.00273781191135448*a.ut+a.ut%1)%1*360;0>d&&(d+=360);b=((c+.014506+((((-3.68E-8*b-2.9956E-5)*b-4.4E-7)*b+1.3915817)*b+4612.156534)*b)/3600+d)%360/15;0>b&&(b+=24);bb={tt:a.tt,st:b}}return bb.st}function vb(a,b){var c=a.latitude*e.DEG2RAD,d=Math.sin(c);c=Math.cos(c);var f=1/Math.hypot(c,.996647180302104*d),g=a.height/1E3,h=6378.1366*f+g;b=(15*b+a.longitude)*e.DEG2RAD; -a=Math.sin(b);b=Math.cos(b);return{pos:[h*c*b/e.KM_PER_AU,h*c*a/e.KM_PER_AU,(6335.438815127603*f+g)*d/e.KM_PER_AU],vel:[-7.292115E-5*h*c*a*86400/e.KM_PER_AU,7.292115E-5*h*c*b*86400/e.KM_PER_AU,0]}}function cb(a,b,c){b=Ka(b,c);return ac(b,a)}function Ka(a,b){a=Wa(a);var c=a.mobl*e.DEG2RAD,d=a.tobl*e.DEG2RAD,f=4.84813681109536E-6*a.dpsi;a=Math.cos(c);c=Math.sin(c);var g=Math.cos(d),h=Math.sin(d);d=Math.cos(f);var l=Math.sin(f);f=-l*a;var k=-l*c,n=l*g,p=d*a*g+c*h,q=d*c*g-a*h;l*=h;var u=d*a*h-c*g;a=d* -c*h+a*g;if(b===G.From2000)return new L([[d,n,l],[f,p,u],[k,q,a]]);if(b===G.Into2000)return new L([[d,f,k],[n,p,q],[l,u,a]]);throw"Invalid precess direction";}function db(a,b,c){return c===G.Into2000?Ia(cb(a,b,c),b,c):cb(Ia(a,b,c),b,c)}function bc(a,b){var c=ba(a);b=vb(b,c).pos;return db(b,a,G.Into2000)}function md(a){if(!(a instanceof Array)||3!==a.length)return!1;for(var b=0;3>b;++b){if(!(a[b]instanceof Array)||3!==a[b].length)return!1;for(var c=0;3>c;++c)if(!Number.isFinite(a[b][c]))return!1}return!0} -function cc(a,b){b=new E(a[0],a[1],a[2],b);var c=b.x*b.x+b.y*b.y,d=Math.sqrt(c+b.z*b.z);if(0===c){if(0===b.z)throw"Indeterminate sky coordinates";return new eb(0,0>b.z?-90:90,d,b)}var f=e.RAD2HOUR*Math.atan2(b.y,b.x);0>f&&(f+=24);return new eb(f,e.RAD2DEG*Math.atan2(a[2],Math.sqrt(c)),d,b)}function sa(a,b){var c=a*e.DEG2RAD;a=Math.cos(c);c=Math.sin(c);return[a*b[0]+c*b[1],a*b[1]-c*b[0],b[2]]}function fb(a,b,c,d,f){a=v(a);ta(b);w(c);w(d);var g=Math.sin(b.latitude*e.DEG2RAD),h=Math.cos(b.latitude*e.DEG2RAD), -l=Math.sin(b.longitude*e.DEG2RAD),k=Math.cos(b.longitude*e.DEG2RAD);b=Math.sin(d*e.DEG2RAD);var n=Math.cos(d*e.DEG2RAD),p=Math.sin(c*e.HOUR2RAD),q=Math.cos(c*e.HOUR2RAD),u=[h*k,h*l,g];g=[-g*k,-g*l,h];l=[l,-k,0];h=-15*ba(a);a=sa(h,u);u=sa(h,g);l=sa(h,l);b=[n*q,n*p,b];p=b[0]*a[0]+b[1]*a[1]+b[2]*a[2];n=b[0]*u[0]+b[1]*u[1]+b[2]*u[2];u=b[0]*l[0]+b[1]*l[1]+b[2]*l[2];q=Math.hypot(n,u);0n&&(n+=360)):n=0;p=e.RAD2DEG*Math.atan2(q,p);q=d;if(f&&(d=p,f=La(f,90-p),p-=f,0l;++l)f.push((b[l]-d*a[l])/u*c+a[l]*q);q=Math.hypot(f[0],f[1]);0c&&(c+=24)):c=0;q=e.RAD2DEG*Math.atan2(f[2],q)}return new dc(n,90-p,c,q)}function ta(a){if(!(a instanceof wb))throw"Not an instance of the Observer class: "+a;w(a.latitude);w(a.longitude);w(a.height);if(-90>a.latitude||90b&&(b+=360));g=e.RAD2DEG*Math.atan2(c,g);a=new E(d,f,c,a.t);return new gc(a,g,b)}function Ma(a){void 0===hb&&(hb=e.DEG2RAD*Wa(v(xb)).mobl,hc=Math.cos(hb),ic=Math.sin(hb));return fc(a,hc,ic)}function Y(a){a=v(a);var b=da(a),c=b.distance_au*Math.cos(b.geo_eclip_lat);b=[c*Math.cos(b.geo_eclip_lon),c*Math.sin(b.geo_eclip_lon),b.distance_au*Math.sin(b.geo_eclip_lat)];var d=Xb(a)*e.DEG2RAD;c=Math.cos(d);d=Math.sin(d);b=Ia([b[0],b[1]*c-b[2]*d,b[1]*d+b[2]*c],a,G.Into2000); -return new E(b[0],b[1],b[2],a)}function ib(a){a=v(a);a=da(a);return new va(a.geo_eclip_lat*e.RAD2DEG,a.geo_eclip_lon*e.RAD2DEG,a.distance_au)}function Na(a){a=v(a);var b=a.AddDays(-1E-5),c=a.AddDays(1E-5);b=Y(b);c=Y(c);return new I((b.x+c.x)/2,(b.y+c.y)/2,(b.z+c.z)/2,(c.x-b.x)/2E-5,(c.y-b.y)/2E-5,(c.z-b.z)/2E-5,a)}function yb(a){a=v(a);var b=Na(a);return new I(b.x/82.30056,b.y/82.30056,b.z/82.30056,b.vx/82.30056,b.vy/82.30056,b.vz/82.30056,a)}function ja(a,b,c){var d=1,f=0;a=$jscomp.makeIterator(a); -for(var g=a.next();!g.done;g=a.next()){var h=0;g=$jscomp.makeIterator(g.value);for(var l=g.next();!l.done;l=g.next()){var k=$jscomp.makeIterator(l.value);l=k.next().value;var n=k.next().value;k=k.next().value;h+=l*Math.cos(n+b*k)}h*=d;c&&(h%=S);f+=h;d*=b}return f}function zb(a,b){var c=1,d=0,f=0,g=0;a=$jscomp.makeIterator(a);for(var h=a.next();!h.done;h=a.next()){var l=0,k=0;h=$jscomp.makeIterator(h.value);for(var n=h.next();!n.done;n=h.next()){var p=$jscomp.makeIterator(n.value);n=p.next().value; -var q=p.next().value;p=p.next().value;q+=b*p;l+=n*p*Math.sin(q);0a?0:a>=b?b-1:a}function Db(a){var b= -$jscomp.makeIterator(a);a=b.next().value;var c=$jscomp.makeIterator(b.next().value);var d=c.next().value;var f=c.next().value;c=c.next().value;var g=$jscomp.makeIterator(b.next().value);b=g.next().value;var h=g.next().value;g=g.next().value;d=new X(a,new C(d,f,c),new C(b,h,g));a=new xa(d.tt);f=d.r.add(a.Sun.r);c=d.v.add(a.Sun.v);b=a.Acceleration(f);d=new Qa(d.tt,f,c,b);return new kc(a,d)}function mc(a,b,c){a=Db(a);for(var d=Math.ceil((b-a.grav.tt)/c),f=0;fka[50][0])c=null;else{c=lc((c-d)/29200,50);if(!Fb[c]){d=Fb[c]=[];d[0]=Db(ka[c]).grav;d[200]=Db(ka[c+1]).grav;var f,g=d[0].tt;for(f=1;200>f;++f)d[f]=Cb(g+=146,d[f-1]).grav;g=d[200].tt;var h=[];h[200]=d[200];for(f=199;0d[1]&&(d[1]+=S);f=$jscomp.makeIterator(b.z);for(g=f.next();!g.done;g=f.next())h=$jscomp.makeIterator(g.value),g=h.next().value,l=h.next().value,h=h.next().value,l+=c*h,d[2]+=g* -Math.cos(l),d[3]+=g*Math.sin(l);f=$jscomp.makeIterator(b.zeta);for(g=f.next();!g.done;g=f.next())h=$jscomp.makeIterator(g.value),g=h.next().value,l=h.next().value,h=h.next().value,l+=c*h,d[4]+=g*Math.cos(l),d[5]+=g*Math.sin(l);f=d[0];h=d[1];g=d[2];l=d[3];c=d[4];d=d[5];var k=Math.sqrt(b.mu/(f*f*f));b=h+g*Math.sin(h)-l*Math.cos(h);do{var n=Math.cos(b);var p=Math.sin(b);n=(h-b+g*p-l*n)/(1-g*n-l*p);b+=n}while(1E-12<=Math.abs(n));n=Math.cos(b);p=Math.sin(b);h=l*n-g*p;var q=-g*n-l*p,u=1/(1+q),z=1/(1+Math.sqrt(1- -g*g-l*l));b=f*(n-g-z*l*h);h=f*(p-l+z*g*h);l=k*u*f*(-p-z*l*q);f=k*u*f*(+n+z*g*q);g=2*Math.sqrt(1-c*c-d*d);k=1-2*d*d;n=1-2*c*c;p=2*d*c;a=new I(b*k+h*p,b*p+h*n,(c*h-b*d)*g,l*k+f*p,l*p+f*n,(c*f-l*d)*g,a);return ya(nd,a)}function ca(a,b){b=v(b);var c=Gb.indexOf(a);if(0<=c)return a=nc[c],a=new va(a.dec,15*a.ra,a.dist),lb(a,b);if(a in M)return ua(M[a],b);if(a===m.Pluto)return a=Eb(b,!0),new E(a.x,a.y,a.z,b);if(a===m.Sun)return new E(0,0,0,b);if(a===m.Moon)return a=ua(M.Earth,b),c=Y(b),new E(a.x+c.x,a.y+ -c.y,a.z+c.z,b);if(a===m.EMB)return a=ua(M.Earth,b),c=Y(b),new E(a.x+c.x/82.30056,a.y+c.y/82.30056,a.z+c.z/82.30056,b);if(a===m.SSB)return a=new E(0,0,0,b),jb(a,b,m.Jupiter,2.825345909524226E-7),jb(a,b,m.Saturn,8.459715185680659E-8),jb(a,b,m.Uranus,1.292024916781969E-8),jb(a,b,m.Neptune,1.524358900784276E-8),a;throw'HelioVector: Unknown body "'+a+'"';}function la(a,b){b=v(b);return a in M?ja(M[a][2],b.tt/365250,!1):ca(a,b).Length()}function oc(a,b){for(var c=b,d=0,f=0;10>f;++f){var g=a.Position(c); -d=g.Length()/e.C_AUDAY;if(1d)return g;c=h}throw"Light-travel time solver did not converge: dt = "+d;}function pc(a,b,c,d){y(d);a=v(a);if(0<=Gb.indexOf(c)){c=ca(c,a);if(d)return b=mb(b,a),d=new E(c.x-b.x,c.y-b.y,c.z-b.z,a),c=e.C_AUDAY/d.Length(),new E(d.x+b.vx/c,d.y+b.vy/c,d.z+b.vz/c,a);b=ca(b,a);return new E(c.x-b.x,c.y-b.y,c.z-b.z,a)}var f=d?new E(0,0,0,a):ca(b,a);b=new Hb(b,c,d,f);return oc(b, -a)}function W(a,b,c){y(c);b=v(b);switch(a){case m.Earth:return new E(0,0,0,b);case m.Moon:return Y(b);default:return a=pc(b,m.Earth,a,c),a.t=b,a}}function ma(a,b){return new I(a.r.x,a.r.y,a.r.z,a.v.x,a.v.y,a.v.z,b)}function mb(a,b){b=v(b);switch(a){case m.Sun:return new I(0,0,0,0,0,0,b);case m.SSB:return a=new xa(b.tt),new I(-a.Sun.r.x,-a.Sun.r.y,-a.Sun.r.z,-a.Sun.v.x,-a.Sun.v.y,-a.Sun.v.z,b);case m.Mercury:case m.Venus:case m.Earth:case m.Mars:case m.Jupiter:case m.Saturn:case m.Uranus:case m.Neptune:return a= -Oa(M[a],b.tt),ma(a,b);case m.Pluto:return Eb(b,!0);case m.Moon:case m.EMB:var c=Oa(M.Earth,b.tt);a=a==m.Moon?Na(b):yb(b);return new I(a.x+c.r.x,a.y+c.r.y,a.z+c.r.z,a.vx+c.v.x,a.vy+c.v.y,a.vz+c.v.z,b);default:throw'HelioState: Unsupported body "'+a+'"';}}function od(a,b,c,d,f){var g=(f+c)/2-d;c=(f-c)/2;if(0==g){if(0==c)return null;d=-d/c;if(-1>d||1=d)return null;f=Math.sqrt(d);d=(-c+f)/(2*g);f=(-c-f)/(2*g);if(-1<=d&&1>=d){if(-1<=f&&1>=f)return null}else if(-1<= -f&&1>=f)d=f;else return null}return{t:a+d*b,df_dt:(2*g*d+c)/b}}function J(a,b,c,d){var f=w(d&&d.dt_tolerance_seconds||1);f=Math.abs(f/86400);var g=d&&d.init_f1||a(b),h=d&&d.init_f2||a(c),l=NaN,k=0;d=d&&d.iter_limit||20;for(var n=!0;;){if(++k>d)throw"Excessive iteration in Search()";var p=new O(b.ut+.5*(c.ut-b.ut)),q=p.ut-b.ut;if(Math.abs(q)(q.ut-b.ut)*(q.ut-c.ut)&&0>(z.ut-b.ut)*(z.ut-c.ut))){u=a(q);var B=a(z);if(0>u&&0<=B){g=u;h=B;b=q;c=z;l=x;n=!1;continue}}}}if(0>g&&0<=l)c=p,h=l;else if(0>l&&0<=h)b=p,g=l;else return null}}function za(a){for(;-180>=a;)a+=360;for(;180a;)a+=360;for(;360<=a;)a-=360;return a}function qc(a,b,c){w(a);w(c);b=v(b);c=b.AddDays(c);return J(function(d){d=ec(d);return za(d.elon-a)},b,c,{dt_tolerance_seconds:.01})}function Ib(a, -b,c){if(a===m.Earth||b===m.Earth)throw"The Earth does not have a longitude as seen from itself.";c=v(c);a=W(a,c,!1);a=Ma(a);b=W(b,c,!1);b=Ma(b);return Aa(a.elon-b.elon)}function Ba(a,b){if(a==m.Earth)throw"The Earth does not have an angle as seen from itself.";var c=v(b);b=W(m.Sun,c,!0);a=W(a,c,!0);return N(b,a)}function na(a,b){if(a===m.Sun)throw"Cannot calculate heliocentric longitude of the Sun.";a=ca(a,b);return Ma(a).elon}function nb(a,b){if(a===m.Earth)throw"The illumination of the Earth is not defined."; -var c=v(b),d=ua(M.Earth,c);if(a===m.Sun){var f=new E(-d.x,-d.y,-d.z,c);b=new E(0,0,0,c);d=0}else a===m.Moon?(f=Y(c),b=new E(d.x+f.x,d.y+f.y,d.z+f.z,c)):(b=ca(a,b),f=new E(b.x-d.x,b.y-d.y,b.z-d.z,c)),d=N(f,b);var g=f.Length(),h=b.Length();if(a===m.Sun)var l=pd+5*Math.log10(g);else if(a===m.Moon)a=d*e.DEG2RAD,l=a*a,a=-12.717+1.49*Math.abs(a)+.0431*l*l,l=a+=5*Math.log10(g/(385000.6/e.KM_PER_AU)*h);else if(a===m.Saturn){var k=d;a=Ma(f);l=28.06*e.DEG2RAD;var n=e.DEG2RAD*a.elat;a=Math.asin(Math.sin(n)* -Math.cos(l)-Math.cos(n)*Math.sin(l)*Math.sin(e.DEG2RAD*a.elon-e.DEG2RAD*(169.51+3.82E-5*c.tt)));l=Math.sin(Math.abs(a));k=-9+.044*k+l*(-2.6+1.2*l)+5*Math.log10(h*g);a*=e.RAD2DEG;l=k;k=a}else{var p=n=l=0;switch(a){case m.Mercury:a=-.6;l=4.98;n=-4.88;p=3.02;break;case m.Venus:163.6>d?(a=-4.47,l=1.03,n=.57,p=.13):(a=.98,l=-1.02);break;case m.Mars:a=-1.52;l=1.6;break;case m.Jupiter:a=-9.4;l=.5;break;case m.Uranus:a=-7.19;l=.25;break;case m.Neptune:a=-6.87;break;case m.Pluto:a=-1;l=4;break;default:throw"VisualMagnitude: unsupported body "+ -a;}var q=d/100;l=a+q*(l+q*(n+q*p))+5*Math.log10(h*g)}return new rc(c,l,d,h,g,f,b,k)}function Ra(a){if(a===m.Earth)throw"The Earth does not have a synodic period as seen from itself.";if(a===m.Moon)return 29.530588;var b=Z[a];if(!b)throw"Not a valid planet name: "+a;a=Z.Earth.OrbitalPeriod;return Math.abs(a/(a/b.OrbitalPeriod-1))}function Ca(a,b,c){function d(n){var p=na(a,n);n=na(m.Earth,n);return za(g*(n-p)-b)}w(b);var f=Z[a];if(!f)throw"Cannot search relative longitude because body is not a planet: "+ -a;if(a===m.Earth)throw"Cannot search relative longitude for the Earth (it is always 0)";var g=f.OrbitalPeriod>Z.Earth.OrbitalPeriod?1:-1;f=Ra(a);c=v(c);var h=d(c);0l;++l){var k=-h/360*f;c=c.AddDays(k);if(1>86400*Math.abs(k))return c;k=h;h=d(c);30>Math.abs(k)&&k!==h&&(k/=k-h,.5k&&(f*=k))}throw"Relative longitude search failed to converge for "+a+" near "+c.toString()+" (error_angle = "+h+").";}function Jb(a){return Ib(m.Moon,m.Sun,a)}function Sa(a,b,c){function d(l){l= -Jb(l);return za(l-a)}w(a);w(c);b=v(b);var f=d(b);if(0>c){0>f&&(f+=360);var g=-(29.530588*f)/360;f=g+1.5;if(fc)return null;f=Math.min(c,g+1.5)}c=b.AddDays(h);b=b.AddDays(f);return J(d,c,b,{dt_tolerance_seconds:.1})}function sc(a){var b=Jb(a);b=(Math.floor(b/90)+1)%4;a=Sa(90*b,a,10);if(!a)throw"Cannot find moon quarter";return new tc(b,a)}function Kb(a,b,c,d,f,g,h){if(0>g&&0<=h)return new qd(d,f,g,h);if(0<=g&& -0>h)return null;if(1786400*l||Math.min(Math.abs(g),Math.abs(h))>l/2*c)return null;l=new O((d.ut+f.ut)/2);var k=b(l);return Kb(1+a,b,c,d,l,g,k)||Kb(1+a,b,c,l,f,k,h)}function rd(a,b){if(-90>b||90h||90f?(n=p.AddDays(-.42),q=l(n)):(p=n.AddDays(.42),u=l(p));var z=Kb(0,l,k,n,p,q,u);if(z){if(k=J(l,z.tx,z.ty,{dt_tolerance_seconds:.1,init_f1:z.ax,init_f2:z.ay})){if(0>f){if(k.utd.ut+f)return null;return k}throw"Rise/set search failed after finding ascent: t1="+n+", t2="+p+", a1="+q+", a2="+u;}if(0>f){if(n.utd.ut+f)return null;n=p;q=u}}}function vc(a,b){b=v(b);var c=Ib(a,m.Sun, -b);if(1805*f;++f){var g=a.AddDays(5),h=b(g);if(0>=d*h){if(0>d||0h){a=J(c,a,g,{init_f1:-d, -init_f2:-h});if(!a)throw"SearchLunarApsis INTERNAL ERROR: apogee search failed!";d=da(a).distance_au;return new Ta(a,1,d)}throw"SearchLunarApsis INTERNAL ERROR: cannot classify apsis event!";}a=g;d=h}throw"SearchLunarApsis INTERNAL ERROR: could not find apsis within 2 synodic months of start date.";}function yc(a,b,c,d){for(var f=b===Da.Apocenter?1:-1;;){d/=9;if(d<1/1440)return c=c.AddDays(d/2),a=la(a,c),new Ta(c,b,a);for(var g=-1,h=0,l=0;10>l;++l){var k=c.AddDays(l*d);k=f*la(a,k);if(0==l||k>h)g= -l,h=k}c=c.AddDays((g-1)*d);d*=2}}function sd(a,b){var c=b.AddDays(-30/360*Z[a].OrbitalPeriod),d=b.AddDays(.75*Z[a].OrbitalPeriod),f=c,g=c,h=-1,l=-1;d=(d.ut-c.ut)/99;for(var k=0;100>k;++k){var n=c.AddDays(k*d),p=la(a,n);0===k?l=h=p:(p>l&&(l=p,g=n),p=b.tt)return a.time.tt>=b.tt&&a.time.tt=b.tt)return a;throw"Internal error: failed to find Neptune apsis.";}function zc(a,b){function c(p){var q= -p.AddDays(-5E-4);p=p.AddDays(5E-4);q=la(a,q);return(la(a,p)-q)/.001}function d(p){return-c(p)}b=v(b);if(a===m.Neptune||a===m.Pluto)return sd(a,b);for(var f=Z[a].OrbitalPeriod,g=f/6,h=c(b),l=0;l*g<2*f;++l){var k=b.AddDays(g),n=c(k);if(0>=h*n){f=g=void 0;if(0>h||0n)g=d,f=Da.Apocenter;else throw"Internal error with slopes in SearchPlanetApsis";b=J(g,b,k);if(!b)throw"Failed to find slope transition in planetary apsis search.";h=la(a,b);return new Ta(b,f,h)}b=k;h= -n}throw"Internal error: should have found planetary apsis within 2 orbital periods.";}function Ea(a){return new L([[a.rot[0][0],a.rot[1][0],a.rot[2][0]],[a.rot[0][1],a.rot[1][1],a.rot[2][1]],[a.rot[0][2],a.rot[1][2],a.rot[2][2]]])}function Fa(a,b){return new L([[b.rot[0][0]*a.rot[0][0]+b.rot[1][0]*a.rot[0][1]+b.rot[2][0]*a.rot[0][2],b.rot[0][1]*a.rot[0][0]+b.rot[1][1]*a.rot[0][1]+b.rot[2][1]*a.rot[0][2],b.rot[0][2]*a.rot[0][0]+b.rot[1][2]*a.rot[0][1]+b.rot[2][2]*a.rot[0][2]],[b.rot[0][0]*a.rot[1][0]+ -b.rot[1][0]*a.rot[1][1]+b.rot[2][0]*a.rot[1][2],b.rot[0][1]*a.rot[1][0]+b.rot[1][1]*a.rot[1][1]+b.rot[2][1]*a.rot[1][2],b.rot[0][2]*a.rot[1][0]+b.rot[1][2]*a.rot[1][1]+b.rot[2][2]*a.rot[1][2]],[b.rot[0][0]*a.rot[2][0]+b.rot[1][0]*a.rot[2][1]+b.rot[2][0]*a.rot[2][2],b.rot[0][1]*a.rot[2][0]+b.rot[1][1]*a.rot[2][1]+b.rot[2][1]*a.rot[2][2],b.rot[0][2]*a.rot[2][0]+b.rot[1][2]*a.rot[2][1]+b.rot[2][2]*a.rot[2][2]]])}function lb(a,b){b=v(b);var c=a.lat*e.DEG2RAD,d=a.lon*e.DEG2RAD,f=a.dist*Math.cos(c);return new E(f* -Math.cos(d),f*Math.sin(d),a.dist*Math.sin(c),b)}function Lb(a){var b=Mb(a);return new eb(b.lon/15,b.lat,b.dist,a)}function Mb(a){var b=a.x*a.x+a.y*a.y,c=Math.sqrt(b+a.z*a.z);if(0===b){if(0===a.z)throw"Zero-length vector not allowed.";var d=0;a=0>a.z?-90:90}else d=e.RAD2DEG*Math.atan2(a.y,a.x),0>d&&(d+=360),a=e.RAD2DEG*Math.atan2(a.z,Math.sqrt(b));return new va(a,d,c)}function Ac(a){a=360-a;360<=a?a-=360:0>a&&(a+=360);return a}function La(a,b){w(b);if(-90>b||90c&&(c=-1);c=1.02/Math.tan((c+10.3/(c+5.11))*e.DEG2RAD)/60;"normal"===a&&-1>b&&(c*=(b+90)/89)}else{if(a)throw"Invalid refraction option: "+a;c=0}return c}function Bc(a,b){if(-90>b||90Math.abs(d))return c-b;c-=d}}function Ua(a,b){return new E(a.rot[0][0]*b.x+a.rot[1][0]*b.y+a.rot[2][0]*b.z,a.rot[0][1]*b.x+a.rot[1][1]*b.y+a.rot[2][1]*b.z,a.rot[0][2]*b.x+a.rot[1][2]*b.y+a.rot[2][2]*b.z,b.t)}function ya(a,b){return new I(a.rot[0][0]* -b.x+a.rot[1][0]*b.y+a.rot[2][0]*b.z,a.rot[0][1]*b.x+a.rot[1][1]*b.y+a.rot[2][1]*b.z,a.rot[0][2]*b.x+a.rot[1][2]*b.y+a.rot[2][2]*b.z,a.rot[0][0]*b.vx+a.rot[1][0]*b.vy+a.rot[2][0]*b.vz,a.rot[0][1]*b.vx+a.rot[1][1]*b.vy+a.rot[2][1]*b.vz,a.rot[0][2]*b.vx+a.rot[1][2]*b.vy+a.rot[2][2]*b.vz,b.t)}function Cc(){return new L([[1,0,0],[0,.9174821430670688,-.3977769691083922],[0,.3977769691083922,.9174821430670688]])}function Nb(a){a=v(a);var b=Ja(a,G.From2000);a=Ka(a,G.From2000);return Fa(b,a)}function Ob(a){a= -v(a);var b=Ka(a,G.Into2000);a=Ja(a,G.Into2000);return Fa(b,a)}function Pb(a,b){a=v(a);var c=Math.sin(b.latitude*e.DEG2RAD),d=Math.cos(b.latitude*e.DEG2RAD),f=Math.sin(b.longitude*e.DEG2RAD),g=Math.cos(b.longitude*e.DEG2RAD);b=[d*g,d*f,c];c=[-c*g,-c*f,d];f=[f,-g,0];a=-15*ba(a);b=sa(a,b);c=sa(a,c);a=sa(a,f);return new L([[c[0],a[0],b[0]],[c[1],a[1],b[1]],[c[2],a[2],b[2]]])}function Dc(a,b){a=Pb(a,b);return Ea(a)}function Ec(a,b){a=v(a);b=Dc(a,b);a=Ob(a);return Fa(b,a)}function Fc(a){a=Ob(a);var b=Cc(); -return Fa(a,b)}function Gc(a){a=Fc(a);return Ea(a)}function Hc(a,b){a=v(a);var c=Gc(a);a=Pb(a,b);return Fa(c,a)}function Va(a,b,c,d){var f=(d.x*c.x+d.y*c.y+d.z*c.z)/(d.x*d.x+d.y*d.y+d.z*d.z);return new td(b,f,e.KM_PER_AU*Math.hypot(f*d.x-c.x,f*d.y-c.y,f*d.z-c.z),695700-(1+f)*(695700-a),-695700+(1+f)*(695700+a),c,d)}function ob(a){var b=W(m.Sun,a,!0);b=new E(-b.x,-b.y,-b.z,b.t);var c=Y(a);return Va(6459,a,c,b)}function Ic(a){var b=W(m.Sun,a,!0),c=Y(a),d=new E(-c.x,-c.y,-c.z,c.t);c.x-=b.x;c.y-=b.y; -c.z-=b.z;return Va(1737.4,a,d,c)}function Qb(a,b){var c=bc(a,b);b=W(m.Sun,a,!0);var d=Y(a);c=new E(c[0]-d.x,c[1]-d.y,c[2]-d.z,a);d.x-=b.x;d.y-=b.y;d.z-=b.z;return Va(1737.4,a,c,d)}function pb(a,b,c){a=W(a,c,!0);var d=W(m.Sun,c,!0),f=new E(a.x-d.x,a.y-d.y,a.z-d.z,c);d.x=-a.x;d.y=-a.y;d.z=-a.z;return Va(b,c,d,f)}function Rb(a,b){var c=1/86400,d=b.AddDays(-c);b=b.AddDays(+c);d=a(d);return(a(b).r-d.r)/c}function ud(a){var b=a.AddDays(-.03);a=a.AddDays(.03);b=J(function(c){return Rb(ob,c)},b,a);if(!b)throw"Failed to find peak Earth shadow time."; -return ob(b)}function vd(a){var b=a.AddDays(-.03);a=a.AddDays(.03);b=J(function(c){return Rb(Ic,c)},b,a);if(!b)throw"Failed to find peak Moon shadow time.";return Ic(b)}function wd(a,b,c){var d=c.AddDays(-1);c=c.AddDays(1);d=J(function(f){var g=1/86400,h=pb(a,b,f.AddDays(-g));return(pb(a,b,f.AddDays(+g)).r-h.r)/g},d,c);if(!d)throw"Failed to find peak planet shadow time.";return pb(a,b,d)}function xd(a,b){function c(g){return Qb(g,b)}var d=a.AddDays(-.2),f=a.AddDays(.2);d=J(function(g){return Rb(c, -g)},d,f);if(!d)throw"PeakLocalMoonShadow: search failure for search_center_time = "+a;return Qb(d,b)}function Sb(a,b,c){var d=c/1440;c=a.AddDays(-d);d=a.AddDays(+d);c=J(function(f){return-(ob(f).r-b)},c,a);a=J(function(f){return+(ob(f).r-b)},a,d);if(!c||!a)throw"Failed to find shadow semiduration";return 720*(a.ut-c.ut)}function Tb(a){a=da(a);return e.RAD2DEG*a.geo_eclip_lat}function Jc(a,b,c){if(0>=a)throw"Radius of first disc must be positive.";if(0>=b)throw"Radius of second disc must be positive."; -if(0>c)throw"Distance between discs is not allowed to be negative.";if(c>=a+b)return 0;if(0==c)return a<=b?1:b*b/(a*a);var d=(a*a-b*b+c*c)/(2*c),f=a*a-d*d;if(0>=f)return a<=b?1:b*b/(a*a);f=Math.sqrt(f);return(a*a*Math.acos(d/a)-d*f+(b*b*Math.acos((c-d)/b)-(c-d)*f))/(Math.PI*a*a)}function Kc(a,b){var c=new E(a.x+b.x,a.y+b.y,a.z+b.z,a.t);a=Math.asin(Lc/c.Length());var d=Math.asin(yd/b.Length());b=N(b,c);b=Jc(a,d,b*e.DEG2RAD);return Math.min(.9999,b)}function Mc(a){a=v(a);for(var b=0;12>b;++b){var c= -Sa(180,a,40);if(!c)throw"Cannot find full moon.";a=Tb(c);if(1.8>Math.abs(a)&&(a=ud(c),a.rb;++b){var c=Sa(0,a,40);if(!c)throw"Cannot find new moon";a=Tb(c); -if(1.8>Math.abs(a)&&(a=vd(c),a.r=d?d+=360:180h.r)throw"Unexpected shadow distance from geoid intersection = "+h.r;g=.014Math.abs(c)){var d=xd(a,b);if(d.rBa(a,d)&&(b=wd(a,c,d),b.r=c.lat*f.lat){a.$jscomp$loop$prop$kind$33= -f.lat>c.lat?oa.Ascending:oa.Descending;b=J(function(g){return function(h){return g.$jscomp$loop$prop$kind$33*ib(h).lat}}(a),b,d);if(!b)throw"Could not find moon node.";return new $c(a.$jscomp$loop$prop$kind$33,b)}b=d;c=f}}function ad(a,b,c,d,f){if(1>a||5=c)throw"Major mass must be a positive number.";if(!Number.isFinite(f)||0>=f)throw"Minor mass must be a negative number.";var g=d.x-b.x,h=d.y-b.y,l=d.z-b.z,k=g*g+h*h+l*l,n=Math.sqrt(k), -p=d.vx-b.vx,q=d.vy-b.vy;d=d.vz-b.vz;if(4===a||5===a){k=h*d-l*q;c=l*p-g*d;var u=g*q-h*p,z=c*l-u*h;u=u*g-k*l;k=k*h-c*g;c=Math.sqrt(z*z+u*u+k*k);z/=c;u/=c;k/=c;g/=n;h/=n;l/=n;a=4==a?.8660254037844386:-.8660254037844386;c=.5*g+a*z;f=.5*h+a*u;var x=.5*l+a*k,B=p*g+q*h+d*l;p=p*z+q*u+d*k;b=new I(n*c,n*f,n*x,B*c+p*(.5*z-a*g),B*f+p*(.5*u-a*h),B*x+p*(.5*k-a*l),b.t)}else{z=f/(c+f)*-n;u=c/(c+f)*+n;k=(c+f)/(k*n);if(1===a||2===a)x=c/(c+f)*Math.cbrt(f/(3*c)),c=-c,1==a?(x=1-x,a=+f):(x=1+x,a=-f);else if(3===a)x=(7/ -12*f-c)/(f+c),c=+c,a=+f;else throw"Invalid Langrage point "+a+". Must be an integer 1..5.";f=n*x-z;do x=f-z,B=f-u,x=(k*f+c/(x*x)+a/(B*B))/(k-2*c/(x*x*x)-2*a/(B*B*B)),f-=x;while(1E-14f)throw"Invalid star body: "+a;w(b);w(c);w(d);if(0>b||24<=b)throw"Invalid right ascension for star: "+b;if(-90>c||90d)throw"Invalid star distance: "+d;nc[f]={ra:b,dec:c,dist:d*e.AU_PER_LY}};var G;(function(a){a[a.From2000=0]="From2000";a[a.Into2000=1]="Into2000"})(G||(G={}));var Z={Mercury:{OrbitalPeriod:87.969},Venus:{OrbitalPeriod:224.701},Earth:{OrbitalPeriod:365.256},Mars:{OrbitalPeriod:686.98},Jupiter:{OrbitalPeriod:4332.589}, -Saturn:{OrbitalPeriod:10759.22},Uranus:{OrbitalPeriod:30685.4},Neptune:{OrbitalPeriod:60189},Pluto:{OrbitalPeriod:90560}};e.PlanetOrbitalPeriod=function(a){if(a in Z)return Z[a].OrbitalPeriod;throw"Unknown orbital period for: "+a;};var M={Mercury:[[[[4.40250710144,0,0],[.40989414977,1.48302034195,26087.9031415742],[.050462942,4.47785489551,52175.8062831484],[.00855346844,1.16520322459,78263.70942472259],[.00165590362,4.11969163423,104351.61256629678],[3.4561897E-4,.77930768443,130439.51570787099], -[7.583476E-5,3.71348404924,156527.41884944518]],[[26087.90313685529,0,0],[.01131199811,6.21874197797,26087.9031415742],[.00292242298,3.04449355541,52175.8062831484],[7.5775081E-4,6.08568821653,78263.70942472259],[1.9676525E-4,2.80965111777,104351.61256629678]]],[[[.11737528961,1.98357498767,26087.9031415742],[.02388076996,5.03738959686,52175.8062831484],[.01222839532,3.14159265359,0],[.0054325181,1.79644363964,78263.70942472259],[.0012977877,4.83232503958,104351.61256629678],[3.1866927E-4,1.58088495658, -130439.51570787099],[7.963301E-5,4.60972126127,156527.41884944518]],[[.00274646065,3.95008450011,26087.9031415742],[9.9737713E-4,3.14159265359,0]]],[[[.39528271651,0,0],[.07834131818,6.19233722598,26087.9031415742],[.00795525558,2.95989690104,52175.8062831484],[.00121281764,6.01064153797,78263.70942472259],[2.1921969E-4,2.77820093972,104351.61256629678],[4.354065E-5,5.82894543774,130439.51570787099]],[[.0021734774,4.65617158665,26087.9031415742],[4.4141826E-4,1.42385544001,52175.8062831484]]]],Venus:[[[[3.17614666774, -0,0],[.01353968419,5.59313319619,10213.285546211],[8.9891645E-4,5.30650047764,20426.571092422],[5.477194E-5,4.41630661466,7860.4193924392],[3.455741E-5,2.6996444782,11790.6290886588],[2.372061E-5,2.99377542079,3930.2096962196],[1.317168E-5,5.18668228402,26.2983197998],[1.664146E-5,4.25018630147,1577.3435424478],[1.438387E-5,4.15745084182,9683.5945811164],[1.200521E-5,6.15357116043,30639.856638633]],[[10213.28554621638,0,0],[9.5617813E-4,2.4640651111,10213.285546211],[7.787201E-5,.6247848222,20426.571092422]]], -[[[.05923638472,.26702775812,10213.285546211],[4.0107978E-4,1.14737178112,20426.571092422],[3.2814918E-4,3.14159265359,0]],[[.00287821243,1.88964962838,10213.285546211]]],[[[.72334820891,0,0],[.00489824182,4.02151831717,10213.285546211],[1.658058E-5,4.90206728031,20426.571092422],[1.378043E-5,1.12846591367,11790.6290886588],[1.632096E-5,2.84548795207,7860.4193924392],[4.98395E-6,2.58682193892,9683.5945811164],[2.21985E-6,2.01346696541,19367.1891622328],[2.37454E-6,2.55136053886,15720.8387848784]], -[[3.4551041E-4,.89198706276,10213.285546211]]]],Earth:[[[[1.75347045673,0,0],[.03341656453,4.66925680415,6283.0758499914],[3.4894275E-4,4.62610242189,12566.1516999828],[3.417572E-5,2.82886579754,3.523118349],[3.497056E-5,2.74411783405,5753.3848848968],[3.135899E-5,3.62767041756,77713.7714681205],[2.676218E-5,4.41808345438,7860.4193924392],[2.342691E-5,6.13516214446,3930.2096962196],[1.273165E-5,2.03709657878,529.6909650946],[1.324294E-5,.74246341673,11506.7697697936],[9.01854E-6,2.04505446477,26.2983197998], -[1.199167E-5,1.10962946234,1577.3435424478],[8.57223E-6,3.50849152283,398.1490034082],[7.79786E-6,1.17882681962,5223.6939198022],[9.9025E-6,5.23268072088,5884.9268465832],[7.53141E-6,2.53339052847,5507.5532386674],[5.05267E-6,4.58292599973,18849.2275499742],[4.92392E-6,4.20505711826,775.522611324],[3.56672E-6,2.91954114478,.0673103028],[2.84125E-6,1.89869240932,796.2980068164],[2.42879E-6,.34481445893,5486.777843175],[3.17087E-6,5.84901948512,11790.6290886588],[2.71112E-6,.31486255375,10977.078804699], -[2.06217E-6,4.80646631478,2544.3144198834],[2.05478E-6,1.86953770281,5573.1428014331],[2.02318E-6,2.45767790232,6069.7767545534],[1.26225E-6,1.08295459501,20.7753954924],[1.55516E-6,.83306084617,213.299095438]],[[6283.0758499914,0,0],[.00206058863,2.67823455808,6283.0758499914],[4.303419E-5,2.63512233481,12566.1516999828]],[[8.721859E-5,1.07253635559,6283.0758499914]]],[[],[[.00227777722,3.4137662053,6283.0758499914],[3.805678E-5,3.37063423795,12566.1516999828]]],[[[1.00013988784,0,0],[.01670699632, -3.09846350258,6283.0758499914],[1.3956024E-4,3.05524609456,12566.1516999828],[3.08372E-5,5.19846674381,77713.7714681205],[1.628463E-5,1.17387558054,5753.3848848968],[1.575572E-5,2.84685214877,7860.4193924392],[9.24799E-6,5.45292236722,11506.7697697936],[5.42439E-6,4.56409151453,3930.2096962196],[4.7211E-6,3.66100022149,5884.9268465832],[8.5831E-7,1.27079125277,161000.6857376741],[5.7056E-7,2.01374292245,83996.84731811189],[5.5736E-7,5.2415979917,71430.69561812909],[1.74844E-6,3.01193636733,18849.2275499742], -[2.43181E-6,4.2734953079,11790.6290886588]],[[.00103018607,1.10748968172,6283.0758499914],[1.721238E-5,1.06442300386,12566.1516999828]],[[4.359385E-5,5.78455133808,6283.0758499914]]]],Mars:[[[[6.20347711581,0,0],[.18656368093,5.0503710027,3340.6124266998],[.01108216816,5.40099836344,6681.2248533996],[9.1798406E-4,5.75478744667,10021.8372800994],[2.7744987E-4,5.97049513147,3.523118349],[1.0610235E-4,2.93958560338,2281.2304965106],[1.2315897E-4,.84956094002,2810.9214616052],[8.926784E-5,4.15697846427, -.0172536522],[8.715691E-5,6.11005153139,13362.4497067992],[6.797556E-5,.36462229657,398.1490034082],[7.774872E-5,3.33968761376,5621.8429232104],[3.575078E-5,1.6618650571,2544.3144198834],[4.161108E-5,.22814971327,2942.4634232916],[3.075252E-5,.85696614132,191.4482661116],[2.628117E-5,.64806124465,3337.0893083508],[2.937546E-5,6.07893711402,.0673103028],[2.389414E-5,5.03896442664,796.2980068164],[2.579844E-5,.02996736156,3344.1355450488],[1.528141E-5,1.14979301996,6151.533888305],[1.798806E-5,.65634057445, -529.6909650946],[1.264357E-5,3.62275122593,5092.1519581158],[1.286228E-5,3.06796065034,2146.1654164752],[1.546404E-5,2.91579701718,1751.539531416],[1.024902E-5,3.69334099279,8962.4553499102],[8.91566E-6,.18293837498,16703.062133499],[8.58759E-6,2.4009381194,2914.0142358238],[8.32715E-6,2.46418619474,3340.5951730476],[8.3272E-6,4.49495782139,3340.629680352],[7.12902E-6,3.66335473479,1059.3819301892],[7.48723E-6,3.82248614017,155.4203994342],[7.23861E-6,.67497311481,3738.761430108],[6.35548E-6,2.92182225127, -8432.7643848156],[6.55162E-6,.48864064125,3127.3133312618],[5.50474E-6,3.81001042328,.9803210682],[5.5275E-6,4.47479317037,1748.016413067],[4.25966E-6,.55364317304,6283.0758499914],[4.15131E-6,.49662285038,213.299095438],[4.72167E-6,3.62547124025,1194.4470102246],[3.06551E-6,.38052848348,6684.7479717486],[3.12141E-6,.99853944405,6677.7017350506],[2.93198E-6,4.22131299634,20.7753954924],[3.02375E-6,4.48618007156,3532.0606928114],[2.74027E-6,.54222167059,3340.545116397],[2.81079E-6,5.88163521788,1349.8674096588], -[2.31183E-6,1.28242156993,3870.3033917944],[2.83602E-6,5.7688543494,3149.1641605882],[2.36117E-6,5.75503217933,3333.498879699],[2.74033E-6,.13372524985,3340.6797370026],[2.99395E-6,2.78323740866,6254.6266625236]],[[3340.61242700512,0,0],[.01457554523,3.60433733236,3340.6124266998],[.00168414711,3.92318567804,6681.2248533996],[2.0622975E-4,4.26108844583,10021.8372800994],[3.452392E-5,4.7321039319,3.523118349],[2.586332E-5,4.60670058555,13362.4497067992],[8.41535E-6,4.45864030426,2281.2304965106]], -[[5.8152577E-4,2.04961712429,3340.6124266998],[1.3459579E-4,2.45738706163,6681.2248533996]]],[[[.03197134986,3.76832042431,3340.6124266998],[.00298033234,4.10616996305,6681.2248533996],[.00289104742,0,0],[3.1365539E-4,4.4465105309,10021.8372800994],[3.4841E-5,4.7881254926,13362.4497067992]],[[.00217310991,6.04472194776,3340.6124266998],[2.0976948E-4,3.14159265359,0],[1.2834709E-4,1.60810667915,6681.2248533996]]],[[[1.53033488271,0,0],[.1418495316,3.47971283528,3340.6124266998],[.00660776362,3.81783443019, -6681.2248533996],[4.6179117E-4,4.15595316782,10021.8372800994],[8.109733E-5,5.55958416318,2810.9214616052],[7.485318E-5,1.77239078402,5621.8429232104],[5.523191E-5,1.3643630377,2281.2304965106],[3.82516E-5,4.49407183687,13362.4497067992],[2.306537E-5,.09081579001,2544.3144198834],[1.999396E-5,5.36059617709,3337.0893083508],[2.484394E-5,4.9254563992,2942.4634232916],[1.960195E-5,4.74249437639,3344.1355450488],[1.167119E-5,2.11260868341,5092.1519581158],[1.102816E-5,5.00908403998,398.1490034082],[8.99066E-6, -4.40791133207,529.6909650946],[9.92252E-6,5.83861961952,6151.533888305],[8.07354E-6,2.10217065501,1059.3819301892],[7.97915E-6,3.44839203899,796.2980068164],[7.40975E-6,1.49906336885,2146.1654164752]],[[.01107433345,2.03250524857,3340.6124266998],[.00103175887,2.37071847807,6681.2248533996],[1.28772E-4,0,0],[1.081588E-4,2.70888095665,10021.8372800994]],[[4.4242249E-4,.47930604954,3340.6124266998],[8.138042E-5,.86998389204,6681.2248533996]]]],Jupiter:[[[[.59954691494,0,0],[.09695898719,5.06191793158, -529.6909650946],[.00573610142,1.44406205629,7.1135470008],[.00306389205,5.41734730184,1059.3819301892],[9.7178296E-4,4.14264726552,632.7837393132],[7.2903078E-4,3.64042916389,522.5774180938],[6.4263975E-4,3.41145165351,103.0927742186],[3.9806064E-4,2.29376740788,419.4846438752],[3.8857767E-4,1.27231755835,316.3918696566],[2.7964629E-4,1.7845459182,536.8045120954],[1.358973E-4,5.7748104079,1589.0728952838],[8.246349E-5,3.5822792584,206.1855484372],[8.768704E-5,3.63000308199,949.1756089698],[7.368042E-5, -5.0810119427,735.8765135318],[6.26315E-5,.02497628807,213.299095438],[6.114062E-5,4.51319998626,1162.4747044078],[4.905396E-5,1.32084470588,110.2063212194],[5.305285E-5,1.30671216791,14.2270940016],[5.305441E-5,4.18625634012,1052.2683831884],[4.647248E-5,4.69958103684,3.9321532631],[3.045023E-5,4.31676431084,426.598190876],[2.609999E-5,1.56667394063,846.0828347512],[2.028191E-5,1.06376530715,3.1813937377],[1.764763E-5,2.14148655117,1066.49547719],[1.722972E-5,3.88036268267,1265.5674786264],[1.920945E-5, -.97168196472,639.897286314],[1.633223E-5,3.58201833555,515.463871093],[1.431999E-5,4.29685556046,625.6701923124],[9.73272E-6,4.09764549134,95.9792272178]],[[529.69096508814,0,0],[.00489503243,4.2208293947,529.6909650946],[.00228917222,6.02646855621,7.1135470008],[3.0099479E-4,4.54540782858,1059.3819301892],[2.072092E-4,5.45943156902,522.5774180938],[1.2103653E-4,.16994816098,536.8045120954],[6.067987E-5,4.42422292017,103.0927742186],[5.433968E-5,3.98480737746,419.4846438752],[4.237744E-5,5.89008707199, -14.2270940016]],[[4.7233601E-4,4.32148536482,7.1135470008],[3.0649436E-4,2.929777887,529.6909650946],[1.4837605E-4,3.14159265359,0]]],[[[.02268615702,3.55852606721,529.6909650946],[.00109971634,3.90809347197,1059.3819301892],[.00110090358,0,0],[8.101428E-5,3.60509572885,522.5774180938],[6.043996E-5,4.25883108339,1589.0728952838],[6.437782E-5,.30627119215,536.8045120954]],[[7.8203446E-4,1.52377859742,529.6909650946]]],[[[5.20887429326,0,0],[.25209327119,3.49108639871,529.6909650946],[.00610599976, -3.84115365948,1059.3819301892],[.00282029458,2.57419881293,632.7837393132],[.00187647346,2.07590383214,522.5774180938],[8.6792905E-4,.71001145545,419.4846438752],[7.2062974E-4,.21465724607,536.8045120954],[6.5517248E-4,5.9799588479,316.3918696566],[2.9134542E-4,1.67759379655,103.0927742186],[3.0135335E-4,2.16132003734,949.1756089698],[2.3453271E-4,3.54023522184,735.8765135318],[2.2283743E-4,4.19362594399,1589.0728952838],[2.3947298E-4,.2745803748,7.1135470008],[1.3032614E-4,2.96042965363,1162.4747044078], -[9.70336E-5,1.90669633585,206.1855484372],[1.2749023E-4,2.71550286592,1052.2683831884],[7.057931E-5,2.18184839926,1265.5674786264],[6.137703E-5,6.26418240033,846.0828347512],[2.616976E-5,2.00994012876,1581.959348283]],[[.0127180152,2.64937512894,529.6909650946],[6.1661816E-4,3.00076460387,1059.3819301892],[5.3443713E-4,3.89717383175,522.5774180938],[3.1185171E-4,4.88276958012,536.8045120954],[4.1390269E-4,0,0]]]],Saturn:[[[[.87401354025,0,0],[.11107659762,3.96205090159,213.299095438],[.01414150957, -4.58581516874,7.1135470008],[.00398379389,.52112032699,206.1855484372],[.00350769243,3.30329907896,426.598190876],[.00206816305,.24658372002,103.0927742186],[7.92713E-4,3.84007056878,220.4126424388],[2.3990355E-4,4.66976924553,110.2063212194],[1.6573588E-4,.43719228296,419.4846438752],[1.4906995E-4,5.76903183869,316.3918696566],[1.582029E-4,.93809155235,632.7837393132],[1.4609559E-4,1.56518472,3.9321532631],[1.3160301E-4,4.44891291899,14.2270940016],[1.5053543E-4,2.71669915667,639.897286314],[1.3005299E-4, -5.98119023644,11.0457002639],[1.0725067E-4,3.12939523827,202.2533951741],[5.863206E-5,.23656938524,529.6909650946],[5.227757E-5,4.20783365759,3.1813937377],[6.126317E-5,1.76328667907,277.0349937414],[5.019687E-5,3.17787728405,433.7117378768],[4.59255E-5,.61977744975,199.0720014364],[4.005867E-5,2.24479718502,63.7358983034],[2.953796E-5,.98280366998,95.9792272178],[3.87367E-5,3.22283226966,138.5174968707],[2.461186E-5,2.03163875071,735.8765135318],[3.269484E-5,.77492638211,949.1756089698],[1.758145E-5, -3.2658010994,522.5774180938],[1.640172E-5,5.5050445305,846.0828347512],[1.391327E-5,4.02333150505,323.5054166574],[1.580648E-5,4.37265307169,309.2783226558],[1.123498E-5,2.83726798446,415.5524906121],[1.017275E-5,3.71700135395,227.5261894396],[8.48642E-6,3.1915017083,209.3669421749]],[[213.2990952169,0,0],[.01297370862,1.82834923978,213.299095438],[.00564345393,2.88499717272,7.1135470008],[9.3734369E-4,1.06311793502,426.598190876],[.00107674962,2.27769131009,206.1855484372],[4.0244455E-4,2.04108104671, -220.4126424388],[1.9941774E-4,1.2795439047,103.0927742186],[1.0511678E-4,2.7488034213,14.2270940016],[6.416106E-5,.38238295041,639.897286314],[4.848994E-5,2.43037610229,419.4846438752],[4.056892E-5,2.92133209468,110.2063212194],[3.768635E-5,3.6496533078,3.9321532631]],[[.0011644133,1.17988132879,7.1135470008],[9.1841837E-4,.0732519584,213.299095438],[3.6661728E-4,0,0],[1.5274496E-4,4.06493179167,206.1855484372]]],[[[.04330678039,3.60284428399,213.299095438],[.00240348302,2.85238489373,426.598190876], -[8.4745939E-4,0,0],[3.0863357E-4,3.48441504555,220.4126424388],[3.4116062E-4,.57297307557,206.1855484372],[1.473407E-4,2.11846596715,639.897286314],[9.916667E-5,5.79003188904,419.4846438752],[6.993564E-5,4.7360468972,7.1135470008],[4.807588E-5,5.43305312061,316.3918696566]],[[.00198927992,4.93901017903,213.299095438],[3.6947916E-4,3.14159265359,0],[1.7966989E-4,.5197943111,426.598190876]]],[[[9.55758135486,0,0],[.52921382865,2.39226219573,213.299095438],[.01873679867,5.2354960466,206.1855484372], +Math.floor(a)}function N(a,b){var c=a.x*a.x+a.y*a.y+a.z*a.z;if(1E-8>Math.abs(c))throw"AngleBetween: first vector is too short.";var d=b.x*b.x+b.y*b.y+b.z*b.z;if(1E-8>Math.abs(d))throw"AngleBetween: second vector is too short.";a=(a.x*b.x+a.y*b.y+a.z*b.z)/Math.sqrt(c*d);return-1>=a?180:1<=a?0:e.RAD2DEG*Math.acos(a)}function U(a){a=jd.indexOf(a);return 0<=a?kd[a]:null}function pa(a){return(a=U(a))&&0b)return a=(b-1820)/100,-20+32*a*a; +if(500>b){a=b/100;b=a*a;var c=a*b;return 10583.6-1014.41*a+33.78311*b-5.952053*c-.1798452*b*b+.022174192*b*c+.0090316521*c*c}if(1600>b)return a=(b-1E3)/100,b=a*a,c=a*b,1574.2-556.01*a+71.23472*b+.319781*c-.8503463*b*b-.005050998*b*c+.0083572073*c*c;if(1700>b)return a=b-1600,b=a*a,120-.9808*a-.01532*b+a*b/7129;if(1800>b)return a=b-1700,b=a*a,8.83+.1603*a-.0059285*b+1.3336E-4*a*b-b*b/1174E3;if(1860>b){a=b-1800;b=a*a;c=a*b;var d=b*b;return 13.72-.332447*a+.0068612*b+.0041116*c-3.7436E-4*d+1.21272E-5* +b*c-1.699E-7*c*c+8.75E-10*c*d}if(1900>b)return a=b-1860,b=a*a,c=a*b,7.62+.5737*a-.251754*b+.01680668*c-4.473624E-4*b*b+b*c/233174;if(1920>b)return a=b-1900,b=a*a,-2.79+1.494119*a-.0598939*b+.0061966*a*b-1.97E-4*b*b;if(1941>b)return a=b-1920,b=a*a,21.2+.84493*a-.0761*b+.0020936*a*b;if(1961>b)return a=b-1950,b=a*a,29.07+.407*a-b/233+a*b/2547;if(1986>b)return a=b-1975,b=a*a,45.45+1.067*a-b/260-a*b/718;if(2005>b)return a=b-2E3,b=a*a,c=a*b,63.86+.3345*a-.060374*b+.0017275*c+6.51814E-4*b*b+2.373599E-5* +b*c;if(2050>b)return a=b-2E3,62.92+.32217*a+.005589*a*a;if(2150>b)return a=(b-1820)/100,-20+32*a*a-.5628*(2150-b);a=(b-1820)/100;return-20+32*a*a}function Wb(a){return a+Xb(a)/86400}function v(a){return a instanceof O?a:new O(a)}function Yb(a){a=a.tt/36525;return(((((-4.34E-8*a-5.76E-7)*a+.0020034)*a-1.831E-4)*a-46.836769)*a+84381.406)/3600}function Xa(a){var b;if(!Ya||1E-6=F;++F)0!==D[F]&&g(K.x,K.y,c(z,D[F],F),c(x,D[F],F),function(ra,sa){return K.x=ra,K.y=sa});return K}function k(D,F,P,ea,K,ra,sa,tb){K=l(K,ra,sa,tb);q+=D*K.y;u+=F*K.y;Za+=P*K.x;ta+=ea*K.x}++e.CalcMoonCount;a=a.tt/36525;var n,p,q,u,z=b(-6,6,1,4),x=b(-6,6,1,4);var B=a*a;var Za=u=q=0;var ta=3422.7;var ia=h(.19833+.05611*a);var fa=h(.27869+.04508*a);var V=h(.16827-.36903*a);var aa=h(.34734-5.37261*a);var Ia=h(.10498-5.37899*a);var $a=h(.42681- +.41855*a),md=h(.14943-5.37511*a);var ab=.84*ia+.31*fa+14.27*V+7.26*aa+.28*Ia+.24*$a;var vb=2.94*ia+.31*fa+14.27*V+9.34*aa+1.12*Ia+.83*$a;var bb=-6.4*ia-1.89*$a;fa=.21*ia+.31*fa+14.27*V-88.7*aa-15.3*Ia+.24*$a-1.86*md;V=ab-bb;ia=-3.332E-6*h(.59734-5.37261*a)-5.39E-7*h(.35498-5.37899*a)-6.4E-8*h(.39943-5.37511*a);ab=R*Q(.60643382+1336.85522467*a-3.13E-6*B)+ab/ha;vb=R*Q(.37489701+1325.55240982*a+2.565E-5*B)+vb/ha;bb=R*Q(.99312619+99.99735956*a-4.4E-7*B)+bb/ha;fa=R*Q(.25909118+1342.2278298*a-8.92E-6*B)+ +fa/ha;Ia=R*Q(.82736186+1236.85308708*a-3.97E-6*B)+V/ha;for(n=1;4>=n;++n){switch(n){case 1:V=vb;B=4;aa=1.000002208;break;case 2:V=bb;B=3;aa=.997504612-.002495388*a;break;case 3:V=fa;B=4;aa=1.000002708+139.978*ia;break;case 4:V=Ia;B=6;aa=1;break;default:throw"Internal error: I = "+n;}d(0,n,1);d(1,n,Math.cos(V)*aa);f(0,n,0);f(1,n,Math.sin(V)*aa);for(p=2;p<=B;++p)g(c(z,p-1,n),c(x,p-1,n),c(z,1,n),c(x,1,n),function(D,F){return d(p,n,D),f(p,n,F)});for(p=1;p<=B;++p)d(-p,n,c(z,p,n)),f(-p,n,-c(x,p,n))}k(13.902, +14.06,-.001,.2607,0,0,0,4);k(.403,-4.01,.394,.0023,0,0,0,3);k(2369.912,2373.36,.601,28.2333,0,0,0,2);k(-125.154,-112.79,-.725,-.9781,0,0,0,1);k(1.979,6.98,-.445,.0433,1,0,0,4);k(191.953,192.72,.029,3.0861,1,0,0,2);k(-8.466,-13.51,.455,-.1093,1,0,0,1);k(22639.5,22609.07,.079,186.5398,1,0,0,0);k(18.609,3.59,-.094,.0118,1,0,0,-1);k(-4586.465,-4578.13,-.077,34.3117,1,0,0,-2);k(3.215,5.44,.192,-.0386,1,0,0,-3);k(-38.428,-38.64,.001,.6008,1,0,0,-4);k(-.393,-1.43,-.092,.0086,1,0,0,-6);k(-.289,-1.59,.123, +-.0053,0,1,0,4);k(-24.42,-25.1,.04,-.3,0,1,0,2);k(18.023,17.93,.007,.1494,0,1,0,1);k(-668.146,-126.98,-1.302,-.3997,0,1,0,0);k(.56,.32,-.001,-.0037,0,1,0,-1);k(-165.145,-165.06,.054,1.9178,0,1,0,-2);k(-1.877,-6.46,-.416,.0339,0,1,0,-4);k(.213,1.02,-.074,.0054,2,0,0,4);k(14.387,14.78,-.017,.2833,2,0,0,2);k(-.586,-1.2,.054,-.01,2,0,0,1);k(769.016,767.96,.107,10.1657,2,0,0,0);k(1.75,2.01,-.018,.0155,2,0,0,-1);k(-211.656,-152.53,5.679,-.3039,2,0,0,-2);k(1.225,.91,-.03,-.0088,2,0,0,-3);k(-30.773,-34.07, +-.308,.3722,2,0,0,-4);k(-.57,-1.4,-.074,.0109,2,0,0,-6);k(-2.921,-11.75,.787,-.0484,1,1,0,2);k(1.267,1.52,-.022,.0164,1,1,0,1);k(-109.673,-115.18,.461,-.949,1,1,0,0);k(-205.962,-182.36,2.056,1.4437,1,1,0,-2);k(.233,.36,.012,-.0025,1,1,0,-3);k(-4.391,-9.66,-.471,.0673,1,1,0,-4);k(.283,1.53,-.111,.006,1,-1,0,4);k(14.577,31.7,-1.54,.2302,1,-1,0,2);k(147.687,138.76,.679,1.1528,1,-1,0,0);k(-1.089,.55,.021,0,1,-1,0,-1);k(28.475,23.59,-.443,-.2257,1,-1,0,-2);k(-.276,-.38,-.006,-.0036,1,-1,0,-3);k(.636,2.27, +.146,-.0102,1,-1,0,-4);k(-.189,-1.68,.131,-.0028,0,2,0,2);k(-7.486,-.66,-.037,-.0086,0,2,0,0);k(-8.096,-16.35,-.74,.0918,0,2,0,-2);k(-5.741,-.04,0,-9E-4,0,0,2,2);k(.255,0,0,0,0,0,2,1);k(-411.608,-.2,0,-.0124,0,0,2,0);k(.584,.84,0,.0071,0,0,2,-1);k(-55.173,-52.14,0,-.1052,0,0,2,-2);k(.254,.25,0,-.0017,0,0,2,-3);k(.025,-1.67,0,.0031,0,0,2,-4);k(1.06,2.96,-.166,.0243,3,0,0,2);k(36.124,50.64,-1.3,.6215,3,0,0,0);k(-13.193,-16.4,.258,-.1187,3,0,0,-2);k(-1.187,-.74,.042,.0074,3,0,0,-4);k(-.293,-.31,-.002, +.0046,3,0,0,-6);k(-.29,-1.45,.116,-.0051,2,1,0,2);k(-7.649,-10.56,.259,-.1038,2,1,0,0);k(-8.627,-7.59,.078,-.0192,2,1,0,-2);k(-2.74,-2.54,.022,.0324,2,1,0,-4);k(1.181,3.32,-.212,.0213,2,-1,0,2);k(9.703,11.67,-.151,.1268,2,-1,0,0);k(-.352,-.37,.001,-.0028,2,-1,0,-1);k(-2.494,-1.17,-.003,-.0017,2,-1,0,-2);k(.36,.2,-.012,-.0043,2,-1,0,-4);k(-1.167,-1.25,.008,-.0106,1,2,0,0);k(-7.412,-6.12,.117,.0484,1,2,0,-2);k(-.311,-.65,-.032,.0044,1,2,0,-4);k(.757,1.82,-.105,.0112,1,-2,0,2);k(2.58,2.32,.027,.0196, +1,-2,0,0);k(2.533,2.4,-.014,-.0212,1,-2,0,-2);k(-.344,-.57,-.025,.0036,0,3,0,-2);k(-.992,-.02,0,0,1,0,2,2);k(-45.099,-.02,0,-.001,1,0,2,0);k(-.179,-9.52,0,-.0833,1,0,2,-2);k(-.301,-.33,0,.0014,1,0,2,-4);k(-6.382,-3.37,0,-.0481,1,0,-2,2);k(39.528,85.13,0,-.7136,1,0,-2,0);k(9.366,.71,0,-.0112,1,0,-2,-2);k(.202,.02,0,0,1,0,-2,-4);k(.415,.1,0,.0013,0,1,2,0);k(-2.152,-2.26,0,-.0066,0,1,2,-2);k(-1.44,-1.3,0,.0014,0,1,-2,2);k(.384,-.04,0,0,0,1,-2,-2);k(1.938,3.6,-.145,.0401,4,0,0,0);k(-.952,-1.58,.052,-.013, +4,0,0,-2);k(-.551,-.94,.032,-.0097,3,1,0,0);k(-.482,-.57,.005,-.0045,3,1,0,-2);k(.681,.96,-.026,.0115,3,-1,0,0);k(-.297,-.27,.002,-9E-4,2,2,0,-2);k(.254,.21,-.003,0,2,-2,0,-2);k(-.25,-.22,.004,.0014,1,3,0,-2);k(-3.996,0,0,4E-4,2,0,2,0);k(.557,-.75,0,-.009,2,0,2,-2);k(-.459,-.38,0,-.0053,2,0,-2,2);k(-1.298,.74,0,4E-4,2,0,-2,0);k(.538,1.14,0,-.0141,2,0,-2,-2);k(.263,.02,0,0,1,1,2,0);k(.426,.07,0,-6E-4,1,1,-2,-2);k(-.304,.03,0,3E-4,1,-1,2,0);k(-.372,-.19,0,-.0027,1,-1,-2,2);k(.418,0,0,0,0,0,4,0);k(-.33, +-.04,0,0,3,0,2,0);B=-526.069*l(0,0,1,-2).y;B+=-3.352*l(0,0,1,-4).y;B+=44.297*l(1,0,1,-2).y;B+=-6*l(1,0,1,-4).y;B+=20.599*l(-1,0,1,0).y;B+=-30.598*l(-1,0,1,-2).y;B+=-24.649*l(-2,0,1,0).y;B+=-2*l(-2,0,1,-2).y;B+=-22.571*l(0,1,1,-2).y;B+=10.985*l(0,-1,1,-2).y;q+=.82*h(.7736-62.5512*a)+.31*h(.0466-125.1025*a)+.35*h(.5785-25.1042*a)+.66*h(.4591+1335.8075*a)+.64*h(.313-91.568*a)+1.14*h(.148+1331.2898*a)+.21*h(.5918+1056.5859*a)+.44*h(.5784+1322.8595*a)+.24*h(.2275-5.7374*a)+.28*h(.2965+2.6929*a)+.33*h(.3132+ +6.3368*a);a=fa+u/ha;a=(1.000002708+139.978*ia)*(18518.511+1.189+Za)*Math.sin(a)-6.24*Math.sin(3*a)+B;return{geo_eclip_lon:R*Q((ab+q/ha)/R),geo_eclip_lat:Math.PI/648E3*a,distance_au:ha*nd/(.999953253*ta)}}function bc(a,b){return[a.rot[0][0]*b[0]+a.rot[1][0]*b[1]+a.rot[2][0]*b[2],a.rot[0][1]*b[0]+a.rot[1][1]*b[1]+a.rot[2][1]*b[2],a.rot[0][2]*b[0]+a.rot[1][2]*b[1]+a.rot[2][2]*b[2]]}function Ja(a,b,c){b=Ka(b,c);return bc(b,a)}function Ka(a,b){a=a.tt/36525;var c=84381.406,d=((((3.337E-7*a-4.67E-7)*a-.00772503)* +a+.0512623)*a-.025754)*a+c;c*=4.84813681109536E-6;var f=((((-9.51E-8*a+1.32851E-4)*a-.00114045)*a-1.0790069)*a+5038.481507)*a*4.84813681109536E-6;d*=4.84813681109536E-6;var g=((((-5.6E-8*a+1.70663E-4)*a-.00121197)*a-2.3814292)*a+10.556403)*a*4.84813681109536E-6;a=Math.sin(c);c=Math.cos(c);var h=Math.sin(-f);f=Math.cos(-f);var l=Math.sin(-d);d=Math.cos(-d);var k=Math.sin(g),n=Math.cos(g);g=n*f-h*k*d;var p=n*h*c+k*d*f*c-a*k*l,q=n*h*a+k*d*f*a+c*k*l,u=-k*f-h*n*d,z=-k*h*c+n*d*f*c-a*n*l;k=-k*h*a+n*d*f* +a+c*n*l;h*=l;n=-l*f*c-a*d;a=-l*f*a+d*c;if(b===G.Into2000)return new L([[g,p,q],[u,z,k],[h,n,a]]);if(b===G.From2000)return new L([[g,u,h],[p,z,n],[q,k,a]]);throw"Invalid precess direction";}function ba(a){if(!cb||cb.tt!==a.tt){var b=a.tt/36525,c=15*Xa(a).ee,d=(.779057273264+.00273781191135448*a.ut+a.ut%1)%1*360;0>d&&(d+=360);b=((c+.014506+((((-3.68E-8*b-2.9956E-5)*b-4.4E-7)*b+1.3915817)*b+4612.156534)*b)/3600+d)%360/15;0>b&&(b+=24);cb={tt:a.tt,st:b}}return cb.st}function wb(a,b){var c=a.latitude*e.DEG2RAD, +d=Math.sin(c);c=Math.cos(c);var f=1/Math.hypot(c,.996647180302104*d),g=a.height/1E3,h=6378.1366*f+g;b=(15*b+a.longitude)*e.DEG2RAD;a=Math.sin(b);b=Math.cos(b);return{pos:[h*c*b/e.KM_PER_AU,h*c*a/e.KM_PER_AU,(6335.438815127603*f+g)*d/e.KM_PER_AU],vel:[-7.292115E-5*h*c*a*86400/e.KM_PER_AU,7.292115E-5*h*c*b*86400/e.KM_PER_AU,0]}}function db(a,b,c){b=La(b,c);return bc(b,a)}function La(a,b){a=Xa(a);var c=a.mobl*e.DEG2RAD,d=a.tobl*e.DEG2RAD,f=4.84813681109536E-6*a.dpsi;a=Math.cos(c);c=Math.sin(c);var g= +Math.cos(d),h=Math.sin(d);d=Math.cos(f);var l=Math.sin(f);f=-l*a;var k=-l*c,n=l*g,p=d*a*g+c*h,q=d*c*g-a*h;l*=h;var u=d*a*h-c*g;a=d*c*h+a*g;if(b===G.From2000)return new L([[d,n,l],[f,p,u],[k,q,a]]);if(b===G.Into2000)return new L([[d,f,k],[n,p,q],[l,u,a]]);throw"Invalid precess direction";}function eb(a,b,c){return c===G.Into2000?Ja(db(a,b,c),b,c):db(Ja(a,b,c),b,c)}function cc(a,b){var c=ba(a);b=wb(b,c).pos;return eb(b,a,G.Into2000)}function od(a){if(!(a instanceof Array)||3!==a.length)return!1;for(var b= +0;3>b;++b){if(!(a[b]instanceof Array)||3!==a[b].length)return!1;for(var c=0;3>c;++c)if(!Number.isFinite(a[b][c]))return!1}return!0}function dc(a,b){b=new E(a[0],a[1],a[2],b);var c=b.x*b.x+b.y*b.y,d=Math.sqrt(c+b.z*b.z);if(0===c){if(0===b.z)throw"Indeterminate sky coordinates";return new fb(0,0>b.z?-90:90,d,b)}var f=e.RAD2HOUR*Math.atan2(b.y,b.x);0>f&&(f+=24);return new fb(f,e.RAD2DEG*Math.atan2(a[2],Math.sqrt(c)),d,b)}function ua(a,b){var c=a*e.DEG2RAD;a=Math.cos(c);c=Math.sin(c);return[a*b[0]+c* +b[1],a*b[1]-c*b[0],b[2]]}function gb(a,b,c,d,f){a=v(a);va(b);w(c);w(d);var g=Math.sin(b.latitude*e.DEG2RAD),h=Math.cos(b.latitude*e.DEG2RAD),l=Math.sin(b.longitude*e.DEG2RAD),k=Math.cos(b.longitude*e.DEG2RAD);b=Math.sin(d*e.DEG2RAD);var n=Math.cos(d*e.DEG2RAD),p=Math.sin(c*e.HOUR2RAD),q=Math.cos(c*e.HOUR2RAD),u=[h*k,h*l,g];g=[-g*k,-g*l,h];l=[l,-k,0];h=-15*ba(a);a=ua(h,u);u=ua(h,g);l=ua(h,l);b=[n*q,n*p,b];p=b[0]*a[0]+b[1]*a[1]+b[2]*a[2];n=b[0]*u[0]+b[1]*u[1]+b[2]*u[2];u=b[0]*l[0]+b[1]*l[1]+b[2]*l[2]; +q=Math.hypot(n,u);0n&&(n+=360)):n=0;p=e.RAD2DEG*Math.atan2(q,p);q=d;if(f&&(d=p,f=Ma(f,90-p),p-=f,0l;++l)f.push((b[l]-d*a[l])/u*c+a[l]*q);q=Math.hypot(f[0],f[1]);0c&&(c+=24)):c=0;q=e.RAD2DEG*Math.atan2(f[2],q)}return new ec(n,90-p,c,q)}function va(a){if(!(a instanceof xb))throw"Not an instance of the Observer class: "+ +a;w(a.latitude);w(a.longitude);w(a.height);if(-90>a.latitude||90b&&(b+=360));g=e.RAD2DEG*Math.atan2(c,g);a=new E(d,f,c,a.t);return new hc(a,g,b)}function Na(a){void 0===ib&&(ib=e.DEG2RAD*Xa(v(yb)).mobl,ic=Math.cos(ib),jc=Math.sin(ib));return gc(a,ic,jc)}function Y(a){a=v(a);var b=da(a),c=b.distance_au*Math.cos(b.geo_eclip_lat);b=[c*Math.cos(b.geo_eclip_lon),c*Math.sin(b.geo_eclip_lon), +b.distance_au*Math.sin(b.geo_eclip_lat)];var d=Yb(a)*e.DEG2RAD;c=Math.cos(d);d=Math.sin(d);b=Ja([b[0],b[1]*c-b[2]*d,b[1]*d+b[2]*c],a,G.Into2000);return new E(b[0],b[1],b[2],a)}function jb(a){a=v(a);a=da(a);return new xa(a.geo_eclip_lat*e.RAD2DEG,a.geo_eclip_lon*e.RAD2DEG,a.distance_au)}function Oa(a){a=v(a);var b=a.AddDays(-1E-5),c=a.AddDays(1E-5);b=Y(b);c=Y(c);return new I((b.x+c.x)/2,(b.y+c.y)/2,(b.z+c.z)/2,(c.x-b.x)/2E-5,(c.y-b.y)/2E-5,(c.z-b.z)/2E-5,a)}function zb(a){a=v(a);var b=Oa(a);return new I(b.x/ +82.30056,b.y/82.30056,b.z/82.30056,b.vx/82.30056,b.vy/82.30056,b.vz/82.30056,a)}function ja(a,b,c){var d=1,f=0;a=$jscomp.makeIterator(a);for(var g=a.next();!g.done;g=a.next()){var h=0;g=$jscomp.makeIterator(g.value);for(var l=g.next();!l.done;l=g.next()){var k=$jscomp.makeIterator(l.value);l=k.next().value;var n=k.next().value;k=k.next().value;h+=l*Math.cos(n+b*k)}h*=d;c&&(h%=R);f+=h;d*=b}return f}function Ab(a,b){var c=1,d=0,f=0,g=0;a=$jscomp.makeIterator(a);for(var h=a.next();!h.done;h=a.next()){var l= +0,k=0;h=$jscomp.makeIterator(h.value);for(var n=h.next();!n.done;n=h.next()){var p=$jscomp.makeIterator(n.value);n=p.next().value;var q=p.next().value;p=p.next().value;q+=b*p;l+=n*p*Math.sin(q);0a?0:a>=b?b-1:a}function Eb(a){var b=$jscomp.makeIterator(a);a=b.next().value;var c=$jscomp.makeIterator(b.next().value);var d=c.next().value;var f=c.next().value;c=c.next().value;var g=$jscomp.makeIterator(b.next().value);b=g.next().value;var h=g.next().value;g=g.next().value;d=new X(a,new C(d,f,c),new C(b,h,g));a=new za(d.tt);f=d.r.add(a.Sun.r);c=d.v.add(a.Sun.v);b=a.Acceleration(f);d=new Ra(d.tt,f, +c,b);return new lc(a,d)}function nc(a,b,c){a=Eb(a);for(var d=Math.ceil((b-a.grav.tt)/c),f=0;fka[50][0])c=null;else{c=mc((c-d)/29200,50);if(!Gb[c]){d=Gb[c]=[];d[0]=Eb(ka[c]).grav;d[200]=Eb(ka[c+1]).grav;var f,g=d[0].tt;for(f=1;200>f;++f)d[f]=Db(g+=146,d[f-1]).grav;g=d[200].tt;var h=[];h[200]=d[200];for(f=199;0d[1]&&(d[1]+=R);f=$jscomp.makeIterator(b.z);for(g=f.next();!g.done;g= +f.next())h=$jscomp.makeIterator(g.value),g=h.next().value,l=h.next().value,h=h.next().value,l+=c*h,d[2]+=g*Math.cos(l),d[3]+=g*Math.sin(l);f=$jscomp.makeIterator(b.zeta);for(g=f.next();!g.done;g=f.next())h=$jscomp.makeIterator(g.value),g=h.next().value,l=h.next().value,h=h.next().value,l+=c*h,d[4]+=g*Math.cos(l),d[5]+=g*Math.sin(l);f=d[0];h=d[1];g=d[2];l=d[3];c=d[4];d=d[5];var k=Math.sqrt(b.mu/(f*f*f));b=h+g*Math.sin(h)-l*Math.cos(h);do{var n=Math.cos(b);var p=Math.sin(b);n=(h-b+g*p-l*n)/(1-g*n-l* +p);b+=n}while(1E-12<=Math.abs(n));n=Math.cos(b);p=Math.sin(b);h=l*n-g*p;var q=-g*n-l*p,u=1/(1+q),z=1/(1+Math.sqrt(1-g*g-l*l));b=f*(n-g-z*l*h);h=f*(p-l+z*g*h);l=k*u*f*(-p-z*l*q);f=k*u*f*(+n+z*g*q);g=2*Math.sqrt(1-c*c-d*d);k=1-2*d*d;n=1-2*c*c;p=2*d*c;a=new I(b*k+h*p,b*p+h*n,(c*h-b*d)*g,l*k+f*p,l*p+f*n,(c*f-l*d)*g,a);return Aa(pd,a)}function ca(a,b){b=v(b);if(a in M)return wa(M[a],b);if(a===m.Pluto)return a=Fb(b,!0),new E(a.x,a.y,a.z,b);if(a===m.Sun)return new E(0,0,0,b);if(a===m.Moon){a=wa(M.Earth, +b);var c=Y(b);return new E(a.x+c.x,a.y+c.y,a.z+c.z,b)}if(a===m.EMB)return a=wa(M.Earth,b),c=Y(b),new E(a.x+c.x/82.30056,a.y+c.y/82.30056,a.z+c.z/82.30056,b);if(a===m.SSB)return a=new E(0,0,0,b),kb(a,b,m.Jupiter,2.825345909524226E-7),kb(a,b,m.Saturn,8.459715185680659E-8),kb(a,b,m.Uranus,1.292024916781969E-8),kb(a,b,m.Neptune,1.524358900784276E-8),a;if(c=pa(a))return a=new xa(c.dec,15*c.ra,c.dist),mb(a,b);throw'HelioVector: Unknown body "'+a+'"';}function la(a,b){var c=pa(a);if(c)return c.dist;b=v(b); +return a in M?ja(M[a][2],b.tt/365250,!1):ca(a,b).Length()}function oc(a,b){for(var c=b,d=0,f=0;10>f;++f){var g=a.Position(c);d=g.Length()/e.C_AUDAY;if(1d)return g;c=h}throw"Light-travel time solver did not converge: dt = "+d;}function pc(a,b,c,d){y(d);a=v(a);if(pa(c)){c=ca(c,a);if(d)return b=nb(b,a),d=new E(c.x-b.x,c.y-b.y,c.z-b.z,a),c=e.C_AUDAY/d.Length(),new E(d.x+b.vx/c,d.y+b.vy/c,d.z+b.vz/ +c,a);b=ca(b,a);return new E(c.x-b.x,c.y-b.y,c.z-b.z,a)}var f=d?new E(0,0,0,a):ca(b,a);b=new Hb(b,c,d,f);return oc(b,a)}function W(a,b,c){y(c);b=v(b);switch(a){case m.Earth:return new E(0,0,0,b);case m.Moon:return Y(b);default:return a=pc(b,m.Earth,a,c),a.t=b,a}}function ma(a,b){return new I(a.r.x,a.r.y,a.r.z,a.v.x,a.v.y,a.v.z,b)}function nb(a,b){b=v(b);switch(a){case m.Sun:return new I(0,0,0,0,0,0,b);case m.SSB:return a=new za(b.tt),new I(-a.Sun.r.x,-a.Sun.r.y,-a.Sun.r.z,-a.Sun.v.x,-a.Sun.v.y,-a.Sun.v.z, +b);case m.Mercury:case m.Venus:case m.Earth:case m.Mars:case m.Jupiter:case m.Saturn:case m.Uranus:case m.Neptune:return a=Pa(M[a],b.tt),ma(a,b);case m.Pluto:return Fb(b,!0);case m.Moon:case m.EMB:var c=Pa(M.Earth,b.tt);a=a==m.Moon?Oa(b):zb(b);return new I(a.x+c.r.x,a.y+c.r.y,a.z+c.r.z,a.vx+c.v.x,a.vy+c.v.y,a.vz+c.v.z,b);default:throw'HelioState: Unsupported body "'+a+'"';}}function qd(a,b,c,d,f){var g=(f+c)/2-d;c=(f-c)/2;if(0==g){if(0==c)return null;d=-d/c;if(-1>d||1=d)return null;f=Math.sqrt(d);d=(-c+f)/(2*g);f=(-c-f)/(2*g);if(-1<=d&&1>=d){if(-1<=f&&1>=f)return null}else if(-1<=f&&1>=f)d=f;else return null}return{t:a+d*b,df_dt:(2*g*d+c)/b}}function J(a,b,c,d){var f=w(d&&d.dt_tolerance_seconds||1);f=Math.abs(f/86400);var g=d&&d.init_f1||a(b),h=d&&d.init_f2||a(c),l=NaN,k=0;d=d&&d.iter_limit||20;for(var n=!0;;){if(++k>d)throw"Excessive iteration in Search()";var p=new O(b.ut+.5*(c.ut-b.ut)),q=p.ut-b.ut;if(Math.abs(q)(q.ut-b.ut)*(q.ut-c.ut)&&0>(z.ut-b.ut)*(z.ut-c.ut))){u=a(q);var B=a(z);if(0>u&&0<=B){g=u;h=B;b=q;c=z;l=x;n=!1;continue}}}}if(0>g&&0<=l)c=p,h=l;else if(0>l&&0<=h)b=p,g=l;else return null}}function Ba(a){for(;-180>=a;)a+=360;for(;180a;)a+=360;for(;360<=a;)a-=360;return a}function qc(a,b,c){w(a); +w(c);b=v(b);c=b.AddDays(c);return J(function(d){d=fc(d);return Ba(d.elon-a)},b,c,{dt_tolerance_seconds:.01})}function Ib(a,b,c){if(a===m.Earth||b===m.Earth)throw"The Earth does not have a longitude as seen from itself.";c=v(c);a=W(a,c,!1);a=Na(a);b=W(b,c,!1);b=Na(b);return Ca(a.elon-b.elon)}function Da(a,b){if(a==m.Earth)throw"The Earth does not have an angle as seen from itself.";var c=v(b);b=W(m.Sun,c,!0);a=W(a,c,!0);return N(b,a)}function na(a,b){if(a===m.Sun)throw"Cannot calculate heliocentric longitude of the Sun."; +a=ca(a,b);return Na(a).elon}function ob(a,b){if(a===m.Earth)throw"The illumination of the Earth is not defined.";var c=v(b),d=wa(M.Earth,c);if(a===m.Sun){var f=new E(-d.x,-d.y,-d.z,c);b=new E(0,0,0,c);d=0}else a===m.Moon?(f=Y(c),b=new E(d.x+f.x,d.y+f.y,d.z+f.z,c)):(b=ca(a,b),f=new E(b.x-d.x,b.y-d.y,b.z-d.z,c)),d=N(f,b);var g=f.Length(),h=b.Length();if(a===m.Sun)var l=rd+5*Math.log10(g);else if(a===m.Moon)a=d*e.DEG2RAD,l=a*a,a=-12.717+1.49*Math.abs(a)+.0431*l*l,l=a+=5*Math.log10(g/(385000.6/e.KM_PER_AU)* +h);else if(a===m.Saturn){var k=d;a=Na(f);l=28.06*e.DEG2RAD;var n=e.DEG2RAD*a.elat;a=Math.asin(Math.sin(n)*Math.cos(l)-Math.cos(n)*Math.sin(l)*Math.sin(e.DEG2RAD*a.elon-e.DEG2RAD*(169.51+3.82E-5*c.tt)));l=Math.sin(Math.abs(a));k=-9+.044*k+l*(-2.6+1.2*l)+5*Math.log10(h*g);a*=e.RAD2DEG;l=k;k=a}else{var p=n=l=0;switch(a){case m.Mercury:a=-.6;l=4.98;n=-4.88;p=3.02;break;case m.Venus:163.6>d?(a=-4.47,l=1.03,n=.57,p=.13):(a=.98,l=-1.02);break;case m.Mars:a=-1.52;l=1.6;break;case m.Jupiter:a=-9.4;l=.5;break; +case m.Uranus:a=-7.19;l=.25;break;case m.Neptune:a=-6.87;break;case m.Pluto:a=-1;l=4;break;default:throw"VisualMagnitude: unsupported body "+a;}var q=d/100;l=a+q*(l+q*(n+q*p))+5*Math.log10(h*g)}return new rc(c,l,d,h,g,f,b,k)}function Sa(a){if(a===m.Earth)throw"The Earth does not have a synodic period as seen from itself.";if(a===m.Moon)return 29.530588;var b=Z[a];if(!b)throw"Not a valid planet name: "+a;a=Z.Earth.OrbitalPeriod;return Math.abs(a/(a/b.OrbitalPeriod-1))}function Ea(a,b,c){function d(n){var p= +na(a,n);n=na(m.Earth,n);return Ba(g*(n-p)-b)}w(b);var f=Z[a];if(!f)throw"Cannot search relative longitude because body is not a planet: "+a;if(a===m.Earth)throw"Cannot search relative longitude for the Earth (it is always 0)";var g=f.OrbitalPeriod>Z.Earth.OrbitalPeriod?1:-1;f=Sa(a);c=v(c);var h=d(c);0l;++l){var k=-h/360*f;c=c.AddDays(k);if(1>86400*Math.abs(k))return c;k=h;h=d(c);30>Math.abs(k)&&k!==h&&(k/=k-h,.5k&&(f*=k))}throw"Relative longitude search failed to converge for "+ +a+" near "+c.toString()+" (error_angle = "+h+").";}function Jb(a){return Ib(m.Moon,m.Sun,a)}function Ta(a,b,c){function d(l){l=Jb(l);return Ba(l-a)}w(a);w(c);b=v(b);var f=d(b);if(0>c){0>f&&(f+=360);var g=-(29.530588*f)/360;f=g+1.5;if(fc)return null;f=Math.min(c,g+1.5)}c=b.AddDays(h);b=b.AddDays(f);return J(d,c,b,{dt_tolerance_seconds:.1})}function sc(a){var b=Jb(a);b=(Math.floor(b/90)+1)%4;a=Ta(90*b,a,10); +if(!a)throw"Cannot find moon quarter";return new tc(b,a)}function Kb(a,b,c,d,f,g,h){if(0>g&&0<=h)return new sd(d,f,g,h);if(0<=g&&0>h)return null;if(1786400*l||Math.min(Math.abs(g),Math.abs(h))>l/2*c)return null;l=new O((d.ut+f.ut)/2);var k=b(l);return Kb(1+a,b,c,d,l,g,k)||Kb(1+a,b,c,l,f,k,h)}function td(a,b){if(-90>b||90h||90f?(n=p.AddDays(-.42),q=l(n)):(p=n.AddDays(.42),u=l(p));var z=Kb(0,l,k,n,p,q,u);if(z){if(k=J(l,z.tx,z.ty,{dt_tolerance_seconds:.1,init_f1:z.ax,init_f2:z.ay})){if(0>f){if(k.utd.ut+f)return null;return k}throw"Rise/set search failed after finding ascent: t1="+ +n+", t2="+p+", a1="+q+", a2="+u;}if(0>f){if(n.utd.ut+f)return null;n=p;q=u}}}function vc(a,b){b=v(b);var c=Ib(a,m.Sun,b);if(1805*f;++f){var g=a.AddDays(5),h=b(g);if(0>=d*h){if(0>d||0h){a=J(c,a,g,{init_f1:-d,init_f2:-h});if(!a)throw"SearchLunarApsis INTERNAL ERROR: apogee search failed!";d=da(a).distance_au;return new Ua(a,1,d)}throw"SearchLunarApsis INTERNAL ERROR: cannot classify apsis event!";}a=g;d=h}throw"SearchLunarApsis INTERNAL ERROR: could not find apsis within 2 synodic months of start date.";}function yc(a,b,c,d){for(var f=b===Fa.Apocenter? +1:-1;;){d/=9;if(d<1/1440)return c=c.AddDays(d/2),a=la(a,c),new Ua(c,b,a);for(var g=-1,h=0,l=0;10>l;++l){var k=c.AddDays(l*d);k=f*la(a,k);if(0==l||k>h)g=l,h=k}c=c.AddDays((g-1)*d);d*=2}}function ud(a,b){var c=b.AddDays(-30/360*Z[a].OrbitalPeriod),d=b.AddDays(.75*Z[a].OrbitalPeriod),f=c,g=c,h=-1,l=-1;d=(d.ut-c.ut)/99;for(var k=0;100>k;++k){var n=c.AddDays(k*d),p=la(a,n);0===k?l=h=p:(p>l&&(l=p,g=n),p=b.tt)return a.time.tt>= +b.tt&&a.time.tt=b.tt)return a;throw"Internal error: failed to find Neptune apsis.";}function zc(a,b){function c(p){var q=p.AddDays(-5E-4);p=p.AddDays(5E-4);q=la(a,q);return(la(a,p)-q)/.001}function d(p){return-c(p)}b=v(b);if(a===m.Neptune||a===m.Pluto)return ud(a,b);for(var f=Z[a].OrbitalPeriod,g=f/6,h=c(b),l=0;l*g<2*f;++l){var k=b.AddDays(g),n=c(k);if(0>=h*n){f=g=void 0;if(0>h||0n)g=d,f=Fa.Apocenter;else throw"Internal error with slopes in SearchPlanetApsis"; +b=J(g,b,k);if(!b)throw"Failed to find slope transition in planetary apsis search.";h=la(a,b);return new Ua(b,f,h)}b=k;h=n}throw"Internal error: should have found planetary apsis within 2 orbital periods.";}function Ga(a){return new L([[a.rot[0][0],a.rot[1][0],a.rot[2][0]],[a.rot[0][1],a.rot[1][1],a.rot[2][1]],[a.rot[0][2],a.rot[1][2],a.rot[2][2]]])}function Ha(a,b){return new L([[b.rot[0][0]*a.rot[0][0]+b.rot[1][0]*a.rot[0][1]+b.rot[2][0]*a.rot[0][2],b.rot[0][1]*a.rot[0][0]+b.rot[1][1]*a.rot[0][1]+ +b.rot[2][1]*a.rot[0][2],b.rot[0][2]*a.rot[0][0]+b.rot[1][2]*a.rot[0][1]+b.rot[2][2]*a.rot[0][2]],[b.rot[0][0]*a.rot[1][0]+b.rot[1][0]*a.rot[1][1]+b.rot[2][0]*a.rot[1][2],b.rot[0][1]*a.rot[1][0]+b.rot[1][1]*a.rot[1][1]+b.rot[2][1]*a.rot[1][2],b.rot[0][2]*a.rot[1][0]+b.rot[1][2]*a.rot[1][1]+b.rot[2][2]*a.rot[1][2]],[b.rot[0][0]*a.rot[2][0]+b.rot[1][0]*a.rot[2][1]+b.rot[2][0]*a.rot[2][2],b.rot[0][1]*a.rot[2][0]+b.rot[1][1]*a.rot[2][1]+b.rot[2][1]*a.rot[2][2],b.rot[0][2]*a.rot[2][0]+b.rot[1][2]*a.rot[2][1]+ +b.rot[2][2]*a.rot[2][2]]])}function mb(a,b){b=v(b);var c=a.lat*e.DEG2RAD,d=a.lon*e.DEG2RAD,f=a.dist*Math.cos(c);return new E(f*Math.cos(d),f*Math.sin(d),a.dist*Math.sin(c),b)}function Lb(a){var b=Mb(a);return new fb(b.lon/15,b.lat,b.dist,a)}function Mb(a){var b=a.x*a.x+a.y*a.y,c=Math.sqrt(b+a.z*a.z);if(0===b){if(0===a.z)throw"Zero-length vector not allowed.";var d=0;a=0>a.z?-90:90}else d=e.RAD2DEG*Math.atan2(a.y,a.x),0>d&&(d+=360),a=e.RAD2DEG*Math.atan2(a.z,Math.sqrt(b));return new xa(a,d,c)}function Ac(a){a= +360-a;360<=a?a-=360:0>a&&(a+=360);return a}function Ma(a,b){w(b);if(-90>b||90c&&(c=-1);c=1.02/Math.tan((c+10.3/(c+5.11))*e.DEG2RAD)/60;"normal"===a&&-1>b&&(c*=(b+90)/89)}else{if(a)throw"Invalid refraction option: "+a;c=0}return c}function Bc(a,b){if(-90>b||90Math.abs(d))return c-b;c-=d}}function Va(a,b){return new E(a.rot[0][0]*b.x+a.rot[1][0]*b.y+a.rot[2][0]*b.z,a.rot[0][1]*b.x+a.rot[1][1]* +b.y+a.rot[2][1]*b.z,a.rot[0][2]*b.x+a.rot[1][2]*b.y+a.rot[2][2]*b.z,b.t)}function Aa(a,b){return new I(a.rot[0][0]*b.x+a.rot[1][0]*b.y+a.rot[2][0]*b.z,a.rot[0][1]*b.x+a.rot[1][1]*b.y+a.rot[2][1]*b.z,a.rot[0][2]*b.x+a.rot[1][2]*b.y+a.rot[2][2]*b.z,a.rot[0][0]*b.vx+a.rot[1][0]*b.vy+a.rot[2][0]*b.vz,a.rot[0][1]*b.vx+a.rot[1][1]*b.vy+a.rot[2][1]*b.vz,a.rot[0][2]*b.vx+a.rot[1][2]*b.vy+a.rot[2][2]*b.vz,b.t)}function Cc(){return new L([[1,0,0],[0,.9174821430670688,-.3977769691083922],[0,.3977769691083922, +.9174821430670688]])}function Nb(a){a=v(a);var b=Ka(a,G.From2000);a=La(a,G.From2000);return Ha(b,a)}function Ob(a){a=v(a);var b=La(a,G.Into2000);a=Ka(a,G.Into2000);return Ha(b,a)}function Pb(a,b){a=v(a);var c=Math.sin(b.latitude*e.DEG2RAD),d=Math.cos(b.latitude*e.DEG2RAD),f=Math.sin(b.longitude*e.DEG2RAD),g=Math.cos(b.longitude*e.DEG2RAD);b=[d*g,d*f,c];c=[-c*g,-c*f,d];f=[f,-g,0];a=-15*ba(a);b=ua(a,b);c=ua(a,c);a=ua(a,f);return new L([[c[0],a[0],b[0]],[c[1],a[1],b[1]],[c[2],a[2],b[2]]])}function Dc(a, +b){a=Pb(a,b);return Ga(a)}function Ec(a,b){a=v(a);b=Dc(a,b);a=Ob(a);return Ha(b,a)}function Fc(a){a=Ob(a);var b=Cc();return Ha(a,b)}function Gc(a){a=Fc(a);return Ga(a)}function Hc(a,b){a=v(a);var c=Gc(a);a=Pb(a,b);return Ha(c,a)}function Wa(a,b,c,d){var f=(d.x*c.x+d.y*c.y+d.z*c.z)/(d.x*d.x+d.y*d.y+d.z*d.z);return new vd(b,f,e.KM_PER_AU*Math.hypot(f*d.x-c.x,f*d.y-c.y,f*d.z-c.z),695700-(1+f)*(695700-a),-695700+(1+f)*(695700+a),c,d)}function pb(a){var b=W(m.Sun,a,!0);b=new E(-b.x,-b.y,-b.z,b.t);var c= +Y(a);return Wa(6459,a,c,b)}function Ic(a){var b=W(m.Sun,a,!0),c=Y(a),d=new E(-c.x,-c.y,-c.z,c.t);c.x-=b.x;c.y-=b.y;c.z-=b.z;return Wa(1737.4,a,d,c)}function Qb(a,b){var c=cc(a,b);b=W(m.Sun,a,!0);var d=Y(a);c=new E(c[0]-d.x,c[1]-d.y,c[2]-d.z,a);d.x-=b.x;d.y-=b.y;d.z-=b.z;return Wa(1737.4,a,c,d)}function qb(a,b,c){a=W(a,c,!0);var d=W(m.Sun,c,!0),f=new E(a.x-d.x,a.y-d.y,a.z-d.z,c);d.x=-a.x;d.y=-a.y;d.z=-a.z;return Wa(b,c,d,f)}function Rb(a,b){var c=1/86400,d=b.AddDays(-c);b=b.AddDays(+c);d=a(d);return(a(b).r- +d.r)/c}function wd(a){var b=a.AddDays(-.03);a=a.AddDays(.03);b=J(function(c){return Rb(pb,c)},b,a);if(!b)throw"Failed to find peak Earth shadow time.";return pb(b)}function xd(a){var b=a.AddDays(-.03);a=a.AddDays(.03);b=J(function(c){return Rb(Ic,c)},b,a);if(!b)throw"Failed to find peak Moon shadow time.";return Ic(b)}function yd(a,b,c){var d=c.AddDays(-1);c=c.AddDays(1);d=J(function(f){var g=1/86400,h=qb(a,b,f.AddDays(-g));return(qb(a,b,f.AddDays(+g)).r-h.r)/g},d,c);if(!d)throw"Failed to find peak planet shadow time."; +return qb(a,b,d)}function zd(a,b){function c(g){return Qb(g,b)}var d=a.AddDays(-.2),f=a.AddDays(.2);d=J(function(g){return Rb(c,g)},d,f);if(!d)throw"PeakLocalMoonShadow: search failure for search_center_time = "+a;return Qb(d,b)}function Sb(a,b,c){var d=c/1440;c=a.AddDays(-d);d=a.AddDays(+d);c=J(function(f){return-(pb(f).r-b)},c,a);a=J(function(f){return+(pb(f).r-b)},a,d);if(!c||!a)throw"Failed to find shadow semiduration";return 720*(a.ut-c.ut)}function Tb(a){a=da(a);return e.RAD2DEG*a.geo_eclip_lat} +function Jc(a,b,c){if(0>=a)throw"Radius of first disc must be positive.";if(0>=b)throw"Radius of second disc must be positive.";if(0>c)throw"Distance between discs is not allowed to be negative.";if(c>=a+b)return 0;if(0==c)return a<=b?1:b*b/(a*a);var d=(a*a-b*b+c*c)/(2*c),f=a*a-d*d;if(0>=f)return a<=b?1:b*b/(a*a);f=Math.sqrt(f);return(a*a*Math.acos(d/a)-d*f+(b*b*Math.acos((c-d)/b)-(c-d)*f))/(Math.PI*a*a)}function Kc(a,b){var c=new E(a.x+b.x,a.y+b.y,a.z+b.z,a.t);a=Math.asin(Lc/c.Length());var d=Math.asin(Ad/ +b.Length());b=N(b,c);b=Jc(a,d,b*e.DEG2RAD);return Math.min(.9999,b)}function Mc(a){a=v(a);for(var b=0;12>b;++b){var c=Ta(180,a,40);if(!c)throw"Cannot find full moon.";a=Tb(c);if(1.8>Math.abs(a)&&(a=wd(c),a.rb;++b){var c=Ta(0,a,40);if(!c)throw"Cannot find new moon";a=Tb(c);if(1.8>Math.abs(a)&&(a=xd(c),a.r=d?d+=360:180h.r)throw"Unexpected shadow distance from geoid intersection = "+h.r;g=.014Math.abs(c)){var d=zd(a,b);if(d.rDa(a,d)&&(b=yd(a,c,d),b.r=c.lat*f.lat){a.$jscomp$loop$prop$kind$33=f.lat>c.lat?oa.Ascending:oa.Descending;b=J(function(g){return function(h){return g.$jscomp$loop$prop$kind$33*jb(h).lat}}(a),b,d);if(!b)throw"Could not find moon node.";return new $c(a.$jscomp$loop$prop$kind$33,b)}b=d;c=f}}function ad(a,b,c,d,f){if(1>a||5=c)throw"Major mass must be a positive number."; +if(!Number.isFinite(f)||0>=f)throw"Minor mass must be a negative number.";var g=d.x-b.x,h=d.y-b.y,l=d.z-b.z,k=g*g+h*h+l*l,n=Math.sqrt(k),p=d.vx-b.vx,q=d.vy-b.vy;d=d.vz-b.vz;if(4===a||5===a){k=h*d-l*q;c=l*p-g*d;var u=g*q-h*p,z=c*l-u*h;u=u*g-k*l;k=k*h-c*g;c=Math.sqrt(z*z+u*u+k*k);z/=c;u/=c;k/=c;g/=n;h/=n;l/=n;a=4==a?.8660254037844386:-.8660254037844386;c=.5*g+a*z;f=.5*h+a*u;var x=.5*l+a*k,B=p*g+q*h+d*l;p=p*z+q*u+d*k;b=new I(n*c,n*f,n*x,B*c+p*(.5*z-a*g),B*f+p*(.5*u-a*h),B*x+p*(.5*k-a*l),b.t)}else{z= +f/(c+f)*-n;u=c/(c+f)*+n;k=(c+f)/(k*n);if(1===a||2===a)x=c/(c+f)*Math.cbrt(f/(3*c)),c=-c,1==a?(x=1-x,a=+f):(x=1+x,a=-f);else if(3===a)x=(7/12*f-c)/(f+c),c=+c,a=+f;else throw"Invalid Langrage point "+a+". Must be an integer 1..5.";f=n*x-z;do x=f-z,B=f-u,x=(k*f+c/(x*x)+a/(B*B))/(k-2*c/(x*x*x)-2*a/(B*B*B)),f-=x;while(1E-14b||24<=b)throw"Invalid right ascension for star: "+b;if(-90>c||90d)throw"Invalid star distance: "+d;f.ra=b;f.dec=c;f.dist=d*e.AU_PER_LY};var G;(function(a){a[a.From2000=0]="From2000";a[a.Into2000=1]="Into2000"})(G||(G={}));var Z={Mercury:{OrbitalPeriod:87.969},Venus:{OrbitalPeriod:224.701},Earth:{OrbitalPeriod:365.256}, +Mars:{OrbitalPeriod:686.98},Jupiter:{OrbitalPeriod:4332.589},Saturn:{OrbitalPeriod:10759.22},Uranus:{OrbitalPeriod:30685.4},Neptune:{OrbitalPeriod:60189},Pluto:{OrbitalPeriod:90560}};e.PlanetOrbitalPeriod=function(a){if(a in Z)return Z[a].OrbitalPeriod;throw"Unknown orbital period for: "+a;};var M={Mercury:[[[[4.40250710144,0,0],[.40989414977,1.48302034195,26087.9031415742],[.050462942,4.47785489551,52175.8062831484],[.00855346844,1.16520322459,78263.70942472259],[.00165590362,4.11969163423,104351.61256629678], +[3.4561897E-4,.77930768443,130439.51570787099],[7.583476E-5,3.71348404924,156527.41884944518]],[[26087.90313685529,0,0],[.01131199811,6.21874197797,26087.9031415742],[.00292242298,3.04449355541,52175.8062831484],[7.5775081E-4,6.08568821653,78263.70942472259],[1.9676525E-4,2.80965111777,104351.61256629678]]],[[[.11737528961,1.98357498767,26087.9031415742],[.02388076996,5.03738959686,52175.8062831484],[.01222839532,3.14159265359,0],[.0054325181,1.79644363964,78263.70942472259],[.0012977877,4.83232503958, +104351.61256629678],[3.1866927E-4,1.58088495658,130439.51570787099],[7.963301E-5,4.60972126127,156527.41884944518]],[[.00274646065,3.95008450011,26087.9031415742],[9.9737713E-4,3.14159265359,0]]],[[[.39528271651,0,0],[.07834131818,6.19233722598,26087.9031415742],[.00795525558,2.95989690104,52175.8062831484],[.00121281764,6.01064153797,78263.70942472259],[2.1921969E-4,2.77820093972,104351.61256629678],[4.354065E-5,5.82894543774,130439.51570787099]],[[.0021734774,4.65617158665,26087.9031415742],[4.4141826E-4, +1.42385544001,52175.8062831484]]]],Venus:[[[[3.17614666774,0,0],[.01353968419,5.59313319619,10213.285546211],[8.9891645E-4,5.30650047764,20426.571092422],[5.477194E-5,4.41630661466,7860.4193924392],[3.455741E-5,2.6996444782,11790.6290886588],[2.372061E-5,2.99377542079,3930.2096962196],[1.317168E-5,5.18668228402,26.2983197998],[1.664146E-5,4.25018630147,1577.3435424478],[1.438387E-5,4.15745084182,9683.5945811164],[1.200521E-5,6.15357116043,30639.856638633]],[[10213.28554621638,0,0],[9.5617813E-4,2.4640651111, +10213.285546211],[7.787201E-5,.6247848222,20426.571092422]]],[[[.05923638472,.26702775812,10213.285546211],[4.0107978E-4,1.14737178112,20426.571092422],[3.2814918E-4,3.14159265359,0]],[[.00287821243,1.88964962838,10213.285546211]]],[[[.72334820891,0,0],[.00489824182,4.02151831717,10213.285546211],[1.658058E-5,4.90206728031,20426.571092422],[1.378043E-5,1.12846591367,11790.6290886588],[1.632096E-5,2.84548795207,7860.4193924392],[4.98395E-6,2.58682193892,9683.5945811164],[2.21985E-6,2.01346696541,19367.1891622328], +[2.37454E-6,2.55136053886,15720.8387848784]],[[3.4551041E-4,.89198706276,10213.285546211]]]],Earth:[[[[1.75347045673,0,0],[.03341656453,4.66925680415,6283.0758499914],[3.4894275E-4,4.62610242189,12566.1516999828],[3.417572E-5,2.82886579754,3.523118349],[3.497056E-5,2.74411783405,5753.3848848968],[3.135899E-5,3.62767041756,77713.7714681205],[2.676218E-5,4.41808345438,7860.4193924392],[2.342691E-5,6.13516214446,3930.2096962196],[1.273165E-5,2.03709657878,529.6909650946],[1.324294E-5,.74246341673,11506.7697697936], +[9.01854E-6,2.04505446477,26.2983197998],[1.199167E-5,1.10962946234,1577.3435424478],[8.57223E-6,3.50849152283,398.1490034082],[7.79786E-6,1.17882681962,5223.6939198022],[9.9025E-6,5.23268072088,5884.9268465832],[7.53141E-6,2.53339052847,5507.5532386674],[5.05267E-6,4.58292599973,18849.2275499742],[4.92392E-6,4.20505711826,775.522611324],[3.56672E-6,2.91954114478,.0673103028],[2.84125E-6,1.89869240932,796.2980068164],[2.42879E-6,.34481445893,5486.777843175],[3.17087E-6,5.84901948512,11790.6290886588], +[2.71112E-6,.31486255375,10977.078804699],[2.06217E-6,4.80646631478,2544.3144198834],[2.05478E-6,1.86953770281,5573.1428014331],[2.02318E-6,2.45767790232,6069.7767545534],[1.26225E-6,1.08295459501,20.7753954924],[1.55516E-6,.83306084617,213.299095438]],[[6283.0758499914,0,0],[.00206058863,2.67823455808,6283.0758499914],[4.303419E-5,2.63512233481,12566.1516999828]],[[8.721859E-5,1.07253635559,6283.0758499914]]],[[],[[.00227777722,3.4137662053,6283.0758499914],[3.805678E-5,3.37063423795,12566.1516999828]]], +[[[1.00013988784,0,0],[.01670699632,3.09846350258,6283.0758499914],[1.3956024E-4,3.05524609456,12566.1516999828],[3.08372E-5,5.19846674381,77713.7714681205],[1.628463E-5,1.17387558054,5753.3848848968],[1.575572E-5,2.84685214877,7860.4193924392],[9.24799E-6,5.45292236722,11506.7697697936],[5.42439E-6,4.56409151453,3930.2096962196],[4.7211E-6,3.66100022149,5884.9268465832],[8.5831E-7,1.27079125277,161000.6857376741],[5.7056E-7,2.01374292245,83996.84731811189],[5.5736E-7,5.2415979917,71430.69561812909], +[1.74844E-6,3.01193636733,18849.2275499742],[2.43181E-6,4.2734953079,11790.6290886588]],[[.00103018607,1.10748968172,6283.0758499914],[1.721238E-5,1.06442300386,12566.1516999828]],[[4.359385E-5,5.78455133808,6283.0758499914]]]],Mars:[[[[6.20347711581,0,0],[.18656368093,5.0503710027,3340.6124266998],[.01108216816,5.40099836344,6681.2248533996],[9.1798406E-4,5.75478744667,10021.8372800994],[2.7744987E-4,5.97049513147,3.523118349],[1.0610235E-4,2.93958560338,2281.2304965106],[1.2315897E-4,.84956094002, +2810.9214616052],[8.926784E-5,4.15697846427,.0172536522],[8.715691E-5,6.11005153139,13362.4497067992],[6.797556E-5,.36462229657,398.1490034082],[7.774872E-5,3.33968761376,5621.8429232104],[3.575078E-5,1.6618650571,2544.3144198834],[4.161108E-5,.22814971327,2942.4634232916],[3.075252E-5,.85696614132,191.4482661116],[2.628117E-5,.64806124465,3337.0893083508],[2.937546E-5,6.07893711402,.0673103028],[2.389414E-5,5.03896442664,796.2980068164],[2.579844E-5,.02996736156,3344.1355450488],[1.528141E-5,1.14979301996, +6151.533888305],[1.798806E-5,.65634057445,529.6909650946],[1.264357E-5,3.62275122593,5092.1519581158],[1.286228E-5,3.06796065034,2146.1654164752],[1.546404E-5,2.91579701718,1751.539531416],[1.024902E-5,3.69334099279,8962.4553499102],[8.91566E-6,.18293837498,16703.062133499],[8.58759E-6,2.4009381194,2914.0142358238],[8.32715E-6,2.46418619474,3340.5951730476],[8.3272E-6,4.49495782139,3340.629680352],[7.12902E-6,3.66335473479,1059.3819301892],[7.48723E-6,3.82248614017,155.4203994342],[7.23861E-6,.67497311481, +3738.761430108],[6.35548E-6,2.92182225127,8432.7643848156],[6.55162E-6,.48864064125,3127.3133312618],[5.50474E-6,3.81001042328,.9803210682],[5.5275E-6,4.47479317037,1748.016413067],[4.25966E-6,.55364317304,6283.0758499914],[4.15131E-6,.49662285038,213.299095438],[4.72167E-6,3.62547124025,1194.4470102246],[3.06551E-6,.38052848348,6684.7479717486],[3.12141E-6,.99853944405,6677.7017350506],[2.93198E-6,4.22131299634,20.7753954924],[3.02375E-6,4.48618007156,3532.0606928114],[2.74027E-6,.54222167059,3340.545116397], +[2.81079E-6,5.88163521788,1349.8674096588],[2.31183E-6,1.28242156993,3870.3033917944],[2.83602E-6,5.7688543494,3149.1641605882],[2.36117E-6,5.75503217933,3333.498879699],[2.74033E-6,.13372524985,3340.6797370026],[2.99395E-6,2.78323740866,6254.6266625236]],[[3340.61242700512,0,0],[.01457554523,3.60433733236,3340.6124266998],[.00168414711,3.92318567804,6681.2248533996],[2.0622975E-4,4.26108844583,10021.8372800994],[3.452392E-5,4.7321039319,3.523118349],[2.586332E-5,4.60670058555,13362.4497067992],[8.41535E-6, +4.45864030426,2281.2304965106]],[[5.8152577E-4,2.04961712429,3340.6124266998],[1.3459579E-4,2.45738706163,6681.2248533996]]],[[[.03197134986,3.76832042431,3340.6124266998],[.00298033234,4.10616996305,6681.2248533996],[.00289104742,0,0],[3.1365539E-4,4.4465105309,10021.8372800994],[3.4841E-5,4.7881254926,13362.4497067992]],[[.00217310991,6.04472194776,3340.6124266998],[2.0976948E-4,3.14159265359,0],[1.2834709E-4,1.60810667915,6681.2248533996]]],[[[1.53033488271,0,0],[.1418495316,3.47971283528,3340.6124266998], +[.00660776362,3.81783443019,6681.2248533996],[4.6179117E-4,4.15595316782,10021.8372800994],[8.109733E-5,5.55958416318,2810.9214616052],[7.485318E-5,1.77239078402,5621.8429232104],[5.523191E-5,1.3643630377,2281.2304965106],[3.82516E-5,4.49407183687,13362.4497067992],[2.306537E-5,.09081579001,2544.3144198834],[1.999396E-5,5.36059617709,3337.0893083508],[2.484394E-5,4.9254563992,2942.4634232916],[1.960195E-5,4.74249437639,3344.1355450488],[1.167119E-5,2.11260868341,5092.1519581158],[1.102816E-5,5.00908403998, +398.1490034082],[8.99066E-6,4.40791133207,529.6909650946],[9.92252E-6,5.83861961952,6151.533888305],[8.07354E-6,2.10217065501,1059.3819301892],[7.97915E-6,3.44839203899,796.2980068164],[7.40975E-6,1.49906336885,2146.1654164752]],[[.01107433345,2.03250524857,3340.6124266998],[.00103175887,2.37071847807,6681.2248533996],[1.28772E-4,0,0],[1.081588E-4,2.70888095665,10021.8372800994]],[[4.4242249E-4,.47930604954,3340.6124266998],[8.138042E-5,.86998389204,6681.2248533996]]]],Jupiter:[[[[.59954691494,0, +0],[.09695898719,5.06191793158,529.6909650946],[.00573610142,1.44406205629,7.1135470008],[.00306389205,5.41734730184,1059.3819301892],[9.7178296E-4,4.14264726552,632.7837393132],[7.2903078E-4,3.64042916389,522.5774180938],[6.4263975E-4,3.41145165351,103.0927742186],[3.9806064E-4,2.29376740788,419.4846438752],[3.8857767E-4,1.27231755835,316.3918696566],[2.7964629E-4,1.7845459182,536.8045120954],[1.358973E-4,5.7748104079,1589.0728952838],[8.246349E-5,3.5822792584,206.1855484372],[8.768704E-5,3.63000308199, +949.1756089698],[7.368042E-5,5.0810119427,735.8765135318],[6.26315E-5,.02497628807,213.299095438],[6.114062E-5,4.51319998626,1162.4747044078],[4.905396E-5,1.32084470588,110.2063212194],[5.305285E-5,1.30671216791,14.2270940016],[5.305441E-5,4.18625634012,1052.2683831884],[4.647248E-5,4.69958103684,3.9321532631],[3.045023E-5,4.31676431084,426.598190876],[2.609999E-5,1.56667394063,846.0828347512],[2.028191E-5,1.06376530715,3.1813937377],[1.764763E-5,2.14148655117,1066.49547719],[1.722972E-5,3.88036268267, +1265.5674786264],[1.920945E-5,.97168196472,639.897286314],[1.633223E-5,3.58201833555,515.463871093],[1.431999E-5,4.29685556046,625.6701923124],[9.73272E-6,4.09764549134,95.9792272178]],[[529.69096508814,0,0],[.00489503243,4.2208293947,529.6909650946],[.00228917222,6.02646855621,7.1135470008],[3.0099479E-4,4.54540782858,1059.3819301892],[2.072092E-4,5.45943156902,522.5774180938],[1.2103653E-4,.16994816098,536.8045120954],[6.067987E-5,4.42422292017,103.0927742186],[5.433968E-5,3.98480737746,419.4846438752], +[4.237744E-5,5.89008707199,14.2270940016]],[[4.7233601E-4,4.32148536482,7.1135470008],[3.0649436E-4,2.929777887,529.6909650946],[1.4837605E-4,3.14159265359,0]]],[[[.02268615702,3.55852606721,529.6909650946],[.00109971634,3.90809347197,1059.3819301892],[.00110090358,0,0],[8.101428E-5,3.60509572885,522.5774180938],[6.043996E-5,4.25883108339,1589.0728952838],[6.437782E-5,.30627119215,536.8045120954]],[[7.8203446E-4,1.52377859742,529.6909650946]]],[[[5.20887429326,0,0],[.25209327119,3.49108639871,529.6909650946], +[.00610599976,3.84115365948,1059.3819301892],[.00282029458,2.57419881293,632.7837393132],[.00187647346,2.07590383214,522.5774180938],[8.6792905E-4,.71001145545,419.4846438752],[7.2062974E-4,.21465724607,536.8045120954],[6.5517248E-4,5.9799588479,316.3918696566],[2.9134542E-4,1.67759379655,103.0927742186],[3.0135335E-4,2.16132003734,949.1756089698],[2.3453271E-4,3.54023522184,735.8765135318],[2.2283743E-4,4.19362594399,1589.0728952838],[2.3947298E-4,.2745803748,7.1135470008],[1.3032614E-4,2.96042965363, +1162.4747044078],[9.70336E-5,1.90669633585,206.1855484372],[1.2749023E-4,2.71550286592,1052.2683831884],[7.057931E-5,2.18184839926,1265.5674786264],[6.137703E-5,6.26418240033,846.0828347512],[2.616976E-5,2.00994012876,1581.959348283]],[[.0127180152,2.64937512894,529.6909650946],[6.1661816E-4,3.00076460387,1059.3819301892],[5.3443713E-4,3.89717383175,522.5774180938],[3.1185171E-4,4.88276958012,536.8045120954],[4.1390269E-4,0,0]]]],Saturn:[[[[.87401354025,0,0],[.11107659762,3.96205090159,213.299095438], +[.01414150957,4.58581516874,7.1135470008],[.00398379389,.52112032699,206.1855484372],[.00350769243,3.30329907896,426.598190876],[.00206816305,.24658372002,103.0927742186],[7.92713E-4,3.84007056878,220.4126424388],[2.3990355E-4,4.66976924553,110.2063212194],[1.6573588E-4,.43719228296,419.4846438752],[1.4906995E-4,5.76903183869,316.3918696566],[1.582029E-4,.93809155235,632.7837393132],[1.4609559E-4,1.56518472,3.9321532631],[1.3160301E-4,4.44891291899,14.2270940016],[1.5053543E-4,2.71669915667,639.897286314], +[1.3005299E-4,5.98119023644,11.0457002639],[1.0725067E-4,3.12939523827,202.2533951741],[5.863206E-5,.23656938524,529.6909650946],[5.227757E-5,4.20783365759,3.1813937377],[6.126317E-5,1.76328667907,277.0349937414],[5.019687E-5,3.17787728405,433.7117378768],[4.59255E-5,.61977744975,199.0720014364],[4.005867E-5,2.24479718502,63.7358983034],[2.953796E-5,.98280366998,95.9792272178],[3.87367E-5,3.22283226966,138.5174968707],[2.461186E-5,2.03163875071,735.8765135318],[3.269484E-5,.77492638211,949.1756089698], +[1.758145E-5,3.2658010994,522.5774180938],[1.640172E-5,5.5050445305,846.0828347512],[1.391327E-5,4.02333150505,323.5054166574],[1.580648E-5,4.37265307169,309.2783226558],[1.123498E-5,2.83726798446,415.5524906121],[1.017275E-5,3.71700135395,227.5261894396],[8.48642E-6,3.1915017083,209.3669421749]],[[213.2990952169,0,0],[.01297370862,1.82834923978,213.299095438],[.00564345393,2.88499717272,7.1135470008],[9.3734369E-4,1.06311793502,426.598190876],[.00107674962,2.27769131009,206.1855484372],[4.0244455E-4, +2.04108104671,220.4126424388],[1.9941774E-4,1.2795439047,103.0927742186],[1.0511678E-4,2.7488034213,14.2270940016],[6.416106E-5,.38238295041,639.897286314],[4.848994E-5,2.43037610229,419.4846438752],[4.056892E-5,2.92133209468,110.2063212194],[3.768635E-5,3.6496533078,3.9321532631]],[[.0011644133,1.17988132879,7.1135470008],[9.1841837E-4,.0732519584,213.299095438],[3.6661728E-4,0,0],[1.5274496E-4,4.06493179167,206.1855484372]]],[[[.04330678039,3.60284428399,213.299095438],[.00240348302,2.85238489373, +426.598190876],[8.4745939E-4,0,0],[3.0863357E-4,3.48441504555,220.4126424388],[3.4116062E-4,.57297307557,206.1855484372],[1.473407E-4,2.11846596715,639.897286314],[9.916667E-5,5.79003188904,419.4846438752],[6.993564E-5,4.7360468972,7.1135470008],[4.807588E-5,5.43305312061,316.3918696566]],[[.00198927992,4.93901017903,213.299095438],[3.6947916E-4,3.14159265359,0],[1.7966989E-4,.5197943111,426.598190876]]],[[[9.55758135486,0,0],[.52921382865,2.39226219573,213.299095438],[.01873679867,5.2354960466,206.1855484372], [.01464663929,1.64763042902,426.598190876],[.00821891141,5.93520042303,316.3918696566],[.00547506923,5.0153261898,103.0927742186],[.0037168465,2.27114821115,220.4126424388],[.00361778765,3.13904301847,7.1135470008],[.00140617506,5.70406606781,632.7837393132],[.00108974848,3.29313390175,110.2063212194],[6.9006962E-4,5.94099540992,419.4846438752],[6.1053367E-4,.94037691801,639.897286314],[4.8913294E-4,1.55733638681,202.2533951741],[3.4143772E-4,.19519102597,277.0349937414],[3.2401773E-4,5.47084567016, 949.1756089698],[2.0936596E-4,.46349251129,735.8765135318],[9.796004E-5,5.20477537945,1265.5674786264],[1.1993338E-4,5.98050967385,846.0828347512],[2.08393E-4,1.52102476129,433.7117378768],[1.5298404E-4,3.0594381494,529.6909650946],[6.465823E-5,.17732249942,1052.2683831884],[1.1380257E-4,1.7310542704,522.5774180938],[3.419618E-5,4.94550542171,1581.959348283]],[[.0618298134,.2584351148,213.299095438],[.00506577242,.71114625261,206.1855484372],[.00341394029,5.79635741658,426.598190876],[.00188491195, .47215589652,220.4126424388],[.00186261486,3.14159265359,0],[.00143891146,1.40744822888,7.1135470008]],[[.00436902572,4.78671677509,213.299095438]]]],Uranus:[[[[5.48129294297,0,0],[.09260408234,.89106421507,74.7815985673],[.01504247898,3.6271926092,1.4844727083],[.00365981674,1.89962179044,73.297125859],[.00272328168,3.35823706307,149.5631971346],[7.0328461E-4,5.39254450063,63.7358983034],[6.8892678E-4,6.09292483287,76.2660712756],[6.1998615E-4,2.26952066061,2.9689454166],[6.1950719E-4,2.85098872691, @@ -169,23 +169,23 @@ Saturn:{OrbitalPeriod:10759.22},Uranus:{OrbitalPeriod:30685.4},Neptune:{OrbitalP 146.594251718],[3.0348723E-4,.70100838798,151.0476698429],[2.9156413E-4,3.180563367,77.7505439839],[2.2637073E-4,.72518687029,529.6909650946],[1.1959076E-4,1.7504339214,984.6003316219],[2.5620756E-4,5.25656086672,380.12776796]],[[.01479896629,3.67205697578,74.7815985673]]]],Neptune:[[[[5.31188633046,0,0],[.0179847553,2.9010127389,38.1330356378],[.01019727652,.48580922867,1.4844727083],[.00124531845,4.83008090676,36.6485629295],[4.2064466E-4,5.41054993053,2.9689454166],[3.7714584E-4,6.09221808686, 35.1640902212],[3.3784738E-4,1.24488874087,76.2660712756],[1.6482741E-4,7.727998E-5,491.5579294568],[9.198584E-5,4.93747051954,39.6175083461],[8.99425E-5,.27462171806,175.1660598002]],[[38.13303563957,0,0],[1.6604172E-4,4.86323329249,1.4844727083],[1.5744045E-4,2.27887427527,38.1330356378]]],[[[.03088622933,1.44104372644,38.1330356378],[2.7780087E-4,5.91271884599,76.2660712756],[2.7623609E-4,0,0],[1.5355489E-4,2.52123799551,36.6485629295],[1.5448133E-4,3.50877079215,39.6175083461]]],[[[30.07013205828, 0,0],[.27062259632,1.32999459377,38.1330356378],[.01691764014,3.25186135653,36.6485629295],[.00807830553,5.18592878704,1.4844727083],[.0053776051,4.52113935896,35.1640902212],[.00495725141,1.5710564165,491.5579294568],[.00274571975,1.84552258866,175.1660598002],[1.201232E-4,1.92059384991,1021.2488945514],[.00121801746,5.79754470298,76.2660712756],[.00100896068,.3770272493,73.297125859],[.00135134092,3.37220609835,39.6175083461],[7.571796E-5,1.07149207335,388.4651552382]]]]};e.DeltaT_EspenakMeeus= -R;e.DeltaT_JplHorizons=function(a){return R(Math.min(a,17*365.24217))};var Wb=R;e.SetDeltaTFunction=function(a){Wb=a};var O=function(a){if(a instanceof O)this.date=a.date,this.ut=a.ut,this.tt=a.tt;else if(a instanceof Date&&Number.isFinite(a.getTime()))this.date=a,this.ut=(a.getTime()-xb.getTime())/864E5,this.tt=Ga(this.ut);else if(Number.isFinite(a))this.date=new Date(xb.getTime()+864E5*a),this.ut=a,this.tt=Ga(this.ut);else throw"Argument must be a Date object, an AstroTime object, or a numeric UTC Julian date."; -};O.FromTerrestrialTime=function(a){for(var b=new O(a);;){var c=a-b.tt;if(1E-12>Math.abs(c))return b;b=b.AddDays(c)}};O.prototype.toString=function(){return this.date.toISOString()};O.prototype.AddDays=function(a){return new O(this.ut+a)};e.AstroTime=O;e.MakeTime=v;var Yb=[[[0,0,0,0,1],[-172064161,-174666,33386,92052331,9086,15377]],[[0,0,2,-2,2],[-13170906,-1675,-13696,5730336,-3015,-4587]],[[0,0,2,0,2],[-2276413,-234,2796,978459,-485,1374]],[[0,0,0,0,2],[2074554,207,-698,-897492,470,-291]],[[0, +qa;e.DeltaT_JplHorizons=function(a){return qa(Math.min(a,17*365.24217))};var Xb=qa;e.SetDeltaTFunction=function(a){Xb=a};var O=function(a){if(a instanceof O)this.date=a.date,this.ut=a.ut,this.tt=a.tt;else if(a instanceof Date&&Number.isFinite(a.getTime()))this.date=a,this.ut=(a.getTime()-yb.getTime())/864E5,this.tt=Wb(this.ut);else if(Number.isFinite(a))this.date=new Date(yb.getTime()+864E5*a),this.ut=a,this.tt=Wb(this.ut);else throw"Argument must be a Date object, an AstroTime object, or a numeric UTC Julian date."; +};O.FromTerrestrialTime=function(a){for(var b=new O(a);;){var c=a-b.tt;if(1E-12>Math.abs(c))return b;b=b.AddDays(c)}};O.prototype.toString=function(){return this.date.toISOString()};O.prototype.AddDays=function(a){return new O(this.ut+a)};e.AstroTime=O;e.MakeTime=v;var Zb=[[[0,0,0,0,1],[-172064161,-174666,33386,92052331,9086,15377]],[[0,0,2,-2,2],[-13170906,-1675,-13696,5730336,-3015,-4587]],[[0,0,2,0,2],[-2276413,-234,2796,978459,-485,1374]],[[0,0,0,0,2],[2074554,207,-698,-897492,470,-291]],[[0, 1,0,0,0],[1475877,-3633,11817,73871,-184,-1924]],[[0,1,2,-2,2],[-516821,1226,-524,224386,-677,-174]],[[1,0,0,0,0],[711159,73,-872,-6750,0,358]],[[0,0,2,0,1],[-387298,-367,380,200728,18,318]],[[1,0,2,0,2],[-301461,-36,816,129025,-63,367]],[[0,-1,2,-2,2],[215829,-494,111,-95929,299,132]],[[0,0,2,-2,1],[128227,137,181,-68982,-9,39]],[[-1,0,2,0,2],[123457,11,19,-53311,32,-4]],[[-1,0,0,2,0],[156994,10,-168,-1235,0,82]],[[1,0,0,0,1],[63110,63,27,-33228,0,-9]],[[-1,0,0,0,1],[-57976,-63,-189,31429,0,-75]], [[-1,0,2,2,2],[-59641,-11,149,25543,-11,66]],[[1,0,2,0,1],[-51613,-42,129,26366,0,78]],[[-2,0,2,0,1],[45893,50,31,-24236,-10,20]],[[0,0,0,2,0],[63384,11,-150,-1220,0,29]],[[0,0,2,2,2],[-38571,-1,158,16452,-11,68]],[[0,-2,2,-2,2],[32481,0,0,-13870,0,0]],[[-2,0,0,2,0],[-47722,0,-18,477,0,-25]],[[2,0,2,0,2],[-31046,-1,131,13238,-11,59]],[[1,0,2,-2,2],[28593,0,-1,-12338,10,-3]],[[-1,0,2,0,1],[20441,21,10,-10758,0,-3]],[[2,0,0,0,0],[29243,0,-74,-609,0,13]],[[0,0,2,0,0],[25887,0,-66,-550,0,11]],[[0,1,0, 0,1],[-14053,-25,79,8551,-2,-45]],[[-1,0,0,2,1],[15164,10,11,-8001,0,-1]],[[0,2,2,-2,2],[-15794,72,-16,6850,-42,-5]],[[0,0,-2,2,0],[21783,0,13,-167,0,13]],[[1,0,0,-2,1],[-12873,-10,-37,6953,0,-14]],[[0,-1,0,0,1],[-12654,11,63,6415,0,26]],[[-1,0,2,2,1],[-10204,0,25,5222,0,15]],[[0,2,0,0,0],[16707,-85,-10,168,-1,10]],[[1,0,2,2,2],[-7691,0,44,3268,0,19]],[[-2,0,2,0,0],[-11024,0,-14,104,0,2]],[[0,1,2,0,2],[7566,-21,-11,-3250,0,-5]],[[0,0,2,2,1],[-6637,-11,25,3353,0,14]],[[0,-1,2,0,2],[-7141,21,8,3070, 0,4]],[[0,0,0,2,1],[-6302,-11,2,3272,0,4]],[[1,0,2,-2,1],[5800,10,2,-3045,0,-1]],[[2,0,2,-2,2],[6443,0,-7,-2768,0,-4]],[[-2,0,0,2,1],[-5774,-11,-15,3041,0,-5]],[[2,0,2,0,1],[-5350,0,21,2695,0,12]],[[0,-1,2,-2,1],[-4752,-11,-3,2719,0,-3]],[[0,0,0,-2,1],[-4940,-11,-21,2720,0,-9]],[[-1,-1,0,2,0],[7350,0,-8,-51,0,4]],[[2,0,0,-2,1],[4065,0,6,-2206,0,1]],[[1,0,0,2,0],[6579,0,-24,-199,0,2]],[[0,1,2,-2,1],[3579,0,5,-1900,0,1]],[[1,-1,0,0,0],[4725,0,-6,-41,0,3]],[[-2,0,2,0,2],[-3075,0,-2,1313,0,-1]],[[3,0, 2,0,2],[-2904,0,15,1233,0,7]],[[0,-1,0,2,0],[4348,0,-10,-81,0,2]],[[1,-1,2,0,2],[-2878,0,8,1232,0,4]],[[0,0,0,1,0],[-4230,0,5,-20,0,-2]],[[-1,-1,2,2,2],[-2819,0,7,1207,0,3]],[[-1,0,2,0,0],[-4056,0,5,40,0,-2]],[[0,-1,2,2,2],[-2647,0,11,1129,0,5]],[[-2,0,0,0,1],[-2294,0,-10,1266,0,-4]],[[1,1,2,0,2],[2481,0,-7,-1062,0,-3]],[[2,0,0,0,1],[2179,0,-2,-1129,0,-2]],[[-1,1,0,1,0],[3276,0,1,-9,0,0]],[[1,1,0,0,0],[-3389,0,5,35,0,-2]],[[1,0,2,0,0],[3339,0,-13,-107,0,1]],[[-1,0,2,-2,1],[-1987,0,-6,1073,0,-2]], -[[1,0,0,0,2],[-1981,0,0,854,0,0]],[[-1,0,0,1,0],[4026,0,-353,-553,0,-139]],[[0,0,2,1,2],[1660,0,-5,-710,0,-2]],[[-1,0,2,4,2],[-1521,0,9,647,0,4]],[[-1,1,0,1,1],[1314,0,0,-700,0,0]],[[0,-2,2,-2,1],[-1283,0,0,672,0,0]],[[1,0,2,2,1],[-1331,0,8,663,0,4]],[[-2,0,2,2,2],[1383,0,-2,-594,0,-2]],[[-1,0,0,0,2],[1405,0,4,-610,0,2]],[[1,1,2,-2,2],[1290,0,0,-556,0,0]]],Xa;e.CalcMoonCount=0;var bd=function(a,b,c,d,f,g){this.elat=a;this.elon=b;this.mlat=c;this.mlon=d;this.dist_km=f;this.diam_deg=g};e.LibrationInfo= -bd;e.Libration=function(a){var b=v(a);a=b.tt/36525;var c=a*a,d=c*a,f=c*c,g=da(b);b=g.geo_eclip_lon;var h=g.geo_eclip_lat;g=g.distance_au*e.KM_PER_AU;var l=1.543*e.DEG2RAD,k=e.DEG2RAD*Aa(93.272095+483202.0175233*a-.0036539*c-d/3526E3+f/86331E4),n=e.DEG2RAD*Aa(125.0445479-1934.1362891*a+.0020754*c+d/467441-f/60616E3),p=e.DEG2RAD*Aa(357.5291092+35999.0502909*a-1.536E-4*c+d/2449E4),q=e.DEG2RAD*Aa(134.9633964+477198.8675055*a+.0087414*c+d/69699-f/14712E3);d=e.DEG2RAD*Aa(297.8501921+445267.1114034*a-.0018819* -c+d/545868-f/113065E3);c=1-.002516*a-7.4E-6*c;var u=b-n;f=Math.atan2(Math.sin(u)*Math.cos(h)*Math.cos(l)-Math.sin(h)*Math.sin(l),Math.cos(u)*Math.cos(h));var z=za(e.RAD2DEG*(f-k));l=Math.asin(-Math.sin(u)*Math.cos(h)*Math.sin(l)-Math.sin(h)*Math.cos(l));u=-.02752*Math.cos(q)+-.02245*Math.sin(k)+.00684*Math.cos(q-2*k)+-.00293*Math.cos(2*k)+-8.5E-4*Math.cos(2*k-2*d)+-5.4E-4*Math.cos(q-2*d)+-2E-4*Math.sin(q+k)+-2E-4*Math.cos(q+2*k)+-2E-4*Math.cos(q-k)+1.4E-4*Math.cos(q+2*k-2*d);var x=-.02816*Math.sin(q)+ +[[1,0,0,0,2],[-1981,0,0,854,0,0]],[[-1,0,0,1,0],[4026,0,-353,-553,0,-139]],[[0,0,2,1,2],[1660,0,-5,-710,0,-2]],[[-1,0,2,4,2],[-1521,0,9,647,0,4]],[[-1,1,0,1,1],[1314,0,0,-700,0,0]],[[0,-2,2,-2,1],[-1283,0,0,672,0,0]],[[1,0,2,2,1],[-1331,0,8,663,0,4]],[[-2,0,2,2,2],[1383,0,-2,-594,0,-2]],[[-1,0,0,0,2],[1405,0,4,-610,0,2]],[[1,1,2,-2,2],[1290,0,0,-556,0,0]]],Ya;e.CalcMoonCount=0;var bd=function(a,b,c,d,f,g){this.elat=a;this.elon=b;this.mlat=c;this.mlon=d;this.dist_km=f;this.diam_deg=g};e.LibrationInfo= +bd;e.Libration=function(a){var b=v(a);a=b.tt/36525;var c=a*a,d=c*a,f=c*c,g=da(b);b=g.geo_eclip_lon;var h=g.geo_eclip_lat;g=g.distance_au*e.KM_PER_AU;var l=1.543*e.DEG2RAD,k=e.DEG2RAD*Ca(93.272095+483202.0175233*a-.0036539*c-d/3526E3+f/86331E4),n=e.DEG2RAD*Ca(125.0445479-1934.1362891*a+.0020754*c+d/467441-f/60616E3),p=e.DEG2RAD*Ca(357.5291092+35999.0502909*a-1.536E-4*c+d/2449E4),q=e.DEG2RAD*Ca(134.9633964+477198.8675055*a+.0087414*c+d/69699-f/14712E3);d=e.DEG2RAD*Ca(297.8501921+445267.1114034*a-.0018819* +c+d/545868-f/113065E3);c=1-.002516*a-7.4E-6*c;var u=b-n;f=Math.atan2(Math.sin(u)*Math.cos(h)*Math.cos(l)-Math.sin(h)*Math.sin(l),Math.cos(u)*Math.cos(h));var z=Ba(e.RAD2DEG*(f-k));l=Math.asin(-Math.sin(u)*Math.cos(h)*Math.sin(l)-Math.sin(h)*Math.cos(l));u=-.02752*Math.cos(q)+-.02245*Math.sin(k)+.00684*Math.cos(q-2*k)+-.00293*Math.cos(2*k)+-8.5E-4*Math.cos(2*k-2*d)+-5.4E-4*Math.cos(q-2*d)+-2E-4*Math.sin(q+k)+-2E-4*Math.cos(q+2*k)+-2E-4*Math.cos(q-k)+1.4E-4*Math.cos(q+2*k-2*d);var x=-.02816*Math.sin(q)+ .02244*Math.cos(k)+-.00682*Math.sin(q-2*k)+-.00279*Math.sin(2*k)+-8.3E-4*Math.sin(2*k-2*d)+6.9E-4*Math.sin(q-2*d)+4E-4*Math.cos(q+k)+-2.5E-4*Math.sin(2*q)+-2.3E-4*Math.sin(q+2*k)+2E-4*Math.cos(q-k)+1.9E-4*Math.sin(q-k)+1.3E-4*Math.sin(q+2*k-2*d)+-1E-4*Math.cos(q-3*k);return new bd(e.RAD2DEG*l+(x*Math.cos(f)-u*Math.sin(f)),z+(-(.0252*c*Math.sin(p)+.00473*Math.sin(2*q-2*k)+-.00467*Math.sin(q)+.00396*Math.sin(e.DEG2RAD*(119.75+131.849*a))+.00276*Math.sin(2*q-2*d)+.00196*Math.sin(n)+-.00183*Math.cos(q- -k)+.00115*Math.sin(q-2*d)+-9.6E-4*Math.sin(q-d)+4.6E-4*Math.sin(2*k-2*d)+-3.9E-4*Math.sin(q-k)+-3.2E-4*Math.sin(q-p-d)+2.7E-4*Math.sin(2*q-p-2*d)+2.3E-4*Math.sin(e.DEG2RAD*(72.56+20.186*a))+-1.4E-4*Math.sin(2*d)+1.4E-4*Math.cos(2*q-2*k)+-1.2E-4*Math.sin(q-2*k)+-1.2E-4*Math.sin(2*q)+1.1E-4*Math.sin(2*q-2*p-2*d))+(u*Math.cos(f)+x*Math.sin(f))*Math.tan(l)),e.RAD2DEG*h,e.RAD2DEG*b,g,2*e.RAD2DEG*Math.atan(1737.4/Math.sqrt(g*g-1737.4*1737.4)))};var bb;e.SiderealTime=function(a){a=v(a);return ba(a)};var E= -function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.t=d};E.prototype.Length=function(){return Math.hypot(this.x,this.y,this.z)};e.Vector=E;var I=function(a,b,c,d,f,g,h){this.x=a;this.y=b;this.z=c;this.vx=d;this.vy=f;this.vz=g;this.t=h};e.StateVector=I;var va=function(a,b,c){this.lat=w(a);this.lon=w(b);this.dist=w(c)};e.Spherical=va;var eb=function(a,b,c,d){this.ra=w(a);this.dec=w(b);this.dist=w(c);this.vec=d};e.EquatorialCoordinates=eb;var L=function(a){this.rot=a};e.RotationMatrix=L;e.MakeRotation= -function(a){if(!md(a))throw"Argument must be a [3][3] array of numbers";return new L(a)};var dc=function(a,b,c,d){this.azimuth=w(a);this.altitude=w(b);this.ra=w(c);this.dec=w(d)};e.HorizontalCoordinates=dc;var gc=function(a,b,c){this.vec=a;this.elat=w(b);this.elon=w(c)};e.EclipticCoordinates=gc;e.Horizon=fb;var wb=function(a,b,c){this.latitude=a;this.longitude=b;this.height=c;ta(this)};e.Observer=wb;e.SunPosition=ec;e.Equator=gb;e.ObserverVector=function(a,b,c){a=v(a);var d=ba(a);b=vb(b,d).pos;c|| -(b=db(b,a,G.Into2000));return new E(b[0],b[1],b[2],a)};e.ObserverState=function(a,b,c){a=v(a);var d=ba(a);b=vb(b,d);b=new I(b.pos[0],b.pos[1],b.pos[2],b.vel[0],b.vel[1],b.vel[2],a);return c?b:(c=G.Into2000,c===G.Into2000?(d=Ka(a,c),b=ya(d,b),a=Ja(a,c),a=ya(a,b)):(d=Ja(a,c),b=ya(d,b),a=Ka(a,c),a=ya(a,b)),a)};e.VectorObserver=function(a,b){var c=ba(a.t),d=[a.x,a.y,a.z];b||(d=Ia(d,a.t,G.From2000),d=cb(d,a.t,G.From2000));b=d[0]*e.KM_PER_AU;var f=d[1]*e.KM_PER_AU;d=d[2]*e.KM_PER_AU;a=Math.hypot(b,f);if(1E-6> -a){c=0;var g=0=c;)c+=360;for(;180Math.abs(p))break;g-=p/(-42.69778487239616*((l-k)/h-k*l*-.006694397995865464/(-42.69778487239616*n))+d*f+a*b)}g*=e.RAD2DEG;h=6378.1366/h;d=Math.abs(f)>Math.abs(b)?d/f-.9933056020041345*h:a/b-h}return new wb(g, -c,1E3*d)};e.ObserverGravity=function(a,b){a=Math.sin(a*e.DEG2RAD);a*=a;return 9.7803253359*(1+.00193185265241*a)/Math.sqrt(1-.00669437999013*a)*(1-(3.15704E-7-2.10269E-9*a)*b+7.37452E-14*b*b)};e.Ecliptic=Ma;e.GeoMoon=Y;e.EclipticGeoMoon=ib;e.GeoMoonState=Na;e.GeoEmbState=yb;var ka=[[-73E4,[-26.118207232108,-14.376168177825,3.384402515299],[.0016339372163656,-.0027861699588508,-.0013585880229445]],[-700800,[41.974905202127,-.448502952929,-12.770351505989],[7.3458569351457E-4,.0022785014891658,4.8619778602049E-4]], +k)+.00115*Math.sin(q-2*d)+-9.6E-4*Math.sin(q-d)+4.6E-4*Math.sin(2*k-2*d)+-3.9E-4*Math.sin(q-k)+-3.2E-4*Math.sin(q-p-d)+2.7E-4*Math.sin(2*q-p-2*d)+2.3E-4*Math.sin(e.DEG2RAD*(72.56+20.186*a))+-1.4E-4*Math.sin(2*d)+1.4E-4*Math.cos(2*q-2*k)+-1.2E-4*Math.sin(q-2*k)+-1.2E-4*Math.sin(2*q)+1.1E-4*Math.sin(2*q-2*p-2*d))+(u*Math.cos(f)+x*Math.sin(f))*Math.tan(l)),e.RAD2DEG*h,e.RAD2DEG*b,g,2*e.RAD2DEG*Math.atan(1737.4/Math.sqrt(g*g-1737.4*1737.4)))};var cb;e.SiderealTime=function(a){a=v(a);return ba(a)};var E= +function(a,b,c,d){this.x=a;this.y=b;this.z=c;this.t=d};E.prototype.Length=function(){return Math.hypot(this.x,this.y,this.z)};e.Vector=E;var I=function(a,b,c,d,f,g,h){this.x=a;this.y=b;this.z=c;this.vx=d;this.vy=f;this.vz=g;this.t=h};e.StateVector=I;var xa=function(a,b,c){this.lat=w(a);this.lon=w(b);this.dist=w(c)};e.Spherical=xa;var fb=function(a,b,c,d){this.ra=w(a);this.dec=w(b);this.dist=w(c);this.vec=d};e.EquatorialCoordinates=fb;var L=function(a){this.rot=a};e.RotationMatrix=L;e.MakeRotation= +function(a){if(!od(a))throw"Argument must be a [3][3] array of numbers";return new L(a)};var ec=function(a,b,c,d){this.azimuth=w(a);this.altitude=w(b);this.ra=w(c);this.dec=w(d)};e.HorizontalCoordinates=ec;var hc=function(a,b,c){this.vec=a;this.elat=w(b);this.elon=w(c)};e.EclipticCoordinates=hc;e.Horizon=gb;var xb=function(a,b,c){this.latitude=a;this.longitude=b;this.height=c;va(this)};e.Observer=xb;e.SunPosition=fc;e.Equator=hb;e.ObserverVector=function(a,b,c){a=v(a);var d=ba(a);b=wb(b,d).pos;c|| +(b=eb(b,a,G.Into2000));return new E(b[0],b[1],b[2],a)};e.ObserverState=function(a,b,c){a=v(a);var d=ba(a);b=wb(b,d);b=new I(b.pos[0],b.pos[1],b.pos[2],b.vel[0],b.vel[1],b.vel[2],a);return c?b:(c=G.Into2000,c===G.Into2000?(d=La(a,c),b=Aa(d,b),a=Ka(a,c),a=Aa(a,b)):(d=Ka(a,c),b=Aa(d,b),a=La(a,c),a=Aa(a,b)),a)};e.VectorObserver=function(a,b){var c=ba(a.t),d=[a.x,a.y,a.z];b||(d=Ja(d,a.t,G.From2000),d=db(d,a.t,G.From2000));b=d[0]*e.KM_PER_AU;var f=d[1]*e.KM_PER_AU;d=d[2]*e.KM_PER_AU;a=Math.hypot(b,f);if(1E-6> +a){c=0;var g=0=c;)c+=360;for(;180Math.abs(p))break;g-=p/(-42.69778487239616*((l-k)/h-k*l*-.006694397995865464/(-42.69778487239616*n))+d*f+a*b)}g*=e.RAD2DEG;h=6378.1366/h;d=Math.abs(f)>Math.abs(b)?d/f-.9933056020041345*h:a/b-h}return new xb(g, +c,1E3*d)};e.ObserverGravity=function(a,b){a=Math.sin(a*e.DEG2RAD);a*=a;return 9.7803253359*(1+.00193185265241*a)/Math.sqrt(1-.00669437999013*a)*(1-(3.15704E-7-2.10269E-9*a)*b+7.37452E-14*b*b)};e.Ecliptic=Na;e.GeoMoon=Y;e.EclipticGeoMoon=jb;e.GeoMoonState=Oa;e.GeoEmbState=zb;var ka=[[-73E4,[-26.118207232108,-14.376168177825,3.384402515299],[.0016339372163656,-.0027861699588508,-.0013585880229445]],[-700800,[41.974905202127,-.448502952929,-12.770351505989],[7.3458569351457E-4,.0022785014891658,4.8619778602049E-4]], [-671600,[14.706930780744,44.269110540027,9.353698474772],[-.00210001479998,2.2295915939915E-4,7.0143443551414E-4]],[-642400,[-29.441003929957,-6.43016153057,6.858481011305],[8.4495803960544E-4,-.0030783914758711,-.0012106305981192]],[-613200,[39.444396946234,-6.557989760571,-13.913760296463],[.0011480029005873,.0022400006880665,3.5168075922288E-4]],[-584E3,[20.2303809507,43.266966657189,7.382966091923],[-.0019754081700585,5.3457141292226E-4,7.5929169129793E-4]],[-554800,[-30.65832536462,2.093818874552, 9.880531138071],[6.1010603013347E-5,-.0031326500935382,-9.9346125151067E-4]],[-525600,[35.737703251673,-12.587706024764,-14.677847247563],[.0015802939375649,.0021347678412429,1.9074436384343E-4]],[-496400,[25.466295188546,41.367478338417,5.216476873382],[-.0018054401046468,8.328308359951E-4,8.0260156912107E-4]],[-467200,[-29.847174904071,10.636426313081,12.297904180106],[-6.3257063052907E-4,-.0029969577578221,-7.4476074151596E-4]],[-438E3,[30.774692107687,-18.236637015304,-14.945535879896],[.0020113162005465, .0019353827024189,-2.0937793168297E-6]],[-408800,[30.243153324028,38.656267888503,2.938501750218],[-.0016052508674468,.0011183495337525,8.3333973416824E-4]],[-379600,[-27.288984772533,18.643162147874,14.023633623329],[-.0011856388898191,-.0027170609282181,-4.9015526126399E-4]],[-350400,[24.519605196774,-23.245756064727,-14.626862367368],[.0024322321483154,.0016062008146048,-2.3369181613312E-4]],[-321200,[34.505274805875,35.125338586954,.557361475637],[-.0013824391637782,.0013833397561817,8.4823598806262E-4]], @@ -199,9 +199,9 @@ c,1E3*d)};e.ObserverGravity=function(a,b){a=Math.sin(a*e.DEG2RAD);a*=a;return 9. -.224524636277],[-.0012941245730845,.0014560427668319,8.4762160640137E-4]],[613200,[-21.538149762417,28.204068269761,15.321973799534],[-.001731211740901,-.0021939631314577,-1.631691327518E-4]],[642400,[13.971521374415,-28.339941764789,-13.083792871886],[.0029334630526035,9.1860931752944E-4,-5.9939422488627E-4]],[671600,[39.526942044143,28.93989736011,-2.872799527539],[-.0010068481658095,.001702113288809,8.3578230511981E-4]],[700800,[-15.576200701394,34.399412961275,15.466033737854],[-.0020098814612884, -.0017191109825989,7.0414782780416E-5]],[73E4,[4.24325283709,-30.118201690825,-10.707441231349],[.0031725847067411,1.609846120227E-4,-9.0672150593868E-4]]],C=function(a,b,c){this.x=a;this.y=b;this.z=c};C.prototype.clone=function(){return new C(this.x,this.y,this.z)};C.prototype.ToAstroVector=function(a){return new E(this.x,this.y,this.z,a)};C.zero=function(){return new C(0,0,0)};C.prototype.quadrature=function(){return this.x*this.x+this.y*this.y+this.z*this.z};C.prototype.add=function(a){return new C(this.x+ a.x,this.y+a.y,this.z+a.z)};C.prototype.sub=function(a){return new C(this.x-a.x,this.y-a.y,this.z-a.z)};C.prototype.incr=function(a){this.x+=a.x;this.y+=a.y;this.z+=a.z};C.prototype.decr=function(a){this.x-=a.x;this.y-=a.y;this.z-=a.z};C.prototype.mul=function(a){return new C(a*this.x,a*this.y,a*this.z)};C.prototype.div=function(a){return new C(this.x/a,this.y/a,this.z/a)};C.prototype.mean=function(a){return new C((this.x+a.x)/2,(this.y+a.y)/2,(this.z+a.z)/2)};C.prototype.neg=function(){return new C(-this.x, --this.y,-this.z)};var X=function(a,b,c){this.tt=a;this.r=b;this.v=c};X.prototype.clone=function(){return new X(this.tt,this.r,this.v)};X.prototype.sub=function(a){return new X(this.tt,this.r.sub(a.r),this.v.sub(a.v))};var xa=function(a){var b=new X(a,new C(0,0,0),new C(0,0,0));this.Jupiter=T(b,a,m.Jupiter,2.825345909524226E-7);this.Saturn=T(b,a,m.Saturn,8.459715185680659E-8);this.Uranus=T(b,a,m.Uranus,1.292024916781969E-8);this.Neptune=T(b,a,m.Neptune,1.524358900784276E-8);this.Jupiter.r.decr(b.r); -this.Jupiter.v.decr(b.v);this.Saturn.r.decr(b.r);this.Saturn.v.decr(b.v);this.Uranus.r.decr(b.r);this.Uranus.v.decr(b.v);this.Neptune.r.decr(b.r);this.Neptune.v.decr(b.v);this.Sun=new X(a,b.r.mul(-1),b.v.mul(-1))};xa.prototype.Acceleration=function(a){var b=Pa(a,2.959122082855911E-4,this.Sun.r);b.incr(Pa(a,2.825345909524226E-7,this.Jupiter.r));b.incr(Pa(a,8.459715185680659E-8,this.Saturn.r));b.incr(Pa(a,1.292024916781969E-8,this.Uranus.r));b.incr(Pa(a,1.524358900784276E-8,this.Neptune.r));return b}; -var Qa=function(a,b,c,d){this.tt=a;this.r=b;this.v=c;this.a=d};Qa.prototype.clone=function(){return new Qa(this.tt,this.r.clone(),this.v.clone(),this.a.clone())};var kc=function(a,b){this.bary=a;this.grav=b},Fb=[],nd=new L([[.999432765338654,-.0336771074697641,0],[.0303959428906285,.902057912352809,.430543388542295],[-.0144994559663353,-.430299169409101,.902569881273754]]),rb=[{mu:2.82489428433814E-7,al:[1.446213296021224,3.5515522861824],a:[[.0028210960212903,0,0]],l:[[-1.925258348666E-4,4.9369589722645, +-this.y,-this.z)};var X=function(a,b,c){this.tt=a;this.r=b;this.v=c};X.prototype.clone=function(){return new X(this.tt,this.r,this.v)};X.prototype.sub=function(a){return new X(this.tt,this.r.sub(a.r),this.v.sub(a.v))};var za=function(a){var b=new X(a,new C(0,0,0),new C(0,0,0));this.Jupiter=S(b,a,m.Jupiter,2.825345909524226E-7);this.Saturn=S(b,a,m.Saturn,8.459715185680659E-8);this.Uranus=S(b,a,m.Uranus,1.292024916781969E-8);this.Neptune=S(b,a,m.Neptune,1.524358900784276E-8);this.Jupiter.r.decr(b.r); +this.Jupiter.v.decr(b.v);this.Saturn.r.decr(b.r);this.Saturn.v.decr(b.v);this.Uranus.r.decr(b.r);this.Uranus.v.decr(b.v);this.Neptune.r.decr(b.r);this.Neptune.v.decr(b.v);this.Sun=new X(a,b.r.mul(-1),b.v.mul(-1))};za.prototype.Acceleration=function(a){var b=Qa(a,2.959122082855911E-4,this.Sun.r);b.incr(Qa(a,2.825345909524226E-7,this.Jupiter.r));b.incr(Qa(a,8.459715185680659E-8,this.Saturn.r));b.incr(Qa(a,1.292024916781969E-8,this.Uranus.r));b.incr(Qa(a,1.524358900784276E-8,this.Neptune.r));return b}; +var Ra=function(a,b,c,d){this.tt=a;this.r=b;this.v=c;this.a=d};Ra.prototype.clone=function(){return new Ra(this.tt,this.r.clone(),this.v.clone(),this.a.clone())};var lc=function(a,b){this.bary=a;this.grav=b},Gb=[],pd=new L([[.999432765338654,-.0336771074697641,0],[.0303959428906285,.902057912352809,.430543388542295],[-.0144994559663353,-.430299169409101,.902569881273754]]),sb=[{mu:2.82489428433814E-7,al:[1.446213296021224,3.5515522861824],a:[[.0028210960212903,0,0]],l:[[-1.925258348666E-4,4.9369589722645, .01358483658305],[-9.70803596076E-5,4.3188796477322,.01303413843243],[-8.988174165E-5,1.9080016428617,.00305064867158],[-5.53101050262E-5,1.4936156681569,.01293892891155]],z:[[.0041510849668155,4.089939635545,-.01290686414666],[6.260521444113E-4,1.446188898627,3.5515522949802],[3.52747346169E-5,2.1256287034578,1.2727416567E-4]],zeta:[[3.142172466014E-4,2.7964219722923,-.002315096098],[9.04169207946E-5,1.0477061879627,-5.6920638196E-4]]},{mu:2.82483274392893E-7,al:[-.3735263437471362,1.76932271112347], a:[[.0044871037804314,0,0],[4.324367498E-7,1.819645606291,1.7822295777568]],l:[[8.576433172936E-4,4.3188693178264,.01303413830805],[4.549582875086E-4,1.4936531751079,.01293892881962],[3.248939825174E-4,1.8196494533458,1.7822295777568],[-3.074250079334E-4,4.9377037005911,.01358483286724],[1.982386144784E-4,1.907986905476,.00305101212869],[1.834063551804E-4,2.1402853388529,.00145009789338],[-1.434383188452E-4,5.622214036663,.89111478887838],[-7.71939140944E-5,4.300272437235,2.6733443704266]],z:[[-.0093589104136341, 4.0899396509039,-.01290686414666],[2.988994545555E-4,5.9097265185595,1.7693227079462],[2.13903639035E-4,2.1256289300016,1.2727418407E-4],[1.980963564781E-4,2.743516829265,6.7797343009E-4],[1.210388158965E-4,5.5839943711203,3.20566149E-5],[8.37042048393E-5,1.6094538368039,-.90402165808846],[8.23525166369E-5,1.4461887708689,3.5515522949802]],zeta:[[.0040404917832303,1.0477063169425,-5.692064054E-4],[2.200421034564E-4,3.3368857864364,-1.2491307307E-4],[1.662544744719E-4,2.4134862374711,0],[5.90282470983E-5, @@ -209,26 +209,26 @@ a:[[.0044871037804314,0,0],[4.324367498E-7,1.819645606291,1.7822295777568]],l:[[ 1.2995922951532,1.0034433456729],[-6.07017260182E-5,.64978769669238,.50172167043264]],z:[[.0014289811307319,2.1256295942739,1.2727413029E-4],[7.71093122676E-4,5.5836330003496,3.20643411E-5],[5.925911780766E-4,4.0899396636448,-.01290686414666],[2.045597496146E-4,5.2713683670372,-.12523544076106],[1.785118648258E-4,.28743156721063,.8782079244252],[1.131999784893E-4,1.4462127277818,3.5515522949802],[-6.5877816921E-5,2.2702423990985,-1.7951364394537],[4.97058888328E-5,5.9096792204858,1.7693227129285]], zeta:[[.0015932721570848,3.3368862796665,-1.2491307058E-4],[8.533093128905E-4,2.4133881688166,0],[3.513347911037E-4,5.9720789850127,-3.056101771E-5],[-1.441929255483E-4,1.0477061764435,-5.6920632124E-4]]},{mu:2.82492144889909E-7,al:[-.3620341291375704,.376486233433828],a:[[.0125879701715314,0,0],[3.595204947E-6,.64965776007116,.50172168165034],[2.7580210652E-6,1.808423578151,3.1750660413359]],l:[[5.586040123824E-4,2.1404207189815,.00145009793231],[-3.805813868176E-4,2.7358844897853,2.972965062E-5], [2.205152863262E-4,.649796525964,.5017216724358],[1.877895151158E-4,1.8084787604005,3.1750660413359],[7.66916975242E-5,6.2720114319755,1.3928364636651],[7.47056855106E-5,1.2995916202344,1.0034433456729]],z:[[.0073755808467977,5.5836071576084,3.206509914E-5],[2.065924169942E-4,5.9209831565786,.37648624194703],[1.589869764021E-4,.28744006242623,.8782079244252],[-1.561131605348E-4,2.1257397865089,1.2727441285E-4],[1.486043380971E-4,1.4462134301023,3.5515522949802],[6.35073108731E-5,5.9096803285954,1.7693227129285], -[5.99351698525E-5,4.1125517584798,-2.7985797954589],[5.40660842731E-5,5.5390350845569,.00286834082283],[-4.89596900866E-5,4.6218149483338,-.62695712529519]],zeta:[[.0038422977898495,2.4133922085557,0],[.0022453891791894,5.9721736773277,-3.056125525E-5],[-2.604479450559E-4,3.3368746306409,-1.2491309972E-4],[3.3211214323E-5,5.5604137742337,.00290037688507]]}],cd=function(a,b,c,d){this.io=a;this.europa=b;this.ganymede=c;this.callisto=d};e.JupiterMoonsInfo=cd;e.JupiterMoons=function(a){a=new O(a);return new cd(kb(a, -rb[0]),kb(a,rb[1]),kb(a,rb[2]),kb(a,rb[3]))};e.HelioVector=ca;e.HelioDistance=la;var dd=function(){};e.PositionFunction=dd;e.CorrectLightTravel=oc;var Hb=function(a,b,c,d){this.observerBody=a;this.targetBody=b;this.aberration=c;this.observerPos=d;return this};$jscomp.inherits(Hb,dd);Hb.prototype.Position=function(a){this.aberration&&(this.observerPos=ca(this.observerBody,a));var b=ca(this.targetBody,a);return new E(b.x-this.observerPos.x,b.y-this.observerPos.y,b.z-this.observerPos.z,a)};e.BackdatePosition= -pc;e.GeoVector=W;e.BaryState=function(a,b){b=v(b);if(a===m.SSB)return new I(0,0,0,0,0,0,b);if(a===m.Pluto)return Eb(b,!1);var c=new xa(b.tt);switch(a){case m.Sun:return ma(c.Sun,b);case m.Jupiter:return ma(c.Jupiter,b);case m.Saturn:return ma(c.Saturn,b);case m.Uranus:return ma(c.Uranus,b);case m.Neptune:return ma(c.Neptune,b);case m.Moon:case m.EMB:var d=Oa(M[m.Earth],b.tt);a=a===m.Moon?Na(b):yb(b);return new I(a.x+c.Sun.r.x+d.r.x,a.y+c.Sun.r.y+d.r.y,a.z+c.Sun.r.z+d.r.z,a.vx+c.Sun.v.x+d.v.x,a.vy+ -c.Sun.v.y+d.v.y,a.vz+c.Sun.v.z+d.v.z,b)}if(a in M)return a=Oa(M[a],b.tt),new I(c.Sun.r.x+a.r.x,c.Sun.r.y+a.r.y,c.Sun.r.z+a.r.z,c.Sun.v.x+a.v.x,c.Sun.v.y+a.v.y,c.Sun.v.z+a.v.z,b);throw'BaryState: Unsupported body "'+a+'"';};e.HelioState=mb;e.Search=J;e.SearchSunLongitude=qc;e.PairLongitude=Ib;e.AngleFromSun=Ba;e.EclipticLongitude=na;var rc=function(a,b,c,d,f,g,h,l){this.time=a;this.mag=b;this.phase_angle=c;this.helio_dist=d;this.geo_dist=f;this.gc=g;this.hc=h;this.ring_tilt=l;this.phase_fraction=(1+ -Math.cos(e.DEG2RAD*c))/2};e.IlluminationInfo=rc;e.Illumination=nb;e.SearchRelativeLongitude=Ca;e.MoonPhase=Jb;e.SearchMoonPhase=Sa;var tc=function(a,b){this.quarter=a;this.time=b};e.MoonQuarter=tc;e.SearchMoonQuarter=sc;e.NextMoonQuarter=function(a){a=new Date(a.time.date.getTime()+5184E5);return sc(a)};e.SearchRiseSet=function(a,b,c,d,f){a:switch(a){case m.Sun:var g=Lc;break a;case m.Moon:g=zd;break a;default:g=0}return uc(a,b,c,d,f,g,-Ad)};e.SearchAltitude=function(a,b,c,d,f,g){if(!Number.isFinite(g)|| --90>g||90c||24<=c)throw"Invalid hour angle "+c;w(f);if(0===f)throw"Direction must be positive or negative.";for(;;){++g;var h=ba(d),l=gb(a,d,b,!0,!0);h=(c+l.ra- -b.longitude/15-h)%24;1===g?0h&&(h+=24):0h?h+=24:123600*Math.abs(h))return a=fb(d,b,l.ra,l.dec,"normal"),new ed(d,a);d=d.AddDays(h/24*.9972695717592592)}};var fd=function(a,b,c,d){this.mar_equinox=a;this.jun_solstice=b;this.sep_equinox=c;this.dec_solstice=d};e.SeasonInfo=fd;e.Seasons=function(a){function b(h,l,k){l=new Date(Date.UTC(a,l-1,k));h=qc(h,l,20);if(!h)throw"Cannot find season change near "+l.toISOString();return h}a instanceof Date&&Number.isFinite(a.getTime())&& -(a=a.getUTCFullYear());if(!Number.isSafeInteger(a))throw"Cannot calculate seasons because year argument "+a+" is neither a Date nor a safe integer.";var c=b(0,3,10),d=b(90,6,10),f=b(180,9,10),g=b(270,12,10);return new fd(c,d,f,g)};var wc=function(a,b,c,d){this.time=a;this.visibility=b;this.elongation=c;this.ecliptic_separation=d};e.ElongationEvent=wc;e.Elongation=vc;e.SearchMaxElongation=function(a,b){function c(n){var p=n.AddDays(-.005);n=n.AddDays(.005);p=Ba(a,p);n=Ba(a,n);return(p-n)/.01}b=v(b); -var d={Mercury:{s1:50,s2:85},Venus:{s1:40,s2:50}}[a];if(!d)throw"SearchMaxElongation works for Mercury and Venus only.";for(var f=0;2>=++f;){var g=na(a,b),h=na(m.Earth,b),l=za(g-h),k=g=h=void 0;l>=-d.s1&&l<+d.s1?(k=0,h=+d.s1,g=+d.s2):l>=+d.s2||l<-d.s2?(k=0,h=-d.s2,g=-d.s1):0<=l?(k=-Ra(a)/4,h=+d.s1,g=+d.s2):(k=-Ra(a)/4,h=-d.s2,g=-d.s1);l=b.AddDays(k);h=Ca(a,h,l);g=Ca(a,g,h);l=c(h);if(0<=l)throw"SearchMaxElongation: internal error: m1 = "+l;k=c(g);if(0>=k)throw"SearchMaxElongation: internal error: m2 = "+ -k;l=J(c,h,g,{init_f1:l,init_f2:k,dt_tolerance_seconds:10});if(!l)throw"SearchMaxElongation: failed search iter "+f+" (t1="+h.toString()+", t2="+g.toString()+")";if(l.tt>=b.tt)return vc(a,l);b=g.AddDays(1)}throw"SearchMaxElongation: failed to find event after 2 tries.";};e.SearchPeakMagnitude=function(a,b){function c(k){var n=k.AddDays(-.005);k=k.AddDays(.005);n=nb(a,n).mag;return(nb(a,k).mag-n)/.01}if(a!==m.Venus)throw"SearchPeakMagnitude currently works for Venus only.";b=v(b);for(var d=0;2>=++d;){var f= -na(a,b),g=na(m.Earth,b),h=za(f-g),l=f=g=void 0;-10<=h&&10>h?(l=0,g=10,f=30):30<=h||-30>h?(l=0,g=-30,f=-10):0<=h?(l=-Ra(a)/4,g=10,f=30):(l=-Ra(a)/4,g=-30,f=-10);h=b.AddDays(l);g=Ca(a,g,h);f=Ca(a,f,g);h=c(g);if(0<=h)throw"SearchPeakMagnitude: internal error: m1 = "+h;l=c(f);if(0>=l)throw"SearchPeakMagnitude: internal error: m2 = "+l;h=J(c,g,f,{init_f1:h,init_f2:l,dt_tolerance_seconds:10});if(!h)throw"SearchPeakMagnitude: failed search iter "+d+" (t1="+g.toString()+", t2="+f.toString()+")";if(h.tt>= -b.tt)return nb(a,h);b=f.AddDays(1)}throw"SearchPeakMagnitude: failed to find event after 2 tries.";};var Da;(function(a){a[a.Pericenter=0]="Pericenter";a[a.Apocenter=1]="Apocenter"})(Da=e.ApsisKind||(e.ApsisKind={}));var Ta=function(a,b,c){this.time=a;this.kind=b;this.dist_au=c;this.dist_km=c*e.KM_PER_AU};e.Apsis=Ta;e.SearchLunarApsis=xc;e.NextLunarApsis=function(a){var b=xc(a.time.AddDays(11));if(1!==b.kind+a.kind)throw"NextLunarApsis INTERNAL ERROR: did not find alternating apogee/perigee: prev="+ -a.kind+" @ "+a.time.toString()+", next="+b.kind+" @ "+b.time.toString();return b};e.SearchPlanetApsis=zc;e.NextPlanetApsis=function(a,b){if(b.kind!==Da.Pericenter&&b.kind!==Da.Apocenter)throw"Invalid apsis kind: "+b.kind;var c=b.time.AddDays(.25*Z[a].OrbitalPeriod);a=zc(a,c);if(1!==a.kind+b.kind)throw"Internal error: previous apsis was "+b.kind+", but found "+a.kind+" for next apsis.";return a};e.InverseRotation=Ea;e.CombineRotation=Fa;e.IdentityMatrix=function(){return new L([[1,0,0],[0,1,0],[0, +[5.99351698525E-5,4.1125517584798,-2.7985797954589],[5.40660842731E-5,5.5390350845569,.00286834082283],[-4.89596900866E-5,4.6218149483338,-.62695712529519]],zeta:[[.0038422977898495,2.4133922085557,0],[.0022453891791894,5.9721736773277,-3.056125525E-5],[-2.604479450559E-4,3.3368746306409,-1.2491309972E-4],[3.3211214323E-5,5.5604137742337,.00290037688507]]}],cd=function(a,b,c,d){this.io=a;this.europa=b;this.ganymede=c;this.callisto=d};e.JupiterMoonsInfo=cd;e.JupiterMoons=function(a){a=new O(a);return new cd(lb(a, +sb[0]),lb(a,sb[1]),lb(a,sb[2]),lb(a,sb[3]))};e.HelioVector=ca;e.HelioDistance=la;var dd=function(){};e.PositionFunction=dd;e.CorrectLightTravel=oc;var Hb=function(a,b,c,d){this.observerBody=a;this.targetBody=b;this.aberration=c;this.observerPos=d;return this};$jscomp.inherits(Hb,dd);Hb.prototype.Position=function(a){this.aberration&&(this.observerPos=ca(this.observerBody,a));var b=ca(this.targetBody,a);return new E(b.x-this.observerPos.x,b.y-this.observerPos.y,b.z-this.observerPos.z,a)};e.BackdatePosition= +pc;e.GeoVector=W;e.BaryState=function(a,b){b=v(b);if(a===m.SSB)return new I(0,0,0,0,0,0,b);if(a===m.Pluto)return Fb(b,!1);var c=new za(b.tt);switch(a){case m.Sun:return ma(c.Sun,b);case m.Jupiter:return ma(c.Jupiter,b);case m.Saturn:return ma(c.Saturn,b);case m.Uranus:return ma(c.Uranus,b);case m.Neptune:return ma(c.Neptune,b);case m.Moon:case m.EMB:var d=Pa(M[m.Earth],b.tt);a=a===m.Moon?Oa(b):zb(b);return new I(a.x+c.Sun.r.x+d.r.x,a.y+c.Sun.r.y+d.r.y,a.z+c.Sun.r.z+d.r.z,a.vx+c.Sun.v.x+d.v.x,a.vy+ +c.Sun.v.y+d.v.y,a.vz+c.Sun.v.z+d.v.z,b)}if(a in M)return a=Pa(M[a],b.tt),new I(c.Sun.r.x+a.r.x,c.Sun.r.y+a.r.y,c.Sun.r.z+a.r.z,c.Sun.v.x+a.v.x,c.Sun.v.y+a.v.y,c.Sun.v.z+a.v.z,b);throw'BaryState: Unsupported body "'+a+'"';};e.HelioState=nb;e.Search=J;e.SearchSunLongitude=qc;e.PairLongitude=Ib;e.AngleFromSun=Da;e.EclipticLongitude=na;var rc=function(a,b,c,d,f,g,h,l){this.time=a;this.mag=b;this.phase_angle=c;this.helio_dist=d;this.geo_dist=f;this.gc=g;this.hc=h;this.ring_tilt=l;this.phase_fraction=(1+ +Math.cos(e.DEG2RAD*c))/2};e.IlluminationInfo=rc;e.Illumination=ob;e.SearchRelativeLongitude=Ea;e.MoonPhase=Jb;e.SearchMoonPhase=Ta;var tc=function(a,b){this.quarter=a;this.time=b};e.MoonQuarter=tc;e.SearchMoonQuarter=sc;e.NextMoonQuarter=function(a){a=new Date(a.time.date.getTime()+5184E5);return sc(a)};e.SearchRiseSet=function(a,b,c,d,f){a:switch(a){case m.Sun:var g=Lc;break a;case m.Moon:g=Bd;break a;default:g=0}return uc(a,b,c,d,f,g,-Cd)};e.SearchAltitude=function(a,b,c,d,f,g){if(!Number.isFinite(g)|| +-90>g||90c||24<=c)throw"Invalid hour angle "+c;w(f);if(0===f)throw"Direction must be positive or negative.";for(;;){++g;var h=ba(d),l=hb(a,d,b,!0,!0);h=(c+l.ra- +b.longitude/15-h)%24;1===g?0h&&(h+=24):0h?h+=24:123600*Math.abs(h))return a=gb(d,b,l.ra,l.dec,"normal"),new ed(d,a);d=d.AddDays(h/24*.9972695717592592)}};var fd=function(a,b,c,d){this.mar_equinox=a;this.jun_solstice=b;this.sep_equinox=c;this.dec_solstice=d};e.SeasonInfo=fd;e.Seasons=function(a){function b(h,l,k){l=new Date(Date.UTC(a,l-1,k));h=qc(h,l,20);if(!h)throw"Cannot find season change near "+l.toISOString();return h}a instanceof Date&&Number.isFinite(a.getTime())&& +(a=a.getUTCFullYear());if(!Number.isSafeInteger(a))throw"Cannot calculate seasons because year argument "+a+" is neither a Date nor a safe integer.";var c=b(0,3,10),d=b(90,6,10),f=b(180,9,10),g=b(270,12,10);return new fd(c,d,f,g)};var wc=function(a,b,c,d){this.time=a;this.visibility=b;this.elongation=c;this.ecliptic_separation=d};e.ElongationEvent=wc;e.Elongation=vc;e.SearchMaxElongation=function(a,b){function c(n){var p=n.AddDays(-.005);n=n.AddDays(.005);p=Da(a,p);n=Da(a,n);return(p-n)/.01}b=v(b); +var d={Mercury:{s1:50,s2:85},Venus:{s1:40,s2:50}}[a];if(!d)throw"SearchMaxElongation works for Mercury and Venus only.";for(var f=0;2>=++f;){var g=na(a,b),h=na(m.Earth,b),l=Ba(g-h),k=g=h=void 0;l>=-d.s1&&l<+d.s1?(k=0,h=+d.s1,g=+d.s2):l>=+d.s2||l<-d.s2?(k=0,h=-d.s2,g=-d.s1):0<=l?(k=-Sa(a)/4,h=+d.s1,g=+d.s2):(k=-Sa(a)/4,h=-d.s2,g=-d.s1);l=b.AddDays(k);h=Ea(a,h,l);g=Ea(a,g,h);l=c(h);if(0<=l)throw"SearchMaxElongation: internal error: m1 = "+l;k=c(g);if(0>=k)throw"SearchMaxElongation: internal error: m2 = "+ +k;l=J(c,h,g,{init_f1:l,init_f2:k,dt_tolerance_seconds:10});if(!l)throw"SearchMaxElongation: failed search iter "+f+" (t1="+h.toString()+", t2="+g.toString()+")";if(l.tt>=b.tt)return vc(a,l);b=g.AddDays(1)}throw"SearchMaxElongation: failed to find event after 2 tries.";};e.SearchPeakMagnitude=function(a,b){function c(k){var n=k.AddDays(-.005);k=k.AddDays(.005);n=ob(a,n).mag;return(ob(a,k).mag-n)/.01}if(a!==m.Venus)throw"SearchPeakMagnitude currently works for Venus only.";b=v(b);for(var d=0;2>=++d;){var f= +na(a,b),g=na(m.Earth,b),h=Ba(f-g),l=f=g=void 0;-10<=h&&10>h?(l=0,g=10,f=30):30<=h||-30>h?(l=0,g=-30,f=-10):0<=h?(l=-Sa(a)/4,g=10,f=30):(l=-Sa(a)/4,g=-30,f=-10);h=b.AddDays(l);g=Ea(a,g,h);f=Ea(a,f,g);h=c(g);if(0<=h)throw"SearchPeakMagnitude: internal error: m1 = "+h;l=c(f);if(0>=l)throw"SearchPeakMagnitude: internal error: m2 = "+l;h=J(c,g,f,{init_f1:h,init_f2:l,dt_tolerance_seconds:10});if(!h)throw"SearchPeakMagnitude: failed search iter "+d+" (t1="+g.toString()+", t2="+f.toString()+")";if(h.tt>= +b.tt)return ob(a,h);b=f.AddDays(1)}throw"SearchPeakMagnitude: failed to find event after 2 tries.";};var Fa;(function(a){a[a.Pericenter=0]="Pericenter";a[a.Apocenter=1]="Apocenter"})(Fa=e.ApsisKind||(e.ApsisKind={}));var Ua=function(a,b,c){this.time=a;this.kind=b;this.dist_au=c;this.dist_km=c*e.KM_PER_AU};e.Apsis=Ua;e.SearchLunarApsis=xc;e.NextLunarApsis=function(a){var b=xc(a.time.AddDays(11));if(1!==b.kind+a.kind)throw"NextLunarApsis INTERNAL ERROR: did not find alternating apogee/perigee: prev="+ +a.kind+" @ "+a.time.toString()+", next="+b.kind+" @ "+b.time.toString();return b};e.SearchPlanetApsis=zc;e.NextPlanetApsis=function(a,b){if(b.kind!==Fa.Pericenter&&b.kind!==Fa.Apocenter)throw"Invalid apsis kind: "+b.kind;var c=b.time.AddDays(.25*Z[a].OrbitalPeriod);a=zc(a,c);if(1!==a.kind+b.kind)throw"Internal error: previous apsis was "+b.kind+", but found "+a.kind+" for next apsis.";return a};e.InverseRotation=Ga;e.CombineRotation=Ha;e.IdentityMatrix=function(){return new L([[1,0,0],[0,1,0],[0, 0,1]])};e.Pivot=function(a,b,c){if(0!==b&&1!==b&&2!==b)throw"Invalid axis "+b+". Must be [0, 1, 2].";var d=w(c)*e.DEG2RAD;c=Math.cos(d);d=Math.sin(d);var f=(b+1)%3,g=(b+2)%3,h=[[0,0,0],[0,0,0],[0,0,0]];h[f][f]=c*a.rot[f][f]-d*a.rot[f][g];h[f][g]=d*a.rot[f][f]+c*a.rot[f][g];h[f][b]=a.rot[f][b];h[g][f]=c*a.rot[g][f]-d*a.rot[g][g];h[g][g]=d*a.rot[g][f]+c*a.rot[g][g];h[g][b]=a.rot[g][b];h[b][f]=c*a.rot[b][f]-d*a.rot[b][g];h[b][g]=d*a.rot[b][f]+c*a.rot[b][g];h[b][b]=a.rot[b][b];return new L(h)};e.VectorFromSphere= -lb;e.EquatorFromVector=Lb;e.SphereFromVector=Mb;e.HorizonFromVector=function(a,b){a=Mb(a);a.lon=Ac(a.lon);a.lat+=La(b,a.lat);return a};e.VectorFromHorizon=function(a,b,c){b=v(b);var d=Ac(a.lon);c=a.lat+Bc(c,a.lat);a=new va(c,d,a.dist);return lb(a,b)};e.Refraction=La;e.InverseRefraction=Bc;e.RotateVector=Ua;e.RotateState=ya;e.Rotation_EQJ_ECL=Cc;e.Rotation_ECL_EQJ=function(){return new L([[1,0,0],[0,.9174821430670688,.3977769691083922],[0,-.3977769691083922,.9174821430670688]])};e.Rotation_EQJ_EQD= -Nb;e.Rotation_EQD_EQJ=Ob;e.Rotation_EQD_HOR=Pb;e.Rotation_HOR_EQD=Dc;e.Rotation_HOR_EQJ=Ec;e.Rotation_EQJ_HOR=function(a,b){a=Ec(a,b);return Ea(a)};e.Rotation_EQD_ECL=Fc;e.Rotation_ECL_EQD=Gc;e.Rotation_ECL_HOR=Hc;e.Rotation_HOR_ECL=function(a,b){a=Hc(a,b);return Ea(a)};e.Rotation_EQJ_GAL=function(){return new L([[-.0548624779711344,.4941095946388765,-.8676668813529025],[-.8734572784246782,-.4447938112296831,-.1980677870294097],[-.483800052994852,.7470034631630423,.4559861124470794]])};e.Rotation_GAL_EQJ= -function(){return new L([[-.0548624779711344,-.8734572784246782,-.483800052994852],[.4941095946388765,-.4447938112296831,.7470034631630423],[-.8676668813529025,-.1980677870294097,.4559861124470794]])};var Bd=[["And","Andromeda"],["Ant","Antila"],["Aps","Apus"],["Aql","Aquila"],["Aqr","Aquarius"],["Ara","Ara"],["Ari","Aries"],["Aur","Auriga"],["Boo","Bootes"],["Cae","Caelum"],["Cam","Camelopardis"],["Cap","Capricornus"],["Car","Carina"],["Cas","Cassiopeia"],["Cen","Centaurus"],["Cep","Cepheus"],["Cet", +mb;e.EquatorFromVector=Lb;e.SphereFromVector=Mb;e.HorizonFromVector=function(a,b){a=Mb(a);a.lon=Ac(a.lon);a.lat+=Ma(b,a.lat);return a};e.VectorFromHorizon=function(a,b,c){b=v(b);var d=Ac(a.lon);c=a.lat+Bc(c,a.lat);a=new xa(c,d,a.dist);return mb(a,b)};e.Refraction=Ma;e.InverseRefraction=Bc;e.RotateVector=Va;e.RotateState=Aa;e.Rotation_EQJ_ECL=Cc;e.Rotation_ECL_EQJ=function(){return new L([[1,0,0],[0,.9174821430670688,.3977769691083922],[0,-.3977769691083922,.9174821430670688]])};e.Rotation_EQJ_EQD= +Nb;e.Rotation_EQD_EQJ=Ob;e.Rotation_EQD_HOR=Pb;e.Rotation_HOR_EQD=Dc;e.Rotation_HOR_EQJ=Ec;e.Rotation_EQJ_HOR=function(a,b){a=Ec(a,b);return Ga(a)};e.Rotation_EQD_ECL=Fc;e.Rotation_ECL_EQD=Gc;e.Rotation_ECL_HOR=Hc;e.Rotation_HOR_ECL=function(a,b){a=Hc(a,b);return Ga(a)};e.Rotation_EQJ_GAL=function(){return new L([[-.0548624779711344,.4941095946388765,-.8676668813529025],[-.8734572784246782,-.4447938112296831,-.1980677870294097],[-.483800052994852,.7470034631630423,.4559861124470794]])};e.Rotation_GAL_EQJ= +function(){return new L([[-.0548624779711344,-.8734572784246782,-.483800052994852],[.4941095946388765,-.4447938112296831,.7470034631630423],[-.8676668813529025,-.1980677870294097,.4559861124470794]])};var Dd=[["And","Andromeda"],["Ant","Antila"],["Aps","Apus"],["Aql","Aquila"],["Aqr","Aquarius"],["Ara","Ara"],["Ari","Aries"],["Aur","Auriga"],["Boo","Bootes"],["Cae","Caelum"],["Cam","Camelopardis"],["Cap","Capricornus"],["Car","Carina"],["Cas","Cassiopeia"],["Cen","Centaurus"],["Cep","Cepheus"],["Cet", "Cetus"],["Cha","Chamaeleon"],["Cir","Circinus"],["CMa","Canis Major"],["CMi","Canis Minor"],["Cnc","Cancer"],["Col","Columba"],["Com","Coma Berenices"],["CrA","Corona Australis"],["CrB","Corona Borealis"],["Crt","Crater"],["Cru","Crux"],["Crv","Corvus"],["CVn","Canes Venatici"],["Cyg","Cygnus"],["Del","Delphinus"],["Dor","Dorado"],["Dra","Draco"],["Equ","Equuleus"],["Eri","Eridanus"],["For","Fornax"],["Gem","Gemini"],["Gru","Grus"],["Her","Hercules"],["Hor","Horologium"],["Hya","Hydra"],["Hyi","Hydrus"], ["Ind","Indus"],["Lac","Lacerta"],["Leo","Leo"],["Lep","Lepus"],["Lib","Libra"],["LMi","Leo Minor"],["Lup","Lupus"],["Lyn","Lynx"],["Lyr","Lyra"],["Men","Mensa"],["Mic","Microscopium"],["Mon","Monoceros"],["Mus","Musca"],["Nor","Norma"],["Oct","Octans"],["Oph","Ophiuchus"],["Ori","Orion"],["Pav","Pavo"],["Peg","Pegasus"],["Per","Perseus"],["Phe","Phoenix"],["Pic","Pictor"],["PsA","Pisces Austrinus"],["Psc","Pisces"],["Pup","Puppis"],["Pyx","Pyxis"],["Ret","Reticulum"],["Scl","Sculptor"],["Sco","Scorpius"], -["Sct","Scutum"],["Ser","Serpens"],["Sex","Sextans"],["Sge","Sagitta"],["Sgr","Sagittarius"],["Tau","Taurus"],["Tel","Telescopium"],["TrA","Triangulum Australe"],["Tri","Triangulum"],["Tuc","Tucana"],["UMa","Ursa Major"],["UMi","Ursa Minor"],["Vel","Vela"],["Vir","Virgo"],["Vol","Volans"],["Vul","Vulpecula"]],Cd=[[83,0,8640,2112],[83,2880,5220,2076],[83,7560,8280,2068],[83,6480,7560,2064],[15,0,2880,2040],[10,3300,3840,1968],[15,0,1800,1920],[10,3840,5220,1920],[83,6300,6480,1920],[33,7260,7560,1920], +["Sct","Scutum"],["Ser","Serpens"],["Sex","Sextans"],["Sge","Sagitta"],["Sgr","Sagittarius"],["Tau","Taurus"],["Tel","Telescopium"],["TrA","Triangulum Australe"],["Tri","Triangulum"],["Tuc","Tucana"],["UMa","Ursa Major"],["UMi","Ursa Minor"],["Vel","Vela"],["Vir","Virgo"],["Vol","Volans"],["Vul","Vulpecula"]],Ed=[[83,0,8640,2112],[83,2880,5220,2076],[83,7560,8280,2068],[83,6480,7560,2064],[15,0,2880,2040],[10,3300,3840,1968],[15,0,1800,1920],[10,3840,5220,1920],[83,6300,6480,1920],[33,7260,7560,1920], [15,0,1263,1848],[10,4140,4890,1848],[83,5952,6300,1800],[15,7260,7440,1800],[10,2868,3300,1764],[33,3300,4080,1764],[83,4680,5952,1680],[13,1116,1230,1632],[33,7350,7440,1608],[33,4080,4320,1596],[15,0,120,1584],[83,5040,5640,1584],[15,8490,8640,1584],[33,4320,4860,1536],[33,4860,5190,1512],[15,8340,8490,1512],[10,2196,2520,1488],[33,7200,7350,1476],[15,7393.2,7416,1462],[10,2520,2868,1440],[82,2868,3030,1440],[33,7116,7200,1428],[15,7200,7393.2,1428],[15,8232,8340,1418],[13,0,876,1404],[33,6990, 7116,1392],[13,612,687,1380],[13,876,1116,1368],[10,1116,1140,1368],[15,8034,8232,1350],[10,1800,2196,1344],[82,5052,5190,1332],[33,5190,6990,1332],[10,1140,1200,1320],[15,7968,8034,1320],[15,7416,7908,1316],[13,0,612,1296],[50,2196,2340,1296],[82,4350,4860,1272],[33,5490,5670,1272],[15,7908,7968,1266],[10,1200,1800,1260],[13,8232,8400,1260],[33,5670,6120,1236],[62,735,906,1212],[33,6120,6564,1212],[13,0,492,1200],[62,492,600,1200],[50,2340,2448,1200],[13,8400,8640,1200],[82,4860,5052,1164],[13,0, 402,1152],[13,8490,8640,1152],[39,6543,6564,1140],[33,6564,6870,1140],[30,6870,6900,1140],[62,600,735,1128],[82,3030,3300,1128],[13,60,312,1104],[82,4320,4350,1080],[50,2448,2652,1068],[30,7887,7908,1056],[30,7875,7887,1050],[30,6900,6984,1044],[82,3300,3660,1008],[82,3660,3882,960],[8,5556,5670,960],[39,5670,5880,960],[50,3330,3450,954],[0,0,906,882],[62,906,924,882],[51,6969,6984,876],[62,1620,1689,864],[30,7824,7875,864],[44,7875,7920,864],[7,2352,2652,852],[50,2652,2790,852],[0,0,720,840],[44, @@ -242,23 +242,23 @@ function(){return new L([[-.0548624779711344,-.8734572784246782,-.48380005299485 -1032],[67,2880,3012,-1032],[35,1230,1392,-1056],[71,5911.5,6420,-1092],[24,6420,6900,-1092],[76,6900,7320,-1092],[53,7320,7680,-1092],[35,1080,1230,-1104],[9,1620,1740,-1116],[49,5520,5640,-1152],[63,0,840,-1156],[35,960,1080,-1176],[40,1470,1536,-1176],[9,1536,1620,-1176],[38,7680,7920,-1200],[67,2160,2880,-1218],[84,2880,2940,-1218],[35,870,960,-1224],[40,1380,1470,-1224],[63,0,660,-1236],[12,2160,2220,-1260],[84,2940,3042,-1272],[40,1260,1380,-1276],[32,1380,1440,-1276],[63,0,570,-1284],[35,780, 870,-1296],[64,1620,1800,-1296],[49,5418,5520,-1296],[84,3042,3180,-1308],[12,2220,2340,-1320],[14,4260,4620,-1320],[49,5100,5418,-1320],[56,5418,5520,-1320],[32,1440,1560,-1356],[84,3180,3960,-1356],[14,3960,4050,-1356],[5,6300,6480,-1368],[78,6480,7320,-1368],[38,7920,8400,-1368],[40,1152,1260,-1380],[64,1800,1980,-1380],[12,2340,2460,-1392],[63,0,480,-1404],[35,480,780,-1404],[63,8400,8640,-1404],[32,1560,1650,-1416],[56,5520,5911.5,-1440],[43,7320,7680,-1440],[64,1980,2160,-1464],[18,5460,5520, -1464],[5,5911.5,5970,-1464],[18,5370,5460,-1526],[5,5970,6030,-1526],[64,2160,2460,-1536],[12,2460,3252,-1536],[14,4050,4260,-1536],[27,4260,4620,-1536],[14,4620,5232,-1536],[18,4860,4920,-1560],[5,6030,6060,-1560],[40,780,1152,-1620],[69,1152,1650,-1620],[18,5310,5370,-1620],[5,6060,6300,-1620],[60,6300,6480,-1620],[81,7920,8400,-1620],[32,1650,2370,-1680],[18,4920,5310,-1680],[79,5310,6120,-1680],[81,0,480,-1800],[42,1260,1650,-1800],[86,2370,3252,-1800],[12,3252,4050,-1800],[55,4050,4920,-1800], -[60,6480,7680,-1800],[43,7680,8400,-1800],[81,8400,8640,-1800],[81,270,480,-1824],[42,0,1260,-1980],[17,2760,4920,-1980],[2,4920,6480,-1980],[52,1260,2760,-2040],[57,0,8640,-2160]],Ub,gd,hd=function(a,b,c,d){this.symbol=a;this.name=b;this.ra1875=c;this.dec1875=d};e.ConstellationInfo=hd;e.Constellation=function(a,b){w(a);w(b);if(-90>b||90a&&(a+=24);Ub||(Ub=Nb(new O(-45655.74141261017)),gd=new O(0));a=new va(b,15*a,1);a=lb(a,gd);a=Ua(Ub, -a);a=Lb(a);b=10/240;for(var c=b/15,d=$jscomp.makeIterator(Cd),f=d.next();!f.done;f=d.next()){f=f.value;var g=f[1]*c,h=f[2]*c;if(f[3]*b<=a.dec&&g<=a.ra&&a.rab||90a&&(a+=24);Ub||(Ub=Nb(new O(-45655.74141261017)),gd=new O(0));a=new xa(b,15*a,1);a=mb(a,gd);a=Va(Ub, +a);a=Lb(a);b=10/240;for(var c=b/15,d=$jscomp.makeIterator(Ed),f=d.next();!f.done;f=d.next()){f=f.value;var g=f[1]*c,h=f[2]*c;if(f[3]*b<=a.dec&&g<=a.ra&&a.ra= 0) ? StarTable[index] : null; +} +function UserDefinedStar(body) { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -306,10 +314,8 @@ const StarTable = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -331,8 +337,8 @@ const StarTable = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ function DefineStar(body, ra, dec, distanceLightYears) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body); + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); VerifyNumber(dec); @@ -343,7 +349,9 @@ function DefineStar(body, ra, dec, distanceLightYears) { throw `Invalid declination for star: ${dec}`; if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * exports.AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * exports.AU_PER_LY; } exports.DefineStar = DefineStar; var PrecessDirection; @@ -2482,7 +2490,7 @@ function Horizon(date, observer, ra, dec, refraction) { const coszd = Math.cos(zd * exports.DEG2RAD); const sinzd0 = Math.sin(zd0 * exports.DEG2RAD); const coszd0 = Math.cos(zd0 * exports.DEG2RAD); - var pr = []; + const pr = []; for (let j = 0; j < 3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0) * sinzd + uz[j] * coszd); } @@ -3661,12 +3669,6 @@ exports.JupiterMoons = JupiterMoons; */ function HelioVector(body, date) { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); - return VectorFromSphere(sphere, time); - } if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -3688,6 +3690,11 @@ function HelioVector(body, date) { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; } exports.HelioVector = HelioVector; @@ -3703,7 +3710,7 @@ exports.HelioVector = HelioVector; * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -3712,6 +3719,9 @@ exports.HelioVector = HelioVector; * The heliocentric distance in AU. */ function HelioDistance(body, date) { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -3859,7 +3869,7 @@ class BodyPosition extends PositionFunction { function BackdatePosition(date, observerBody, targetBody, aberration) { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/source/js/astronomy.min.js b/source/js/astronomy.min.js index 478372af..b65a8f32 100644 --- a/source/js/astronomy.min.js +++ b/source/js/astronomy.min.js @@ -58,8 +58,8 @@ function MassProduct(a){switch(a){case Body.Sun:return SUN_GM;case Body.Mercury: exports.MassProduct=MassProduct;var ob2000,cos_ob2000,sin_ob2000;function VerifyBoolean(a){if(!0!==a&&!1!==a)throw console.trace(),"Value is not boolean: "+a;return a}function VerifyNumber(a){if(!Number.isFinite(a))throw console.trace(),"Value is not a finite number: "+a;return a}function Frac(a){return a-Math.floor(a)} function AngleBetween(a,b){var c=a.x*a.x+a.y*a.y+a.z*a.z;if(1E-8>Math.abs(c))throw"AngleBetween: first vector is too short.";var d=b.x*b.x+b.y*b.y+b.z*b.z;if(1E-8>Math.abs(d))throw"AngleBetween: second vector is too short.";a=(a.x*b.x+a.y*b.y+a.z*b.z)/Math.sqrt(c*d);return-1>=a?180:1<=a?0:exports.RAD2DEG*Math.acos(a)}exports.AngleBetween=AngleBetween;var Body; (function(a){a.Sun="Sun";a.Moon="Moon";a.Mercury="Mercury";a.Venus="Venus";a.Earth="Earth";a.Mars="Mars";a.Jupiter="Jupiter";a.Saturn="Saturn";a.Uranus="Uranus";a.Neptune="Neptune";a.Pluto="Pluto";a.SSB="SSB";a.EMB="EMB";a.Star1="Star1";a.Star2="Star2";a.Star3="Star3";a.Star4="Star4";a.Star5="Star5";a.Star6="Star6";a.Star7="Star7";a.Star8="Star8"})(Body=exports.Body||(exports.Body={})); -var StarList=[Body.Star1,Body.Star2,Body.Star3,Body.Star4,Body.Star5,Body.Star6,Body.Star7,Body.Star8],StarTable=[{ra:0,dec:0,dist:exports.AU_PER_LY},{ra:0,dec:0,dist:exports.AU_PER_LY},{ra:0,dec:0,dist:exports.AU_PER_LY},{ra:0,dec:0,dist:exports.AU_PER_LY},{ra:0,dec:0,dist:exports.AU_PER_LY},{ra:0,dec:0,dist:exports.AU_PER_LY},{ra:0,dec:0,dist:exports.AU_PER_LY},{ra:0,dec:0,dist:exports.AU_PER_LY}]; -function DefineStar(a,b,c,d){var e=StarList.indexOf(a);if(0>e)throw"Invalid star body: "+a;VerifyNumber(b);VerifyNumber(c);VerifyNumber(d);if(0>b||24<=b)throw"Invalid right ascension for star: "+b;if(-90>c||90d)throw"Invalid star distance: "+d;StarTable[e]={ra:b,dec:c,dist:d*exports.AU_PER_LY}}exports.DefineStar=DefineStar;var PrecessDirection;(function(a){a[a.From2000=0]="From2000";a[a.Into2000=1]="Into2000"})(PrecessDirection||(PrecessDirection={})); +var StarList=[Body.Star1,Body.Star2,Body.Star3,Body.Star4,Body.Star5,Body.Star6,Body.Star7,Body.Star8],StarTable=[{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0},{ra:0,dec:0,dist:0}];function GetStar(a){a=StarList.indexOf(a);return 0<=a?StarTable[a]:null}function UserDefinedStar(a){return(a=GetStar(a))&&0b||24<=b)throw"Invalid right ascension for star: "+b;if(-90>c||90d)throw"Invalid star distance: "+d;e.ra=b;e.dec=c;e.dist=d*exports.AU_PER_LY}exports.DefineStar=DefineStar;var PrecessDirection;(function(a){a[a.From2000=0]="From2000";a[a.Into2000=1]="Into2000"})(PrecessDirection||(PrecessDirection={})); var Planet={Mercury:{OrbitalPeriod:87.969},Venus:{OrbitalPeriod:224.701},Earth:{OrbitalPeriod:365.256},Mars:{OrbitalPeriod:686.98},Jupiter:{OrbitalPeriod:4332.589},Saturn:{OrbitalPeriod:10759.22},Uranus:{OrbitalPeriod:30685.4},Neptune:{OrbitalPeriod:60189},Pluto:{OrbitalPeriod:90560}};function PlanetOrbitalPeriod(a){if(a in Planet)return Planet[a].OrbitalPeriod;throw"Unknown orbital period for: "+a;}exports.PlanetOrbitalPeriod=PlanetOrbitalPeriod; var vsop={Mercury:[[[[4.40250710144,0,0],[.40989414977,1.48302034195,26087.9031415742],[.050462942,4.47785489551,52175.8062831484],[.00855346844,1.16520322459,78263.70942472259],[.00165590362,4.11969163423,104351.61256629678],[3.4561897E-4,.77930768443,130439.51570787099],[7.583476E-5,3.71348404924,156527.41884944518]],[[26087.90313685529,0,0],[.01131199811,6.21874197797,26087.9031415742],[.00292242298,3.04449355541,52175.8062831484],[7.5775081E-4,6.08568821653,78263.70942472259],[1.9676525E-4,2.80965111777, 104351.61256629678]]],[[[.11737528961,1.98357498767,26087.9031415742],[.02388076996,5.03738959686,52175.8062831484],[.01222839532,3.14159265359,0],[.0054325181,1.79644363964,78263.70942472259],[.0012977877,4.83232503958,104351.61256629678],[3.1866927E-4,1.58088495658,130439.51570787099],[7.963301E-5,4.60972126127,156527.41884944518]],[[.00274646065,3.95008450011,26087.9031415742],[9.9737713E-4,3.14159265359,0]]],[[[.39528271651,0,0],[.07834131818,6.19233722598,26087.9031415742],[.00795525558,2.95989690104, @@ -203,11 +203,11 @@ f,g*h+d*m,g*m+d*l,(k*d-g*c)*f,a)} function CalcJupiterMoon(a,b){for(var c=a.tt+18262.5,d=[0,b.al[0]+c*b.al[1],0,0,0,0],e=$jscomp.makeIterator(b.a),f=e.next();!f.done;f=e.next()){var g=$jscomp.makeIterator(f.value);f=g.next().value;var k=g.next().value;g=g.next().value;d[0]+=f*Math.cos(k+c*g)}e=$jscomp.makeIterator(b.l);for(f=e.next();!f.done;f=e.next())g=$jscomp.makeIterator(f.value),f=g.next().value,k=g.next().value,g=g.next().value,d[1]+=f*Math.sin(k+c*g);d[1]%=PI2;0>d[1]&&(d[1]+=PI2);e=$jscomp.makeIterator(b.z);for(f=e.next();!f.done;f= e.next())g=$jscomp.makeIterator(f.value),f=g.next().value,k=g.next().value,g=g.next().value,k+=c*g,d[2]+=f*Math.cos(k),d[3]+=f*Math.sin(k);e=$jscomp.makeIterator(b.zeta);for(f=e.next();!f.done;f=e.next())g=$jscomp.makeIterator(f.value),f=g.next().value,k=g.next().value,g=g.next().value,k+=c*g,d[4]+=f*Math.cos(k),d[5]+=f*Math.sin(k);a=JupiterMoon_elem2pv(a,b.mu,d);return RotateState(Rotation_JUP_EQJ,a)} function JupiterMoons(a){a=new AstroTime(a);return new JupiterMoonsInfo(CalcJupiterMoon(a,JupiterMoonModel[0]),CalcJupiterMoon(a,JupiterMoonModel[1]),CalcJupiterMoon(a,JupiterMoonModel[2]),CalcJupiterMoon(a,JupiterMoonModel[3]))}exports.JupiterMoons=JupiterMoons; -function HelioVector(a,b){b=MakeTime(b);var c=StarList.indexOf(a);if(0<=c)return a=StarTable[c],a=new Spherical(a.dec,15*a.ra,a.dist),VectorFromSphere(a,b);if(a in vsop)return CalcVsop(vsop[a],b);if(a===Body.Pluto)return a=CalcPluto(b,!0),new Vector(a.x,a.y,a.z,b);if(a===Body.Sun)return new Vector(0,0,0,b);if(a===Body.Moon)return a=CalcVsop(vsop.Earth,b),c=GeoMoon(b),new Vector(a.x+c.x,a.y+c.y,a.z+c.z,b);if(a===Body.EMB){a=CalcVsop(vsop.Earth,b);c=GeoMoon(b);var d=1+EARTH_MOON_MASS_RATIO;return new Vector(a.x+ -c.x/d,a.y+c.y/d,a.z+c.z/d,b)}if(a===Body.SSB)return CalcSolarSystemBarycenter(b);throw'HelioVector: Unknown body "'+a+'"';}exports.HelioVector=HelioVector;function HelioDistance(a,b){b=MakeTime(b);return a in vsop?VsopFormula(vsop[a][RAD_INDEX],b.tt/DAYS_PER_MILLENNIUM,!1):HelioVector(a,b).Length()}exports.HelioDistance=HelioDistance;var PositionFunction=function(){};exports.PositionFunction=PositionFunction; +function HelioVector(a,b){b=MakeTime(b);if(a in vsop)return CalcVsop(vsop[a],b);if(a===Body.Pluto)return a=CalcPluto(b,!0),new Vector(a.x,a.y,a.z,b);if(a===Body.Sun)return new Vector(0,0,0,b);if(a===Body.Moon){a=CalcVsop(vsop.Earth,b);var c=GeoMoon(b);return new Vector(a.x+c.x,a.y+c.y,a.z+c.z,b)}if(a===Body.EMB){a=CalcVsop(vsop.Earth,b);c=GeoMoon(b);var d=1+EARTH_MOON_MASS_RATIO;return new Vector(a.x+c.x/d,a.y+c.y/d,a.z+c.z/d,b)}if(a===Body.SSB)return CalcSolarSystemBarycenter(b);if(c=UserDefinedStar(a))return a= +new Spherical(c.dec,15*c.ra,c.dist),VectorFromSphere(a,b);throw'HelioVector: Unknown body "'+a+'"';}exports.HelioVector=HelioVector;function HelioDistance(a,b){var c=UserDefinedStar(a);if(c)return c.dist;b=MakeTime(b);return a in vsop?VsopFormula(vsop[a][RAD_INDEX],b.tt/DAYS_PER_MILLENNIUM,!1):HelioVector(a,b).Length()}exports.HelioDistance=HelioDistance;var PositionFunction=function(){};exports.PositionFunction=PositionFunction; function CorrectLightTravel(a,b){for(var c=b,d=0,e=0;10>e;++e){var f=a.Position(c);d=f.Length()/exports.C_AUDAY;if(1d)return f;c=g}throw"Light-travel time solver did not converge: dt = "+d;}exports.CorrectLightTravel=CorrectLightTravel;var BodyPosition=function(a,b,c,d){PositionFunction.call(this);this.observerBody=a;this.targetBody=b;this.aberration=c;this.observerPos=d}; $jscomp.inherits(BodyPosition,PositionFunction);BodyPosition.prototype.Position=function(a){this.aberration&&(this.observerPos=HelioVector(this.observerBody,a));var b=HelioVector(this.targetBody,a);return new Vector(b.x-this.observerPos.x,b.y-this.observerPos.y,b.z-this.observerPos.z,a)}; -function BackdatePosition(a,b,c,d){VerifyBoolean(d);a=MakeTime(a);if(0<=StarList.indexOf(c)){c=HelioVector(c,a);if(d)return b=HelioState(b,a),d=new Vector(c.x-b.x,c.y-b.y,c.z-b.z,a),c=exports.C_AUDAY/d.Length(),new Vector(d.x+b.vx/c,d.y+b.vy/c,d.z+b.vz/c,a);b=HelioVector(b,a);return new Vector(c.x-b.x,c.y-b.y,c.z-b.z,a)}var e=d?new Vector(0,0,0,a):HelioVector(b,a);b=new BodyPosition(b,c,d,e);return CorrectLightTravel(b,a)}exports.BackdatePosition=BackdatePosition; +function BackdatePosition(a,b,c,d){VerifyBoolean(d);a=MakeTime(a);if(UserDefinedStar(c)){c=HelioVector(c,a);if(d)return b=HelioState(b,a),d=new Vector(c.x-b.x,c.y-b.y,c.z-b.z,a),c=exports.C_AUDAY/d.Length(),new Vector(d.x+b.vx/c,d.y+b.vy/c,d.z+b.vz/c,a);b=HelioVector(b,a);return new Vector(c.x-b.x,c.y-b.y,c.z-b.z,a)}var e=d?new Vector(0,0,0,a):HelioVector(b,a);b=new BodyPosition(b,c,d,e);return CorrectLightTravel(b,a)}exports.BackdatePosition=BackdatePosition; function GeoVector(a,b,c){VerifyBoolean(c);b=MakeTime(b);switch(a){case Body.Earth:return new Vector(0,0,0,b);case Body.Moon:return GeoMoon(b);default:return a=BackdatePosition(b,Body.Earth,a,c),a.t=b,a}}exports.GeoVector=GeoVector;function ExportState(a,b){return new StateVector(a.r.x,a.r.y,a.r.z,a.v.x,a.v.y,a.v.z,b)} function BaryState(a,b){b=MakeTime(b);if(a===Body.SSB)return new StateVector(0,0,0,0,0,0,b);if(a===Body.Pluto)return CalcPluto(b,!1);var c=new major_bodies_t(b.tt);switch(a){case Body.Sun:return ExportState(c.Sun,b);case Body.Jupiter:return ExportState(c.Jupiter,b);case Body.Saturn:return ExportState(c.Saturn,b);case Body.Uranus:return ExportState(c.Uranus,b);case Body.Neptune:return ExportState(c.Neptune,b);case Body.Moon:case Body.EMB:var d=CalcVsopPosVel(vsop[Body.Earth],b.tt);a=a===Body.Moon? GeoMoonState(b):GeoEmbState(b);return new StateVector(a.x+c.Sun.r.x+d.r.x,a.y+c.Sun.r.y+d.r.y,a.z+c.Sun.r.z+d.r.z,a.vx+c.Sun.v.x+d.v.x,a.vy+c.Sun.v.y+d.v.y,a.vz+c.Sun.v.z+d.v.z,b)}if(a in vsop)return a=CalcVsopPosVel(vsop[a],b.tt),new StateVector(c.Sun.r.x+a.r.x,c.Sun.r.y+a.r.y,c.Sun.r.z+a.r.z,c.Sun.v.x+a.v.x,c.Sun.v.y+a.v.y,c.Sun.v.z+a.v.z,b);throw'BaryState: Unsupported body "'+a+'"';}exports.BaryState=BaryState; diff --git a/source/js/astronomy.ts b/source/js/astronomy.ts index b41761fc..93def0e4 100644 --- a/source/js/astronomy.ts +++ b/source/js/astronomy.ts @@ -320,32 +320,41 @@ export enum Body { Star8 = 'Star8', } - const StarList = [ Body.Star1, Body.Star2, Body.Star3, Body.Star4, Body.Star5, Body.Star6, Body.Star7, Body.Star8 ]; - interface StarDef { ra: number, // EQJ right ascension dec: number, // EQJ declination dist: number // heliocentric distance in AU }; - const StarTable: StarDef[] = [ - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star1 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star2 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star3 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star4 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star5 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star6 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star7 - { ra: 0, dec: 0, dist: AU_PER_LY }, // Body.Star8 + { ra: 0, dec: 0, dist: 0 }, // Body.Star1 + { ra: 0, dec: 0, dist: 0 }, // Body.Star2 + { ra: 0, dec: 0, dist: 0 }, // Body.Star3 + { ra: 0, dec: 0, dist: 0 }, // Body.Star4 + { ra: 0, dec: 0, dist: 0 }, // Body.Star5 + { ra: 0, dec: 0, dist: 0 }, // Body.Star6 + { ra: 0, dec: 0, dist: 0 }, // Body.Star7 + { ra: 0, dec: 0, dist: 0 }, // Body.Star8 ]; +function GetStar(body: Body): StarDef | null { + const index = StarList.indexOf(body); + return (index >= 0) ? StarTable[index] : null; +} + + +function UserDefinedStar(body: Body): StarDef | null { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} + + /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -354,10 +363,8 @@ const StarTable: StarDef[] = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -379,8 +386,8 @@ const StarTable: StarDef[] = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ export function DefineStar(body: Body, ra: number, dec: number, distanceLightYears: number) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body) + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); @@ -396,7 +403,9 @@ export function DefineStar(body: Body, ra: number, dec: number, distanceLightYea if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * AU_PER_LY; } @@ -2707,7 +2716,7 @@ export function Horizon(date: FlexibleDateTime, observer: Observer, ra: number, const coszd = Math.cos(zd * DEG2RAD); const sinzd0 = Math.sin(zd0 * DEG2RAD); const coszd0 = Math.cos(zd0 * DEG2RAD); - var pr = []; + const pr: number[] = []; for (let j=0; j<3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0)*sinzd + uz[j]*coszd); } @@ -4092,13 +4101,6 @@ export function JupiterMoons(date: FlexibleDateTime): JupiterMoonsInfo { export function HelioVector(body: Body, date: FlexibleDateTime): Vector { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15*star.ra, star.dist); - return VectorFromSphere(sphere, time); - } - if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -4120,6 +4122,12 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15*star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; }; @@ -4134,7 +4142,7 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -4143,6 +4151,9 @@ export function HelioVector(body: Body, date: FlexibleDateTime): Vector { * The heliocentric distance in AU. */ export function HelioDistance(body: Body, date: FlexibleDateTime): number { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -4312,7 +4323,7 @@ export function BackdatePosition( ): Vector { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/source/js/esm/astronomy.js b/source/js/esm/astronomy.js index c7c78104..45e499ab 100644 --- a/source/js/esm/astronomy.js +++ b/source/js/esm/astronomy.js @@ -283,15 +283,23 @@ const StarList = [ ]; ; const StarTable = [ - { ra: 0, dec: 0, dist: AU_PER_LY }, - { ra: 0, dec: 0, dist: AU_PER_LY }, - { ra: 0, dec: 0, dist: AU_PER_LY }, - { ra: 0, dec: 0, dist: AU_PER_LY }, - { ra: 0, dec: 0, dist: AU_PER_LY }, - { ra: 0, dec: 0, dist: AU_PER_LY }, - { ra: 0, dec: 0, dist: AU_PER_LY }, - { ra: 0, dec: 0, dist: AU_PER_LY }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, + { ra: 0, dec: 0, dist: 0 }, ]; +function GetStar(body) { + const index = StarList.indexOf(body); + return (index >= 0) ? StarTable[index] : null; +} +function UserDefinedStar(body) { + const star = GetStar(body); + return (star && star.dist > 0) ? star : null; +} /** * @brief Assign equatorial coordinates to a user-defined star. * @@ -300,10 +308,8 @@ const StarTable = [ * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Star1`..`Star8`. * - * A star that has not been defined through a call to `DefineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `DefineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `DefineStar`. * * @param {Body} body * One of the eight user-defined star identifiers: @@ -325,8 +331,8 @@ const StarTable = [ * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ export function DefineStar(body, ra, dec, distanceLightYears) { - const index = StarList.indexOf(body); - if (index < 0) + const star = GetStar(body); + if (!star) throw `Invalid star body: ${body}`; VerifyNumber(ra); VerifyNumber(dec); @@ -337,7 +343,9 @@ export function DefineStar(body, ra, dec, distanceLightYears) { throw `Invalid declination for star: ${dec}`; if (distanceLightYears < 1) throw `Invalid star distance: ${distanceLightYears}`; - StarTable[index] = { ra: ra, dec: dec, dist: distanceLightYears * AU_PER_LY }; + star.ra = ra; + star.dec = dec; + star.dist = distanceLightYears * AU_PER_LY; } var PrecessDirection; (function (PrecessDirection) { @@ -2458,7 +2466,7 @@ export function Horizon(date, observer, ra, dec, refraction) { const coszd = Math.cos(zd * DEG2RAD); const sinzd0 = Math.sin(zd0 * DEG2RAD); const coszd0 = Math.cos(zd0 * DEG2RAD); - var pr = []; + const pr = []; for (let j = 0; j < 3; ++j) { pr.push(((p[j] - coszd0 * uz[j]) / sinzd0) * sinzd + uz[j] * coszd); } @@ -3622,12 +3630,6 @@ export function JupiterMoons(date) { */ export function HelioVector(body, date) { var time = MakeTime(date); - const starIndex = StarList.indexOf(body); - if (starIndex >= 0) { - const star = StarTable[starIndex]; - const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); - return VectorFromSphere(sphere, time); - } if (body in vsop) return CalcVsop(vsop[body], time); if (body === Body.Pluto) { @@ -3649,6 +3651,11 @@ export function HelioVector(body, date) { } if (body === Body.SSB) return CalcSolarSystemBarycenter(time); + const star = UserDefinedStar(body); + if (star) { + const sphere = new Spherical(star.dec, 15 * star.ra, star.dist); + return VectorFromSphere(sphere, time); + } throw `HelioVector: Unknown body "${body}"`; } ; @@ -3663,7 +3670,7 @@ export function HelioVector(body, date) { * * @param {Body} body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, or any of the planets. + * the Sun, Moon, any of the planets, or a user-defined star. * * @param {FlexibleDateTime} date * The date and time for which to calculate the heliocentric distance. @@ -3672,6 +3679,9 @@ export function HelioVector(body, date) { * The heliocentric distance in AU. */ export function HelioDistance(body, date) { + const star = UserDefinedStar(body); + if (star) + return star.dist; const time = MakeTime(date); if (body in vsop) return VsopFormula(vsop[body][RAD_INDEX], time.tt / DAYS_PER_MILLENNIUM, false); @@ -3816,7 +3826,7 @@ class BodyPosition extends PositionFunction { export function BackdatePosition(date, observerBody, targetBody, aberration) { VerifyBoolean(aberration); const time = MakeTime(date); - if (StarList.indexOf(targetBody) >= 0) { + if (UserDefinedStar(targetBody)) { // This is a user-defined star, which must be treated as a special case. // First, we assume its heliocentric position does not change with time. // Second, we assume its heliocentric position has already been corrected diff --git a/source/kotlin/doc/define-star.md b/source/kotlin/doc/define-star.md index 24b39450..3d4abdef 100644 --- a/source/kotlin/doc/define-star.md +++ b/source/kotlin/doc/define-star.md @@ -8,7 +8,7 @@ Assign equatorial coordinates to a user-defined star. Some Astronomy Engine functions allow their body parameter to be a user-defined fixed point in the sky, loosely called a "star". This function assigns a right ascension, declination, and distance to one of the eight user-defined stars Body.Star1..Body.Star8. -A star that has not been defined through a call to defineStar defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. Once defined, the star keeps the given coordinates until a subsequent call to defineStar replaces the coordinates with new values. +Stars are not valid until defined. Once defined, they retain their definition until re-defined by another call to defineStar. ## Parameters diff --git a/source/kotlin/doc/helio-distance.md b/source/kotlin/doc/helio-distance.md index cb6b94e6..c62e13fb 100644 --- a/source/kotlin/doc/helio-distance.md +++ b/source/kotlin/doc/helio-distance.md @@ -16,5 +16,5 @@ The heliocentric distance in AU. | | | |---|---| -| body | A body for which to calculate a heliocentric distance: the Sun, Moon, EMB, SSB, or any of the planets. | +| body | A body for which to calculate a heliocentric distance: the Sun, Moon, EMB, SSB, any of the planets, or a user-defined star. | | time | The date and time for which to calculate the distance. | diff --git a/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt b/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt index 5b787a12..75ea38af 100644 --- a/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt +++ b/source/kotlin/src/main/kotlin/io/github/cosinekitty/astronomy/astronomy.kt @@ -381,9 +381,9 @@ enum class Body( private class StarDef { - public var ra: Double = 0.0 // heliocentric right ascension in EQJ - public var dec: Double = 0.0 // heliocentric declination in EQJ - public var dist: Double = AU_PER_LY // heliocentric distance in AU + public var ra: Double = 0.0 // heliocentric right ascension in EQJ + public var dec: Double = 0.0 // heliocentric declination in EQJ + public var dist: Double = 0.0 // heliocentric distance in AU } private val starTable = arrayOf( @@ -397,7 +397,7 @@ private val starTable = arrayOf( StarDef() // Star8 ) -private fun getUserDefinedStar(body: Body): StarDef? = +private fun getStar(body: Body): StarDef? = when (body) { Body.Star1 -> starTable[0] Body.Star2 -> starTable[1] @@ -410,8 +410,13 @@ private fun getUserDefinedStar(body: Body): StarDef? = else -> null } -private fun isUserDefinedStar(body: Body): Boolean = - (getUserDefinedStar(body) != null) +private fun userDefinedStar(body: Body): StarDef? { + val star = getStar(body) + return if (star != null && star.dist > 0.0) // has the star been defined? + star + else + null +} /** @@ -422,10 +427,8 @@ private fun isUserDefinedStar(body: Body): Boolean = * This function assigns a right ascension, declination, and distance * to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. * - * A star that has not been defined through a call to `defineStar` - * defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - * Once defined, the star keeps the given coordinates until - * a subsequent call to `defineStar` replaces the coordinates with new values. + * Stars are not valid until defined. Once defined, they retain their + * definition until re-defined by another call to `defineStar`. * * @param body * One of the eight user-defined star identifiers: `Body.Star1`, `Body.Star2`, ..., `Body.Star8`. @@ -446,7 +449,7 @@ private fun isUserDefinedStar(body: Body): Boolean = * The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. */ public fun defineStar(body: Body, ra: Double, dec: Double, distanceLightYears: Double) { - val star = getUserDefinedStar(body) ?: throw InvalidBodyException(body) + val star = getStar(body) ?: throw InvalidBodyException(body) if (!ra.isFinite() || ra < 0.0 || ra >= 24.0) throw IllegalArgumentException("Invalid right ascension: $ra") if (!dec.isFinite() || dec < -90.0 || dec > +90.0) throw IllegalArgumentException("Invalid declination: $dec") if (!distanceLightYears.isFinite() || distanceLightYears < 1.0) throw IllegalArgumentException("Invalid distance: $distanceLightYears") @@ -4835,7 +4838,7 @@ private fun solarSystemBarycenterState(time: Time): StateVector { * @return The heliocentric position vector of the center of the given body. */ fun helioVector(body: Body, time: Time): Vector { - val star = getUserDefinedStar(body) + val star = userDefinedStar(body) if (star != null) return Spherical(star.dec, 15.0*star.ra, star.dist).toVector(time) @@ -4860,7 +4863,7 @@ fun helioVector(body: Body, time: Time): Vector { * * @param body * A body for which to calculate a heliocentric distance: - * the Sun, Moon, EMB, SSB, or any of the planets. + * the Sun, Moon, EMB, SSB, any of the planets, or a user-defined star. * * @param time * The date and time for which to calculate the distance. @@ -4870,6 +4873,9 @@ fun helioVector(body: Body, time: Time): Vector { fun helioDistance(body: Body, time: Time): Double { if (body == Body.Sun) return 0.0 + val star = userDefinedStar(body) + if (star != null) + return star.dist val vm = optionalVsopModel(body) return if (vm != null) vsopDistance(vm, time) @@ -4906,7 +4912,7 @@ fun helioDistance(body: Body, time: Time): Double { * The velocities are expressed in AU/day. */ fun helioState(body: Body, time: Time): StateVector { - if (isUserDefinedStar(body)) { + if (null != userDefinedStar(body)) { val vec = helioVector(body, time) return StateVector(vec.x, vec.y, vec.z, 0.0, 0.0, 0.0, time) } diff --git a/source/python/README.md b/source/python/README.md index a9063312..a222c411 100644 --- a/source/python/README.md +++ b/source/python/README.md @@ -1457,10 +1457,8 @@ Some Astronomy Engine functions allow their `body` parameter to be a user-defined fixed point in the sky, loosely called a "star". This function assigns a right ascension, declination, and distance to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. -A star that has not been defined through a call to `DefineStar` -defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. -Once defined, the star keeps the given coordinates until -a subsequent call to `DefineStar` replaces the coordinates with new values. +Stars are not valid until defined. Once defined, they retain their +definition until re-defined by another call to `DefineStar`. | Type | Parameter | Description | | --- | --- | --- | @@ -1733,7 +1731,7 @@ of the resulting vector. | Type | Parameter | Description | | --- | --- | --- | -| [`Body`](#Body) | `body` | A body for which to calculate a heliocentric distance: the Sun, Moon, or any of the planets. | +| [`Body`](#Body) | `body` | A body for which to calculate a heliocentric distance: the Sun, Moon, any of the planets, or a user-defined star. | | [`Time`](#Time) | `time` | The date and time for which to calculate the heliocentric distance. | **Returns**: `float` diff --git a/source/python/astronomy/astronomy.py b/source/python/astronomy/astronomy.py index 960fcfd6..c2e327f0 100644 --- a/source/python/astronomy/astronomy.py +++ b/source/python/astronomy/astronomy.py @@ -355,27 +355,23 @@ class Body(enum.Enum): Star8 = 108 class _StarDef: - def __init__(self, ra, dec, dist): - self.ra = ra - self.dec = dec - self.dist = dist + def __init__(self): + self.ra = 0.0 + self.dec = 0.0 + self.dist = 0.0 # signals that the star has not yet been defined -_StarTable = [ - _StarDef(0.0, 0.0, AU_PER_LY), # Star1 - _StarDef(0.0, 0.0, AU_PER_LY), # Star2 - _StarDef(0.0, 0.0, AU_PER_LY), # Star3 - _StarDef(0.0, 0.0, AU_PER_LY), # Star4 - _StarDef(0.0, 0.0, AU_PER_LY), # Star5 - _StarDef(0.0, 0.0, AU_PER_LY), # Star6 - _StarDef(0.0, 0.0, AU_PER_LY), # Star7 - _StarDef(0.0, 0.0, AU_PER_LY), # Star8 -] +_StarTable = [_StarDef() for _ in range(8)] -def _IsUserDefinedStar(body): - return Body.Star1.value <= body.value <= Body.Star8.value +def _GetStar(body): + if Body.Star1.value <= body.value <= Body.Star8.value: + return _StarTable[body.value - Body.Star1.value] + return None -def _GetUserDefinedStar(body): - return _StarTable[body.value - Body.Star1.value] if _IsUserDefinedStar(body) else None +def _UserDefinedStar(body): + star = _GetStar(body) + if star and (star.dist > 0.0): + return star + return None def DefineStar(body, ra, dec, distanceLightYears): """Assign equatorial coordinates to a user-defined star. @@ -385,10 +381,8 @@ def DefineStar(body, ra, dec, distanceLightYears): This function assigns a right ascension, declination, and distance to one of the eight user-defined stars `Body.Star1`..`Body.Star8`. - A star that has not been defined through a call to `DefineStar` - defaults to the coordinates RA=0, DEC=0 and a heliocentric distance of 1 light-year. - Once defined, the star keeps the given coordinates until - a subsequent call to `DefineStar` replaces the coordinates with new values. + Stars are not valid until defined. Once defined, they retain their + definition until re-defined by another call to `DefineStar`. Parameters ---------- @@ -407,9 +401,9 @@ def DefineStar(body, ra, dec, distanceLightYears): If you don't know the distance to the star, using a large value like 1000 will generally work well. The minimum allowed distance is 1 light-year, which is required to provide certain internal optimizations. """ - star = _GetUserDefinedStar(body) + star = _GetStar(body) if star is None: - raise Error('Body must be a user-defined star, not {}.'.format(body)) + raise InvalidBodyError(body) if not (0.0 <= ra < 24.0): raise Error('Invalid right ascension: {}'.format(ra)) if not (-90.0 <= dec <= +90.0): @@ -4537,8 +4531,8 @@ def HelioVector(body, time): if body == Body.SSB: return _CalcSolarSystemBarycenter(time) - star = _GetUserDefinedStar(body) - if star is not None: + star = _UserDefinedStar(body) + if star: return VectorFromSphere(Spherical(star.dec, 15.0*star.ra, star.dist), time) raise InvalidBodyError(body) @@ -4557,7 +4551,7 @@ def HelioDistance(body, time): ---------- body : Body A body for which to calculate a heliocentric distance: - the Sun, Moon, or any of the planets. + the Sun, Moon, any of the planets, or a user-defined star. time : Time The date and time for which to calculate the heliocentric distance. @@ -4572,6 +4566,10 @@ def HelioDistance(body, time): if 0 <= body.value < len(_vsop): return _VsopHelioDistance(_vsop[body.value], time) + star = _UserDefinedStar(body) + if star: + return star.dist + return HelioVector(body, time).Length() @@ -4727,7 +4725,7 @@ def BackdatePosition(time, observerBody, targetBody, aberration): Its `t` field holds the time that light left the observed body to arrive at the observer at the observation time. """ - if _IsUserDefinedStar(targetBody): + if _UserDefinedStar(targetBody): # This is a user-defined star, which must be treated as a special case. # First, we assume its heliocentric position does not change with time. # Second, we assume its heliocentric position has already been corrected @@ -4958,7 +4956,7 @@ def HelioState(body, time): time ) - if _IsUserDefinedStar(body): + if _UserDefinedStar(body): vec = HelioVector(body, time) return StateVector(vec.x, vec.y, vec.z, 0.0, 0.0, 0.0, time) @@ -6668,7 +6666,7 @@ def _MaxAltitudeSlope(body, latitude): elif body in [Body.Jupiter, Body.Saturn, Body.Uranus, Body.Neptune, Body.Pluto]: deriv_ra = -0.2 deriv_dec = +0.2 - elif _IsUserDefinedStar(body): + elif _UserDefinedStar(body): # The minimum allowed heliocentric distance of a user-defined star # is one light-year. This can cause a tiny amount of parallax (about 0.001 degrees). # Also, including stellar aberration (22 arcsec = 0.006 degrees), we provide a