Gridfinity Bin
A storage bin compatible with the Gridfinity 42 mm grid system, generated in any grid size and height. It follows the standard profile: stepped 45-degree feet that sit in a baseplate, a 41.5 mm outline with rounded corners, and a stacking lip so bins stack on each other. Options are compartments along X and Y, a scoop that rounds the floor into the front wall so small parts can be swept out with a finger, a label shelf along the back wall, and four 6.5 x 2.4 mm magnet pockets per cell under the feet. The default 2 x 1 bin, 3 units high with two compartments, measures 83.5 x 41.5 x 24.9 mm. It prints upright on its feet with no supports; every overhang is 45 degrees or less. Parameters: grid units in X and Y, height units, lip, compartments in X and Y, scoop, label shelf, magnets and wall thickness.
# Gridfinity Bin - any grid size and height, with X/Y dividers, scoop, label shelf and magnets
#
# A Gridfinity-compatible storage bin: the standard 42 mm grid, 7 mm height units,
# 41.5 mm outline with R3.75 corners, stepped 45 deg feet (0.8 + 1.8 + 2.15) that sit in a
# baseplate, and a 4.4 mm stacking lip so another bin can sit on top.
# Options: compartments along X and Y, a scoop (rounded floor against the front wall so small
# parts can be swept out with a finger), a label shelf along the back wall, and four
# 6.5 x 2.4 mm magnet pockets per cell under the feet.
# Prints upright on the feet with no supports: every overhang in the profile is 45 deg or less.
@param 1..8 desc:"Grid units along X"
$units_x = 2
@param 1..8 desc:"Grid units along Y"
$units_y = 1
@param 2..12 desc:"Height in 7 mm units (excluding the lip)"
$height_u = 3
@param desc:"Stacking lip"
$lip = true
@param 1..6 desc:"Compartments along X"
$div_x = 2
@param 1..6 desc:"Compartments along Y"
$div_y = 1
@param desc:"Scoop: rounded floor along the front wall"
$scoop = true
@param desc:"Label shelf along the back wall"
$label = true
@param desc:"Magnet pockets (6 x 2 mm) under the feet"
$magnets = true
@param 0.8..2.4 step:0.1 desc:"Wall thickness (mm)"
$wall = 1.2
# --- Standard values ------------------------------------------------------
$pitch = 42
$unit = 7
$foot_h = 4.75 # 0.8 (45 deg) + 1.8 + 2.15 (45 deg)
$r = 3.75
$lip_land = 0.5 # small flat on top of the lip (the spec has a sharp edge)
$floor_top = 6 # inner floor height above the foot bottom (covers the magnet pockets)
def rr($w, $h, $r) = rect ($w - 2 * $r) ($h - 2 * $r) | offset $r
$W = $units_x * $pitch - 0.5
$D = $units_y * $pitch - 0.5
$H = $height_u * $unit
$z_top = if $lip then $H + 4.4 - $lip_land else $H
# --- Feet: one per cell, inset 2.95 from the 41.5 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, $r)] [0.8, 2.6, $foot_h] ruled:true
def cx($i) = ($i % $units_x - ($units_x - 1) / 2) * $pitch
def cy($i) = ($i // $units_x - ($units_y - 1) / 2) * $pitch
$n = $units_x * $units_y
$feet = union [$foot | translate cx(i) cy(i) 0 for i in range($n)]
$body = rr($W, $D, $r) | extrude ($z_top - $foot_h) | translate 0 0 $foot_h
# --- Cavity. With a lip it narrows at 45 deg to the lip's lower edge, then follows the
# stepped lip profile (0.7 / 1.8 / 1.9) back out to the outline
$Wi = $W - 2 * $wall
$Di = $D - 2 * $wall
$ri = $r - $wall
$sup = 2.6 - $wall # height of the 45 deg support under the lip
$cav_lip = rr($Wi, $Di, $ri)
| loft [rr($Wi, $Di, $ri), rr($W - 5.2, $D - 5.2, $r - 2.6), rr($W - 1.4, $D - 1.4, $r - 0.7), rr($W - 1.4, $D - 1.4, $r - 0.7), rr($W, $D, $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
$div_top = $H - $sup # dividers and shelves stop under the lip support
# --- Scoop: a quarter-round fillet between the floor and the front wall ---------------
$pitch_y = $Di / $div_y
$R = min(14, $div_top - $floor_top - 1, $pitch_y - $wall - 2)
$scoop_blank = box ($Wi + 2) $R $R center:(true, false, false) | translate 0 ($Di / -2 - 1) $floor_top
$scoop_cyl = cylinder $R ($Wi + 4) | rotate 0 90 0 | translate 0 ($Di / -2 - 1 + $R) ($floor_top + $R)
$scoop_fill = $scoop_blank - $scoop_cyl
# --- Dividers ------------------------------------------------------------------------
$div_h = $div_top - $floor_top
$divs_x = union [box $wall ($Di + 1) $div_h at:(($k + 1) * $Wi / $div_x - $Wi / 2, 0, $floor_top + $div_h / 2) for $k in range($div_x - 1)]
$divs_y = union [box ($Wi + 1) $wall $div_h at:(0, ($k + 1) * $pitch_y - $Di / 2, $floor_top + $div_h / 2) for $k in range($div_y - 1)]
# --- Label shelf: triangular, along the back wall, 45 deg underside ---------------------
$tab_w = min(12, $div_h - 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 pockets: four per cell at +-13, open at the bottom ---------------------------
$mag = cylinder 3.25 2.6 center:(true, true, false) | translate 0 0 -0.2
$mags = union [$mag | translate (cx(i // 4) + (if i % 2 == 0 then 13 else -13)) (cy(i // 4) + (if i // 2 % 2 == 0 then 13 else -13)) 0 for i in range($n * 4)]
# --- Assemble --------------------------------------------------------------------------
$shell0 = ($feet + $body) - $cavity
$b1 = if $scoop then $shell0 + $scoop_fill else $shell0
$b2 = if $div_x > 1 then $b1 + $divs_x else $b1
$b3 = if $div_y > 1 then $b2 + $divs_y else $b2
$b4 = if $label then $b3 + $tab else $b3
$bin = if $magnets then $b4 - $mags else $b4
# --- Checks ----------------------------------------------------------------------------
assert $bin.solids == 1
assert $bin.bbox.x ~ $W
assert $bin.bbox.y ~ $D
assert $bin.bbox.z ~ $z_top
assert $bin.volume < $W * $D * $z_top * 0.5 # it is hollow
assert $R > 2 # the scoop has room
print "size (mm)" $bin.bbox.x
print "volume (mm^3)" $bin.volume
$bin