2D or Not 2D

Tonight I shipped cylinder booleans. Subtracting cylinders from boxes to make holes. Classic CAD operation.

The problem: a cylinder intersects a cube's face along a circle. Circles in 3D are annoying. No start, no end, curving through space. Splitting a planar face along one means handling the inner disk separately from the outer ring.

The answer is UV space.

parameter space

Every surface in CAD has a 2D coordinate system that maps to points on the 3D surface. We call the coordinates uu and vv because xx, yy, zz are taken.

A cylinder is just a rectangle that got rolled up:

  • uu goes around the circumference (00 to 2π2\pi)
  • vv goes up the height

The surface equation:

P(u,v)=center+r(cos(u)x^+sin(u)y^)+vaxisP(u, v) = \text{center} + r \cdot (\cos(u) \cdot \hat{x} + \sin(u) \cdot \hat{y}) + v \cdot \text{axis}

Plug in any (u,v)(u, v), get the exact 3D point. No triangles, no approximation.

circles become lines

When a horizontal plane cuts through a vertical cylinder, the intersection is a circle in 3D. In UV space? A horizontal line.

The circle sits at constant height hh. Height is the vv coordinate. So the circle becomes v=hv = h.

A 3D circle became a 1D line. That's the trick.

splitting a cylinder

When you subtract a cylinder from a cube, you keep only the part inside the cube. That means splitting at the top and bottom faces.

Say the cube spans z=0 to z=20. The cylinder runs from z=-5 to z=25, poking out both ends. Intersection circles at z=0 and z=20.

In UV space:

  • Original cylinder: rectangle [0,2π]×[5,25][0, 2\pi] \times [-5, 25]
  • Split at v=0v=0 and v=20v=20
  • Three strips:
    • Bottom [-5, 0]: outside cube, discard
    • Middle [0, 20]: inside cube, keep for hole wall
    • Top [20, 25]: outside cube, discard

"Split a curved 3D surface along two circles" became "draw two horizontal lines on a rectangle."

uv domains

Every curved surface has one:

Surfaceuu domainvv domain
Cylinder[0,2π][0, 2\pi] angle(,)(-\infty, \infty) height
Sphere[0,2π][0, 2\pi] longitude[π2,π2][-\frac{\pi}{2}, \frac{\pi}{2}] latitude
Cone[0,2π][0, 2\pi] angle[0,)[0, \infty) distance from apex
Torus[0,2π][0, 2\pi] major[0,2π][0, 2\pi] minor

The domain shape tells you about topology. A cylinder's UV domain is an open rectangle, infinite in vv. A torus is closed, both uu and vv wrap around.

why bother

When building a CAD kernel, you have two choices:

  1. Work in 3D: intersect surfaces, trace curves through space, handle every edge case
  2. Work in UV: map to 2D, solve easy problems, map back

Option 2 wins.

Surface-surface intersection? Sample the curve, convert to UV, get a 2D curve on each surface. Trim curves? 2D paths. Face splitting? 2D polygon operations.

Complex 3D geometry becomes simple 2D geometry.

the code

Here's cylinder splitting in vcad:

pub fn split_cylindrical_face_by_circle(
    brep: &mut BRepSolid,
    face_id: FaceId,
    circle: &Circle3d,
) -> SplitResult {
    let cyl = get_cylinder_surface(brep, face_id);

    // Convert circle to UV: just compute v coordinate
    let v_split = (circle.center - cyl.center).dot(&cyl.axis);

    let (v_min, v_max) = get_face_v_bounds(brep, face_id);

    // Lower: [0, 2π] × [v_min, v_split]
    // Upper: [0, 2π] × [v_split, v_max]
    create_split_faces(brep, face_id, v_split, v_min, v_max)
}

Fifteen lines. No 3D circle math. Project to v, split the rectangle.

the seam

One gotcha: cylinders have a seam. The UV rectangle's left and right edges (u=0u=0 and u=2πu=2\pi) are the same line in 3D.

When a split curve crosses the seam, it wraps around. Phase 2 handles this. For perpendicular cuts like drilling holes, the intersection is a complete circle that doesn't cross the seam, so we're fine.

what's next

Cylinder booleans unlocked:

  • Drilling vertical holes through horizontal plates (done)
  • Drilling angled holes (elliptical intersections)
  • Cylinder-cylinder intersections (pipe joints)
  • General curved surface booleans

Same pattern every time: map to UV, solve in 2D, map back.

Once you see surfaces as 2D domains, everything clicks.

Related: