Turn Eris, Haumea, Makemake and Nereid on their pages at their measured days on the map's clock

The body page's comment said the body is drawn at the clock's date and turns at its rate, but a
body with no IAU model turned 0.08 radians a second of wall time whatever the clock said: on
Nereid's, Eris's, Haumea's and Makemake's pages the Clock tab's rates and Backwards changed
nothing (Nereid 4.58 degrees a second at every rate), while the system view turns them at their
measured days on the clock. Hyperion spun the same way on its page and is still in the system
view, where it tumbles and has no day.

A body whose day is measured but whose pole is not now turns pole up at that day, counted from its
orbit's epoch as spinFor counts it; Hyperion is left still; only an exoplanet, whose day no one has
measured, still turns for show. The template comment now says so, and the tick doc names all
five bodies. Live on :4301, degrees a wall second at clock rates 1, 3600 and -3600: Nereid 0.009,
31.05, 31.08 (360/11.594 = 31.05); Eris 0, 0.951, 0.955 (360/378.504 = 0.951); Hyperion 0, 0, 0;
Mars, by its IAU elements, 0.004, 14.67, 14.56.

That makes the sphere reset when a body is shown matter for Hyperion and an exoplanet. The test the
earlier fix added for that reset checked only the light, and deleting the reset passed the suite;
a test now opens Hyperion after Earth and expects the sphere at rest (Earth left it 0.89 radians
turned). Eris's page test checks it stands while the clock stands and turns a sixth of a turn in
a sixth of its 378.504-hour day, pole up.

Guarded mutants (full suite), each failing only its named test: the day ignored and Eris turned
for show ('turns a body whose day is measured'); Hyperion turned for show, and the reset deleted
(both 'puts the sphere back at rest ... Hyperion after Earth').

Unit suite 862/862, tsc -p tsconfig.app.json and etl:typecheck clean.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-30 17:33:01 +02:00
co-authored by Claude Opus 5.5
parent a9e910c2ea
commit 7080a5a817
2 changed files with 41 additions and 8 deletions
@@ -34,9 +34,11 @@ const SATURN: BodyRecord = {
rates: {meanMotionDegPerDay: 0.033459683702669406, longitudeOfAscendingNodeDegPerDay: -0.000006848734291581108, argumentOfPeriapsisDegPerDay: 0.000021682266940451745},
rotationalElements: {poleRaDeg: [40.589, -0.036, 0], poleDecDeg: [83.537, -0.004, 0], primeMeridianDeg: [38.9, 810.7939024, 0]}
};
// Eris as it is shipped for this page's purposes: no IAU model, so its page keeps its own light.
const ERIS: BodyRecord = { ...EARTH, id: 'eris', name: 'Eris', kind: 'dwarf', radiusKm: 1163, rotationalElements: undefined };
const BODIES = [EARTH, SATURN, ERIS];
// Eris and Hyperion as they are shipped for this page's purposes: no IAU model, so their pages keep
// their own light; Eris's day is measured, and Hyperion tumbles and has none.
const ERIS: BodyRecord = { ...EARTH, id: 'eris', name: 'Eris', kind: 'dwarf', radiusKm: 1163, rotationalElements: undefined, rotationPeriodHours: 378.504 };
const HYPERION: BodyRecord = { ...ERIS, id: 'hyperion', name: 'Hyperion', kind: 'moon', radiusKm: 135, parentBodyId: 'saturn', rotationPeriodHours: undefined };
const BODIES = [EARTH, SATURN, ERIS, HYPERION];
/** Stands in for the WebGPU engine: a scene, a camera, and the tick hook, driven by hand. */
class FakeEngineService {
@@ -155,6 +157,30 @@ describe('BodyDetailSceneComponent', () => {
expect(page.sunLight.position.distanceTo(new THREE.Vector3(4, 3, 5))).toBeLessThan(1e-9);
});
it('puts the sphere back at rest when the next body shown does not turn: Hyperion after Earth', async () => {
await open('earth');
expect(page.planet.quaternion.angleTo(new THREE.Quaternion())).toBeGreaterThan(0.1);
route.next(convertToParamMap({ id: 'hyperion' }));
await flushAsync();
engine.tick(0.016);
engine.tick(0.016);
expect(page.planet.quaternion.angleTo(new THREE.Quaternion())).toBeLessThan(1e-9);
});
it('turns a body whose day is measured but not its pole at that day on the map’s clock: Eris a sixth of a turn in 63.084 hours', async () => {
await open('eris');
const start = page.planet.rotation.y;
// The clock stands (the page is opened at rate 0): so does Eris, where it used to turn for show.
engine.tick(1);
expect(page.planet.rotation.y).toBe(start);
time.setDate(new Date(Date.parse('2025-06-01T12:00Z') + (378.504 / 6) * 3600000));
engine.tick(0.016);
const turned = (((page.planet.rotation.y - start) / (2 * Math.PI)) % 1 + 1) % 1;
expect(turned).toBeCloseTo(1 / 6, 6);
// Pole up, as the system view turns it about its orbit's normal.
expect(new THREE.Vector3(0, 1, 0).applyQuaternion(page.planet.quaternion).y).toBeCloseTo(1, 12);
});
it('says on its dock the date the body is drawn for, and nothing at the present, and offers the clock', async () => {
await open('saturn', '2032-06-01T12:00Z', true);
fixture.detectChanges();