Skip to main content
InvariantCAD documents are kernel-neutral, but geometry capabilities are not. Choose the backend based on representation, exchange, topology, performance, and deployment needs.

Comparison

Default Manifold

Choose Manifold for fast, robust mesh-first workflows, ordinary parametric modeling, browser evaluation, and STL/OBJ output. It supports twist and top-scale extrusion, which the exact backend does not currently advertise.

Stock OpenCascade

Choose stock OCCT for analytic B-Rep geometry, topology snapshots, exact bounded lofts/sweeps, fillets/chamfers/shells/offsets, and STEP/BREP exchange. Stock history for several complex features remains partial. The following own-data rule applies since 0.2.0; the 0.1.1 package read these fields through ordinary property access. The OCCT kernel reads context.signal, context.feature, context.tolerance, and every low-level STEP export option from own data properties only. An accessor-backed field, or one supplied by a caller-defined prototype such as a class getter, fails with TypeError instead of being ignored, so a class-based cancellation signal is never silently dropped. A field reachable only through the intrinsic Object.prototype is ignored, so prototype pollution cannot relabel feature lineage or change kernel tolerances. feature must be a string and tolerance a number when present. Each operation captures these values once when it is called: changing or reusing the context object afterwards does not change the lineage that later topology() calls report for shapes it already created. The profile is stronger than checking representation === "brep": creation also requires the documented primitive and feature baseline, native exchange methods, exactness, face/edge/vertex topology with semantic roles, sketch sources, geometry, and adjacency, and a callable topology() snapshot method. inspectEvaluatorProfile(kernel, "mechanical-exact") lists each missing requirement as a stable path such as topology:adjacency or topology:snapshot. For custom loading, create the kernel explicitly and request the same preflight:
When createOcctKernel() receives an explicit wasm source or moduleFactory and the loaded module does not expose the owned facade ABI, the kernel is not the qualified zero-override stock runtime, even when it loads the identical stock occt-wasm.wasm bytes. It omits the persistent topology signature declaration (capabilities.topology.signatures and signatureProfiles), so evaluating a document that stores a persistent topology reference fails with KERNEL_CAPABILITY_MISSING for capability persistent-topology-signatures. It also omits the deterministic stepExport envelope and keeps weak raw STEP export. The mechanical-exact preflight still passes, because it does not require signatures. Prefer letting the bundler place occt-wasm.wasm next to its JavaScript glue so the zero-override createOcctKernel() call can load it.

Owned OCCT facade

The facade is a matched extension built from pinned source and repository patches. The JavaScript factory and WASM binary must come from the same verified bundle. InvariantCAD probes its versioned ABI and advertises only the refinements that probe succeeds. It is not bundled with the npm package, not selected automatically, and not downloaded at runtime.

Capability preflight

The evaluator treats capabilities as data contracts. Before executing a feature, it checks:
  • protocol version
  • primitive or feature name
  • exact composite-sweep refinements
  • native import/export format
  • strong single-body import format and unit mode
  • topology evidence surfaces and signature fingerprint
  • exact indexed topology evolution when a stronger contract is required
  • versioned measurement semantics such as exact or unsupported genus
  • body-result classification protocol and a callable classifier whenever a staged product solid graph contains a Boolean
  • deterministic single-shape STEP metadata, bounds, and byte scope
