@openwaters/almanac 0.0.0-bootstrap
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/LICENSE +21 -0
- package/NOTICE +32 -0
- package/README.md +75 -0
- package/dist/eclipse.d.ts +66 -0
- package/dist/eclipse.js +295 -0
- package/dist/events.d.ts +81 -0
- package/dist/events.js +492 -0
- package/dist/illumination.d.ts +32 -0
- package/dist/illumination.js +88 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +6 -0
- package/dist/moon.d.ts +38 -0
- package/dist/moon.js +310 -0
- package/dist/nutation.d.ts +65 -0
- package/dist/nutation.js +255 -0
- package/dist/positions.d.ts +34 -0
- package/dist/positions.js +52 -0
- package/dist/sun.d.ts +27 -0
- package/dist/sun.js +184 -0
- package/dist/time.d.ts +28 -0
- package/dist/time.js +144 -0
- package/dist/transforms.d.ts +61 -0
- package/dist/transforms.js +198 -0
- package/dist/types.d.ts +16 -0
- package/dist/types.js +31 -0
- package/package.json +34 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// L1 public positions: apparent geocentric Sun and Moon on the true equator and
|
|
2
|
+
// equinox of date.
|
|
3
|
+
//
|
|
4
|
+
// The composition chain mirrors the cosinekitty/astronomy upstream (pinned sha
|
|
5
|
+
// 865d3da7d8112bbc7911238052c6af4aaf877181):
|
|
6
|
+
// Sun: GeoVector(Body.Sun, t, aberration=true) -> BackdatePosition ->
|
|
7
|
+
// CorrectLightTravel over -HelioVector(Earth), then
|
|
8
|
+
// Equator(ofdate=true) -> gyration(From2000) -> vector2radec.
|
|
9
|
+
// Moon: GeoVector(Body.Moon, t) -> GeoMoon (MOON2, ecliptic of date ->
|
|
10
|
+
// mean equator of date -> J2000), then the same
|
|
11
|
+
// Equator(ofdate=true) gyration and vector2radec.
|
|
12
|
+
// Both are geocentric, so upstream's `gc_observer` term (Equator's topocentric
|
|
13
|
+
// parallax subtraction) is zero and drops out.
|
|
14
|
+
import { assertSupported } from './types.js';
|
|
15
|
+
import { ttDays } from './time.js';
|
|
16
|
+
import { KM_PER_AU, equatorialFromVector } from './nutation.js';
|
|
17
|
+
import { moonGeoVector } from './moon.js';
|
|
18
|
+
import { sunGeoVector } from './sun.js';
|
|
19
|
+
/**
|
|
20
|
+
* INTERNAL: apparent Sun for a TT instant, expressed as days since the J2000
|
|
21
|
+
* epoch in Terrestrial Time. This is the entry point the TT-labeled position
|
|
22
|
+
* fixtures compare against — going through `sunPosition` would first convert
|
|
23
|
+
* UTC → TT with a ΔT model, putting a timescale approximation between the
|
|
24
|
+
* ephemeris and the reference data.
|
|
25
|
+
*/
|
|
26
|
+
export function sunApparentAtTT(tt) {
|
|
27
|
+
const { raDeg, decDeg, distanceAu } = equatorialFromVector(sunGeoVector(tt));
|
|
28
|
+
return { raDeg, decDeg, distanceAu };
|
|
29
|
+
}
|
|
30
|
+
/** INTERNAL: apparent Moon for a TT instant. See {@link sunApparentAtTT}. */
|
|
31
|
+
export function moonApparentAtTT(tt) {
|
|
32
|
+
const { raDeg, decDeg, distanceAu } = equatorialFromVector(moonGeoVector(tt));
|
|
33
|
+
return { raDeg, decDeg, distanceKm: distanceAu * KM_PER_AU };
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Apparent geocentric position of the Sun — right ascension and declination on
|
|
37
|
+
* the true equator and equinox of date (precession, nutation and aberration
|
|
38
|
+
* applied), plus the light-time-corrected distance in AU.
|
|
39
|
+
*/
|
|
40
|
+
export function sunPosition(time) {
|
|
41
|
+
assertSupported(time);
|
|
42
|
+
return sunApparentAtTT(ttDays(time));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Apparent geocentric position of the Moon — right ascension and declination on
|
|
46
|
+
* the true equator and equinox of date (precession and nutation applied), plus
|
|
47
|
+
* the Earth-Moon centre distance in kilometres.
|
|
48
|
+
*/
|
|
49
|
+
export function moonPosition(time) {
|
|
50
|
+
assertSupported(time);
|
|
51
|
+
return moonApparentAtTT(ttDays(time));
|
|
52
|
+
}
|
package/dist/sun.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Vec3 } from './nutation.js';
|
|
2
|
+
/**
|
|
3
|
+
* UPSTREAM: `CalcVsop`, astronomy.ts lines 3255-3262, specialised to
|
|
4
|
+
* `vsop.Earth` — i.e. `HelioVector(Body.Earth, time)`. J2000 mean equator (EQJ).
|
|
5
|
+
*/
|
|
6
|
+
export declare function earthHelioVector(tt: number): Vec3;
|
|
7
|
+
/**
|
|
8
|
+
* UPSTREAM: `CorrectLightTravel` (astronomy.ts 4170-4191) driving
|
|
9
|
+
* `BodyPosition.Position` (4193-4241) with observerBody = Earth,
|
|
10
|
+
* targetBody = Sun, aberration = true — i.e. what
|
|
11
|
+
* `GeoVector(Body.Sun, time, true)` computes via `BackdatePosition`.
|
|
12
|
+
*
|
|
13
|
+
* `HelioVector(Body.Sun, t)` is the zero vector, so the target position is
|
|
14
|
+
* always the origin and the whole correction is the backdated Earth: the
|
|
15
|
+
* light-time retardation and the ~20.5" annual aberration fall out of the same
|
|
16
|
+
* iteration, exactly as upstream intends.
|
|
17
|
+
*
|
|
18
|
+
* @returns geocentric position in AU, J2000 mean equator (EQJ).
|
|
19
|
+
*/
|
|
20
|
+
export declare function sunGeoVectorEqj(tt: number): Vec3;
|
|
21
|
+
/**
|
|
22
|
+
* UPSTREAM: `GeoVector(Body.Sun, time, aberration=true)` composed with the
|
|
23
|
+
* `gyration(..., From2000)` of `Equator(ofdate=true)` (astronomy.ts 2803-2822).
|
|
24
|
+
*
|
|
25
|
+
* @returns geocentric position in AU, true equator & equinox of date.
|
|
26
|
+
*/
|
|
27
|
+
export declare function sunGeoVector(tt: number): Vec3;
|
package/dist/sun.js
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// L1 solar position: geocentric Sun from the truncated VSOP87 Earth series,
|
|
2
|
+
// with light-travel and aberration correction.
|
|
3
|
+
//
|
|
4
|
+
// Translated from the cosinekitty/astronomy upstream, pinned sha
|
|
5
|
+
// 865d3da7d8112bbc7911238052c6af4aaf877181, source/js/astronomy.ts. The
|
|
6
|
+
// `vsop.Earth` table below is copied verbatim from that file (lines 555-628);
|
|
7
|
+
// operation order is preserved so a Swift port agrees bit-for-bit.
|
|
8
|
+
//
|
|
9
|
+
// INTERNAL: not part of the curated public API (see index.ts).
|
|
10
|
+
import { C_AUDAY, PI2, PrecessDirection, gyration } from './nutation.js';
|
|
11
|
+
/** UPSTREAM: `vsop.Earth`, astronomy.ts lines 555-628 (longitude, latitude, radius). */
|
|
12
|
+
const vsopEarth = [
|
|
13
|
+
[
|
|
14
|
+
[
|
|
15
|
+
[1.75347045673, 0.00000000000, 0.00000000000],
|
|
16
|
+
[0.03341656453, 4.66925680415, 6283.07584999140],
|
|
17
|
+
[0.00034894275, 4.62610242189, 12566.15169998280],
|
|
18
|
+
[0.00003417572, 2.82886579754, 3.52311834900],
|
|
19
|
+
[0.00003497056, 2.74411783405, 5753.38488489680],
|
|
20
|
+
[0.00003135899, 3.62767041756, 77713.77146812050],
|
|
21
|
+
[0.00002676218, 4.41808345438, 7860.41939243920],
|
|
22
|
+
[0.00002342691, 6.13516214446, 3930.20969621960],
|
|
23
|
+
[0.00001273165, 2.03709657878, 529.69096509460],
|
|
24
|
+
[0.00001324294, 0.74246341673, 11506.76976979360],
|
|
25
|
+
[0.00000901854, 2.04505446477, 26.29831979980],
|
|
26
|
+
[0.00001199167, 1.10962946234, 1577.34354244780],
|
|
27
|
+
[0.00000857223, 3.50849152283, 398.14900340820],
|
|
28
|
+
[0.00000779786, 1.17882681962, 5223.69391980220],
|
|
29
|
+
[0.00000990250, 5.23268072088, 5884.92684658320],
|
|
30
|
+
[0.00000753141, 2.53339052847, 5507.55323866740],
|
|
31
|
+
[0.00000505267, 4.58292599973, 18849.22754997420],
|
|
32
|
+
[0.00000492392, 4.20505711826, 775.52261132400],
|
|
33
|
+
[0.00000356672, 2.91954114478, 0.06731030280],
|
|
34
|
+
[0.00000284125, 1.89869240932, 796.29800681640],
|
|
35
|
+
[0.00000242879, 0.34481445893, 5486.77784317500],
|
|
36
|
+
[0.00000317087, 5.84901948512, 11790.62908865880],
|
|
37
|
+
[0.00000271112, 0.31486255375, 10977.07880469900],
|
|
38
|
+
[0.00000206217, 4.80646631478, 2544.31441988340],
|
|
39
|
+
[0.00000205478, 1.86953770281, 5573.14280143310],
|
|
40
|
+
[0.00000202318, 2.45767790232, 6069.77675455340],
|
|
41
|
+
[0.00000126225, 1.08295459501, 20.77539549240],
|
|
42
|
+
[0.00000155516, 0.83306084617, 213.29909543800]
|
|
43
|
+
],
|
|
44
|
+
[
|
|
45
|
+
[6283.07584999140, 0.00000000000, 0.00000000000],
|
|
46
|
+
[0.00206058863, 2.67823455808, 6283.07584999140],
|
|
47
|
+
[0.00004303419, 2.63512233481, 12566.15169998280]
|
|
48
|
+
],
|
|
49
|
+
[
|
|
50
|
+
[0.00008721859, 1.07253635559, 6283.07584999140]
|
|
51
|
+
]
|
|
52
|
+
],
|
|
53
|
+
[
|
|
54
|
+
[],
|
|
55
|
+
[
|
|
56
|
+
[0.00227777722, 3.41376620530, 6283.07584999140],
|
|
57
|
+
[0.00003805678, 3.37063423795, 12566.15169998280]
|
|
58
|
+
]
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
[
|
|
62
|
+
[1.00013988784, 0.00000000000, 0.00000000000],
|
|
63
|
+
[0.01670699632, 3.09846350258, 6283.07584999140],
|
|
64
|
+
[0.00013956024, 3.05524609456, 12566.15169998280],
|
|
65
|
+
[0.00003083720, 5.19846674381, 77713.77146812050],
|
|
66
|
+
[0.00001628463, 1.17387558054, 5753.38488489680],
|
|
67
|
+
[0.00001575572, 2.84685214877, 7860.41939243920],
|
|
68
|
+
[0.00000924799, 5.45292236722, 11506.76976979360],
|
|
69
|
+
[0.00000542439, 4.56409151453, 3930.20969621960],
|
|
70
|
+
[0.00000472110, 3.66100022149, 5884.92684658320],
|
|
71
|
+
[0.00000085831, 1.27079125277, 161000.68573767410],
|
|
72
|
+
[0.00000057056, 2.01374292245, 83996.84731811189],
|
|
73
|
+
[0.00000055736, 5.24159799170, 71430.69561812909],
|
|
74
|
+
[0.00000174844, 3.01193636733, 18849.22754997420],
|
|
75
|
+
[0.00000243181, 4.27349530790, 11790.62908865880]
|
|
76
|
+
],
|
|
77
|
+
[
|
|
78
|
+
[0.00103018607, 1.10748968172, 6283.07584999140],
|
|
79
|
+
[0.00001721238, 1.06442300386, 12566.15169998280]
|
|
80
|
+
],
|
|
81
|
+
[
|
|
82
|
+
[0.00004359385, 5.78455133808, 6283.07584999140]
|
|
83
|
+
]
|
|
84
|
+
]
|
|
85
|
+
];
|
|
86
|
+
/** UPSTREAM: astronomy.ts lines 3229-3232. */
|
|
87
|
+
const DAYS_PER_MILLENNIUM = 365250;
|
|
88
|
+
const LON_INDEX = 0;
|
|
89
|
+
const LAT_INDEX = 1;
|
|
90
|
+
const RAD_INDEX = 2;
|
|
91
|
+
/** UPSTREAM: `VsopFormula`, astronomy.ts lines 3191-3205. */
|
|
92
|
+
function vsopFormula(formula, t, clamp_angle) {
|
|
93
|
+
let tpower = 1;
|
|
94
|
+
let coord = 0;
|
|
95
|
+
for (let series of formula) {
|
|
96
|
+
let sum = 0;
|
|
97
|
+
for (let [ampl, phas, freq] of series)
|
|
98
|
+
sum += ampl * Math.cos(phas + (t * freq));
|
|
99
|
+
let incr = tpower * sum;
|
|
100
|
+
if (clamp_angle)
|
|
101
|
+
incr %= PI2; // improve precision for longitudes: they can be hundreds of radians
|
|
102
|
+
coord += incr;
|
|
103
|
+
tpower *= t;
|
|
104
|
+
}
|
|
105
|
+
return coord;
|
|
106
|
+
}
|
|
107
|
+
/** UPSTREAM: `VsopRotate`, astronomy.ts lines 3234-3241 — VSOP ecliptic to J2000 equatorial. */
|
|
108
|
+
function vsopRotate(eclip) {
|
|
109
|
+
return {
|
|
110
|
+
x: eclip.x + 0.000000440360 * eclip.y - 0.000000190919 * eclip.z,
|
|
111
|
+
y: -0.000000479966 * eclip.x + 0.917482137087 * eclip.y - 0.397776982902 * eclip.z,
|
|
112
|
+
z: 0.397776982902 * eclip.y + 0.917482137087 * eclip.z
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/** UPSTREAM: `VsopSphereToRect`, astronomy.ts lines 3243-3253. */
|
|
116
|
+
function vsopSphereToRect(lon, lat, radius) {
|
|
117
|
+
// Convert spherical coordinates to ecliptic cartesian coordinates.
|
|
118
|
+
const r_coslat = radius * Math.cos(lat);
|
|
119
|
+
const coslon = Math.cos(lon);
|
|
120
|
+
const sinlon = Math.sin(lon);
|
|
121
|
+
return {
|
|
122
|
+
x: r_coslat * coslon,
|
|
123
|
+
y: r_coslat * sinlon,
|
|
124
|
+
z: radius * Math.sin(lat)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* UPSTREAM: `CalcVsop`, astronomy.ts lines 3255-3262, specialised to
|
|
129
|
+
* `vsop.Earth` — i.e. `HelioVector(Body.Earth, time)`. J2000 mean equator (EQJ).
|
|
130
|
+
*/
|
|
131
|
+
export function earthHelioVector(tt) {
|
|
132
|
+
const t = tt / DAYS_PER_MILLENNIUM; // millennia since 2000
|
|
133
|
+
const lon = vsopFormula(vsopEarth[LON_INDEX], t, true);
|
|
134
|
+
const lat = vsopFormula(vsopEarth[LAT_INDEX], t, false);
|
|
135
|
+
const rad = vsopFormula(vsopEarth[RAD_INDEX], t, false);
|
|
136
|
+
const eclip = vsopSphereToRect(lon, lat, rad);
|
|
137
|
+
return vsopRotate(eclip);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* UPSTREAM: `CorrectLightTravel` (astronomy.ts 4170-4191) driving
|
|
141
|
+
* `BodyPosition.Position` (4193-4241) with observerBody = Earth,
|
|
142
|
+
* targetBody = Sun, aberration = true — i.e. what
|
|
143
|
+
* `GeoVector(Body.Sun, time, true)` computes via `BackdatePosition`.
|
|
144
|
+
*
|
|
145
|
+
* `HelioVector(Body.Sun, t)` is the zero vector, so the target position is
|
|
146
|
+
* always the origin and the whole correction is the backdated Earth: the
|
|
147
|
+
* light-time retardation and the ~20.5" annual aberration fall out of the same
|
|
148
|
+
* iteration, exactly as upstream intends.
|
|
149
|
+
*
|
|
150
|
+
* @returns geocentric position in AU, J2000 mean equator (EQJ).
|
|
151
|
+
*/
|
|
152
|
+
export function sunGeoVectorEqj(tt) {
|
|
153
|
+
let ltime = tt;
|
|
154
|
+
let dt = 0;
|
|
155
|
+
for (let iter = 0; iter < 10; ++iter) {
|
|
156
|
+
// BodyPosition.Position: (0,0,0) - HelioVector(Earth, ltime).
|
|
157
|
+
const earth = earthHelioVector(ltime);
|
|
158
|
+
const pos = { x: -earth.x, y: -earth.y, z: -earth.z };
|
|
159
|
+
const lt = Math.sqrt(pos.x * pos.x + pos.y * pos.y + pos.z * pos.z) / C_AUDAY;
|
|
160
|
+
// This solver does not support more than one light-day of distance,
|
|
161
|
+
// because that would cause convergence problems and inaccurate
|
|
162
|
+
// values for stellar aberration angles.
|
|
163
|
+
if (lt > 1.0)
|
|
164
|
+
throw new Error('Object is too distant for light-travel solver.');
|
|
165
|
+
// Upstream backdates via `AstroTime.AddDays`, which subtracts from UT and
|
|
166
|
+
// recomputes TT; subtracting from TT directly is what that intends (upstream
|
|
167
|
+
// documents the UT detour as "slightly wrong" at AddDays, line 1329).
|
|
168
|
+
const ltime2 = tt - lt;
|
|
169
|
+
dt = Math.abs(ltime2 - ltime);
|
|
170
|
+
if (dt < 1.0e-9) // 86.4 microseconds
|
|
171
|
+
return pos;
|
|
172
|
+
ltime = ltime2;
|
|
173
|
+
}
|
|
174
|
+
throw new Error(`Light-travel time solver did not converge: dt = ${dt}`);
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* UPSTREAM: `GeoVector(Body.Sun, time, aberration=true)` composed with the
|
|
178
|
+
* `gyration(..., From2000)` of `Equator(ofdate=true)` (astronomy.ts 2803-2822).
|
|
179
|
+
*
|
|
180
|
+
* @returns geocentric position in AU, true equator & equinox of date.
|
|
181
|
+
*/
|
|
182
|
+
export function sunGeoVector(tt) {
|
|
183
|
+
return gyration(sunGeoVectorEqj(tt), tt, PrecessDirection.From2000);
|
|
184
|
+
}
|
package/dist/time.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** Days since J2000 (UT), fractional. */
|
|
2
|
+
export declare function utDays(d: Date): number;
|
|
3
|
+
/** Julian day (UT). */
|
|
4
|
+
export declare function julianDay(d: Date): number;
|
|
5
|
+
/**
|
|
6
|
+
* ΔT = TT − UT, in seconds, for a given decimal year.
|
|
7
|
+
*
|
|
8
|
+
* Translated from `DeltaT_EspenakMeeus` in the cosinekitty/astronomy upstream
|
|
9
|
+
* (pinned sha 865d3da7d8112bbc7911238052c6af4aaf877181,
|
|
10
|
+
* source/js/astronomy.ts, lines ~1098-1190). The upstream function converts a
|
|
11
|
+
* `ut` (days since J2000) argument to a decimal year `y` first; this port
|
|
12
|
+
* takes the decimal year directly (see ttDays' yearOf below for the caller's
|
|
13
|
+
* ut→year conversion) and translates the piecewise polynomial verbatim,
|
|
14
|
+
* coefficient-for-coefficient, including branches outside the 1950-2100
|
|
15
|
+
* interval this package supports.
|
|
16
|
+
*/
|
|
17
|
+
export declare function deltaTSeconds(decimalYear: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* Days since J2000 (TT) for a UT-days value already in hand — factored out of
|
|
20
|
+
* {@link ttDays} so L2 transforms that compute `ut` once (sidereal time,
|
|
21
|
+
* topocentric parallax) can derive `tt` from it without re-deriving the
|
|
22
|
+
* ut→year→ΔT conversion.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ttDaysFromUt(ut: number): number;
|
|
25
|
+
/** Days since J2000 (TT), fractional — the argument every translated function consumes. */
|
|
26
|
+
export declare function ttDays(d: Date): number;
|
|
27
|
+
/** Inverse of {@link utDays} — the instant, truncated to integer epoch ms (TimeClip). */
|
|
28
|
+
export declare function dateFromUt(ut: number): Date;
|
package/dist/time.js
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// L0 time layer: Julian day, ΔT (Espenak–Meeus), and TT — the foundation every
|
|
2
|
+
// later astronomy layer (sun/moon position, rise/set, phase) consumes via ttDays().
|
|
3
|
+
// INTERNAL: not part of the curated public API (see index.ts) — L1+ layers import
|
|
4
|
+
// directly from './time.js'.
|
|
5
|
+
const J2000_EPOCH_MS = Date.UTC(2000, 0, 1, 12); // 2000-01-01T12:00:00Z
|
|
6
|
+
/** Days since J2000 (UT), fractional. */
|
|
7
|
+
export function utDays(d) {
|
|
8
|
+
return (d.getTime() - J2000_EPOCH_MS) / 86400000;
|
|
9
|
+
}
|
|
10
|
+
/** Julian day (UT). */
|
|
11
|
+
export function julianDay(d) {
|
|
12
|
+
return utDays(d) + 2451545.0;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* ΔT = TT − UT, in seconds, for a given decimal year.
|
|
16
|
+
*
|
|
17
|
+
* Translated from `DeltaT_EspenakMeeus` in the cosinekitty/astronomy upstream
|
|
18
|
+
* (pinned sha 865d3da7d8112bbc7911238052c6af4aaf877181,
|
|
19
|
+
* source/js/astronomy.ts, lines ~1098-1190). The upstream function converts a
|
|
20
|
+
* `ut` (days since J2000) argument to a decimal year `y` first; this port
|
|
21
|
+
* takes the decimal year directly (see ttDays' yearOf below for the caller's
|
|
22
|
+
* ut→year conversion) and translates the piecewise polynomial verbatim,
|
|
23
|
+
* coefficient-for-coefficient, including branches outside the 1950-2100
|
|
24
|
+
* interval this package supports.
|
|
25
|
+
*/
|
|
26
|
+
export function deltaTSeconds(decimalYear) {
|
|
27
|
+
const y = decimalYear;
|
|
28
|
+
let u, u2, u3, u4, u5, u6, u7;
|
|
29
|
+
if (y < -500) {
|
|
30
|
+
u = (y - 1820) / 100;
|
|
31
|
+
return -20 + 32 * u * u;
|
|
32
|
+
}
|
|
33
|
+
if (y < 500) {
|
|
34
|
+
u = y / 100;
|
|
35
|
+
u2 = u * u;
|
|
36
|
+
u3 = u * u2;
|
|
37
|
+
u4 = u2 * u2;
|
|
38
|
+
u5 = u2 * u3;
|
|
39
|
+
u6 = u3 * u3;
|
|
40
|
+
return 10583.6 - 1014.41 * u + 33.78311 * u2 - 5.952053 * u3 - 0.1798452 * u4 + 0.022174192 * u5 + 0.0090316521 * u6;
|
|
41
|
+
}
|
|
42
|
+
if (y < 1600) {
|
|
43
|
+
u = (y - 1000) / 100;
|
|
44
|
+
u2 = u * u;
|
|
45
|
+
u3 = u * u2;
|
|
46
|
+
u4 = u2 * u2;
|
|
47
|
+
u5 = u2 * u3;
|
|
48
|
+
u6 = u3 * u3;
|
|
49
|
+
return 1574.2 - 556.01 * u + 71.23472 * u2 + 0.319781 * u3 - 0.8503463 * u4 - 0.005050998 * u5 + 0.0083572073 * u6;
|
|
50
|
+
}
|
|
51
|
+
if (y < 1700) {
|
|
52
|
+
u = y - 1600;
|
|
53
|
+
u2 = u * u;
|
|
54
|
+
u3 = u * u2;
|
|
55
|
+
return 120 - 0.9808 * u - 0.01532 * u2 + u3 / 7129.0;
|
|
56
|
+
}
|
|
57
|
+
if (y < 1800) {
|
|
58
|
+
u = y - 1700;
|
|
59
|
+
u2 = u * u;
|
|
60
|
+
u3 = u * u2;
|
|
61
|
+
u4 = u2 * u2;
|
|
62
|
+
return 8.83 + 0.1603 * u - 0.0059285 * u2 + 0.00013336 * u3 - u4 / 1174000;
|
|
63
|
+
}
|
|
64
|
+
if (y < 1860) {
|
|
65
|
+
u = y - 1800;
|
|
66
|
+
u2 = u * u;
|
|
67
|
+
u3 = u * u2;
|
|
68
|
+
u4 = u2 * u2;
|
|
69
|
+
u5 = u2 * u3;
|
|
70
|
+
u6 = u3 * u3;
|
|
71
|
+
u7 = u3 * u4;
|
|
72
|
+
return 13.72 - 0.332447 * u + 0.0068612 * u2 + 0.0041116 * u3 - 0.00037436 * u4 + 0.0000121272 * u5 - 0.0000001699 * u6 + 0.000000000875 * u7;
|
|
73
|
+
}
|
|
74
|
+
if (y < 1900) {
|
|
75
|
+
u = y - 1860;
|
|
76
|
+
u2 = u * u;
|
|
77
|
+
u3 = u * u2;
|
|
78
|
+
u4 = u2 * u2;
|
|
79
|
+
u5 = u2 * u3;
|
|
80
|
+
return 7.62 + 0.5737 * u - 0.251754 * u2 + 0.01680668 * u3 - 0.0004473624 * u4 + u5 / 233174;
|
|
81
|
+
}
|
|
82
|
+
if (y < 1920) {
|
|
83
|
+
u = y - 1900;
|
|
84
|
+
u2 = u * u;
|
|
85
|
+
u3 = u * u2;
|
|
86
|
+
u4 = u2 * u2;
|
|
87
|
+
return -2.79 + 1.494119 * u - 0.0598939 * u2 + 0.0061966 * u3 - 0.000197 * u4;
|
|
88
|
+
}
|
|
89
|
+
if (y < 1941) {
|
|
90
|
+
u = y - 1920;
|
|
91
|
+
u2 = u * u;
|
|
92
|
+
u3 = u * u2;
|
|
93
|
+
return 21.20 + 0.84493 * u - 0.076100 * u2 + 0.0020936 * u3;
|
|
94
|
+
}
|
|
95
|
+
if (y < 1961) {
|
|
96
|
+
u = y - 1950;
|
|
97
|
+
u2 = u * u;
|
|
98
|
+
u3 = u * u2;
|
|
99
|
+
return 29.07 + 0.407 * u - u2 / 233 + u3 / 2547;
|
|
100
|
+
}
|
|
101
|
+
if (y < 1986) {
|
|
102
|
+
u = y - 1975;
|
|
103
|
+
u2 = u * u;
|
|
104
|
+
u3 = u * u2;
|
|
105
|
+
return 45.45 + 1.067 * u - u2 / 260 - u3 / 718;
|
|
106
|
+
}
|
|
107
|
+
if (y < 2005) {
|
|
108
|
+
u = y - 2000;
|
|
109
|
+
u2 = u * u;
|
|
110
|
+
u3 = u * u2;
|
|
111
|
+
u4 = u2 * u2;
|
|
112
|
+
u5 = u2 * u3;
|
|
113
|
+
return 63.86 + 0.3345 * u - 0.060374 * u2 + 0.0017275 * u3 + 0.000651814 * u4 + 0.00002373599 * u5;
|
|
114
|
+
}
|
|
115
|
+
if (y < 2050) {
|
|
116
|
+
u = y - 2000;
|
|
117
|
+
return 62.92 + 0.32217 * u + 0.005589 * u * u;
|
|
118
|
+
}
|
|
119
|
+
if (y < 2150) {
|
|
120
|
+
u = (y - 1820) / 100;
|
|
121
|
+
return -20 + 32 * u * u - 0.5628 * (2150 - y);
|
|
122
|
+
}
|
|
123
|
+
/* all years after 2150 */
|
|
124
|
+
u = (y - 1820) / 100;
|
|
125
|
+
return -20 + 32 * u * u;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Days since J2000 (TT) for a UT-days value already in hand — factored out of
|
|
129
|
+
* {@link ttDays} so L2 transforms that compute `ut` once (sidereal time,
|
|
130
|
+
* topocentric parallax) can derive `tt` from it without re-deriving the
|
|
131
|
+
* ut→year→ΔT conversion.
|
|
132
|
+
*/
|
|
133
|
+
export function ttDaysFromUt(ut) {
|
|
134
|
+
const year = 2000 + ut / 365.25;
|
|
135
|
+
return ut + deltaTSeconds(year) / 86400;
|
|
136
|
+
}
|
|
137
|
+
/** Days since J2000 (TT), fractional — the argument every translated function consumes. */
|
|
138
|
+
export function ttDays(d) {
|
|
139
|
+
return ttDaysFromUt(utDays(d));
|
|
140
|
+
}
|
|
141
|
+
/** Inverse of {@link utDays} — the instant, truncated to integer epoch ms (TimeClip). */
|
|
142
|
+
export function dateFromUt(ut) {
|
|
143
|
+
return new Date(ut * 86400000 + J2000_EPOCH_MS);
|
|
144
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Observer } from './types.js';
|
|
2
|
+
import { Vec3 } from './nutation.js';
|
|
3
|
+
/** Topocentric horizontal position: azimuth from true north through east, altitude above the horizon. */
|
|
4
|
+
export interface AltAz {
|
|
5
|
+
azDeg: number;
|
|
6
|
+
altDeg: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* INTERNAL: what {@link topoAltAzUnrefracted} already computes on the way to
|
|
10
|
+
* az/alt. The L3 event layer needs all four from a single evaluation — the
|
|
11
|
+
* local hour angle brackets each daily cycle's altitude extrema, and the
|
|
12
|
+
* topocentric distance sets the Moon's semidiameter, hence its rise/set target.
|
|
13
|
+
*/
|
|
14
|
+
export interface TopoUnrefracted extends AltAz {
|
|
15
|
+
hourAngleDeg: number;
|
|
16
|
+
distanceAu: number;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* UPSTREAM: `sidereal_time`, astronomy.ts ~2031 — Greenwich Apparent Sidereal
|
|
20
|
+
* Time (GAST). Returned in **degrees** [0, 360) rather than upstream's hours:
|
|
21
|
+
* every caller in this port (terra/geo_pos, Horizon's spin angle) only ever
|
|
22
|
+
* uses `15 * gastHours`, so upstream's final `/15` and each caller's `*15`
|
|
23
|
+
* are folded into one multiply here — same value, one division dropped.
|
|
24
|
+
*/
|
|
25
|
+
export declare function siderealDeg(ut: number): number;
|
|
26
|
+
/**
|
|
27
|
+
* UPSTREAM: the topocentric path composed of `Equator(body, date, observer,
|
|
28
|
+
* ofdate=true, aberration=true)` (astronomy.ts ~2803) followed by `Horizon`
|
|
29
|
+
* (astronomy.ts ~2565), through its az/zd computation only — Horizon's
|
|
30
|
+
* post-refraction ra/dec refinement branch produces topocentric ra/dec, which
|
|
31
|
+
* this layer's callers (sunAltAz/moonAltAz) don't need.
|
|
32
|
+
*
|
|
33
|
+
* @param bodyEqj geocentric position of the body in AU, J2000 mean equator
|
|
34
|
+
* (EQJ) — i.e. `GeoVector`'s return, matching {@link sunGeoVectorEqj} /
|
|
35
|
+
* {@link moonGeoVectorEqj}, NOT the already-of-date vector
|
|
36
|
+
* {@link sunApparentAtTT}/{@link moonApparentAtTT} consume.
|
|
37
|
+
* @param ut days since J2000 in UT — the event layer iterates in days, and
|
|
38
|
+
* `Date` round-trips are pure overhead on a search's inner loop.
|
|
39
|
+
* @returns unrefracted topocentric azimuth/altitude, plus the local hour angle
|
|
40
|
+
* and topocentric distance the same evaluation already produced.
|
|
41
|
+
*/
|
|
42
|
+
export declare function topoAltAzUnrefracted(bodyEqj: Vec3, ut: number, observer: Observer): TopoUnrefracted;
|
|
43
|
+
/**
|
|
44
|
+
* UPSTREAM: `Refraction('normal', altitude)`, astronomy.ts ~7176 — the
|
|
45
|
+
* Saemundsson/Meeus atmospheric-lift formula (JPL Horizons' algorithm per
|
|
46
|
+
* upstream's comment), gradually reduced toward the nadir so a refracted
|
|
47
|
+
* altitude never drops below -90.
|
|
48
|
+
*/
|
|
49
|
+
export declare function refractionDeg(altitudeDeg: number): number;
|
|
50
|
+
/**
|
|
51
|
+
* Topocentric azimuth/altitude of the Sun — parallax (via the observer's
|
|
52
|
+
* geocentric position, WGS-84 flattening, elevation) and atmospheric
|
|
53
|
+
* refraction (upstream `'normal'` model) both applied.
|
|
54
|
+
*/
|
|
55
|
+
export declare function sunAltAz(time: Date, observer: Observer): AltAz;
|
|
56
|
+
/**
|
|
57
|
+
* Topocentric azimuth/altitude of the Moon — parallax (via the observer's
|
|
58
|
+
* geocentric position, WGS-84 flattening, elevation) and atmospheric
|
|
59
|
+
* refraction (upstream `'normal'` model) both applied.
|
|
60
|
+
*/
|
|
61
|
+
export declare function moonAltAz(time: Date, observer: Observer): AltAz;
|