STEP export: undo face merging for a body when the merged faces do not read back cleanly
With solvecraft-repo's curved-edge fillets (d72ec38), oracle 40's torus
groove comes out of truck in three pieces. Merging them made a band round the
torus whose single loop crosses itself, and the reader could not lay it out
("unsupported seam loop layout (2 runs)"). Each body's merged B-rep is now
read back. If that gives warnings and the unmerged pieces read cleanly, the
pieces are written instead.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
2ac226cf0a
commit
8ea38bc518
1 file changed
+41
@@ -937,10 +937,51 @@ fn brep_exchange(b: &Body) -> Result<p21::Exchange> {
|
||||
let text = crate::step::truck_step(&[b], "SolveCraft")?;
|
||||
let mut ex = p21::parse(&text).map_err(|e| KernelError::Failed(format!("STEP export: {e}")))?;
|
||||
collapse_short_edges(&mut ex);
|
||||
let plain = ex.clone();
|
||||
merge_split_faces(&mut ex);
|
||||
// Keep the merged faces only when they read back as cleanly as the pieces (a merge that
|
||||
// leaves a face the reader cannot lay out, such as a band round a closed surface whose
|
||||
// loop crosses itself, is undone).
|
||||
let clean = |ex: &p21::Exchange| {
|
||||
let header = text.split("DATA;").next().unwrap_or_default();
|
||||
exchange_text(header, ex).and_then(|t| crate::step_in::step_import(&t).ok()).is_some_and(|imp| imp.warnings.is_empty())
|
||||
};
|
||||
if ex.entities.len() != plain.entities.len() && !clean(&ex) && clean(&plain) {
|
||||
return Ok(plain);
|
||||
}
|
||||
Ok(ex)
|
||||
}
|
||||
|
||||
/// A parsed exchange written back as STEP text (with the given header).
|
||||
fn exchange_text(header: &str, ex: &p21::Exchange) -> Option<String> {
|
||||
let map: HashMap<u64, u64> = ex.entities.keys().map(|k| (*k, *k)).collect();
|
||||
let mut ids: Vec<u64> = ex.entities.keys().copied().collect();
|
||||
ids.sort();
|
||||
let mut o = format!("{header}DATA;\n");
|
||||
for id in ids {
|
||||
let e = ex.get(id)?;
|
||||
let _ = write!(o, "#{id}=");
|
||||
if e.is_complex() {
|
||||
o.push('(');
|
||||
for r in &e.records {
|
||||
o.push_str(&r.name);
|
||||
o.push('(');
|
||||
params(&r.params, &map, &mut o).ok()?;
|
||||
o.push(')');
|
||||
}
|
||||
o.push(')');
|
||||
} else {
|
||||
o.push_str(e.name());
|
||||
o.push('(');
|
||||
params(e.params(), &map, &mut o).ok()?;
|
||||
o.push(')');
|
||||
}
|
||||
o.push_str(";\n");
|
||||
}
|
||||
o.push_str("ENDSEC;\nEND-ISO-10303-21;\n");
|
||||
Some(o)
|
||||
}
|
||||
|
||||
fn rigid_frame(m: &[[f64; 4]; 4]) -> Result<([f64; 3], [f64; 3], [f64; 3])> {
|
||||
let x = [m[0][0], m[0][1], m[0][2]];
|
||||
let y = [m[1][0], m[1][1], m[1][2]];
|
||||
|
||||
Reference in new issue
Block a user