@motioncomplex/cosmos-lib 1.0.9
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 +125 -0
- package/dist/api.d.ts +246 -0
- package/dist/cache.d.ts +11 -0
- package/dist/clock.d.ts +181 -0
- package/dist/constants.d.ts +43 -0
- package/dist/data/constellations.d.ts +58 -0
- package/dist/data/cutouts.d.ts +70 -0
- package/dist/data/deep-sky.d.ts +27 -0
- package/dist/data/images.d.ts +147 -0
- package/dist/data/index.d.ts +422 -0
- package/dist/data/messier.d.ts +61 -0
- package/dist/data/ps1-files.d.ts +11 -0
- package/dist/data/showers.d.ts +62 -0
- package/dist/data/solar-system.d.ts +34 -0
- package/dist/data/stars.d.ts +57 -0
- package/dist/data/textures.d.ts +67 -0
- package/dist/eclipse.d.ts +176 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.ts +237 -0
- package/dist/index.js +713 -0
- package/dist/math.d.ts +532 -0
- package/dist/media-DVOcIMa1.js +252 -0
- package/dist/media-DlE7RKBL.cjs +1 -0
- package/dist/media.d.ts +217 -0
- package/dist/moon.d.ts +170 -0
- package/dist/planner.d.ts +224 -0
- package/dist/react/index.cjs +1 -0
- package/dist/react/index.d.ts +167 -0
- package/dist/react/index.js +163 -0
- package/dist/skymap-hittest.d.ts +69 -0
- package/dist/skymap-interactive-CLg6FA0X.js +6377 -0
- package/dist/skymap-interactive-D2OZFwJ7.cjs +1 -0
- package/dist/skymap-interactive.d.ts +153 -0
- package/dist/skymap.d.ts +172 -0
- package/dist/sun.d.ts +119 -0
- package/dist/three/factories.d.ts +160 -0
- package/dist/three/flight.d.ts +116 -0
- package/dist/three/index.cjs +20 -0
- package/dist/three/index.d.ts +21 -0
- package/dist/three/index.js +404 -0
- package/dist/three/lod.d.ts +100 -0
- package/dist/three/shaders.d.ts +22 -0
- package/dist/three/types.d.ts +169 -0
- package/dist/transitions.d.ts +246 -0
- package/dist/types.d.ts +730 -0
- package/dist/units.d.ts +132 -0
- package/package.json +93 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Complete Messier Catalog -- all 110 objects.
|
|
3
|
+
*
|
|
4
|
+
* Source: SEDS Messier Database.
|
|
5
|
+
* Coordinates are J2000 equatorial.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A Messier catalog entry with position, photometry, and classification.
|
|
11
|
+
*
|
|
12
|
+
* Each object has a Messier number (1-110), an optional NGC/IC cross-reference,
|
|
13
|
+
* and is typed as `'nebula'`, `'cluster'`, or `'galaxy'` with a more specific subtype.
|
|
14
|
+
*/
|
|
15
|
+
export interface MessierObject {
|
|
16
|
+
/** Messier number (1-110) */
|
|
17
|
+
messier: number;
|
|
18
|
+
/** Common name */
|
|
19
|
+
name: string;
|
|
20
|
+
/** NGC/IC cross-reference */
|
|
21
|
+
ngc?: string;
|
|
22
|
+
/** Object type */
|
|
23
|
+
type: 'nebula' | 'cluster' | 'galaxy';
|
|
24
|
+
/** Subtype for more detail */
|
|
25
|
+
subtype: string;
|
|
26
|
+
/** 3-letter constellation abbreviation */
|
|
27
|
+
constellation: string;
|
|
28
|
+
/** Right Ascension in degrees (J2000) */
|
|
29
|
+
ra: number;
|
|
30
|
+
/** Declination in degrees (J2000) */
|
|
31
|
+
dec: number;
|
|
32
|
+
/** Apparent visual magnitude */
|
|
33
|
+
mag: number | null;
|
|
34
|
+
/** Angular size in arcminutes */
|
|
35
|
+
size_arcmin?: number;
|
|
36
|
+
/** Distance in kilo-light-years */
|
|
37
|
+
distance_kly?: number;
|
|
38
|
+
/** Brief description */
|
|
39
|
+
description: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The complete Messier catalog: all 110 deep-sky objects cataloged by
|
|
43
|
+
* Charles Messier in the 18th century.
|
|
44
|
+
*
|
|
45
|
+
* Includes nebulae, star clusters, and galaxies with J2000 coordinates,
|
|
46
|
+
* apparent magnitudes, angular sizes, and distances.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* import { MESSIER_CATALOG } from '@motioncomplex/cosmos-lib'
|
|
51
|
+
*
|
|
52
|
+
* const m42 = MESSIER_CATALOG.find(m => m.messier === 42)
|
|
53
|
+
* console.log(m42?.name) // 'Orion Nebula'
|
|
54
|
+
* console.log(m42?.distance_kly) // 1.34
|
|
55
|
+
*
|
|
56
|
+
* // Get all galaxies in the catalog
|
|
57
|
+
* const galaxies = MESSIER_CATALOG.filter(m => m.type === 'galaxy')
|
|
58
|
+
* console.log(galaxies.length) // 40
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export declare const MESSIER_CATALOG: readonly MessierObject[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Precomputed Pan-STARRS DR2 file list for catalog objects.
|
|
3
|
+
*
|
|
4
|
+
* Maps object ID to per-filter filenames from the PS1 archive.
|
|
5
|
+
* Used by the runtime cutout module to skip the file-list API call,
|
|
6
|
+
* reducing Pan-STARRS cutout requests from 2 round-trips to 1.
|
|
7
|
+
*
|
|
8
|
+
* Generated by: scripts/generate-ps1-filelist.mjs
|
|
9
|
+
* DO NOT EDIT MANUALLY.
|
|
10
|
+
*/
|
|
11
|
+
export declare const PS1_FILES: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Major meteor showers -- ~23 significant annual showers.
|
|
3
|
+
*
|
|
4
|
+
* Source: IAU Meteor Data Center + IMO Working List.
|
|
5
|
+
*
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* A meteor shower with radiant position, timing, and activity data.
|
|
10
|
+
*
|
|
11
|
+
* Activity windows are defined by solar longitude and approximate calendar
|
|
12
|
+
* dates. The zenithal hourly rate (ZHR) represents the theoretical peak
|
|
13
|
+
* rate under ideal conditions.
|
|
14
|
+
*/
|
|
15
|
+
export interface MeteorShower {
|
|
16
|
+
/** Unique identifier */
|
|
17
|
+
id: string;
|
|
18
|
+
/** Common name */
|
|
19
|
+
name: string;
|
|
20
|
+
/** IAU 3-letter code */
|
|
21
|
+
code: string;
|
|
22
|
+
/** Radiant Right Ascension in degrees */
|
|
23
|
+
radiantRA: number;
|
|
24
|
+
/** Radiant Declination in degrees */
|
|
25
|
+
radiantDec: number;
|
|
26
|
+
/** Peak solar longitude in degrees */
|
|
27
|
+
solarLon: number;
|
|
28
|
+
/** Approximate peak date (MMM DD) */
|
|
29
|
+
peakDate: string;
|
|
30
|
+
/** Activity start date (MMM DD) */
|
|
31
|
+
start: string;
|
|
32
|
+
/** Activity end date (MMM DD) */
|
|
33
|
+
end: string;
|
|
34
|
+
/** Zenithal Hourly Rate at peak */
|
|
35
|
+
zhr: number;
|
|
36
|
+
/** Geocentric velocity in km/s */
|
|
37
|
+
speed: number;
|
|
38
|
+
/** Parent body (comet or asteroid) */
|
|
39
|
+
parentBody?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* All major annual meteor showers with radiant positions, peak dates,
|
|
43
|
+
* activity windows, and zenithal hourly rates.
|
|
44
|
+
*
|
|
45
|
+
* Solar longitudes can be compared against the Sun's ecliptic longitude
|
|
46
|
+
* (from `AstroMath.planetEcliptic`) to determine which showers are
|
|
47
|
+
* currently active. See {@link Data.getActiveShowers} for a convenience method.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* import { METEOR_SHOWERS } from '@motioncomplex/cosmos-lib'
|
|
52
|
+
*
|
|
53
|
+
* const perseids = METEOR_SHOWERS.find(s => s.id === 'perseids')
|
|
54
|
+
* console.log(perseids?.zhr) // 100
|
|
55
|
+
* console.log(perseids?.parentBody) // '109P/Swift-Tuttle'
|
|
56
|
+
* console.log(perseids?.peakDate) // 'Aug 12'
|
|
57
|
+
*
|
|
58
|
+
* // Get showers with ZHR > 50
|
|
59
|
+
* const major = METEOR_SHOWERS.filter(s => s.zhr > 50)
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare const METEOR_SHOWERS: readonly MeteorShower[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CelestialObject } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* A solar-system body with physical properties extending {@link CelestialObject}.
|
|
4
|
+
*
|
|
5
|
+
* Includes diameter, mass, moon count, and surface temperature in addition
|
|
6
|
+
* to the standard celestial-object fields. Solar-system bodies have `null`
|
|
7
|
+
* RA/Dec because their positions are computed dynamically.
|
|
8
|
+
*/
|
|
9
|
+
export interface SolarSystemBody extends CelestialObject {
|
|
10
|
+
/** Equatorial diameter in kilometres. */
|
|
11
|
+
diameter_km: number;
|
|
12
|
+
/** Mass in kilograms. Omitted for some minor bodies. */
|
|
13
|
+
mass_kg?: number;
|
|
14
|
+
/** Number of known natural satellites. */
|
|
15
|
+
moons?: number;
|
|
16
|
+
/** Mean surface (or cloud-top) temperature in Kelvin. */
|
|
17
|
+
surface_temp_K?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* All major solar-system bodies: the Sun, eight planets, and the Moon.
|
|
21
|
+
*
|
|
22
|
+
* Each entry is a {@link SolarSystemBody} with RA/Dec set to `null`
|
|
23
|
+
* (positions should be computed at runtime via `AstroMath.planetEcliptic`).
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { SOLAR_SYSTEM } from '@motioncomplex/cosmos-lib'
|
|
28
|
+
*
|
|
29
|
+
* const jupiter = SOLAR_SYSTEM.find(b => b.id === 'jupiter')
|
|
30
|
+
* console.log(jupiter?.diameter_km) // 139820
|
|
31
|
+
* console.log(jupiter?.moons) // 95
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare const SOLAR_SYSTEM: readonly SolarSystemBody[];
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bright Star Catalog -- Top ~200 named stars by apparent magnitude.
|
|
3
|
+
*
|
|
4
|
+
* Source: IAU Working Group on Star Names + Yale Bright Star Catalog.
|
|
5
|
+
* Coordinates are J2000 equatorial. Proper motions in milliarcseconds/year.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A named bright star from the IAU catalog with astrometric data.
|
|
11
|
+
*
|
|
12
|
+
* Contains position (J2000), photometry, spectral type, and proper motion.
|
|
13
|
+
* Stars are identified by their slugified IAU proper name.
|
|
14
|
+
*/
|
|
15
|
+
export interface BrightStar {
|
|
16
|
+
/** Unique identifier (IAU name, slugified) */
|
|
17
|
+
id: string;
|
|
18
|
+
/** IAU proper name */
|
|
19
|
+
name: string;
|
|
20
|
+
/** 3-letter IAU constellation abbreviation */
|
|
21
|
+
con: string;
|
|
22
|
+
/** Harvard Revised (HR/BS) catalog number */
|
|
23
|
+
hr: number;
|
|
24
|
+
/** Right Ascension in degrees (J2000) */
|
|
25
|
+
ra: number;
|
|
26
|
+
/** Declination in degrees (J2000) */
|
|
27
|
+
dec: number;
|
|
28
|
+
/** Apparent visual magnitude */
|
|
29
|
+
mag: number;
|
|
30
|
+
/** Spectral type */
|
|
31
|
+
spec: string;
|
|
32
|
+
/** Proper motion in RA (mas/yr, includes cos(dec) factor) */
|
|
33
|
+
pmRa: number;
|
|
34
|
+
/** Proper motion in Dec (mas/yr) */
|
|
35
|
+
pmDec: number;
|
|
36
|
+
/** B-V color index */
|
|
37
|
+
bv: number;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* IAU-named stars sorted by apparent visual magnitude (brightest first).
|
|
41
|
+
*
|
|
42
|
+
* RA/Dec are J2000.0 epoch in degrees. Proper motions are in mas/yr
|
|
43
|
+
* (pmRA includes the cos(dec) factor). Magnitudes are V-band.
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { BRIGHT_STARS } from '@motioncomplex/cosmos-lib'
|
|
48
|
+
*
|
|
49
|
+
* const sirius = BRIGHT_STARS.find(s => s.name === 'Sirius')
|
|
50
|
+
* console.log(sirius?.mag) // -1.46
|
|
51
|
+
* console.log(sirius?.spec) // 'A1V'
|
|
52
|
+
*
|
|
53
|
+
* // Get the 10 brightest stars
|
|
54
|
+
* const top10 = BRIGHT_STARS.slice(0, 10)
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare const BRIGHT_STARS: readonly BrightStar[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Curated public-domain texture URL registry.
|
|
3
|
+
*
|
|
4
|
+
* Does **not** bundle binary assets -- provides URLs to known-good sources
|
|
5
|
+
* (primarily Wikimedia Commons). Multiple fallback URLs per texture for
|
|
6
|
+
* use with `Media.chainLoad`.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Metadata for a single texture asset, including resolution and licensing.
|
|
12
|
+
*
|
|
13
|
+
* Each texture has one or more URLs ordered by quality (highest first).
|
|
14
|
+
* The multiple-URL design enables fallback loading via `Media.chainLoad`.
|
|
15
|
+
*/
|
|
16
|
+
export interface TextureInfo {
|
|
17
|
+
/** Unique identifier (e.g. `'earth'`, `'saturn_ring'`). */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Human-readable name (e.g. `'Earth Blue Marble'`). */
|
|
20
|
+
name: string;
|
|
21
|
+
/** URLs ordered by quality (highest first). Multiple entries for fallback. */
|
|
22
|
+
urls: string[];
|
|
23
|
+
/** Attribution/credit string. */
|
|
24
|
+
credit: string;
|
|
25
|
+
/** License type. */
|
|
26
|
+
license: 'public-domain' | 'CC0' | 'CC-BY';
|
|
27
|
+
/** Texture width in pixels. */
|
|
28
|
+
width: number;
|
|
29
|
+
/** Texture height in pixels. */
|
|
30
|
+
height: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Planet and moon surface textures -- NASA/JPL public-domain imagery.
|
|
34
|
+
*
|
|
35
|
+
* Includes the Sun, all eight planets (with atmosphere/cloud/night variants
|
|
36
|
+
* for Earth and Venus), Saturn's ring, and the Moon. Keyed by body ID.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* import { PLANET_TEXTURES } from '@motioncomplex/cosmos-lib'
|
|
41
|
+
*
|
|
42
|
+
* const earth = PLANET_TEXTURES['earth']
|
|
43
|
+
* console.log(earth.name) // 'Earth Blue Marble'
|
|
44
|
+
* console.log(earth.width) // 8192
|
|
45
|
+
* console.log(earth.urls[0]) // Wikimedia Commons URL
|
|
46
|
+
*
|
|
47
|
+
* // Load with fallback chain
|
|
48
|
+
* const marsUrl = await Media.chainLoad(PLANET_TEXTURES['mars'].urls)
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare const PLANET_TEXTURES: Readonly<Record<string, TextureInfo>>;
|
|
52
|
+
/**
|
|
53
|
+
* Star field and Milky Way panorama textures for sky-sphere backgrounds.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* import { STAR_TEXTURES } from '@motioncomplex/cosmos-lib'
|
|
58
|
+
*
|
|
59
|
+
* const milkyWay = STAR_TEXTURES['milky_way']
|
|
60
|
+
* console.log(milkyWay.credit) // 'ESO/S. Brunier'
|
|
61
|
+
* console.log(milkyWay.license) // 'CC-BY'
|
|
62
|
+
*
|
|
63
|
+
* const starField = STAR_TEXTURES['star_field']
|
|
64
|
+
* console.log(starField.width) // 8192
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare const STAR_TEXTURES: Readonly<Record<string, TextureInfo>>;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Describes a predicted eclipse event, returned by the {@link Eclipse} search methods.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* The `magnitude` field represents the fraction of the Sun's (solar eclipse) or
|
|
6
|
+
* Moon's (lunar eclipse) diameter covered at maximum eclipse. A magnitude of 1.0
|
|
7
|
+
* indicates a total eclipse; values between 0 and 1 indicate partial coverage.
|
|
8
|
+
* For annular solar eclipses, the magnitude equals the ratio of the Moon's
|
|
9
|
+
* apparent diameter to the Sun's apparent diameter.
|
|
10
|
+
*/
|
|
11
|
+
export interface EclipseEvent {
|
|
12
|
+
/** Whether this is a `'solar'` or `'lunar'` eclipse. */
|
|
13
|
+
type: 'solar' | 'lunar';
|
|
14
|
+
/** Eclipse subtype: `'total'`, `'annular'`, `'partial'`, or `'penumbral'` (lunar only). */
|
|
15
|
+
subtype: 'total' | 'annular' | 'partial' | 'penumbral';
|
|
16
|
+
/** Date and time of maximum eclipse (approximate). */
|
|
17
|
+
date: Date;
|
|
18
|
+
/** Eclipse magnitude: fraction of diameter covered at maximum (0 to 1+). */
|
|
19
|
+
magnitude: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Eclipse prediction using a simplified Besselian approach.
|
|
23
|
+
*
|
|
24
|
+
* Checks for eclipses near new moons (solar) and full moons (lunar) by
|
|
25
|
+
* computing the angular separation between the Sun and Moon and comparing
|
|
26
|
+
* it against their apparent angular radii. Solar eclipses are classified
|
|
27
|
+
* as total, annular, or partial; lunar eclipses as total, partial, or
|
|
28
|
+
* penumbral.
|
|
29
|
+
*
|
|
30
|
+
* @remarks
|
|
31
|
+
* Based on Jean Meeus, "Astronomical Algorithms" (2nd ed.), Chapters 54-55.
|
|
32
|
+
* This is a simplified geometric approach that does not perform a full
|
|
33
|
+
* Besselian element calculation. It iterates over lunations (new moons for
|
|
34
|
+
* solar eclipses, full moons for lunar eclipses) and tests whether the
|
|
35
|
+
* Moon's ecliptic latitude is small enough for an eclipse to occur.
|
|
36
|
+
*
|
|
37
|
+
* Accuracy is sufficient for predicting whether an eclipse occurs and its
|
|
38
|
+
* approximate type and magnitude, but not for computing local circumstances
|
|
39
|
+
* (contact times, path of totality, etc.).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { Eclipse } from '@motioncomplex/cosmos-lib'
|
|
44
|
+
*
|
|
45
|
+
* // Find the next solar eclipse after the 2024 vernal equinox
|
|
46
|
+
* const solar = Eclipse.nextSolar(new Date('2024-03-20'))
|
|
47
|
+
* if (solar) {
|
|
48
|
+
* console.log(`${solar.subtype} solar eclipse on ${solar.date.toISOString()}`)
|
|
49
|
+
* console.log(`Magnitude: ${solar.magnitude.toFixed(3)}`)
|
|
50
|
+
* }
|
|
51
|
+
*
|
|
52
|
+
* // Search for all eclipses in 2024
|
|
53
|
+
* const eclipses = Eclipse.search(
|
|
54
|
+
* new Date('2024-01-01'),
|
|
55
|
+
* new Date('2025-01-01'),
|
|
56
|
+
* )
|
|
57
|
+
* eclipses.forEach(e => console.log(`${e.type} ${e.subtype} — ${e.date.toISOString()}`))
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare const Eclipse: {
|
|
61
|
+
/**
|
|
62
|
+
* Find the next solar eclipse after the given date.
|
|
63
|
+
*
|
|
64
|
+
* Iterates through upcoming new moons (up to 26 lunations, approximately
|
|
65
|
+
* 2 years) and checks each one for a solar eclipse condition.
|
|
66
|
+
*
|
|
67
|
+
* @param date - Start date from which to search forward. Defaults to the current date/time.
|
|
68
|
+
* @returns An {@link EclipseEvent} describing the next solar eclipse, or `null` if none is found within approximately 2 years.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { Eclipse } from '@motioncomplex/cosmos-lib'
|
|
73
|
+
*
|
|
74
|
+
* const next = Eclipse.nextSolar(new Date('2024-03-20'))
|
|
75
|
+
* if (next) {
|
|
76
|
+
* console.log(`Next solar eclipse: ${next.subtype} on ${next.date.toISOString()}`)
|
|
77
|
+
* console.log(`Magnitude: ${next.magnitude.toFixed(3)}`)
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
readonly nextSolar: (date?: Date) => EclipseEvent | null;
|
|
82
|
+
/**
|
|
83
|
+
* Find the next lunar eclipse after the given date.
|
|
84
|
+
*
|
|
85
|
+
* Iterates through upcoming full moons (up to 26 lunations, approximately
|
|
86
|
+
* 2 years) and checks each one for a lunar eclipse condition.
|
|
87
|
+
*
|
|
88
|
+
* @param date - Start date from which to search forward. Defaults to the current date/time.
|
|
89
|
+
* @returns An {@link EclipseEvent} describing the next lunar eclipse, or `null` if none is found within approximately 2 years.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* import { Eclipse } from '@motioncomplex/cosmos-lib'
|
|
94
|
+
*
|
|
95
|
+
* const next = Eclipse.nextLunar(new Date('2024-03-20'))
|
|
96
|
+
* if (next) {
|
|
97
|
+
* console.log(`Next lunar eclipse: ${next.subtype} on ${next.date.toISOString()}`)
|
|
98
|
+
* console.log(`Magnitude: ${next.magnitude.toFixed(3)}`)
|
|
99
|
+
* }
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
readonly nextLunar: (date?: Date) => EclipseEvent | null;
|
|
103
|
+
/**
|
|
104
|
+
* Search for all eclipses in a date range.
|
|
105
|
+
*
|
|
106
|
+
* Scans the interval from `startDate` to `endDate` in steps of approximately
|
|
107
|
+
* 15 days, checking both new moons (solar) and full moons (lunar) for eclipse
|
|
108
|
+
* conditions. Results are sorted chronologically and deduplicated (eclipses
|
|
109
|
+
* found within 1 day of each other are treated as the same event).
|
|
110
|
+
*
|
|
111
|
+
* @remarks
|
|
112
|
+
* The search advances by 15-day increments to ensure both new and full moons
|
|
113
|
+
* within each lunation are tested. When `type` is specified, only that eclipse
|
|
114
|
+
* type is checked, improving performance for targeted searches. Deduplication
|
|
115
|
+
* uses a 1-day threshold to handle cases where the same eclipse is detected
|
|
116
|
+
* from adjacent search windows.
|
|
117
|
+
*
|
|
118
|
+
* @param startDate - The beginning of the search window (inclusive).
|
|
119
|
+
* @param endDate - The end of the search window (exclusive).
|
|
120
|
+
* @param type - Optional filter: `'solar'` to search only for solar eclipses, `'lunar'` for only lunar eclipses, or omit for both.
|
|
121
|
+
* @returns An array of {@link EclipseEvent} objects sorted by date, with duplicates removed.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```ts
|
|
125
|
+
* import { Eclipse } from '@motioncomplex/cosmos-lib'
|
|
126
|
+
*
|
|
127
|
+
* // Find all eclipses in 2024
|
|
128
|
+
* const all = Eclipse.search(new Date('2024-01-01'), new Date('2025-01-01'))
|
|
129
|
+
* console.log(`Found ${all.length} eclipses in 2024`)
|
|
130
|
+
* all.forEach(e => console.log(`${e.type} ${e.subtype} — ${e.date.toISOString()}`))
|
|
131
|
+
*
|
|
132
|
+
* // Only solar eclipses in a 5-year span
|
|
133
|
+
* const solar = Eclipse.search(
|
|
134
|
+
* new Date('2024-01-01'),
|
|
135
|
+
* new Date('2029-01-01'),
|
|
136
|
+
* 'solar',
|
|
137
|
+
* )
|
|
138
|
+
* solar.forEach(e => console.log(`${e.subtype} solar eclipse: ${e.date.toISOString()}`))
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
readonly search: (startDate: Date, endDate: Date, type?: "solar" | "lunar") => EclipseEvent[];
|
|
142
|
+
/**
|
|
143
|
+
* Check if a new moon produces a solar eclipse.
|
|
144
|
+
*
|
|
145
|
+
* Computes the Moon's ecliptic latitude and angular separation from the Sun
|
|
146
|
+
* at the instant of new moon. If the Moon is within 1.5° of the ecliptic plane
|
|
147
|
+
* and the angular separation is less than 1.5 times the sum of the apparent
|
|
148
|
+
* solar and lunar radii, an eclipse is predicted. The subtype (total, annular,
|
|
149
|
+
* or partial) is determined by comparing the apparent radii and the separation.
|
|
150
|
+
*
|
|
151
|
+
* @internal
|
|
152
|
+
* @param newMoon - The date/time of the new moon to test.
|
|
153
|
+
* @returns An {@link EclipseEvent} if a solar eclipse occurs at this new moon, or `null` otherwise.
|
|
154
|
+
*/
|
|
155
|
+
readonly _checkSolarEclipse: (newMoon: Date) => EclipseEvent | null;
|
|
156
|
+
/**
|
|
157
|
+
* Check if a full moon produces a lunar eclipse.
|
|
158
|
+
*
|
|
159
|
+
* Computes the Moon's ecliptic latitude at the instant of full moon and
|
|
160
|
+
* compares it against the angular radii of Earth's umbral and penumbral
|
|
161
|
+
* shadow cones at the Moon's distance. The subtype (total, partial, or
|
|
162
|
+
* penumbral) is determined by where the Moon's latitude falls relative
|
|
163
|
+
* to the umbral and penumbral boundaries.
|
|
164
|
+
*
|
|
165
|
+
* @remarks
|
|
166
|
+
* The umbral cone angular radius is approximated as 2.6 times the Earth's
|
|
167
|
+
* angular radius at the Moon's distance, and the penumbral cone as 4.3 times.
|
|
168
|
+
* These are simplified multipliers; a full calculation would use solar parallax
|
|
169
|
+
* and Earth's atmospheric extension.
|
|
170
|
+
*
|
|
171
|
+
* @internal
|
|
172
|
+
* @param fullMoon - The date/time of the full moon to test.
|
|
173
|
+
* @returns An {@link EclipseEvent} if a lunar eclipse occurs at this full moon, or `null` otherwise.
|
|
174
|
+
*/
|
|
175
|
+
readonly _checkLunarEclipse: (fullMoon: Date) => EclipseEvent | null;
|
|
176
|
+
};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const t=require("./skymap-interactive-D2OZFwJ7.cjs"),O=require("./media-DlE7RKBL.cjs"),N={auToKm:e=>e*t.CONSTANTS.AU_TO_KM,kmToAu:e=>e/t.CONSTANTS.AU_TO_KM,lyToPc:e=>e/t.CONSTANTS.PC_TO_LY,pcToLy:e=>e*t.CONSTANTS.PC_TO_LY,pcToKm:e=>e*t.CONSTANTS.PC_TO_KM,lyToKm:e=>e*t.CONSTANTS.LY_TO_KM,kmToLy:e=>e/t.CONSTANTS.LY_TO_KM,degToRad:e=>e*t.CONSTANTS.DEG_TO_RAD,radToDeg:e=>e*t.CONSTANTS.RAD_TO_DEG,arcsecToDeg:e=>e/3600,degToArcsec:e=>e*3600,hrsToDeg:e=>e*15,degToHrs:e=>e/15,formatDistance(e){const o=e/t.CONSTANTS.AU_TO_KM;if(o<.01)return`${e.toFixed(0)} km`;if(o<1e3)return`${o.toPrecision(4)} AU`;const i=e/t.CONSTANTS.LY_TO_KM;return i<1e6?`${i.toPrecision(4)} ly`:`${(i/1e6).toPrecision(4)} Mly`},formatAngle(e){const o=e<0?"-":"",i=Math.abs(e),r=Math.floor(i),s=Math.floor((i-r)*60),c=((i-r)*60-s)*60;return`${o}${r}°${s}′${c.toFixed(1)}″`},formatRA(e){const o=(e%360+360)%360,i=Math.floor(o/15),r=Math.floor((o/15-i)*60),s=((o/15-i)*60-r)*60;return`${i}h ${r}m ${s.toFixed(1)}s`}},C={nextSolar(e=new Date){let o=new Date(e);for(let i=0;i<26;i++){const r=t.Moon.nextPhase(o,"new"),s=this._checkSolarEclipse(r);if(s)return s;o=new Date(r.valueOf()+864e5)}return null},nextLunar(e=new Date){let o=new Date(e);for(let i=0;i<26;i++){const r=t.Moon.nextPhase(o,"full"),s=this._checkLunarEclipse(r);if(s)return s;o=new Date(r.valueOf()+864e5)}return null},search(e,o,i){const r=[];let s=new Date(e);const c=o.valueOf();for(;s.valueOf()<c;){if(i!=="lunar"){const n=t.Moon.nextPhase(s,"new");if(n.valueOf()>c)break;const a=this._checkSolarEclipse(n);a&&r.push(a)}if(i!=="solar"){const n=t.Moon.nextPhase(s,"full");if(n.valueOf()<=c){const a=this._checkLunarEclipse(n);a&&r.push(a)}}s=new Date(s.valueOf()+15*864e5)}return r.sort((n,a)=>n.date.valueOf()-a.date.valueOf()),r.filter((n,a)=>a===0||Math.abs(n.date.valueOf()-r[a-1].date.valueOf())>864e5)},_checkSolarEclipse(e){const o=t.Moon.position(e),i=t.AstroMath.planetEcliptic("earth",e),r=((i.lon+180)%360+360)%360;if(Math.abs(o.eclipticLat)>1.5)return null;const c=i.r*1495978707e-1,n=Math.atan2(696e3,c)*(180/Math.PI),a=Math.atan2(1737.4,o.distance_km)*(180/Math.PI),u=t.AstroMath.angularSeparation(o,t.AstroMath.eclipticToEquatorial({lon:r,lat:0})),m=n+a;if(u>m*1.5)return null;let d,l;if(a>=n&&u<a-n)d="total",l=1;else if(a<n&&u<n-a)d="annular",l=a/n;else if(u<m)d="partial",l=(m-u)/(2*n);else return null;return{type:"solar",subtype:d,date:e,magnitude:l}},_checkLunarEclipse(e){const o=t.Moon.position(e),i=Math.abs(o.eclipticLat),r=Math.atan2(6371,o.distance_km)*(180/Math.PI),s=r*2.6,c=r*4.3,n=Math.atan2(1737.4,o.distance_km)*(180/Math.PI);if(i>c+n)return null;let a,u;if(i<s-n)a="total",u=(s-i)/(2*n);else if(i<s+n)a="partial",u=(s+n-i)/(2*n);else if(i<c+n)a="penumbral",u=(c+n-i)/(2*n);else return null;return{type:"lunar",subtype:a,date:e,magnitude:Math.min(u,1)}}},L={sun:{id:"sun",name:"Sun Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/b/b4/The_Sun_by_the_Atmospheric_Imaging_Assembly_of_NASA%27s_Solar_Dynamics_Observatory_-_20100819.jpg"],credit:"NASA/SDO (AIA)",license:"public-domain",width:4096,height:4096},mercury:{id:"mercury",name:"Mercury Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/9/92/Solarsystemscope_texture_2k_mercury.jpg"],credit:"NASA/Johns Hopkins APL/Carnegie Institution",license:"public-domain",width:2048,height:1024},venus:{id:"venus",name:"Venus Surface (Radar)",urls:["https://upload.wikimedia.org/wikipedia/commons/1/16/Solarsystemscope_texture_2k_venus_surface.jpg"],credit:"NASA/JPL-Caltech",license:"public-domain",width:2048,height:1024},venus_atmosphere:{id:"venus_atmosphere",name:"Venus Atmosphere",urls:["https://upload.wikimedia.org/wikipedia/commons/7/72/Solarsystemscope_texture_2k_venus_atmosphere.jpg"],credit:"NASA/JPL-Caltech",license:"public-domain",width:2048,height:1024},earth:{id:"earth",name:"Earth Blue Marble",urls:["https://upload.wikimedia.org/wikipedia/commons/0/04/Solarsystemscope_texture_8k_earth_daymap.jpg","https://upload.wikimedia.org/wikipedia/commons/2/23/Blue_Marble_2002.png"],credit:"NASA Visible Earth",license:"public-domain",width:8192,height:4096},earth_night:{id:"earth_night",name:"Earth Night Lights",urls:["https://upload.wikimedia.org/wikipedia/commons/b/ba/Solarsystemscope_texture_8k_earth_nightmap.jpg"],credit:"NASA Earth Observatory",license:"public-domain",width:8192,height:4096},earth_clouds:{id:"earth_clouds",name:"Earth Clouds",urls:["https://upload.wikimedia.org/wikipedia/commons/9/9d/Solarsystemscope_texture_8k_earth_clouds.jpg"],credit:"NASA Visible Earth",license:"public-domain",width:8192,height:4096},moon:{id:"moon",name:"Moon Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/a/a8/Solarsystemscope_texture_8k_moon.jpg"],credit:"NASA/GSFC/Arizona State University (LROC)",license:"public-domain",width:8192,height:4096},mars:{id:"mars",name:"Mars Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/f/fe/Solarsystemscope_texture_8k_mars.jpg"],credit:"NASA/JPL-Caltech (MOLA)",license:"public-domain",width:8192,height:4096},jupiter:{id:"jupiter",name:"Jupiter Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/4/48/Solarsystemscope_texture_8k_jupiter.jpg"],credit:"NASA/JPL-Caltech (Cassini/Juno)",license:"public-domain",width:8192,height:4096},saturn:{id:"saturn",name:"Saturn Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/e/ea/Solarsystemscope_texture_8k_saturn.jpg"],credit:"NASA/JPL-Caltech (Cassini)",license:"public-domain",width:8192,height:4096},saturn_ring:{id:"saturn_ring",name:"Saturn Ring",urls:["https://upload.wikimedia.org/wikipedia/commons/1/1e/Solarsystemscope_texture_2k_saturn_ring_alpha.png"],credit:"NASA/JPL-Caltech (Cassini)",license:"public-domain",width:2048,height:64},uranus:{id:"uranus",name:"Uranus Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/9/95/Solarsystemscope_texture_2k_uranus.jpg"],credit:"NASA/JPL-Caltech (Voyager)",license:"public-domain",width:2048,height:1024},neptune:{id:"neptune",name:"Neptune Surface",urls:["https://upload.wikimedia.org/wikipedia/commons/1/1e/Solarsystemscope_texture_2k_neptune.jpg"],credit:"NASA/JPL-Caltech (Voyager)",license:"public-domain",width:2048,height:1024}},P={milky_way:{id:"milky_way",name:"Milky Way Panorama",urls:["https://upload.wikimedia.org/wikipedia/commons/4/43/ESO_-_Milky_Way.jpg"],credit:"ESO/S. Brunier",license:"CC-BY",width:9e3,height:3600},star_field:{id:"star_field",name:"Star Field Background",urls:["https://upload.wikimedia.org/wikipedia/commons/8/80/Solarsystemscope_texture_8k_stars.jpg"],credit:"NASA/Goddard Space Flight Center",license:"public-domain",width:8192,height:4096}};async function T(e,o={}){const{duration:i=400,easing:r="ease-in-out",signal:s}=o;if(s!=null&&s.aborted)return;if(!("startViewTransition"in document)){await e();return}document.documentElement.style.setProperty("--cosmos-vt-duration",`${i}ms`),document.documentElement.style.setProperty("--cosmos-vt-easing",r),await document.startViewTransition(e).finished}function k(e,o={}){const{delay:i=0,stagger:r=60,duration:s=500,from:c="bottom",distance:n="20px",signal:a}=o;if(a!=null&&a.aborted)return Promise.resolve();const m={top:`translateY(-${n})`,bottom:`translateY(${n})`,left:`translateX(-${n})`,right:`translateX(${n})`}[c],d=[...e.children];return d.forEach(l=>{l.style.opacity="0",l.style.transform=m,l.style.transition="none"}),d.length===0?Promise.resolve():new Promise(l=>{const f=performance.now()+i,p=()=>{d.forEach(S=>{S.style.opacity="1",S.style.transform="none",S.style.transition=""}),l()};a==null||a.addEventListener("abort",p,{once:!0});const h=S=>{if(a!=null&&a.aborted)return;let _=!0;for(let A=0;A<d.length;A++){const y=f+A*r;if(S>=y){const w=d[A];w.style.opacity==="0"&&(w.style.transition=`opacity ${s}ms ease, transform ${s}ms cubic-bezier(0.2,0,0,1)`,w.style.opacity="1",w.style.transform="none"),S<y+s&&(_=!1)}else _=!1}_?(a==null||a.removeEventListener("abort",p),l()):requestAnimationFrame(h)};requestAnimationFrame(()=>requestAnimationFrame(h))})}function E(e,o={}){const{stagger:i=40,duration:r=300,from:s="bottom",distance:c="12px",signal:n}=o;if(n!=null&&n.aborted)return Promise.resolve();const u={top:`translateY(-${c})`,bottom:`translateY(${c})`,left:`translateX(-${c})`,right:`translateX(${c})`}[s],m=[...e.children].reverse();return m.length===0?Promise.resolve():new Promise(d=>{const l=performance.now(),f=()=>{m.forEach(h=>{h.style.opacity="0",h.style.transform=u,h.style.transition=""}),d()};n==null||n.addEventListener("abort",f,{once:!0});const p=h=>{if(n!=null&&n.aborted)return;let S=!0;for(let _=0;_<m.length;_++){const A=l+_*i;if(h>=A){const y=m[_];y.style.opacity!=="0"&&(y.style.transition=`opacity ${r}ms ease, transform ${r}ms ease`,y.style.opacity="0",y.style.transform=u),h<A+r&&(S=!1)}else S=!1}S?(n==null||n.removeEventListener("abort",f),d()):requestAnimationFrame(p)};requestAnimationFrame(p)})}function g(e,o,i=300){return new Promise(r=>{e.style.transition=`opacity ${i}ms ease`,e.style.opacity=o==="in"?"1":"0",e.style.pointerEvents=o==="in"?"auto":"none";const s=()=>{e.removeEventListener("transitionend",s),r()};e.addEventListener("transitionend",s,{once:!0}),setTimeout(r,i+50)})}async function M(e,o,i=400){o.style.opacity="0",o.style.pointerEvents="none",o.style.display="",await Promise.all([g(e,"out",i),g(o,"in",i)]),e.style.display="none"}function b(e,o={}){const{duration:i=500,easing:r="cubic-bezier(0.4,0,0.2,1)",onDone:s,signal:c}=o;if(c!=null&&c.aborted)return;const n=e.getBoundingClientRect(),a=window.innerWidth/n.width,u=window.innerHeight/n.height,m=window.innerWidth/2-(n.left+n.width/2),d=window.innerHeight/2-(n.top+n.height/2);e.style.transformOrigin="center center",e.style.transition="none",e.style.transform="translate(0,0) scale(1,1)",requestAnimationFrame(()=>{c!=null&&c.aborted||requestAnimationFrame(()=>{if(c!=null&&c.aborted)return;e.style.transition=`transform ${i}ms ${r}`,e.style.transform=`translate(${m}px, ${d}px) scale(${a}, ${u})`;const l=()=>{e.removeEventListener("transitionend",l),e.style.transform="",e.style.transition="",s==null||s()};e.addEventListener("transitionend",l,{once:!0}),setTimeout(l,i+100)})})}function v(e,o={},i){const{duration:r=400,easing:s="cubic-bezier(0.4,0,0.2,1)",onDone:c,signal:n}=o;if(n!=null&&n.aborted)return;const a=e.getBoundingClientRect(),u=a.width/window.innerWidth,m=a.height/window.innerHeight,d=a.left+a.width/2-window.innerWidth/2,l=a.top+a.height/2-window.innerHeight/2,f=!i,p=i??document.createElement("div");f&&(Object.assign(p.style,{position:"fixed",inset:"0",pointerEvents:"none",zIndex:"9999",transformOrigin:"center center"}),document.body.appendChild(p)),p.style.transition=`transform ${r}ms ${s}, opacity ${r*.6}ms ease ${r*.4}ms`;const h=()=>{p.removeEventListener("transitionend",h),f&&p.remove(),c==null||c()};requestAnimationFrame(()=>{if(n!=null&&n.aborted){h();return}p.style.transform=`translate(${d}px, ${l}px) scale(${u}, ${m})`,p.style.opacity="0",p.addEventListener("transitionend",h,{once:!0}),setTimeout(h,r+100)})}const $={morph:T,staggerIn:k,staggerOut:E,fade:g,crossfade:M,heroExpand:b,heroCollapse:v},I={CONSTANTS:t.CONSTANTS,Units:N,Math:t.AstroMath,Sun:t.Sun,Moon:t.Moon,Eclipse:C,Planner:t.Planner,AstroClock:t.AstroClock,Data:t.Data,Media:O.Media,API:{NASA:t.NASA,ESA:t.ESA,resolveSimbad:t.resolveSimbad},SkyMap:{render:t.renderSkyMap,stereographic:t.stereographic,mollweide:t.mollweide,gnomonic:t.gnomonic,Interactive:t.InteractiveSkyMap,create:t.createInteractiveSkyMap},Transitions:{morph:T,staggerIn:k,staggerOut:E,fade:g,crossfade:M,heroExpand:b,heroCollapse:v}};exports.AstroClock=t.AstroClock;exports.AstroMath=t.AstroMath;exports.BRIGHT_STARS=t.BRIGHT_STARS;exports.CONSTANTS=t.CONSTANTS;exports.CONSTELLATIONS=t.CONSTELLATIONS;exports.DEEP_SKY_EXTRAS=t.DEEP_SKY_EXTRAS;exports.Data=t.Data;exports.ESA=t.ESA;exports.IMAGE_FALLBACKS=t.IMAGE_FALLBACKS;exports.InteractiveSkyMap=t.InteractiveSkyMap;exports.MESSIER_CATALOG=t.MESSIER_CATALOG;exports.METEOR_SHOWERS=t.METEOR_SHOWERS;exports.Moon=t.Moon;exports.NASA=t.NASA;exports.Planner=t.Planner;exports.SOLAR_SYSTEM=t.SOLAR_SYSTEM;exports.SkyMap=t.SkyMap;exports.Sun=t.Sun;exports.canvasToEquatorial=t.canvasToEquatorial;exports.computeFov=t.computeFov;exports.createInteractiveSkyMap=t.createInteractiveSkyMap;exports.getObjectImage=t.getObjectImage;exports.gnomonic=t.gnomonic;exports.mollweide=t.mollweide;exports.prefetchImages=t.prefetchImages;exports.renderSkyMap=t.renderSkyMap;exports.resolveImages=t.resolveImages;exports.resolveSimbad=t.resolveSimbad;exports.spectralColor=t.spectralColor;exports.stereographic=t.stereographic;exports.tryDSS=t.tryDSS;exports.tryPanSTARRS=t.tryPanSTARRS;exports.Media=O.Media;exports.Eclipse=C;exports.PLANET_TEXTURES=L;exports.STAR_TEXTURES=P;exports.Transitions=$;exports.Units=N;exports.crossfade=M;exports.default=I;exports.fade=g;exports.heroCollapse=v;exports.heroExpand=b;exports.morph=T;exports.staggerIn=k;exports.staggerOut=E;
|