Files
| Format | Shapes only | With names, colors, assemblies |
|---|---|---|
| STEP | STEPControl_Reader, STEPControl_Writer |
STEPCAFControl_Reader, STEPCAFControl_Writer (Assemblies) |
| IGES | IGESControl_Reader, IGESControl_Writer |
IGESCAFControl_Reader, IGESCAFControl_Writer |
| BRep (OCCT's own) | BRepTools.Read, BRepTools.Write, BinTools (binary) |
|
| STL | StlAPI_Writer, RWStl.ReadFile |
|
| glTF | RWGltf_CafWriter, RWGltf_CafReader |
|
| OBJ | RWObj_CafWriter, RWObj_CafReader |
|
| PLY | RWPly_CafWriter |
|
| VRML | VrmlAPI_Writer |
VrmlAPI_Writer.WriteDoc |
STEP and IGES keep exact geometry. STL, glTF, OBJ and PLY hold triangles: mesh first.
How readers work
The STEP and IGES readers work in two steps: ReadFile loads the file's entities into a model, TransferRoots translates them into shapes.
sequenceDiagram
participant App as your code
participant Reader as STEPControl_Reader
participant Model as model of entities
App->>Reader: ReadFile(path)
Reader->>Model: parse
Reader-->>App: IFSelect_RetDone
App->>Reader: TransferRoots()
Reader->>Model: translate each root entity
Reader-->>App: number of shapes
App->>Reader: OneShape()
Reader-->>App: TopoDS_Shape (a compound for several)
STEP
var writer = new STEPControl_Writer();
if (writer.Transfer(shape, STEPControl_StepModelType.STEPControl_AsIs)
!= IFSelect_ReturnStatus.IFSelect_RetDone
|| writer.Write("Ünïcödé.step") != IFSelect_ReturnStatus.IFSelect_RetDone)
{
throw new IOException("writing the STEP file failed");
}
var reader = new STEPControl_Reader();
if (reader.ReadFile("Ünïcödé.step") != IFSelect_ReturnStatus.IFSelect_RetDone)
{
throw new IOException("reading the STEP file failed");
}
reader.TransferRoots(); // translates every root entity
var read = reader.OneShape(); // all of them: one shape, or a compound
Paths are UTF-8 on every platform: Ünïcödé.step works. NbRootsForTransfer() and TransferRoot(i) translate roots one by one, NbShapes() and Shape(i) give them separately.
IGES
var writer =
new IGESControl_Writer("MM", 1); // 1: faces as B-rep solids, 0: as trimmed surfaces
writer.AddShape(shape);
writer.ComputeModel();
writer.Write("part.igs");
var reader = new IGESControl_Reader();
reader.ReadFile("part.igs");
reader.TransferRoots();
var read = reader.OneShape();
BRep
OCCT's native format, exact and fast; the choice for caching shapes between runs.
// OCCT's own format keeps the shape exactly as it is
BRepTools.Write(shape, "part.brep");
var read = new TopoDS_Shape(); // Read fills the shape it's given
BRepTools.Read(read, "part.brep", new BRep_Builder());
Streams
Every reader and writer taking a std::istream or std::ostream takes a System.IO.Stream: files, memory, network.
// any System.IO.Stream stands in for std::ostream and std::istream
using var buffer = new MemoryStream();
BRepTools.Write(shape, buffer);
buffer.Position = 0;
var read = new TopoDS_Shape();
BRepTools.Read(read, buffer, new BRep_Builder());
The stream is lent for the call: OCCT writes into a native buffer that's copied to the stream afterwards, and reads the stream's remaining bytes, leaving a seekable stream positioned where it stopped.
STL
// STL holds triangles: mesh first
new BRepMesh_IncrementalMesh(shape, 0.05);
var writer = new StlAPI_Writer();
writer.ASCIIMode() = false; // a ref return: binary STL
writer.Write(shape, "part.stl");
// read back as one triangulation, not as a face per triangle
var mesh = RWStl.ReadFile("part.stl");
var triangles = mesh.NbTriangles();
StlAPI_Reader also reads STL, but into a face per triangle, slow and large for real meshes; RWStl.ReadFile gives one Poly_Triangulation.
glTF and OBJ
The mesh formats with materials write XCAF documents:
// the glTF and OBJ writers take an XCAF document, for names, colors and assemblies
var application = XCAFApp_Application.GetApplication();
TDocStd_Document? document = null;
application.NewDocument("MDTV-XCAF", ref document);
var label = XCAFDoc_DocumentTool.ShapeTool(document!.Main()).AddShape(shape, false);
TDataStd_Name.Set(label, "cylinder");
// they write the triangulation: mesh first
new BRepMesh_IncrementalMesh(shape, 0.05);
var writer = new RWGltf_CafWriter("part.glb", true); // true: binary glTF
var axes = writer.ChangeCoordinateSystemConverter();
axes.SetInputLengthUnit(0.001); // millimetres in, glTF's metres out
axes.SetInputCoordinateSystem(RWMesh_CoordinateSystem
.RWMesh_CoordinateSystem_Zup); // Z up in, glTF's Y up out
var written = writer.Perform(document, new TColStd_IndexedDataMapOfStringString(),
new Message_ProgressRange());
application.Close(document);
RWObj_CafWriter works the same way. Reading: RWGltf_CafReader and RWObj_CafReader fill a document (SetDocument, then Perform(path, new Message_ProgressRange())) with triangulated faces.
Progress
Methods that take a Message_ProgressRange last, with a default, have it left out in C#. Where OCCT requires one, pass new Message_ProgressRange().