Gridfinity Bin and Baseplate
A storage bin and baseplate compatible with the Gridfinity 42 mm grid system, generated from a single parametric source in any size. The stepped 45-degree foot, stacking lip and baseplate pockets follow the standard profile, and the bin can include dividers, a label shelf on the back wall and 6 x 2 mm magnet holes. The baseplate can be sized by grid count, or set to the inner dimensions of a drawer or box so the number of cells is calculated automatically and the leftover becomes an even margin. The default output (a 2 x 1 x 3u bin next to a 3 x 2 baseplate) measures 219.5 x 84 x 24.9 mm. Both parts print upright on their bottom face with no supports, since every overhang is 45 degrees or less. Adjustable parameters include the part to output, bin grid size and height units, lip, label shelf, compartments, magnets, wall thickness, baseplate grid size, box fit dimensions and clearance.
# Gridfinity-compatible Bin + Baseplate - every size from one source
# Standard values: 42mm grid / 7mm height unit / bin outline 41.5 R3.75
# baseplate profile 0.7 (45deg) + 1.8 (vertical) + 2.15 (45deg) = 4.65
@param choices:["bin", "baseplate", "both"] desc:"Part to output"
part = "both"
# ---- Bin ----
@param 1..8 group:"Bin" desc:"Bin size in grid units, X"
bin_x = 2
@param 1..8 group:"Bin" desc:"Bin size in grid units, Y"
bin_y = 1
@param 2..12 group:"Bin" desc:"Height units (x7mm, excluding lip)"
bin_u = 3
@param group:"Bin" desc:"Add stacking lip"
lip = true
@param group:"Bin" desc:"Add label shelf (on the back wall)"
label = true
@param 1..6 group:"Bin" desc:"Compartments along X"
div_x = 2
@param group:"Bin" desc:"6x2 magnet holes in the base"
magnets = true
@param 0.8..2.4..0.1 group:"Bin" desc:"Wall thickness (mm)"
wall = 1.2
# ---- Baseplate ----
@param 1..10 group:"Baseplate" desc:"Grid units X (used when fit_w=0)"
plate_x = 3
@param 1..10 group:"Baseplate" desc:"Grid units Y (used when fit_d=0)"
plate_y = 2
@param 0..400 group:"Baseplate" desc:"Inner width of the box to fill, X (mm, 0=off)"
fit_w = 0
@param 0..400 group:"Baseplate" desc:"Inner depth of the box to fill, Y (mm, 0=off)"
fit_d = 0
@param 0..2..0.1 group:"Baseplate" desc:"Clearance to the box (per side)"
fit_clear = 0.5
# ---- Standard constants ----
pitch = 42
unit = 7
foot_h = 4.75 # bin foot: 0.8 (45deg) + 1.8 + 2.15 (45deg)
bin_r = 3.75
lip_land = 0.5 # flat land on top of the lip (spec is a sharp edge; kept for printability)
floor_top = 6 # height of the bin's inner floor (assumed)
def rr(w, h, r) = rect (w - 2 * r) (h - 2 * r) | offset r
# ===== Bin =====
W = bin_x * pitch - 0.5
D = bin_y * pitch - 0.5
H = bin_u * unit
z_top = if lip then H + 4.4 - lip_land else H
# One foot (inset 2.95 from the 41.5 square outline)
foot = rr(35.6, 35.6, 0.8)
| loft [rr(37.2, 37.2, 1.6), rr(37.2, 37.2, 1.6), rr(41.5, 41.5, bin_r)] [0.8, 2.6, foot_h] ruled:true
n_bin = bin_x * bin_y
feet = union [foot | translate ((i % bin_x - (bin_x - 1) / 2) * pitch) ((i // bin_x - (bin_y - 1) / 2) * pitch) 0 for i in range(n_bin)]
body = rr(W, D, bin_r) | extrude (z_top - foot_h) | translate 0 0 foot_h
# Inner cavity. With a lip, it narrows at 45deg from H-1.4 to the lip's lower edge (outline - 5.2),
# then opens with the stepped 0.7/1.8/1.9 slopes
Wi = W - 2 * wall
Di = D - 2 * wall
ri = bin_r - wall
sup = 2.6 - wall # lip overhang inside the wall = height of the support slope
cav_lip = rr(Wi, Di, ri)
| loft [rr(Wi, Di, ri), rr(W - 5.2, D - 5.2, bin_r - 2.6), rr(W - 1.4, D - 1.4, bin_r - 0.7), rr(W - 1.4, D - 1.4, bin_r - 0.7), rr(W, D, bin_r)] [H - sup - floor_top, H - floor_top, H + 1.9 - floor_top, H + 3.7 - floor_top, H + 4.4 - floor_top] ruled:true
| translate 0 0 floor_top
cav_open = rr(Wi, Di, ri) | extrude (H + 1 - floor_top) | translate 0 0 floor_top
cavity = if lip then cav_lip else cav_open
# Dividers (up to the bottom of the lip support)
div_top = H - sup
dividers = union [box wall (Di + 1) (div_top - floor_top) at:((k + 1) * Wi / div_x - Wi / 2, 0, (div_top + floor_top) / 2) for k in range(div_x - 1)]
# Label shelf: triangular shelf along the back wall, 45deg underside
tab_w = min(12, div_top - floor_top - 2)
yw = Di / 2 + 0.5
tab = workplane YZ
| polyline [(yw, div_top), (yw - tab_w, div_top), (yw - tab_w, div_top - 0.8), (yw, div_top - 0.8 - tab_w)]
| extrude Wi | translate (Wi / -2) 0 0
# Magnet holes 6.5 dia x 2.4 (for 6x2 magnets), +-13 from each cell center
mag = cylinder 3.25 2.6 | floor | translate 0 0 -0.2
mags = union [mag | translate ((i // 4 % bin_x - (bin_x - 1) / 2) * pitch + (if i % 2 == 0 then 13 else -13)) ((i // 4 // bin_x - (bin_y - 1) / 2) * pitch + (if i // 2 % 2 == 0 then 13 else -13)) 0 for i in range(n_bin * 4)]
bin0 = (feet + body) - cavity
bin1 = if div_x > 1 then bin0 + dividers else bin0
bin2 = if label then bin1 + tab else bin1
bin = if magnets then bin2 - mags else bin2
# ===== Baseplate =====
px = if fit_w > 0 then floor((fit_w - 2 * fit_clear) / pitch) else plate_x
py = if fit_d > 0 then floor((fit_d - 2 * fit_clear) / pitch) else plate_y
PW = if fit_w > 0 then fit_w - 2 * fit_clear else px * pitch
PD = if fit_d > 0 then fit_d - 2 * fit_clear else py * pitch
plate_h = 4.65
# Cutter for one cell: bottom 36.3 R1.15 -> 0.7 (45deg) -> 1.8 -> 2.15 (45deg) -> top 42 R4, overshooting top and bottom
pocket = rr(36.3, 36.3, 1.15)
| loft [rr(36.3, 36.3, 1.15), rr(37.7, 37.7, 1.85), rr(37.7, 37.7, 1.85), rr(42, 42, 4), rr(43, 43, 4.5)] [0.5, 1.2, 3.0, 5.15, 5.65] ruled:true
| translate 0 0 -0.5
n_pl = px * py
pockets = union [pocket | translate ((i % px - (px - 1) / 2) * pitch) ((i // px - (py - 1) / 2) * pitch) 0 for i in range(n_pl)]
plate_blank = rr(PW, PD, 4) | extrude plate_h
baseplate = plate_blank - pockets
# ===== Output =====
gap = 10
if part == "bin" then bin else (if part == "baseplate" then baseplate else baseplate + (bin | translate (PW / 2 + gap + W / 2) 0 0))