Token Tray
A sorting tray for game tokens or coins: one half-round trough per denomination, in which the tokens stand on edge in a row so every one is visible and easy to pick. The trough radius follows the token diameter, the trough length the number of tokens it should hold (thickness times count), and a finger scoop is cut across the front of the dividers. The default, five troughs of thirty 25 mm tokens, is 147 x 84 x 19 mm; the number of troughs (2 to 8), token size and count, divider and floor thickness are all parameters. Prints flat on its base with no supports.
# Token Tray - round-bottom troughs that hold game tokens or coins on edge
#
# A block with one half-round trough per denomination; tokens stand on edge in a
# row, so the top of every token shows and one can be picked with two fingers. The
# trough radius comes from the token diameter, the trough length from how many
# tokens it should hold, and a finger scoop is cut across the front of the dividers.
# Prints flat on its base, no supports (the troughs are concave, the scoop is a
# 45 deg-free arc).
@param 2..8 step:1 group:"Layout" desc:"Number of troughs"
$slots = 5
@param 15..40 step:1 group:"Tokens" desc:"Token diameter (mm)"
$token_d = 25
@param 1.5..4 step:0.5 group:"Tokens" desc:"Token thickness (mm)"
$token_t = 2.5
@param 10..60 step:5 group:"Tokens" desc:"Tokens per trough"
$stack = 30
@param 1.6..3 step:0.2 group:"Tray" desc:"Divider thickness (mm)"
$div = 2
@param 2..4 step:0.5 group:"Tray" desc:"Floor thickness under the troughs (mm)"
$floor_t = 2
$R = $token_d / 2 + 1 # trough radius
$wall_h = max(3, $token_d * 0.65 - $R) # straight wall above the half-round; the token top still shows
assert $R + $wall_h < $token_d
$tr_w = 2 * $R
$tr_l = $stack * $token_t + 3
$end = 3 # end walls
$W = $slots * $tr_w + ($slots + 1) * $div
$L = $tr_l + 2 * $end
$H = $floor_t + $R + $wall_h
$top_z = $H
def trough_x($i) = -$W / 2 + $div + $R + $i * ($tr_w + $div)
def trough($i) = (cylinder $R $tr_l | rotate 90 0 0 | translate trough_x($i) 0 ($floor_t + $R))
+ (box $tr_w $tr_l ($wall_h + 1) center:(true, true, false) | translate trough_x($i) 0 ($floor_t + $R))
$block = rect ($W - 6) ($L - 6) | offset 3 | extrude $H
$troughs = union [trough($i) for $i in range($slots)]
$scoop_r = 8
$scoop = cylinder $scoop_r ($W + 2) | rotate 0 90 0 | translate 0 (-$L / 2 + $end + 6) ($top_z + 2)
$tray = $block - $troughs - $scoop
assert $tray.solids == 1
assert $tray.bbox.x ~ $W
assert $tray.bbox.y ~ $L
assert $tray.bbox.z ~ $H
$v_troughs = $slots * (pi * $R * $R / 2 + $tr_w * $wall_h) * $tr_l
assert $tray.volume < $block.volume - $v_troughs
assert $tray.volume > $block.volume - $v_troughs - $slots * 2 * $scoop_r * $scoop_r * $div * 4
print "tray (mm)" [$W, $L, $H]
$tray