Observatory

class Observatory
devtools/src/observatory.ts:370

Members

constructor

constructor(host: Host) → Observatory
hostHost
Undocumented

aimaccessor

aim() → DropAim | null

The point a drop is being aimed at, or null when nothing is being aimed.

Presentation state, set by whatever is holding the gesture and read by whatever draws the aid — a hover, in the same sense the look offset is a hover. It writes nothing canonical, it does not move the camera, and it is cleared by everything that replaces the pose, so an aim cannot survive the body it was taken over.

eyeaccessor

eye() → UniverseVector | null

Where the camera is this instant, or null when it is holding nothing.

Deliberately not sample(): that one advances the ease and is the render loop's to call exactly once per frame. This is a reading, for anything that needs to know where the viewer is without being the viewer — the catalog sorts by distance from it, so calling sample to find out would have a panel stepping the camera's animation every time it polled.

galaxyInstrumentaccessor

galaxyInstrument() → boolean

galaxyViewaccessor

galaxyView() → 'face-on' | 'edge-on' | null

heldTimeaccessor

heldTime() → number | null

journeyaccessor

journey() → GalaxyJourneyStatus | null

lookaccessor

look() → LookOffset

Where the head is turned, relative to what the pose aims at.

mutationRevisionaccessor

mutationRevision() → number

Explicit camera and photographic-time edits, excluding render advancement.

standingaccessor

standing() → boolean

Whether the camera is on the ground rather than in orbit.

stateaccessor

state() → ObserverState

targetaccessor

target() → ObserverTarget | null

timeaccessor

time() → number

A held photographic instant, or the live simulation's presentation time.

timePausedaccessor

timePaused() → boolean

timeScaleaccessor

timeScale() → number

advanceTime

advanceTime(seconds: number) → void
secondsnumber
Undocumented

bounds

bounds() → { max: number; min: number }

The band the current target permits. Panels draw sliders against it.

capture

capture() → { 6 fields }

center

center() → void

Back to whatever the pose aims at.

clear

clear() → void

Let go of the camera.

With no target the observatory produces no pose, and the host falls back to whatever owns the camera otherwise — the ship, in every flight mode. That fallback is the whole mechanism for leaving the planetarium: there is no "restore" step and nothing to put back, because nothing was taken.

compose

compose(id: string) → ObserverStatus

Take a named composition of whatever is being looked at.

The observatory's placer, beside the ship's. One list, two placers, and the difference is what they move: placeShot teleports a hull and this moves a camera, so ir.shot('gibbous') and compose('gibbous') end with the same picture and only one of them changes canonical state.

Which arm it lands on is placeComposition's decision and it is a real one: the orbit arm clamps at 1.5 radii, and sunset at 1.04 radii is a stance four hundredths of a radius up. Three of the sixteen were ship-only for exactly this reason before the surface arm existed to receive them.

idstring
Undocumented

drag

drag(dxPixels: number, dyPixels: number, sensitivity: number) → void

Orbit by a pointer drag, in pixels.

The sensitivity defaults to the solved one rather than to 1, so a caller that omits it gets the lens's own pixel angle instead of a 4.8× drag at the flight lens. turn solves it internally for the same reason; the argument survives for a script that wants a stated rate.

dxPixelsnumber
Undocumented
dyPixelsnumber
Undocumented
sensitivitynumber
Undocumented

dragSensitivity

dragSensitivity() → number

Radians of camera motion per pixel of pointer, over the reference rate.

The one number every draggable camera reads; dragSensitivity.ts carries the two pixel counts it reconciles and why a constant cannot.

drop

drop(destination: string | undefined, point: { latitude: number; longitude: number }, options: { seconds?: number }) → ObserverStatus

Fly the camera from where it is down to a point on the ground, and stand there facing the star.

The one eased entry to the surface arm. stand cuts, and is right to: it is the instrument a plate is captured through, and a plate has to be the frame after the call returns. This is the other thing arriving can be — a picture of it — and it is asked for by a different gesture, the figure dragged from orbit onto a world. The path is the ballistic entry entryArc describes, walked down dropRadius's logarithmic schedule over seconds of wall clock; the camera watches the touchdown point on the way and turns to face the star along the horizon over the last third.

