From deb0ae13a040e331b37c6e8b6f7b446c7039ecb8 Mon Sep 17 00:00:00 2001 From: Gal Buki Date: Tue, 23 Jun 2026 18:55:40 +0300 Subject: [PATCH] Expose BRepBuilderAPI_MakeFace::Add for faces with holes --- .../opencascade-sys/src/b_rep_builder_api.rs | 2 + crates/opencascade/src/primitives/face.rs | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/crates/opencascade-sys/src/b_rep_builder_api.rs b/crates/opencascade-sys/src/b_rep_builder_api.rs index 754465f48..4b42cac9e 100644 --- a/crates/opencascade-sys/src/b_rep_builder_api.rs +++ b/crates/opencascade-sys/src/b_rep_builder_api.rs @@ -90,6 +90,8 @@ mod inner { pub fn Shape(self: Pin<&mut BRepBuilderAPI_MakeFace>) -> &TopoDS_Shape; pub fn Build(self: Pin<&mut BRepBuilderAPI_MakeFace>, progress: &Message_ProgressRange); pub fn IsDone(self: &BRepBuilderAPI_MakeFace) -> bool; + #[rust_name = "add_wire"] + pub fn Add(self: Pin<&mut BRepBuilderAPI_MakeFace>, wire: &TopoDS_Wire); type BRepBuilderAPI_MakeSolid; #[cxx_name = "construct_unique"] diff --git a/crates/opencascade/src/primitives/face.rs b/crates/opencascade/src/primitives/face.rs index 1b21c0a88..051fb4fcc 100644 --- a/crates/opencascade/src/primitives/face.rs +++ b/crates/opencascade/src/primitives/face.rs @@ -42,6 +42,17 @@ impl Face { Self::from_make_face(make_face) } + pub fn from_wire_with_holes(outer: &Wire, holes: &[Wire]) -> Self { + let only_plane = true; + let mut make_face = + ffi::b_rep_builder_api::BRepBuilderAPI_MakeFace_wire(&outer.inner, only_plane); + for hole in holes { + make_face.pin_mut().add_wire(&hole.inner); + } + make_face.pin_mut().Build(&ffi::message::Message_ProgressRange_new()); + Self::from_make_face(make_face) + } + pub fn from_surface(surface: &Surface) -> Self { const EDGE_TOLERANCE: f64 = 0.0001; @@ -558,4 +569,42 @@ mod tests { face.surface_area() ); } + + #[test] + fn test_from_wire_with_no_holes() { + let outer = Workplane::xy().rect(10.0, 10.0); + let face = Face::from_wire_with_holes(&outer, &[]); + assert!( + (face.surface_area() - 100.0).abs() <= 0.00001, + "Expected surface_area() to be ~100.0, was actually {}", + face.surface_area() + ); + } + + #[test] + fn test_from_wire_with_holes() { + let outer = Workplane::xy().rect(10.0, 10.0); + let hole = Workplane::xy().circle(0.0, 0.0, 2.0); + let face = Face::from_wire_with_holes(&outer, &[hole]); + let expected = 100.0 - std::f64::consts::PI * 4.0; + assert!( + (face.surface_area() - expected).abs() <= 0.01, + "Expected surface_area() to be ~{expected}, was actually {}", + face.surface_area() + ); + } + + #[test] + fn test_from_wire_with_multiple_holes() { + let outer = Workplane::xy().rect(10.0, 10.0); + let hole1 = Workplane::xy().circle(-2.0, -2.0, 2.0); + let hole2 = Workplane::xy().circle(3.0, 3.0, 1.0); + let face = Face::from_wire_with_holes(&outer, &[hole1, hole2]); + let expected = 100.0 - std::f64::consts::PI * (4.0 + 1.0); + assert!( + (face.surface_area() - expected).abs() <= 0.01, + "Expected surface_area() to be ~{expected}, was actually {}", + face.surface_area() + ); + } }