Scales and display choices

Space is almost entirely empty. Rendering it “to scale” with everything in the same frame is impossible on any normal display. Each view makes a specific compromise.

The problem, in one table

At true proportional scale with Earth’s orbit drawn at 15 world units:

Object True radius (world units) Where it’d appear
Sun 109 Larger than Mars’s orbit
Earth 1.0
Jupiter 11.2 Visible dot
Neptune 3.9 Invisible dot at x=451
Pluto ~0.7 Lost in the noise

At this scale the Sun is bigger than the inner solar system, and Neptune is literally off the screen. That’s why almost every solar-system image you’ve seen — including NASA’s own educational art — cheats on distance, size, or both.

What each view cheats on

solar-system.html — the “pleasing” view

Compresses both sizes and distances so the whole system fits comfortably. Orbital periods (speeds) stay accurate.

Planet    Real scaled   This view   Compression
Mercury   5.85          8           1.37×
Earth     15 (anchor)   15          1×
Jupiter   78            28          0.36×
Neptune   451           58          0.13×

Gas giants are also drawn at ~30% of their true relative radius so they don’t dominate.

Moon systems (Jupiter, Saturn) use an additional moonScale: 0.5 so that the outermost moon orbit rings (Callisto, Iapetus) stay within their planet’s gap and do not overlap neighbouring planet orbit rings.

Goal: you can see all 8 planets at once.

scale.html — the “honest” view

Keeps sizes AND distances at their real proportions. Uses 1 unit = 100 000 km, so:

Planets are therefore essentially invisible at any zoom that shows more than one of them. The view compensates with pixel-size marker sprites that stay constant on screen regardless of camera distance, so bodies are findable from far out. Zoom in to see the actual sphere.

Goal: you can feel how empty the solar system really is.

galaxy.html — the Milky Way

Compresses the Milky Way (100 000 ly diameter) into a 500-unit-radius disk. The Sun orbits a galactic centre 150 units away, which is a reasonable approximation of its real 26 000 ly from Sagittarius A* at this scale.

Stars rotate differentially (ω = v_c / r) in a vertex shader — so stars at the Sun’s radius move with it, inner stars whip around faster, outer stars lag. This is physically accurate for the Milky Way’s flat rotation curve. See physics.md § Galactic rotation.

Goal: you can see the Sun’s place in the galaxy and how the galaxy rotates.

universe.html — the cosmic hierarchy

1 world unit = 1 million light-years. At this scale the Milky Way is a 0.1-unit disk and the observable universe is a 46 000-unit sphere. Switches between preset zoom levels (Local Group → Virgo Supercluster → Laniakea → Cosmic Web → Observable Universe) with labels appearing and disappearing based on camera distance.

Named objects (Andromeda, Virgo Cluster, Great Attractor, etc.) are placed at their real RA/Dec directions from the Milky Way — the cosmic web filaments and background galaxies are procedural.

Goal: you can navigate the structure of the cosmos.

Why not always “to scale”?

For intuition-building, compression beats accuracy. The pleasing view is more useful for “here’s what the solar system is” than the honest one — because on the honest one, you can’t see anything. The combination of both (and clear honesty about which is which) is the pedagogical sweet spot.

Slider-driven unification (#91)

solar-system.html now exposes two scale sliders (size, distance) that interpolate per-planet between the compressed PLANETS-table values (slider 0) and real astronomical proportions (slider 1). The “pleasing view vs honest view” framing collapses into a single view where the user feels the compromise rather than choosing between two static visualizations. Slider 1 is the same physical reality scale.html shows; once the slider covers all of scale.html’s use cases, scale.html is deleted as a follow-up cleanup.

The slider state is also a programmatic, animatable axis of the storytelling stack: setScale({ size, distance }, { duration, curve }) and per-body setBodyScale(id, …) are the same API shape voyage scripts use on the time and (forthcoming) model axes. See docs/storytelling.md for the cross-axis conventions.

Exaggeration sub-axis

A third slider exposes the implicit ~1500× radius inflation at slider position 1. The two endpoints in solar-system.html use different rulers — radii are anchored on Earth-radius=1 unit, distances on 1 AU=15 units — and the ratio between those rulers is the inflation. At exaggeration=0 the radius ruler collapses onto the distance ruler (planets become sub-pixel; markers take over via the existing #91 fade logic). At exaggeration=1 the scene matches the pre-amendment behavior. At exaggeration=2 (cinematic) radii are doubled over the default.

STRICT_FACTOR = EARTH_RADIUS_KM / (KM_PER_AU / 15) ≈ 1/1565 is derived in solar-system-scale.js from src/data/constants.js and the project convention “Earth at world distance 15 in solar-system.html”. Mapping is log-uniform on slider [0, 1] (continuity at pivot, otherwise 99% of the slider feels “barely visible”) and linear on [1, 2].

← Astrarium