Skip to content

Latest commit

 

History

2,734 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Remus

Exact B-Rep solid modeling kernel for Rust and WebAssembly.

CI Commit activity License: Apache-2.0 Rust 1.88+ unsafe denied

Kernel contract · Architecture · Performance · Getting started · Known limitations · Contributing

One exact-geometry engine, from Rust and from JavaScript. Cut a solid, measure it, export it.

use remus::prelude::*;

# fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut model = Model::new();

// Primitives are anchored at the origin, so this cylinder rounds off the
// block's corner. Transform it first to place the cut elsewhere.
let block = model.make_box(30.0, 20.0, 10.0)?;
let cutter = model.make_cylinder(5.0, 15.0)?;
let notched = model.cut(block, cutter)?;

// Every policy-aware boolean discloses whether its result stayed exact.
assert_eq!(notched.quality, BooleanQuality::Exact);
let volume = model.volume(notched.solid, 0.1)?;
let step = model.write_step(&[notched.solid])?;

assert!(volume > 0.0);
assert!(step.starts_with("ISO-10303-21;"));
# Ok(())
# }
import { BrepKernel } from 'remus-wasm';
import { RemusIo } from 'remus-wasm-io';

const kernel = new BrepKernel();

// Primitives are anchored at the origin, so this cylinder rounds off the
// block's corner. Use `transformSolid` to place it somewhere else.
const block = kernel.makeBox(30, 20, 10);
const cutter = kernel.makeCylinder(5, 15);
const cut = kernel.cutDetailed(block, cutter);
if (cut.status === 'error') {
  throw new Error(`${cut.code}: ${cut.details.message}`);
}
const notched = cut.value;
const vol = kernel.volume(notched, 0.1);

// File formats live in a separate translator module, loaded only around
// import and export. Bodies cross between the two as exact arena documents.
const io = new RemusIo();
const step = io.exportStep(kernel.serializeSolids(Uint32Array.of(notched))); // Uint8Array

Why a CAD kernel?

Remus is a B-Rep solid modeling kernel written from scratch in Rust. It targets WebAssembly, so the same kernel runs in the browser and on the desktop. unsafe is denied by lint, as are unwrap and panic. Every public operation returns a Result.

Parametric CAD in the browser has long meant choosing between proprietary kernels and large C++ codebases compiled to WASM. Remus exists to be the third option: a from-scratch Rust kernel with exact geometry and a permanent Apache-2.0 license. It is maintained by Esau Engineering as the Apache-2.0 continuation of an upstream kernel that relicensed at v3 — see Provenance for how that boundary is enforced.

The geometry is exact. Booleans run on analytic and NURBS surfaces and keep those surfaces through the operation, so a cylinder stays a cylinder instead of becoming a bag of triangles. That keeps face counts low and round-trips lossless.

Remus's canonical modeling convention is millimetres for length and radians for angle. The kernel does not attach units to scalar values or silently convert them; applications using another length unit must scale all coordinates, dimensions, deflections, and linear tolerances consistently at their boundary. See the tolerance and robustness guide.

Kernel contract

Remus is being driven from a broad-but-maturing kernel toward a professional-grade one, and the rules for that are written down rather than implied. This is the part of the repository worth reading before you trust a feature label.

  • Kernel maturity target — what "professional-grade" means here, the program invariants, and the program-wide definition of done.
  • Capability matrix — the qualification structure. Every cell of every operation family is Qualified, Partial, Unqualified, Unsupported-typed, or Unsupported-untyped. It is the promotion authority for the feature labels in Status: no feature is promoted on a single successful fixture.
  • Operation contract — the result, quality, fallback, and postcondition contract every operation converges on.
  • Failure taxonomy — stable failure categories, and how they map onto the error-code registry.
  • Testing strategy — what kind of evidence qualifies a capability cell, and what CI gates.
  • Stability matrix — the audited disposition of each label shipping today, including the rows whose advertised domain is not yet fully evidenced.
  • Stabilization plan — the working plan for promoting every Beta/Experimental row below to Stable, sequenced under the capability-matrix promotion rules.
  • Unified roadmap — the live work queue across the correctness program (P-Class) and the adoption program (Open Kernel), each with a status ledger updated in the PR that changes it.
  • Industrial parity overlay — where each capability stands against the incumbent open-source reference kernel, on a competitive axis kept separate from the contract states above; it changes no label here.

