Files
figcraft/crates/engine/src/boolean_cap_tests.rs
T
BFlat cc3052de5e M8: cap the input of boolean operations (#1104) (#1581)
Each sweep takes at most 250 000 segments and 2 million possible crossings (pairs of segments whose bounds overlap, counted in O(n log n)), and a fold at most 4 million segments swept over its steps; past them the operation is refused with PathOpsError::TooComplex before it runs. A boolean group past the caps draws without its result, with a warning once, and the refusal is cached; vector.flatten refuses it instead of dropping it.
2026-10-30 06:03:35 +07:00

40 lines
1.6 KiB
Rust

//! A boolean group past the path operations' caps: it stays a boolean group, flattening it is
//! refused with the reason, and the document is unchanged.
use figcraft_doc::{NodeKind, VectorNetwork};
use figcraft_geom::kurbo::{BezPath, Rect, Shape};
use serde_json::json;
use crate::Session;
use crate::params::id_of;
/// `n` long thin bars, across or down: 750 of each cross 2.25 million times, past the caps.
fn bars(n: usize, across: bool) -> BezPath {
let mut p = BezPath::new();
for i in 0..n {
let (at, len) = (i as f64 * 4.0, n as f64 * 4.0);
let r = if across { Rect::new(0.0, at, len, at + 2.0) } else { Rect::new(at, 0.0, at + 2.0, len) };
p.extend(r.path_elements(0.1));
}
p
}
#[test]
fn flattening_a_boolean_past_the_caps_is_refused() {
let mut s = Session::new();
let page = s.page().unwrap();
let ids: Vec<_> = [true, false]
.into_iter()
.map(|across| {
let network = VectorNetwork::from_path(&bars(750, across));
s.doc_mut().unwrap().create(page, NodeKind::Vector { network }, "Bars", 0.0, 0.0, 3000.0, 3000.0).unwrap()
})
.collect();
let g = id_of(&s.execute("bool.union", &json!({"ids": ids})).unwrap()["id"]).unwrap();
let e = s.execute("vector.flatten", &json!({"ids": [g]})).unwrap_err().to_string();
assert!(e.contains("too complex to combine"), "{e}");
let doc = s.doc().unwrap();
assert!(matches!(doc.node(g).map(|n| &n.kind), Some(NodeKind::BooleanOp { .. })), "the group is kept");
assert_eq!(doc.node(g).map(|n| n.children.len()), Some(2));
}