Docs · Concepts

How it fits together

The object model every wrapper shares, explained once. Names here are Python’s; each language page gives its own spelling at the same anchor.

Two libraries

The reader and the kernel

The reader (cadaclysm_capi) opens a CAD file — STEP, IGES, IFC, Rhino 3dm, ACIS SAT, OpenSCAD and the rest — into a Scene: a tree of nodes, the geometry each draws, and the places it is drawn. It meshes on demand, hands back exact surfaces where the file had them, and writes glTF, OBJ, STL and Gmsh .msh.

The kernel (cadaclysm_blacksmith) builds exact solids from profiles — extrude, revolve, loft, sweep — combines them with booleans, rounds and bevels their edges, hollows them, and writes STEP. Solid.to_scene hands a solid to the reader for everything else.

Each is its own shared library with its own licence call; one licence file serves both.

Reading

Scenes, nodes, placements

A node is anything the file has: an assembly, a part, a body, a layer, a storey, an instance. Nodes form a tree (roots, children, parent) and are cheap: a name, a kind, attributes, a colour. A node is a handle into the scene, not a copy, so asking for its name reads the scene at that moment.

Geometry is built lazily. node.mesh, node.bounds and node.edges build a node's geometry the first time they are asked; scene.realize_all() builds all of it across every core. A tree can be on screen before the first triangle exists.

Draw placements, not nodes. A part used seventy times is one node of geometry and seventy Placements — each naming that node and a transform. Iterate scene.placements to draw, upload each geometry node's mesh once, and draw it at every placement's transform. A node walk would draw the part once, at its definition.

Coordinates. Meshes and polylines are in their node's own frame, single precision; transforms are 4×4 double precision, so a model at survey coordinates keeps its millimetres. The Convention passed to open — native, Y-up metres, Unreal, Unity, Blender — is applied by the library, so what comes out is already in the space you draw in.

Exact surfaces. Where a reader has them (STEP, IGES, SAT, 3dm), node.surfaces gives each face as its surface — plane, cylinder, cone, sphere, torus, revolution, extrusion, NURBS — plus trim loops in the surface's own (u, v). It costs the mesh nothing.

Finding things. scene.query(filter) takes one boolean expression in the query language and returns the matching nodes.

Memory

Everything borrows from the scene

Mesh and polyline arrays are views into the scene's own memory, not copies: a large assembly is tens of millions of triangles, most of which go straight to a GPU and are dropped. They are valid until the scene is closed; mesh.copy() gives arrays of your own. Strings are always copied out and outlive everything. The kernel's meshes are views into the solid's cache in the same way. Each language page's Lifetimes section gives the exact rule in its terms.

Errors

The library's own words

A failing call surfaces the library's reason: an exception in Python, C#, Java and Node.js and a thrown error in Swift (CadaclysmError from the reader, BuildError from the kernel), an error value in Go, an Err in Rust, last_error in C. Kernel operations fail at once, at the call that failed — a fillet too large for its faces, a profile that crosses itself — rather than at some later step. A query that matches nothing is an empty result, not an error.

Building

Profiles, workplanes, solids

A Profile is a closed 2D outline with holes: a rectangle, circle, slot or polygon, or a Path of lines, arcs, Béziers and NURBS. A Solid comes from a primitive or from a profile on a frame — extruded, revolved, lofted to another profile, or swept along a path of lines and arcs. Solids are immutable: every operation returns a new one.

The Workplane chain reads like a sketch-and-extrude session: start on a plane, extrude, pick a face with a Selector, move onto it, build the next feature there. Combining is explicit: build each feature as its own solid and join, cut or common them. Then edges, filtered by kind, direction and neighbouring faces, feed fillet and chamfer; shell hollows.

Everything stays exact: a fillet between two planes is a cylinder, a circle swept along an arc is a torus. Triangles appear only when asked for — mesh(tolerance) — and the booleans decide at a tolerance (0.05 by default) that is a cost dial, not an accuracy one.

Threads

Concurrency

Opening, meshing and the kernel's operations are blocking calls; run them off a UI thread. realize_all uses every core by itself, and realized/realize_total can be polled from another thread to show progress. Node.js has …Async twins that run on a worker thread. Error reasons are per thread in every language.