Add kernel booleans: union, subtract and intersect for Solid3D

SolidOperation::Boolean runs synchronously, surfaces the kernel's refusal
with a plain reason and leaves the operands untouched, consumes them on
success unless keep_operands, and records one undo step. The lifecycle test
uses planar boxes with exact volumes and covers chaining, refusals, both
formats and undo; an ignored test shows a curved refusal reaching the script.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Felix RiestraandClaude Sonnet 5 committed 2026-09-20 17:58:38 +02:00
1 parent 69047549e7
commit 5a39052397
8 files changed
+320 -1

No files matched your search

+21
View File
@@ -76,6 +76,15 @@ pub enum SolidPrimitive {
Pyramid { center: [f64; 3], radius: f64, height: f64, sides: u32 },
}
/// How two solids combine.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SolidBoolean {
Union,
/// Remove the second solid from the first.
Subtract,
Intersect,
}
/// A kernel operation on ACIS-backed solids (API v7, additive). The host owns
/// the geometry: a script never sees or rewrites the payload.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
@@ -95,6 +104,18 @@ pub enum SolidOperation {
/// Extrude a planar profile along `direction`: a solid when the profile is
/// closed, a surface when it is open.
Extrude { source: Handle, direction: [f64; 3], layer: Option<String>, delete_source: bool },
/// Combine two solids into a new one. Both operands are consumed unless
/// `keep_operands`; the result goes on `layer` or the first operand's
/// layer. The kernel refuses some cases (coincident faces, cuts it has no
/// closed form for); a refusal changes nothing. Curved operands can take a
/// second or two, and the host thread is busy meanwhile.
Boolean {
first: Handle,
second: Handle,
operation: SolidBoolean,
layer: Option<String>,
keep_operands: bool,
},
}
/// Value of a host-managed drafting or document setting exposed to plugins.
@@ -115,6 +115,13 @@ mod tests {
},
SolidOperation::Transform { handle: acadrust::Handle::new(7), matrix: [1.0; 16] },
SolidOperation::RegionFromProfile { source: acadrust::Handle::new(3), layer: None, delete_source: true },
SolidOperation::Boolean {
first: acadrust::Handle::new(1),
second: acadrust::Handle::new(2),
operation: crate::host::SolidBoolean::Subtract,
layer: None,
keep_operands: false,
},
SolidOperation::SurfaceFromProfile { source: acadrust::Handle::new(4), layer: Some("S".into()), delete_source: false },
SolidOperation::Extrude { source: acadrust::Handle::new(5), direction: [0.0, 0.0, 2.0], layer: None, delete_source: true },
] {