From f8929a19a8b7f47613f6e91bce326991299710e2 Mon Sep 17 00:00:00 2001 From: Steve Dudenhoeffer Date: Tue, 21 Jul 2026 10:23:22 -0400 Subject: [PATCH] Address Gadfly findings on #76 - clampTo's doc justified itself by stopping hexCenters "looping forever", which stopped being true when hexCenters became count-bounded. Say what it actually does now, and note the inversion the new guard relies on. - Trim the changelog prose from hexCenters' doc down to the one line that earns its keep: don't re-anchor at the min corner, and why. - Rename a test local from `max` so it stops shadowing the builtin. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ --- internal/service/ops.go | 12 +++++++----- internal/service/ops_test.go | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/internal/service/ops.go b/internal/service/ops.go index a0c9865..f1e18be 100644 --- a/internal/service/ops.go +++ b/internal/service/ops.go @@ -29,7 +29,10 @@ type Region struct { } // clampTo intersects the region with an object's local bounds (±halfW, ±halfH), -// so an oversized caller-supplied region can't make hexCenters loop forever. +// so a fill can't plant outside the object it was aimed at. +// +// Note this INVERTS (Max ends up below Min) rather than empties a region that +// misses the object altogether — hexCenters treats that as "nothing to plant". func (r Region) clampTo(halfW, halfH float64) Region { return Region{ MinX: math.Max(r.MinX, -halfW), MinY: math.Max(r.MinY, -halfH), @@ -187,10 +190,9 @@ type localPoint struct{ x, y float64 } // the edge that the rule asks for. Overhang is capped there and nowhere near the // full radius: a clump mostly outside the bed is a drawing of plants in the path. // -// Anchoring at the min corner instead (what this did originally) was wrong twice -// over: staggered rows started a FULL pitch in, leaving a clump-sized bare strip -// down one side of every other row, while the far edge had clumps hanging off it -// by 13cm — and nothing clips them, so they drew outside the bed. +// Do not "simplify" this back to anchoring at the region's min corner. That is +// what #75 was: staggered rows start a full pitch in, and the leftover all lands +// on the far edge, where clumps hang outside a bed that nothing clips them to. func hexCenters(r Region, radius, spacing float64) []localPoint { if radius <= 0 { return nil diff --git a/internal/service/ops_test.go b/internal/service/ops_test.go index d36e499..18e6939 100644 --- a/internal/service/ops_test.go +++ b/internal/service/ops_test.go @@ -103,14 +103,14 @@ func TestHexCentersEdgeInset(t *testing.T) { // A clump may cross the edge, but only by the half-spacing the rule // allows — never enough to be mostly out in the path. - max := tc.spacing / 2 + budget := tc.spacing / 2 for _, p := range pts { over := math.Max( math.Max(r.MinX-(p.x-tc.radius), (p.x+tc.radius)-r.MaxX), math.Max(r.MinY-(p.y-tc.radius), (p.y+tc.radius)-r.MaxY), ) - if over > max+1e-6 { - t.Errorf("plop at (%.1f,%.1f) overhangs by %.2f, max %.2f", p.x, p.y, over, max) + if over > budget+1e-6 { + t.Errorf("plop at (%.1f,%.1f) overhangs by %.2f, budget %.2f", p.x, p.y, over, budget) } }