BREP_kernel 0.2.0

A boundary representation (BREP) geometry kernel for building CAD applications.
Documentation
//! ISO-10303-21 (STEP Part 21) importer — the read side of `step.rs`.
//!
//! Strategy is ROUND-TRIP-FIRST: this reads back exactly what `export_step`
//! writes (an all-NURBS ADVANCED_BREP: B_SPLINE_CURVE/SURFACE_WITH_KNOTS and
//! their rational complex forms, VERTEX_POINT / EDGE_CURVE / ORIENTED_EDGE /
//! EDGE_LOOP / FACE_(OUTER_)BOUND / ADVANCED_FACE / CLOSED_SHELL /
//! MANIFOLD_SOLID_BREP), reconstructs a `BrepSolid`, and validates it.
//!
//! The exporter drops pcurves and degenerate (pole) edges, so this module
//! rebuilds both: pcurves are DERIVED by projecting each 3D edge curve onto its
//! carrier surface (`build_pcurve_on_surface_range`), seam edges are placed on
//! opposite domain boundaries, and collapsed pole boundaries are re-synthesised
//! as degenerate edges so faces close their parameter domain and integrate to
//! the correct mass properties.
//!
//! Analytic-surface recognition on import (PLANE/CYLINDRICAL/…) is a documented
//! follow-up: the exporter emits only NURBS, so faithful NURBS round-trip is the
//! milestone. Unsupported entities produce a clear `Err`, never a panic.

use crate::topology::{
    BrepSolid, CoedgeRecord, EdgeRecord, FaceRecord, LoopRecord, ShellRecord, VertexRecord,
};
use crate::{
    build_pcurve_on_surface_range, make_arc, make_extrusion, make_line, make_plane,
    make_revolution, offset_surface, transform_brep, AffineTransform, NurbsCurve, NurbsSurface,
    Vec3, Vec4,
};
use rustc_hash::{FxHashMap as HashMap, FxHashSet as HashSet};
use std::collections::VecDeque;

const TAU: f64 = std::f64::consts::TAU;

mod parse;
mod bodies;
mod builder;
mod geometry;
#[cfg(test)]
mod tests;

use parse::*;
use bodies::*;
use builder::*;
use geometry::*;


// ---------------------------------------------------------------------------
// Topology assembly
// ---------------------------------------------------------------------------

/// Public entry: parse a STEP Part 21 document and return one `BrepSolid` per
/// MANIFOLD_SOLID_BREP, FACETED_BREP, or certified BREP_WITH_VOIDS. Every
/// returned solid passes `validate()`.
pub fn import_step(text: &str) -> Result<Vec<BrepSolid>, String> {
    let (solids, _failed, first_error) = collect_step_solids(text)?;
    if solids.is_empty() {
        return Err(first_error.unwrap_or_else(|| {
            "step_import: no MANIFOLD_SOLID_BREP/FACETED_BREP/BREP_WITH_VOIDS body imported (unsupported or invalid representation)"
                .into()
        }));
    }
    Ok(solids)
}

/// Like [`import_step`] but reports how many bodies failed and the first error,
/// so callers can distinguish a fully- from a partially-imported assembly.
pub fn import_step_report(text: &str) -> Result<(Vec<BrepSolid>, usize, Option<String>), String> {
    collect_step_solids(text)
}