Four mechanisms carry that contract in code:

Mechanism Where What it gives you
Operation context remus_math::context::OperationContext (RFC 0001) Tolerances, hard work budgets, fallback policy, and cooperative cancellation as explicit caller-visible policy. Defaults reproduce prior behavior exactly; cancellation is typed and transactional.
Structured diagnostics remus_math::diagnostic Every failure carries a stable category plus a stable code, independent of the Rust error type. Codes are explicit literals, never derived from type or variant names, and the registry is additive only.
Coedges and per-use p-curves remus_topology (RFC 0002) First-class edge uses, so seams, poles, and periodic surfaces are represented correctly. Seam p-curve access is fail-closed rather than silently picking one side.
Reproduction bundles remus_wasm::repro Versioned JSON that replays an operation sequence and its expected results through the batch dispatch path — identically on native and WASM. Bundles are the canonical carrier for new regressions; expected failures are first-class.

Structural work lands through versioned RFCs in docs/design and incremental vertical slices, not repository-wide rewrites. Tests are not weakened, tolerances are not widened, and a mesh fallback is not introduced to make a failing case pass.

Status

Remus is in active development. Core modeling is solid. Each feature below carries the label the stability matrix assigns it (stable, beta, experimental, or partial, with any declared domain in parentheses), and that matrix records what evidence each label currently rests on. Known Limitations covers the gaps.

Category Feature Status
Primitives Box, cylinder, cone, sphere, torus, ellipsoid Stable
Primitives Convex hull, Minkowski sum (convex inputs) Stable
Booleans Union, cut, intersect on plane, cylinder, cone, sphere, NURBS Stable
Booleans Batch fuse-all (disjoint-aware union) Stable
Booleans Torus booleans (box ± torus, coaxial torus) Beta
Booleans Cellular and Compound operands (severing planar cuts, disjoint fuses) Experimental
Modifiers Validated planar fillet/chamfer and axisymmetric closed-rim fillet; other curved blend geometry (experimental assembly) Stable / Experimental
Modifiers Fillet overflow: transactional stop-at-cliff refusal (rollover unqualified) Stable
Modifiers Variable-radius, curved-support, and N-way vertex blends Experimental
Modifiers Face-face blend sheets and hold lines Experimental
Modifiers Resize or remove an analytic blend band (resize_blend) Experimental
Modifiers Push/pull and move face (analytic cylinder caps, holed planar boss supports) Stable (declared domain)
Modifiers Replace surface (plane, coaxial bore cylinder) Experimental
Modifiers Shell (hollow solid) Stable
Modifiers Offset face, offset solid, thicken, mirror, pattern Stable
Modifiers Draft (planar faces) Stable
Sweeps Extrude (planar + NURBS profiles) Stable
Sweeps Revolve, sweep, loft, pipe (planar profiles) Stable
Sweeps Helical sweep Stable
Sweeps Non-planar profiles for loft, sweep, pipe, revolve Stable
Sweeps First-class wire bodies as sweep profiles Experimental
Construction Coons-patch face fill, sew, untrim Stable
Sectioning Cross-section faces, split by plane Stable
Sectioning Sheet split/trim and planar solid imprint Experimental
Measurement Bounding box, area, volume, center of mass, inertia tensor + principal axes Stable
Measurement Point-to-solid, solid-to-solid distance, point classification Stable
Measurement Sheet area, bounds, and centroid; wire length Experimental
Drawing Hidden-line edge projection Stable
Geometry NURBS evaluation, derivatives, knot ops, fitting, projection Stable
Geometry Analytic intersections (plane × cylinder, cone, sphere exact; torus sampled) Stable
Geometry Surface-surface intersection (analytic + marching) Stable
Geometry Curve-curve intersection (Bezier clipping) Stable
Tessellation Adaptive deflection, CDT, analytic-surface optimization Stable
Tessellation Open sheet bodies Experimental
Repair Shape healing (wire, face, shell fixes), sewing, validation Stable
I/O STEP import/export (analytic-preserving round-trip) Stable
I/O STL, 3MF, OBJ, PLY, glTF (.glb) import/export Stable
I/O IGES import/export Experimental
I/O Sheet and wire bodies in arena documents; STEP sheet models Experimental
Sketching 2D constraint solver (DogLeg) Stable
Feature Recognition Holes, pockets, chamfers, fillets Stable
Assemblies Hierarchy, transforms, bill of materials Stable
Evolution Face provenance (booleans, blends, direct moves, offset, patterns, draft, defeature, split, shell) Stable (declared coverage)
Defeaturing Remove planar faces Stable
Defeaturing Curved rim-band removal Partial
Rendering Offscreen wgpu render to image plus face-id buffer (remus-render) Experimental

