@openwaters/almanac 0.6.0 → 0.8.0
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 +83 -7
- package/dist/eclipse.d.ts +1 -1
- package/dist/eclipse.js +6 -5
- package/dist/events.d.ts +44 -4
- package/dist/events.js +84 -16
- package/dist/horizon.d.ts +3 -0
- package/dist/horizon.js +24 -0
- package/dist/illumination.d.ts +22 -0
- package/dist/illumination.js +33 -3
- package/dist/index.d.ts +8 -5
- package/dist/index.js +4 -2
- package/dist/planetModels.d.ts +5 -0
- package/dist/planetModels.js +1261 -0
- package/dist/planets.d.ts +32 -0
- package/dist/planets.js +111 -0
- package/dist/solar.d.ts +3 -3
- package/dist/solar.js +17 -16
- package/dist/sun.d.ts +4 -0
- package/dist/sun.js +2 -2
- package/dist/transforms.d.ts +7 -3
- package/dist/transforms.js +2 -2
- package/dist/types.d.ts +3 -0
- package/dist/types.js +5 -0
- package/package.json +4 -3
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 and
|
|
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, planetary brightness, lunar and solar eclipses, and fixed-star altitude and azimuth from catalog positions, computed from pure geometry with zero network and zero runtime data files.
|
|
4
4
|
|
|
5
5
|
Twin implementations, one behavior:
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ Twin implementations, one behavior:
|
|
|
12
12
|
Supported interval: 1950-01-01T00:00Z ≤ t < 2101-01-01T00:00Z; results outside it raise a typed error. All instants are UT1-accurate, while unknown future DUT1 is outside the civil-UTC accuracy promise. See the [public contract](docs/CONTRACT.md#time-and-supported-interval) for the time model.
|
|
13
13
|
|
|
14
14
|
- Contract: [`docs/CONTRACT.md`](docs/CONTRACT.md), including coordinates, public behavior, accuracy, and fixture evidence.
|
|
15
|
-
- Scope: [`docs/
|
|
15
|
+
- Scope: [`docs/SCOPE.md`](docs/SCOPE.md), including supported behavior and deliberate boundaries.
|
|
16
16
|
- Development and releases: [`CONTRIBUTING.md`](CONTRIBUTING.md), including pinned tools and required checks.
|
|
17
17
|
- Landing page: [openwaters.io/sky](https://openwaters.io/sky), with the library running live in a browser.
|
|
18
18
|
|
|
@@ -21,11 +21,13 @@ Algorithms translated from [Astronomy Engine](https://github.com/cosinekitty/ast
|
|
|
21
21
|
|
|
22
22
|
## Performance
|
|
23
23
|
|
|
24
|
-
Almanac includes a shared performance harness for both ports: **
|
|
24
|
+
Almanac includes a shared performance harness for both ports: **34 workloads**
|
|
25
25
|
cover positions, a 228-hour sky track, short/year/polar event windows, full-range
|
|
26
26
|
moon phases, next/previous/range lunar, solar, and global solar eclipse searches,
|
|
27
27
|
including empty windows, solar obscuration over a 228-hour track, and the central
|
|
28
|
-
line of the 2024-04-08 eclipse
|
|
28
|
+
line of the 2024-04-08 eclipse, five-planet sky tracks, planetary rise/set, a
|
|
29
|
+
year of golden-hour crossings and Sun and Moon transits, and a 228-hour Moon
|
|
30
|
+
orientation track.
|
|
29
31
|
|
|
30
32
|
Event searches find altitude extrema with Brent's method and altitude crossings
|
|
31
33
|
with a cosine-seeded secant solver, each root proven inside a half-second
|
|
@@ -49,10 +51,10 @@ Reproduce the comparison locally from the repository root with mise 2026.9.1 or
|
|
|
49
51
|
```bash
|
|
50
52
|
mise install
|
|
51
53
|
mise exec -- npm ci --prefix typescript
|
|
52
|
-
mise exec -- node benchmarks/run.mjs --base v0.4.1 --skip '^global/'
|
|
54
|
+
mise exec -- node benchmarks/run.mjs --base v0.4.1 --skip '^(global|planets|suncalc)/'
|
|
53
55
|
```
|
|
54
56
|
|
|
55
|
-
The `--skip` pattern leaves out
|
|
57
|
+
The `--skip` pattern leaves out global eclipse, planetary, and SunCalc-parity workloads absent from that base. Use `--skip '^(solar|global|planets|suncalc)/'` when the base predates 0.4.0, which is when the solar eclipse workloads arrived. For a base that lacks only the SunCalc-parity APIs, use `--skip '^suncalc/'`.
|
|
56
58
|
|
|
57
59
|
CI runs the harness on code changes and fails on **median regressions over 20%**.
|
|
58
60
|
Results include timing tables, raw samples, checksums, and revision/toolchain
|
|
@@ -64,6 +66,10 @@ background task; use shorter windows for interactive queries.
|
|
|
64
66
|
|
|
65
67
|
## Usage
|
|
66
68
|
|
|
69
|
+
Migrating from SunCalc: [`docs/migrating-from-suncalc.md`](docs/migrating-from-suncalc.md) maps every SunCalc call to Almanac and gives drop-in `getTimes` and `getMoonTimes` adapters. Migrating from Solar: [`docs/migrating-from-solar.md`](docs/migrating-from-solar.md). How Almanac compares with SunCalc, Astronomy Engine, astronomia, Solar, SwiftAA, and EDSunriseSet, and when each is the better choice: [`docs/comparison.md`](docs/comparison.md).
|
|
70
|
+
|
|
71
|
+
Migrating from the Solar Swift library: [`docs/migrating-from-solar.md`](docs/migrating-from-solar.md) maps every Solar property to Almanac and gives a drop-in `Solar` adapter.
|
|
72
|
+
|
|
67
73
|
### TypeScript
|
|
68
74
|
|
|
69
75
|
```bash
|
|
@@ -98,10 +104,21 @@ for (const { kind, time } of sunEvents(today, tomorrow, observer)) {
|
|
|
98
104
|
const { azDeg, altDeg } = starAltAz(88.792939, 7.407064, today, observer);
|
|
99
105
|
```
|
|
100
106
|
|
|
107
|
+
For an unobstructed sea horizon, supply eye height above the water separately from elevation above sea level. Body altitudes remain measured from the horizontal plane:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { horizonDip, sunAltAz } from '@openwaters/almanac';
|
|
111
|
+
const eyeHeightM = 2;
|
|
112
|
+
const viewer = { latitudeDeg: 48.5, longitudeDeg: -123.0, elevationM: 2 };
|
|
113
|
+
const horizonAltDeg = horizonDip(viewer, eyeHeightM);
|
|
114
|
+
const sunAltitudeAboveHorizonDeg = sunAltAz(new Date(), viewer).altDeg - horizonAltDeg;
|
|
115
|
+
const crossings = sunEvents(today, tomorrow, viewer, eyeHeightM);
|
|
116
|
+
```
|
|
117
|
+
|
|
101
118
|
### Swift
|
|
102
119
|
|
|
103
120
|
```swift
|
|
104
|
-
.package(url: "https://github.com/openwatersio/almanac.git", exact: "0.
|
|
121
|
+
.package(url: "https://github.com/openwatersio/almanac.git", exact: "0.8.0")
|
|
105
122
|
```
|
|
106
123
|
|
|
107
124
|
```swift
|
|
@@ -134,6 +151,65 @@ for event in try sunEvents(from: today, to: tomorrow, observer: observer) {
|
|
|
134
151
|
let star = try starAltAz(raDeg: 88.792939, decDeg: 7.407064, at: today, observer: observer)
|
|
135
152
|
```
|
|
136
153
|
|
|
154
|
+
### Golden hour, transits, and the Moon's tilt
|
|
155
|
+
|
|
156
|
+
`sunAltitudeEvents` finds the Sun's center crossing any altitude, with the twilight convention, so `6` gives golden hour and `-6` civil twilight. `sunTransits` and `moonTransits` give each body's highest (`upper`) and lowest (`lower`) meridian crossings. `moonOrientation` turns the Moon's disc: subtracting the parallactic angle from the bright-limb angle gives the bright limb's direction from the zenith.
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
import { sunAltitudeEvents, sunTransits, moonTransits, moonOrientation } from '@openwaters/almanac';
|
|
160
|
+
const golden = sunAltitudeEvents(today, tomorrow, observer, 6); // 'rising' ends morning golden hour, 'falling' starts the evening one
|
|
161
|
+
const solarMidnight = sunTransits(today, tomorrow, observer).find(e => e.kind === 'lower');
|
|
162
|
+
const moonHighest = moonTransits(today, tomorrow, observer).find(e => e.kind === 'upper');
|
|
163
|
+
const { brightLimbAngleDeg, parallacticAngleDeg } = moonOrientation(today, observer);
|
|
164
|
+
const brightLimbFromZenithDeg = brightLimbAngleDeg - parallacticAngleDeg;
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
```swift
|
|
168
|
+
let golden = try sunAltitudeEvents(from: today, to: tomorrow, observer: observer, altitudeDeg: 6)
|
|
169
|
+
let solarMidnight = try sunTransits(from: today, to: tomorrow, observer: observer).first { $0.kind == .lower }
|
|
170
|
+
let moonHighest = try moonTransits(from: today, to: tomorrow, observer: observer).first { $0.kind == .upper }
|
|
171
|
+
let orientation = try moonOrientation(at: today, observer: observer)
|
|
172
|
+
let brightLimbFromZenithDeg = orientation.brightLimbAngleDeg - orientation.parallacticAngleDeg
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Planetary views
|
|
176
|
+
|
|
177
|
+
Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, and Neptune have geometric Sun-centered positions in AU, in fixed J2000 equatorial coordinates. Place the Sun at `(0, 0, 0)` and orient the scene's camera for the desired view:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
import { planetHeliocentricPosition, planetAltAz, planetIllumination, planetEvents,
|
|
181
|
+
horizonDip, sunAltAz } from '@openwaters/almanac';
|
|
182
|
+
import type { Planet } from '@openwaters/almanac';
|
|
183
|
+
|
|
184
|
+
const planets: Planet[] = ['mercury', 'venus', 'earth', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune'];
|
|
185
|
+
const now = new Date();
|
|
186
|
+
const positions = planets.map(planet => ({ planet, ...planetHeliocentricPosition(planet, now) }));
|
|
187
|
+
|
|
188
|
+
const viewer = { latitudeDeg: 48.5, longitudeDeg: -123.0, elevationM: 2 };
|
|
189
|
+
const horizonAltDeg = horizonDip(viewer, 2);
|
|
190
|
+
const venus = planetAltAz('venus', now, viewer);
|
|
191
|
+
const brightness = planetIllumination('venus', now);
|
|
192
|
+
console.log(venus.azDeg, venus.altDeg - horizonAltDeg, sunAltAz(now, viewer).altDeg,
|
|
193
|
+
brightness.magnitude, brightness.elongationDeg);
|
|
194
|
+
const crossings = planetEvents('venus', now, new Date(now.getTime() + 86400000), viewer, 2);
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
```swift
|
|
198
|
+
let now = Date()
|
|
199
|
+
let positions = try Planet.allCases.map { try planetHeliocentricPosition($0, at: now) }
|
|
200
|
+
let viewer = try Observer(latitudeDeg: 48.5, longitudeDeg: -123.0, elevationM: 2)
|
|
201
|
+
let horizon = try horizonDip(observer: viewer, heightAboveGroundM: 2)
|
|
202
|
+
let venus = try planetAltAz(.venus, at: now, observer: viewer)
|
|
203
|
+
let brightness = try planetIllumination(.venus, at: now)
|
|
204
|
+
print(venus.azDeg, venus.altDeg - horizon, brightness.magnitude, brightness.elongationDeg)
|
|
205
|
+
let crossings = try planetEvents(.venus, from: now, to: now.addingTimeInterval(86400),
|
|
206
|
+
observer: viewer, heightAboveGroundM: 2)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Earth is included for the solar-system view. Earth-based position, altitude/azimuth, illumination, and rise/set reject Earth. Sky coordinates include light-time and apparent corrections; heliocentric scene coordinates do not.
|
|
210
|
+
|
|
211
|
+
A viewing-window policy can combine planet altitude above the horizon, Sun altitude, elongation, and brightness. Actual visibility also depends on weather and observing conditions. Magnitude is approximate: the pinned model and Horizons differ by up to 0.75 magnitudes for extreme Venus crescents in the fixture interval.
|
|
212
|
+
|
|
137
213
|
### Eclipse searches
|
|
138
214
|
|
|
139
215
|
Search for a previous eclipse or all eclipses in a time window:
|
package/dist/eclipse.d.ts
CHANGED
|
@@ -127,4 +127,4 @@ export declare function lunarEclipses(startUtc: Date, endUtc: Date): LunarEclips
|
|
|
127
127
|
*
|
|
128
128
|
* @throws {RangeError} if `eclipse` is structurally invalid or `observer` is out of range.
|
|
129
129
|
*/
|
|
130
|
-
export declare function lunarEclipseVisibility(eclipse: LunarEclipse, observer: Observer): LunarEclipseVisibility;
|
|
130
|
+
export declare function lunarEclipseVisibility(eclipse: LunarEclipse, observer: Observer, heightAboveGroundM?: number): LunarEclipseVisibility;
|
package/dist/eclipse.js
CHANGED
|
@@ -17,12 +17,13 @@
|
|
|
17
17
|
// result.
|
|
18
18
|
// - upstream reports semi-durations in minutes; the spec's public shape is
|
|
19
19
|
// the contact instants themselves, and `obscuration` is not in it.
|
|
20
|
-
import {
|
|
20
|
+
import { assertSupported, assertSupportedWindowEnd, AlmanacOutOfRangeError, SUPPORTED_MIN, SUPPORTED_MAX } from './types.js';
|
|
21
21
|
import { dateFromUt, ttDaysFromUt, utDays } from './time.js';
|
|
22
22
|
import { KM_PER_AU, RAD2DEG } from './nutation.js';
|
|
23
23
|
import { calcMoon, moonGeoVectorEqj } from './moon.js';
|
|
24
24
|
import { sunGeoVectorEqj } from './sun.js';
|
|
25
25
|
import { topoAltAzUnrefracted } from './transforms.js';
|
|
26
|
+
import { horizonDip } from './horizon.js';
|
|
26
27
|
import { MOON_MEAN_RADIUS_KM, SUN_RADIUS_KM, search, searchMoonPhase } from './events.js';
|
|
27
28
|
/** UPSTREAM: `EARTH_MEAN_RADIUS_KM` + `EARTH_ATMOSPHERE_KM`, astronomy.ts 142-144.
|
|
28
29
|
* The 88 km of atmosphere is what makes the umbra match observed eclipse
|
|
@@ -306,19 +307,19 @@ function assertLunarEclipse(e) {
|
|
|
306
307
|
*
|
|
307
308
|
* @throws {RangeError} if `eclipse` is structurally invalid or `observer` is out of range.
|
|
308
309
|
*/
|
|
309
|
-
export function lunarEclipseVisibility(eclipse, observer) {
|
|
310
|
+
export function lunarEclipseVisibility(eclipse, observer, heightAboveGroundM = 0) {
|
|
310
311
|
assertLunarEclipse(eclipse);
|
|
311
|
-
|
|
312
|
+
const dip = horizonDip(observer, heightAboveGroundM);
|
|
312
313
|
const altAt = (d) => {
|
|
313
314
|
const ut = utDays(d);
|
|
314
315
|
return topoAltAzUnrefracted(moonGeoVectorEqj(ttDaysFromUt(ut)), ut, observer).altDeg;
|
|
315
316
|
};
|
|
316
317
|
// `== null` deliberately: the validator counts `undefined` as absent too,
|
|
317
318
|
// so the reader must, or an `undefined` contact would reach `utDays` raw.
|
|
318
|
-
const up = (d) => (d == null ? null : altAt(d) >
|
|
319
|
+
const up = (d) => (d == null ? null : altAt(d) > dip);
|
|
319
320
|
const peakAltDeg = altAt(eclipse.peak);
|
|
320
321
|
return {
|
|
321
|
-
visibleAtPeak: peakAltDeg >
|
|
322
|
+
visibleAtPeak: peakAltDeg > dip,
|
|
322
323
|
moonGeometricAltAtPeakDeg: peakAltDeg,
|
|
323
324
|
contactsVisible: {
|
|
324
325
|
p1: up(eclipse.p1),
|
package/dist/events.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Observer } from './types.js';
|
|
1
|
+
import { Observer, type Planet } from './types.js';
|
|
2
2
|
/** A Sun event: a horizon or twilight crossing, or upper transit. */
|
|
3
3
|
export type SunEventKind = 'rise' | 'set' | 'civilDawn' | 'civilDusk' | 'nauticalDawn' | 'nauticalDusk' | 'astroDawn' | 'astroDusk' | 'transit';
|
|
4
4
|
export interface SunEvent {
|
|
@@ -11,6 +11,24 @@ export interface MoonEvent {
|
|
|
11
11
|
time: Date;
|
|
12
12
|
kind: MoonEventKind;
|
|
13
13
|
}
|
|
14
|
+
/** A planet's point center crossing the apparent horizon. */
|
|
15
|
+
export type PlanetEventKind = 'rise' | 'set';
|
|
16
|
+
export interface PlanetEvent {
|
|
17
|
+
time: Date;
|
|
18
|
+
kind: PlanetEventKind;
|
|
19
|
+
}
|
|
20
|
+
/** The Sun's center crossing a caller-chosen altitude, upward or downward. */
|
|
21
|
+
export type AltitudeEventKind = 'rising' | 'falling';
|
|
22
|
+
export interface AltitudeEvent {
|
|
23
|
+
time: Date;
|
|
24
|
+
kind: AltitudeEventKind;
|
|
25
|
+
}
|
|
26
|
+
/** A body crossing the local meridian: highest at `upper`, lowest at `lower`. */
|
|
27
|
+
export type TransitEventKind = 'upper' | 'lower';
|
|
28
|
+
export interface TransitEvent {
|
|
29
|
+
time: Date;
|
|
30
|
+
kind: TransitEventKind;
|
|
31
|
+
}
|
|
14
32
|
/** A quarter lunar phase. */
|
|
15
33
|
export type MoonPhaseName = 'new' | 'firstQuarter' | 'full' | 'lastQuarter';
|
|
16
34
|
export interface MoonPhaseEvent {
|
|
@@ -41,7 +59,7 @@ export declare function quantizedUt(ut: number): number;
|
|
|
41
59
|
* Sun rise, set, the three twilights and upper transit within the half-open
|
|
42
60
|
* window `[startUtc, endUtc)`, sorted ascending.
|
|
43
61
|
*
|
|
44
|
-
* Rise and set
|
|
62
|
+
* Rise and set use the supplied horizon dip minus (34′ + the
|
|
45
63
|
* Sun's true semidiameter at distance) — the upper-limb convention with the
|
|
46
64
|
* actual disc, the same rule the Moon gets; the twilights are centre altitude
|
|
47
65
|
* −6°, −12° and −18° with no refraction term; transit is local hour angle
|
|
@@ -49,14 +67,36 @@ export declare function quantizedUt(ut: number): number;
|
|
|
49
67
|
* the crossings — while transit is reported regardless of whether the Sun is
|
|
50
68
|
* above the horizon when it happens.
|
|
51
69
|
*/
|
|
52
|
-
export declare function sunEvents(startUtc: Date, endUtc: Date, observer: Observer): SunEvent[];
|
|
70
|
+
export declare function sunEvents(startUtc: Date, endUtc: Date, observer: Observer, heightAboveGroundM?: number): SunEvent[];
|
|
53
71
|
/**
|
|
54
72
|
* Moonrise and moonset within the half-open window `[startUtc, endUtc)`,
|
|
55
73
|
* sorted ascending — the apparent topocentric upper limb crossing the horizon,
|
|
56
74
|
* so refraction (34′), topocentric parallax and the true semidiameter at the
|
|
57
75
|
* Moon's distance are all included — the same upper-limb rule as the Sun's. An empty list is a valid answer.
|
|
58
76
|
*/
|
|
59
|
-
export declare function moonEvents(startUtc: Date, endUtc: Date, observer: Observer): MoonEvent[];
|
|
77
|
+
export declare function moonEvents(startUtc: Date, endUtc: Date, observer: Observer, heightAboveGroundM?: number): MoonEvent[];
|
|
78
|
+
/** Rise/set of a point center at geometric altitude horizonDip minus 34 arcminutes. */
|
|
79
|
+
export declare function planetEvents(planet: Planet, startUtc: Date, endUtc: Date, observer: Observer, heightAboveGroundM?: number): PlanetEvent[];
|
|
80
|
+
/**
|
|
81
|
+
* The Sun's unrefracted geometric center crossing `altitudeDeg` within the
|
|
82
|
+
* half-open window `[startUtc, endUtc)`, sorted ascending: `rising` upward,
|
|
83
|
+
* `falling` downward. The twilight convention, so `-6` returns the civil
|
|
84
|
+
* twilight instants. A window with no crossing, as in polar day or night,
|
|
85
|
+
* returns an empty list.
|
|
86
|
+
*/
|
|
87
|
+
export declare function sunAltitudeEvents(startUtc: Date, endUtc: Date, observer: Observer, altitudeDeg: number): AltitudeEvent[];
|
|
88
|
+
/**
|
|
89
|
+
* The Sun's upper (local hour angle 0) and lower (180°) transits within the
|
|
90
|
+
* half-open window `[startUtc, endUtc)`, sorted ascending, whether or not the
|
|
91
|
+
* Sun is above the horizon. The upper transit is `sunEvents`' `transit`.
|
|
92
|
+
*/
|
|
93
|
+
export declare function sunTransits(startUtc: Date, endUtc: Date, observer: Observer): TransitEvent[];
|
|
94
|
+
/**
|
|
95
|
+
* The Moon's upper and lower transits within the half-open window
|
|
96
|
+
* `[startUtc, endUtc)`, sorted ascending, from the topocentric hour angle, so
|
|
97
|
+
* parallax is included, whether or not the Moon is above the horizon.
|
|
98
|
+
*/
|
|
99
|
+
export declare function moonTransits(startUtc: Date, endUtc: Date, observer: Observer): TransitEvent[];
|
|
60
100
|
/**
|
|
61
101
|
* UPSTREAM: `Search`, astronomy.ts ~4634 — bisection with quadratic
|
|
62
102
|
* acceleration for the ascending zero crossing of `f` in `[t1, t2]`. Times are
|
package/dist/events.js
CHANGED
|
@@ -21,13 +21,15 @@
|
|
|
21
21
|
// `SearchMoonPhase` (~5260) and the `Search` (~4634) / `QuadInterp` (~4528)
|
|
22
22
|
// root finder it calls, plus the quarter walk of `SearchMoonQuarter` (~5339)
|
|
23
23
|
// and `NextMoonQuarter` (~5362).
|
|
24
|
-
import { assertObserver, assertSupported, assertSupportedWindowEnd, SUPPORTED_MIN, SUPPORTED_MAX } from './types.js';
|
|
24
|
+
import { assertObserver, assertPlanet, assertSupported, assertSupportedWindowEnd, SUPPORTED_MIN, SUPPORTED_MAX } from './types.js';
|
|
25
25
|
import { dateFromUt, ttDaysFromUt, utDays } from './time.js';
|
|
26
26
|
import { DEG2RAD, KM_PER_AU, RAD2DEG } from './nutation.js';
|
|
27
27
|
import { topoAltAzUnrefracted } from './transforms.js';
|
|
28
28
|
import { sunGeoVectorEqj } from './sun.js';
|
|
29
29
|
import { moonGeoVectorEqj } from './moon.js';
|
|
30
30
|
import { moonPhaseDeg } from './illumination.js';
|
|
31
|
+
import { horizonDip } from './horizon.js';
|
|
32
|
+
import { planetGeoVectorEqj } from './planetModels.js';
|
|
31
33
|
// ---------------------------------------------------------------- constants
|
|
32
34
|
const CIVIL_ALT_DEG = -6;
|
|
33
35
|
const NAUTICAL_ALT_DEG = -12;
|
|
@@ -114,24 +116,30 @@ function assertReached(condition, what) {
|
|
|
114
116
|
if (!condition)
|
|
115
117
|
throw new Error(`almanac internal: ${what} did not converge`);
|
|
116
118
|
}
|
|
117
|
-
function sunSampler(observer) {
|
|
119
|
+
function sunSampler(observer, dip) {
|
|
118
120
|
return (ut) => {
|
|
119
121
|
const p = topoAltAzUnrefracted(sunGeoVectorEqj(ttDaysFromUt(ut)), ut, observer);
|
|
120
122
|
return {
|
|
121
123
|
ut, altDeg: p.altDeg, hourAngleDeg: p.hourAngleDeg,
|
|
122
|
-
riseSetAltDeg: upperLimbTargetDeg(SUN_RADIUS_KM, p.distanceAu)
|
|
124
|
+
riseSetAltDeg: dip + upperLimbTargetDeg(SUN_RADIUS_KM, p.distanceAu)
|
|
123
125
|
};
|
|
124
126
|
};
|
|
125
127
|
}
|
|
126
|
-
function moonSampler(observer) {
|
|
128
|
+
function moonSampler(observer, dip) {
|
|
127
129
|
return (ut) => {
|
|
128
130
|
const p = topoAltAzUnrefracted(moonGeoVectorEqj(ttDaysFromUt(ut)), ut, observer);
|
|
129
131
|
return {
|
|
130
132
|
ut, altDeg: p.altDeg, hourAngleDeg: p.hourAngleDeg,
|
|
131
|
-
riseSetAltDeg: upperLimbTargetDeg(MOON_MEAN_RADIUS_KM, p.distanceAu)
|
|
133
|
+
riseSetAltDeg: dip + upperLimbTargetDeg(MOON_MEAN_RADIUS_KM, p.distanceAu)
|
|
132
134
|
};
|
|
133
135
|
};
|
|
134
136
|
}
|
|
137
|
+
function planetSampler(planet, observer, dip) {
|
|
138
|
+
return (ut) => {
|
|
139
|
+
const p = topoAltAzUnrefracted(planetGeoVectorEqj(planet, ttDaysFromUt(ut)), ut, observer);
|
|
140
|
+
return { ut, altDeg: p.altDeg, hourAngleDeg: p.hourAngleDeg, riseSetAltDeg: dip - HORIZON_REFRACTION_DEG };
|
|
141
|
+
};
|
|
142
|
+
}
|
|
135
143
|
function offsetDeg(s, level) {
|
|
136
144
|
return s.altDeg - (level === null ? s.riseSetAltDeg : level);
|
|
137
145
|
}
|
|
@@ -404,9 +412,12 @@ function secantCrossing(f, a, b, s0, s1, targetDeg) {
|
|
|
404
412
|
* solving every monotonic segment between consecutive extrema for every target
|
|
405
413
|
* level. The chain starts a full cycle before `startUt` so the segment
|
|
406
414
|
* containing the window's first instant is covered, and runs one extremum past
|
|
407
|
-
* `endUt` so an event just inside the window's end is too.
|
|
415
|
+
* `endUt` so an event just inside the window's end is too. `transitKind` is
|
|
416
|
+
* emitted at each hour angle 0 and `lowerTransitKind` at each hour angle 180.
|
|
417
|
+
* With no levels the extrema are never refined: the hour-angle chain alone
|
|
418
|
+
* places the transits.
|
|
408
419
|
*/
|
|
409
|
-
function searchAltitudeEvents(sample, levels, transitKind, startUt, endUt, haRateDegPerDay, cycleDays, flatCycle) {
|
|
420
|
+
function searchAltitudeEvents(sample, levels, transitKind, lowerTransitKind, startUt, endUt, haRateDegPerDay, cycleDays, flatCycle) {
|
|
410
421
|
const extremumHalfWidthDays = flatCycle ? cycleDays / 2 : EXTREMUM_HALF_WIDTH_DAYS;
|
|
411
422
|
const found = [];
|
|
412
423
|
const emit = (ut, kind) => {
|
|
@@ -430,7 +441,8 @@ function searchAltitudeEvents(sample, levels, transitKind, startUt, endUt, haRat
|
|
|
430
441
|
// extremum we are not allowed to probe past. The segment up to it is
|
|
431
442
|
// still monotonic, so any crossing inside the window is still found.
|
|
432
443
|
const s1 = atRangeEnd ? sample(MAX_UT)
|
|
433
|
-
:
|
|
444
|
+
: levels.length === 0 ? sample(nextEst)
|
|
445
|
+
: refineExtremum(sample, nextEst, nextIsMax, extremumHalfWidthDays, s0.ut, flatCycle);
|
|
434
446
|
assertReached(s1.ut > s0.ut, 'extremum chain ordering');
|
|
435
447
|
// Earlier extrema still establish the chain, but their crossings cannot be emitted.
|
|
436
448
|
if (quantizedUt(s1.ut) >= startUt) {
|
|
@@ -442,8 +454,9 @@ function searchAltitudeEvents(sample, levels, transitKind, startUt, endUt, haRat
|
|
|
442
454
|
emit(solveCrossing(sample, spec.level, s0, s1), g1 > 0 ? spec.rising : spec.falling);
|
|
443
455
|
}
|
|
444
456
|
}
|
|
445
|
-
|
|
446
|
-
|
|
457
|
+
const transit = nextIsMax ? transitKind : lowerTransitKind;
|
|
458
|
+
if (transit !== null && !atRangeEnd)
|
|
459
|
+
emit(nextEst, transit);
|
|
447
460
|
s0 = s1;
|
|
448
461
|
if (atRangeEnd)
|
|
449
462
|
break;
|
|
@@ -469,7 +482,7 @@ function flatCycle(observer) {
|
|
|
469
482
|
* Sun rise, set, the three twilights and upper transit within the half-open
|
|
470
483
|
* window `[startUtc, endUtc)`, sorted ascending.
|
|
471
484
|
*
|
|
472
|
-
* Rise and set
|
|
485
|
+
* Rise and set use the supplied horizon dip minus (34′ + the
|
|
473
486
|
* Sun's true semidiameter at distance) — the upper-limb convention with the
|
|
474
487
|
* actual disc, the same rule the Moon gets; the twilights are centre altitude
|
|
475
488
|
* −6°, −12° and −18° with no refraction term; transit is local hour angle
|
|
@@ -477,13 +490,13 @@ function flatCycle(observer) {
|
|
|
477
490
|
* the crossings — while transit is reported regardless of whether the Sun is
|
|
478
491
|
* above the horizon when it happens.
|
|
479
492
|
*/
|
|
480
|
-
export function sunEvents(startUtc, endUtc, observer) {
|
|
493
|
+
export function sunEvents(startUtc, endUtc, observer, heightAboveGroundM = 0) {
|
|
481
494
|
assertSupported(startUtc);
|
|
482
495
|
assertSupportedWindowEnd(endUtc);
|
|
483
|
-
|
|
496
|
+
const dip = horizonDip(observer, heightAboveGroundM);
|
|
484
497
|
if (startUtc.getTime() >= endUtc.getTime())
|
|
485
498
|
return [];
|
|
486
|
-
return searchAltitudeEvents(sunSampler(observer), SUN_LEVELS, 'transit', utDays(startUtc), utDays(endUtc), SUN_HA_RATE_DEG_PER_DAY, SUN_CYCLE_DAYS, flatCycle(observer));
|
|
499
|
+
return searchAltitudeEvents(sunSampler(observer, dip), SUN_LEVELS, 'transit', null, utDays(startUtc), utDays(endUtc), SUN_HA_RATE_DEG_PER_DAY, SUN_CYCLE_DAYS, flatCycle(observer));
|
|
487
500
|
}
|
|
488
501
|
/**
|
|
489
502
|
* Moonrise and moonset within the half-open window `[startUtc, endUtc)`,
|
|
@@ -491,13 +504,68 @@ export function sunEvents(startUtc, endUtc, observer) {
|
|
|
491
504
|
* so refraction (34′), topocentric parallax and the true semidiameter at the
|
|
492
505
|
* Moon's distance are all included — the same upper-limb rule as the Sun's. An empty list is a valid answer.
|
|
493
506
|
*/
|
|
494
|
-
export function moonEvents(startUtc, endUtc, observer) {
|
|
507
|
+
export function moonEvents(startUtc, endUtc, observer, heightAboveGroundM = 0) {
|
|
508
|
+
assertSupported(startUtc);
|
|
509
|
+
assertSupportedWindowEnd(endUtc);
|
|
510
|
+
const dip = horizonDip(observer, heightAboveGroundM);
|
|
511
|
+
if (startUtc.getTime() >= endUtc.getTime())
|
|
512
|
+
return [];
|
|
513
|
+
return searchAltitudeEvents(moonSampler(observer, dip), MOON_LEVELS, null, null, utDays(startUtc), utDays(endUtc), MOON_HA_RATE_DEG_PER_DAY, MOON_CYCLE_DAYS, flatCycle(observer));
|
|
514
|
+
}
|
|
515
|
+
/** Rise/set of a point center at geometric altitude horizonDip minus 34 arcminutes. */
|
|
516
|
+
export function planetEvents(planet, startUtc, endUtc, observer, heightAboveGroundM = 0) {
|
|
517
|
+
assertPlanet(planet);
|
|
518
|
+
assertSupported(startUtc);
|
|
519
|
+
assertSupportedWindowEnd(endUtc);
|
|
520
|
+
const dip = horizonDip(observer, heightAboveGroundM);
|
|
521
|
+
if (startUtc.getTime() >= endUtc.getTime())
|
|
522
|
+
return [];
|
|
523
|
+
const cycleDays = 0.9972695717592592;
|
|
524
|
+
return searchAltitudeEvents(planetSampler(planet, observer, dip), MOON_LEVELS, null, null, utDays(startUtc), utDays(endUtc), 360 / cycleDays, cycleDays, flatCycle(observer));
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* The Sun's unrefracted geometric center crossing `altitudeDeg` within the
|
|
528
|
+
* half-open window `[startUtc, endUtc)`, sorted ascending: `rising` upward,
|
|
529
|
+
* `falling` downward. The twilight convention, so `-6` returns the civil
|
|
530
|
+
* twilight instants. A window with no crossing, as in polar day or night,
|
|
531
|
+
* returns an empty list.
|
|
532
|
+
*/
|
|
533
|
+
export function sunAltitudeEvents(startUtc, endUtc, observer, altitudeDeg) {
|
|
534
|
+
if (!(altitudeDeg >= -90 && altitudeDeg <= 90))
|
|
535
|
+
throw new RangeError(`altitudeDeg out of range: ${altitudeDeg}`);
|
|
536
|
+
assertSupported(startUtc);
|
|
537
|
+
assertSupportedWindowEnd(endUtc);
|
|
538
|
+
assertObserver(observer);
|
|
539
|
+
if (startUtc.getTime() >= endUtc.getTime())
|
|
540
|
+
return [];
|
|
541
|
+
const levels = [{ level: altitudeDeg, rising: 'rising', falling: 'falling' }];
|
|
542
|
+
return searchAltitudeEvents(sunSampler(observer, 0), levels, null, null, utDays(startUtc), utDays(endUtc), SUN_HA_RATE_DEG_PER_DAY, SUN_CYCLE_DAYS, flatCycle(observer));
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* The Sun's upper (local hour angle 0) and lower (180°) transits within the
|
|
546
|
+
* half-open window `[startUtc, endUtc)`, sorted ascending, whether or not the
|
|
547
|
+
* Sun is above the horizon. The upper transit is `sunEvents`' `transit`.
|
|
548
|
+
*/
|
|
549
|
+
export function sunTransits(startUtc, endUtc, observer) {
|
|
550
|
+
assertSupported(startUtc);
|
|
551
|
+
assertSupportedWindowEnd(endUtc);
|
|
552
|
+
assertObserver(observer);
|
|
553
|
+
if (startUtc.getTime() >= endUtc.getTime())
|
|
554
|
+
return [];
|
|
555
|
+
return searchAltitudeEvents(sunSampler(observer, 0), [], 'upper', 'lower', utDays(startUtc), utDays(endUtc), SUN_HA_RATE_DEG_PER_DAY, SUN_CYCLE_DAYS, flatCycle(observer));
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* The Moon's upper and lower transits within the half-open window
|
|
559
|
+
* `[startUtc, endUtc)`, sorted ascending, from the topocentric hour angle, so
|
|
560
|
+
* parallax is included, whether or not the Moon is above the horizon.
|
|
561
|
+
*/
|
|
562
|
+
export function moonTransits(startUtc, endUtc, observer) {
|
|
495
563
|
assertSupported(startUtc);
|
|
496
564
|
assertSupportedWindowEnd(endUtc);
|
|
497
565
|
assertObserver(observer);
|
|
498
566
|
if (startUtc.getTime() >= endUtc.getTime())
|
|
499
567
|
return [];
|
|
500
|
-
return searchAltitudeEvents(moonSampler(observer),
|
|
568
|
+
return searchAltitudeEvents(moonSampler(observer, 0), [], 'upper', 'lower', utDays(startUtc), utDays(endUtc), MOON_HA_RATE_DEG_PER_DAY, MOON_CYCLE_DAYS, flatCycle(observer));
|
|
501
569
|
}
|
|
502
570
|
// -------------------------------------------------------------- moon phases
|
|
503
571
|
/**
|
package/dist/horizon.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { assertObserver } from './types.js';
|
|
2
|
+
import { DEG2RAD, RAD2DEG, EARTH_FLATTENING, EARTH_EQUATORIAL_RADIUS_KM } from './nutation.js';
|
|
3
|
+
/** Apparent horizon altitude below the horizontal plane; eye height is measured above the unobstructed surface. */
|
|
4
|
+
export function horizonDip(observer, heightAboveGroundM) {
|
|
5
|
+
assertObserver(observer);
|
|
6
|
+
const elevation = observer.elevationM ?? 0;
|
|
7
|
+
const ground = elevation - heightAboveGroundM;
|
|
8
|
+
if (!(heightAboveGroundM >= 0 && heightAboveGroundM <= 10000) || !(ground >= -500 && ground <= 10000))
|
|
9
|
+
throw new RangeError('eye height or ground elevation out of range');
|
|
10
|
+
if (heightAboveGroundM === 0)
|
|
11
|
+
return 0;
|
|
12
|
+
// HorizonDipAngle: https://github.com/cosinekitty/astronomy/blob/865d3da7d8112bbc7911238052c6af4aaf877181/source/js/astronomy.ts#L5437.
|
|
13
|
+
const phi = observer.latitudeDeg * DEG2RAD;
|
|
14
|
+
const sinphi = Math.sin(phi);
|
|
15
|
+
const cosphi = Math.cos(phi);
|
|
16
|
+
const c = 1 / Math.hypot(cosphi, sinphi * EARTH_FLATTENING);
|
|
17
|
+
const s = c * (EARTH_FLATTENING * EARTH_FLATTENING);
|
|
18
|
+
const htKm = ground / 1000;
|
|
19
|
+
const ach = EARTH_EQUATORIAL_RADIUS_KM * c + htKm;
|
|
20
|
+
const ash = EARTH_EQUATORIAL_RADIUS_KM * s + htKm;
|
|
21
|
+
const radiusM = 1000 * Math.hypot(ach * cosphi, ash * sinphi);
|
|
22
|
+
const k = 0.175 * Math.pow(1 - (6.5e-3 / 283.15) * (elevation - (2 / 3) * heightAboveGroundM), 3.256);
|
|
23
|
+
return RAD2DEG * -(Math.sqrt(2 * (1 - k) * heightAboveGroundM / radiusM) / (1 - k));
|
|
24
|
+
}
|
package/dist/illumination.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Observer } from './types.js';
|
|
2
|
+
import { Vec3 } from './nutation.js';
|
|
1
3
|
/** Moon illumination at an instant. `phase` is 0 at new moon, 0.5 at full. */
|
|
2
4
|
export interface MoonIllumination {
|
|
3
5
|
fraction: number;
|
|
@@ -5,6 +7,8 @@ export interface MoonIllumination {
|
|
|
5
7
|
phase: number;
|
|
6
8
|
waxing: boolean;
|
|
7
9
|
}
|
|
10
|
+
/** UPSTREAM: `AngleBetween`, astronomy.ts lines 256-273 — angle between two vectors, [0, 180]. */
|
|
11
|
+
export declare function angleBetweenDeg(a: Vec3, b: Vec3): number;
|
|
8
12
|
/**
|
|
9
13
|
* INTERNAL: the Moon's apparent ecliptic longitude ahead of the Sun's, [0, 360)
|
|
10
14
|
* — 0 at new moon, 180 at full. The single definition of lunar phase in this
|
|
@@ -30,3 +34,21 @@ export declare function moonIlluminationAtTT(tt: number): MoonIllumination;
|
|
|
30
34
|
* phase (0 = new, 0.5 = full, `waxing` = phase < 0.5).
|
|
31
35
|
*/
|
|
32
36
|
export declare function moonIllumination(time: Date): MoonIllumination;
|
|
37
|
+
/**
|
|
38
|
+
* How the Moon's disc is turned on the observer's sky. `brightLimbAngleDeg` is
|
|
39
|
+
* the position angle of the bright limb's midpoint from celestial north
|
|
40
|
+
* through east, in [0, 360); `parallacticAngleDeg` is the angle at the Moon
|
|
41
|
+
* from celestial north to the observer's zenith, in (-180, 180]. Their
|
|
42
|
+
* difference is the bright limb's angle from the zenith.
|
|
43
|
+
*/
|
|
44
|
+
export interface MoonOrientation {
|
|
45
|
+
brightLimbAngleDeg: number;
|
|
46
|
+
parallacticAngleDeg: number;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The Moon's orientation at an instant: the bright limb from the apparent
|
|
50
|
+
* topocentric Moon and the apparent geocentric Sun (Meeus, Astronomical
|
|
51
|
+
* Algorithms, 48.5), and the parallactic angle from the Moon's topocentric
|
|
52
|
+
* hour angle and declination at the observer's geodetic latitude (Meeus 14.1).
|
|
53
|
+
*/
|
|
54
|
+
export declare function moonOrientation(time: Date, observer: Observer): MoonOrientation;
|
package/dist/illumination.js
CHANGED
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
// 865d3da7d8112bbc7911238052c6af4aaf877181, source/js/astronomy.ts.
|
|
9
9
|
//
|
|
10
10
|
// INTERNAL: not part of the curated public API (see index.ts).
|
|
11
|
-
import { assertSupported } from './types.js';
|
|
12
|
-
import { ttDays } from './time.js';
|
|
11
|
+
import { assertObserver, assertSupported } from './types.js';
|
|
12
|
+
import { ttDays, ttDaysFromUt, utDays } from './time.js';
|
|
13
|
+
import { topoAltAzUnrefracted } from './transforms.js';
|
|
14
|
+
import { sunApparentAtTT } from './positions.js';
|
|
13
15
|
import { DEG2RAD, PrecessDirection, RAD2DEG, earthTilt, eclipticToEquatorial, gyration } from './nutation.js';
|
|
14
16
|
import { moonGeoVectorEqj } from './moon.js';
|
|
15
17
|
import { earthHelioVector, sunGeoVectorEqj } from './sun.js';
|
|
16
18
|
/** UPSTREAM: `AngleBetween`, astronomy.ts lines 256-273 — angle between two vectors, [0, 180]. */
|
|
17
|
-
function angleBetweenDeg(a, b) {
|
|
19
|
+
export function angleBetweenDeg(a, b) {
|
|
18
20
|
const aa = a.x * a.x + a.y * a.y + a.z * a.z;
|
|
19
21
|
const bb = b.x * b.x + b.y * b.y + b.z * b.z;
|
|
20
22
|
const dot = (a.x * b.x + a.y * b.y + a.z * b.z) / Math.sqrt(aa * bb);
|
|
@@ -89,3 +91,31 @@ export function moonIllumination(time) {
|
|
|
89
91
|
assertSupported(time);
|
|
90
92
|
return moonIlluminationAtTT(ttDays(time));
|
|
91
93
|
}
|
|
94
|
+
/**
|
|
95
|
+
* The Moon's orientation at an instant: the bright limb from the apparent
|
|
96
|
+
* topocentric Moon and the apparent geocentric Sun (Meeus, Astronomical
|
|
97
|
+
* Algorithms, 48.5), and the parallactic angle from the Moon's topocentric
|
|
98
|
+
* hour angle and declination at the observer's geodetic latitude (Meeus 14.1).
|
|
99
|
+
*/
|
|
100
|
+
export function moonOrientation(time, observer) {
|
|
101
|
+
assertSupported(time);
|
|
102
|
+
assertObserver(observer);
|
|
103
|
+
const ut = utDays(time);
|
|
104
|
+
const tt = ttDaysFromUt(ut);
|
|
105
|
+
const moon = topoAltAzUnrefracted(moonGeoVectorEqj(tt), ut, observer);
|
|
106
|
+
const sun = sunApparentAtTT(tt);
|
|
107
|
+
const dec = moon.decDeg * DEG2RAD;
|
|
108
|
+
const sunDec = sun.decDeg * DEG2RAD;
|
|
109
|
+
const dRa = (sun.raDeg - moon.raDeg) * DEG2RAD;
|
|
110
|
+
let brightLimbAngleDeg = RAD2DEG * Math.atan2(Math.cos(sunDec) * Math.sin(dRa), Math.sin(sunDec) * Math.cos(dec) - Math.cos(sunDec) * Math.sin(dec) * Math.cos(dRa));
|
|
111
|
+
if (brightLimbAngleDeg < 0)
|
|
112
|
+
brightLimbAngleDeg += 360;
|
|
113
|
+
if (brightLimbAngleDeg >= 360)
|
|
114
|
+
brightLimbAngleDeg -= 360;
|
|
115
|
+
const ha = moon.hourAngleDeg * DEG2RAD;
|
|
116
|
+
const lat = observer.latitudeDeg * DEG2RAD;
|
|
117
|
+
let parallacticAngleDeg = RAD2DEG * Math.atan2(Math.sin(ha), Math.tan(lat) * Math.cos(dec) - Math.sin(dec) * Math.cos(ha));
|
|
118
|
+
if (parallacticAngleDeg <= -180)
|
|
119
|
+
parallacticAngleDeg += 360;
|
|
120
|
+
return { brightLimbAngleDeg, parallacticAngleDeg };
|
|
121
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
export type { Observer } from './types.js';
|
|
1
|
+
export type { Observer, Planet } from './types.js';
|
|
2
|
+
export type { HeliocentricPosition, PlanetPosition, PlanetIllumination } from './planets.js';
|
|
3
|
+
export { planetHeliocentricPosition, planetPosition, planetAltAz, planetIllumination } from './planets.js';
|
|
4
|
+
export { horizonDip } from './horizon.js';
|
|
2
5
|
export { AlmanacOutOfRangeError } from './types.js';
|
|
3
6
|
export type { SunPosition, MoonPosition } from './positions.js';
|
|
4
7
|
export { sunPosition, moonPosition } from './positions.js';
|
|
5
8
|
export type { AltAz } from './transforms.js';
|
|
6
9
|
export { sunAltAz, moonAltAz, starAltAz } from './transforms.js';
|
|
7
|
-
export type { MoonIllumination } from './illumination.js';
|
|
8
|
-
export { moonIllumination } from './illumination.js';
|
|
9
|
-
export type { SunEvent, SunEventKind, MoonEvent, MoonEventKind, MoonPhaseEvent, MoonPhaseName } from './events.js';
|
|
10
|
-
export { sunEvents, moonEvents, searchMoonPhases } from './events.js';
|
|
10
|
+
export type { MoonIllumination, MoonOrientation } from './illumination.js';
|
|
11
|
+
export { moonIllumination, moonOrientation } from './illumination.js';
|
|
12
|
+
export type { SunEvent, SunEventKind, MoonEvent, MoonEventKind, MoonPhaseEvent, MoonPhaseName, PlanetEvent, PlanetEventKind, AltitudeEvent, AltitudeEventKind, TransitEvent, TransitEventKind } from './events.js';
|
|
13
|
+
export { sunEvents, moonEvents, searchMoonPhases, planetEvents, sunAltitudeEvents, sunTransits, moonTransits } from './events.js';
|
|
11
14
|
export type { LunarEclipse, LunarEclipseVisibility } from './eclipse.js';
|
|
12
15
|
export { nextLunarEclipse, previousLunarEclipse, lunarEclipses, lunarEclipseVisibility } from './eclipse.js';
|
|
13
16
|
export type { SolarEclipse, SolarEclipseKind, SolarEclipseSunAltitudes } from './solar.js';
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
export { planetHeliocentricPosition, planetPosition, planetAltAz, planetIllumination } from './planets.js';
|
|
2
|
+
export { horizonDip } from './horizon.js';
|
|
1
3
|
export { AlmanacOutOfRangeError } from './types.js';
|
|
2
4
|
export { sunPosition, moonPosition } from './positions.js';
|
|
3
5
|
export { sunAltAz, moonAltAz, starAltAz } from './transforms.js';
|
|
4
|
-
export { moonIllumination } from './illumination.js';
|
|
5
|
-
export { sunEvents, moonEvents, searchMoonPhases } from './events.js';
|
|
6
|
+
export { moonIllumination, moonOrientation } from './illumination.js';
|
|
7
|
+
export { sunEvents, moonEvents, searchMoonPhases, planetEvents, sunAltitudeEvents, sunTransits, moonTransits } from './events.js';
|
|
6
8
|
export { nextLunarEclipse, previousLunarEclipse, lunarEclipses, lunarEclipseVisibility } from './eclipse.js';
|
|
7
9
|
export { nextSolarEclipse, previousSolarEclipse, solarEclipses, solarObscuration } from './solar.js';
|
|
8
10
|
export { nextGlobalSolarEclipse, previousGlobalSolarEclipse, globalSolarEclipses, solarEclipseAxisPoint, solarEclipseCentralLine } from './globalSolar.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Planet } from './types.js';
|
|
2
|
+
import { type Vec3 } from './nutation.js';
|
|
3
|
+
/** INTERNAL: geometric Sun-centered vector in AU, J2000 mean equator. */
|
|
4
|
+
export declare function planetHelioVector(planet: Planet, tt: number): Vec3;
|
|
5
|
+
export declare function planetGeoVectorEqj(planet: Planet, tt: number, aberration?: boolean): Vec3;
|