Create and Measure Solids
Solid-root B-Rep work goes through the Brep namespace of @huukhanhnguyen/geometry (one-shell documents have their own namespace, Shell). Solids are JSON documents (strings): every function takes documents and returns a fresh one. Inputs are never mutated and there is nothing to free.
Primitives
import { Brep } from '@huukhanhnguyen/geometry'
const box = Brep.box(100, 60, 40) // dx, dy, dz from the origin corner
const shaft = Brep.cylinder(12, 80) // radius, height — axis along +Z
const ball = Brep.sphere(25) // radiusMove and rotate
Translation has a dedicated door. Rotation goes through a 4×4 matrix — there is no Brep.rotate; build the matrix with the Transformation namespace and apply it with Brep.transform:
import { Brep, Transformation } from '@huukhanhnguyen/geometry'
const moved = Brep.translate(box, 10, 20, 30)
const rot = Transformation.fromRotation(0, 0, 1, Math.PI / 4) // axis xyz + angle (rad)
const spun = Brep.transform(box, rot)
// Compose: matrices are Float64Array, flat 4×4, translation at [12..14]
const m = Transformation.multiply(Transformation.fromTranslation(0, 0, 50), rot)
const placed = Brep.transform(box, m)Measure
Volume and surface area take the document plus a tolerance. Brep.measurementDefaultEps() returns the kernel default — a relative band of 1e-6:
const eps = Brep.measurementDefaultEps()
Brep.volume(box, eps) // 240_000
Brep.surfaceArea(box, eps) // 24_800Planar geometry measures to machine precision; curved booleans carry tessellator sag, so compare curved volumes with a looser band (~1%) rather than 1e-9.
Inspect
Cheap structural checks before you commit to expensive operations:
Brep.isClosed(box) // true — sealed solid
Brep.freeEdgeCount(box) // 0 — no open boundaries
const [vertices, edges, , faces] = Brep.entityCounts(box)
// box → vertices 8, edges 12, faces 6End to end
import { Brep } from '@huukhanhnguyen/geometry'
const eps = Brep.measurementDefaultEps()
const a = Brep.box(2, 2, 2)
const b = Brep.translate(Brep.box(2, 2, 2), 1, 1, 1)
const u = Brep.union(a, b)
console.log(Brep.volume(u, eps)) // 15 (8 + 8 − 1 overlap)Where next
- Booleans and edits — subtract/union/intersect, chamfer, fillet, draft.
- Tessellate for display — turn the document into triangles.
- Concepts: units and tolerances — what
epsactually means.