Frame the Sun's system out to Eris on a portrait window, where Eris and Makemake arrived off screen

The arrival framing fits the grid's outer ring, which Eris (a = 67.93 AU) took from 40 AU to 80,
but its 200 AU ceiling was sized for Pluto's ring. At 390 by 844 the ring needs 416 AU and at 1000
by 1400 269, so both were clamped to 200: Eris arrived at NDC (2.08, 0.48) on the phone, with
Makemake at (-1.14, -0.25), and at (1.34, 0.48) on the tall window. The spec never saw it, its
solar system ending at Neptune.

The ceiling is now 500 AU, which frames the 80 AU ring at any aspect down to 0.385; the landscape
fit is unchanged. The window-shape test now includes the solar system out to Eris and a 390 by 844
phone. In the running app every top-level body is on screen on arrival: the camera at 415.8 AU on
390x844, 269.0 on 1000x1400 and 192.1 on 1600x1000.

Control: the ceiling back at 200 fails "leaves the outermost ring clear of the frame edge at every
scale and window shape".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-29 19:42:23 +02:00
co-authored by Claude Opus 5.5
parent 8c4f1c11c9
commit 6c0626ca38
2 changed files with 11 additions and 6 deletions
@@ -18,6 +18,8 @@ import {
const TRAPPIST_1 = { innermost: 0.01154, outermost: 0.06189 };
const GL_357 = { innermost: 0.035, outermost: 0.204 };
const SOLAR = { innermost: 0.387, outermost: 30.07 };
/** The solar system as the map draws it: out to Eris's semi-major axis, 67.93 AU. */
const SOLAR_TO_ERIS = { innermost: 0.387, outermost: 67.93 };
describe('starMarkerRadiusAu', () => {
it('never reaches the innermost orbit', () => {
@@ -123,14 +125,15 @@ describe('the grid and the framing together', () => {
const VIEWPORTS: SystemViewport[] = [
{ fovDegrees: 50, aspect: 1.78 },
{ fovDegrees: 50, aspect: 1 },
{ fovDegrees: 50, aspect: 0.6 }
{ fovDegrees: 50, aspect: 0.6 },
{ fovDegrees: 50, aspect: 390 / 844 } // a phone held upright
];
it('leaves the outermost ring clear of the frame edge at every scale and window shape', () => {
// The whole point of framing against the grid rather than the orbits: before this, 368 of
// the 371 systems in the datasets drew a grid wider than the view that was meant to hold it.
for (const viewport of VIEWPORTS) {
for (const { outermost } of [TRAPPIST_1, GL_357, SOLAR, { outermost: 1 }, { outermost: 12.4 }]) {
for (const { outermost } of [TRAPPIST_1, GL_357, SOLAR, SOLAR_TO_ERIS, { outermost: 1 }, { outermost: 12.4 }]) {
const { ring, frame } = fit(outermost, viewport);
expect(ring).toBeLessThan(frame);
expect(ring / frame).toBeLessThan(0.93);
@@ -61,13 +61,15 @@ const MIN_FRAMING_DISTANCE_AU = 0.06;
/**
* Ceiling on the framing distance, so a distant companion does not push the star to a dot.
*
* Generous enough to frame the solar system out to Pluto in any window shape, which needs 120 AU
* on a landscape display and 140 on a portrait one once the camera's real field of view is
* accounted for. Only genuinely pathological systems reach it now — the handful with
* Generous enough to frame the solar system out to Eris in any window a reader holds: its grid's
* outer ring, 80 AU, needs 192 AU on a landscape display and 416 on a 390 by 844 phone once the
* camera's real field of view is accounted for, and 500 holds it down to an aspect of 0.385. At
* 200, which framed Pluto's 40 AU ring, a portrait window arrived with Eris off screen, and a
* phone with Makemake too. Only genuinely pathological systems reach it now — the handful with
* directly-imaged companions hundreds of AU out — and those still arrive framed on their inner
* region, with the orbit controls reaching far enough to pull back to the rest.
*/
const MAX_FRAMING_DISTANCE_AU = 200;
const MAX_FRAMING_DISTANCE_AU = 500;
/** Framing for a star with no known planets, where there is nothing to fit. */
const EMPTY_SYSTEM_FRAMING_DISTANCE_AU = 3;