Booleans and Edits
All of these are Brep.* doors: documents in, a fresh document out.
Booleans
import { Brep, Shell } from '@huukhanhnguyen/geometry'
const base = Brep.box(100, 100, 100)
const tool = Brep.translate(Brep.cylinder(25, 200), 50, 50, -50)
const drilled = Brep.subtract(base, tool) // base − tool
const merged = Brep.union(base, tool) // base ∪ tool
const overlap = Brep.intersect(base, tool) // base ∩ toolThe result of a boolean over closed solids is itself a closed solid — Brep.isClosed(result) stays true, and you can keep chaining booleans on the result.
Chamfer
Bevel selected edges by index. Edge indices address the document's edge table (Brep.entityCounts tells you how many edges exist).
// Two distances for asymmetric chamfers; equal values = 45°.
const chamfered = Brep.chamfer(base, new Uint32Array([0, 1, 2]), 5, 5)
// All edges meeting at one corner vertex:
const cutCorner = Brep.cornerChamfer(base, 0, 8)Fillet
Round selected edges. The law_kind selects the radius law — 0 is a constant radius read from the first entry of law_params:
const rounded = Brep.fillet(
base,
new Uint32Array([0, 1, 2, 3]),
0, // law_kind 0 = constant radius
new Float64Array([6]), // law_params: [radius]
)
const roundCorner = Brep.cornerFillet(base, 0, 10, 0) // vertex 0, radius 10Both chamfer and fillet have report doors — Brep.chamferReportJson / Brep.filletReportJson — that return diagnostics JSON instead of throwing on partial failures; use them when edge selection is user-driven.
Draft
Taper selected planar faces by angle radians, pivoting on the neutral plane through neutral_* with normal pull_*:
// 5° draft on face 0, pulling in +Z, neutral plane through the origin:
const tapered = Brep.draftFaces(base, new Uint32Array([0]), 0, 0, 1, (5 * Math.PI) / 180, 0, 0, 0)Other edits in the catalog
The same namespace carries shelling and face edits, all document-in/document-out: Brep.offset, Brep.thickOffset, Shell.thicken (sheet → thin solid), Brep.draftFaces and Brep.pullFace. See the generated Brep reference for signatures.
There is no history-free direct-modelling family (move / delete / replace face, defeature): a shape here is the output of an expression graph, so an edit is a change to the graph that produced the solid, not a patch applied to the solid afterwards.
Rules of thumb
- Boolean operands should overlap with real volume — coincident faces are the classic failure mode; nudge the tool slightly past the surface (the
-50overshoot in the drill example above). - Measure after editing:
Brep.volume(result, Brep.measurementDefaultEps())is the cheapest sanity check that the kernel produced the body you expected. - Failed edges in a chamfer/fillet are reported per-edge via the report doors — don't retry blindly with a bigger radius.
Where next
- Tessellate for display — render the edited solid.
- Import STEP and IGES — edit imported bodies with the same doors.