Everything about the release is measured before anything commits, for the reason stand gives at length: a refusal after a retarget would leave the planetarium looking at a body the call declined. The eye and its orientation are taken from the camera as it is — tracking transform and look offset included — and carried into the body's rotating axes, so the first frame of the drop is the frame before it and the arc lands where it was aimed however far the body turns underneath.

Presentation only, like every verb here: no teleport, no clock, no entity write. observatory.test.ts compares the state hash across one.

destinationstring | undefined
Undocumented
point{ latitude: number; longitude: number }
Undocumented
options{ seconds?: number }
Undocumented

entryArcPreview

entryArcPreview(destination: string | undefined, point: DropAim, samples: number) → { 6 fields } | null

Scene geometry in body radii, sharing the landing coordinate with release.

destinationstring | undefined
Undocumented
pointDropAim
Undocumented
samplesnumber
Undocumented

focus

focus(destination: string, options: { ease?: boolean; fill?: number }) → ObserverStatus

Point the observatory at something, and frame it.

Lenient about what it is handed, exactly like goTo: this is typed into a search box or clicked out of a list, and parseAddress is deliberately strict everywhere else. ease is what makes a click a move — the camera travels there rather than cutting, which is the whole reason to look at a planetarium instead of a table of coordinates.

destinationstring
Undocumented
options{ ease?: boolean; fill?: number }
Undocumented

framePair

framePair() → void

Fit the pair inside the vertical field while retaining its orbit angles.

frameTarget

frameTarget(fill: number) → void

Re-frame the current target so it fills fill of the frame height.

fillnumber
Undocumented

groundUnderRay

groundUnderRay(destination: string | undefined, direction: Vec3) → { address: string; latitude: number; longitude: number } | null

Where a ray from the eye meets a body's ground, as a latitude and longitude, or null when it misses.

The hit test behind the drop gesture. The pointer is a direction from the camera, and the answer is a point on the datum sphere — body.radius — rather than on the drawn terrain, because a fingertip is not aiming at a ridge, and finding where a ray enters a heightfield means sampling the field along it. The drop then lands on the drawn ground at that latitude and longitude, which is what the ring drawn there promised.

direction is in universe axes, which are also the render camera's: render space is a translation and a radial compression about the eye, and neither turns a direction. Nothing here reads a render position.

destinationstring | undefined
Undocumented
directionVec3
Undocumented

hold

hold() → ObserverStatus

Stop presentation travel at the current pose without touching the world.

holdGalaxyJourney

holdGalaxyJourney() → ObserverStatus

Hold the displayed pose, including an orbit gesture made during the journey.

leaveSurface

leaveSurface() → ObserverStatus

Back to orbit, at whatever framing the camera had before the descent.

levelToHorizon

levelToHorizon() → void

Put the horizon across the middle of the frame from where the eye is now.

The height comes from the stance rather than from a caller, because a panel reads the stance out of an 8 Hz sample: a control that solved the dip from the height it last saw would aim at 0.045° after a scrub to 400 km, and — worse — setStanceHeight decides whether to keep tracking the horizon by comparing the pitch it holds against the dip the current height implies, so a pitch solved from a stale height fails that test forever after and the tracking never resumes.

moveTo

moveTo(site: string | { latitude: number; longitude: number }) → void

Move the stance without changing the height or the heading.

sitestring | { latitude: number; longitude: number }
Undocumented

orbitPhase

orbitPhase(phase: number, rate: number, tilt: number) → void

An automatic phase sweep, in degrees per presented second, held while the clock is paused.

Presented rather than simulated seconds: the simulated clock runs at whatever time warp a flight session left behind, and the front door, which is the caller, is forbidden from changing that warp to fix it.

phasenumber
Undocumented
ratenumber
Undocumented
tiltnumber
Undocumented

pose

pose() → ObserverPose | null

The whole camera this instant — eye with its orientation — or null.

A reading, not sample(), for the same reason eye is one: the drop takes the camera as it stands at release, orientation included, and a verb that stepped the ease to find out where the camera was would move the thing it is measuring.

