Skip to main content

Module build

Module build 

Source
Expand description

StepBuilder — the convenience authoring layer over the strict Ap242Author constructors.

new lays down the skeleton every exporter needs (application protocol, product contexts, units — new_with to choose them); finish assembles everything added so far and returns the Part 21 text.

The core is parts and their shape. part adds one product with its full definition chain (part_with also sets part number / version / descriptions). Topology mirrors the kernel’s own — vertexedgefacesolid, with analytic surfaces and curves as plain inputs (SurfaceInput, CurveInput, ProfileInput). Assemblies are one place(parent, child, at) call per placed instance, the child’s definition shared between them.

Everything else is one call each. mesh attaches a display mesh (vertex array + index triangles), optionally linked to the b-rep solid it renders. style colours a solid or a single face, with optional transparency; layer, hide, and hide_layer manage presentation layers and default visibility. contributor, approve, document, and security attach PLM records to a part’s version, with people as shared person_and_org handles. header fills the Part 21 file header.

Anything the builder does not cover is still reachable: author hands out the underlying Ap242Author, and ids cross freely between the two levels.

The minimal flow — a planar part handed over from a kernel:

use step_io::build::{CurveInput, FaceBoundInput, Frame, SurfaceInput};

let mut b = step_io::StepBuilder::new().unwrap();
let plate = b.part("plate").unwrap();

let vs: Vec<_> = kernel.points.iter()
    .map(|p| b.vertex(*p).unwrap())
    .collect();
let es: Vec<_> = kernel.edges.iter()
    .map(|e| b.edge(vs[e.start], vs[e.end], CurveInput::Line).unwrap())
    .collect();
let fs: Vec<_> = kernel.faces.iter()
    .map(|f| {
        let plane = Frame { origin: f.origin, axis: f.normal, ref_dir: f.x_dir };
        let bound = f.bound.iter().map(|&i| (es[i], true)).collect();
        b.face(SurfaceInput::Plane(plane), true, vec![FaceBoundInput::outer(bound)])
            .unwrap()
    })
    .collect();
b.solid(plate, "plate body", fs).unwrap();

std::fs::write("plate.step", b.finish().unwrap()).unwrap();

The full tour — assembly, display mesh, presentation, metadata, header:

use step_io::build::{
    ApprovalInput, Frame, HeaderInput, MeshInput, MeshNormalsInput, PersonOrg,
    Rgb, StyleTarget,
};

let mut b = step_io::StepBuilder::new().unwrap();
b.header(&HeaderInput {
    file_name: Some("car.step".into()),
    organizations: vec!["ACME".into()],
    originating_system: Some("MyKernel 2.1".into()),
    ..Default::default() // timestamp auto-stamped
});

let car = b.part("car").unwrap();
let wheel = b.part("wheel").unwrap();
let wheel_faces = faces(&mut b); // b-rep translated as in the minimal flow
let body = b.solid(wheel, "wheel body", wheel_faces).unwrap();

// One placed instance per call; the wheel's definition is shared.
let z = [0.0, 0.0, 1.0];
let x = [1.0, 0.0, 0.0];
b.place(car, wheel, Frame { origin: [900.0, 700.0, 300.0], axis: z, ref_dir: x }).unwrap();
b.place(car, wheel, Frame { origin: [900.0, -700.0, 300.0], axis: z, ref_dir: x }).unwrap();

// Display mesh (the kernel's tessellation) linked to the b-rep it renders.
b.mesh(wheel, "wheel mesh", &MeshInput {
    points: kernel.mesh_points,
    triangles: kernel.mesh_triangles,
    normals: MeshNormalsInput::None,
}, Some(body.into())).unwrap();

// Presentation: colour/transparency, layers, default visibility.
b.style(StyleTarget::Solid(body), Rgb { red: 0.8, green: 0.2, blue: 0.1 }, None).unwrap();
let hidden = b.layer("REFERENCE", vec![StyleTarget::Solid(body)]).unwrap();
b.hide_layer(hidden);

