UNPKG

11.6 kBJavaScriptView Raw
1export { _approxTimes as approxTimes };
2export { _times as times };
3
4function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
5
6/* eslint key-spacing: 1 */
7/**
8 * @copyright 2013 Sonia Keys
9 * @copyright 2016 commenthol
10 * @license MIT
11 * @module rise
12 */
13/**
14 * Rise: Chapter 15, Rising, Transit, and Setting.
15 */
16
17import base from './base';
18import deltat from './deltat';
19import elliptic from './elliptic';
20import interp from './interpolation';
21import julian from './julian';
22import sexa from './sexagesimal';
23import sidereal from './sidereal';
24var acos = Math.acos,
25 asin = Math.asin,
26 cos = Math.cos,
27 sin = Math.sin;
28
29
30var SECS_PER_DEGREE = 240; // = 86400 / 360
31var SECS_PER_DAY = 86400;
32var D2R = Math.PI / 180;
33
34export var errorAboveHorizon = base.errorCode('always above horizon', -1);
35export var errorBelowHorizon = base.errorCode('always below horizon', 1);
36
37/**
38 * mean refraction of the atmosphere
39 */
40export var meanRefraction = new sexa.Angle(false, 0, 34, 0).rad();
41
42/**
43 * "Standard altitudes" for various bodies already including `meanRefraction` of 0°34'
44 *
45 * The standard altitude is the geometric altitude of the center of body
46 * at the time of apparent rising or seting.
47 */
48export var stdh0 = {
49 stellar: -meanRefraction,
50 solar: new sexa.Angle(true, 0, 50, 0).rad(),
51 // not containing meanRefraction
52 lunar: new sexa.Angle(false, 0, 0, 0.7275).rad(),
53 lunarMean: new sexa.Angle(false, 0, 0, 0.125).rad()
54
55 /**
56 * Helper function to obtain corrected refraction
57 * @param {number} h0 - altitude of the body in radians containing `meanRefraction` of 0°34'
58 * @param {number} corr - the calcluated refraction e.g. from package `refraction` in radians
59 * @return {number} refraction value in radians
60 */
61};export function refraction(h0, corr) {
62 if (!corr) {
63 return h0;
64 } else {
65 return h0 - meanRefraction - corr;
66 }
67}
68
69/**
70 * standard altitude for stars, planets at apparent rising, seting
71 */
72export var stdh0Stellar = function stdh0Stellar(_refraction) {
73 return refraction(stdh0.stellar, _refraction);
74};
75export var Stdh0Stellar = stdh0Stellar(); // for backward-compatibility
76/**
77 * standard altitude for sun for upper limb of the disk
78 */
79export var stdh0Solar = function stdh0Solar(_refraction) {
80 return refraction(stdh0.solar, _refraction);
81};
82export var Stdh0Solar = stdh0Solar(); // for backward-compatibility
83
84/**
85 * standard altitude for moon (low accuracy)
86 */
87export var stdh0LunarMean = function stdh0LunarMean(_refraction) {
88 return stdh0.lunarMean - refraction(_refraction);
89};
90export var Stdh0LunarMean = stdh0LunarMean(); // for backward-compatibility
91/**
92 * Stdh0Lunar is the standard altitude of the Moon considering π, the
93 * Moon's horizontal parallax.
94 * @param {number} π - the Moon's horizontal parallax
95 * @param {number} [refraction] - optional value for refraction in radians if
96 * omitted than meanRefraction is used
97 * @return {number} altitude of Moon in radians
98 */
99export var stdh0Lunar = function stdh0Lunar(π, refraction) {
100 refraction = refraction || meanRefraction;
101 return stdh0.lunar * π - refraction;
102};
103export var Stdh0Lunar = stdh0Lunar; // for backward-compatibility
104
105/**
106 * @return {number} local angle in radians
107 */
108export function hourAngle(lat, h0, δ) {
109 // approximate local hour angle
110 var cosH = (sin(h0) - sin(lat) * sin(δ)) / (cos(lat) * cos(δ)); // (15.1) p. 102
111 if (cosH < -1) {
112 throw errorAboveHorizon;
113 } else if (cosH > 1) {
114 throw errorBelowHorizon;
115 }
116 var H = acos(cosH);
117 return H;
118}
119
120/**
121 * @param {number} lon - longitude in radians
122 * @param {number} α - right ascension in radians
123 * @param {number} th0 - sidereal.apparent0UT in seconds of day `[0...86400[`
124 * @return {number} time of transit in seconds of day `[0, 86400[`
125 */
126function _mt(lon, α, th0) {
127 // const mt = (((lon + α) * 180 / Math.PI - (th0 * 360 / 86400)) * 86400 / 360)
128 var mt = (lon + α) * SECS_PER_DEGREE * 180 / Math.PI - th0;
129 return mt;
130}
131
132/**
133 * @param {number} Th0 - sidereal.apparent0UT in seconds of day `[0...86400[`
134 * @param {number} m - motion in seconds of day `[0...86400[`
135 * @return {number} new siderial time seconds of day `[0...86400[`
136 */
137function _th0(Th0, m) {
138 // in original formula Th0 = 0...360 and m = 0...1 -> return value would be in 0...360 degrees
139 // Th0 /= 240
140 // m /= 86400
141 var th0 = base.pmod(Th0 + m * 360.985647 / 360, SECS_PER_DAY); // p103
142 return th0; // 0...86400 in seconds angle
143}
144
145// maintain backward compatibility - will be removed in v2
146// return value in future will be an object not an array
147function _compatibility(rs) {
148 var _rs = [rs.rise, rs.transit, rs.set];
149 _rs.rise = rs.rise;
150 _rs.transit = rs.transit;
151 _rs.set = rs.set;
152 return _rs;
153}
154
155/**
156 * ApproxTimes computes approximate UT rise, transit and set times for
157 * a celestial object on a day of interest.
158 *
159 * The function argurments do not actually include the day, but do include
160 * values computed from the day.
161 *
162 * @param {coord.Globe} p - is geographic coordinates of observer.
163 * @param {number} h0 - is "standard altitude" of the body in radians
164 * @param {number} Th0 - is apparent sidereal time at 0h UT at Greenwich in seconds
165 * (range 0...86400) must be the time on the day of interest, in seconds.
166 * See sidereal.apparent0UT
167 * @param {Array<number>} α3 - slices of three right ascensions
168 * @param {Array<number>} δ3 - slices of three declinations.
169 * α3, δ3 must be values at 0h dynamical time for the day before, the day of,
170 * and the day after the day of interest. Units are radians.
171 * @return Result units are seconds and are in the range [0,86400)
172 * @throws Error
173 */
174function _approxTimes(p, h0, Th0, α, δ) {
175 var H0 = hourAngle(p.lat, h0, δ) * SECS_PER_DEGREE * 180 / Math.PI; // in degrees per day === seconds
176 // approximate transit, rise, set times.
177 // (15.2) p. 102.0
178 var mt = _mt(p.lon, α, Th0);
179 var rs = {};
180 rs.transit = base.pmod(mt, SECS_PER_DAY);
181 rs.rise = base.pmod(mt - H0, SECS_PER_DAY);
182 rs.set = base.pmod(mt + H0, SECS_PER_DAY);
183 return _compatibility(rs);
184}
185
186/**
187 * Times computes UT rise, transit and set times for a celestial object on
188 * a day of interest.
189 *
190 * The function argurments do not actually include the day, but do include
191 * a number of values computed from the day.
192 *
193 * @param {coord.Globe} p - is geographic coordinates of observer.
194 * @param {number} ΔT - is delta T in seconds
195 * @param {number} h0 - is "standard altitude" of the body in radians
196 * @param {number} Th0 - is apparent sidereal time at 0h UT at Greenwich in seconds
197 * (range 0...86400) must be the time on the day of interest, in seconds.
198 * See sidereal.apparent0UT
199 * @param {Array<number>} α3 - slices of three right ascensions
200 * @param {Array<number>} δ3 - slices of three declinations.
201 * α3, δ3 must be values at 0h dynamical time for the day before, the day of,
202 * and the day after the day of interest. Units are radians.
203 *
204 * @return Result units are seconds and are in the range [0,86400)
205 * @throws Error
206 */
207function _times(p, ΔT, h0, Th0, α3, δ3) {
208 // (p globe.Coord, ΔT, h0, Th0 float64, α3, δ3 []float64) (mRise, mTransit, mSet float64, err error)
209 var rs = _approxTimes(p, h0, Th0, α3[1], δ3[1]);
210 var d3α = new interp.Len3(-SECS_PER_DAY, SECS_PER_DAY, α3);
211 var d3δ = new interp.Len3(-SECS_PER_DAY, SECS_PER_DAY, δ3);
212
213 // adjust mTransit
214 var ut = rs.transit + ΔT;
215 var α = d3α.interpolateX(ut);
216 var th0 = _th0(Th0, rs.transit);
217 var H = -1 * _mt(p.lon, α, th0); // in secs // Hmeus = 0...360
218 rs.transit -= H;
219
220 // adjust mRise, mSet
221
222 var _base$sincos = base.sincos(p.lat),
223 sLat = _base$sincos[0],
224 cLat = _base$sincos[1];
225
226 var adjustRS = function adjustRS(m) {
227 var ut = m + ΔT;
228 var α = d3α.interpolateX(ut);
229 var δ = d3δ.interpolateX(ut);
230 var th0 = _th0(Th0, m);
231 var H = -1 * _mt(p.lon, α, th0);
232 var Hrad = H / SECS_PER_DEGREE * D2R;
233 var h = asin(sLat * sin(δ) + cLat * cos(δ) * cos(Hrad)); // formula 13.6
234 var Δm = SECS_PER_DAY * (h - h0) / (cos(δ) * cLat * sin(Hrad) * 2 * Math.PI); // formula p103 3
235 return m + Δm;
236 };
237
238 rs.rise = adjustRS(rs.rise);
239 rs.set = adjustRS(rs.set);
240
241 return _compatibility(rs);
242}
243
244/**
245 * RisePlanet computes rise, transit and set times for a planet on a day of interest.
246 */
247export var PlanetRise = function () {
248 /**
249 * @param {number|Date} jd - Julian Day starting at midnight or Date object
250 * @param {number} lat - geographic latitude of the observerin degrees
251 * @param {number} lon - geographic longitude of the observer in degrees (measured positively westward)
252 * @param {planetposition.Planet} earth - VSOP87 Planet object for Earth
253 * @param {planetposition.Planet} planet - VSOP87 Planet object of observed body
254 * @param {object} opts
255 * @param {boolean} opts.date - return times as Date objects
256 * @param {number} opts.refraction - use different refraction than `stdh0Stellar`
257 */
258 function PlanetRise(jd, lat, lon, earth, planet, opts) {
259 _classCallCheck(this, PlanetRise);
260
261 this.opts = opts || {};
262 this.refraction = this.opts.refraction || stdh0Stellar();
263 if (jd instanceof Date) {
264 jd = new julian.Calendar().fromDate(jd).toJD();
265 }
266 this.jd = Math.floor(jd - 0.5) + 0.5; // start at midnight
267 this.lat = lat * D2R; // convert to radians
268 this.lon = lon * D2R;
269 var cal = new julian.Calendar().fromJD(this.jd);
270 this.jde = cal.toJDE();
271 this.ΔT = deltat.deltaT(cal.toYear());
272 this.earth = earth;
273 this.planet = planet;
274 }
275
276 PlanetRise.prototype.approxTimes = function approxTimes() {
277 var body = elliptic.position(this.planet, this.earth, this.jde);
278 var Th0 = sidereal.apparent0UT(this.jd);
279 var rs = _approxTimes({ lat: this.lat, lon: this.lon }, this.refraction, Th0, body.ra, body.dec);
280 return this._rsToJD(rs);
281 };
282
283 PlanetRise.prototype.times = function times() {
284 var body = [elliptic.position(this.planet, this.earth, this.jde - 1), elliptic.position(this.planet, this.earth, this.jde), elliptic.position(this.planet, this.earth, this.jde + 1)];
285 var Th0 = sidereal.apparent0UT(this.jd);
286 var rs = _times({ lat: this.lat, lon: this.lon }, this.ΔT, this.refraction, Th0, this._toArr(body, 'ra'), this._toArr(body, 'dec'));
287 return this._rsToJD(rs);
288 };
289 /** @private */
290
291
292 PlanetRise.prototype._toArr = function _toArr(body, p) {
293 return body.map(function (item) {
294 return item[p];
295 });
296 };
297 /** @private */
298
299
300 PlanetRise.prototype._rsToJD = function _rsToJD(rs) {
301 return {
302 rise: this._toJD(rs.rise),
303 transit: this._toJD(rs.transit),
304 set: this._toJD(rs.set)
305 };
306 };
307 /** @private */
308
309
310 PlanetRise.prototype._toJD = function _toJD(secs) {
311 var jd = this.jd + secs / 86400;
312 if (this.opts.date) {
313 return new julian.Calendar().fromJD(jd).toDate();
314 } else {
315 return jd;
316 }
317 };
318
319 return PlanetRise;
320}();
321
322export default {
323 errorAboveHorizon: errorAboveHorizon,
324 errorBelowHorizon: errorBelowHorizon,
325 meanRefraction: meanRefraction,
326 stdh0: stdh0,
327 refraction: refraction,
328 stdh0Stellar: stdh0Stellar,
329 Stdh0Stellar: Stdh0Stellar,
330 stdh0Solar: stdh0Solar,
331 Stdh0Solar: Stdh0Solar,
332 stdh0LunarMean: stdh0LunarMean,
333 Stdh0LunarMean: Stdh0LunarMean,
334 stdh0Lunar: stdh0Lunar,
335 Stdh0Lunar: Stdh0Lunar,
336 hourAngle: hourAngle,
337 approxTimes: _approxTimes,
338 times: _times,
339 PlanetRise: PlanetRise
340};
\No newline at end of file