Measure the ring span along the plane the rings lie in
The span went to `distanceRings` as the target's straight-line distance from the Sun, but a ring of radius r passes within |r - p| of the view's centre, where p is how far out that centre is *along* the galactic plane. For a target above the plane the two differ by its height, so the band was centred on a radius no ring has — and `ringLabels` picks its bearing by comparing its own in-plane distance against the innermost ring, a comparison the new first ring quietly broke. Two comments and a constant, from the same review. A frame short of the survey edge gets its callout only when its last ring overshoots it: 245 pc does, 235 pc does not, which is now a test rather than a sentence. The ring count can reach 16, not 14, now that the span need not start at the Sun. And a ring label was measured as 135 px of star name when "50 pc" is a third of that, which rejected rungs a hand's breadth clear of the name: RING_LABEL_REACH_NDC, 0.23, is the widest of them — "1.5 kpc" with "Survey edge" under it. Three mutants, three caught. Measured again in the app: unchanged for a star in the plane (4 labels at 20 pc above it, 7 at 2 pc), and the rings now follow the plane for one 195 pc above it rather than ringing a place the grid does not reach. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016jxMkwA2rbicdGxHosecYi
This commit is contained in:
@@ -58,6 +58,10 @@ describe('distanceRings', () => {
|
||||
|
||||
it('leaves the callout out when it is past the last ring, or behind the first', () => {
|
||||
expect(distanceRings(0, 100, 5, 250)).toEqual([20, 40, 60, 80, 100]);
|
||||
// Short of the survey edge by less than one step is not the rule — the last ring is: 245 pc
|
||||
// overshoots to 260 and gets it, 235 pc stops at 240 and does not, on the same 20 pc step.
|
||||
expect(distanceRings(0, 245, 5, 250)).toContain(250);
|
||||
expect(distanceRings(0, 235, 5, 250)).not.toContain(250);
|
||||
expect(distanceRings(400, 440, 5, 250)).toEqual([400, 405, 410, 415, 420, 425, 430, 435, 440]);
|
||||
});
|
||||
|
||||
|
||||
@@ -19,16 +19,18 @@ export function roundLengthAtMost(value: number): number | null {
|
||||
* Rings across the span from `nearest` to `reach`, at a round step of about a `count`th of it,
|
||||
* plus `callout` where it falls between the first ring and the last: the grid's own radii are
|
||||
* round, and the one radius that means something in its own right is marked whether the step lands
|
||||
* on it or not. A frame short of it by less than one step still gets it, since the last ring
|
||||
* overshoots `reach`; one that stops well short does not.
|
||||
* on it or not. A frame that stops short of it gets it only when the last ring — the first multiple
|
||||
* of `step` at or past `reach` — is past it: reach 245 with a 20 pc step gets it, reach 235 does
|
||||
* not, since its last ring is 240.
|
||||
*
|
||||
* Two numbers rather than one because these rings are centred on a fixed point — the Sun — and a
|
||||
* frame need not be. Looking at something 200 pc out from 20 pc away, what is on screen is a band
|
||||
* 200 pc wide at its narrowest and nowhere near the Sun; a step sized to the whole 220 puts every
|
||||
* ring off the frame. The span is what the frame covers, so the step is what it can resolve.
|
||||
*
|
||||
* Rounding the step down makes for `count` to `ceil(2.5 × count)` rings, and the callout can add
|
||||
* one: 5 to 14 for a count of 5.
|
||||
* Rounding the step down, over a span that need not start at the Sun, makes for `count` to
|
||||
* `ceil(2.5 × count) + 2` rings — `ceil(reach / step) - floor(nearest / step) + 1` — and the
|
||||
* callout can add one: 5 to 16 for a count of 5.
|
||||
*/
|
||||
export function distanceRings(nearest: number, reach: number, count: number, callout: number): number[] {
|
||||
const step = roundLengthAtMost((reach - nearest) / count);
|
||||
|
||||
Reference in New Issue
Block a user