// PLM metadata on the part's version.
let john = b.person_and_org(&PersonOrg {
    person_id: "p1".into(),
    first_name: Some("John".into()),
    last_name: Some("Doe".into()),
    organization: "ACME".into(),
}).unwrap();
b.contributor(wheel, "creator", john).unwrap();
b.approve(wheel, &ApprovalInput {
    status: "approved".into(),
    level: "final".into(),
    approvers: vec![(john, "approver".into())],
    date: None,
}).unwrap();

let text = b.finish().unwrap();

Re-exports§

pub use crate::scene::NurbsCurve;
pub use crate::scene::NurbsSurface;
pub use crate::scene::Rgb;

Structs§

ApprovalInput
One approval for StepBuilder::approve: a status word (customarily "approved"), a level, any number of approvers with their roles, and an optional approval date.
DateTimeInput
A calendar date with wall-clock time (no time zone — emitted as UTC).
DocumentInput
An external document reference for StepBuilder::document.
FaceBoundInput
One face bound for StepBuilder::face: the loop’s edges with their per-edge direction, whether this is the outer bound, and the bound’s own orientation flag.
Frame
A right-handed placement frame: origin plus the axis (local Z) and ref_dir (local X) directions — the builder’s input for AXIS2_PLACEMENT_3D. Directions are passed through as given (kernels supply unit vectors); geometric well-formedness is the caller’s responsibility.
HeaderInput
Part 21 HEADER fields for StepBuilder::header. Everything defaults to empty except the pieces the builder supplies itself: the timestamp (current UTC time unless overridden) and the preprocessor stamp (always step-io <version>).
MeshInput
A display mesh for StepBuilder::mesh: a vertex array plus 0-based index triangles — the plain form kernels and renderers already hold.
Part
Handle for a part created by StepBuilder::part — an index into the builder that created it. Passing it to a different builder panics (out of range) or silently targets the wrong part (in range).
PartOptions
Optional overrides for StepBuilder::part_with — every field defaults to the plain part behaviour.
PersonOrg
A person at an organization, for StepBuilder::person_and_org.
StepBuilder
Ergonomic writer for the standard AP242 file shape: shared contexts and units up front, one product chain per part, everything bound and emitted by finish.
UnitsInput
Unit setup for StepBuilder::new_with; the default is what plain new uses (millimetre, 1e-7 uncertainty).
Vertex
Handle for a vertex created by StepBuilder::vertex — an index into the builder that created it (a different builder’s handle panics or targets the wrong vertex). The builder keeps the vertex position so straight edges can derive their line geometry.

Enums§

CurveInput
Curve input for StepBuilder::edge. NurbsCurve mirrors the read-side to_nurbs() type; see SurfaceInput for the rational/non-rational split.
LengthUnit
The file’s length unit, chosen at StepBuilder::new_with time (a unit context is a file-global entity every shape references).
MeshNormalsInput
Normals for a MeshInput, mirroring what the read side exposes: none, one for the whole mesh, or one per vertex (row count must match the point count — a mismatch is the caller’s responsibility).
ProfileInput
A profile curve for the swept surfaces — plain geometry, no vertices (unlike CurveInput::Line, which derives from edge vertices).
SolidRef
Which solid a display mesh tessellates (StepBuilder::mesh): a plain solid or one with voids (solid_with_voids). The id types convert with Into, so Some(body.into()) works for either.
StyleTarget
What a StepBuilder::style call colours: a whole solid (with or without voids) or one face — the targets the read-side Scene resolves styles for.
SurfaceInput
Surface input for StepBuilder::face: the stored analytic forms, plus NURBS for everything else — NurbsSurface is the same type Surface::to_nurbs() returns on the read side, so read-side output can be fed straight back in. Non-rational data (all weights 1.0) becomes a plain B_SPLINE_SURFACE_WITH_KNOTS; rational data becomes the customary multi-part complex instance.
VoidShellNormals
Which way the face normals of the void shells passed to StepBuilder::solid_with_voids point. The caller declares this so step-io can orient each cavity’s ORIENTED_CLOSED_SHELL correctly without evaluating geometry. See that method for how to choose.