Fill: honour the half-spacing edge rule when packing plops (#75)
Filling a bed left the outer row too far from the edge, and staggered rows worse still. Two defects, both from anchoring the lattice at the region's min corner: - Odd rows offset by `radius` started at `MinX + 2·radius`, leaving a bare strip a whole plop wide down one side of every other row. - All the leftover slack piled up on the far edge, where plops hung 13cm outside the bed on a 4×8ft garlic bed. Nothing clips them, so they drew over the bed outline. Spacing is a constraint between neighbouring plants competing for the same soil, light and water. A bed edge is not a competitor, so the outer row owes it half the spacing — the arithmetic inside every square-foot-gardening chart (4/square = 6" apart, 3" from the square's edge). The wrinkle: a plop is a CLUMP, not a plant. defaultPlopRadius is 1.5×spacing, so keeping the whole circle inside the bed insets the outer row by 1.5 spacings, three times what the rule allows. So centre the lattice and set the minimum centre-inset to `radius - spacing/2`: the clump may cross the edge by up to half a spacing, putting its outermost plants exactly the half-spacing from the edge the rule asks for. Capped there — a clump mostly outside the bed would be a drawing of plants in the path. Same bed, same 15 plops, now symmetric with a deliberate 6.5cm overhang inside the 7.5cm budget instead of an accidental 13cm on one side only. The stagger falls out of the centring for free: an offset row holds one fewer plop, and centring that run puts it exactly half a pitch off its neighbours. TestFillRegionDeterministicPacking expected 4 plops in a 60×60 bed; the fourth was centred ON the east edge with half of it outside, well past the budget. It is 3 now — the fix working, not a regression in it. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01H3zbym8Doka2d7D48maSgZ
This commit is contained in:
@@ -85,6 +85,12 @@ Frontend: React 19 + Vite + Tailwind 4 + TanStack Router/Query, built into
|
||||
deliberately. `ErrForbidden` means "you can see it but may not do that".
|
||||
- **Plops (plantings) live in their parent object's local frame**, origin at the
|
||||
object's center, `-y` is north. Moving or rotating a bed moves its plants free.
|
||||
- **A plop is a clump, not a plant.** `defaultPlopRadius` is `1.5 × spacing`, so a
|
||||
plop is three spacings across and holds `π·r²/spacing²` plants. Reasoning about
|
||||
fills as if one plop were one plant gets the geometry wrong every time — which
|
||||
is how #75 happened: requiring the whole circle inside the bed inset the outer
|
||||
row by 1.5 spacings when the horticultural rule is *half* a spacing. Spacing is
|
||||
a constraint between neighbouring plants; a bed edge is nobody's neighbour.
|
||||
- **Soft removal**: "clear bed" sets `removed_at`; the editor reads
|
||||
`removed_at IS NULL`. Hard delete is a different operation.
|
||||
- **Migrations** are numbered `.sql` files in `internal/store/migrations/`, run
|
||||
|
||||
Reference in New Issue
Block a user