Known Limitations

A few areas are still maturing. Worth knowing before you build on them:

  • Boolean fallback. Most booleans run on an exact path that preserves analytic and NURBS surfaces. Hard configurations may use a bounded mesh-based fallback, which tessellates curved faces. If its input/work budgets are exceeded or the welded result is open, non-manifold, or invalid, the operation returns an error instead of a partial solid. Bounded off-axis cone-sphere, sphere-cylinder, and torus-sphere configurations are now exact for fuse, cut, and intersect across three scales and rigid placement, but general quartic seam arrangements are not. Exact tangency and sliver crossings are the two contact configurations that still fall over to that path rather than being answered analytically.
  • Walking fillet/chamfer and offset. The v2 modifier APIs validate completed topology and reject partial results. Unsupported/no-op trimming and offsetting a solid that already contains cavity shells return explicit errors; they do not silently drop faces or cavities. Radii the rolling ball cannot fit are refused as typed errors naming the edge and the limit, not delivered as a partial result. Constant-radius closed rims on cylinder/cone, cylinder/sphere, and cone/cone supports assemble; the cross-drilled cylinder/cylinder rim refuses rather than adding material on the wrong side, and correct-side assembly there is still unqualified.
  • Torus booleans. Box-with-torus, coaxial-torus, plane-through-centre, and coaxial-cylinder cases give correct volumes; coaxial torus×cylinder / axis-centred torus×sphere sections are exact circles; a box notch partitions the torus into winding-correct annuli; and a bounded off-axis torus×sphere matrix is exact for fuse, cut, and intersect across three scales and two placements. Broader quartic torus pairs and tangent contacts are unqualified and resolve through the bounded mesh fallback, an oversized torus×sphere witness refuses on its march budget, and general torus-to-torus intersections have known gaps.
  • Non-planar profiles. Loft, sweep, and pipe close non-planar section boundaries with bilinear (4-sided) or Coons (5-or-more-sided) caps whose boundary iso-curves are exactly the ring chords. Sweep and pipe also preserve disjoint rectangular iso-parametric holes on bilinear and Coons caps as single trimmed faces (B12 annular-Coons cell); off-surface, curved, touching/overlapping, and multi-span-straddling hole trims refuse typed. Loft profiles with holes now refuse instead of discarding their inner wires. Revolve accepts non-planar profile surfaces; a full revolution takes any boundary, and a partial revolution closes non-planar polygonal boundaries with the same caps (curved-edge non-planar boundaries and holes stay typed refusals). Only the miter-corner sweep variant still requires planar profiles (its bisector-plane joint faces would otherwise be non-planar).
  • Evolution coverage. Face provenance is exact and construction-derived for booleans, the walking and planar blend builders, qualified direct face moves, the default offset builder, patterns, draft, defeature, plane split, and shell. Arc-joint and self-intersection-removal offsets and direct edits outside the qualified cells still journal as explicit barriers, and edge/vertex provenance beyond the boolean path is roadmap work.
  • Sheet and wire bodies. Standalone sheets and wires are first-class bodies (RFC 0005) with declared bounds: a validated closed planar wire sweeps to a solid, planar sheets split and trim solids and each other, and trimmed NURBS sheets measure and tessellate. Open or non-planar wire profiles and configurations outside those cells refuse with typed errors.
  • IGES is experimental. Export writes planar and NURBS surfaces but skips analytic surfaces and approximates circular and elliptical edges as polylines. Import reconstructs planar placeholder faces only. Use STEP for B-Rep exchange.
  • Declared domains. Feature recognition claims only its declared feature set (holes, rectangular pockets, chamfers, curved fillet bands) — outside it, absence of a claim is the contract. Defeaturing removes features whose wound lies on planar kept faces (the removed feature itself may be curved); draft targets planar faces. Each refuses outside its domain by name.