Malformed metadata fails separately from absent support. A kernel cannot obtain behavior merely by defining an unadvertised method. Use inspectKernelMeasurementCapabilities(...) or kernelSupports(capabilities, "measurement", "genus") for discovery. A numeric measurement is exact for the backend representation; null means unsupported. The following strong STEP envelope was added in 0.2.0 and is not in 0.1.1. Use inspectKernelStepExportCapabilities(...) for the optional strong STEP envelope. nativeExports containing "step" promises only that bytes can be written. Calling output.export("step") without a second argument remains compatible with weak kernels; supporting kernels use their deterministic defaults, and fall back to weak native bytes for an output they can write only as several STEP products. Passing any second argument, including {}, requires a valid stepExport envelope or throws CadError with KERNEL_CAPABILITY_MISSING. nativeImports is the weak exchange declaration. Document-backed imported bodies require the separate versioned documentBodyImport envelope and a callable importDocumentBody(...) method. Stock OCCT currently makes only these stronger promises: The strong path rejects multiple solids, shells, and wrappers containing loose topology. It unwraps a pure one-solid compound, normalizes reversed orientation, uses fatal UTF-8 for text BREP, and releases provisional native handles on failure or cancellation. It does not claim healing, assembly import, stable feature lineage, or containment of an untrusted native parser. The public ImportedBodyDocument workflow composes this kernel contract with a caller-supplied SHA-256/byte-length commitment and resolver. It accepts only STEP + model/step + file units, text BREP + text/plain + declared units, or binary BREP + application/octet-stream + declared units. Its explicit format chooses the reader; the media type is provenance rather than inference. The high-level workflow fails before native parsing when resolution or commitment verification fails and never falls back to importShape(...) or Manifold. See Import and export.

Body-result classification

Body-result classification was added in 0.2.0 and is not in 0.1.1.
Protocol v1 is an optional kernel capability. A kernel that advertises bodyResultClassification: { protocolVersion: 1 } implements classifyBodyResult(shape, context?). The call borrows one shape and returns exactly one classification of its retained representation: Use inspectKernelBodyResultClassificationCapabilities(...) for discovery. It reads only own data properties, never invokes accessors, returns an immutable snapshot, and reports uninspectable-metadata, not-object, or unsupported-protocol-version separately from absent support. The result describes the kernel’s declared representation, so it inherits that representation’s exactness:
  • Manifold classifies connected components of its approximate mesh. Each component with strictly positive native volume is a body. Manifold separates a hollow solid’s cavity boundary into a negative-volume component, so that boundary bounds a void rather than adding a body. A zero-volume component is non-body topology. Its native decomposition is one synchronous WASM call: cancellation is checked before and after it, not during it. Every temporary component is deleted on success, failure, and cancellation.
  • OCCT classifies exact B-Rep contents. It traverses compound and compsolid occurrences, counts each solid occurrence as one body without reinterpreting that solid’s shells, and treats any other occurrence as loose topology. Repeated occurrences of the same solid count separately. Cancellation is checked before each traversal step and after traversal. Visited plus queued occurrences, including the root and every compound or compsolid wrapper, are bounded at 1,000,000: the pinned runtime has no non-allocating child count, so one native call materializes a wrapper’s direct children, which are charged to the bound immediately and released when it rejects them. Every traversal handle is released on success, failure, and cancellation.
Both classifiers are synchronous. They observe a signal that is already aborted when the call starts or that code running during the call aborts; an abort() scheduled from elsewhere on the same thread cannot run until the call returns. context must be a plain object, and context.signal, when present, must be an own data property; an accessor-backed signal or one supplied by a caller-defined prototype fails with TypeError instead of being ignored, while one reachable only through Object.prototype is ignored as pollution. Context and cancellation are checked before the shape is validated. Classification is structural. It does not validate the bodies it counts: check status(...) separately, as the staged evaluator does before classifying. The two classifications are not a cross-backend equivalence claim. For example, Manifold reports two boxes that touch only along an edge as two components of its mesh; near-contact geometry can classify differently on another backend. The staged Document v7 evaluator uses this contract to require that every Boolean result is exactly one body. It never splits a disconnected Boolean into invented body-set members, retries another backend, or converts exact geometry to mesh. Authors who need separate bodies list them explicitly in a bodySet.

Do not equate these guarantees

  • A B-Rep kernel is not automatically exact for every authored feature.
  • Construction support does not imply complete topology history.
  • STEP/BREP exchange does not imply safe backend-owned shape artifact caching.
  • Native STEP export does not imply deterministic metadata or byte equality.
  • Weak native import does not imply the strong document-body import contract.
  • A topology snapshot does not imply persistent signature support.
  • Successful tessellation does not make mesh coordinates analytically exact.
  • A single-body classification is only as exact as the kernel representation it classifies.
Use the support matrix for the feature-level boundary and the architecture for protocol rationale.