Wall Toothbrush and Razor Holder
A wall shelf that keeps toothbrushes and razors off the counter: toothbrushes stand in round holes and razors hang in slots with their heads resting on the shelf, so everything drips dry. Gussets under the shelf carry the load, and two countersunk screw holes fix it to the wall; a flat back also suits double-sided tape. The default has four brush holes and two razor slots and measures 168 x 40 x 30 mm. It is modelled in its print orientation, back plate flat on the bed, so the shelf is a vertical fin and the holes run horizontally: no supports. Adjustable parameters: number of brush holes and razor slots, hole diameter, slot length and width, shelf depth, plate height and thickness.
# Wall Toothbrush and Razor Holder - a shelf with a hole per item, screwed or taped to the wall
#
# A back plate with a shelf along its top edge; toothbrushes stand in round holes and
# razors hang in slots with their heads resting on the shelf, so everything drips dry
# and nothing touches the counter. Gussets under the shelf carry the load. Two
# countersunk screw holes, or use double-sided tape on the flat back.
# Modelled and printed with the back plate flat on the bed: the shelf is a vertical fin
# and the holes run horizontally, so no supports are needed.
@param 0..6 step:1 group:"Items" desc:"Toothbrush holes"
$brushes = 4
@param 0..4 step:1 group:"Items" desc:"Razor slots"
$razors = 2
@param 12..20 step:0.5 group:"Items" desc:"Toothbrush hole diameter (mm)"
$brush_d = 16
@param 16..30 step:1 group:"Items" desc:"Razor slot length (mm)"
$slot_l = 24
@param 6..14 step:0.5 group:"Items" desc:"Razor slot width (mm)"
$slot_w = 9
@param 20..32 step:1 group:"Plate" desc:"Shelf depth from the wall (mm)"
$depth = 26
@param 30..60 step:2 group:"Plate" desc:"Back plate height (mm)"
$height = 40
@param 3..5 step:0.5 group:"Plate" desc:"Back plate thickness (mm)"
$plate_t = 4
$shelf_t = 8
$brush_pitch = $brush_d + 8
$razor_pitch = $slot_l + 8
$len = $brushes * $brush_pitch + $razors * $razor_pitch + 8
assert $brushes + $razors >= 1
# print frame: back plate flat (z = 0..plate_t), wall side down; +Y is up when hung
$plate = box $len $height $plate_t center:(true, false, false) | edges =Z | fillet 5
$shelf = box $len $shelf_t ($plate_t + $depth) center:(true, false, false) | translate 0 ($height - $shelf_t) 0
| edges >Z =X | fillet 3
# gussets: a triangle in the YZ plane under the shelf, at both ends and between the groups
$gusset = polyline [($height - $shelf_t, $plate_t - 0.01), ($height - $shelf_t - 16, $plate_t - 0.01), ($height - $shelf_t, $plate_t + $depth - 4)]
| extrude 3 | rotate 90 0 90 | translate (-1.5) 0 0
$gussets = union [$gusset | translate $x 0 0 for $x in [-$len / 2 + 2.5, $len / 2 - 2.5]]
$body = $plate + $shelf + $gussets
# holes through the shelf (axis Y), centred on the shelf's depth
$zc = $plate_t + ($depth + 1) / 2 + 1
$x_first = -$len / 2 + 4
$brush_x = [$x_first + $brush_pitch * ($i + 0.5) for $i in range($brushes)]
$razor_x = [$x_first + $brushes * $brush_pitch + $razor_pitch * ($i + 0.5) for $i in range($razors)]
$brush_holes = union [cylinder ($brush_d / 2) ($shelf_t + 2) | rotate 90 0 0 | translate ($brush_x[$i]) ($height - $shelf_t / 2) $zc for $i in range($brushes)]
$slot = box $slot_l $slot_w ($shelf_t + 2) | edges =Z | fillet ($slot_w / 2 - 0.01) | rotate 90 0 0
$razor_slots = union [$slot | translate ($razor_x[$i]) ($height - $shelf_t / 2) $zc for $i in range($razors)]
# countersunk screw holes through the back plate
$screw = (cylinder 2.3 ($plate_t + 2)) + (cone 2.3 4.6 2.3 center:(true, true, false) | translate 0 0 ($plate_t - 2.3))
$screws = union [$screw | translate $x 12 0 for $x in [-$len / 4, $len / 4]]
$holder = $body - $brush_holes - $razor_slots - $screws
assert $holder.solids == 1
assert $holder.bbox.x ~ $len
assert $holder.bbox.y ~ $height
assert $holder.bbox.z ~ ($plate_t + $depth)
assert $holder.volume < $body.volume - $brushes * 3.14 * ($brush_d / 2) ** 2 * $shelf_t * 0.9 - $razors * $slot_l * $slot_w * $shelf_t * 0.7
assert $brush_d + 4 <= $depth # a hole leaves 2 mm of shelf on each side
print "holder" $holder.bbox
$holder