The versioned WASM fillet/chamfer provenance payload and its strict decoder are documented in WASM face evolution.

Scope

Remus deliberately does not:

  • Bundle a viewport into the kernel. The core emits exact geometry and tessellated meshes; camera, lighting, and shading belong to the caller (Three.js and the like). The optional remus-render crate provides offscreen wgpu rendering with a face-id buffer, for tests and headless verification, and is not required by any core operation.
  • Plan toolpaths or slice. Export STEP, STL, or 3MF and pass the output to a CAM tool or slicer.
  • Model with meshes. The kernel operates on exact B-Rep geometry. Subdivision surfaces, polygon meshes, and voxels are out of scope.
  • Provide a GUI. Remus is a library. Building a UI around it is the application's job.
  • Simulate physics. Measurement (volume, area, center of mass) is included. Stress analysis, collision detection, and dynamics are not.

Architecture

Layered Cargo workspace. Each crate depends only on the same or lower layers, and CI enforces the boundaries with scripts/check-boundaries.sh.

Layer Crate What it does
L0 remus-math Points, vectors, matrices, NURBS curves and surfaces, geometric predicates, CDT, convex hull, operation context, diagnostics
L1 remus-geometry Curve sampling (uniform, deflection, arc-length, curvature), extrema, analytic-to-NURBS conversion
L1 remus-topology Arena-allocated B-Rep: vertex, edge, coedge, loop, wire, face, shell, solid, with an edge-to-face adjacency index
L2 remus-algo General Fuse boolean engine: pave filler, face classification, solid assembly
L2 remus-blend Walking-based fillet and chamfer with constant, variable, and custom radius laws
L2 remus-heal Shape healing: analysis, fixing, upgrading, sewing, tolerance management, configurable pipeline
L2 remus-check Point classification, validation, properties (volume, area, center of mass), distance
L2 remus-offset Solid offset and thickening via global face-face intersection
L2 remus-sketch 2D parametric constraint solver (GCS) using a DogLeg trust-region method
L3 remus-operations Booleans, fillet, chamfer, extrude, revolve, sweep, loft, shell, offset, measure, tessellation
L3 remus-io Import and export: STEP, IGES, STL, 3MF, OBJ, PLY, glTF
L4 remus-wasm JavaScript API via wasm-bindgen, with batch execution, checkpoint/restore, and reproduction bundles
L4 remus-wasm-io JavaScript file-format translators as a separate module; bodies cross to and from the kernel as exact arena documents
L4 remus-render Offscreen wgpu rendering to a color image plus a face-id buffer. Optional, nothing depends on it
L5 remus Native Rust facade: owned model session, explicit operation policy, curated modeling and I/O API

The layer DAG is a program invariant: preserving it is a constraint on every change, and a violation fails both the pre-push hook and CI.

Performance

Median times from the brepjs benchmark suite (5 iterations, Node.js, Linux x86_64). WASM is single-threaded. Native benchmarks use criterion.

Operation Remus (WASM) OCCT (WASM) Speedup Remus (native)
fuse(box, box) (×10) 0.5 ms 43.7 ms 87x 122 µs
cut(box, cylinder) (×10) 28.3 ms 64.3 ms 2.3x 9.3 ms
box + chamfer 0.2 ms 5.4 ms 27x 46 µs
box + fillet 0.3 ms 6.2 ms 21x 127 µs
multi-boolean (16 holes) 4.7 ms 30.1 ms 6.4x 2.8 ms
mesh sphere (tol=0.01) 7.1 ms 51.9 ms 7.3x 6.0 ms
exportSTEP (×10) 0.9 ms 14.3 ms 16x n/a

