forked from 1b-agent/opencadstudio-upstream
fix(paper): handle NaN sentinels when building hatch fill path
`HatchModel.boundary` stores multi-region hatches as a single Vec with NaN-NaN sentinels separating each disconnected sub-path (documented on the field). The paper-canvas hatch fill ignored the sentinels and forwarded every vertex straight to the iced canvas path builder. When a layout contained a multi-region hatch, lyon received a polygon containing NaN coordinates and panicked with `Tessellate path.: Internal(IncorrectActiveEdgeOrder(4))` from inside `iced_wgpu::geometry::Frame::fill`, taking the whole app down the first time Layout 1 painted. Walk the boundary instead, opening a fresh sub-path on each sentinel and closing whichever was active. Each region is now filled as its own closed polygon. Reproduces with #22. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
a3e9b05130
commit
e55b280dda
1 file changed
+24
-5
@@ -174,13 +174,32 @@ fn draw_hatch(frame: &mut canvas::Frame, hatch: &HatchModel, to_px: &impl Fn(f32
|
||||
// Reconstruct offset-rel WCS from stored small offsets + f64 anchor.
|
||||
let ox = hatch.world_origin[0] as f32;
|
||||
let oy = hatch.world_origin[1] as f32;
|
||||
// `boundary` may carry multiple disconnected sub-paths separated by
|
||||
// NaN-NaN sentinels (multi-region hatches with islands / holes).
|
||||
// Forwarding NaN to lyon's path builder panics
|
||||
// (`IncorrectActiveEdgeOrder`) — start a fresh sub-path on each
|
||||
// sentinel so each region is closed and filled independently.
|
||||
let path = canvas::Path::new(|builder| {
|
||||
let first = to_px(hatch.boundary[0][0] + ox, hatch.boundary[0][1] + oy);
|
||||
builder.move_to(first);
|
||||
for &[x, y] in &hatch.boundary[1..] {
|
||||
builder.line_to(to_px(x + ox, y + oy));
|
||||
let mut active = false;
|
||||
for &[x, y] in hatch.boundary.iter() {
|
||||
if x.is_nan() || y.is_nan() {
|
||||
if active {
|
||||
builder.close();
|
||||
active = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let p = to_px(x + ox, y + oy);
|
||||
if !active {
|
||||
builder.move_to(p);
|
||||
active = true;
|
||||
} else {
|
||||
builder.line_to(p);
|
||||
}
|
||||
}
|
||||
if active {
|
||||
builder.close();
|
||||
}
|
||||
builder.close();
|
||||
});
|
||||
|
||||
match &hatch.pattern {
|
||||
|
||||
Reference in new issue
Block a user