@elite-dangerous-almanac/core 0.2.1 → 0.2.2
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 +3 -2
- package/THIRD_PARTY_NOTICES.md +24 -2
- package/dist/astro/body-orbit.d.ts +174 -0
- package/dist/astro/body-orbit.js +1 -0
- package/dist/astro/body-orbit.js.map +1 -0
- package/dist/astro/body-physics.d.ts +228 -0
- package/dist/astro/body-physics.js +1 -0
- package/dist/astro/body-physics.js.map +1 -0
- package/dist/astro/body-rings.d.ts +223 -0
- package/dist/astro/body-rings.js +1 -0
- package/dist/astro/body-rings.js.map +1 -0
- package/dist/astro/codex-region-lookup.js +1 -1
- package/dist/astro/codex-region-lookup.js.map +1 -1
- package/dist/astro/index.d.ts +38 -1
- package/dist/astro/index.js +1 -1
- package/dist/astro/nebulae.d.ts +4 -4
- package/dist/astro/procedural-system.js +1 -1
- package/dist/astro/star-physics.d.ts +255 -0
- package/dist/astro/star-physics.js +1 -0
- package/dist/astro/star-physics.js.map +1 -0
- package/dist/body-scan-CEUYjCfH.d.ts +416 -0
- package/dist/{chunk-HUYYGTRM.js → chunk-3LZXB2MC.js} +1 -1
- package/dist/chunk-3RTUSDQF.js +1 -0
- package/dist/chunk-3RTUSDQF.js.map +1 -0
- package/dist/chunk-4OTQBHQL.js +1 -0
- package/dist/chunk-4OTQBHQL.js.map +1 -0
- package/dist/{chunk-MRTTQYT5.js → chunk-7EWZGDWY.js} +1 -1
- package/dist/{chunk-TBZJIQ5P.js → chunk-7TVFV3VO.js} +1 -1
- package/dist/chunk-7TVFV3VO.js.map +1 -0
- package/dist/chunk-7ZERP4TB.js +1 -0
- package/dist/{chunk-APEG4ZER.js.map → chunk-7ZERP4TB.js.map} +1 -1
- package/dist/chunk-B5VTFOK4.js +1 -0
- package/dist/chunk-B5VTFOK4.js.map +1 -0
- package/dist/chunk-DAQ3PJ4R.js +1 -0
- package/dist/chunk-DAQ3PJ4R.js.map +1 -0
- package/dist/chunk-GBTCWNO6.js +1 -0
- package/dist/chunk-GBTCWNO6.js.map +1 -0
- package/dist/chunk-NEXDA73Y.js +1 -0
- package/dist/chunk-NEXDA73Y.js.map +1 -0
- package/dist/chunk-P2MUFVJC.js +1 -0
- package/dist/chunk-P2MUFVJC.js.map +1 -0
- package/dist/{chunk-AAE4KZ2V.js → chunk-SS6XK336.js} +1 -1
- package/dist/{chunk-AAE4KZ2V.js.map → chunk-SS6XK336.js.map} +1 -1
- package/dist/chunk-TMXKC6JL.js +1 -0
- package/dist/chunk-TMXKC6JL.js.map +1 -0
- package/dist/chunk-ZZ376WHL.js +1 -0
- package/dist/chunk-ZZ376WHL.js.map +1 -0
- package/dist/commodities/commodities.d.ts +1 -1
- package/dist/equipment/index.js +1 -1
- package/dist/equipment/upgrade-costs.js +1 -1
- package/dist/equipment/upgrade-costs.js.map +1 -1
- package/dist/i18n/index.js +1 -1
- package/dist/materials/index.js +1 -1
- package/dist/materials/materials.d.ts +1 -1
- package/dist/materials/micro-resources-all.js +1 -1
- package/dist/materials/micro-resources.d.ts +1 -1
- package/dist/materials/micro-resources.js +1 -1
- package/dist/ships/build-metrics.d.ts +21 -232
- package/dist/ships/build-metrics.js +1 -1
- package/dist/ships/distributor.d.ts +1 -1
- package/dist/ships/heat.d.ts +1 -1
- package/dist/ships/index.d.ts +2 -2
- package/dist/ships/index.js +1 -1
- package/dist/ships/loadout-calculations.d.ts +2 -2
- package/dist/ships/mobility-capacitor.d.ts +1 -1
- package/dist/ships/modules-all.js +1 -1
- package/dist/ships/modules.d.ts +1 -1
- package/dist/ships/modules.js +1 -1
- package/dist/ships/pre-engineered-stats.d.ts +7 -5
- package/dist/ships/pre-engineered-stats.js +1 -1
- package/dist/ships/shield-capacitor.d.ts +1 -1
- package/dist/ships/shields.d.ts +1 -1
- package/dist/ships/ship-loadout.d.ts +71 -16
- package/dist/ships/ship-loadout.js +1 -1
- package/package.json +18 -3
- package/dist/chunk-6S36AVA4.js +0 -1
- package/dist/chunk-6S36AVA4.js.map +0 -1
- package/dist/chunk-APEG4ZER.js +0 -1
- package/dist/chunk-GVNTKCVF.js +0 -1
- package/dist/chunk-GVNTKCVF.js.map +0 -1
- package/dist/chunk-JET673E5.js +0 -1
- package/dist/chunk-JET673E5.js.map +0 -1
- package/dist/chunk-SG6YLUQ4.js +0 -1
- package/dist/chunk-SG6YLUQ4.js.map +0 -1
- package/dist/chunk-TBZJIQ5P.js.map +0 -1
- /package/dist/{chunk-HUYYGTRM.js.map → chunk-3LZXB2MC.js.map} +0 -0
- /package/dist/{chunk-MRTTQYT5.js.map → chunk-7EWZGDWY.js.map} +0 -0
package/README.md
CHANGED
|
@@ -45,7 +45,8 @@ coordinate lookup are only exported from their leaf subpaths, not the feature ba
|
|
|
45
45
|
|
|
46
46
|
The package has six feature areas:
|
|
47
47
|
|
|
48
|
-
- `astro`: procedural names, id64 addresses, regions, nebulae
|
|
48
|
+
- `astro`: procedural names, id64 addresses, regions, nebulae, permit locks, and scanned
|
|
49
|
+
bodies with their physics;
|
|
49
50
|
- `ships`: ships, modules, SLEF loadouts, engineering and build metrics;
|
|
50
51
|
- `equipment`: Odyssey suits, handheld weapons, grade upgrades and modifications;
|
|
51
52
|
- `i18n`: sparse localized catalogue names, descriptions, slot labels and structured
|
|
@@ -120,7 +121,7 @@ const build = ShipLoadout.fromSlef(slefJsonString);
|
|
|
120
121
|
const metrics = BuildMetrics.of(build);
|
|
121
122
|
metrics.maxJumpRange();
|
|
122
123
|
metrics.powerBudget();
|
|
123
|
-
metrics.
|
|
124
|
+
metrics.shieldMetricsResult().value;
|
|
124
125
|
metrics.armourMetrics();
|
|
125
126
|
metrics.weaponMetrics();
|
|
126
127
|
metrics.weaponsCapacitorMetrics({ weaponsPips: 2 });
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -61,6 +61,28 @@ a verbatim copy produced at build time — edit this file, never the copy.
|
|
|
61
61
|
- **SLEF parsing and writing** — both follow the
|
|
62
62
|
[Inara Ship Loadout Export Format specification](https://inara.cz/elite/inara-impexp-slef/)
|
|
63
63
|
published by **Inara** (Artie).
|
|
64
|
+
- **Body calculations** — bulk density, the rigid and fluid Roche limits, the Hill radius,
|
|
65
|
+
a primary's angular diameter, orbit extents and their eccentricity bands, spin-orbit
|
|
66
|
+
resonance, equatorial velocity, ring dynamics and surface density, the invisible-ring
|
|
67
|
+
heuristic, ring-particle densities, main-sequence lifetime, absolute bolometric
|
|
68
|
+
magnitude, the Schwarzschild radius, the degeneracy-pressure mass limits and the
|
|
69
|
+
neutron-star classes are ported as fact (our own implementation, re-expressed in the
|
|
70
|
+
journal's units) from **canonn-signals**' `body-physics.service.ts`,
|
|
71
|
+
`stellar-physics.service.ts` and `stellar-reference.ts` — credited under Data below.
|
|
72
|
+
Most of it is textbook astrophysics; three parts are the **Canonn Research Group's own
|
|
73
|
+
observational research** into how the game behaves, and are theirs rather than
|
|
74
|
+
astronomy's: the `3/8` nominal-radius factor that recovers a ring's single rigid-body
|
|
75
|
+
rotation period, the invisible-ring width and surface-density thresholds, and the
|
|
76
|
+
neutron-star classification bands with the observed in-game mass past which neutron
|
|
77
|
+
stars become rare.
|
|
78
|
+
Each carries that provenance in its own TSDoc.
|
|
79
|
+
- **The journal `Scan` event shape** — the body-scan import interface describes the format
|
|
80
|
+
**Frontier Developments plc** writes its Player Journal in, and its field set, types and
|
|
81
|
+
conditional presence are cross-checked against
|
|
82
|
+
[jixxed/ed-journal-schemas](https://github.com/jixxed/ed-journal-schemas), the
|
|
83
|
+
community-maintained JSON Schemas for post-Odyssey journal events, **Apache-2.0**.
|
|
84
|
+
Field names and types are facts about Frontier's format; no schema text is redistributed
|
|
85
|
+
and no code from that project is used.
|
|
64
86
|
|
|
65
87
|
## Data
|
|
66
88
|
|
|
@@ -101,8 +123,8 @@ a verbatim copy produced at build time — edit this file, never the copy.
|
|
|
101
123
|
[Frontier forums](https://forums.frontier.co.uk/threads/determining-the-region-of-a-system.537845/).
|
|
102
124
|
- **[canonn-science/canonn-signals](https://github.com/canonn-science/canonn-signals)** by
|
|
103
125
|
the **Canonn Research Group**, **MIT**, © 2023 — the route by which two of the sources
|
|
104
|
-
below were obtained,
|
|
105
|
-
|
|
126
|
+
below were obtained, the TypeScript port the procedural-naming algorithm passed through,
|
|
127
|
+
and the source of the body calculations credited under Algorithms above.
|
|
106
128
|
- **EDAstro nebulae coordinates** published by **CMDR Orvidius**
|
|
107
129
|
([EDAstro](https://edastro.com/mapcharts/)) — nebula names, catalogued systems,
|
|
108
130
|
coordinates, classes and region ids, obtained via canonn-signals. EDAstro states no
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { b as BodyProperties } from '../body-scan-CEUYjCfH.js';
|
|
2
|
+
import './system-address-input.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* What a scanned body's orbit and spin work out to: where the orbit actually reaches, how
|
|
6
|
+
* eccentric it is, whether the spin is locked to the orbit, and how fast the surface moves.
|
|
7
|
+
*
|
|
8
|
+
* Every function takes {@link BodyProperties} — a journal `Scan` line as it comes, or any
|
|
9
|
+
* record carrying the same fields — and works in the journal's own units: metres for
|
|
10
|
+
* distance, seconds for a period, degrees for an angle. Nothing here holds data. The type
|
|
11
|
+
* itself is exported from `../astro`, alongside `BodyScanEvent`.
|
|
12
|
+
*
|
|
13
|
+
* These read the body's own fields only, so none of them needs the primary.
|
|
14
|
+
*
|
|
15
|
+
* The maths is ported from the Canonn Research Group's
|
|
16
|
+
* [canonn-signals](https://github.com/canonn-science/canonn-signals); see
|
|
17
|
+
* [ATTRIBUTIONS.md](https://github.com/DarkSession/Elite-Dangerous-Almanac/blob/main/ATTRIBUTIONS.md).
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { orbitExtents } from '@elite-dangerous-almanac/core/astro/body-orbit';
|
|
22
|
+
*
|
|
23
|
+
* // A semi-major axis is a mean: this orbit is 10% closer at one end and 10% further at the other.
|
|
24
|
+
* const extents = orbitExtents({ SemiMajorAxis: 1e9, Eccentricity: 0.1 });
|
|
25
|
+
* extents?.periapsis; // -> 900000000
|
|
26
|
+
* extents?.apoapsis; // -> 1100000000
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @packageDocumentation
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** How far an orbit actually reaches at each end, in metres from the primary's centre. */
|
|
33
|
+
interface OrbitExtents {
|
|
34
|
+
/** The orbit's semi-major axis, in metres — its mean distance, as the scan wrote it. */
|
|
35
|
+
readonly semiMajorAxis: number;
|
|
36
|
+
/** Closest approach, in metres — `a(1 − e)`. */
|
|
37
|
+
readonly periapsis: number;
|
|
38
|
+
/** Furthest recession, in metres — `a(1 + e)`. */
|
|
39
|
+
readonly apoapsis: number;
|
|
40
|
+
/** The eccentricity used, which is `0` when the scan wrote none. */
|
|
41
|
+
readonly eccentricity: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* How round an orbit is, in the four bands the Canonn tooling reports.
|
|
45
|
+
*
|
|
46
|
+
* - `circular` — eccentricity exactly `0`.
|
|
47
|
+
* - `nearly-circular` — below `0.4`.
|
|
48
|
+
* - `eccentric` — below `0.8`.
|
|
49
|
+
* - `highly-eccentric` — `0.8` and above.
|
|
50
|
+
*
|
|
51
|
+
* @remarks
|
|
52
|
+
* The bands are descriptive rather than physical: nothing changes at `0.4`. They exist so
|
|
53
|
+
* that "how unusual is this orbit" has one answer everywhere instead of a different
|
|
54
|
+
* threshold per caller.
|
|
55
|
+
*/
|
|
56
|
+
type EccentricityClass = 'circular' | 'nearly-circular' | 'eccentric' | 'highly-eccentric';
|
|
57
|
+
/** A spin-orbit resonance as the small whole-number ratio it is. */
|
|
58
|
+
interface SpinOrbitResonance {
|
|
59
|
+
/** Rotations the body makes — the `3` of a 3:2 resonance. */
|
|
60
|
+
readonly rotations: number;
|
|
61
|
+
/** Orbits it makes in the same time — the `2` of a 3:2 resonance. */
|
|
62
|
+
readonly orbits: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Where a body's orbit actually reaches, from the mean distance and eccentricity the scan
|
|
66
|
+
* wrote.
|
|
67
|
+
*
|
|
68
|
+
* @remarks
|
|
69
|
+
* {@link BodyProperties.SemiMajorAxis | SemiMajorAxis} is an average, and an eccentric
|
|
70
|
+
* orbit spends none of its time there. Periapsis is the figure a Roche breach, a tidal
|
|
71
|
+
* heating argument or a close-approach question turns on.
|
|
72
|
+
*
|
|
73
|
+
* @param body - The body. Needs {@link BodyProperties.SemiMajorAxis | SemiMajorAxis};
|
|
74
|
+
* {@link BodyProperties.Eccentricity | Eccentricity} is taken as `0` when absent, which is
|
|
75
|
+
* what a circular orbit means.
|
|
76
|
+
* @returns The extents in metres, or `null` when the body has no usable semi-major axis —
|
|
77
|
+
* a single-star system's primary star, which orbits nothing, among them.
|
|
78
|
+
* @throws {TypeError} If `body` is not an object.
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* import { orbitExtents } from '@elite-dangerous-almanac/core/astro/body-orbit';
|
|
82
|
+
*
|
|
83
|
+
* orbitExtents({ SemiMajorAxis: 1e9, Eccentricity: 0.25 })?.periapsis; // -> 750000000
|
|
84
|
+
*
|
|
85
|
+
* // No eccentricity written means a circle: both ends sit on the axis.
|
|
86
|
+
* orbitExtents({ SemiMajorAxis: 1e9 })?.apoapsis; // -> 1000000000
|
|
87
|
+
*
|
|
88
|
+
* orbitExtents({ MassEM: 1 }); // -> null
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
declare function orbitExtents(body: BodyProperties): OrbitExtents | null;
|
|
92
|
+
/**
|
|
93
|
+
* Which of the four descriptive bands an eccentricity falls in.
|
|
94
|
+
*
|
|
95
|
+
* @param eccentricity - An orbital eccentricity, as
|
|
96
|
+
* {@link BodyProperties.Eccentricity | Eccentricity} carries it: `0` for a circle, rising
|
|
97
|
+
* towards `1` for a long ellipse.
|
|
98
|
+
* @returns The band. See {@link EccentricityClass} for the thresholds.
|
|
99
|
+
* @throws {RangeError} If `eccentricity` is not a finite non-negative number. This takes a
|
|
100
|
+
* bare number rather than a body, so there is no absent field for a bad one to be.
|
|
101
|
+
* @example
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { classifyEccentricity } from '@elite-dangerous-almanac/core/astro/body-orbit';
|
|
104
|
+
*
|
|
105
|
+
* classifyEccentricity(0); // -> 'circular'
|
|
106
|
+
* classifyEccentricity(0.0549); // -> 'nearly-circular'
|
|
107
|
+
* classifyEccentricity(0.9); // -> 'highly-eccentric'
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
declare function classifyEccentricity(eccentricity: number): EccentricityClass;
|
|
111
|
+
/**
|
|
112
|
+
* The simple whole-number resonance between a body's spin and its orbit, when there is one.
|
|
113
|
+
*
|
|
114
|
+
* @remarks
|
|
115
|
+
* A body in a spin-orbit resonance turns a whole number of times for a whole number of
|
|
116
|
+
* orbits. `1:1` is tidal locking — one face kept to the primary, which the scan also
|
|
117
|
+
* reports as {@link BodyProperties.TidalLock | TidalLock} — and `3:2` is the next most
|
|
118
|
+
* common, the resonance Mercury sits in.
|
|
119
|
+
*
|
|
120
|
+
* Both terms are searched up to 5, and a ratio counts as a resonance when it lands within
|
|
121
|
+
* 1% of it. A retrograde rotation is written as a negative period; the resonance is a
|
|
122
|
+
* ratio of magnitudes, so a retrograde tidally-locked body still reads `1:1`.
|
|
123
|
+
*
|
|
124
|
+
* @param body - The body. Needs {@link BodyProperties.RotationPeriod | RotationPeriod} and
|
|
125
|
+
* {@link BodyProperties.OrbitalPeriod | OrbitalPeriod}. Both are seconds, and only their
|
|
126
|
+
* ratio matters.
|
|
127
|
+
* @returns The resonance, or `null` when either period is missing or the ratio is not
|
|
128
|
+
* close to any simple one — most bodies are in no resonance at all.
|
|
129
|
+
* @throws {TypeError} If `body` is not an object.
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* import { spinOrbitResonance } from '@elite-dangerous-almanac/core/astro/body-orbit';
|
|
133
|
+
*
|
|
134
|
+
* // One rotation per orbit: tidally locked.
|
|
135
|
+
* spinOrbitResonance({ RotationPeriod: 86400, OrbitalPeriod: 86400 }); // -> { rotations: 1, orbits: 1 }
|
|
136
|
+
*
|
|
137
|
+
* // Mercury: three rotations every two orbits.
|
|
138
|
+
* spinOrbitResonance({ RotationPeriod: 5067360, OrbitalPeriod: 7600544 }); // -> { rotations: 3, orbits: 2 }
|
|
139
|
+
*
|
|
140
|
+
* spinOrbitResonance({ RotationPeriod: 86400, OrbitalPeriod: 271828 }); // -> null
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
declare function spinOrbitResonance(body: BodyProperties): SpinOrbitResonance | null;
|
|
144
|
+
/**
|
|
145
|
+
* How fast a body's equator moves as it turns, in metres per second.
|
|
146
|
+
*
|
|
147
|
+
* @remarks
|
|
148
|
+
* `2πR / T`. This is the ground speed a point on the equator carries, which is why a fast
|
|
149
|
+
* rotator is worth knowing about before landing on one: the surface of a neutron star
|
|
150
|
+
* spinning in milliseconds is moving at a sizeable fraction of light speed.
|
|
151
|
+
*
|
|
152
|
+
* Speed is a magnitude, so a retrograde body — written with a negative
|
|
153
|
+
* {@link BodyProperties.RotationPeriod | RotationPeriod} — reads the same as a prograde
|
|
154
|
+
* one turning as fast.
|
|
155
|
+
*
|
|
156
|
+
* @param body - The body. Needs {@link BodyProperties.Radius | Radius} and
|
|
157
|
+
* {@link BodyProperties.RotationPeriod | RotationPeriod}.
|
|
158
|
+
* @returns The equatorial speed in m/s, or `null` when either is missing. A body the scan
|
|
159
|
+
* reports as not rotating carries no period, and answers `null` rather than `0`.
|
|
160
|
+
* @throws {TypeError} If `body` is not an object.
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* import { equatorialVelocity } from '@elite-dangerous-almanac/core/astro/body-orbit';
|
|
164
|
+
*
|
|
165
|
+
* // Earth: about 465 m/s at the equator.
|
|
166
|
+
* equatorialVelocity({ Radius: 6_378_137, RotationPeriod: 86164.1 }); // -> 465.1…
|
|
167
|
+
*
|
|
168
|
+
* // Retrograde is the same speed, the other way round.
|
|
169
|
+
* equatorialVelocity({ Radius: 6_378_137, RotationPeriod: -86164.1 }); // -> 465.1…
|
|
170
|
+
* ```
|
|
171
|
+
*/
|
|
172
|
+
declare function equatorialVelocity(body: BodyProperties): number | null;
|
|
173
|
+
|
|
174
|
+
export { type EccentricityClass, type OrbitExtents, type SpinOrbitResonance, classifyEccentricity, equatorialVelocity, orbitExtents, spinOrbitResonance };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{classifyEccentricity,equatorialVelocity,orbitExtents,spinOrbitResonance}from"../chunk-ZZ376WHL.js"; //# sourceMappingURL=body-orbit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"O"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { b as BodyProperties } from '../body-scan-CEUYjCfH.js';
|
|
2
|
+
import './system-address-input.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Bulk properties of a scanned body, and the geometry between a body and the one it
|
|
6
|
+
* orbits: mass, density, Roche limits, Hill radius, apparent size.
|
|
7
|
+
*
|
|
8
|
+
* Every function takes {@link BodyProperties} — a journal `Scan` line as it comes, or any
|
|
9
|
+
* record carrying the same fields — and works in the journal's own units: metres,
|
|
10
|
+
* kilograms, seconds. Nothing here holds data or reads a catalogue. The type itself is
|
|
11
|
+
* exported from `../astro`, alongside `BodyScanEvent`.
|
|
12
|
+
*
|
|
13
|
+
* **A calculation that compares two bodies takes both.** A journal line names a body's
|
|
14
|
+
* parent only by `BodyID` ({@link BodyProperties} carries no parent), so
|
|
15
|
+
* {@link rocheLimits}, {@link hillRadius} and {@link primaryAngularDiameter} take the
|
|
16
|
+
* primary as a second argument. Resolve it from your own record of the system — the
|
|
17
|
+
* `Parents` chain on the scan says which `BodyID` to look for.
|
|
18
|
+
*
|
|
19
|
+
* **Everything answers `null` rather than guessing.** A field the scan did not write, a
|
|
20
|
+
* zero radius, a `NaN` mass: all are "cannot be computed", never a substituted zero.
|
|
21
|
+
*
|
|
22
|
+
* The maths is ported from the Canonn Research Group's
|
|
23
|
+
* [canonn-signals](https://github.com/canonn-science/canonn-signals); see
|
|
24
|
+
* [ATTRIBUTIONS.md](https://github.com/DarkSession/Elite-Dangerous-Almanac/blob/main/ATTRIBUTIONS.md).
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { bulkDensity } from '@elite-dangerous-almanac/core/astro/body-physics';
|
|
29
|
+
*
|
|
30
|
+
* bulkDensity({ MassEM: 1, Radius: 6_371_000 }); // -> 5513.2…
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @packageDocumentation
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Newton's gravitational constant, in m³ kg⁻¹ s⁻² (CODATA).
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Exported because every orbital figure this library reports is proportional to it, so a
|
|
41
|
+
* consumer reproducing one gets the same answer rather than a near miss.
|
|
42
|
+
*/
|
|
43
|
+
declare const GRAVITATIONAL_CONSTANT = 6.6743e-11;
|
|
44
|
+
/**
|
|
45
|
+
* Kilograms in one Earth mass — the unit {@link BodyProperties.MassEM | MassEM} is written
|
|
46
|
+
* in.
|
|
47
|
+
*/
|
|
48
|
+
declare const KG_PER_EARTH_MASS = 5.972e+24;
|
|
49
|
+
/**
|
|
50
|
+
* Kilograms in one solar mass — the unit {@link BodyProperties.StellarMass | StellarMass}
|
|
51
|
+
* is written in.
|
|
52
|
+
*/
|
|
53
|
+
declare const KG_PER_SOLAR_MASS = 1.989e+30;
|
|
54
|
+
/**
|
|
55
|
+
* The two Roche limits for one pair of bodies, in metres from the primary's centre.
|
|
56
|
+
*
|
|
57
|
+
* @remarks
|
|
58
|
+
* Inside the Roche limit a satellite is pulled apart by the tide the primary raises on it.
|
|
59
|
+
* Which limit applies depends on what holds the satellite together: a rigid body resists
|
|
60
|
+
* with its own strength, a fluid one only with self-gravity, so the fluid limit is the
|
|
61
|
+
* larger and the truth for a real body sits between them.
|
|
62
|
+
*/
|
|
63
|
+
interface RocheLimits {
|
|
64
|
+
/**
|
|
65
|
+
* Rigid-body limit, in metres — `1.26 · R · (ρ_primary / ρ_satellite)^(1/3)`. The
|
|
66
|
+
* conservative figure: a solid body can survive closer than this only on its own
|
|
67
|
+
* material strength.
|
|
68
|
+
*/
|
|
69
|
+
readonly rigid: number;
|
|
70
|
+
/**
|
|
71
|
+
* Fluid-body limit, in metres — `2.456 · R · (ρ_primary / ρ_satellite)^(1/3)`. The
|
|
72
|
+
* generous figure, for a satellite held together by gravity alone.
|
|
73
|
+
*/
|
|
74
|
+
readonly fluid: number;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A body's mass in kilograms, whichever unit the scan wrote it in.
|
|
78
|
+
*
|
|
79
|
+
* @param body - The body. A planet or moon carries
|
|
80
|
+
* {@link BodyProperties.MassEM | MassEM} (Earth masses), a star
|
|
81
|
+
* {@link BodyProperties.StellarMass | StellarMass} (solar masses).
|
|
82
|
+
* @returns The mass in kilograms, or `null` when the scan wrote neither field usably. When
|
|
83
|
+
* a record carries both — which no journal line does — `MassEM` is the one read.
|
|
84
|
+
* @throws {TypeError} If `body` is not an object.
|
|
85
|
+
* @example
|
|
86
|
+
* ```ts
|
|
87
|
+
* import { bodyMass } from '@elite-dangerous-almanac/core/astro/body-physics';
|
|
88
|
+
*
|
|
89
|
+
* bodyMass({ MassEM: 1 }); // -> 5.972e24
|
|
90
|
+
* bodyMass({ StellarMass: 1 }); // -> 1.989e30
|
|
91
|
+
* bodyMass({ Radius: 6_371_000 }); // -> null
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
declare function bodyMass(body: BodyProperties): number | null;
|
|
95
|
+
/**
|
|
96
|
+
* A body's mean density, in kg/m³ — its mass spread evenly through a sphere of its radius.
|
|
97
|
+
*
|
|
98
|
+
* @param body - The body. Needs a mass ({@link bodyMass}) and
|
|
99
|
+
* {@link BodyProperties.Radius | Radius}.
|
|
100
|
+
* @returns Density in kg/m³, or `null` when either is missing. The scale is wide: an icy
|
|
101
|
+
* moon reads near 1000, rock and metal a few thousand, a neutron star around 10¹⁷.
|
|
102
|
+
* @throws {TypeError} If `body` is not an object.
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* import { bulkDensity } from '@elite-dangerous-almanac/core/astro/body-physics';
|
|
106
|
+
*
|
|
107
|
+
* // Earth: one Earth mass in a 6371 km sphere.
|
|
108
|
+
* bulkDensity({ MassEM: 1, Radius: 6_371_000 }); // -> 5513.2…
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
declare function bulkDensity(body: BodyProperties): number | null;
|
|
112
|
+
/**
|
|
113
|
+
* Roche limits around a primary for a satellite of a stated density.
|
|
114
|
+
*
|
|
115
|
+
* @remarks
|
|
116
|
+
* Use this when the satellite's density is assumed rather than measured — ring material,
|
|
117
|
+
* for instance, whose density comes from its class rather than from a mass and a radius
|
|
118
|
+
* (`ringRocheLimits` in `./body-rings` is this function with that density filled in).
|
|
119
|
+
* When the satellite is a scanned body with a mass and a radius of its own, prefer
|
|
120
|
+
* {@link rocheLimits}, which reads the density off it.
|
|
121
|
+
*
|
|
122
|
+
* @param primary - The body being orbited. Needs a mass and a
|
|
123
|
+
* {@link BodyProperties.Radius | Radius}.
|
|
124
|
+
* @param satelliteDensityKgM3 - The orbiting material's density in kg/m³.
|
|
125
|
+
* @returns Both limits in metres from the primary's centre, or `null` when the primary's
|
|
126
|
+
* own density cannot be computed.
|
|
127
|
+
* @throws {TypeError} If `primary` is not an object.
|
|
128
|
+
* @throws {RangeError} If `satelliteDensityKgM3` is not a finite positive number — an
|
|
129
|
+
* assumed density is the caller's own figure, so a bad one is a mistake rather than a
|
|
130
|
+
* missing scan field.
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* import { rocheLimitsForDensity } from '@elite-dangerous-almanac/core/astro/body-physics';
|
|
134
|
+
*
|
|
135
|
+
* // Icy particles (1000 kg/m³) around an Earth-density primary.
|
|
136
|
+
* const limits = rocheLimitsForDensity({ MassEM: 1, Radius: 6_371_000 }, 1000);
|
|
137
|
+
* limits?.rigid; // -> 14181242.2…
|
|
138
|
+
* limits?.fluid; // -> 27642167.3…
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
declare function rocheLimitsForDensity(primary: BodyProperties, satelliteDensityKgM3: number): RocheLimits | null;
|
|
142
|
+
/**
|
|
143
|
+
* Roche limits around a primary for one scanned satellite.
|
|
144
|
+
*
|
|
145
|
+
* @remarks
|
|
146
|
+
* Compare them against the satellite's **periapsis**, not its semi-major axis: a breach is
|
|
147
|
+
* set by closest approach, so an eccentric moon can dip inside the rigid limit while its
|
|
148
|
+
* mean distance looks safe. `orbitExtents` in `./body-orbit` gives that periapsis.
|
|
149
|
+
*
|
|
150
|
+
* @param satellite - The orbiting body. Needs a mass and a
|
|
151
|
+
* {@link BodyProperties.Radius | Radius}, from which its density is taken.
|
|
152
|
+
* @param primary - The body being orbited. Needs the same.
|
|
153
|
+
* @returns Both limits in metres from the primary's centre, or `null` when either body's
|
|
154
|
+
* density cannot be computed.
|
|
155
|
+
* @throws {TypeError} If either argument is not an object.
|
|
156
|
+
* @example
|
|
157
|
+
* ```ts
|
|
158
|
+
* import { rocheLimits } from '@elite-dangerous-almanac/core/astro/body-physics';
|
|
159
|
+
* import { orbitExtents } from '@elite-dangerous-almanac/core/astro/body-orbit';
|
|
160
|
+
*
|
|
161
|
+
* const moon = { MassEM: 0.0123, Radius: 1_737_400, SemiMajorAxis: 3.844e8, Eccentricity: 0.0549 };
|
|
162
|
+
* const earth = { MassEM: 1, Radius: 6_371_000 };
|
|
163
|
+
*
|
|
164
|
+
* const limits = rocheLimits(moon, earth);
|
|
165
|
+
* const closest = orbitExtents(moon)?.periapsis ?? 0;
|
|
166
|
+
*
|
|
167
|
+
* closest < (limits?.rigid ?? 0); // -> false
|
|
168
|
+
* ```
|
|
169
|
+
*/
|
|
170
|
+
declare function rocheLimits(satellite: BodyProperties, primary: BodyProperties): RocheLimits | null;
|
|
171
|
+
/**
|
|
172
|
+
* The radius of a body's Hill sphere, in metres — how far its own gravity wins against the
|
|
173
|
+
* body it orbits.
|
|
174
|
+
*
|
|
175
|
+
* @remarks
|
|
176
|
+
* `r_H = a · (m / 3M)^(1/3)`. Anything orbiting the body must stay inside this radius to
|
|
177
|
+
* remain bound to it, so it is the reach a moon has over nearby material — which is what
|
|
178
|
+
* makes a small moon a shepherd of a ring it does not sit in.
|
|
179
|
+
*
|
|
180
|
+
* The semi-major axis is used as written, so the figure is the mean-distance Hill radius.
|
|
181
|
+
* On an eccentric orbit the sphere shrinks at periapsis; recompute with
|
|
182
|
+
* `orbitExtents(body)?.periapsis` in place of the axis when that matters.
|
|
183
|
+
*
|
|
184
|
+
* @param body - The body whose sphere is wanted. Needs
|
|
185
|
+
* {@link BodyProperties.SemiMajorAxis | SemiMajorAxis} and a mass.
|
|
186
|
+
* @param primary - The body it orbits. Needs a mass.
|
|
187
|
+
* @returns The Hill radius in metres, or `null` when a mass or the orbit is missing.
|
|
188
|
+
* @throws {TypeError} If either argument is not an object.
|
|
189
|
+
* @example
|
|
190
|
+
* ```ts
|
|
191
|
+
* import { hillRadius } from '@elite-dangerous-almanac/core/astro/body-physics';
|
|
192
|
+
*
|
|
193
|
+
* // Earth about the Sun: about 1.5 million km.
|
|
194
|
+
* hillRadius({ MassEM: 1, SemiMajorAxis: 1.496e11 }, { StellarMass: 1 }); // -> 1496417737.0…
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
declare function hillRadius(body: BodyProperties, primary: BodyProperties): number | null;
|
|
198
|
+
/**
|
|
199
|
+
* How large the body it orbits appears in a body's sky, as an angular diameter in degrees.
|
|
200
|
+
*
|
|
201
|
+
* @remarks
|
|
202
|
+
* `2 · atan(R_primary / a)`, taken exactly rather than through the small-angle
|
|
203
|
+
* approximation `2R/a`: the two diverge by percent at the tens of degrees a parent
|
|
204
|
+
* actually subtends from a close moon, which is the range worth asking about. A landable
|
|
205
|
+
* moon whose primary fills 45° of sky is a view; one at 0.5° is a dot.
|
|
206
|
+
*
|
|
207
|
+
* Distance is the body's own semi-major axis, centre to centre, so the figure is the mean.
|
|
208
|
+
*
|
|
209
|
+
* @param body - The body being stood on. Needs
|
|
210
|
+
* {@link BodyProperties.SemiMajorAxis | SemiMajorAxis}.
|
|
211
|
+
* @param primary - The body it orbits. Needs {@link BodyProperties.Radius | Radius}.
|
|
212
|
+
* @returns The angular diameter in degrees, or `null` when the orbit or the primary's
|
|
213
|
+
* radius is missing.
|
|
214
|
+
* @throws {TypeError} If either argument is not an object.
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* import { primaryAngularDiameter } from '@elite-dangerous-almanac/core/astro/body-physics';
|
|
218
|
+
*
|
|
219
|
+
* // A primary as far away as it is wide fills a right angle of sky.
|
|
220
|
+
* primaryAngularDiameter({ SemiMajorAxis: 1e9 }, { Radius: 1e9 }); // -> 90
|
|
221
|
+
*
|
|
222
|
+
* // Earth's Moon, looking back: Earth subtends about 2°.
|
|
223
|
+
* primaryAngularDiameter({ SemiMajorAxis: 3.844e8 }, { Radius: 6_371_000 }); // -> 1.899…
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
declare function primaryAngularDiameter(body: BodyProperties, primary: BodyProperties): number | null;
|
|
227
|
+
|
|
228
|
+
export { GRAVITATIONAL_CONSTANT, KG_PER_EARTH_MASS, KG_PER_SOLAR_MASS, type RocheLimits, bodyMass, bulkDensity, hillRadius, primaryAngularDiameter, rocheLimits, rocheLimitsForDensity };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{GRAVITATIONAL_CONSTANT,KG_PER_EARTH_MASS,KG_PER_SOLAR_MASS,bodyMass,bulkDensity,hillRadius,primaryAngularDiameter,rocheLimits,rocheLimitsForDensity}from"../chunk-TMXKC6JL.js"; //# sourceMappingURL=body-physics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"O"}
|