Every quoted row is output-verified across both kernels before timing is compared: fuse, chamfer, and sphere volumes match exactly; cut, fillet, and multi-boolean volumes agree within 0.004%. The sphere mesh densities are comparable at equal tolerance (9,800 triangles vs 10,176). The intersect(box, sphere) row is excluded: the kernel currently keeps the wrong sphere region for that configuration (an open, pinned defect), so its ~200x timing would not be a like-for-like comparison.

Booleans preserve analytic surfaces, so face counts stay low across chained operations. A nine-step compound boolean settles at 72 faces while a mesh-based approach would reach roughly 7,000. The same holds for blends: a straight edge filleted between two planar faces keeps an exact cylindrical wall rather than a NURBS approximation of one.

The OCCT comparison uses occt-wasm, an OpenCASCADE build compiled to WebAssembly. Both kernels ran single-threaded in Node.js. Boolean and exportSTEP rows were timed as batches of ten operations. WASM figures are medians of kernel-comparison.bench.test.ts (5 iterations) against a local cargo xtask wasm-build package, hash-verified at the require path. Native figures came from cargo bench -p remus-operations --bench cad_operations, except the mesh-sphere row, which used crates/operations/examples/perf_probe.rs at matching parameters. Measured 2026-08-06, before the Apache-only line was established; the upstream head-to-head harness is retired, so treat these figures as historical and do not quote them as current. Run scripts/bench-compare.sh for the maintained native Criterion baselines.

Data Exchange

Format Type Import Export
STEP B-Rep ✓ ✓
STL Mesh ✓ ✓
3MF Mesh ✓ ✓
OBJ Mesh ✓ ✓
PLY Mesh ✓ ✓
glTF (.glb) Mesh ✓ ✓
IGES B-Rep preview lossy

STEP preserves exact geometry on round-trip. Analytic surfaces (plane, cylinder, cone, sphere, torus) are written as native STEP surface entities rather than tessellated, and they read back to the same surface types. NURBS surfaces are preserved too, as are line, circle, ellipse, and NURBS edges.

Mesh formats export tessellated triangles. glTF is binary .glb, with no materials or scene graph. IGES is experimental, as described in Known Limitations.

In the browser, every format lives in the remus-wasm-io translator module rather than the kernel package, so applications that never touch files do not pay for the readers and writers. The kernel serialises bodies to exact arena documents (serializeSolids) and the translator consumes those; imports flow back through deserializeSolids.

All Rust importer entry points apply production defaults through ImportLimits: 256 MiB encoded input, 256 MiB for the uncompressed 3MF model XML entry, and 3,000,000 format-specific model entities. Use each format's *_with_limits reader to choose stricter or application-specific budgets; the WASM importers accept optional maxInputBytes / maxEntities arguments for the same purpose. Limit violations return IoError::LimitExceeded before avoidable large allocations. The WASM batch API separately limits JSON to 16 MiB and 10,000 operations.

Getting Started

Packages

Remus publishes nothing yet. No crates.io releases, no npm packages, no GitHub releases. Release ownership — named maintainers, package identity, vulnerability intake, signing and provenance, rollback and yank authority — has to be established first; the gate is documented in fork maintenance and release policy.

Two consequences worth stating plainly:

  • A remus-wasm package on npm does not come from this repository. It belongs to the historical upstream line, which is no longer permissively licensed. Installing it does not get you this kernel.
  • The checked-in crates/wasm/pkg (kernel) and crates/wasm-io/pkg (file-format translators) directories are frozen compatibility snapshots for an existing consumer that installs them by git path, pinned to one commit. They are not a release channel and not the way to adopt Remus.

Until packages exist, build from source.

As a Rust dependency

[dependencies]
remus = { git = "https://github.com/esaueng/remus" }

Pin a revision (rev = "...") for anything you intend to reproduce: no first-party package has been published yet, and main moves.

