From c5942f6fcc2d0f5ff571a9f87f9c7a915e617b9f Mon Sep 17 00:00:00 2001 From: "Dylan M. Taylor" Date: Tue, 3 Nov 2026 20:43:21 +0000 Subject: [PATCH] address review: keep wide contour boxes out of the nesting grid --- crates/path/src/trace.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/crates/path/src/trace.rs b/crates/path/src/trace.rs index 454b877fe..7b15b55c2 100644 --- a/crates/path/src/trace.rs +++ b/crates/path/src/trace.rs @@ -85,6 +85,10 @@ pub fn trace(field: &[f32], w: usize, h: usize, o: &TraceOpts) -> Vec { /// Grid cell (pixels) of the index [`nesting_depths`] finds candidate containers with. const DEPTH_CELL: f64 = 32.0; +/// Most grid cells one loop's box is entered into; a box covering more is kept in a short list +/// every point is tested against, so nested full-image contours can't fill the grid. +const MAX_BOX_CELLS: usize = 64; + /// Per loop (simplified points, |area|): how many other, larger loops contain its first point. /// Only loops whose bounding box holds that point can contain it, so each loop's box is entered /// into a coarse grid over the `w × h` field and a point is tested against the loops of its @@ -102,9 +106,15 @@ fn nesting_depths(polys: &[(&[[f64; 2]], f64)], w: usize, h: usize) -> Vec> = vec![Vec::new(); gw * gh]; + let mut wide: Vec = Vec::new(); for (j, b) in boxes.iter().enumerate() { - for cy in cell(b[1], gh)..=cell(b[3], gh) { - for cx in cell(b[0], gw)..=cell(b[2], gw) { + let (x0, x1, y0, y1) = (cell(b[0], gw), cell(b[2], gw), cell(b[1], gh), cell(b[3], gh)); + if (x1 - x0 + 1).saturating_mul(y1 - y0 + 1) > MAX_BOX_CELLS { + wide.push(j); + continue; + } + for cy in y0..=y1 { + for cx in x0..=x1 { grid[cy * gw + cx].push(j); } } @@ -114,6 +124,7 @@ fn nesting_depths(polys: &[(&[[f64; 2]], f64)], w: usize, h: usize) -> Vec polys[i].1 && p[0] >= b[0] && p[0] <= b[2] && p[1] >= b[1] && p[1] <= b[3] && point_in_poly(p, polys[j].0) @@ -424,6 +435,20 @@ mod tests { assert!(fast.iter().max() >= Some(&5)); } + #[test] + fn nesting_depths_count_wide_boxes_kept_out_of_the_grid() { + // Concentric squares whose boxes each cover far more than MAX_BOX_CELLS cells. + let (w, h) = (4000, 4000); + let squares: Vec> = (0..40) + .map(|k| { + let (a, b) = (10.0 + 40.0 * k as f64, 3990.0 - 40.0 * k as f64); + vec![[a, a], [b, a], [b, b], [a, b]] + }) + .collect(); + let refs: Vec<(&[[f64; 2]], f64)> = squares.iter().map(|p| (p.as_slice(), (p[1][0] - p[0][0]).powi(2))).collect(); + assert_eq!(nesting_depths(&refs, w, h), (0..40).collect::>()); + } + #[test] fn simplification_work_is_bounded_and_keeps_the_outline() { // Out of budget, the spans still waiting keep every point: nothing is lost, the outline