previewDrop

previewDrop(point: { latitude: number; longitude: number } | null) → void
point{ latitude: number; longitude: number } | null
Undocumented

previewLaunch

previewLaunch(hold: Vec3, up: Vec3) → void

Aim by a held point in body radii. Gravity chooses the touchdown.

holdVec3
Undocumented
upVec3
Undocumented

restore

restore(address: string, framing: { 6 fields }) → ObserverStatus
addressstring
Undocumented
framing{ 6 fields }
Undocumented

rise

rise(options: { clearance?: number; height?: number }) → { fovDeg: number; status: ObserverStatus }

Stand on this body with its parent a stated clearance over the horizon.

Earthrise, and the two-body composition it is the only example of. Every other picture here is relative to whatever is under the camera; this one names the other body, which is why it needs a verb of its own and why the lens is solved with it — Earth is 1.9° across from Luna and Mars is 42.39° from Phobos, and one focal length is not the picture for both.

Returns the field of view it solved, because the caller has to fit it: the observatory has no lens of its own by design (#lens says why), so the host's setFlightLens carries it to the flight lens and the standoff arithmetic here reads it back.

options{ clearance?: number; height?: number }
Undocumented

sample

sample(dt: number) → ObserverPose | null

The camera pose for this frame, or null when no target is set.

dt is wall-clock seconds — the same delta the render loop already has — because the easing is a presentation filter and must run at display rate even when the simulation is paused. A planetarium in which pausing time also freezes a fly-to mid-flight would be a bug in every screenshot.

dtnumber
Undocumented

setAngles

setAngles(azimuth: number, elevation: number, ease: boolean, look: LookOffset) → void

Set the orbit angles directly — the panel's presets and every composition.

The one writer that takes a look offset with the angles, because a composition that aims at a limb or a specular point is two numbers about the pose and one about the head. Absent, the head goes back to center: a composed picture replaces the pose, so carrying a viewer's free look into it would frame something other than what the composition names.

azimuthnumber
Undocumented
elevationnumber
Undocumented
easeboolean
Undocumented
lookLookOffset
Undocumented

setDistance

setDistance(distance: number, ease: boolean) → void

Set the distance directly — the panel's slider and the presets.

distancenumber
Undocumented
easeboolean
Undocumented

setHeading

setHeading(heading: number) → void

Compass heading in radians: 0 is north, increasing toward east.

headingnumber
Undocumented

setLook

setLook(yaw: number, pitch: number) → void

Aim the head at an absolute offset, radians. ir.aim.

yawnumber
Undocumented
pitchnumber
Undocumented

setPhase

setPhase(phaseDeg: number, elevationDeg: number, ease: boolean) → void

Move to a photographic phase angle — full face, gibbous, crescent.

The angle is measured against where the star actually is now, so the preset means the same thing at any point in a planet's year. That is the bug placeShot documents in the flight harness, met again here: a phase solved once against a stale sun line is right in one season and wrong in the other three.

phaseDegnumber
Undocumented
elevationDegnumber
Undocumented
easeboolean
Undocumented

setPitch

setPitch(pitch: number) → void

Above the horizontal, radians. Clamped short of vertical.

pitchnumber
Undocumented

setStanceFlight

setStanceFlight(flight: { fast: boolean; forward: number; right: number; up: number } | null) → void

Fly the stance with the keys: axes in the stance's own heading, -1..1.

The speed follows the height, a brisk walk two meters up and the whole planet in reach from the orbit floor, so one set of keys serves the shoreline and the crossing to the next continent. The heading is where the head is turned, which is what free look already sets; the keys do not turn it, so a viewer looking at a peak flies toward the peak.

flight{ fast: boolean; forward: number; right: number; up: number } | null
Undocumented

setStanceHeight

setStanceHeight(height: number) → void

Set the height above the ground, meters.

Direct manipulation, unfiltered, exactly like drag and for the same reason: this is a slider under a finger, and a damping filter between the finger and the picture is lag rather than easing.

heightnumber
Undocumented

setStanceScrub

setStanceScrub(t: number) → void

Set the height from a scrub position in [0, 1]. See heightForScrub.

tnumber
Undocumented

setTime

setTime(time: number | null) → void
timenumber | null
Undocumented

setTimePaused

setTimePaused(paused: boolean) → void
pausedboolean
Undocumented

setTimeScale

setTimeScale(scale: number) → void
scalenumber
Undocumented

sites

sites() → readonly SurveySite[]

The named places on the body being looked at. Empty for a star.

stanceBounds

stanceBounds() → { max: number; min: number }

The height band the surface arm covers here. Panels draw sliders against it.

stand

stand(destination?: string, options: { 6 fields }) → ObserverStatus

Put the camera on the ground.

Below MIN_DISTANCE_RADII, which the orbit arm refuses to go under and is right to: half a radius up is where a planetarium stops showing you a world and starts showing you ground with no horizon in it. What that clamp also prevented was ever inspecting a surface, so the only way to look at terrain was to fly a ship at it — which is the line in the plan's gap table that says iteration and testing both pay for it.

Read-only like everything else here. No teleport, no clock, no entity write: it samples surfaceRadius and returns a camera pose, and observatory.test.ts's state-hash comparison covers this arm too.

Entering is a cut, not a fly-to, and that is deliberate. The orbit arm eases because a transition across fourteen decades has to read as a move; this one is the instrument a plate is captured through, and an ease means every capture has to wait an unspecified number of frames for a filter to settle before the picture is the picture. ir.visit returns and the frame after it is the frame you asked for.

It resolves before it commits, and the ordering is the whole of two bugs. Calling focus first is the obvious shape and is wrong twice. focus re-solves the distance from framingDistance, so a stand on the body already held silently discarded the framing the user had zoomed to — and leaveSurface then "restored" a default nobody had chosen, which is exactly the thing four docstrings here promise it does not do. And because the surface check ran after the commit, stand('s:SOL/b:5') retargeted the camera to Saturn and only then threw "no surface to stand on", leaving the planetarium looking at a body the call had refused.

destinationstring
Undocumented
options{ 6 fields }
Undocumented

startMotion

startMotion(recipe: ObserverMotionRecipe) → boolean

A finite, target-relative move sampled by this camera's existing owner.

recipeObserverMotionRecipe
Undocumented

status

status() → ObserverStatus

stopMotion

stopMotion() → boolean

Stop only future recipe frames; the sampled view keeps its revision.

track

track(address: string | null) → ObserverStatus

Target a companion while keeping the current orbit anchor and composition.

addressstring | null
Undocumented

travelGalaxy

travelGalaxy(progress: number, seconds: number) → ObserverStatus
progressnumber
Undocumented
secondsnumber
Undocumented

turn

turn(dxPixels: number, dyPixels: number) → void

Turn the head by a drag, in pixels.

On the ground the offset is the heading and the pitch, which the stance already holds — so this is the one verb that writes through both arms, and the orbit writers' refusal does not apply to it. That refusal is why this verb exists: with it and nothing else listening, a drag on Miranda's summit does nothing at all.

sensitivity is pixelAngle(lens, viewport) / DRAG_RADIANS_PER_PIXEL when a caller has a display, which makes the ground under the pointer follow the pointer at any lens. Solved here rather than at the call site because the observatory already reads the lens and a second reader of it is a second idea of the optics.

dxPixelsnumber
Undocumented
dyPixelsnumber
Undocumented

validatePicture

validatePicture(address: string, framing: PictureFraming) → void
addressstring
Undocumented
framingPictureFraming
Undocumented

viewGalaxy

viewGalaxy(view: 'face-on' | 'edge-on') → ObserverStatus
view'face-on' | 'edge-on'
Undocumented

zoom

zoom(factor: number) → void

Zoom by a ratio. Above 1 retreats.

factornumber
Undocumented

zoomNotches

zoomNotches(notches: number) → void

Zoom by whole wheel notches. Positive retreats.

notchesnumber
Undocumented

Generated from the source of @inertialref/devtools and its comments. Nothing on this page is written by hand.