IGES 5.3 import and export; OBJ import; STL reading hardened
- IGES import (kernel iges_in, from the published specification). The file
is restated as STEP and read by the STEP reader, so an IGES file becomes
the same Import base feature.
- Manifold solid B-reps (186/514/510/508/504/502).
- Trimmed (144), bounded (143) and bare B-spline surfaces, sewn into a
solid by shared edges, with face orientation made consistent.
- Curves: lines, arcs, ellipses, composite and rational B-spline curves.
- Surfaces: planes, analytic surfaces 190-198, B-spline surfaces,
surfaces of revolution and tabulated cylinders.
- Transformations, units, colours, names (406 form 15 or labels).
Open, insert and drop .igs/.iges like STEP.
- IGES export (kernel iges_out): each body as a manifold solid B-rep on the
surfaces a STEP export uses, with name properties and colours.
ExportCommand to .igs.
- OBJ import as mesh bodies: objects/groups, polygons fanned, negative
indices, bad lines reported.
- STL: binary files whose header starts with "solid" and those with a zero
triangle count read as binary; non-finite vertices dropped; facet
normals ignored; ASCII with non-UTF-8 names. Mesh bodies get consistent
winding (stray inverted facets turned over).
- Tests: primitives and features round-trip through IGES (volume, area,
name, colour). Six trimmed patches sew into a closed box. Hostile IGES,
OBJ and STL inputs never panic. STL quirks. The engine exports a design
to IGES and opens it again. All 76 oracle parts round-trip through IGES
with matching volume (local check).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
7a2eb059c4
commit
51ffaf9945
13 files changed
+2615
-31
No files matched your search
@@ -95,6 +95,7 @@ pub fn mesh_body(positions: &[Vec3], triangles: &[[u32; 3]]) -> Result<Body> {
|
||||
if out.triangles.is_empty() {
|
||||
return Err(KernelError::Invalid("mesh has no triangles".into()));
|
||||
}
|
||||
unify_winding(&mut out);
|
||||
if out.volume6() < 0.0 && is_closed(&out) {
|
||||
for t in &mut out.triangles {
|
||||
t.swap(1, 2);
|
||||
@@ -103,6 +104,48 @@ pub fn mesh_body(positions: &[Vec3], triangles: &[[u32; 3]]) -> Result<Body> {
|
||||
Ok(Body { solid: Arc::new(crate::body::Solid::new_unchecked(Vec::new())), mesh: Some(Arc::new(out)), color: None, paint: None })
|
||||
}
|
||||
|
||||
/// Wind every connected piece one way: a triangle that runs a side in the same direction as
|
||||
/// its neighbour is turned over (files with stray inverted facets). Sides shared by more than
|
||||
/// two triangles are left alone.
|
||||
fn unify_winding(m: &mut TriMesh) {
|
||||
let mut sides: HashMap<(u32, u32), Vec<usize>> = HashMap::new();
|
||||
for (i, t) in m.triangles.iter().enumerate() {
|
||||
for (a, b) in [(t[0], t[1]), (t[1], t[2]), (t[2], t[0])] {
|
||||
sides.entry((a.min(b), a.max(b))).or_default().push(i);
|
||||
}
|
||||
}
|
||||
let runs = |t: &[u32; 3], a: u32, b: u32| [(t[0], t[1]), (t[1], t[2]), (t[2], t[0])].contains(&(a, b));
|
||||
let mut done = vec![false; m.triangles.len()];
|
||||
for start in 0..m.triangles.len() {
|
||||
if done[start] {
|
||||
continue;
|
||||
}
|
||||
done[start] = true;
|
||||
let mut stack = vec![start];
|
||||
while let Some(i) = stack.pop() {
|
||||
let Some(t) = m.triangles.get(i).copied() else { continue };
|
||||
for (a, b) in [(t[0], t[1]), (t[1], t[2]), (t[2], t[0])] {
|
||||
let Some(list) = sides.get(&(a.min(b), a.max(b))) else { continue };
|
||||
if list.len() != 2 {
|
||||
continue;
|
||||
}
|
||||
for &j in list {
|
||||
if j == i || done[j] {
|
||||
continue;
|
||||
}
|
||||
done[j] = true;
|
||||
if let Some(u) = m.triangles.get_mut(j)
|
||||
&& runs(u, a, b)
|
||||
{
|
||||
u.swap(1, 2);
|
||||
}
|
||||
stack.push(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Every triangle side is shared by exactly two triangles in opposite directions.
|
||||
fn is_closed(m: &TriMesh) -> bool {
|
||||
let mut count: HashMap<(u32, u32), i32> = HashMap::new();
|
||||
|
||||
Reference in new issue
Block a user