cadrum
Rust CAD library powered by statically linked, headless OpenCASCADE (OCCT 8.0.0-beta1).
Usage
| primitives | write read | transform | boolean |
|---|---|---|---|
| extrude | loft | sweep | shell |
| bspline | fillet | chamfer | |
More examples with source code are available at lzpel.github.io/cadrum.
Add this to your Cargo.toml:
[]
= "^0.7"
Build
cargo build automatically downloads a prebuilt OCCT 8.0.0-rc5 binary for the targets below.
| Target | Prebuilt | |
|---|---|---|
x86_64-unknown-linux-gnu |
✅ | |
aarch64-unknown-linux-gnu |
✅ | |
x86_64-pc-windows-msvc |
✅ | |
x86_64-pc-windows-gnu |
✅ |
For other targets, build OCCT from source:
OCCT_ROOT=/path/to/occt cargo build --features source-build
If OCCT_ROOT is not set, built binaries are cached under target/.
Requirements when building OpenCASCADE from source
- C++17 compiler (GCC, Clang, or MSVC)
- CMake
Examples
Primitives
Primitive solids: box, cylinder, sphere, cone, torus — colored and exported as STEP + SVG.
//! Primitive solids: box, cylinder, sphere, cone, torus — colored and exported as STEP + SVG.
use ;
Write read
Read and write: chain STEP, BRep text, and BRep binary round-trips with progressive rotation.
//! Read and write: chain STEP, BRep text, and BRep binary round-trips with progressive rotation.
use ;
use FRAC_PI_8;
Transform
Transform operations: translate, rotate, scale, and mirror applied to a cone.
//! Transform operations: translate, rotate, scale, and mirror applied to a cone.
use ;
use PI;
Boolean
Boolean operations: union, subtract, and intersect between a box and a cylinder.
//! Boolean operations: union, subtract, and intersect between a box and a cylinder.
use ;
Extrude
Demo of Solid::extrude: push a closed 2D profile along a direction vector.
//! Demo of `Solid::extrude`: push a closed 2D profile along a direction vector.
//!
//! - **Box**: square polygon extruded along Z
//! - **Oblique cylinder**: circle extruded at a steep angle
//! - **L-beam**: L-shaped polygon extruded along Z
//! - **Heart**: BSpline heart-shaped profile extruded along Z
use ;
/// Square polygon → box (simplest extrude).
/// Circle extruded at a steep angle → oblique cylinder.
/// L-shaped polygon → L-beam.
/// Heart-shaped BSpline profile extruded along Z.
Loft
Demo of Solid::loft: skin a smooth solid through cross-section wires.
//! Demo of `Solid::loft`: skin a smooth solid through cross-section wires.
//!
//! - **Frustum**: two circles of different radii → truncated cone (minimal loft)
//! - **Morph**: square polygon → circle (cross-section shape transition)
//! - **Tilted**: three non-parallel circular sections → twisted loft
use ;
/// Two circles → frustum (minimal loft example).
/// Square polygon → circle (2-section morph loft).
/// Three non-parallel circular sections → twisted loft.
Sweep
Sweep showcase: M2 screw (helix spine) + U-shaped pipe (line+arc+line spine)
//! Sweep showcase: M2 screw (helix spine) + U-shaped pipe (line+arc+line spine)
//! + twisted ribbon (`Auxiliary` aux-spine mode).
//!
//! `ProfileOrient` controls how the profile is oriented as it travels along the spine:
//!
//! - `Fixed`: profile is parallel-transported without rotating. Cross-sections
//! stay parallel to the starting orientation. Suited for straight extrusions;
//! on a curved spine the profile drifts off the tangent and the result breaks.
//! - `Torsion`: profile follows the spine's principal normal (raw Frenet–Serret
//! frame). Suited for constant-curvature/torsion curves like helices and for
//! 3D free curves where the natural twist should carry into the profile.
//! Fails near inflection points where the principal normal flips.
//! - `Up(axis)`: profile keeps `axis` as its binormal — at every point the
//! profile is rotated around the tangent so one in-plane axis stays in the
//! tangent–`axis` plane. Suited for roads/rails/pipes that must preserve a
//! gravity direction. On a helix, `Up(helix_axis)` is equivalent to `Torsion`.
//! Fails when the tangent becomes parallel to `axis`.
//! - `Auxiliary(aux_spine)`: profile's tracked axis points from the main spine
//! toward a parallel auxiliary spine. Arbitrary twist control — e.g. a
//! helical `aux_spine` on a straight `spine` produces a twisted ribbon.
use ;
// ==================== Component 1: M2 ISO screw ====================
// ==================== Component 2: U-shaped pipe ====================
// ==================== Component 3: Auxiliary-spine twisted ribbon ====================
// Sweeping a straight spine with `Auxiliary(&[helix])` rotates the tracked
// axis of the profile at each point to face the corresponding helix point.
// A pitch=h helix makes exactly one 360° turn over [0, h], so a flat
// rectangular profile becomes a ribbon twisted once. With `Fixed` or
// `Torsion` the profile wouldn't rotate along a straight spine — visible
// twist is therefore proof that Auxiliary is in effect.
// ==================== main: side-by-side layout ====================
//
// Each builder places its component at its final world position (screw at
// origin, U-pipe at x=6, ribbon at x=12) and applies its color, so main
// just concatenates them.
Shell
Demo of Solid::shell:
//! Demo of `Solid::shell`:
//! - Cube: remove top face, offset inward → open-top container
//! - Sealed cube: empty open_faces → solid with an internal void (outer skin
//! + reversed inner shell)
//! - Torus: bisect with a half-space to introduce planar cut faces, then
//! shell using those cut faces as the openings → thin-walled half-ring
//! with both cross-sections exposed
use ;
Bspline
use ;
use TAU;
// 2 field-period stellarator-like torus.
// `Solid::bspline` is fed a 2D control-point grid to build a periodic B-spline solid.
// Every variation below is invariant under phi → phi+π (or shifts by a multiple
// of 2π), so the resulting shape has 180° rotational symmetry around the Z axis:
// a(phi) = 1.8 + 0.6 * sin(2φ) radial semi-axis
// b(phi) = 1.0 + 0.4 * cos(2φ) Z semi-axis
// psi(phi) = 2 * phi cross-section twist (2 turns per loop)
// z_shift(phi) = 1.0 * sin(2φ) vertical undulation
const M: usize = 48; // toroidal (U) — must be even for 180° symmetry
const N: usize = 24; // poloidal (V) — arbitrary
const RING_R: f64 = 6.0;
Fillet
Demo of Solid::fillet_edges:
//! Demo of `Solid::fillet_edges`:
//! - All 12 cube edges filleted uniformly (rounded cube)
//! - Only top 4 edges filleted (soft top, sharp base)
//! - Cylinder top circular edge filleted (coin shape)
use ;
Chamfer
Demo of Solid::chamfer_edges — mirror of 10_fillet.rs using bevels:
//! Demo of `Solid::chamfer_edges` — mirror of `10_fillet.rs` using bevels:
//! - All 12 cube edges chamfered uniformly (beveled cube)
//! - Only top 4 edges chamfered (soft top, sharp base)
//! - Cylinder top circular edge chamfered (coin with beveled rim)
use ;
Features
color(default): Colored STEP I/O via XDE. Enableswrite_step_with_colors,read_step_with_colors, and per-face color onSolid.source-build: Download and build OCCT from upstream sources via CMake. Enable this on triples without a published prebuilt.
Showcase
A browser-based configurator that lets you tweak dimensions of a STEP model and get an instant 3D preview and quote. cadrum powers the parametric reshaping and meshing on the backend.
Release Notes
0.7.5
Aggregated changes since 0.7.2 (no separate entries were written for 0.7.3 / 0.7.4).
- OCCT bumped to 8.0.0-beta1 ahead of the May 7 final release. Inherits upstream perf gains (STEP read up to ~75% faster vs 7.7) and the Shape-Healing /
BRepFill_PipeShellcrash fixes. - Linux prebuilts are now self-contained (#147):
libstdc++.a/libgcc.a/libgcc_eh.aare bundled into the tarball, so binaries linked against the prebuilt no longer depend on the host distro's libstdc++ runtime — fixes link-time__cxa_call_terminateundefined errors on Amazon Linux 2023 and other distros with older default GCC. Same self-contained guarantee that mingw already had since 0.7.2 (#89). x86_64-pc-windows-gnullvmprebuilt dropped. The prior "support" was a relabeledwindows-gnuartifact, not a real llvm-mingw build. Use--features source-buildor switch to thewindows-gnutoolchain.- I/O methods relocated to
Solidimpl (#145):Solid::write_step / write_brep_binary / write_brep_text / read_step / read_brep. The free-standingcadrum::write_*re-exports are gone. Breaking vs 0.7.4:cadrum::write_step(...)→Solid::write_step(...), etc. Edge::id()/Face::id()/Solid::id()(#142, #143): TShape-pointer-based identity exposed as a stableu64for cross-shape correspondence (e.g. before/after boolean ops). Replaces the underscoredtshape_id. Breaking for callers that named the old method.Face::iter_edge() -> impl Iterator<Item = &Edge>(#143): face-edge incidence query without going through the Solid boundary explorer.Face::project(point)(#142): closest-point + normal query on a face viaBRepExtrema_DistShapeShape. Sibling to the existingEdge::project/Wire::project.- C¹-periodic B-spline seam fix (#120):
Solid::bspline(_, periodic=true)no longer emits a discontinuous U=0 seam — surfaces that previously showed dents at the seam now interpolate smoothly. Regression test intests/bspline.rs.
0.7.2
Aggregated changes since 0.6.0 (no separate entries were written for 0.6.1 – 0.7.1).
Solid::shell(thickness, open_faces)— hollow a solid viaBRepOffsetAPI_MakeThickSolid. Emptyopen_facesproduces a sealed internal void (cavity). Example:examples/08_shell.rs.Solid::fillet_edges(radius, edges)/Solid::chamfer_edges(distance, edges)— uniform fillet / chamfer on selected edges viaBRepFilletAPI_MakeFillet/MakeChamfer.Solid::area()/Solid::center()/Solid::inertia()— surface area, center of mass, inertia tensor. Replaces the previousshell_countquery.Wire::project(point)— closest-point + tangent query onEdge/Vec<Edge>/[Edge; N]viaGeomAPI_ProjectPointOnCurve.Edge::end_point()/Edge::end_tangent()— added as siblings to the existingstart_*accessors.Solid::iter_edge()/Solid::iter_face()— yield&Edge/&Facereferences through internalOnceLockcaches; first call populates, subsequent calls are free.Solid::history+Solid::iter_history()— face-derivation pairs[post_id, src_id]populated by boolean ops andclean(). Lets callers select result faces by their original input membership.- Multi-color STEP read recovery (#129). SolveSpace-style multi-color STEP files (which duplicate
EDGE_CURVEentities at face boundaries instead of sharing them) used to land asCompound{Shell×N}with zero solids, breaking every downstream op. ABRepBuilderAPI_Sewingpost-process now stitches coincident edges, promotes the result to one validSolid, and remaps the colormap. The same STEP file is currently unfixable in CadQuery — seesandbox-cadquery/read_step_fillet.py. Mesh::write_svg/Mesh::to_svggainedup_dir: DVec3betweenview: DVec3andhidden_lines: bool(#127). Breaking vs 0.7.0: passDVec3::Zto reproduce earlier output.Transformtrait no longer in the public prelude (#91) — its methods reach you viaCompound/Wireforwarders, souse cadrum::{Compound, Wire};is enough for every transform call. Breaking vs 0.7.0 for code that importedTransformexplicitly.*_with_metadataboolean variants removed (#130) — the same information is now available viaSolid::iter_history()on the result solid. Breaking for callers that consumed the metadata tuple.- glam types re-exported from the crate root (#94, #95) — downstream code no longer needs its own
glamdependency forDVec3etc. - OCCT
Statistics on Transferstdout chatter silenced on every STEP read / write (#97). - mingw prebuilt is now self-contained (#89): bundles the container's
libstdc++.a/libgcc.a, so user-builtx86_64-pc-windows-gnuexecutables do not depend on MinGW runtime DLLs at link time. - docs.rs build restored (#107, #111): dropped the unsupported
x86_64-pc-windows-msvctarget and reorderedbuild.rsso trait delegation generation runs before the DOCS_RS early-return. - New example
08_shell.rs(hollow torus carved by halfspace-cut openings); old08_bspline.rsrenumbered to09_bspline.rs. Top README image updated to the alphastell stellarator render (#125).
0.6.0
source-buildfeature now gatescmake/walkdiras optional build-dependencies. Defaultcargo buildno longer compiles them, significantly reducing build time on prebuilt targets. Users on unsupported targets must enable--features source-build(behavior unchanged — previously these targets also failed, just with a download error instead of a clear message).x86_64-pc-windows-gnuprebuilt added via Docker cross-compilation with Debian mingw-w64 (posix thread model). All MinGW runtime DLLs are statically absorbed — the resulting exe depends only on Windows OS DLLs.- LGPL 2.1 §2 compliance: source builds now retain only the ~9 patched OCCT source files alongside the
.alibraries, removing the unmodified bulk (~88 MB of data/dox/tests). The patched files carry timestamped headers per §2(a). OCCT_ROOTrelative path handling fixed: resolved viaenv::current_dir()instead of the unreliableCARGO_TARGET_DIRheuristic.--target <triple>flag now works correctly.build.rsrestructured:resolve_occtuses match chains with#[cfg]for source-build vs prebuilt paths. Source-build code lives in#[cfg(feature = "source-build")] mod source.patch_occt_sourcessplit intowalk_occt_sources+patch_or_none(side-effect-free).- README simplified: Build section moved after Usage with a prebuilt target table + OS icons.
0.5.1
0.4.5 was published briefly but its version number was lower than the already-published 0.5.0 (OCCT 7.9.3, older feature set), so
cargo add cadrumwould silently pick up 0.5.0 instead of the newer 0.4.5 code. Re-released as 0.5.1 with identical contents. Prefer 0.5.1 over 0.4.5.
Solid::bspline<const M, const N>(grid, periodic)— new constructor: build a periodic B-spline solid from a 2D control-point grid. V (cross-section) is always periodic; U (longitudinal) is controlled by theperiodicflag (torus whentrue, capped pipe whenfalse). Implemented viaGeomAPI_PointsToBSplineSurface::Interpolateover an augmented grid plusSetUPeriodic/SetVPeriodic.write_svg/Mesh::to_svgnow takeshading: bool— opt-in Lambertian shading with head-on light. Whentrue, triangles are tinted by0.5 + 0.5 * (normal · dir)so curved/organic shapes read clearly;falsereproduces the pre-0.5.1 flat rendering. Breaking vs 0.5.0: existing callers must add the flag (passfalseto preserve earlier output).examples/08_bspline.rsrewritten: 2 field-period stellarator-like torus with twisted + vertically undulating elliptic cross-sections, exercisingSolid::bsplineandshading=true.tests/bspline.rsadded: verifies 180° point symmetry of the stellarator shape via XZ/YZ half-space intersection (s1 ≈ s3, s2 ≈ s4).Error::BsplineFailed(String)new variant. Breaking for downstream code that does exhaustivematchonError.- OCCT 8.0.0 deprecation warnings resolved in
make_bspline_edgeandmake_bspline_solid(NCollection_HArray1<gp_Pnt>via localusingalias to bypass theHandle()macro comma-splitting issue;NCollection_Array2<gp_Pnt>directly).
License
This project is licensed under the MIT License.
Compiled binaries include OpenCASCADE Technology (OCCT), which is licensed under the LGPL 2.1. Users who distribute applications built with cadrum must comply with the LGPL 2.1 terms. Since cadrum builds OCCT from source, end users can rebuild and relink OCCT to satisfy this requirement.