Table of Contents

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().