STEP export: AP242 file of our own, names, colours, components as assemblies

Our writer assembles the file: AP242 header and contexts, a product per part
(or per component, with NEXT_ASSEMBLY_USAGE_OCCURRENCE and item-defined
placements per occurrence), named solids, surface colours as styled items,
ADVANCED_FACE for advanced breps. truck now writes only each body's B-rep,
which we copy in; identical geometric entities are written once and shared.
Designs with components export as assemblies (bodies in component frames).

step_validate also rejects unreferenced non-root entities. Tests: the sample
plate and a component assembly export, validate and read back with no
warnings and the same volume, area and face counts; the oracle replay checks
area and faces too (39 rebuildable cases pass). An independent Part 21
parser (step-p21, run outside the repo) accepts our exports.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 00:16:52 +00:00
1 parent dd7485503a
commit 9330ee5698
10 files changed
+682 -14

No files matched your search

+9 -3
View File
@@ -67,9 +67,15 @@ fn step_export_check(s: &solvecraft_engine::Session, volume: f64) -> (bool, Stri
Ok(imp) if !imp.warnings.is_empty() => (false, format!("warnings: {}", imp.warnings.join("; "))),
Ok(imp) if imp.bodies.len() != st.bodies.len() => (false, format!("{} bodies back of {}", imp.bodies.len(), st.bodies.len())),
Ok(imp) => {
let v: f64 = imp.bodies.iter().filter_map(|b| solvecraft_engine::kernel::measure(&b.body).ok()).map(|m| m.volume).sum();
let ok = (v - volume).abs() <= REL_TOL * volume.abs().max(1.0);
(ok, format!("re-imported volume {v:.3}"))
let m: Vec<_> = imp.bodies.iter().filter_map(|b| solvecraft_engine::kernel::measure(&b.body).ok()).collect();
let m0: Vec<_> = st.bodies.iter().filter_map(|b| solvecraft_engine::kernel::measure(&b.body).ok()).collect();
let v: f64 = m.iter().map(|x| x.volume).sum();
let (a, a0): (f64, f64) = (m.iter().map(|x| x.area).sum(), m0.iter().map(|x| x.area).sum());
let faces: usize = imp.bodies.iter().map(|b| b.file_faces).sum();
let faces0: usize = st.bodies.iter().map(|b| b.body.face_count()).sum();
let close = |x: f64, y: f64| (x - y).abs() <= REL_TOL * y.abs().max(1.0);
let ok = close(v, volume) && close(a, a0) && faces == faces0;
(ok, format!("re-imported volume {v:.3}, area {a:.3} (was {a0:.3}), faces {faces} (was {faces0})"))
}
Err(e) => (false, format!("import: {e}")),
}