B-rep Helper Functions

Centralize exports and reusable OBJ/STEP helpers in your truck_brep crate so shape files only worry about geometry.

src/lib.rs

Imports and module wiring

#![allow(unused)]
fn main() {
use std::{fs, io, path::Path};

use truck_meshalgo::prelude::*;
use truck_modeling::*;
use truck_stepio::out::{CompleteStepDisplay, StepModel};
use truck_topology::compress::{CompressedShell, CompressedSolid};
}
What this does Brings in filesystem/IO utilities plus the Truck modeling, meshing, STEP output, and compression helpers that the rest of the files use.

StepCompress trait

#![allow(unused)]
fn main() {
/// Helper to compress modeling shapes into STEP-compatible data.
pub trait StepCompress {
    type Compressed;
    fn compress_for_step(&self) -> Self::Compressed;
}
}
What this does Defines a small adapter trait so both `Shell` and `Solid` expose a common `compress_for_step` method, hiding their different compressed types.

StepCompress for Shell

#![allow(unused)]
fn main() {
impl StepCompress for Shell {
    type Compressed = CompressedShell<Point3, Curve, Surface>;
    fn compress_for_step(&self) -> Self::Compressed {
        self.compress()
    }
}
}
What this does Implements `StepCompress` for shells by delegating to the kernel’s built-in `compress`, returning the STEP-ready shell representation.

StepCompress for Solid

#![allow(unused)]
fn main() {
impl StepCompress for Solid {
    type Compressed = CompressedSolid<Point3, Curve, Surface>;
    fn compress_for_step(&self) -> Self::Compressed {
        self.compress()
    }
}
}
What this does Implements `StepCompress` for solids, again forwarding to `compress` so solids can be exported with the same helper API.

save_step helper

#![allow(unused)]
fn main() {
/// Export any B-rep (Solid or Shell) to STEP.
pub fn save_step<T, P>(brep: &T, path: P) -> io::Result<()>
where
    T: StepCompress,
    for<'a> StepModel<'a, Point3, Curve, Surface>: From<&'a T::Compressed>,
    P: AsRef<Path>,
{
    let path = path.as_ref();
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    let compressed = brep.compress_for_step();
    let display = CompleteStepDisplay::new(StepModel::from(&compressed), Default::default());
    fs::write(path, display.to_string())
}
}
What this does Creates parent folders if needed, compresses the shape, wraps it in a STEP display with defaults, and writes the STEP text to disk.

save_obj helper

#![allow(unused)]
fn main() {
/// Triangulate any B-rep (Solid or Shell) and write an OBJ mesh.
pub fn save_obj(shape: &impl MeshableShape, path: impl AsRef<Path>) -> io::Result<()> {
    let mesh = shape.triangulation(0.01).to_polygon();
    let path = path.as_ref();
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    let mut obj = fs::File::create(path)?;
    obj::write(&mesh, &mut obj).map_err(|err| io::Error::new(io::ErrorKind::Other, err))
}
}
What this does Tessellates the shape with a 0.01 chord tolerance, ensures the output folder exists, then writes the resulting polygon mesh as an OBJ file.

Target directory tree
truck_brep/
├─ Cargo.toml      # add truck-modeling, truck-meshalgo, truck-stepio deps
├─ src/
│  ├─ lib.rs       # helpers + re-exports
│  ├─ ...          # shape modules (add torus.rs, cylinder.rs, bottle.rs, etc.)
├─ examples/
│  └─ ...          # one small example per shape
└─ output/         # generated OBJ/STEP files (created at runtime)
Complete src/lib.rs
#![allow(unused)]
fn main() {
use std::{fs, io, path::Path};

use truck_meshalgo::prelude::*;
use truck_modeling::*;
use truck_stepio::out::{CompleteStepDisplay, StepModel};
use truck_topology::compress::{CompressedShell, CompressedSolid};

/// Helper to compress modeling shapes into STEP-compatible data.
pub trait StepCompress {
    type Compressed;
    fn compress_for_step(&self) -> Self::Compressed;
}

impl StepCompress for Shell {
    type Compressed = CompressedShell<Point3, Curve, Surface>;
    fn compress_for_step(&self) -> Self::Compressed { self.compress() }
}

impl StepCompress for Solid {
    type Compressed = CompressedSolid<Point3, Curve, Surface>;
    fn compress_for_step(&self) -> Self::Compressed { self.compress() }
}

/// Export any B-rep (Solid or Shell) to STEP.
pub fn save_step<T, P>(brep: &T, path: P) -> io::Result<()>
where
    T: StepCompress,
    for<'a> StepModel<'a, Point3, Curve, Surface>: From<&'a T::Compressed>,
    P: AsRef<Path>,
{
    let path = path.as_ref();
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    let compressed = brep.compress_for_step();
    let display = CompleteStepDisplay::new(
        StepModel::from(&compressed),
        Default::default(),
    );
    fs::write(path, display.to_string())
}

/// Triangulate any B-rep (Solid or Shell) and write an OBJ mesh.
pub fn save_obj(shape: &impl MeshableShape, path: impl AsRef<Path>) -> io::Result<()> {
    let mesh = shape.triangulation(0.01).to_polygon();
    let path = path.as_ref();
    if let Some(parent) = path.parent() {
        fs::create_dir_all(parent)?;
    }
    let mut obj = fs::File::create(path)?;
    obj::write(&mesh, &mut obj).map_err(|err| io::Error::new(io::ErrorKind::Other, err))
}
}