← Docs
Common patterns
Copy-paste recipes for everyday 3D printing geometry.
Rounded box / enclosure base
mod rbox(w, d, h, r) {
hull {
translate(r, r, 0) cylinder(h: h, r: r)
translate(w - r, r, 0) cylinder(h: h, r: r)
translate(r, d - r, 0) cylinder(h: h, r: r)
translate(w - r, d - r, 0) cylinder(h: h, r: r)
}
}
rbox(60, 40, 20, 3)Screw hole with countersink
mod screw_hole(d, h, cs_d, cs_depth) {
// Through hole
cylinder(h: h, r: d / 2)
// Countersink
translate(0, 0, h - cs_depth)
cylinder(h: cs_depth + 0.1, r1: d / 2, r2: cs_d / 2)
}
// M3 countersunk screw through 5mm plate
difference {
cube(20, 20, 5)
translate(10, 10, -0.5)
screw_hole(3.4, 6, 6.5, 1.8)
}Mounting hole pattern
mod mount_holes(w, d, h, hole_r, inset) {
for (x in [inset, w - inset]) {
for (y in [inset, d - inset]) {
translate(x, y, -0.5)
cylinder(h: h + 1, r: hole_r)
}
}
}
difference {
cube(60, 40, 3)
mount_holes(60, 40, 3, 1.7, 5)
}Wall with fillet (rounded inner edge)
mod fillet(r, h) {
difference {
cube(r, r, h)
translate(r, r, -0.1)
cylinder(h: h + 0.2, r: r)
}
}
// Vertical wall with fillet at the base
cube(40, 2, 20)
fillet(3, 20)Circular array
param count: int = 8 [3:24] "Number of items"
param radius: float = 25 [10:50] "Array radius (mm)"
for (i in [0:count - 1]) {
let angle = i * 360 / count
rotate(0, 0, angle)
translate(radius, 0, 0)
cylinder(h: 10, r: 3)
}Linear array with spacing
param count: int = 5 [1:20] "Count"
param spacing: float = 15 [8:30] "Spacing (mm)"
for (i in [0:count - 1]) {
translate(i * spacing, 0, 0) cube(10, 10, 10)
}Hollow box (shell)
param w: float = 60 [20:150] "Width (mm)"
param d: float = 40 [20:100] "Depth (mm)"
param h: float = 25 [10:60] "Height (mm)"
param wall: float = 2 [1.2:4:0.2] "Wall (mm)"
difference {
cube(w, d, h)
translate(wall, wall, wall)
cube(w - wall*2, d - wall*2, h)
}Chamfered edge
// 45-degree chamfer on top edge of a box
param size: float = 30 [10:60] "Size (mm)"
param chamfer: float = 2 [0.5:5] "Chamfer (mm)"
difference {
cube(size, size, size)
translate(0, 0, size)
rotate(45, 0, 0)
cube(size + 1, chamfer * 2, chamfer * 2)
}Text emboss / deboss
// Raised text on a plate
// Note: text() is supported but limited to built-in fonts
param text_depth: float = 1 [0.4:3:0.2] "Text height (mm)"
cube(50, 20, 2)
translate(5, 5, 2)
extrude(text_depth)
text("HELLO", size: 10)Snap-fit clip
// Simple cantilever snap-fit
param length: float = 10 [5:20] "Clip length (mm)"
param width: float = 5 [3:10] "Clip width (mm)"
param thickness: float = 1 [0.8:2:0.1] "Thickness (mm)"
param hook: float = 1.5 [0.5:3:0.5] "Hook depth (mm)"
// Cantilever arm
cube(length, width, thickness)
// Hook at the end
translate(length - thickness, 0, -hook)
cube(thickness, width, hook + thickness)Cable comb (repeated slots)
param cables: int = 6 [2:12] "Number of cables"
param cable_d: float = 5 [3:10:0.5] "Cable diameter (mm)"
param wall: float = 2 [1.5:4:0.5] "Wall (mm)"
param depth: float = 8 [5:15] "Depth (mm)"
let slot = cable_d + wall
let total_w = cables * slot + wall
difference {
cube(total_w, depth, cable_d + wall * 2)
for (i in [0:cables - 1]) {
translate(wall + i * slot + slot / 2, -0.5, wall + cable_d / 2)
rotate(-90, 0, 0)
cylinder(h: depth + 1, r: cable_d / 2)
}
}Tolerance test block
// Print this to calibrate your clearance parameter
let sizes = [0.1, 0.2, 0.3, 0.4, 0.5]
for (i in [0:4]) {
translate(i * 12, 0, 0) {
difference {
cube(10, 10, 5)
translate(5, 5, -0.5)
cylinder(h: 6, r: 3 + sizes[i])
}
}
}