Half-Space Slicing and Polyhedral BReps
using Rasmah
using LinearAlgebraOverview
Boolean operations answer “what is the union/intersection/difference of two solids?”; a half-space slice answers the simpler, cheaper question “what is the part of this solid on one side of a plane?” — the question behind the drawing office’s section views: cut a part with a plane and look at the cross-section. clip_half_space does this exactly for polyhedral (planar-faced) BReps — no tessellation — and convex_polyhedron_sdf turns the result back into a fast, exact signed field.
This tutorial draws a standard machined part — a 60 × 40 × 30 mm spacer block with a 3 × 3 chamfer along one edge — entirely by clipping, and takes its section views. Dimensions are millimetres.
The chamfer: a half-space cut
A chamfer is the classic half-space feature: the machinist sets the block at 45° and cuts off the corner. clip_half_space(b, n, offset) keeps the part of b where n·x ≤ offset (the normal is normalised for you), so the plane x + z = 42 trims the top-right corner of the block to a 3 mm chamfer:
block = brep(box(60.0, 40.0, 30.0))
chamfered = clip_half_space(block, [1.0, 0.0, 1.0], 42.0 / √2) # x + z ≤ 42
println("faces: ", length(chamfered.faces), ", watertight: ", is_watertight(chamfered))faces: 7, watertight: true
vtk(chamfered)The cut removes a triangular prism of cross-section 3 × 3 / 2 along the whole 40 mm edge — and the clipped BRep volume is that number, exactly:
vm = volume(surface_mesh(chamfered; n = 64))
println("clipped volume = ", round(vm; digits = 1), " mm³")
println("analytic = ", round(60.0 * 40.0 * 30.0 - 3.0 * 3.0 / 2 * 40.0; digits = 1), " mm³")clipped volume = 71820.0 m^3 mm³
analytic = 71820.0 mm³
The section view
A drawing shows the inside of a part by cutting it. The vertical plane x = 0 splits the block down its middle — keep one half:
sec = clip_half_space(chamfered, [1.0, 0.0, 0.0], 0.0) # keep x ≤ 0
println("section faces: ", length(sec.faces), ", watertight: ", is_watertight(sec))
println("section volume = ", round(volume(surface_mesh(sec; n = 64)); digits = 1),
" mm³ (half of 72000; the chamfer lies on the removed side)")section faces: 6, watertight: true
section volume = 36000.0 m^3 mm³ (half of 72000; the chamfer lies on the removed side)
vtk(sec)Slicing is repeatable: cut the half again with the horizontal plane z = 0 to isolate the bottom quarter:
quarter = clip_half_space(sec, [0.0, 0.0, 1.0], 0.0) # keep z ≤ 0
println("quarter volume = ", round(volume(surface_mesh(quarter; n = 64)); digits = 1), " mm³")quarter volume = 18000.0 m^3 mm³
Every cut stitches a planar cap onto the slicing plane, so each result stays a closed, consistently-oriented solid — the exact polyhedron a drawing’s section view depicts.
The fast polyhedral field
convex_polyhedron_sdf builds a PlanarBRepField — an ImplicitGeometry that evaluates each shell as the intersection of its face half-spaces (max of the signed plane distances) and the whole solid as the union of its shells (min across shells). It carries finite bounds, so translate/rotate/dilate, field, and marching cubes all work on it without meshing the BRep:
g = convex_polyhedron_sdf(sec)
println("inside the section: ", g([-10.0, 0.0, 10.0])) # negative
println("outside the section: ", g([10.0, 0.0, 10.0])) # positive
println("on the section plane: ", g([0.0, 0.0, 10.0])) # ≈ 0
println("bounds: ", bounds(g))inside the section: -5.0
outside the section: 10.0
on the section plane: 0.0
bounds: ([-30.0, -20.0, -15.0], [0.0, 20.0, 15.0])
Because the field is exact, the SDF-sampled surface matches the exact BRep (to the marching resolution) — the cheap, gradient-friendly proxy the assembly optimizer uses for the fragmented solid:
m = surface_mesh(g; n = 64)
println("marched volume: ", round(volume(m); digits = 1)) # → 36000 as n growsmarched volume: 35998.5 m^3
Faceted BRep: mesh → BRep
The reverse conversion — a triangle mesh back into an exact (planar-faceted) BRep — is faceted_brep. It welds coincident vertices and shared edges, so a closed, oriented surface mesh becomes a watertight, consistently-oriented solid that flows through the rest of the kernel (STEP export, booleans, is_watertight):
fb = faceted_brep(sphere(1.0); n = 24) # also brep(::TriangleMesh)
println("faceted faces: ", length(fb.faces))
println("faceted watertight: ", is_watertight(fb))faceted faces: 1280
faceted watertight: true
Summary
clip_half_spaceslices a polyhedral BRep exactly (no tessellation), sewing a planar cap onto the cut — the section-view and chamfer primitive.convex_polyhedron_sdfturns a planar BRep into a fast exact signed field with finite bounds.faceted_brepturns any triangle mesh back into a watertight planar BRep.
Together they close the loop between exact polyhedra and the SDF/mesh pipeline.
Next steps
- Boundary Representation (BRep) — the exact topological model.
- BRep Booleans, Intersections, and Editing — the general exact boolean kernel.
- Cleaning Assemblies: Filling Gaps and Smooth BReps —
dilate+faceted_brepclosing gaps in assembled parts.
