mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-18 14:32:36 +00:00
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:
co-authored by
Claude Opus 4.8
parent
30713f0f23
commit
aa2907f730
@@ -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
|
||||
|
||||
@@ -360,6 +360,13 @@ public:
|
||||
std::string serialize_recipe() const;
|
||||
bool deserialize_recipe(const std::string& blob);
|
||||
|
||||
// Export every body to a STEP file as native B-rep (not mesh). body_xforms is the
|
||||
// per-body display transform (Move gizmo); when supplied the bodies are written at
|
||||
// those positions so the STEP matches what Commit ships. false + err on failure.
|
||||
bool export_step(const std::string& path,
|
||||
const std::vector<Transform3d>& body_xforms,
|
||||
std::string& err) const;
|
||||
|
||||
// Undo/redo of the feature recipe (Onshape-style Ctrl+Z). The caller marks a
|
||||
// user-action boundary by calling checkpoint() BEFORE the mutation(s) for that
|
||||
// action (add/delete/move/replace, or a direct features edit). undo()/redo() then
|
||||
|
||||
@@ -1514,7 +1514,11 @@ DesignPanel::DesignPanel(wxWindow* parent)
|
||||
|
||||
auto* commit = new wxButton(m_form, wxID_ANY, _L("Commit to Plate"));
|
||||
commit->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_commit(); });
|
||||
root->Add(commit, 0, wxALL, 12);
|
||||
root->Add(commit, 0, wxLEFT | wxRIGHT | wxTOP, 12);
|
||||
|
||||
auto* export_step = new wxButton(m_form, wxID_ANY, _L("Export STEP…"));
|
||||
export_step->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { on_export_step(); });
|
||||
root->Add(export_step, 0, wxALL, 12);
|
||||
|
||||
m_shape->Bind(wxEVT_CHOICE, [this](wxCommandEvent& e) { on_shape_changed(); e.Skip(); });
|
||||
on_shape_changed();
|
||||
@@ -4766,6 +4770,31 @@ void DesignPanel::on_edit_feature()
|
||||
}
|
||||
}
|
||||
|
||||
void DesignPanel::on_export_step()
|
||||
{
|
||||
// Bake any open feature preview first, so the STEP matches what is shown (mirrors on_commit).
|
||||
if (m_active != Tool::None)
|
||||
confirm_tool();
|
||||
if (m_doc.bodies.empty()) {
|
||||
m_status->SetForegroundColour(wxNullColour);
|
||||
m_status->SetLabel(_L("Nothing to export — add a feature first"));
|
||||
m_status->Refresh();
|
||||
return;
|
||||
}
|
||||
wxFileDialog dlg(this, _L("Export STEP"), wxEmptyString, "model.step",
|
||||
"STEP files (*.step;*.stp)|*.step;*.stp",
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if (dlg.ShowModal() != wxID_OK)
|
||||
return;
|
||||
sync_body_xform(); // export bodies at their displayed Move-gizmo positions
|
||||
std::string err;
|
||||
const bool ok = m_doc.export_step(dlg.GetPath().ToUTF8().data(), m_body_xform, err);
|
||||
m_status->SetForegroundColour(ok ? wxColour(120, 210, 120) : wxColour(235, 110, 110));
|
||||
m_status->SetLabel(ok ? _L("Exported STEP")
|
||||
: _L("STEP export failed: ") + wxString::FromUTF8(err));
|
||||
m_status->Refresh();
|
||||
}
|
||||
|
||||
void DesignPanel::on_commit()
|
||||
{
|
||||
// A feature tool open with a live preview ghost (e.g. a fillet being previewed) is
|
||||
|
||||
@@ -97,6 +97,7 @@ private:
|
||||
// a modal dialog editing the feature's placement transform in place.
|
||||
void on_transform_imported(int feat_idx);
|
||||
void on_commit();
|
||||
void on_export_step(); // write all bodies to a .step file (native B-rep)
|
||||
// Rehydrate the parametric model from a project's saved recipe (3MF
|
||||
// Metadata/SnapOrca_cad.bin): deserialize -> recompute -> refresh viewport + tree.
|
||||
void load_recipe(const std::string& blob);
|
||||
|
||||
Reference in New Issue
Block a user