Skip to main content

brep_kernel/io/step_import/
mod.rs

1//! ISO-10303-21 (STEP Part 21) importer — the read side of `step.rs`.
2//!
3//! Strategy is ROUND-TRIP-FIRST: this reads back exactly what `export_step`
4//! writes (an all-NURBS ADVANCED_BREP: B_SPLINE_CURVE/SURFACE_WITH_KNOTS and
5//! their rational complex forms, VERTEX_POINT / EDGE_CURVE / ORIENTED_EDGE /
6//! EDGE_LOOP / FACE_(OUTER_)BOUND / ADVANCED_FACE / CLOSED_SHELL /
7//! MANIFOLD_SOLID_BREP), reconstructs a `BrepSolid`, and validates it.
8//!
9//! The exporter drops pcurves and degenerate (pole) edges, so this module
10//! rebuilds both: pcurves are DERIVED by projecting each 3D edge curve onto its
11//! carrier surface (`build_pcurve_on_surface_range`), seam edges are placed on
12//! opposite domain boundaries, and collapsed pole boundaries are re-synthesised
13//! as degenerate edges so faces close their parameter domain and integrate to
14//! the correct mass properties.
15//!
16//! Analytic-surface recognition on import (PLANE/CYLINDRICAL/…) is a documented
17//! follow-up: the exporter emits only NURBS, so faithful NURBS round-trip is the
18//! milestone. Unsupported entities produce a clear `Err`, never a panic.
19
20use crate::topology::{
21    BrepSolid, CoedgeRecord, EdgeRecord, FaceRecord, LoopRecord, ShellRecord, VertexRecord,
22};
23use crate::{
24    build_pcurve_on_surface_range, make_arc, make_extrusion, make_line, make_plane,
25    make_revolution, offset_surface, transform_brep, AffineTransform, NurbsCurve, NurbsSurface,
26    Vec3, Vec4,
27};
28use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
29use std::collections::VecDeque;
30
31const TAU: f64 = std::f64::consts::TAU;
32
33mod parse;
34mod bodies;
35mod builder;
36mod geometry;
37#[cfg(test)]
38mod tests;
39
40use parse::*;
41use bodies::*;
42use builder::*;
43use geometry::*;
44
45
46// ---------------------------------------------------------------------------
47// Topology assembly
48// ---------------------------------------------------------------------------
49
50/// Public entry: parse a STEP Part 21 document and return one `BrepSolid` per
51/// MANIFOLD_SOLID_BREP, FACETED_BREP, or certified BREP_WITH_VOIDS. Every
52/// returned solid passes `validate()`.
53pub fn import_step(text: &str) -> Result<Vec<BrepSolid>, String> {
54    let (solids, _failed, first_error) = collect_step_solids(text)?;
55    if solids.is_empty() {
56        return Err(first_error.unwrap_or_else(|| {
57            "step_import: no MANIFOLD_SOLID_BREP/FACETED_BREP/BREP_WITH_VOIDS body imported (unsupported or invalid representation)"
58                .into()
59        }));
60    }
61    Ok(solids)
62}
63
64/// Like [`import_step`] but reports how many bodies failed and the first error,
65/// so callers can distinguish a fully- from a partially-imported assembly.
66pub fn import_step_report(text: &str) -> Result<(Vec<BrepSolid>, usize, Option<String>), String> {
67    collect_step_solids(text)
68}
69