package detail import "salty/terrain/internal/manifest" // MarginCells is the overlap a tile must carry for the particle pass, in detail cells. // // Rule 2 of the tiling plan says to size a margin by how far the pass can move material, and for droplets // that is not simply the lifetime. Within one round a droplet travels at most its lifetime, plus one cell for // the cut brush. Across rounds the error compounds: a droplet in round two reads heights the round-one // droplets moved, so the cut edge's influence walks a lifetime further in with every round. // // Taking that literally would make the margin `rounds * lifetime`, which at the defaults is 640 cells against // a 2500-cell tile. Measured instead, at lifetime 12 and 8 rounds (TestHowFarTheCutEdgeReachesIn), the worst // difference between a tile and the same ground in one whole run falls off much faster than that: // // cells in from the cut edge: 0 4 8 12 16 20 24 32 40 // worst difference, metres: 7.97 2.53 0.72 0.49 0.44 0.18 0.03 0.00 0.00 // // It is the first lifetime that carries almost all of it, and by three the error is gone - a droplet has to be // unlucky in the same way several rounds running for it to keep propagating, and that stops happening. Three // lifetimes plus the brush is the margin, which at the default lifetime of 40 is 122 detail cells, 244 m, or // about five per cent of a 5 km tile on each side. func MarginCells(cfg manifest.Particle) int { life := cfg.Lifetime if life < 1 { life = 1 } return 3*life + 2 }