first commit
This commit is contained in:
53
docs/geospatial/geo/geo-planet/README.md
Normal file
53
docs/geospatial/geo/geo-planet/README.md
Normal file
@@ -0,0 +1,53 @@
|
||||
# @suaveplan/geo-planet - Configurable planet surface geometry from PlanetConfig — ellipsoid, atmosphere, satellites, and orbital elements.
|
||||
|
||||
## Summary
|
||||
|
||||
Configurable planet surface geometry from `PlanetConfig` — ellipsoid, atmosphere, satellites, and orbital elements.
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
## Documentation tree
|
||||
|
||||
- [atmospheric](./src/atmospheric/atmospheric.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [atmospheric](./src/atmospheric/atmospheric.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
- [schemas](./src/types/schemas.md) — The `schemas` module exposes Zod runtime schemas mirroring every public type declared in `types.ts`. Validation is the…
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
|
||||
<!-- end:auto-docs --> - [atmospheric](./src/atmospheric/atmospheric.md) — <!-- begin:auto-docs --> _(no submodules)_- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/types/schemas.md) — The `schemas` module exposes Zod runtime schemas mirroring every public type declared in `types.ts`. Validation is the…
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [atmospheric](./src/atmospheric/atmospheric.md) — <!-- begin:auto-docs --> _(no submodules)_- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/types/schemas.md) — The `schemas` module exposes Zod runtime schemas mirroring every public type declared in `types.ts`. Validation is the…
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [atmospheric](./src/atmospheric/atmospheric.md) — <!-- begin:auto-docs --> _(no submodules)_- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/types/schemas.md) — The `schemas` module exposes Zod runtime schemas mirroring every public type declared in `types.ts`. Validation is the…
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_- [atmospheric](./src/atmospheric/atmospheric.md) — <!-- begin:auto-docs --> _(no submodules)_- [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_ - [planet-surface](./src/planet-surface/planet-surface.md) — <!-- begin:auto-docs --> _(no submodules)_- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_ - [schemas](./src/types/schemas.md) — The `schemas` module exposes Zod runtime schemas mirroring every public type declared in `types.ts`. Validation is the…
|
||||
- [types](./src/types/types.md) — <!-- begin:auto-docs --> _(no submodules)_
|
||||
## Install
|
||||
|
||||
```bash
|
||||
bun add @suaveplan/geo-planet
|
||||
```
|
||||
|
||||
## Quick start
|
||||
|
||||
```ts
|
||||
import { PlanetSurface, PlanetConfigSchema } from "@suaveplan/geo-planet";
|
||||
|
||||
const config = PlanetConfigSchema.parse({
|
||||
name: "Mars",
|
||||
mass: 6.39e23,
|
||||
radius: 3_396_200,
|
||||
polarRadius: 3_376_200,
|
||||
surfaceGravity: 3.72,
|
||||
rotationPeriod: 88_620,
|
||||
axialTilt: 25.2,
|
||||
atmosphere: null,
|
||||
satellites: [],
|
||||
});
|
||||
|
||||
const surface = new PlanetSurface(config);
|
||||
console.log(surface.distance(a, b, "kilometre"));
|
||||
```
|
||||
|
||||
## Modules
|
||||
|
||||
- [`src/planet-surface/planet-surface.md`](src/planet-surface/planet-surface.md)
|
||||
- [`src/atmospheric/atmospheric.md`](src/atmospheric/atmospheric.md)
|
||||
- [`src/types/types.md`](src/types/types.md)
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
The `atmospheric` module provides the two physics primitives every planetary renderer, sky-colour solver, and observation-quality estimator needs: the local density of an atmospheric column at altitude, and the relative path length light travels through that column for a given elevation angle. Both functions accept a `PlanetConfig` so the same code path serves Earth, Mars, Titan, or any other modelled body.
|
||||
|
||||
These primitives are intentionally pure and free of vendor coupling so they can be reused by `@suaveplan/universe`, `@suaveplan/gaming-environment-lighting`, server-side astronomical computations, and offline analysis without dragging a graphics runtime into the call site.
|
||||
|
||||
## Features
|
||||
|
||||
- `atmosphericDensity(planet, altitudeMetres)` — exponential isothermal scale-height model that returns `0` for airless bodies
|
||||
- `airMass(altitudeDeg)` — Kasten–Young 1989 air-mass approximation valid from zenith down to the horizon
|
||||
- Numerical-stable horizon handling: negative altitudes are clamped to `0` so the formula remains finite at the bound
|
||||
- Pure functions: no I/O, no side effects, no global state — safe for `Worker` threads, SSR, and deterministic tests
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```ts
|
||||
import { atmosphericDensity } from "@suaveplan/geo-planet";
|
||||
import type { PlanetConfig } from "@suaveplan/geo-planet";
|
||||
|
||||
const earth: PlanetConfig = {
|
||||
name: "Earth",
|
||||
mass: 5.972e24,
|
||||
radius: 6_378_137,
|
||||
polarRadius: 6_356_752,
|
||||
surfaceGravity: 9.81,
|
||||
rotationPeriod: 86_164,
|
||||
axialTilt: 23.44,
|
||||
atmosphere: {
|
||||
surfacePressure: 101_325,
|
||||
scaleHeight: 8_500,
|
||||
rayleighCoefficient: 5.8e-6,
|
||||
mieCoefficient: 21e-6,
|
||||
extinctionPerAirMass: 0.13,
|
||||
},
|
||||
satellites: [],
|
||||
};
|
||||
|
||||
const surface = atmosphericDensity(earth, 0); // 101325 Pa
|
||||
const cruise = atmosphericDensity(earth, 11_000); // ~27 kPa
|
||||
```
|
||||
|
||||
### Advanced Example
|
||||
|
||||
```ts
|
||||
import { airMass, atmosphericDensity } from "@suaveplan/geo-planet";
|
||||
import type { PlanetConfig } from "@suaveplan/geo-planet";
|
||||
|
||||
function transmittance(
|
||||
planet: PlanetConfig,
|
||||
altitudeMetres: number,
|
||||
sunElevationDeg: number,
|
||||
): number {
|
||||
if (!planet.atmosphere) return 1;
|
||||
const density = atmosphericDensity(planet, altitudeMetres);
|
||||
const am = airMass(sunElevationDeg);
|
||||
const tau = planet.atmosphere.extinctionPerAirMass * am;
|
||||
return Math.exp(-tau) * (density / planet.atmosphere.surfacePressure);
|
||||
}
|
||||
|
||||
// Use at every camera step in a sky shader, or to score
|
||||
// observability for ground-station pass scheduling.
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `atmosphericDensity(planet: PlanetConfig, altitudeMetres: number): number`
|
||||
|
||||
Returns the local pressure (`Pa`) using `p₀ · exp(-h / H)` where `p₀` is `planet.atmosphere.surfacePressure` and `H` is `planet.atmosphere.scaleHeight`. Returns `0` when `planet.atmosphere === null`. No clamping is applied to altitude; negative altitudes (subterranean, sub-sea-level) yield pressures above `p₀`, which is the physically correct extrapolation for a barometric law.
|
||||
|
||||
### `airMass(altitudeDeg: number): number`
|
||||
|
||||
Returns the Kasten–Young air mass:
|
||||
|
||||
`1 / (sin(alt) + 0.50572 · (alt + 6.07995)^-1.6364)`
|
||||
|
||||
with `alt` in degrees. Negative altitudes are clamped to `0` so the result remains finite at the horizon (returning ≈ `38`). At zenith the return value approaches `1`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The density function uses the isothermal barometric equation rather than a layered ISA model because every consumer in this project treats density as a smooth analytic function for shader sampling. The Kasten–Young formulation was chosen over the simpler `1 / sin(alt)` secant model because it remains stable down to the horizon and only diverges by ≈ `0.4%` from full atmospheric ray-tracing above 5° elevation. Both functions are allocation-free hot-path code; consumers can call them once per pixel without GC pressure.
|
||||
@@ -0,0 +1,111 @@
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
The `planet-surface` module provides the `PlanetSurface` class, an oblate-ellipsoid wrapper around a `PlanetConfig` that exposes the geodetic operations every multi-planet system needs: great-circle distance, initial bearing, terminal-point projection from a heading and distance, and point-in-polygon tests. It is the single bridge between body-specific configuration (Earth, Mars, Titan, …) and the body-agnostic geometry primitives in `@suaveplan/geo`.
|
||||
|
||||
By deriving the ellipsoid once per `PlanetSurface` instance from the `radius` and `polarRadius` fields of `PlanetConfig`, callers never have to thread an ellipsoid through every distance call, and they cannot accidentally mix Earth-flattening into a Mars computation.
|
||||
|
||||
## Features
|
||||
|
||||
- `PlanetSurface` class — owns the planet config and the cached `Ellipsoid`
|
||||
- `distance(a, b, unit?)` — geodesic great-circle distance with selectable distance unit
|
||||
- `bearing(from, to)` — initial forward azimuth in degrees from north, clockwise
|
||||
- `destination(start, bearingDeg, distanceM)` — terminal-point projection by direct-geodesic solution
|
||||
- `pointInPolygon(point, polygon)` — spherical-coordinate ray-cast / winding test for arbitrary closed rings
|
||||
- Body-agnostic — works for any planet whose oblateness is well-modelled by an ellipsoid of revolution
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```ts
|
||||
import { PlanetSurface } from "@suaveplan/geo-planet";
|
||||
import type { PlanetConfig } from "@suaveplan/geo-planet";
|
||||
|
||||
const earth: PlanetConfig = {
|
||||
name: "Earth",
|
||||
mass: 5.972e24,
|
||||
radius: 6_378_137,
|
||||
polarRadius: 6_356_752,
|
||||
surfaceGravity: 9.81,
|
||||
rotationPeriod: 86_164,
|
||||
axialTilt: 23.44,
|
||||
atmosphere: null,
|
||||
satellites: [],
|
||||
};
|
||||
|
||||
const surface = new PlanetSurface(earth);
|
||||
const km = surface.distance(
|
||||
{ latitude: 51.5, longitude: -0.13 }, // London
|
||||
{ latitude: 40.71, longitude: -74.0 }, // New York
|
||||
"kilometre",
|
||||
);
|
||||
```
|
||||
|
||||
### Advanced Example
|
||||
|
||||
```ts
|
||||
import { PlanetSurface } from "@suaveplan/geo-planet";
|
||||
import type { PlanetConfig } from "@suaveplan/geo-planet";
|
||||
|
||||
const mars: PlanetConfig = {
|
||||
name: "Mars",
|
||||
mass: 6.39e23,
|
||||
radius: 3_396_200,
|
||||
polarRadius: 3_376_200,
|
||||
surfaceGravity: 3.72,
|
||||
rotationPeriod: 88_620,
|
||||
axialTilt: 25.2,
|
||||
atmosphere: null,
|
||||
satellites: [],
|
||||
};
|
||||
|
||||
const surface = new PlanetSurface(mars);
|
||||
|
||||
// Project a 100 km traverse from Jezero crater on a 45° heading.
|
||||
const start = { latitude: 18.44, longitude: 77.45 };
|
||||
const end = surface.destination(start, 45, 100_000);
|
||||
|
||||
// Heading toward Olympus Mons.
|
||||
const heading = surface.bearing(start, { latitude: 18.65, longitude: -133.8 });
|
||||
|
||||
// Region containment for science-target zones.
|
||||
const aoi = [
|
||||
{ latitude: 18.0, longitude: 77.0 },
|
||||
{ latitude: 19.0, longitude: 77.0 },
|
||||
{ latitude: 19.0, longitude: 78.0 },
|
||||
{ latitude: 18.0, longitude: 78.0 },
|
||||
];
|
||||
const inside = surface.pointInPolygon(end, aoi);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `class PlanetSurface`
|
||||
|
||||
#### `constructor(planet: PlanetConfig)`
|
||||
|
||||
Stores the planet on `surface.planet` and constructs an `Ellipsoid` via `defineEllipsoid(planet.radius, planet.polarRadius)` once per instance.
|
||||
|
||||
#### `distance(a, b, unit?: DistanceUnit): number`
|
||||
|
||||
Returns the great-circle distance between two `SphericalCoord` points along the cached ellipsoid. `unit` defaults to `"metre"`; pass `"kilometre"`, `"mile"`, etc. as supported by `@suaveplan/geo`.
|
||||
|
||||
#### `bearing(from, to): number`
|
||||
|
||||
Returns the initial forward azimuth in degrees clockwise from north. Note: the spherical bearing in `@suaveplan/geo` does not depend on the ellipsoid.
|
||||
|
||||
#### `destination(start, bearingDeg, distanceM): SphericalCoord`
|
||||
|
||||
Solves the direct geodesic problem on the cached ellipsoid: given a start point, an initial bearing, and a distance in metres, returns the terminal point.
|
||||
|
||||
#### `pointInPolygon(point, polygon: SphericalCoord[]): boolean`
|
||||
|
||||
Tests containment of `point` inside the closed polygon ring; uses spherical-coordinate point-in-polygon math from `@suaveplan/geo`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The ellipsoid is built once at construction and then reused on every method call, which keeps every distance / destination call allocation-free in steady state. Bearing intentionally does not pass the ellipsoid because the underlying `bearing` from `@suaveplan/geo` is a pure spherical primitive — for the precision needed in mission-planning UIs, the difference between spherical and geodetic bearing is below display granularity, and the geometric simplicity is worth more than the marginal accuracy gain. Storing `planet` as a public readonly property lets consumers retain the original config (for atmosphere, satellites, textures, etc.) without round-tripping through a separate registry.
|
||||
84
docs/geospatial/geo/geo-planet/src/types/schemas.md
Normal file
84
docs/geospatial/geo/geo-planet/src/types/schemas.md
Normal file
@@ -0,0 +1,84 @@
|
||||
## Purpose
|
||||
|
||||
The `schemas` module exposes Zod runtime schemas mirroring every public type declared in `types.ts`. Validation is the boundary contract for any consumer accepting raw JSON, configuration files, IPC payloads, or untrusted user input that will later be handed to `PlanetSurface`, atmospheric solvers, or astronomical providers.
|
||||
|
||||
By keeping schemas co-located with the type module they validate, `geo-planet` guarantees that the runtime parser and the static `interface` shapes never drift. Every numeric invariant required by physical models (positive masses, normalised eccentricities, non-negative pressures) is enforced at parse time so downstream code can assume well-formed inputs without defensive null checks.
|
||||
|
||||
## Features
|
||||
|
||||
- `AtmosphereConfigSchema` — non-negative pressure / coefficients, positive scale height
|
||||
- `SatelliteConfigSchema` — positive mass/radius/orbit, eccentricity ∈ `[0, 1]`, albedo ∈ `[0, 1]`
|
||||
- `OrbitalConfigSchema` — Keplerian elements (semi-major axis AU, inclination, perihelion, ascending node, mean anomaly, epoch JD)
|
||||
- `PlanetTextureManifestSchema` — optional diffuse/normal/specular/clouds/night texture URLs
|
||||
- `PlanetConfigSchema` — composite root validating physical, orbital, and rendering metadata
|
||||
- Inferred types via `z.infer<typeof Schema>` interoperate with the hand-authored `interface`s in `types.ts`
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```ts
|
||||
import { PlanetConfigSchema } from "@suaveplan/geo-planet";
|
||||
|
||||
const earth = PlanetConfigSchema.parse({
|
||||
name: "Earth",
|
||||
mass: 5.972e24,
|
||||
radius: 6_378_137,
|
||||
polarRadius: 6_356_752,
|
||||
surfaceGravity: 9.81,
|
||||
rotationPeriod: 86_164,
|
||||
axialTilt: 23.44,
|
||||
atmosphere: null,
|
||||
satellites: [],
|
||||
});
|
||||
```
|
||||
|
||||
### Advanced Example
|
||||
|
||||
```ts
|
||||
import {
|
||||
AtmosphereConfigSchema,
|
||||
OrbitalConfigSchema,
|
||||
PlanetConfigSchema,
|
||||
SatelliteConfigSchema,
|
||||
} from "@suaveplan/geo-planet";
|
||||
|
||||
const result = PlanetConfigSchema.safeParse(rawJson);
|
||||
if (!result.success) {
|
||||
for (const issue of result.error.issues) {
|
||||
console.error(issue.path.join("."), issue.message);
|
||||
}
|
||||
throw new Error("invalid planet config");
|
||||
}
|
||||
|
||||
// Per-field schemas compose for partial validation pipelines.
|
||||
const atmo = AtmosphereConfigSchema.parse(rawJson.atmosphere);
|
||||
const orbit = OrbitalConfigSchema.parse(rawJson.orbital);
|
||||
const moon = SatelliteConfigSchema.parse(rawJson.satellites[0]);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `AtmosphereConfigSchema`
|
||||
|
||||
Validates `surfacePressure ≥ 0`, `scaleHeight > 0`, and non-negative Rayleigh, Mie, and air-mass extinction coefficients. Throws on negative numbers or missing fields.
|
||||
|
||||
### `SatelliteConfigSchema`
|
||||
|
||||
Validates non-empty `name`, positive `mass` / `radius` / `orbitalRadius` / `orbitalPeriod`, free `orbitalInclination`, and clamped `eccentricity` and `albedo` in `[0, 1]`.
|
||||
|
||||
### `OrbitalConfigSchema`
|
||||
|
||||
Validates positive `semiMajorAxisAU`, eccentricity ∈ `[0, 1]`, free angular elements, and any finite epoch Julian Date.
|
||||
|
||||
### `PlanetTextureManifestSchema`
|
||||
|
||||
All texture URL fields are optional strings; missing fields default to `undefined`.
|
||||
|
||||
### `PlanetConfigSchema`
|
||||
|
||||
Composite schema enforcing positive `mass` / `radius` / `polarRadius` / `surfaceGravity` / `rotationPeriod`, free `axialTilt`, `atmosphere: AtmosphereConfig | null`, an array of satellites, and optional `orbital` and `textures`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Every schema is built directly with `zod` and exports the parser; `z.infer` keeps inferred shapes structurally identical to the hand-authored interfaces. The `null`-permissive atmosphere field models airless bodies (Mercury, Moon) without forcing consumers into an option-type at the validation layer. Eccentricity is clamped to a closed interval rather than a half-open one because a parabolic trajectory (`e === 1`) is a useful boundary case for astronomical fixtures even though it is not bound. Schemas avoid `.strict()` so additive forward-compatible fields can be carried by raw payloads without forcing a parser bump.
|
||||
117
docs/geospatial/geo/geo-planet/src/types/types.md
Normal file
117
docs/geospatial/geo/geo-planet/src/types/types.md
Normal file
@@ -0,0 +1,117 @@
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
The `types` module declares the static TypeScript interfaces describing every value `geo-planet` accepts and emits. These are the canonical shapes consumed by `PlanetSurface`, atmospheric models, and any downstream renderer or astronomical provider that needs a single source of truth for what defines a planetary body.
|
||||
|
||||
Keeping the interfaces in a hand-authored file (rather than relying solely on `z.infer`) lets the compiler emit precise, documented declarations into `.d.ts` outputs without dragging the Zod runtime into type-only consumers. The runtime mirror lives in `schemas.ts` and is verified by tests to stay structurally aligned with these interfaces.
|
||||
|
||||
## Features
|
||||
|
||||
- `AtmosphereConfig` — exponential atmosphere parameters (surface pressure, scale height, Rayleigh / Mie coefficients, extinction)
|
||||
- `SatelliteConfig` — physical and orbital parameters for a natural satellite
|
||||
- `OrbitalConfig` — heliocentric Keplerian elements with epoch Julian Date
|
||||
- `PlanetTextureManifest` — optional URLs for diffuse / normal / specular / cloud / night textures
|
||||
- `PlanetConfig` — composite top-level shape: physical body + optional atmosphere + satellites + optional orbital and texture metadata
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Example
|
||||
|
||||
```ts
|
||||
import type { PlanetConfig } from "@suaveplan/geo-planet";
|
||||
|
||||
const mars: PlanetConfig = {
|
||||
name: "Mars",
|
||||
mass: 6.39e23,
|
||||
radius: 3_396_200,
|
||||
polarRadius: 3_376_200,
|
||||
surfaceGravity: 3.72,
|
||||
rotationPeriod: 88_620,
|
||||
axialTilt: 25.2,
|
||||
atmosphere: null,
|
||||
satellites: [],
|
||||
};
|
||||
```
|
||||
|
||||
### Advanced Example
|
||||
|
||||
```ts
|
||||
import type {
|
||||
AtmosphereConfig,
|
||||
OrbitalConfig,
|
||||
PlanetConfig,
|
||||
SatelliteConfig,
|
||||
} from "@suaveplan/geo-planet";
|
||||
|
||||
const earthAtmosphere: AtmosphereConfig = {
|
||||
surfacePressure: 101_325,
|
||||
scaleHeight: 8_500,
|
||||
rayleighCoefficient: 5.8e-6,
|
||||
mieCoefficient: 21e-6,
|
||||
extinctionPerAirMass: 0.13,
|
||||
};
|
||||
|
||||
const earthOrbit: OrbitalConfig = {
|
||||
semiMajorAxisAU: 1.0,
|
||||
eccentricity: 0.0167,
|
||||
inclinationDeg: 0.0,
|
||||
argumentOfPerihelionDeg: 102.94,
|
||||
ascendingNodeDeg: -11.26,
|
||||
meanAnomalyAtEpochDeg: 357.51,
|
||||
epochJd: 2_451_545,
|
||||
};
|
||||
|
||||
const luna: SatelliteConfig = {
|
||||
name: "Luna",
|
||||
mass: 7.342e22,
|
||||
radius: 1_737_400,
|
||||
orbitalRadius: 384_400_000,
|
||||
orbitalPeriod: 2_360_592,
|
||||
orbitalInclination: 5.145,
|
||||
eccentricity: 0.0549,
|
||||
albedo: 0.12,
|
||||
};
|
||||
|
||||
const earth: PlanetConfig = {
|
||||
name: "Earth",
|
||||
mass: 5.972e24,
|
||||
radius: 6_378_137,
|
||||
polarRadius: 6_356_752,
|
||||
surfaceGravity: 9.81,
|
||||
rotationPeriod: 86_164,
|
||||
axialTilt: 23.44,
|
||||
atmosphere: earthAtmosphere,
|
||||
satellites: [luna],
|
||||
orbital: earthOrbit,
|
||||
textures: { diffuse: "/textures/earth-diffuse.ktx2" },
|
||||
};
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `AtmosphereConfig`
|
||||
|
||||
`surfacePressure: number`, `scaleHeight: number`, `rayleighCoefficient: number`, `mieCoefficient: number`, `extinctionPerAirMass: number`.
|
||||
|
||||
### `SatelliteConfig`
|
||||
|
||||
`name: string`, plus the same physical and orbital scalars as a planet, restricted to `eccentricity ∈ [0, 1]` and `albedo ∈ [0, 1]` at the runtime layer.
|
||||
|
||||
### `OrbitalConfig`
|
||||
|
||||
`semiMajorAxisAU`, `eccentricity`, `inclinationDeg`, `argumentOfPerihelionDeg`, `ascendingNodeDeg`, `meanAnomalyAtEpochDeg`, `epochJd`.
|
||||
|
||||
### `PlanetTextureManifest`
|
||||
|
||||
Optional `diffuse`, `normal`, `specular`, `clouds`, `night` texture URL strings.
|
||||
|
||||
### `PlanetConfig`
|
||||
|
||||
`name`, `mass`, `radius`, `polarRadius`, `surfaceGravity`, `rotationPeriod`, `axialTilt`, `atmosphere: AtmosphereConfig | null`, `satellites: SatelliteConfig[]`, optional `orbital`, optional `textures`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The atmosphere field is `AtmosphereConfig | null` rather than `AtmosphereConfig | undefined` so airless bodies (Mercury, Moon) are explicitly modelled rather than accidentally omitted; renderers and atmospheric solvers branch on `=== null` directly. Both equatorial `radius` and `polarRadius` are required because `PlanetSurface` constructs an oblate ellipsoid for accurate great-circle math; spherical bodies pass equal values. Orbital and texture metadata are optional because tests, fixtures, and offline renderers often only need physical scalars.
|
||||
Reference in New Issue
Block a user