@openwaters/almanac 0.11.0 → 0.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/nutation.d.ts +6 -0
- package/dist/nutation.js +14 -3
- package/dist/positions.d.ts +16 -0
- package/dist/positions.js +21 -3
- package/dist/sun.d.ts +12 -0
- package/dist/sun.js +69 -0
- package/dist/transforms.d.ts +26 -6
- package/dist/transforms.js +54 -40
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Almanac
|
|
2
2
|
|
|
3
|
-
Offline sky engine for the Salish Sea and everywhere else: Sun, Moon, and planet positions, apparent horizon dip, rise, set, twilight, any Sun altitude, upper and lower transits, Moon phase and orientation, equinoxes and solstices, lunar perigee and apogee, the equation of time, planetary brightness, lunar and solar eclipses,
|
|
3
|
+
Offline sky engine for the Salish Sea and everywhere else: Sun, Moon, and planet positions, apparent horizon dip, rise, set, twilight, any Sun altitude, upper and lower transits, Moon phase and orientation, equinoxes and solstices, lunar perigee and apogee, the equation of time, planetary brightness, lunar and solar eclipses, fixed-star apparent places, altitude, and azimuth from catalog positions, and Greenwich sidereal time for sight reduction, computed from pure geometry with zero network and zero runtime data files.
|
|
4
4
|
|
|
5
5
|
Three implementations, one behavior:
|
|
6
6
|
|
|
@@ -111,6 +111,7 @@ npm install @openwaters/almanac
|
|
|
111
111
|
```ts
|
|
112
112
|
import {
|
|
113
113
|
nextLunarEclipse, lunarEclipseVisibility, nextSolarEclipse, solarObscuration, nextGlobalSolarEclipse, sunEvents, starAltAz,
|
|
114
|
+
starPosition, greenwichSiderealTime,
|
|
114
115
|
seasons, moonApsides, earthApsides, equationOfTime
|
|
115
116
|
} from '@openwaters/almanac';
|
|
116
117
|
|
|
@@ -136,6 +137,10 @@ for (const { kind, time } of sunEvents(today, tomorrow, observer)) {
|
|
|
136
137
|
// Betelgeuse from its J2000 catalog position: az/alt in degrees, refracted.
|
|
137
138
|
const { azDeg, altDeg } = starAltAz(88.792939, 7.407064, today, observer);
|
|
138
139
|
|
|
140
|
+
// Its apparent place and Greenwich hour angle for sight reduction, in degrees.
|
|
141
|
+
const place = starPosition(88.792939, 7.407064, today);
|
|
142
|
+
const ghaDeg = (greenwichSiderealTime(today) - place.raDeg + 360) % 360;
|
|
143
|
+
|
|
139
144
|
// The year's equinoxes and solstices, the Moon's perigees and apogees with
|
|
140
145
|
// distances, and the equation of time in minutes.
|
|
141
146
|
const year = new Date(today.getUTCFullYear() + 1, 0, 1);
|
|
@@ -161,7 +166,7 @@ const crossings = sunEvents(today, tomorrow, viewer, eyeHeightM);
|
|
|
161
166
|
Requires a Swift 6 or newer toolchain.
|
|
162
167
|
|
|
163
168
|
```swift
|
|
164
|
-
.package(url: "https://github.com/openwatersio/almanac.git", exact: "0.
|
|
169
|
+
.package(url: "https://github.com/openwatersio/almanac.git", exact: "0.12.1")
|
|
165
170
|
```
|
|
166
171
|
|
|
167
172
|
```swift
|
|
@@ -193,6 +198,10 @@ for event in try sunEvents(from: today, to: tomorrow, observer: observer) {
|
|
|
193
198
|
// Betelgeuse from its J2000 catalog position: az/alt in degrees, refracted.
|
|
194
199
|
let star = try starAltAz(raDeg: 88.792939, decDeg: 7.407064, at: today, observer: observer)
|
|
195
200
|
|
|
201
|
+
// Its apparent place and Greenwich hour angle for sight reduction, in degrees.
|
|
202
|
+
let place = try starPosition(raDeg: 88.792939, decDeg: 7.407064, at: today)
|
|
203
|
+
let ghaDeg = (try greenwichSiderealTime(today) - place.raDeg + 360).truncatingRemainder(dividingBy: 360)
|
|
204
|
+
|
|
196
205
|
// The year's equinoxes and solstices, the Moon's perigees and apogees with
|
|
197
206
|
// distances, and the equation of time in minutes.
|
|
198
207
|
let year = today.addingTimeInterval(366 * 24 * 60 * 60)
|
|
@@ -204,7 +213,7 @@ print(try equationOfTime(today)) // sundial minus clock, minutes
|
|
|
204
213
|
|
|
205
214
|
### Kotlin/JVM and Android
|
|
206
215
|
|
|
207
|
-
The Kotlin library provides the same
|
|
216
|
+
The Kotlin library provides the same functions and result fields, using `java.time.Instant` and immutable data classes. It targets JVM 8 and Android minSdk 26, builds with JDK 17, and has no runtime dependencies beyond the Kotlin standard library and platform APIs. Maven publication and a Kotlin benchmark runner are deferred; consume the source at a reviewed Git SHA as described in [`kotlin/README.md`](kotlin/README.md).
|
|
208
217
|
|
|
209
218
|
```kotlin
|
|
210
219
|
import io.openwaters.almanac.*
|
package/dist/index.d.ts
CHANGED
|
@@ -4,14 +4,14 @@ export type { HeliocentricPosition, PlanetPosition, PlanetIllumination } from '.
|
|
|
4
4
|
export { planetHeliocentricPosition, planetPosition, planetAltAz, planetIllumination } from './planets.js';
|
|
5
5
|
export { horizonDip } from './horizon.js';
|
|
6
6
|
export { AlmanacOutOfRangeError } from './types.js';
|
|
7
|
-
export type { SunPosition, MoonPosition } from './positions.js';
|
|
8
|
-
export { sunPosition, moonPosition, equationOfTime } from './positions.js';
|
|
7
|
+
export type { SunPosition, MoonPosition, StarPosition } from './positions.js';
|
|
8
|
+
export { sunPosition, moonPosition, starPosition, equationOfTime } from './positions.js';
|
|
9
9
|
export type { SeasonKind, SeasonEvent } from './seasons.js';
|
|
10
10
|
export { seasons } from './seasons.js';
|
|
11
11
|
export type { MoonApsisKind, MoonApsis } from './apsides.js';
|
|
12
12
|
export { moonApsides } from './apsides.js';
|
|
13
13
|
export type { AltAz } from './transforms.js';
|
|
14
|
-
export { sunAltAz, moonAltAz, starAltAz } from './transforms.js';
|
|
14
|
+
export { sunAltAz, moonAltAz, starAltAz, greenwichSiderealTime } from './transforms.js';
|
|
15
15
|
export type { MoonIllumination, MoonOrientation } from './illumination.js';
|
|
16
16
|
export { moonIllumination, moonOrientation } from './illumination.js';
|
|
17
17
|
export type { SunEvent, SunEventKind, MoonEvent, MoonEventKind, MoonPhaseEvent, MoonPhaseName, PlanetEvent, PlanetEventKind, AltitudeEvent, AltitudeEventKind, TransitEvent, TransitEventKind } from './events.js';
|
package/dist/index.js
CHANGED
|
@@ -3,10 +3,10 @@ export { degreesToRadians, radiansToDegrees } from './angles.js';
|
|
|
3
3
|
export { planetHeliocentricPosition, planetPosition, planetAltAz, planetIllumination } from './planets.js';
|
|
4
4
|
export { horizonDip } from './horizon.js';
|
|
5
5
|
export { AlmanacOutOfRangeError } from './types.js';
|
|
6
|
-
export { sunPosition, moonPosition, equationOfTime } from './positions.js';
|
|
6
|
+
export { sunPosition, moonPosition, starPosition, equationOfTime } from './positions.js';
|
|
7
7
|
export { seasons } from './seasons.js';
|
|
8
8
|
export { moonApsides } from './apsides.js';
|
|
9
|
-
export { sunAltAz, moonAltAz, starAltAz } from './transforms.js';
|
|
9
|
+
export { sunAltAz, moonAltAz, starAltAz, greenwichSiderealTime } from './transforms.js';
|
|
10
10
|
export { moonIllumination, moonOrientation } from './illumination.js';
|
|
11
11
|
export { sunIsUp, sunEvents, moonEvents, searchMoonPhases, planetEvents, sunAltitudeEvents, sunTransits, moonTransits } from './events.js';
|
|
12
12
|
export { nextLunarEclipse, previousLunarEclipse, lunarEclipses, lunarEclipseVisibility } from './eclipse.js';
|
package/dist/nutation.d.ts
CHANGED
|
@@ -34,6 +34,12 @@ export declare enum PrecessDirection {
|
|
|
34
34
|
}
|
|
35
35
|
/** UPSTREAM: `Frac`, astronomy.ts line 235. */
|
|
36
36
|
export declare function frac(x: number): number;
|
|
37
|
+
/**
|
|
38
|
+
* Not upstream: an angle wrapped into [0, 360). Upstream adds 360 to a
|
|
39
|
+
* negative remainder, and a remainder within an ulp below zero then rounds
|
|
40
|
+
* to 360 itself.
|
|
41
|
+
*/
|
|
42
|
+
export declare function wrapDeg360(deg: number): number;
|
|
37
43
|
/** UPSTREAM: `mean_obliq`, astronomy.ts lines 1437-1447. Degrees. */
|
|
38
44
|
export declare function meanObliquityDeg(tt: number): number;
|
|
39
45
|
/** UPSTREAM: `EarthTiltInfo`, astronomy.ts lines 1449-1457. dpsi/deps arcsec, mobl/tobl degrees. */
|
package/dist/nutation.js
CHANGED
|
@@ -37,6 +37,19 @@ export var PrecessDirection;
|
|
|
37
37
|
export function frac(x) {
|
|
38
38
|
return x - Math.floor(x);
|
|
39
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Not upstream: an angle wrapped into [0, 360). Upstream adds 360 to a
|
|
42
|
+
* negative remainder, and a remainder within an ulp below zero then rounds
|
|
43
|
+
* to 360 itself.
|
|
44
|
+
*/
|
|
45
|
+
export function wrapDeg360(deg) {
|
|
46
|
+
let r = deg % 360;
|
|
47
|
+
if (r < 0)
|
|
48
|
+
r += 360;
|
|
49
|
+
if (r >= 360)
|
|
50
|
+
r -= 360;
|
|
51
|
+
return r;
|
|
52
|
+
}
|
|
40
53
|
/**
|
|
41
54
|
* UPSTREAM: `iau2000b`, astronomy.ts lines 1392-1435. The IAU 2000B nutation
|
|
42
55
|
* series truncated to its five largest terms; returns arcseconds.
|
|
@@ -247,9 +260,7 @@ export function equatorialFromVector(pos) {
|
|
|
247
260
|
throw new Error('Indeterminate sky coordinates');
|
|
248
261
|
return { raDeg: 0, decDeg: (pos.z < 0) ? -90 : +90, distanceAu: dist };
|
|
249
262
|
}
|
|
250
|
-
|
|
251
|
-
if (raDeg < 0)
|
|
252
|
-
raDeg += 360;
|
|
263
|
+
const raDeg = wrapDeg360(RAD2DEG * Math.atan2(pos.y, pos.x));
|
|
253
264
|
const decDeg = RAD2DEG * Math.atan2(pos.z, Math.sqrt(xyproj));
|
|
254
265
|
return { raDeg, decDeg, distanceAu: dist };
|
|
255
266
|
}
|
package/dist/positions.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ export interface MoonPosition {
|
|
|
10
10
|
decDeg: number;
|
|
11
11
|
distanceKm: number;
|
|
12
12
|
}
|
|
13
|
+
/** Apparent geocentric position of a fixed star: equator of date, RA in [0, 360). */
|
|
14
|
+
export interface StarPosition {
|
|
15
|
+
raDeg: number;
|
|
16
|
+
decDeg: number;
|
|
17
|
+
}
|
|
13
18
|
/**
|
|
14
19
|
* INTERNAL: apparent Sun for a TT instant, expressed as days since the J2000
|
|
15
20
|
* epoch in Terrestrial Time. This is the entry point the TT-labeled position
|
|
@@ -32,6 +37,17 @@ export declare function sunPosition(time: Date): SunPosition;
|
|
|
32
37
|
* the Earth-Moon centre distance in kilometres.
|
|
33
38
|
*/
|
|
34
39
|
export declare function moonPosition(time: Date): MoonPosition;
|
|
40
|
+
/**
|
|
41
|
+
* Apparent geocentric position of a fixed star from its J2000 (ICRS) catalog
|
|
42
|
+
* right ascension and declination, both in degrees — right ascension and
|
|
43
|
+
* declination on the true equator and equinox of date, with annual
|
|
44
|
+
* aberration, precession and nutation applied. Proper motion and stellar
|
|
45
|
+
* parallax are not applied.
|
|
46
|
+
*
|
|
47
|
+
* UPSTREAM: `Equator(star, date, observer, ofdate=true, aberration=true)`
|
|
48
|
+
* (astronomy.ts ~2803) with the geocentric observer term dropped.
|
|
49
|
+
*/
|
|
50
|
+
export declare function starPosition(raDeg: number, decDeg: number, time: Date): StarPosition;
|
|
35
51
|
/**
|
|
36
52
|
* INTERNAL: equation of time for a TT instant, in minutes. Not from upstream:
|
|
37
53
|
* Meeus, *Astronomical Algorithms*, formula 28.1, `E = L0 − 0.0057183° − α +
|
package/dist/positions.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
// L1 public positions: apparent geocentric Sun and
|
|
2
|
-
// equinox of date.
|
|
1
|
+
// L1 public positions: apparent geocentric Sun, Moon and fixed stars on the true
|
|
2
|
+
// equator and equinox of date.
|
|
3
3
|
//
|
|
4
4
|
// The composition chain mirrors the cosinekitty/astronomy upstream (pinned sha
|
|
5
5
|
// 865d3da7d8112bbc7911238052c6af4aaf877181):
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
// parallax subtraction) is zero and drops out.
|
|
14
14
|
import { assertSupported } from './types.js';
|
|
15
15
|
import { ttDays } from './time.js';
|
|
16
|
-
import { DEG2RAD, KM_PER_AU, earthTilt, equatorialFromVector } from './nutation.js';
|
|
16
|
+
import { DEG2RAD, KM_PER_AU, PrecessDirection, earthTilt, equatorialFromVector, gyration } from './nutation.js';
|
|
17
17
|
import { moonGeoVector } from './moon.js';
|
|
18
18
|
import { sunGeoVector } from './sun.js';
|
|
19
|
+
import { assertStarCatalog, starGeoVectorEqj } from './transforms.js';
|
|
19
20
|
/**
|
|
20
21
|
* INTERNAL: apparent Sun for a TT instant, expressed as days since the J2000
|
|
21
22
|
* epoch in Terrestrial Time. This is the entry point the TT-labeled position
|
|
@@ -50,6 +51,23 @@ export function moonPosition(time) {
|
|
|
50
51
|
assertSupported(time);
|
|
51
52
|
return moonApparentAtTT(ttDays(time));
|
|
52
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Apparent geocentric position of a fixed star from its J2000 (ICRS) catalog
|
|
56
|
+
* right ascension and declination, both in degrees — right ascension and
|
|
57
|
+
* declination on the true equator and equinox of date, with annual
|
|
58
|
+
* aberration, precession and nutation applied. Proper motion and stellar
|
|
59
|
+
* parallax are not applied.
|
|
60
|
+
*
|
|
61
|
+
* UPSTREAM: `Equator(star, date, observer, ofdate=true, aberration=true)`
|
|
62
|
+
* (astronomy.ts ~2803) with the geocentric observer term dropped.
|
|
63
|
+
*/
|
|
64
|
+
export function starPosition(raDeg, decDeg, time) {
|
|
65
|
+
assertSupported(time);
|
|
66
|
+
assertStarCatalog(raDeg, decDeg);
|
|
67
|
+
const tt = ttDays(time);
|
|
68
|
+
const { raDeg: ra, decDeg: dec } = equatorialFromVector(gyration(starGeoVectorEqj(raDeg, decDeg, tt), tt, PrecessDirection.From2000));
|
|
69
|
+
return { raDeg: ra, decDeg: dec };
|
|
70
|
+
}
|
|
53
71
|
/**
|
|
54
72
|
* INTERNAL: equation of time for a TT instant, in minutes. Not from upstream:
|
|
55
73
|
* Meeus, *Astronomical Algorithms*, formula 28.1, `E = L0 − 0.0057183° − α +
|
package/dist/sun.d.ts
CHANGED
|
@@ -17,6 +17,18 @@ export declare function earthHelioDistance(tt: number): number;
|
|
|
17
17
|
* `vsop.Earth` — i.e. `HelioVector(Body.Earth, time)`. J2000 mean equator (EQJ).
|
|
18
18
|
*/
|
|
19
19
|
export declare function earthHelioVector(tt: number): Vec3;
|
|
20
|
+
/** Heliocentric position in AU and velocity in AU per day, J2000 mean equator (EQJ). */
|
|
21
|
+
export interface HelioState {
|
|
22
|
+
pos: Vec3;
|
|
23
|
+
vel: Vec3;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* UPSTREAM: `CalcVsopPosVel`, astronomy.ts lines 3264-3314, specialised to
|
|
27
|
+
* `vsop.Earth` — i.e. `HelioState(Body.Earth, time)`. Not upstream: a
|
|
28
|
+
* one-entry cache on the exact instant, because a star catalog drawn for one
|
|
29
|
+
* moment asks for the same Earth state once per star.
|
|
30
|
+
*/
|
|
31
|
+
export declare function earthHelioState(tt: number): HelioState;
|
|
20
32
|
/**
|
|
21
33
|
* UPSTREAM: `CorrectLightTravel` (astronomy.ts 4170-4191) driving
|
|
22
34
|
* `BodyPosition.Position` (4193-4241) with observerBody = Earth,
|
package/dist/sun.js
CHANGED
|
@@ -237,6 +237,75 @@ export function earthHelioVector(tt) {
|
|
|
237
237
|
const eclip = vsopSphereToRect(lon, lat, rad);
|
|
238
238
|
return vsopRotate(eclip);
|
|
239
239
|
}
|
|
240
|
+
/**
|
|
241
|
+
* UPSTREAM: `VsopDeriv`, astronomy.ts lines 3207-3227 — the time derivative
|
|
242
|
+
* of a VSOP series, per millennium. It loops over the table rather than
|
|
243
|
+
* unrolling like `earthLon`: only the star path needs it, once per call.
|
|
244
|
+
*/
|
|
245
|
+
function vsopDeriv(formula, t) {
|
|
246
|
+
let tpower = 1; // t^s
|
|
247
|
+
let dpower = 0; // t^(s-1)
|
|
248
|
+
let deriv = 0;
|
|
249
|
+
let s = 0;
|
|
250
|
+
for (const series of formula) {
|
|
251
|
+
let sin_sum = 0;
|
|
252
|
+
let cos_sum = 0;
|
|
253
|
+
for (const [ampl, phas, freq] of series) {
|
|
254
|
+
const angle = phas + (t * freq);
|
|
255
|
+
sin_sum += ampl * freq * Math.sin(angle);
|
|
256
|
+
if (s > 0)
|
|
257
|
+
cos_sum += ampl * Math.cos(angle);
|
|
258
|
+
}
|
|
259
|
+
deriv += (s * dpower * cos_sum) - (tpower * sin_sum);
|
|
260
|
+
dpower = tpower;
|
|
261
|
+
tpower *= t;
|
|
262
|
+
++s;
|
|
263
|
+
}
|
|
264
|
+
return deriv;
|
|
265
|
+
}
|
|
266
|
+
let cacheEarthState;
|
|
267
|
+
let cacheEarthStateTt = NaN;
|
|
268
|
+
/**
|
|
269
|
+
* UPSTREAM: `CalcVsopPosVel`, astronomy.ts lines 3264-3314, specialised to
|
|
270
|
+
* `vsop.Earth` — i.e. `HelioState(Body.Earth, time)`. Not upstream: a
|
|
271
|
+
* one-entry cache on the exact instant, because a star catalog drawn for one
|
|
272
|
+
* moment asks for the same Earth state once per star.
|
|
273
|
+
*/
|
|
274
|
+
export function earthHelioState(tt) {
|
|
275
|
+
if (!cacheEarthState || cacheEarthStateTt !== tt) {
|
|
276
|
+
cacheEarthState = computeEarthHelioState(tt);
|
|
277
|
+
cacheEarthStateTt = tt;
|
|
278
|
+
}
|
|
279
|
+
return cacheEarthState;
|
|
280
|
+
}
|
|
281
|
+
function computeEarthHelioState(tt) {
|
|
282
|
+
const t = tt / DAYS_PER_MILLENNIUM;
|
|
283
|
+
const lon = earthLon(t);
|
|
284
|
+
const lat = earthLat(t);
|
|
285
|
+
const rad = earthRad(t);
|
|
286
|
+
const dlon_dt = vsopDeriv(vsopEarth[0], t);
|
|
287
|
+
const dlat_dt = vsopDeriv(vsopEarth[1], t);
|
|
288
|
+
const drad_dt = vsopDeriv(vsopEarth[2], t);
|
|
289
|
+
const coslon = Math.cos(lon);
|
|
290
|
+
const sinlon = Math.sin(lon);
|
|
291
|
+
const coslat = Math.cos(lat);
|
|
292
|
+
const sinlat = Math.sin(lat);
|
|
293
|
+
const vx = (+(drad_dt * coslat * coslon)
|
|
294
|
+
- (rad * sinlat * coslon * dlat_dt)
|
|
295
|
+
- (rad * coslat * sinlon * dlon_dt));
|
|
296
|
+
const vy = (+(drad_dt * coslat * sinlon)
|
|
297
|
+
- (rad * sinlat * sinlon * dlat_dt)
|
|
298
|
+
+ (rad * coslat * coslon * dlon_dt));
|
|
299
|
+
const vz = (+(drad_dt * sinlat)
|
|
300
|
+
+ (rad * coslat * dlat_dt));
|
|
301
|
+
// AU per millennium to AU per day.
|
|
302
|
+
const eclipVel = {
|
|
303
|
+
x: vx / DAYS_PER_MILLENNIUM,
|
|
304
|
+
y: vy / DAYS_PER_MILLENNIUM,
|
|
305
|
+
z: vz / DAYS_PER_MILLENNIUM
|
|
306
|
+
};
|
|
307
|
+
return { pos: vsopRotate(vsopSphereToRect(lon, lat, rad)), vel: vsopRotate(eclipVel) };
|
|
308
|
+
}
|
|
240
309
|
/**
|
|
241
310
|
* UPSTREAM: `CorrectLightTravel` (astronomy.ts 4170-4191) driving
|
|
242
311
|
* `BodyPosition.Position` (4193-4241) with observerBody = Earth,
|
package/dist/transforms.d.ts
CHANGED
|
@@ -72,15 +72,35 @@ export declare function sunAltAz(time: Date, observer: Observer): AltAz;
|
|
|
72
72
|
* refraction (upstream `'normal'` model) both applied.
|
|
73
73
|
*/
|
|
74
74
|
export declare function moonAltAz(time: Date, observer: Observer): AltAz;
|
|
75
|
+
/** INTERNAL: shared argument checks for the J2000 catalog position the star functions take. */
|
|
76
|
+
export declare function assertStarCatalog(raDeg: number, decDeg: number): void;
|
|
77
|
+
/**
|
|
78
|
+
* UPSTREAM: `GeoVector` for a `DefineStar` body with aberration = true —
|
|
79
|
+
* `HelioVector`'s `VectorFromSphere(Spherical(dec, 15*ra, dist))`
|
|
80
|
+
* (astronomy.ts ~4097, 7015) through the user-defined-star branch of
|
|
81
|
+
* `BackdatePosition` (4270-4300). The star is not backdated; the vector from
|
|
82
|
+
* Earth to the star is shifted by Earth's heliocentric velocity over the
|
|
83
|
+
* light travel time, which is the annual aberration, at most 20.5″.
|
|
84
|
+
*
|
|
85
|
+
* @returns geocentric position in AU, J2000 mean equator (EQJ).
|
|
86
|
+
*/
|
|
87
|
+
export declare function starGeoVectorEqj(raDeg: number, decDeg: number, tt: number): Vec3;
|
|
75
88
|
/**
|
|
76
89
|
* Topocentric azimuth/altitude of a fixed star from its J2000 (ICRS)
|
|
77
90
|
* catalog right ascension and declination, both in degrees.
|
|
78
91
|
*
|
|
79
|
-
* Applied: precession and nutation to the equator of
|
|
80
|
-
* apparent sidereal time, and atmospheric refraction
|
|
81
|
-
* model, the same as sunAltAz/moonAltAz). Not applied:
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
92
|
+
* Applied: annual aberration, precession and nutation to the equator of
|
|
93
|
+
* date, Greenwich apparent sidereal time, and atmospheric refraction
|
|
94
|
+
* (upstream `'normal'` model, the same as sunAltAz/moonAltAz). Not applied:
|
|
95
|
+
* proper motion (pass catalog coordinates; fast movers such as Arcturus
|
|
96
|
+
* drift ~1′ in 26 years) and stellar parallax (negligible at the 1000 ly the
|
|
97
|
+
* star is placed at).
|
|
85
98
|
*/
|
|
86
99
|
export declare function starAltAz(raDeg: number, decDeg: number, time: Date, observer: Observer): AltAz;
|
|
100
|
+
/**
|
|
101
|
+
* Greenwich apparent sidereal time in degrees, [0, 360): the hour angle of
|
|
102
|
+
* the true equinox of date at Greenwich, including the equation of the
|
|
103
|
+
* equinoxes. A body's Greenwich hour angle is this minus its right ascension
|
|
104
|
+
* of date.
|
|
105
|
+
*/
|
|
106
|
+
export declare function greenwichSiderealTime(time: Date): number;
|
package/dist/transforms.js
CHANGED
|
@@ -13,20 +13,17 @@
|
|
|
13
13
|
// refinement since this layer only needs az/alt; Refraction 'normal' (~7176).
|
|
14
14
|
//
|
|
15
15
|
// INTERNAL: not part of the curated public API (see index.ts) except
|
|
16
|
-
// sunAltAz
|
|
16
|
+
// sunAltAz, moonAltAz, starAltAz and greenwichSiderealTime.
|
|
17
17
|
import { assertObserver, assertSupported } from './types.js';
|
|
18
18
|
import { ttDaysFromUt, utDays } from './time.js';
|
|
19
|
-
import { DEG2RAD, RAD2DEG, EARTH_EQUATORIAL_RADIUS_KM, EARTH_FLATTENING, EARTH_FLATTENING_SQUARED, KM_PER_AU, PrecessDirection, earthTilt, equatorialFromVector, gyration } from './nutation.js';
|
|
20
|
-
import { sunGeoVectorEqj } from './sun.js';
|
|
19
|
+
import { C_AUDAY, DEG2RAD, RAD2DEG, EARTH_EQUATORIAL_RADIUS_KM, EARTH_FLATTENING, EARTH_FLATTENING_SQUARED, KM_PER_AU, PrecessDirection, earthTilt, equatorialFromVector, gyration, wrapDeg360 } from './nutation.js';
|
|
20
|
+
import { earthHelioState, sunGeoVectorEqj } from './sun.js';
|
|
21
21
|
import { moonGeoVectorEqj } from './moon.js';
|
|
22
22
|
/** UPSTREAM: `era` (Earth Rotation Angle), astronomy.ts ~2014. */
|
|
23
23
|
function earthRotationAngleDeg(ut) {
|
|
24
24
|
const thet1 = 0.7790572732640 + 0.00273781191135448 * ut;
|
|
25
25
|
const thet3 = ut % 1;
|
|
26
|
-
|
|
27
|
-
if (theta < 0)
|
|
28
|
-
theta += 360;
|
|
29
|
-
return theta;
|
|
26
|
+
return wrapDeg360(360 * ((thet1 + thet3) % 1));
|
|
30
27
|
}
|
|
31
28
|
/**
|
|
32
29
|
* UPSTREAM: `sidereal_time`, astronomy.ts ~2031 — Greenwich Apparent Sidereal
|
|
@@ -46,10 +43,7 @@ export function siderealDeg(ut) {
|
|
|
46
43
|
- 0.00000044) * t
|
|
47
44
|
+ 1.3915817) * t
|
|
48
45
|
+ 4612.156534) * t;
|
|
49
|
-
|
|
50
|
-
if (gastDeg < 0)
|
|
51
|
-
gastDeg += 360;
|
|
52
|
-
return gastDeg;
|
|
46
|
+
return wrapDeg360(st / 3600 + theta);
|
|
53
47
|
}
|
|
54
48
|
/**
|
|
55
49
|
* UPSTREAM: `terra` (astronomy.ts ~2147 — position only; its velocity output
|
|
@@ -149,17 +143,13 @@ export function topoAltAzUnrefracted(bodyEqj, ut, observer) {
|
|
|
149
143
|
const proj = Math.hypot(pn, pw);
|
|
150
144
|
let az;
|
|
151
145
|
if (proj > 0) {
|
|
152
|
-
az = -RAD2DEG * Math.atan2(pw, pn);
|
|
153
|
-
if (az < 0)
|
|
154
|
-
az += 360;
|
|
146
|
+
az = wrapDeg360(-RAD2DEG * Math.atan2(pw, pn));
|
|
155
147
|
}
|
|
156
148
|
else {
|
|
157
149
|
az = 0;
|
|
158
150
|
}
|
|
159
151
|
const zd = RAD2DEG * Math.atan2(proj, pz);
|
|
160
|
-
|
|
161
|
-
if (hourAngleDeg < 0)
|
|
162
|
-
hourAngleDeg += 360;
|
|
152
|
+
const hourAngleDeg = wrapDeg360(gast + observer.longitudeDeg - raDeg);
|
|
163
153
|
return { azDeg: az, altDeg: 90 - zd, hourAngleDeg, distanceAu, raDeg, decDeg };
|
|
164
154
|
}
|
|
165
155
|
/**
|
|
@@ -208,40 +198,64 @@ export function moonAltAz(time, observer) {
|
|
|
208
198
|
return refract(topoAltAzUnrefracted(moonGeoVectorEqj(ttDaysFromUt(ut)), ut, observer));
|
|
209
199
|
}
|
|
210
200
|
/**
|
|
211
|
-
* UPSTREAM: the user-defined star path — `HelioVector` for a `DefineStar`
|
|
212
|
-
* body (astronomy.ts ~4097: `VectorFromSphere(Spherical(dec, 15*ra, dist))`)
|
|
213
|
-
* into `Equator(body, date, observer, ofdate=true, aberration=false)` (~2803)
|
|
214
|
-
* and `Horizon` (~2565): the same topocentric path sunAltAz/moonAltAz take.
|
|
215
201
|
* Upstream floors a star's distance at 1 light-year and suggests 1000 when
|
|
216
202
|
* unknown; the star sits at 1000 ly here (`AU_PER_LY`, astronomy.ts line 52).
|
|
217
|
-
* Upstream's geocentric step (star vector minus Earth's heliocentric
|
|
218
|
-
* position) is skipped: at 1000 ly it moves the star 0.003″.
|
|
219
203
|
*/
|
|
220
204
|
const STAR_DISTANCE_AU = 1000 * 63241.07708807546;
|
|
221
|
-
/**
|
|
222
|
-
|
|
223
|
-
* catalog right ascension and declination, both in degrees.
|
|
224
|
-
*
|
|
225
|
-
* Applied: precession and nutation to the equator of date, Greenwich
|
|
226
|
-
* apparent sidereal time, and atmospheric refraction (upstream `'normal'`
|
|
227
|
-
* model, the same as sunAltAz/moonAltAz). Not applied: annual aberration
|
|
228
|
-
* (at most 20.5″ — see the roadmap), proper motion (pass catalog
|
|
229
|
-
* coordinates; fast movers such as Arcturus drift ~1′ in 26 years), and
|
|
230
|
-
* stellar parallax (negligible at the 1000 ly the star is placed at).
|
|
231
|
-
*/
|
|
232
|
-
export function starAltAz(raDeg, decDeg, time, observer) {
|
|
233
|
-
assertSupported(time);
|
|
234
|
-
assertObserver(observer);
|
|
205
|
+
/** INTERNAL: shared argument checks for the J2000 catalog position the star functions take. */
|
|
206
|
+
export function assertStarCatalog(raDeg, decDeg) {
|
|
235
207
|
if (!(raDeg >= 0 && raDeg < 360))
|
|
236
208
|
throw new RangeError(`raDeg out of range: ${raDeg}`);
|
|
237
209
|
if (!(decDeg >= -90 && decDeg <= 90))
|
|
238
210
|
throw new RangeError(`decDeg out of range: ${decDeg}`);
|
|
239
|
-
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* UPSTREAM: `GeoVector` for a `DefineStar` body with aberration = true —
|
|
214
|
+
* `HelioVector`'s `VectorFromSphere(Spherical(dec, 15*ra, dist))`
|
|
215
|
+
* (astronomy.ts ~4097, 7015) through the user-defined-star branch of
|
|
216
|
+
* `BackdatePosition` (4270-4300). The star is not backdated; the vector from
|
|
217
|
+
* Earth to the star is shifted by Earth's heliocentric velocity over the
|
|
218
|
+
* light travel time, which is the annual aberration, at most 20.5″.
|
|
219
|
+
*
|
|
220
|
+
* @returns geocentric position in AU, J2000 mean equator (EQJ).
|
|
221
|
+
*/
|
|
222
|
+
export function starGeoVectorEqj(raDeg, decDeg, tt) {
|
|
240
223
|
const rCosDec = STAR_DISTANCE_AU * Math.cos(decDeg * DEG2RAD);
|
|
241
|
-
const
|
|
224
|
+
const tvec = {
|
|
242
225
|
x: rCosDec * Math.cos(raDeg * DEG2RAD),
|
|
243
226
|
y: rCosDec * Math.sin(raDeg * DEG2RAD),
|
|
244
227
|
z: STAR_DISTANCE_AU * Math.sin(decDeg * DEG2RAD),
|
|
245
228
|
};
|
|
246
|
-
|
|
229
|
+
const ostate = earthHelioState(tt);
|
|
230
|
+
const rvec = { x: tvec.x - ostate.pos.x, y: tvec.y - ostate.pos.y, z: tvec.z - ostate.pos.z };
|
|
231
|
+
const s = C_AUDAY / Math.sqrt(rvec.x * rvec.x + rvec.y * rvec.y + rvec.z * rvec.z);
|
|
232
|
+
return { x: rvec.x + ostate.vel.x / s, y: rvec.y + ostate.vel.y / s, z: rvec.z + ostate.vel.z / s };
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Topocentric azimuth/altitude of a fixed star from its J2000 (ICRS)
|
|
236
|
+
* catalog right ascension and declination, both in degrees.
|
|
237
|
+
*
|
|
238
|
+
* Applied: annual aberration, precession and nutation to the equator of
|
|
239
|
+
* date, Greenwich apparent sidereal time, and atmospheric refraction
|
|
240
|
+
* (upstream `'normal'` model, the same as sunAltAz/moonAltAz). Not applied:
|
|
241
|
+
* proper motion (pass catalog coordinates; fast movers such as Arcturus
|
|
242
|
+
* drift ~1′ in 26 years) and stellar parallax (negligible at the 1000 ly the
|
|
243
|
+
* star is placed at).
|
|
244
|
+
*/
|
|
245
|
+
export function starAltAz(raDeg, decDeg, time, observer) {
|
|
246
|
+
assertSupported(time);
|
|
247
|
+
assertObserver(observer);
|
|
248
|
+
assertStarCatalog(raDeg, decDeg);
|
|
249
|
+
const ut = utDays(time);
|
|
250
|
+
return refract(topoAltAzUnrefracted(starGeoVectorEqj(raDeg, decDeg, ttDaysFromUt(ut)), ut, observer));
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Greenwich apparent sidereal time in degrees, [0, 360): the hour angle of
|
|
254
|
+
* the true equinox of date at Greenwich, including the equation of the
|
|
255
|
+
* equinoxes. A body's Greenwich hour angle is this minus its right ascension
|
|
256
|
+
* of date.
|
|
257
|
+
*/
|
|
258
|
+
export function greenwichSiderealTime(time) {
|
|
259
|
+
assertSupported(time);
|
|
260
|
+
return siderealDeg(utDays(time));
|
|
247
261
|
}
|