Keep reconstructed label corridors finite and inside blockers
This commit is contained in:
@@ -59,7 +59,7 @@ pub(super) fn widest_clear(
|
||||
}
|
||||
let candidate = Rectangle {
|
||||
x: start,
|
||||
width: end - start,
|
||||
width: contained_width(start, end),
|
||||
..band
|
||||
};
|
||||
// Use f64 only for comparison distance: subtracting two admitted f32
|
||||
@@ -83,6 +83,18 @@ pub(super) fn widest_clear(
|
||||
Ok(best)
|
||||
}
|
||||
|
||||
/// Finite f32 endpoints can subtract to infinity or round across a blocker.
|
||||
/// Compute in f64, cap to finite f32, and round inward if nearest rounding
|
||||
/// overshot the admitted interval's end.
|
||||
fn contained_width(start: f32, end: f32) -> f32 {
|
||||
let exact = f64::from(end) - f64::from(start);
|
||||
let mut width = exact.min(f64::from(f32::MAX)) as f32;
|
||||
if f64::from(start) + f64::from(width) > f64::from(end) {
|
||||
width = width.next_down();
|
||||
}
|
||||
width
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -186,4 +198,34 @@ mod tests {
|
||||
}
|
||||
assert_eq!(widest_clear(band, &[], f32::INFINITY), Err(InvalidGeometry));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn finite_band_cannot_reconstruct_an_infinite_width() {
|
||||
let band = rect(f32::from_bits(0xfe79636e), 0., f32::MAX, 20.);
|
||||
let right = band.x + band.width;
|
||||
assert!(right.is_finite());
|
||||
assert!(
|
||||
(right - band.x).is_infinite(),
|
||||
"counterexample must exercise f32 subtraction overflow"
|
||||
);
|
||||
let result = widest_clear(band, &[], 0.).unwrap().unwrap();
|
||||
assert!(result.width.is_finite() && result.width > 0.);
|
||||
assert!(result.x + result.width <= right);
|
||||
assert!(f64::from(result.x) + f64::from(result.width) <= f64::from(right));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reconstructed_width_rounds_inward_at_a_blocker() {
|
||||
let band = rect(-999_948.562_5, 0., 1_000_000., 20.);
|
||||
let blocker = rect(2.1, 0., 10., 20.);
|
||||
assert!(
|
||||
band.x + (blocker.x - band.x) > blocker.x,
|
||||
"counterexample must cross the blocker under naive reconstruction"
|
||||
);
|
||||
let result = widest_clear(band, &[blocker], 0.).unwrap().unwrap();
|
||||
assert_eq!(result.x, band.x);
|
||||
assert!(result.width > 999_000.);
|
||||
assert!(result.x + result.width <= blocker.x);
|
||||
assert!(f64::from(result.x) + f64::from(result.width) <= f64::from(blocker.x));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user