Files
skills/docs/geospatial/geo/universe/src/observer/observer.md
2026-05-29 08:20:56 +01:00

115 lines
3.9 KiB
Markdown

# Observer
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Re-exports the `ObserverPosition` discriminated union that every universe-family entry point consumes. The union has three branches — `SurfaceObserver`, `AtmosphericObserver`, and `SpaceObserver` — distinguished by a `kind` literal field so call sites can narrow exhaustively without runtime type tags or class hierarchies.
Centralising these types in one module gives `@suaveplan/universe/client/client`, providers, and frame-conversion utilities a single shape to consume. Because the source declarations live in `@suaveplan/types` (zero-runtime, types-only), this re-export adds no bundle weight; it exists so consumers can import observer shapes without crossing into the foundational types package directly.
## Features
- `ObserverPosition` — full discriminated union, switch on `kind`.
- `SurfaceObserver` — planet-bound observer at a `{latitude, longitude}` coordinate.
- `AtmosphericObserver` — same as surface but with `altitudeMetres` (planes, balloons, drones).
- `SpaceObserver` — heliocentric vector + reference `frame` (e.g. `"icrs"`).
- All three branches share the `kind` literal as the discriminator.
- Pure types — zero runtime cost, tree-shaken to nothing.
## Usage: Basic Example
```ts
import type { ObserverPosition } from "@suaveplan/universe";
const observer: ObserverPosition = {
kind: "space",
heliocentricVec: { x: 1, y: 0, z: 0 },
frame: "icrs",
};
```
## Usage: Advanced Example
```ts
import type {
AtmosphericObserver,
ObserverPosition,
SpaceObserver,
SurfaceObserver,
} from "@suaveplan/universe";
function describe(o: ObserverPosition): string {
switch (o.kind) {
case "surface":
return `surface at ${o.coord.latitude},${o.coord.longitude}`;
case "atmospheric":
return `${o.altitudeMetres} m above ${o.planet.name}`;
case "space":
return `space, ${o.frame} vector ${JSON.stringify(o.heliocentricVec)}`;
}
}
const earth = {
name: "Earth",
mass: 1,
radius: 1,
polarRadius: 1,
surfaceGravity: 1,
rotationPeriod: 1,
axialTilt: 23.4,
atmosphere: null,
satellites: [],
};
const surface: SurfaceObserver = {
kind: "surface",
planet: earth,
coord: { latitude: 51.5, longitude: -0.12 },
};
const balloon: AtmosphericObserver = {
kind: "atmospheric",
planet: earth,
coord: { latitude: 51.5, longitude: -0.12 },
altitudeMetres: 12000,
};
const probe: SpaceObserver = {
kind: "space",
heliocentricVec: { x: 1.0, y: 0.0, z: 0.0 },
frame: "icrs",
};
[surface, balloon, probe].forEach((o) => describe(o));
```
## API Reference
### `type SurfaceObserver`
| Property | Type | Description |
|---|---|---|
| `kind` | `"surface"` | Discriminator literal. |
| `planet` | `PlanetConfig` | Host body (mass, radius, axial tilt, satellites …). |
| `coord` | `{ latitude: number; longitude: number }` | Geographic location in degrees. |
### `type AtmosphericObserver`
Extends `SurfaceObserver` shape with an additional `altitudeMetres: number` and `kind: "atmospheric"`.
### `type SpaceObserver`
| Property | Type | Description |
|---|---|---|
| `kind` | `"space"` | Discriminator literal. |
| `heliocentricVec` | `{ x: number; y: number; z: number }` | Cartesian position in AU. |
| `frame` | `string` | Reference frame label, e.g. `"icrs"`. |
### `type ObserverPosition`
`SurfaceObserver | AtmosphericObserver | SpaceObserver` — exhaustive switch on `kind`.
## Implementation Notes
These types are re-exported from `@suaveplan/types`; this module contains no runtime code and contributes nothing to the emitted bundle. Keeping the canonical declarations in `@suaveplan/types` preserves the universe-family rule that any observer-shaped value flowing through providers, the client, frame conversions, or packet codecs is structurally identical no matter which sibling package produced it.