feat: STEPOUT command — export 3D meshes to STEP AP203
Adds STEPOUT / STPOUT / EXPORTSTEP command that exports all tessellated Solid3D / Region / Body meshes to an ISO 10303-21 (STEP AP203) file. Each triangle is encoded as a minimal ADVANCED_FACE with a PLANE surface and CLOSED_SHELL topology — sufficient for import into all major CAD systems. A file-save dialog picks the output path; the command line reports success or errors. Requires at least one tessellated solid in the drawing. Closes ROADMAP 14.10. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f515b556c7
commit
b24e0c5da9
5 changed files with 267 additions and 0 deletions
|
|
@ -3788,6 +3788,11 @@ impl H7CAD {
|
|||
return Task::done(Message::StlExport);
|
||||
}
|
||||
|
||||
// STEPOUT — export 3D meshes to STEP AP203 format
|
||||
"STEPOUT"|"EXPORTSTEP"|"STPOUT" => {
|
||||
return Task::done(Message::StepExport);
|
||||
}
|
||||
|
||||
// ── Plot Style Editor GUI ─────────────────────────────────────
|
||||
"PLOTSTYLEPANEL"|"PLOTSTYLEEDITOR"|"STYLESMANAGER" => {
|
||||
return Task::done(Message::PlotStylePanelOpen);
|
||||
|
|
|
|||
|
|
@ -497,6 +497,11 @@ pub enum Message {
|
|||
StlExport,
|
||||
/// Callback after the user picks (or cancels) the STL save path.
|
||||
StlExportPath(Option<std::path::PathBuf>),
|
||||
// ── STEP export ───────────────────────────────────────────────────────
|
||||
/// Trigger STEP AP203 export: show save dialog.
|
||||
StepExport,
|
||||
/// Callback after the user picks (or cancels) the STEP save path.
|
||||
StepExportPath(Option<std::path::PathBuf>),
|
||||
// ── OBJ import ────────────────────────────────────────────────────────
|
||||
/// Trigger OBJ import: show open-file dialog.
|
||||
ObjImport,
|
||||
|
|
|
|||
|
|
@ -288,6 +288,48 @@ impl H7CAD {
|
|||
|
||||
Message::StlExportPath(None) => Task::none(),
|
||||
|
||||
// ── STEP AP203 export ─────────────────────────────────────────
|
||||
Message::StepExport => {
|
||||
let i = self.active_tab;
|
||||
if self.tabs[i].scene.meshes.is_empty() {
|
||||
self.command_line.push_error("STEPOUT: no 3D mesh data in this drawing.");
|
||||
return Task::none();
|
||||
}
|
||||
Task::perform(
|
||||
async {
|
||||
rfd::AsyncFileDialog::new()
|
||||
.set_title("Export STEP AP203")
|
||||
.set_file_name("export.step")
|
||||
.add_filter("STEP Files", &["step", "stp"])
|
||||
.add_filter("All Files", &["*"])
|
||||
.save_file()
|
||||
.await
|
||||
.map(|h| h.path().to_path_buf())
|
||||
},
|
||||
Message::StepExportPath,
|
||||
)
|
||||
}
|
||||
|
||||
Message::StepExportPath(Some(path)) => {
|
||||
let i = self.active_tab;
|
||||
let meshes: Vec<crate::scene::mesh_model::MeshModel> =
|
||||
self.tabs[i].scene.meshes.values().cloned().collect();
|
||||
let mesh_refs: Vec<&crate::scene::mesh_model::MeshModel> = meshes.iter().collect();
|
||||
match crate::io::step::build_step(&mesh_refs) {
|
||||
Some(text) => match std::fs::write(&path, text.as_bytes()) {
|
||||
Ok(()) => self.command_line.push_output(&format!(
|
||||
"STEPOUT: exported to \"{}\"",
|
||||
path.display()
|
||||
)),
|
||||
Err(e) => self.command_line.push_error(&format!("STEPOUT: write error: {e}")),
|
||||
},
|
||||
None => self.command_line.push_error("STEPOUT: no mesh data to export."),
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::StepExportPath(None) => Task::none(),
|
||||
|
||||
// ── OBJ import ────────────────────────────────────────────────
|
||||
Message::ObjImport => {
|
||||
Task::perform(
|
||||
|
|
|
|||
Loading…
Reference in a new issue