diff --git a/crates/opencascade-sys/build.rs b/crates/opencascade-sys/build.rs index e03a72f8..fd9a8909 100644 --- a/crates/opencascade-sys/build.rs +++ b/crates/opencascade-sys/build.rs @@ -49,7 +49,21 @@ fn main() { println!("cargo:rustc-link-lib=dylib=user32"); } - let mut build = cxx_build::bridge("src/lib.rs"); + let rust_bridges = [ + "src/b_rep_g_prop.rs", + "src/b_rep_mesh.rs", + "src/b_rep_tools.rs", + "src/g_prop.rs", + "src/gc_pnts.rs", + "src/lib.rs", + "src/poly.rs", + "src/shape_analysis.rs", + "src/shape_upgrade.rs", + "src/stl_api.rs", + "src/top_loc.rs", + ]; + + let mut build = cxx_build::bridges(rust_bridges); if is_windows_gnu { build.define("OCC_CONVERT_SIGNALS", "TRUE"); @@ -70,7 +84,10 @@ fn main() { println!("cargo:rustc-link-lib=static=wrapper"); - println!("cargo:rerun-if-changed=src/lib.rs"); + for bridge in rust_bridges { + println!("cargo:rerun-if-changed={bridge}"); + } + println!("cargo:rerun-if-changed=include/wrapper.hxx"); } diff --git a/crates/opencascade-sys/examples/bottle.rs b/crates/opencascade-sys/examples/bottle.rs index 5dae71f0..3d99f718 100644 --- a/crates/opencascade-sys/examples/bottle.rs +++ b/crates/opencascade-sys/examples/bottle.rs @@ -1,23 +1,27 @@ use cxx::UniquePtr; -use opencascade_sys::ffi::{ - cylinder_to_surface, ellipse_to_HandleGeom2d_Curve, ellipse_value, gp_Ax2_ctor, gp_Ax2d_ctor, - gp_Ax3_from_gp_Ax2, gp_DZ, gp_Dir2d_ctor, gp_OX, handle_geom_plane_location, - new_HandleGeomCurve_from_HandleGeom_TrimmedCurve, new_HandleGeomPlane_from_HandleGeomSurface, - new_list_of_shape, new_point, new_point_2d, new_transform, new_vec, shape_list_append_face, - type_name, write_stl, BRepAlgoAPI_Fuse_ctor, BRepBuilderAPI_MakeEdge_CurveSurface2d, - BRepBuilderAPI_MakeEdge_HandleGeomCurve, BRepBuilderAPI_MakeFace_wire, - BRepBuilderAPI_MakeWire_ctor, BRepBuilderAPI_MakeWire_edge_edge, - BRepBuilderAPI_MakeWire_edge_edge_edge, BRepBuilderAPI_Transform_ctor, - BRepFilletAPI_MakeFillet_ctor, BRepLibBuildCurves3d, BRepMesh_IncrementalMesh_ctor, - BRepOffsetAPI_MakeThickSolid_ctor, BRepOffsetAPI_ThruSections_ctor, - BRepPrimAPI_MakeCylinder_ctor, BRepPrimAPI_MakePrism_ctor, BRep_Builder_ctor, - BRep_Builder_upcast_to_topods_builder, BRep_Tool_Surface, DynamicType, ExplorerCurrentShape, - GCE2d_MakeSegment_point_point, GC_MakeArcOfCircle_Value, GC_MakeArcOfCircle_point_point_point, - GC_MakeSegment_Value, GC_MakeSegment_point_point, Geom2d_Ellipse_ctor, - Geom2d_TrimmedCurve_ctor, Geom_CylindricalSurface_ctor, HandleGeom2d_TrimmedCurve_to_curve, - MakeThickSolidByJoin, StlAPI_Writer_ctor, TopAbs_ShapeEnum, TopExp_Explorer_ctor, - TopoDS_Compound_as_shape, TopoDS_Compound_ctor, TopoDS_Face, TopoDS_Face_to_owned, - TopoDS_cast_to_edge, TopoDS_cast_to_face, TopoDS_cast_to_wire, +use opencascade_sys::{ + b_rep_mesh::IncrementalMesh, + ffi::{ + cylinder_to_surface, ellipse_to_HandleGeom2d_Curve, ellipse_value, gp_Ax2_ctor, + gp_Ax2d_ctor, gp_Ax3_from_gp_Ax2, gp_DZ, gp_Dir2d_ctor, gp_OX, handle_geom_plane_location, + new_HandleGeomCurve_from_HandleGeom_TrimmedCurve, + new_HandleGeomPlane_from_HandleGeomSurface, new_list_of_shape, new_point, new_point_2d, + new_transform, new_vec, shape_list_append_face, type_name, BRepAlgoAPI_Fuse_ctor, + BRepBuilderAPI_MakeEdge_CurveSurface2d, BRepBuilderAPI_MakeEdge_HandleGeomCurve, + BRepBuilderAPI_MakeFace_wire, BRepBuilderAPI_MakeWire_ctor, + BRepBuilderAPI_MakeWire_edge_edge, BRepBuilderAPI_MakeWire_edge_edge_edge, + BRepBuilderAPI_Transform_ctor, BRepFilletAPI_MakeFillet_ctor, BRepLibBuildCurves3d, + BRepOffsetAPI_MakeThickSolid_ctor, BRepOffsetAPI_ThruSections_ctor, + BRepPrimAPI_MakeCylinder_ctor, BRepPrimAPI_MakePrism_ctor, BRep_Builder_ctor, + BRep_Builder_upcast_to_topods_builder, BRep_Tool_Surface, DynamicType, + ExplorerCurrentShape, GCE2d_MakeSegment_point_point, GC_MakeArcOfCircle_Value, + GC_MakeArcOfCircle_point_point_point, GC_MakeSegment_Value, GC_MakeSegment_point_point, + Geom2d_Ellipse_ctor, Geom2d_TrimmedCurve_ctor, Geom_CylindricalSurface_ctor, + HandleGeom2d_TrimmedCurve_to_curve, MakeThickSolidByJoin, TopAbs_ShapeEnum, + TopExp_Explorer_ctor, TopoDS_Compound_as_shape, TopoDS_Compound_ctor, TopoDS_Face, + TopoDS_Face_to_owned, TopoDS_cast_to_edge, TopoDS_cast_to_face, TopoDS_cast_to_wire, + }, + stl_api, }; // All dimensions are in millimeters. @@ -217,9 +221,9 @@ pub fn main() { let final_shape = compound_shape; // Export to an STL file - let mut stl_writer = StlAPI_Writer_ctor(); - let triangulation = BRepMesh_IncrementalMesh_ctor(&final_shape, 0.01); - let success = write_stl(stl_writer.pin_mut(), triangulation.Shape(), "bottle.stl".to_owned()); + let mut stl_writer = stl_api::Writer::new(); + let triangulation = IncrementalMesh::new(&final_shape, 0.01); + let success = stl_writer.pin_mut().write_stl(triangulation.Shape(), "bottle.stl".to_owned()); println!("Done! Success = {success}"); } diff --git a/crates/opencascade-sys/src/b_rep_g_prop.rs b/crates/opencascade-sys/src/b_rep_g_prop.rs new file mode 100644 index 00000000..b0312cfc --- /dev/null +++ b/crates/opencascade-sys/src/b_rep_g_prop.rs @@ -0,0 +1,55 @@ +use std::pin::Pin; + +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type TopoDS_Shape = crate::ffi::TopoDS_Shape; + type TopoDS_Face = crate::ffi::TopoDS_Face; + type gp_Ax1 = crate::ffi::gp_Ax1; + type gp_Pnt = crate::ffi::gp_Pnt; + type gp_Vec = crate::ffi::gp_Vec; + + #[cxx_name = "GProp_GProps"] + type GProps = crate::g_prop::GProps; + + fn BRepGProp_LinearProperties(shape: &TopoDS_Shape, props: Pin<&mut GProps>); + fn BRepGProp_SurfaceProperties(shape: &TopoDS_Shape, props: Pin<&mut GProps>); + fn BRepGProp_VolumeProperties(shape: &TopoDS_Shape, props: Pin<&mut GProps>); + + type BRepGProp; + #[cxx_name = "BRepGProp_Face"] + type Face; + + #[cxx_name = "construct_unique"] + fn Face_new(face: &TopoDS_Face) -> UniquePtr; + fn Normal(self: &Face, u: f64, v: f64, point: Pin<&mut gp_Pnt>, normal: Pin<&mut gp_Vec>); + } +} + +impl BRepGProp { + pub fn linear_properties(shape: &TopoDS_Shape, props: Pin<&mut GProps>) { + inner::BRepGProp_LinearProperties(shape, props) + } + + pub fn surface_properties(shape: &TopoDS_Shape, props: Pin<&mut GProps>) { + inner::BRepGProp_SurfaceProperties(shape, props) + } + + pub fn volume_properties(shape: &TopoDS_Shape, props: Pin<&mut GProps>) { + inner::BRepGProp_VolumeProperties(shape, props) + } +} + +impl Face { + pub fn new(face: &TopoDS_Face) -> cxx::UniquePtr { + Face_new(face) + } + + pub fn normal(&self, u: f64, v: f64, point: Pin<&mut gp_Pnt>, normal: Pin<&mut gp_Vec>) { + self.Normal(u, v, point, normal); + } +} diff --git a/crates/opencascade-sys/src/b_rep_mesh.rs b/crates/opencascade-sys/src/b_rep_mesh.rs new file mode 100644 index 00000000..9e9354d1 --- /dev/null +++ b/crates/opencascade-sys/src/b_rep_mesh.rs @@ -0,0 +1,35 @@ +use cxx::UniquePtr; +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type TopoDS_Shape = crate::ffi::TopoDS_Shape; + + #[cxx_name = "BRepMesh_IncrementalMesh"] + type IncrementalMesh; + + #[cxx_name = "construct_unique"] + fn IncrementalMesh_new(shape: &TopoDS_Shape, deflection: f64) + -> UniquePtr; + + fn Shape(self: &IncrementalMesh) -> &TopoDS_Shape; + fn IsDone(self: &IncrementalMesh) -> bool; + } +} + +impl IncrementalMesh { + pub fn new(shape: &TopoDS_Shape, deflection: f64) -> UniquePtr { + IncrementalMesh_new(shape, deflection) + } + + pub fn shape(&self) -> &TopoDS_Shape { + self.Shape() + } + + pub fn is_done(&self) -> bool { + self.IsDone() + } +} diff --git a/crates/opencascade-sys/src/b_rep_tools.rs b/crates/opencascade-sys/src/b_rep_tools.rs new file mode 100644 index 00000000..4c8e814e --- /dev/null +++ b/crates/opencascade-sys/src/b_rep_tools.rs @@ -0,0 +1,22 @@ +use cxx::UniquePtr; +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type TopoDS_Face = crate::ffi::TopoDS_Face; + type TopoDS_Wire = crate::ffi::TopoDS_Wire; + + type BRepTools; + + fn outer_wire(face: &TopoDS_Face) -> UniquePtr; + } +} + +impl BRepTools { + pub fn outer_wire(face: &TopoDS_Face) -> UniquePtr { + outer_wire(face) + } +} diff --git a/crates/opencascade-sys/src/g_prop.rs b/crates/opencascade-sys/src/g_prop.rs new file mode 100644 index 00000000..8d877108 --- /dev/null +++ b/crates/opencascade-sys/src/g_prop.rs @@ -0,0 +1,50 @@ +use cxx::UniquePtr; + +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type gp_Ax1 = crate::ffi::gp_Ax1; + type gp_Pnt = crate::ffi::gp_Pnt; + + #[cxx_name = "GProp_GProps"] + type GProps; + + #[cxx_name = "construct_unique"] + fn GProps_new() -> UniquePtr; + fn Mass(self: &GProps) -> f64; + fn StaticMoments(self: &GProps, lx: &mut f64, ly: &mut f64, lz: &mut f64); + fn MomentOfInertia(self: &GProps, axis: &gp_Ax1) -> f64; + fn RadiusOfGyration(self: &GProps, axis: &gp_Ax1) -> f64; + fn GProp_GProps_CentreOfMass(props: &GProps) -> UniquePtr; + } +} + +impl GProps { + pub fn new() -> cxx::UniquePtr { + GProps_new() + } + + pub fn mass(&self) -> f64 { + self.Mass() + } + + pub fn static_moments(&self, lx: &mut f64, ly: &mut f64, lz: &mut f64) { + self.StaticMoments(lx, ly, lz) + } + + pub fn moment_of_inertia(&self, axis: &gp_Ax1) -> f64 { + self.MomentOfInertia(axis) + } + + pub fn radius_of_gyration(&self, axis: &gp_Ax1) -> f64 { + self.RadiusOfGyration(axis) + } + + pub fn center_of_mass(&self) -> UniquePtr { + GProp_GProps_CentreOfMass(self) + } +} diff --git a/crates/opencascade-sys/src/gc_pnts.rs b/crates/opencascade-sys/src/gc_pnts.rs new file mode 100644 index 00000000..940ea2cd --- /dev/null +++ b/crates/opencascade-sys/src/gc_pnts.rs @@ -0,0 +1,45 @@ +use cxx::UniquePtr; +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type gp_Pnt = crate::ffi::gp_Pnt; + type BRepAdaptor_Curve = crate::ffi::BRepAdaptor_Curve; + + #[cxx_name = "GCPnts_TangentialDeflection"] + type TangentialDeflection; + + #[cxx_name = "construct_unique"] + fn TangentialDeflection_new( + curve: &BRepAdaptor_Curve, + angular_deflection: f64, + curvature_deflection: f64, + ) -> UniquePtr; + fn NbPoints(self: &TangentialDeflection) -> i32; + fn GCPnts_TangentialDeflection_Value( + approximator: &TangentialDeflection, + index: i32, + ) -> UniquePtr; + } +} + +impl TangentialDeflection { + pub fn new( + curve: &BRepAdaptor_Curve, + angular_deflection: f64, + curvature_deflection: f64, + ) -> cxx::UniquePtr { + TangentialDeflection_new(curve, angular_deflection, curvature_deflection) + } + + pub fn num_points(&self) -> i32 { + self.NbPoints() + } + + pub fn value(&self, index: i32) -> UniquePtr { + GCPnts_TangentialDeflection_Value(self, index) + } +} diff --git a/crates/opencascade-sys/src/lib.rs b/crates/opencascade-sys/src/lib.rs index e369a116..ae61cdca 100644 --- a/crates/opencascade-sys/src/lib.rs +++ b/crates/opencascade-sys/src/lib.rs @@ -1,3 +1,14 @@ +pub mod b_rep_g_prop; +pub mod b_rep_mesh; +pub mod b_rep_tools; +pub mod g_prop; +pub mod gc_pnts; +pub mod poly; +pub mod shape_analysis; +pub mod shape_upgrade; +pub mod stl_api; +pub mod top_loc; + #[cxx::bridge] pub mod ffi { #[repr(u32)] @@ -423,16 +434,12 @@ pub mod ffi { pub fn TopoDS_cast_to_compound(shape: &TopoDS_Shape) -> &TopoDS_Compound; #[cxx_name = "Move"] - pub fn translate( - self: Pin<&mut TopoDS_Shape>, - position: &TopLoc_Location, - raise_exception: bool, - ); + pub fn translate(self: Pin<&mut TopoDS_Shape>, position: &Location, raise_exception: bool); #[cxx_name = "Location"] pub fn set_global_translation( self: Pin<&mut TopoDS_Shape>, - translation: &TopLoc_Location, + translation: &Location, raise_exception: bool, ); @@ -1125,7 +1132,7 @@ pub mod ffi { pub fn BRep_Tool_Pnt(vertex: &TopoDS_Vertex) -> UniquePtr; pub fn BRep_Tool_Triangulation( face: &TopoDS_Face, - location: Pin<&mut TopLoc_Location>, + location: Pin<&mut Location>, ) -> UniquePtr; type BRepIntCurveSurface_Inter; @@ -1214,39 +1221,11 @@ pub mod ffi { ) -> IFSelect_ReturnStatus; pub fn write_iges(writer: Pin<&mut IGESControl_Writer>, filename: String) -> bool; - type StlAPI_Writer; - - #[cxx_name = "construct_unique"] - pub fn StlAPI_Writer_ctor() -> UniquePtr; - - // pub fn Write(self: Pin<&mut StlAPI_Writer>, shape: &TopoDS_Shape, filename: &c_char) -> bool; - pub fn write_stl( - writer: Pin<&mut StlAPI_Writer>, - shape: &TopoDS_Shape, - filename: String, - ) -> bool; - - // Triangulation - type BRepMesh_IncrementalMesh; - - #[cxx_name = "construct_unique"] - pub fn BRepMesh_IncrementalMesh_ctor( - shape: &TopoDS_Shape, - deflection: f64, - ) -> UniquePtr; - - pub fn Shape(self: &BRepMesh_IncrementalMesh) -> &TopoDS_Shape; - pub fn IsDone(self: &BRepMesh_IncrementalMesh) -> bool; - - type TopLoc_Location; - #[cxx_name = "construct_unique"] - pub fn TopLoc_Location_ctor() -> UniquePtr; - - #[cxx_name = "construct_unique"] - pub fn TopLoc_Location_from_transform(transform: &gp_Trsf) -> UniquePtr; - - pub fn TopLoc_Location_Transformation(location: &TopLoc_Location) -> UniquePtr; + #[cxx_name = "TopLoc_Location"] + type Location = crate::top_loc::Location; + #[cxx_name = "Poly_Triangulation"] + type Poly_Triangulation = crate::poly::Triangulation; type HandlePoly_Triangulation; pub fn HandlePoly_Triangulation_ctor( @@ -1259,117 +1238,7 @@ pub mod ffi { handle: &HandlePoly_Triangulation, ) -> Result<&Poly_Triangulation>; - type Poly_Triangulation; - #[cxx_name = "construct_unique"] - pub fn Poly_Triangulation_ctor( - nb_nodes: i32, - nb_triangles: i32, - has_uv: bool, - has_normals: bool, - ) -> UniquePtr; - pub fn NbNodes(self: &Poly_Triangulation) -> i32; - pub fn NbTriangles(self: &Poly_Triangulation) -> i32; - pub fn HasNormals(self: &Poly_Triangulation) -> bool; - pub fn HasUVNodes(self: &Poly_Triangulation) -> bool; - pub fn Triangle(self: &Poly_Triangulation, index: i32) -> &Poly_Triangle; - pub fn SetTriangle( - self: Pin<&mut Poly_Triangulation>, - index: i32, - triangle: &Poly_Triangle, - ); - pub fn SetNode(self: Pin<&mut Poly_Triangulation>, index: i32, node: &gp_Pnt); - pub fn SetNormal(self: Pin<&mut Poly_Triangulation>, index: i32, dir: &gp_Dir); - pub fn SetUVNode(self: Pin<&mut Poly_Triangulation>, index: i32, uv: &gp_Pnt2d); - pub fn Poly_Triangulation_Normal( - triangulation: &Poly_Triangulation, - index: i32, - ) -> UniquePtr; - pub fn Poly_Triangulation_Node( - triangulation: &Poly_Triangulation, - index: i32, - ) -> UniquePtr; - pub fn Poly_Triangulation_UV( - triangulation: &Poly_Triangulation, - index: i32, - ) -> UniquePtr; - - type Poly_Triangle; - #[cxx_name = "construct_unique"] - pub fn Poly_Triangle_ctor(node1: i32, node2: i32, node3: i32) -> UniquePtr; - pub fn Value(self: &Poly_Triangle, index: i32) -> i32; - - type Poly_Connect; - #[cxx_name = "construct_unique"] - pub fn Poly_Connect_ctor( - triangulation: &HandlePoly_Triangulation, - ) -> UniquePtr; - pub fn compute_normals(face: &TopoDS_Face, triangulation: &HandlePoly_Triangulation); - - // Edge approximation - type GCPnts_TangentialDeflection; - - #[cxx_name = "construct_unique"] - pub fn GCPnts_TangentialDeflection_ctor( - curve: &BRepAdaptor_Curve, - angular_deflection: f64, - curvature_deflection: f64, - ) -> UniquePtr; - pub fn NbPoints(self: &GCPnts_TangentialDeflection) -> i32; - pub fn GCPnts_TangentialDeflection_Value( - approximator: &GCPnts_TangentialDeflection, - index: i32, - ) -> UniquePtr; - - // Shape Properties - type GProp_GProps; - #[cxx_name = "construct_unique"] - pub fn GProp_GProps_ctor() -> UniquePtr; - pub fn Mass(self: &GProp_GProps) -> f64; - pub fn StaticMoments(self: &GProp_GProps, lx: &mut f64, ly: &mut f64, lz: &mut f64); - pub fn MomentOfInertia(self: &GProp_GProps, axis: &gp_Ax1) -> f64; - pub fn RadiusOfGyration(self: &GProp_GProps, axis: &gp_Ax1) -> f64; - pub fn GProp_GProps_CentreOfMass(props: &GProp_GProps) -> UniquePtr; - - pub fn BRepGProp_LinearProperties(shape: &TopoDS_Shape, props: Pin<&mut GProp_GProps>); - pub fn BRepGProp_SurfaceProperties(shape: &TopoDS_Shape, props: Pin<&mut GProp_GProps>); - pub fn BRepGProp_VolumeProperties(shape: &TopoDS_Shape, props: Pin<&mut GProp_GProps>); - - type BRepGProp_Face; - - #[cxx_name = "construct_unique"] - pub fn BRepGProp_Face_ctor(face: &TopoDS_Face) -> UniquePtr; - pub fn Normal( - self: &BRepGProp_Face, - u: f64, - v: f64, - point: Pin<&mut gp_Pnt>, - normal: Pin<&mut gp_Vec>, - ); - - // BRepTools - pub fn outer_wire(face: &TopoDS_Face) -> UniquePtr; - - // Cleaning - type ShapeUpgrade_UnifySameDomain; - - #[cxx_name = "construct_unique"] - pub fn ShapeUpgrade_UnifySameDomain_ctor( - shape: &TopoDS_Shape, - unify_edges: bool, - unify_faces: bool, - concat_b_splines: bool, - ) -> UniquePtr; - pub fn AllowInternalEdges(self: Pin<&mut ShapeUpgrade_UnifySameDomain>, allow: bool); - pub fn Build(self: Pin<&mut ShapeUpgrade_UnifySameDomain>); - pub fn Shape(self: &ShapeUpgrade_UnifySameDomain) -> &TopoDS_Shape; - - pub fn connect_edges_to_wires( - edges: Pin<&mut HandleTopTools_HSequenceOfShape>, - tolerance: f64, - shared: bool, - wires: Pin<&mut HandleTopTools_HSequenceOfShape>, - ); } } diff --git a/crates/opencascade-sys/src/poly.rs b/crates/opencascade-sys/src/poly.rs new file mode 100644 index 00000000..dbfa60e9 --- /dev/null +++ b/crates/opencascade-sys/src/poly.rs @@ -0,0 +1,82 @@ +use cxx::UniquePtr; +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type gp_Pnt = crate::ffi::gp_Pnt; + type gp_Pnt2d = crate::ffi::gp_Pnt2d; + type HandlePoly_Triangulation = crate::ffi::HandlePoly_Triangulation; + type gp_Dir = crate::ffi::gp_Dir; + type BRepAdaptor_Curve = crate::ffi::BRepAdaptor_Curve; + + #[cxx_name = "Poly_Triangulation"] + type Triangulation; + #[cxx_name = "construct_unique"] + fn Triangulation_new( + nb_nodes: i32, + nb_triangles: i32, + has_uv: bool, + has_normals: bool, + ) -> UniquePtr; + fn NbNodes(self: &Triangulation) -> i32; + fn NbTriangles(self: &Triangulation) -> i32; + fn HasNormals(self: &Triangulation) -> bool; + fn HasUVNodes(self: &Triangulation) -> bool; + fn Triangle(self: &Triangulation, index: i32) -> &Triangle; + fn SetTriangle(self: Pin<&mut Triangulation>, index: i32, triangle: &Triangle); + fn SetNode(self: Pin<&mut Triangulation>, index: i32, node: &gp_Pnt); + fn SetNormal(self: Pin<&mut Triangulation>, index: i32, dir: &gp_Dir); + fn SetUVNode(self: Pin<&mut Triangulation>, index: i32, uv: &gp_Pnt2d); + fn Poly_Triangulation_Normal( + triangulation: &Triangulation, + index: i32, + ) -> UniquePtr; + fn Poly_Triangulation_Node(triangulation: &Triangulation, index: i32) -> UniquePtr; + fn Poly_Triangulation_UV(triangulation: &Triangulation, index: i32) -> UniquePtr; + + #[cxx_name = "Poly_Triangle"] + type Triangle; + #[cxx_name = "construct_unique"] + fn Triangle_new(node1: i32, node2: i32, node3: i32) -> UniquePtr; + fn Value(self: &Triangle, index: i32) -> i32; + + #[cxx_name = "Poly_Connect"] + type Connect; + #[cxx_name = "construct_unique"] + fn Connect_new(triangulation: &HandlePoly_Triangulation) -> UniquePtr; + } +} + +impl Triangulation { + pub fn new( + nb_nodes: i32, + nb_triangles: i32, + has_uv: bool, + has_normals: bool, + ) -> UniquePtr { + Triangulation_new(nb_nodes, nb_triangles, has_uv, has_normals) + } + + pub fn num_nodes(&self) -> i32 { + self.NbNodes() + } + + pub fn num_triangles(&self) -> i32 { + self.NbTriangles() + } + + pub fn node(&self, index: i32) -> UniquePtr { + Poly_Triangulation_Node(self, index) + } + + pub fn uv(&self, index: i32) -> UniquePtr { + Poly_Triangulation_UV(self, index) + } + + pub fn normal(&self, index: i32) -> UniquePtr { + Poly_Triangulation_Normal(self, index) + } +} diff --git a/crates/opencascade-sys/src/shape_analysis.rs b/crates/opencascade-sys/src/shape_analysis.rs new file mode 100644 index 00000000..31ca5d4b --- /dev/null +++ b/crates/opencascade-sys/src/shape_analysis.rs @@ -0,0 +1,34 @@ +use std::pin::Pin; + +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type TopoDS_Shape = crate::ffi::TopoDS_Shape; + type HandleTopTools_HSequenceOfShape = crate::ffi::HandleTopTools_HSequenceOfShape; + + #[cxx_name = "ShapeAnalysis_FreeBounds"] + type FreeBounds; + + fn connect_edges_to_wires( + edges: Pin<&mut HandleTopTools_HSequenceOfShape>, + tolerance: f64, + shared: bool, + wires: Pin<&mut HandleTopTools_HSequenceOfShape>, + ); + } +} + +impl FreeBounds { + pub fn connect_edges_to_wires( + edges: Pin<&mut HandleTopTools_HSequenceOfShape>, + tolerance: f64, + shared: bool, + wires: Pin<&mut HandleTopTools_HSequenceOfShape>, + ) { + connect_edges_to_wires(edges, tolerance, shared, wires); + } +} diff --git a/crates/opencascade-sys/src/shape_upgrade.rs b/crates/opencascade-sys/src/shape_upgrade.rs new file mode 100644 index 00000000..fc20c0af --- /dev/null +++ b/crates/opencascade-sys/src/shape_upgrade.rs @@ -0,0 +1,49 @@ +use std::pin::Pin; + +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type TopoDS_Shape = crate::ffi::TopoDS_Shape; + + #[cxx_name = "ShapeUpgrade_UnifySameDomain"] + type UnifySameDomain; + + #[cxx_name = "construct_unique"] + pub fn UnifySameDomain_new( + shape: &TopoDS_Shape, + unify_edges: bool, + unify_faces: bool, + concat_b_splines: bool, + ) -> UniquePtr; + fn AllowInternalEdges(self: Pin<&mut UnifySameDomain>, allow: bool); + fn Build(self: Pin<&mut UnifySameDomain>); + fn Shape(self: &UnifySameDomain) -> &TopoDS_Shape; + } +} + +impl UnifySameDomain { + pub fn new( + shape: &TopoDS_Shape, + unify_edges: bool, + unify_faces: bool, + concat_b_splines: bool, + ) -> cxx::UniquePtr { + UnifySameDomain_new(shape, unify_edges, unify_faces, concat_b_splines) + } + + pub fn allow_internal_edges(self: Pin<&mut UnifySameDomain>, allow: bool) { + self.AllowInternalEdges(allow) + } + + pub fn build(self: Pin<&mut UnifySameDomain>) { + self.Build() + } + + pub fn shape(&self) -> &TopoDS_Shape { + self.Shape() + } +} diff --git a/crates/opencascade-sys/src/stl_api.rs b/crates/opencascade-sys/src/stl_api.rs new file mode 100644 index 00000000..4970512e --- /dev/null +++ b/crates/opencascade-sys/src/stl_api.rs @@ -0,0 +1,31 @@ +use cxx::UniquePtr; +pub use inner::*; +use std::pin::Pin; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type TopoDS_Shape = crate::ffi::TopoDS_Shape; + + #[cxx_name = "StlAPI_Writer"] + type Writer; + + #[cxx_name = "construct_unique"] + fn Writer_new() -> UniquePtr; + + // fn Write(self: Pin<&mut Writer>, shape: &TopoDS_Shape, filename: &c_char) -> bool; + fn write_stl(writer: Pin<&mut Writer>, shape: &TopoDS_Shape, filename: String) -> bool; + } +} + +impl Writer { + pub fn new() -> UniquePtr { + Writer_new() + } + + pub fn write_stl(self: Pin<&mut Writer>, shape: &TopoDS_Shape, filename: String) -> bool { + write_stl(self, shape, filename) + } +} diff --git a/crates/opencascade-sys/src/top_loc.rs b/crates/opencascade-sys/src/top_loc.rs new file mode 100644 index 00000000..4b58f4ed --- /dev/null +++ b/crates/opencascade-sys/src/top_loc.rs @@ -0,0 +1,35 @@ +use cxx::UniquePtr; +pub use inner::*; + +#[cxx::bridge] +mod inner { + unsafe extern "C++" { + include!("opencascade-sys/include/wrapper.hxx"); + + type gp_Trsf = crate::ffi::gp_Trsf; + + #[cxx_name = "TopLoc_Location"] + type Location; + #[cxx_name = "construct_unique"] + fn Location_new() -> UniquePtr; + + #[cxx_name = "construct_unique"] + fn Location_from_transform(transform: &gp_Trsf) -> UniquePtr; + + fn TopLoc_Location_Transformation(location: &Location) -> UniquePtr; + } +} + +impl Location { + pub fn new() -> UniquePtr { + Location_new() + } + + pub fn from_transform(transform: &gp_Trsf) -> UniquePtr { + Location_from_transform(transform) + } + + pub fn transform(&self) -> UniquePtr { + TopLoc_Location_Transformation(self) + } +} diff --git a/crates/opencascade-sys/tests/triangulation.rs b/crates/opencascade-sys/tests/triangulation.rs index 1754da0d..22bc5c1f 100644 --- a/crates/opencascade-sys/tests/triangulation.rs +++ b/crates/opencascade-sys/tests/triangulation.rs @@ -1,7 +1,10 @@ -use opencascade_sys::ffi::{ - new_point, BRepMesh_IncrementalMesh_ctor, BRepPrimAPI_MakeBox_ctor, BRep_Tool_Triangulation, - HandlePoly_Triangulation_Get, Poly_Triangulation_Node, TopAbs_ShapeEnum, TopExp_Explorer_ctor, - TopLoc_Location_ctor, TopoDS_cast_to_face, +use opencascade_sys::{ + b_rep_mesh::IncrementalMesh, + ffi::{ + new_point, BRepPrimAPI_MakeBox_ctor, BRep_Tool_Triangulation, HandlePoly_Triangulation_Get, + TopAbs_ShapeEnum, TopExp_Explorer_ctor, TopoDS_cast_to_face, + }, + top_loc::Location, }; #[test] @@ -9,7 +12,7 @@ fn it_can_access_mesh_triangulation() { let origin = new_point(0., 0., 0.); let mut cube = BRepPrimAPI_MakeBox_ctor(&origin, 10., 10., 10.); - let mut mesh = BRepMesh_IncrementalMesh_ctor(cube.pin_mut().Shape(), 0.01); + let mut mesh = IncrementalMesh::new(cube.pin_mut().Shape(), 0.01); let mut triangle_corners = 0; @@ -17,7 +20,7 @@ fn it_can_access_mesh_triangulation() { TopExp_Explorer_ctor(mesh.pin_mut().Shape(), TopAbs_ShapeEnum::TopAbs_FACE); while edge_explorer.More() { let face = TopoDS_cast_to_face(edge_explorer.Current()); - let mut location = TopLoc_Location_ctor(); + let mut location = Location::new(); let triangulation_handle = BRep_Tool_Triangulation(face, location.pin_mut()); if let Ok(triangulation) = HandlePoly_Triangulation_Get(&triangulation_handle) { @@ -25,8 +28,7 @@ fn it_can_access_mesh_triangulation() { let triangle = triangulation.Triangle(index + 1); for corner_index in 1..=3 { - let _point = - Poly_Triangulation_Node(triangulation, triangle.Value(corner_index)); + let _point = triangulation.node(triangle.Value(corner_index)); triangle_corners += 1; } } diff --git a/crates/opencascade/src/mesh.rs b/crates/opencascade/src/mesh.rs index 711908e7..2b26aa79 100644 --- a/crates/opencascade/src/mesh.rs +++ b/crates/opencascade/src/mesh.rs @@ -4,7 +4,7 @@ use crate::{ }; use cxx::UniquePtr; use glam::{dvec2, dvec3, DVec2, DVec3}; -use opencascade_sys::ffi; +use opencascade_sys::{b_rep_mesh::IncrementalMesh, ffi, top_loc::Location}; #[derive(Debug)] pub struct Mesh { @@ -15,12 +15,12 @@ pub struct Mesh { } pub struct Mesher { - pub(crate) inner: UniquePtr, + pub(crate) inner: UniquePtr, } impl Mesher { pub fn try_new(shape: &Shape, triangulation_tolerance: f64) -> Result { - let inner = ffi::BRepMesh_IncrementalMesh_ctor(&shape.inner, triangulation_tolerance); + let inner = IncrementalMesh::new(&shape.inner, triangulation_tolerance); if inner.IsDone() { Ok(Self { inner }) @@ -38,7 +38,7 @@ impl Mesher { let triangulated_shape = Shape::from_shape(self.inner.pin_mut().Shape()); for face in triangulated_shape.faces() { - let mut location = ffi::TopLoc_Location_ctor(); + let mut location = Location::new(); let triangulation_handle = ffi::BRep_Tool_Triangulation(&face.inner, location.pin_mut()); @@ -50,8 +50,8 @@ impl Mesher { let face_point_count = triangulation.NbNodes(); for i in 1..=face_point_count { - let mut point = ffi::Poly_Triangulation_Node(triangulation, i); - point.pin_mut().Transform(&ffi::TopLoc_Location_Transformation(&location)); + let mut point = triangulation.node(i); + point.pin_mut().Transform(&location.transform()); vertices.push(dvec3(point.X(), point.Y(), point.Z())); } @@ -62,7 +62,7 @@ impl Mesher { let mut v_max = f64::NEG_INFINITY; for i in 1..=(face_point_count) { - let uv = ffi::Poly_Triangulation_UV(triangulation, i); + let uv = triangulation.uv(i); let (u, v) = (uv.X(), uv.Y()); u_min = u_min.min(u); @@ -92,7 +92,7 @@ impl Mesher { // TODO(bschwind) - Why do we start at 1 here? for i in 1..(normal_array.Length() as usize) { - let normal = ffi::Poly_Triangulation_Normal(triangulation, i as i32); + let normal = triangulation.normal(i as i32); normals.push(dvec3(normal.X(), normal.Y(), normal.Z())); } diff --git a/crates/opencascade/src/primitives/edge.rs b/crates/opencascade/src/primitives/edge.rs index 163761ca..b26d0f57 100644 --- a/crates/opencascade/src/primitives/edge.rs +++ b/crates/opencascade/src/primitives/edge.rs @@ -1,7 +1,7 @@ use crate::primitives::{make_axis_2, make_point}; use cxx::UniquePtr; use glam::{dvec3, DVec3}; -use opencascade_sys::ffi; +use opencascade_sys::{ffi, gc_pnts::TangentialDeflection}; use super::make_vec; @@ -151,7 +151,7 @@ impl Edge { pub fn approximation_segments(&self) -> ApproximationSegmentIterator { let adaptor_curve = ffi::BRepAdaptor_Curve_ctor(&self.inner); - let approximator = ffi::GCPnts_TangentialDeflection_ctor(&adaptor_curve, 0.1, 0.1); + let approximator = TangentialDeflection::new(&adaptor_curve, 0.1, 0.1); ApproximationSegmentIterator { count: 1, approximator } } @@ -167,16 +167,15 @@ impl Edge { pub struct ApproximationSegmentIterator { count: usize, - approximator: UniquePtr, + approximator: UniquePtr, } impl Iterator for ApproximationSegmentIterator { type Item = DVec3; fn next(&mut self) -> Option { - if self.count <= self.approximator.NbPoints() as usize { - let point = - ffi::GCPnts_TangentialDeflection_Value(&self.approximator, self.count as i32); + if self.count <= self.approximator.num_points() as usize { + let point = self.approximator.value(self.count as i32); self.count += 1; Some(dvec3(point.X(), point.Y(), point.Z())) diff --git a/crates/opencascade/src/primitives/face.rs b/crates/opencascade/src/primitives/face.rs index 7dfeffda..4090787e 100644 --- a/crates/opencascade/src/primitives/face.rs +++ b/crates/opencascade/src/primitives/face.rs @@ -9,7 +9,11 @@ use crate::{ }; use cxx::UniquePtr; use glam::{dvec3, DVec3}; -use opencascade_sys::ffi; +use opencascade_sys::{ + b_rep_g_prop::{self, BRepGProp, BRepGProp_SurfaceProperties}, + b_rep_tools, ffi, + g_prop::GProps, +}; pub struct Face { pub(crate) inner: UniquePtr, @@ -225,7 +229,7 @@ impl Face { let law_function = law_function_from_graph(radius_values); let law_handle = ffi::Law_Function_to_handle(law_function); - let profile_wire = ffi::outer_wire(&self.inner); + let profile_wire = b_rep_tools::outer_wire(&self.inner); let mut make_pipe_shell = make_pipe_shell_with_law_function(&profile_wire, &path.inner, &law_handle); @@ -247,12 +251,12 @@ impl Face { } pub fn center_of_mass(&self) -> DVec3 { - let mut props = ffi::GProp_GProps_ctor(); + let mut props = GProps::new(); let inner_shape = ffi::cast_face_to_shape(&self.inner); - ffi::BRepGProp_SurfaceProperties(inner_shape, props.pin_mut()); + BRepGProp_SurfaceProperties(inner_shape, props.pin_mut()); - let center = ffi::GProp_GProps_CentreOfMass(&props); + let center = props.center_of_mass(); dvec3(center.X(), center.Y(), center.Z()) } @@ -268,7 +272,7 @@ impl Face { let mut p = ffi::new_point(0.0, 0.0, 0.0); let mut normal = ffi::new_vec(0.0, 1.0, 0.0); - let face = ffi::BRepGProp_Face_ctor(&self.inner); + let face = b_rep_g_prop::Face::new(&self.inner); face.Normal(u, v, p.pin_mut(), normal.pin_mut()); dvec3(normal.X(), normal.Y(), normal.Z()) @@ -338,10 +342,10 @@ impl Face { } pub fn surface_area(&self) -> f64 { - let mut props = ffi::GProp_GProps_ctor(); + let mut props = GProps::new(); let inner_shape = ffi::cast_face_to_shape(&self.inner); - ffi::BRepGProp_SurfaceProperties(inner_shape, props.pin_mut()); + BRepGProp::surface_properties(inner_shape, props.pin_mut()); // Returns surface area, obviously. props.Mass() @@ -353,7 +357,7 @@ impl Face { #[must_use] pub fn outer_wire(&self) -> Wire { - let inner = ffi::outer_wire(&self.inner); + let inner = b_rep_tools::outer_wire(&self.inner); Wire { inner } } diff --git a/crates/opencascade/src/primitives/shape.rs b/crates/opencascade/src/primitives/shape.rs index 4021d1d6..ffa94c56 100644 --- a/crates/opencascade/src/primitives/shape.rs +++ b/crates/opencascade/src/primitives/shape.rs @@ -8,7 +8,7 @@ use crate::{ }; use cxx::UniquePtr; use glam::{dvec2, dvec3, DVec3}; -use opencascade_sys::ffi; +use opencascade_sys::{ffi, shape_upgrade::UnifySameDomain, stl_api, top_loc::Location}; use std::path::Path; pub struct Shape { @@ -597,13 +597,11 @@ impl Shape { path: P, triangulation_tolerance: f64, ) -> Result<(), Error> { - let mut stl_writer = ffi::StlAPI_Writer_ctor(); + let mut stl_writer = stl_api::Writer::new(); let mesher = Mesher::try_new(self, triangulation_tolerance)?; - let success = ffi::write_stl( - stl_writer.pin_mut(), - mesher.inner.Shape(), - path.as_ref().to_string_lossy().to_string(), - ); + let success = stl_writer + .pin_mut() + .write_stl(mesher.inner.Shape(), path.as_ref().to_string_lossy().to_string()); if success { Ok(()) @@ -614,7 +612,7 @@ impl Shape { #[must_use] pub fn clean(&self) -> Self { - let mut upgrader = ffi::ShapeUpgrade_UnifySameDomain_ctor(&self.inner, true, true, true); + let mut upgrader = UnifySameDomain::new(&self.inner, true, true, true); upgrader.pin_mut().AllowInternalEdges(false); upgrader.pin_mut().Build(); @@ -626,7 +624,7 @@ impl Shape { let translation_vec = make_vec(translation); transform.pin_mut().set_translation_vec(&translation_vec); - let location = ffi::TopLoc_Location_from_transform(&transform); + let location = Location::from_transform(&transform); self.inner.pin_mut().set_global_translation(&location, false); } diff --git a/crates/opencascade/src/primitives/wire.rs b/crates/opencascade/src/primitives/wire.rs index 5f55d405..7a74106f 100644 --- a/crates/opencascade/src/primitives/wire.rs +++ b/crates/opencascade/src/primitives/wire.rs @@ -1,3 +1,4 @@ +use opencascade_sys::{b_rep_tools, shape_analysis::connect_edges_to_wires, top_loc::Location}; use std::iter::once; use crate::{ @@ -97,7 +98,7 @@ impl Wire { EdgeConnection::Fuzzy { tolerance } => (tolerance, false), }; - ffi::connect_edges_to_wires(edges.pin_mut(), tolerance, shared, wires.pin_mut()); + connect_edges_to_wires(edges.pin_mut(), tolerance, shared, wires.pin_mut()); let mut make_wire = ffi::BRepBuilderAPI_MakeWire_ctor(); @@ -163,7 +164,7 @@ impl Wire { pub fn fillet(&self, radius: f64) -> Wire { // Create a face from this wire let face = Face::from_wire(self).fillet(radius); - let inner = ffi::outer_wire(&face.inner); + let inner = b_rep_tools::outer_wire(&face.inner); Self { inner } } @@ -172,7 +173,7 @@ impl Wire { #[must_use] pub fn chamfer(&self, distance_1: f64) -> Wire { let face = Face::from_wire(self).chamfer(distance_1); - let inner = ffi::outer_wire(&face.inner); + let inner = b_rep_tools::outer_wire(&face.inner); Self { inner } } @@ -234,7 +235,7 @@ impl Wire { transform.pin_mut().SetRotation(&rotation_axis_vec, angle.radians()); transform.pin_mut().set_translation_vec(&translation_vec); - let location = ffi::TopLoc_Location_from_transform(&transform); + let location = Location::from_transform(&transform); let wire_shape = ffi::cast_wire_to_shape(&self.inner); let mut wire_shape = Shape::from_shape(wire_shape).inner;