The Remus versioning policy defines the YYYY.RELEASE.PATCH numbers in source manifests and future releases. A version in this repository does not imply that an artifact has been published.

Building from source

MSRV is Rust 1.88, and CI holds that floor. Day-to-day development uses the toolchain pinned in rust-toolchain.toml, which rustup picks up automatically along with the wasm32-unknown-unknown target.

cargo build --workspace
cargo test --workspace
cargo clippy --all-targets -- -D warnings
cargo fmt --all

# WASM packages (kernel + file-format translators): dual-target build,
# merge, and validation
cargo xtask wasm-build

# Plain WASM builds: the kernel as shipped (no translators), the single-module
# kernel with translators bundled, and the translator module
cargo build -p remus-wasm --target wasm32-unknown-unknown --release --no-default-features
cargo build -p remus-wasm --target wasm32-unknown-unknown --release
cargo build -p remus-wasm-io --target wasm32-unknown-unknown --release

# API docs
cargo doc --workspace --no-deps --open

Repository invariants have their own checks, all of which CI runs:

./scripts/check-boundaries.sh              # layer dependency DAG
./scripts/check-doc-paths.sh               # documented file paths still resolve
./scripts/check-apache-lineage.sh          # no prohibited upstream lineage
python3 scripts/check-apache-replay-provenance.py   # provenance ledger integrity

Documentation

Where What
book/ Task-oriented guide: getting started, architecture, concepts, operation reference, tolerances, data exchange, WASM, rendering, troubleshooting
docs/kernel-maturity/ The maturity contract (target, capability matrix, operation contract, failure taxonomy, testing strategy), the master roadmap and its supporting capability/adoption specifications
docs/design/ RFCs and design research: operation context (0001), coedge architecture (0002), persistent naming (0003), tolerant modeling (0004), body taxonomy (0005), swept analytic surfaces (0006)
docs/production-readiness/ Audit, stability matrix, coverage, release checklist, fork maintenance, Apache replay provenance
AGENTS.md Working guide: module map, ripple-effect checklists, common pitfalls
CHANGELOG.md Full history, including the pre-fork series

Maintainers should use the production-readiness audit, stability matrix, and release checklist before cutting an artifact. The checklist is validation guidance and does not grant authority to publish.

Roadmap

The Remus master roadmap is the single source of truth for priorities, dependencies, implementation status and remaining work. It consolidates P-Class, Open Kernel, bridge work, stabilization residue and all 111 performance packages. Start with its current priorities and check in-flight PR ownership before selecting one bounded item.

Detailed specifications, design RFCs and source-pinned audits remain supporting references. The kernel maturity target, capability matrix and stability matrix continue to define correctness and public claims.

Contributing

See CONTRIBUTING.md. Contributions are inbound under Apache-2.0 and require a Developer Certificate of Origin sign-off. Commits are conventional commits, enforced by commitlint; the pre-commit hook runs cargo fmt and clippy, and CI gates the full test suite, the layer-boundary check, and the license-lineage check on every push.

New regressions should land as reproduction bundles where the failure is expressible through the batch API — every discovered defect is meant to become a permanent, replayable regression.

Security reports: see SECURITY.md.

Provenance

Remus continues a codebase whose upstream relicensed to AGPL at v3. This repository is the permanent Apache-2.0 line of that work, maintained by Esau Engineering. The last permissive upstream release is v2.129.15; nothing from v3 or later is merged, and behavior from those releases enters only under an explicit Apache-2.0 grant or as an independent implementation proven by a regression test.

That boundary is enforced in CI and every replayed contribution is recorded in an auditable ledger — see Apache contribution provenance.

The project's use of AI tooling is disclosed in AI-DISCLOSURE-ETHICS.md.

License

Remus is licensed under the Apache License, Version 2.0, permanently — see Provenance for how the AGPL boundary with the historical upstream is enforced. Attribution is in NOTICE, and contributions come in under the same license (see CONTRIBUTING.md).

About

Exact B-Rep solid modeling kernel for Rust and WebAssembly: analytic-preserving booleans, blends, sweeps, healing, and STEP exchange. Apache-2.0.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages