address review: charge actual clip work instead of projected polygon growth

This commit is contained in:
Dylan M. Taylor
2026-11-03 23:04:55 +00:00
parent 00b8bf38d6
commit 16ddef0744
2 changed files with 13 additions and 4 deletions
+2 -4
View File
@@ -111,12 +111,10 @@ pub(crate) fn clip_polygon(poly: &[P], clip: &[P]) -> Vec<P> {
/// can gain a vertex at every edge, so its cost isn't known from its input size alone. `None`
/// once the budget is spent.
fn clip_polygon_within(poly: &[P], clip: &[P], budget: &mut usize) -> Option<Vec<P>> {
if poly.len().saturating_mul(clip.len()) > *budget {
return None;
}
let mut poly = poly.to_vec();
for i in 0..clip.len() {
if poly.len().saturating_mul(clip.len() - i) > *budget {
// The work actually done: this edge visits the polygon as it now stands.
if poly.len() > *budget {
return None;
}
*budget -= poly.len();
+11
View File
@@ -2075,6 +2075,17 @@ fn clip_polygon_work_bound() {
assert!(clipped.is_empty(), "excessive polygon clip product rejected");
}
#[test]
fn clip_polygon_charges_actual_work_not_projected_growth() {
// Two convex 1,000-gons: the product is exactly the budget, and a cut that adds a vertex must
// not make a later step look over budget.
let gon = |cx: f64| -> Vec<(f64, f64)> {
(0..1000).map(|i| (i as f64 / 1000.0 * std::f64::consts::TAU).sin_cos()).map(|(s, c)| (cx + 100.0 * c, 100.0 * s)).collect()
};
let clipped = crate::cliprect::clip_polygon(&gon(0.0), &gon(30.0));
assert!(clipped.len() > 100, "the intersection is kept: {}", clipped.len());
}
#[test]
fn clip_work_is_bounded_across_subpaths() {
use crate::canvas::Raw;