Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add iges import and export #186

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/opencascade-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const OCCT_LIBS: &[&str] = &[
"TKBRep",
"TKPrim",
"TKDESTEP",
"TKDEIGES",
"TKDESTL",
"TKMesh",
"TKShHealing",
Expand Down
20 changes: 19 additions & 1 deletion crates/opencascade-sys/include/wrapper.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
#include <Geom_Plane.hxx>
#include <Geom_Surface.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <IGESControl_Reader.hxx>
#include <IGESControl_Writer.hxx>
#include <Law_Function.hxx>
#include <Law_Interpol.hxx>
#include <NCollection_Array1.hxx>
Expand Down Expand Up @@ -361,7 +363,15 @@ inline IFSelect_ReturnStatus read_step(STEPControl_Reader &reader, rust::String
return reader.ReadFile(theFileName.c_str());
}

inline std::unique_ptr<TopoDS_Shape> one_shape(const STEPControl_Reader &reader) {
inline IFSelect_ReturnStatus read_iges(IGESControl_Reader &reader, rust::String theFileName) {
return reader.ReadFile(theFileName.c_str());
}

inline std::unique_ptr<TopoDS_Shape> one_shape_step(const STEPControl_Reader &reader) {
return std::unique_ptr<TopoDS_Shape>(new TopoDS_Shape(reader.OneShape()));
}

inline std::unique_ptr<TopoDS_Shape> one_shape_iges(const IGESControl_Reader &reader) {
return std::unique_ptr<TopoDS_Shape>(new TopoDS_Shape(reader.OneShape()));
}

Expand All @@ -370,10 +380,18 @@ inline IFSelect_ReturnStatus transfer_shape(STEPControl_Writer &writer, const To
return writer.Transfer(theShape, STEPControl_AsIs);
}

inline void compute_model(IGESControl_Writer &writer) { writer.ComputeModel(); }

inline bool add_shape(IGESControl_Writer &writer, const TopoDS_Shape &theShape) { return writer.AddShape(theShape); }

inline IFSelect_ReturnStatus write_step(STEPControl_Writer &writer, rust::String theFileName) {
return writer.Write(theFileName.c_str());
}

inline bool write_iges(IGESControl_Writer &writer, rust::String theFileName) {
return writer.Write(theFileName.c_str());
}

inline bool write_stl(StlAPI_Writer &writer, const TopoDS_Shape &theShape, rust::String theFileName) {
return writer.Write(theShape, theFileName.c_str());
}
Expand Down
22 changes: 21 additions & 1 deletion crates/opencascade-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1146,35 +1146,55 @@ pub mod ffi {

// Data Import
type STEPControl_Reader;
type IGESControl_Reader;
type IFSelect_ReturnStatus;

#[cxx_name = "construct_unique"]
pub fn STEPControl_Reader_ctor() -> UniquePtr<STEPControl_Reader>;

#[cxx_name = "construct_unique"]
pub fn IGESControl_Reader_ctor() -> UniquePtr<IGESControl_Reader>;

pub fn read_step(
reader: Pin<&mut STEPControl_Reader>,
filename: String,
) -> IFSelect_ReturnStatus;
pub fn read_iges(
reader: Pin<&mut IGESControl_Reader>,
filename: String,
) -> IFSelect_ReturnStatus;
pub fn TransferRoots(
self: Pin<&mut STEPControl_Reader>,
progress: &Message_ProgressRange,
) -> i32;
pub fn one_shape(reader: &STEPControl_Reader) -> UniquePtr<TopoDS_Shape>;
pub fn TransferRoots(
self: Pin<&mut IGESControl_Reader>,
progress: &Message_ProgressRange,
) -> i32;
pub fn one_shape_step(reader: &STEPControl_Reader) -> UniquePtr<TopoDS_Shape>;
pub fn one_shape_iges(reader: &IGESControl_Reader) -> UniquePtr<TopoDS_Shape>;

// Data Export
type STEPControl_Writer;
type IGESControl_Writer;

#[cxx_name = "construct_unique"]
pub fn STEPControl_Writer_ctor() -> UniquePtr<STEPControl_Writer>;

#[cxx_name = "construct_unique"]
pub fn IGESControl_Writer_ctor() -> UniquePtr<IGESControl_Writer>;

pub fn transfer_shape(
writer: Pin<&mut STEPControl_Writer>,
shape: &TopoDS_Shape,
) -> IFSelect_ReturnStatus;
pub fn add_shape(writer: Pin<&mut IGESControl_Writer>, shape: &TopoDS_Shape) -> bool;
pub fn compute_model(writer: Pin<&mut IGESControl_Writer>);
pub fn write_step(
writer: Pin<&mut STEPControl_Writer>,
filename: String,
) -> IFSelect_ReturnStatus;
pub fn write_iges(writer: Pin<&mut IGESControl_Writer>, filename: String) -> bool;

type StlAPI_Writer;

Expand Down
4 changes: 4 additions & 0 deletions crates/opencascade/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ pub enum Error {
StlWriteFailed,
#[error("failed to read STEP file")]
StepReadFailed,
#[error("failed to read IGES file")]
IgesReadFailed,
#[error("failed to read KiCAD PCB file: {0}")]
KicadReadFailed(#[from] kicad_parser::Error),
#[error("failed to write STEP file")]
StepWriteFailed,
#[error("failed to write IGES file")]
IgesWriteFailed,
#[error("failed to triangulate Shape")]
TriangulationFailed,
#[error("encountered a face with no triangulation")]
Expand Down
38 changes: 37 additions & 1 deletion crates/opencascade/src/primitives/shape.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,7 @@ impl Shape {

reader.pin_mut().TransferRoots(&ffi::Message_ProgressRange_ctor());

let inner = ffi::one_shape(&reader);
let inner = ffi::one_shape_step(&reader);

Ok(Self { inner })
}
Expand All @@ -518,6 +518,42 @@ impl Shape {
Ok(())
}

pub fn read_iges(path: impl AsRef<Path>) -> Result<Self, Error> {
let mut reader = ffi::IGESControl_Reader_ctor();

let status = ffi::read_iges(reader.pin_mut(), path.as_ref().to_string_lossy().to_string());

reader.pin_mut().TransferRoots(&ffi::Message_ProgressRange_ctor());

if status != ffi::IFSelect_ReturnStatus::IFSelect_RetDone {
return Err(Error::IgesReadFailed);
}

let inner = ffi::one_shape_iges(&reader);

Ok(Self { inner })
}

pub fn write_iges(&self, path: impl AsRef<Path>) -> Result<(), Error> {
let mut writer = ffi::IGESControl_Writer_ctor();

let success = ffi::add_shape(writer.pin_mut(), &self.inner);

if !success {
return Err(Error::IgesWriteFailed);
}

ffi::compute_model(writer.pin_mut());
let success =
ffi::write_iges(writer.pin_mut(), path.as_ref().to_string_lossy().to_string());

if success {
Ok(())
} else {
Err(Error::IgesWriteFailed)
}
}

#[must_use]
pub fn union(&self, other: &Shape) -> BooleanShape {
let mut fuse_operation = ffi::BRepAlgoAPI_Fuse_ctor(&self.inner, &other.inner);
Expand Down
6 changes: 3 additions & 3 deletions docs/writing_bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,13 @@ Standard_EXPORT TopoDS_Shape OneShape() const;
Unfortunately, this returns a bare `TopoDS_Shape` so we can't directly bind to it, we'll have to create a wrapper C++ function.

```rust
pub fn one_shape(reader: &STEPControl_Reader) -> UniquePtr<TopoDS_Shape>;
pub fn one_shape_step(reader: &STEPControl_Reader) -> UniquePtr<TopoDS_Shape>;
```

and

```c++
inline std::unique_ptr<TopoDS_Shape> one_shape(const STEPControl_Reader &reader) {
inline std::unique_ptr<TopoDS_Shape> one_shape_step(const STEPControl_Reader &reader) {
return std::unique_ptr<TopoDS_Shape>(new TopoDS_Shape(reader.OneShape()));
}
```
Expand Down Expand Up @@ -233,7 +233,7 @@ pub fn from_step_file<P: AsRef<Path>>(path: P) -> Shape {
read_step(reader.pin_mut(), path.as_ref().to_string_lossy().to_string());
reader.pin_mut().TransferRoots(&Message_ProgressRange_ctor());

let inner = one_shape(&reader);
let inner = one_shape_step(&reader);

// Assuming a Shape struct has a UniquePtr<TopoDS_Shape> field called `inner`
Shape { inner }
Expand Down
3 changes: 3 additions & 0 deletions examples/src/write_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct Args {
enum Format {
Step,
Stl,
Iges,
}

fn main() {
Expand All @@ -38,6 +39,7 @@ fn main() {
});

match format {
Format::Iges => model.write_iges(args.output).unwrap(),
Format::Step => model.write_step(args.output).unwrap(),
Format::Stl => model.write_stl(args.output).unwrap(),
}
Expand All @@ -47,6 +49,7 @@ fn determine_format(extension: &OsStr) -> Option<Format> {
match extension.to_ascii_lowercase().as_bytes() {
b"step" | b"stp" => Some(Format::Step),
b"stl" => Some(Format::Stl),
b"iges" | b"igs" => Some(Format::Iges),
_ => None,
}
}
Loading