forked from 1b-agent/opencadstudio-upstream
fix(hatch): preserve all island loops in complex hatches (#148)
The hatch boundary was flat-truncated to 1024 vertices before upload. The active renderer is the batched path, which stores boundaries in a GPU storage buffer with no length limit, so the cap only ever served the per-hatch uniform path (now wipeout-only, and self-clamping). On a real drawing a 36-loop, depth-3 nested hatch (1482 verts) was cut mid-boundary: trailing island loops were dropped and the final partial loop was left open, flipping the even-odd parity so the fill bled across the rest of the shape and islands rendered incorrectly. Drop the flat truncate. Keep every loop; only guard pathological vertex counts (16384), and when trimming, cut at a NaN sentinel (whole-loop boundary) so no sub-loop is ever left open. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
e6e8167b36
commit
6fb5c89a7b
1 file changed
+20
-1
+20
-1
@@ -5063,7 +5063,26 @@ impl Scene {
|
||||
if boundary.is_empty() {
|
||||
return None;
|
||||
}
|
||||
boundary.truncate(model::hatch_model::MAX_HATCH_BOUNDARY_VERTS);
|
||||
// The batched hatch renderer keeps boundaries in a GPU storage
|
||||
// buffer (no fixed length), so a hatch with many island loops must
|
||||
// retain *every* loop or even-odd island detection breaks. The old
|
||||
// flat `truncate(1024)` cut complex multi-loop hatches mid-boundary:
|
||||
// trailing islands were dropped and the final partial loop was left
|
||||
// open, flipping the even-odd parity so the fill bled across the
|
||||
// rest of the shape. Only guard against pathological vertex counts,
|
||||
// and when trimming, cut at a whole-loop (NaN sentinel) boundary so
|
||||
// no sub-loop is ever left open. (#148)
|
||||
const MAX_HATCH_MODEL_VERTS: usize = 16_384;
|
||||
if boundary.len() > MAX_HATCH_MODEL_VERTS {
|
||||
// Drop only whole trailing loops: cut at the last NaN sentinel
|
||||
// at/before the cap. If the first loop alone exceeds the cap,
|
||||
// keep it whole rather than leaving it open.
|
||||
let cut = boundary[..MAX_HATCH_MODEL_VERTS]
|
||||
.iter()
|
||||
.rposition(|&[x, y]| x.is_nan() || y.is_nan())
|
||||
.unwrap_or(boundary.len());
|
||||
boundary.truncate(cut);
|
||||
}
|
||||
|
||||
let pattern = if dxf.gradient_color.is_enabled() {
|
||||
let color2 = dxf
|
||||
|
||||
Reference in new issue
Block a user