Card Deck Box
A two-part box for a deck of playing cards: the cards stand on their short edge in a box with rounded corners, and a cap slides over the top with a friction fit. Choose the card format (poker 63 x 88, bridge 57 x 88, mini 44 x 68 or tarot 70 x 120 mm), the number of cards and whether they are sleeved; the box width, depth and height follow from that, at 0.30 mm per plain card or 0.40 mm per sleeved card. A thumb notch on both wide faces lets you lift the deck out. The default 60 poker cards give a box of 68 x 22 x 91 mm with a 71 x 26 x 22 mm cap; the whole layout is 146 x 26 x 91 mm. Both parts print open side up with no supports. Wall thickness, cap depth and the cap clearance are parameters, and a closed view shows the cap on the box.
# Card Deck Box - a two-part box sized from the card format, the deck size and sleeves
#
# The cards stand on their short edge in a box with rounded vertical corners; a cap
# slides over the top with a friction fit. The inner size comes from the card format
# (poker, bridge, mini or tarot) plus the sleeve allowance, and the depth from the
# number of cards times the thickness per card (0.30 mm plain, 0.40 mm sleeved). A
# thumb notch on both wide faces lets you lift the deck out. Both parts print open
# side up with no supports; the layout shows the box and, beside it, the cap. Use
# `view = "closed"` to see the cap on the box (the fit is checked with clear()).
@param choices:["poker", "bridge", "mini", "tarot"] group:"Cards" desc:"Card format: poker 63 x 88, bridge 57 x 88, mini 44 x 68, tarot 70 x 120 (mm)"
$format = "poker"
@param 20..200 step:10 group:"Cards" desc:"Number of cards"
$count = 60
@param group:"Cards" desc:"Cards are in sleeves (adds 2 x 3 mm and 0.1 mm per card)"
$sleeved = false
@param 1.2..2.4 step:0.2 group:"Box" desc:"Wall thickness (mm)"
$wall = 1.6
@param 15..30 step:1 group:"Box" desc:"Cap depth (mm)"
$cap_d = 20
@param 0.2..0.5 step:0.05 group:"Box" desc:"Clearance between cap and box per side (mm)"
$fit = 0.3
@param choices:["print", "closed"] group:"Output" desc:"Print layout, or the cap closed on the box"
$view = "print"
$cw = if $format == "poker" then 63 else if $format == "bridge" then 57 else if $format == "mini" then 44 else 70
$ch = if $format == "poker" then 88 else if $format == "bridge" then 88 else if $format == "mini" then 68 else 120
$card_t = if $sleeved then 0.40 else 0.30
$sl_w = if $sleeved then 2 else 0
$sl_h = if $sleeved then 3 else 0
$clr = 1.0 # free play around the deck
$floor_t = 1.6
$corner = 3
$in_w = $cw + $sl_w + $clr # cavity along X
$in_d = $count * $card_t + $clr # cavity along Y (the stack)
$in_h = $ch + $sl_h + 1 # cards sit 1 mm below the rim
$W = $in_w + 2 * $wall
$D = $in_d + 2 * $wall
$H = $in_h + $floor_t
assert $D >= 8 # not too thin a box to print
$notch_r = 10
assert $notch_r < $cap_d - 2 # the notch is hidden under the cap
def rr($w, $h, $r) = rect ($w - 2 * $r) ($h - 2 * $r) | offset $r
# --- Box ---------------------------------------------------------------
$body = rr($W, $D, $corner) | extrude $H
$cavity = rr($in_w, $in_d, $corner - $wall + 0.4) | extrude $in_h | translate 0 0 $floor_t
$notch = cylinder $notch_r ($D + 2) | rotate 90 0 0 | translate 0 0 $H
$box = $body - $cavity - $notch
assert $box.solids == 1
assert $box.bbox.x ~ $W
assert $box.bbox.y ~ $D
assert $box.bbox.z ~ $H
print "cavity (mm)" [$in_w, $in_d, $in_h]
# --- Cap: an open box whose inside is the box outline plus the clearance --------
$cW = $W + 2 * $fit + 2 * $wall
$cD = $D + 2 * $fit + 2 * $wall
$cH = $cap_d + $wall
$cap_body = rr($cW, $cD, $corner + $fit + $wall) | extrude $cH
$cap_in = rr($W + 2 * $fit, $D + 2 * $fit, $corner + $fit) | extrude $cap_d | translate 0 0 $wall
$cap = $cap_body - $cap_in
assert $cap.solids == 1
assert $cap.bbox.x ~ $cW
assert $cap.bbox.z ~ $cH
# --- Closed view: cap turned over and dropped onto the box ----------------------
$cap_on = $cap | rotate 180 0 0 | translate 0 0 ($H + $wall)
assert clear($box, $cap_on)
$closed = union [$box, $cap_on]
assert $closed.bbox.z ~ ($H + $wall)
$print = union [$box, $cap | translate (($W + $cW) / 2 + 8) 0 0]
assert $print.solids == 2
if $view == "closed" then $closed else $print