UNPKG

21.6 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.EclipticPrecessor = exports.Precessor = undefined;
7
8var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
9
10var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /**
11 * @copyright 2013 Sonia Keys
12 * @copyright 2016 commenthol
13 * @license MIT
14 * @module precess
15 */
16/**
17 * Precession: Chapter 21, Precession.
18 *
19 * Functions in this package take Julian epoch argurments rather than Julian
20 * days. Use base.JDEToJulianYear() to convert.
21 *
22 * Also in package base are some definitions related to the Besselian and
23 * Julian Year.
24 *
25 * Partial: Precession from FK4 not implemented. Meeus gives no test cases.
26 * It's a fair amount of code and data, representing significant chances for
27 * errors. And precession from FK4 would seem to be of little interest today.
28 *
29 * Proper motion units
30 *
31 * Meeus gives some example annual proper motions in units of seconds of
32 * right ascension and seconds of declination. To make units clear,
33 * functions in this package take proper motions with argument types of
34 * sexa.HourAngle and sexa.Angle respectively. Error-prone conversions
35 * can be avoided by using the constructors for these base types.
36 *
37 * For example, given an annual proper motion in right ascension of -0ˢ.03847,
38 * rather than
39 *
40 * mra = -0.03847 / 13751 // as Meeus suggests
41 *
42 * or
43 *
44 * mra = -0.03847 * (15/3600) * (pi/180) // less magic
45 *
46 * use
47 *
48 * mra = new sexa.HourAngle(false, 0, 0, -0.03847)
49 *
50 * Unless otherwise indicated, functions in this library expect proper motions
51 * to be annual proper motions, so the unit denominator is years.
52 * (The code, following Meeus's example, technically treats it as Julian years.)
53 */
54
55exports.approxAnnualPrecession = approxAnnualPrecession;
56exports.mn = mn;
57exports.approxPosition = approxPosition;
58exports.position = position;
59exports.eclipticPosition = eclipticPosition;
60exports.properMotion = properMotion;
61exports.properMotion3D = properMotion3D;
62
63var _base = require('./base');
64
65var _base2 = _interopRequireDefault(_base);
66
67var _coord = require('./coord');
68
69var _coord2 = _interopRequireDefault(_coord);
70
71var _elementequinox = require('./elementequinox');
72
73var _elementequinox2 = _interopRequireDefault(_elementequinox);
74
75var _nutation = require('./nutation');
76
77var _nutation2 = _interopRequireDefault(_nutation);
78
79var _sexagesimal = require('./sexagesimal');
80
81var _sexagesimal2 = _interopRequireDefault(_sexagesimal);
82
83function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
84
85function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
86
87/**
88 * approxAnnualPrecession returns approximate annual precision in right
89 * ascension and declination.
90 *
91 * The two epochs should be within a few hundred years.
92 * The declinations should not be too close to the poles.
93 *
94 * @param {coord.Equatorial} eqFrom
95 * @param {Number} epochFrom - use `base.JDEToJulianYear(year)` to get epoch
96 * @param {Number} epochTo - use `base.JDEToJulianYear(year)` to get epoch
97 * @returns {Array}
98 * {sexa.HourAngle} seconds of right ascension
99 * {sexa.Angle} seconds of Declination
100 */
101function approxAnnualPrecession(eqFrom, epochFrom, epochTo) {
102 var _mn = mn(epochFrom, epochTo),
103 _mn2 = _slicedToArray(_mn, 3),
104 m = _mn2[0],
105 na = _mn2[1],
106 nd = _mn2[2];
107
108 var _base$sincos = _base2.default.sincos(eqFrom.ra),
109 _base$sincos2 = _slicedToArray(_base$sincos, 2),
110 sa = _base$sincos2[0],
111 ca = _base$sincos2[1];
112 // (21.1) p. 132
113
114
115 var Δαs = m + na * sa * Math.tan(eqFrom.dec); // seconds of RA
116 var Δδs = nd * ca; // seconds of Dec
117 var ra = new _sexagesimal2.default.HourAngle(false, 0, 0, Δαs).rad();
118 var dec = new _sexagesimal2.default.Angle(false, 0, 0, Δδs).rad();
119 return { ra: ra, dec: dec };
120}
121
122/**
123 * @param {Number} epochFrom - use `base.JDEToJulianYear(year)` to get epoch
124 * @param {Number} epochTo - use `base.JDEToJulianYear(year)` to get epoch
125 */
126function mn(epochFrom, epochTo) {
127 var T = (epochTo - epochFrom) * 0.01;
128 var m = 3.07496 + 0.00186 * T;
129 var na = 1.33621 - 0.00057 * T;
130 var nd = 20.0431 - 0.0085 * T;
131 return [m, na, nd];
132}
133
134/**
135 * ApproxPosition uses ApproxAnnualPrecession to compute a simple and quick
136 * precession while still considering proper motion.
137 *
138 * @param {coord.Equatorial} eqFrom
139 * @param {Number} epochFrom
140 * @param {Number} epochTo
141 * @param {Number} mα - in radians
142 * @param {Number} mδ - in radians
143 * @returns {coord.Equatorial} eqTo
144 */
145function approxPosition(eqFrom, epochFrom, epochTo, mα, mδ) {
146 var _approxAnnualPrecessi = approxAnnualPrecession(eqFrom, epochFrom, epochTo),
147 ra = _approxAnnualPrecessi.ra,
148 dec = _approxAnnualPrecessi.dec;
149
150 var dy = epochTo - epochFrom;
151 var eqTo = new _coord2.default.Equatorial();
152 eqTo.ra = eqFrom.ra + (ra + mα) * dy;
153 eqTo.dec = eqFrom.dec + (dec + mδ) * dy;
154 return eqTo;
155}
156
157// constants
158var d = Math.PI / 180;
159var s = d / 3600;
160
161// coefficients from (21.2) p. 134
162var ζT = [2306.2181 * s, 1.39656 * s, -0.000139 * s];
163var zT = [2306.2181 * s, 1.39656 * s, -0.000139 * s];
164var θT = [2004.3109 * s, -0.8533 * s, -0.000217 * s];
165// coefficients from (21.3) p. 134
166var ζt = [2306.2181 * s, 0.30188 * s, 0.017998 * s];
167var zt = [2306.2181 * s, 1.09468 * s, 0.018203 * s];
168var θt = [2004.3109 * s, -0.42665 * s, -0.041833 * s];
169
170/**
171 * Precessor represents precession from one epoch to another.
172 *
173 * Construct with NewPrecessor, then call method Precess.
174 * After construction, Precess may be called multiple times to precess
175 * different coordinates with the same initial and final epochs.
176 */
177
178var Precessor = exports.Precessor = function () {
179 /**
180 * constructs a Precessor object and initializes it to precess
181 * coordinates from epochFrom to epochTo.
182 * @param {Number} epochFrom
183 * @param {Number} epochTo
184 */
185 function Precessor(epochFrom, epochTo) {
186 _classCallCheck(this, Precessor);
187
188 // (21.2) p. 134
189 var ζCoeff = ζt;
190 var zCoeff = zt;
191 var θCoeff = θt;
192 if (epochFrom !== 2000) {
193 var T = (epochFrom - 2000) * 0.01;
194 ζCoeff = [_base2.default.horner(T, ζT), 0.30188 * s - 0.000344 * s * T, 0.017998 * s];
195 zCoeff = [_base2.default.horner(T, zT), 1.09468 * s + 0.000066 * s * T, 0.018203 * s];
196 θCoeff = [_base2.default.horner(T, θT), -0.42665 * s - 0.000217 * s * T, -0.041833 * s];
197 }
198 var t = (epochTo - epochFrom) * 0.01;
199 this.ζ = _base2.default.horner(t, ζCoeff) * t;
200 this.z = _base2.default.horner(t, zCoeff) * t;
201 var θ = _base2.default.horner(t, θCoeff) * t;
202 this.sθ = Math.sin(θ);
203 this.cθ = Math.cos(θ);
204 }
205
206 /**
207 * Precess precesses coordinates eqFrom, leaving result in eqTo.
208 *
209 * @param {coord.Equatorial} eqFrom
210 * @returns {coord.Equatorial} eqTo
211 */
212
213
214 _createClass(Precessor, [{
215 key: 'precess',
216 value: function precess(eqFrom) {
217 // (21.4) p. 134
218 var _base$sincos3 = _base2.default.sincos(eqFrom.dec),
219 _base$sincos4 = _slicedToArray(_base$sincos3, 2),
220 sδ = _base$sincos4[0],
221 cδ = _base$sincos4[1];
222
223 var _base$sincos5 = _base2.default.sincos(eqFrom.ra + this.ζ),
224 _base$sincos6 = _slicedToArray(_base$sincos5, 2),
225 sαζ = _base$sincos6[0],
226 cαζ = _base$sincos6[1];
227
228 var A = cδ * sαζ;
229 var B = this.cθ * cδ * cαζ - this.sθ * sδ;
230 var C = this.sθ * cδ * cαζ + this.cθ * sδ;
231 var eqTo = new _coord2.default.Equatorial();
232 eqTo.ra = Math.atan2(A, B) + this.z;
233 if (C < _base2.default.CosSmallAngle) {
234 eqTo.dec = Math.asin(C);
235 } else {
236 eqTo.dec = Math.acos(Math.hypot(A, B)); // near pole
237 }
238 return eqTo;
239 }
240 }]);
241
242 return Precessor;
243}();
244
245/**
246 * Position precesses equatorial coordinates from one epoch to another,
247 * including proper motions.
248 *
249 * If proper motions are not to be considered or are not applicable, pass 0, 0
250 * for mα, mδ
251 *
252 * Both eqFrom and eqTo must be non-nil, although they may point to the same
253 * struct. EqTo is returned for convenience.
254 * @param {coord.Equatorial} eqFrom
255 * @param {coord.Equatorial} eqTo
256 * @param {Number} epochFrom
257 * @param {Number} epochTo
258 * @param {Number} mα - in radians
259 * @param {Number} mδ - in radians
260 * @returns {coord.Equatorial} [eqTo]
261 */
262
263
264function position(eqFrom, epochFrom, epochTo, mα, mδ) {
265 var p = new Precessor(epochFrom, epochTo);
266 var t = epochTo - epochFrom;
267 var eqTo = new _coord2.default.Equatorial();
268 eqTo.ra = eqFrom.ra + mα * t;
269 eqTo.dec = eqFrom.dec + mδ * t;
270 return p.precess(eqTo);
271}
272
273// coefficients from (21.5) p. 136
274var ηT = [47.0029 * s, -0.06603 * s, 0.000598 * s];
275var πT = [174.876384 * d, 3289.4789 * s, 0.60622 * s];
276var pT = [5029.0966 * s, 2.22226 * s, -0.000042 * s];
277var ηt = [47.0029 * s, -0.03302 * s, 0.000060 * s];
278var πt = [174.876384 * d, -869.8089 * s, 0.03536 * s];
279var pt = [5029.0966 * s, 1.11113 * s, -0.000006 * s];
280
281/**
282 * EclipticPrecessor represents precession from one epoch to another.
283 *
284 * Construct with NewEclipticPrecessor, then call method Precess.
285 * After construction, Precess may be called multiple times to precess
286 * different coordinates with the same initial and final epochs.
287 */
288
289var EclipticPrecessor = exports.EclipticPrecessor = function () {
290 /**
291 * constructs an EclipticPrecessor object and initializes
292 * it to precess coordinates from epochFrom to epochTo.
293 * @param {Number} epochFrom
294 * @param {Number} epochTo
295 */
296 function EclipticPrecessor(epochFrom, epochTo) {
297 _classCallCheck(this, EclipticPrecessor);
298
299 // (21.5) p. 136
300 var ηCoeff = ηt;
301 var πCoeff = πt;
302 var pCoeff = pt;
303 if (epochFrom !== 2000) {
304 var T = (epochFrom - 2000) * 0.01;
305 ηCoeff = [_base2.default.horner(T, ηT), -0.03302 * s + 0.000598 * s * T, 0.000060 * s];
306 πCoeff = [_base2.default.horner(T, πT), -869.8089 * s - 0.50491 * s * T, 0.03536 * s];
307 pCoeff = [_base2.default.horner(T, pT), 1.11113 * s - 0.000042 * s * T, -0.000006 * s];
308 }
309 var t = (epochTo - epochFrom) * 0.01;
310 this.π = _base2.default.horner(t, πCoeff);
311 this.p = _base2.default.horner(t, pCoeff) * t;
312 var η = _base2.default.horner(t, ηCoeff) * t;
313 this.sη = Math.sin(η);
314 this.cη = Math.cos(η);
315 }
316
317 /**
318 * EclipticPrecess precesses coordinates eclFrom, leaving result in eclTo.
319 *
320 * The same struct may be used for eclFrom and eclTo.
321 * EclTo is returned for convenience.
322 * @param {coord.Ecliptic} eclFrom
323 * @param {coord.Ecliptic} eclTo
324 * @returns {coord.Ecliptic} [eclTo]
325 */
326
327
328 _createClass(EclipticPrecessor, [{
329 key: 'precess',
330 value: function precess(eclFrom) {
331 // (21.7) p. 137
332 var _base$sincos7 = _base2.default.sincos(eclFrom.lat),
333 _base$sincos8 = _slicedToArray(_base$sincos7, 2),
334 sβ = _base$sincos8[0],
335 cβ = _base$sincos8[1];
336
337 var _base$sincos9 = _base2.default.sincos(this.π - eclFrom.lon),
338 _base$sincos10 = _slicedToArray(_base$sincos9, 2),
339 sd = _base$sincos10[0],
340 cd = _base$sincos10[1];
341
342 var A = this.cη * cβ * sd - this.sη * sβ;
343 var B = cβ * cd;
344 var C = this.cη * sβ + this.sη * cβ * sd;
345 var eclTo = new _coord2.default.Ecliptic();
346 eclTo.lon = this.p + this.π - Math.atan2(A, B);
347 if (C < _base2.default.CosSmallAngle) {
348 eclTo.lat = Math.asin(C);
349 } else {
350 eclTo.lat = Math.acos(Math.hypot(A, B)); // near pole
351 }
352 return eclTo;
353 }
354
355 /**
356 * ReduceElements reduces orbital elements of a solar system body from one
357 * equinox to another.
358 *
359 * This function is described in chapter 24, but is located in this
360 * package so it can be a method of EclipticPrecessor.
361 *
362 * @param {elementequinox.Elements} eFrom
363 * @returns {elementequinox.Elements} eTo
364 */
365
366 }, {
367 key: 'reduceElements',
368 value: function reduceElements(eFrom) {
369 var ψ = this.π + this.p;
370
371 var _base$sincos11 = _base2.default.sincos(eFrom.inc),
372 _base$sincos12 = _slicedToArray(_base$sincos11, 2),
373 si = _base$sincos12[0],
374 ci = _base$sincos12[1];
375
376 var _base$sincos13 = _base2.default.sincos(eFrom.node - this.π),
377 _base$sincos14 = _slicedToArray(_base$sincos13, 2),
378 snp = _base$sincos14[0],
379 cnp = _base$sincos14[1];
380
381 var eTo = new _elementequinox2.default.Elements();
382 // (24.1) p. 159
383 eTo.inc = Math.acos(ci * this.cη + si * this.sη * cnp);
384 // (24.2) p. 159
385 eTo.node = Math.atan2(si * snp, this.cη * si * cnp - this.sη * ci) + ψ;
386 // (24.3) p. 159
387 eTo.peri = Math.atan2(-this.sη * snp, si * this.cη - ci * this.sη * cnp) + eFrom.peri;
388 return eTo;
389 }
390 }]);
391
392 return EclipticPrecessor;
393}();
394
395/**
396 * eclipticPosition precesses ecliptic coordinates from one epoch to another,
397 * including proper motions.
398 * While eclFrom is given as ecliptic coordinates, proper motions mα, mδ are
399 * still expected to be equatorial. If proper motions are not to be considered
400 * or are not applicable, pass 0, 0.
401 * Both eclFrom and eclTo must be non-nil, although they may point to the same
402 * struct. EclTo is returned for convenience.
403 *
404 * @param {coord.Ecliptic} eclFrom,
405 * @param {Number} epochFrom
406 * @param {Number} epochTo
407 * @param {sexa.HourAngle} mα
408 * @param {sexa.Angle} mδ
409 * @returns {coord.Ecliptic} eclTo
410 */
411
412
413function eclipticPosition(eclFrom, epochFrom, epochTo, mα, mδ) {
414 var p = new EclipticPrecessor(epochFrom, epochTo);
415
416 if (mα !== 0 || mδ !== 0) {
417 var _properMotion = properMotion(mα.rad(), mδ.rad(), epochFrom, eclFrom),
418 lon = _properMotion.lon,
419 lat = _properMotion.lat;
420
421 var t = epochTo - epochFrom;
422 eclFrom.lon += lon * t;
423 eclFrom.lat += lat * t;
424 }
425 return p.precess(eclFrom);
426}
427
428/**
429 * @param {Number} mα - anual proper motion (ra)
430 * @param {Number} mδ - anual proper motion (dec)
431 * @param {Number} epoch
432 * @param {coord.Ecliptic} ecl
433 * @returns {Number[]} [mλ, mβ]
434 */
435function properMotion(mα, mδ, epoch, ecl) {
436 var ε = _nutation2.default.meanObliquity(_base2.default.JulianYearToJDE(epoch));
437
438 var _base$sincos15 = _base2.default.sincos(ε),
439 _base$sincos16 = _slicedToArray(_base$sincos15, 2),
440 εsin = _base$sincos16[0],
441 εcos = _base$sincos16[1];
442
443 var _ecl$toEquatorial = ecl.toEquatorial(ε),
444 ra = _ecl$toEquatorial.ra,
445 dec = _ecl$toEquatorial.dec;
446
447 var _base$sincos17 = _base2.default.sincos(ra),
448 _base$sincos18 = _slicedToArray(_base$sincos17, 2),
449 sα = _base$sincos18[0],
450 cα = _base$sincos18[1];
451
452 var _base$sincos19 = _base2.default.sincos(dec),
453 _base$sincos20 = _slicedToArray(_base$sincos19, 2),
454 sδ = _base$sincos20[0],
455 cδ = _base$sincos20[1];
456
457 var cβ = Math.cos(ecl.lat);
458 var lon = (mδ * εsin * cα + mα * cδ * (εcos * cδ + εsin * sδ * sα)) / (cβ * cβ);
459 var lat = (mδ * (εcos * cδ + εsin * sδ * sα) - mα * εsin * cα * cδ) / cβ;
460 return new _coord2.default.Ecliptic(lon, lat);
461}
462
463/**
464 * ProperMotion3D takes the 3D equatorial coordinates of an object
465 * at one epoch and computes its coordinates at a new epoch, considering
466 * proper motion and radial velocity.
467 *
468 * Radial distance (r) must be in parsecs, radial velocitiy (mr) in
469 * parsecs per year.
470 *
471 * Both eqFrom and eqTo must be non-nil, although they may point to the same
472 * struct. EqTo is returned for convenience.
473 *
474 * @param {coord.Equatorial} eqFrom,
475 * @param {Number} epochFrom
476 * @param {Number} r
477 * @param {Number} mr
478 * @param {sexa.HourAngle} mα
479 * @param {sexa.Angle} mδ
480 * @returns {coord.Equatorial} eqTo
481 */
482function properMotion3D(eqFrom, epochFrom, epochTo, r, mr, mα, mδ) {
483 var _base$sincos21 = _base2.default.sincos(eqFrom.ra),
484 _base$sincos22 = _slicedToArray(_base$sincos21, 2),
485 sα = _base$sincos22[0],
486 cα = _base$sincos22[1];
487
488 var _base$sincos23 = _base2.default.sincos(eqFrom.dec),
489 _base$sincos24 = _slicedToArray(_base$sincos23, 2),
490 sδ = _base$sincos24[0],
491 cδ = _base$sincos24[1];
492
493 var x = r * cδ * cα;
494 var y = r * cδ * sα;
495 var z = r * sδ;
496 var mrr = mr / r;
497 var zmδ = z * mδ.rad();
498 var mx = x * mrr - zmδ * cα - y * mα.rad();
499 var my = y * mrr - zmδ * sα + x * mα.rad();
500 var mz = z * mrr + r * mδ.rad() * cδ;
501 var t = epochTo - epochFrom;
502 var xp = x + t * mx;
503 var yp = y + t * my;
504 var zp = z + t * mz;
505 var eqTo = new _coord2.default.Equatorial();
506 eqTo.ra = Math.atan2(yp, xp);
507 eqTo.dec = Math.atan2(zp, Math.hypot(xp, yp));
508 return eqTo;
509}
510
511exports.default = {
512 approxAnnualPrecession: approxAnnualPrecession,
513 mn: mn,
514 approxPosition: approxPosition,
515 Precessor: Precessor,
516 position: position,
517 EclipticPrecessor: EclipticPrecessor,
518 eclipticPosition: eclipticPosition,
519 properMotion: properMotion,
520 properMotion3D: properMotion3D
521};
\No newline at end of file