JefSCAD
Rust, Python bindings, CSG, BRep, NURBS, numerical meshing
The Problem
I like OpenSCAD. Defining solids programmatically is the right way to do parametric 3D modeling. But OpenSCAD has two fundamental problems:
-
Floating-point errors create thin sections. When combining or subtracting solids, floating point inaccuracies produce tiny slivers along boolean operation boundaries. They're invisible on screen but ruin 3D prints.
-
Immediate meshing loses fidelity. Objects are meshed at creation time. A cylinder becomes a faceted polygon immediately — stretch it into an ellipse and the facets stretch unevenly, revealing the fixed resolution.
There's a third desire: OpenSCAD's scripting language is limited. Real parametric modeling should live inside a real programming language.
JefSCAD is my answer: a geometry kernel that keeps solids as mathematical objects until the final export step, embedded in Python with a Rust backend.
The Architecture: Three Levels
The system operates through three successive representations:
CSG (tree) ──→ BRep (topology + geometry) ──→ Mesh (triangles)
1. Constructive Solid Geometry (CSG)
A tree structure where:
- Leaf nodes are primitives (cylinder, sphere, box, extrusion, solid of rotation)
- Internal nodes are boolean operations (union, intersection, difference)
- All nodes carry transforms (translate, rotate, scale)
The tree is pure mathematical description — no meshing happens here. This means you can combine solids and the result stays exact until you explicitly compile it.
Each node has a geometry hash for caching and a provenance ID for tracing which part of the tree produced which piece of the final solid.
2. Boundary Representation (BRep)
The BRep separates topology from geometry:
| Topology | Geometry |
|---|---|
| Solid → Shells | Surface (parametric: u,v → R³) |
| Shell → Faces | Curve (parametric: t → R³) |
| Face → Loops → Coedges | P-Curve (t → u,v for trimming) |
| Coedge → Edge → Vertex | Point (x,y,z) |
A shell is a set of faces forming a closed manifold. A solid is an outer shell plus optional inner shells defining voids.
Faces reference parametric surfaces (plane, cylinder, sphere, NURBS). Edges reference parametric curves (line, arc, NURBS). Coedges carry p-curves that trim the face boundary in the surface's (u,v) parameter space.
This separation means: high-precision STEP export (using the exact surface/curve definitions), separate control over mesh resolution per face, and the ability to refine meshes locally without re-evaluating the entire boolean tree.
3. Mesh
An unstructured triangle mesh generated from the BRep:
- Vertices with positions and vertex normals
- Triangles with per-vertex normals and UV coordinates
- Constraint tracking — which edges correspond to BRep edges (cannot be flipped during refinement)
- Refinement — Delaunay triangulation with edge flips and point insertion for quality control
Numerical Meshing Module
This is what connects JefSCAD to the GPU Fluid Dynamics project. The meshing module exports solver-ready spatial data:
- Voxelized volumes — identifying fluid cells vs. solid cells
- Boundary-intersection maps — exact distance from cell center to geometry surface (for interpolated bounce-back in LBM)
- Warped hex-grids — curvilinear coordinates that hug complex geometry while maintaining structured memory access
Ideal Usage
import jefscad
# Start with primitives
cyl = jefscad.cylinder(r=2, h=3)
ball = jefscad.sphere(r=2.5)
capped_sphere = jefscad.union(cyl, ball.translate(0, 0, 3))
# Compile to BRep for precision / STEP export
ctx = jefscad.new_context()
brep = capped_sphere.compile_to_brep(ctx)
brep.save_step("my_thing.step")
# Generate a mesh for STL / OBJ / rendering
mesh = capped_sphere.create_mesh(ctx)
mesh.save_stl("my_thing.stl")
mesh.save_obj("my_thing.obj")
Current Status
JefSCAD is an active project. The CSG tree structure, BRep data model, and mesh generation strategy are fully specified. Current work focuses on:
- Implementing the CSG → BRep compilation (evaluating boolean operations against parametric surfaces)
- Building the half-edge mesh data structure with constraint-aware refinement
- Developing the Python bindings for the ergonomic API shown above
The geometry kernel design is informed by my background in computational physics and finite element methods — the BRep data model draws directly from techniques used in FEM mesh generation.
Related Projects
- GPU Fluid Dynamics — consumes JefSCAD's numerical meshing for LBM simulation
- Constructive Solid Geometry — detailed notes on the CSG tree structure (on wiki)
- Boundary Representation (BRep) — full topological data model (on wiki)