Design: STEP export of the CAD model

Add an "Export STEP…" button to the Design panel that writes every body to a
.step file as native B-rep (not mesh).

- CadDocument::export_step: compound all bodies (applying their per-body Move
  display transform so the STEP matches what Commit ships) and write via OCCT
  STEPControl_Writer (AsIs). Full error handling incl. OCCT Standard_Failure.
- DesignPanel::on_export_step: bake any open preview, wxFileDialog save, export
  at the displayed body positions, status feedback.

Kernel write path verified with a standalone OCCT box->STEP->readback check
(1 solid, non-null) against the same OCCT build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BVzKmX6Y1aEteit1HTXG4Q
This commit is contained in:
Tommaso Bianchi
2026-06-30 08:21:03 +02:00
co-authored by Claude Opus 4.8
parent 30713f0f23
commit aa2907f730
4 changed files with 85 additions and 1 deletions
+47
View File
@@ -39,6 +39,9 @@
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Trsf.hxx> // pattern: rigid copy transforms
#include <STEPControl_Writer.hxx> // STEP export (native B-rep)
#include <STEPControl_StepModelType.hxx>
#include <IFSelect_ReturnStatus.hxx>
#include <gp_Ax1.hxx> // pattern: rotation axis (circular)
#include <BRepBuilderAPI_Transform.hxx>
#include <cmath>
@@ -1780,4 +1783,48 @@ bool CadDocument::deserialize_recipe(const std::string& blob)
}
}
bool CadDocument::export_step(const std::string& path,
const std::vector<Transform3d>& body_xforms,
std::string& err) const
{
err.clear();
if (bodies.empty()) { err = "nothing to export"; return false; }
try {
// Compound every body at its displayed (Move-gizmo) position so the STEP matches
// what Commit ships. Move transforms are rigid, so gp_Trsf::SetValues is valid.
BRep_Builder bld;
TopoDS_Compound comp;
bld.MakeCompound(comp);
for (size_t i = 0; i < bodies.size(); ++i) {
if (bodies[i].shape.IsNull()) continue;
TopoDS_Shape s = bodies[i].shape;
if (i < body_xforms.size() && !body_xforms[i].isApprox(Transform3d::Identity())) {
const Transform3d& m = body_xforms[i];
gp_Trsf t;
t.SetValues(m(0,0), m(0,1), m(0,2), m(0,3),
m(1,0), m(1,1), m(1,2), m(1,3),
m(2,0), m(2,1), m(2,2), m(2,3));
s = BRepBuilderAPI_Transform(s, t, true).Shape();
}
bld.Add(comp, s);
}
STEPControl_Writer writer;
if (writer.Transfer(comp, STEPControl_AsIs) != IFSelect_RetDone) {
err = "STEP transfer failed";
return false;
}
if (writer.Write(path.c_str()) != IFSelect_RetDone) {
err = "cannot write STEP file";
return false;
}
} catch (const Standard_Failure& e) {
err = e.GetMessageString() ? e.GetMessageString() : "OCCT failed to write STEP";
return false;
} catch (const std::exception& e) {
err = e.what();
return false;
}
return true;
}
} // namespace Slic3r