Lower the star halo floor so the inner orbits stay legible

The floor that stopped the Sun disappearing reached past Venus and up to
Earth, covering the two orbits it most needed to leave alone.

Halved, from 3.5% of the framed radius to 2%. The halo's visual radius is
half its extent, so that puts its edge at 1% of the framed radius, and the
orbits it has to clear sit at their own fraction of the same radius: in
the solar system, framed to hold Pluto, Venus is at 1.3% and Earth at
1.8%. Both are now outside it, and the star still reads at about nine
pixels across on a typical window.

Mercury, at 0.7%, is still inside — and would be at any halo large enough
to see, since its orbit is only three pixels wide at that range. That is
now a pinned test rather than an oversight.

The floor was only ever the lower bound; the tests now state the upper one
too, in the terms the trade is actually made in — pixels on screen for
visibility, AU against real orbits for clearance.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WaySiNst4HhDXBHnMy8p5G
This commit is contained in:
Claude
2026-08-05 08:01:19 +00:00
parent be19d9cbcc
commit 029162ff52
3 changed files with 48 additions and 9 deletions
@@ -114,13 +114,27 @@ describe('systemFramingDistanceAu', () => {
});
describe('starGlowExtentAu', () => {
/** A typical viewport, so a screen-space claim can be made in pixels rather than in ratios. */
const REFERENCE_VIEWPORT_HALF_HEIGHT_PX = 450;
/** The halo's visual radius, in AU, at the distance this system is framed from. */
function haloRadiusAu(innermostAu: number, outermostAu: number, glowScale = 1): number {
// The sprite's extent is its full width, so half of it is what reaches out from the star.
return starGlowExtentAu(starMarkerRadiusAu(innermostAu), frameRadiusFor(outermostAu), glowScale) / 2;
}
function frameRadiusFor(outermostAu: number): number {
const rings = systemGridRingsAu(outermostAu);
return systemFrameRadiusAu(systemFramingDistanceAu(rings[rings.length - 1]));
}
/** Apparent size on screen, as a fraction of the frame's half-height. */
function apparentFraction(innermostAu: number, outermostAu: number, glowScale = 1): number {
const rings = systemGridRingsAu(outermostAu);
const distance = systemFramingDistanceAu(rings[rings.length - 1]);
const frame = systemFrameRadiusAu(distance);
// The sprite's extent is its full width, so half of it is what reaches out from the star.
return starGlowExtentAu(starMarkerRadiusAu(innermostAu), frame, glowScale) / 2 / frame;
return haloRadiusAu(innermostAu, outermostAu, glowScale) / frameRadiusFor(outermostAu);
}
function apparentPixels(innermostAu: number, outermostAu: number): number {
return apparentFraction(innermostAu, outermostAu) * REFERENCE_VIEWPORT_HALF_HEIGHT_PX;
}
it('scales with the star for a compact system, where the star is already big enough', () => {
@@ -142,7 +156,23 @@ describe('starGlowExtentAu', () => {
it('keeps the Sun visible at the distance that frames the solar system', () => {
// The case that prompted this: the solar system spans a factor of a hundred from Mercury to
// Pluto, so a disc that stays clear of Mercury is about a pixel across once Pluto is in view.
expect(apparentFraction(0.387, 39.288)).toBeGreaterThan(0.015);
expect(apparentPixels(0.387, 39.288)).toBeGreaterThan(4);
});
it('leaves the inner orbits clear of the halo', () => {
// The other half of the same trade. Venus and Earth have to stay legible as rings around the
// star, which bounds the halo from above just as visibility bounds it from below.
const halo = haloRadiusAu(0.387, 39.288);
const VENUS_AU = 0.723;
const EARTH_AU = 1;
expect(halo).toBeLessThan(VENUS_AU);
expect(halo).toBeLessThan(EARTH_AU);
});
it('cannot clear Mercury as well, and does not pretend to', () => {
// Mercury's orbit is 0.7% of the framed radius — about three pixels — so it is inside any
// halo big enough to see. Pinned so the trade is a decision rather than an oversight.
expect(haloRadiusAu(0.387, 39.288)).toBeGreaterThan(0.387);
});
it('holds the floor across every system scale the datasets contain', () => {
@@ -154,7 +184,7 @@ describe('starGlowExtentAu', () => {
[0.01154, 0.06189],
[1.2, 12.4]
]) {
expect(apparentFraction(innermost, outermost)).toBeGreaterThan(0.015);
expect(apparentPixels(innermost, outermost)).toBeGreaterThan(4);
}
});
@@ -41,9 +41,16 @@ const STAR_RADIUS_TO_INNERMOST_ORBIT = 0.45;
* The halo resolves it, because light is not a surface: a glow that reaches past the innermost
* orbit does not claim the star is that large, it claims the star is bright. So the disc stays
* honest to the orbits and the halo is floored against the frame.
*
* The floor is set by what it must not cover. Its visual radius is half the extent, so a floor
* of `f` puts the halo's edge at `f / 2` of the frame radius — and the orbits it has to leave
* legible sit at their own fraction of that same radius. In the solar system, framed to hold
* Pluto, Venus's orbit is at 1.3% of the frame radius and Earth's at 1.8%, so a floor of 2%
* leaves both of them outside the halo. Mercury's, at 0.7%, is inside it — and would be at any
* halo large enough to see, since the orbit itself is only a few pixels wide there.
*/
const STAR_GLOW_TO_MARKER = 3.2;
const MIN_STAR_GLOW_TO_FRAME = 0.035;
const MIN_STAR_GLOW_TO_FRAME = 0.02;
/**
* Clear space left around the framed radius, as a fraction of it. The camera backs off this