Skip to content
Shapemetry

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 ∩ tool

The 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 10

Both 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 -50 overshoot 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

Last updated: 📖 2 min readEdit on GitHub