Center Finder
A 90-degree V square that marks the centre of round and square stock. Set the V against the side of a dowel, pipe or square bar with the end of the stock against the underside of the blade and draw a pencil line along the blade edge; the edge lies exactly on the bisector of the V, so the line passes through the centre, and a second line after turning the stock crosses it there. The arm length is calculated from the largest round and square stock the tool must take, and the blade is made long enough to reach across it. A millimetre scale from the apex is engraved along the drawing edge so the diameter can be read as well. The default for stock up to 60 mm round or 40 mm square measures 90 x 79 x 13 mm. Print it blade down as modelled, with no supports. Parameters: largest round and square stock, blade thickness and width, arm height and width.
# Center Finder - 90 deg V square that marks the centre of round and square stock
#
# Set the V against the side of a dowel, pipe or square bar, with the end of the stock
# against the underside of the blade, and draw a pencil line along the blade's edge: the
# edge lies exactly on the bisector of the V, so the line passes through the centre.
# Turn the stock 90 deg and draw again; the lines cross at the centre.
# The arm length comes from the largest round and square stock it must take, and the
# blade is long enough to reach across it. A mm scale from the apex is engraved along
# the drawing edge, so the diameter can be read off as well.
# Print it blade down (as modelled), no supports.
@param 20..120 desc:"Largest round stock diameter (mm)"
$max_dia = 60
@param 10..80 desc:"Largest square stock side (mm)"
$max_sq = 40
@param 2..4 step:0.5 desc:"Blade thickness (mm)"
$blade_t = 3
@param 16..40 desc:"Blade width (mm)"
$blade_w = 24
@param 8..20 desc:"Arm height above the blade (mm)"
$arm_h = 10
@param 6..12 desc:"Arm width (mm)"
$arm_w = 8
# --- Geometry from the stock sizes --------------------------------------------------
# A circle of diameter D in a 90 deg V touches each arm D/2 from the apex, and its centre
# is 0.707 D along the bisector; a square of side S needs arms S long.
$arm_l = max($max_dia / 2, $max_sq) + 8
$blade_l = max($max_dia * 1.21, $max_sq * 1.42) + 8
$h = $blade_t + $arm_h
$c45 = cos(45)
# blade: along +X from just behind the apex, its y = 0 edge is the drawing edge on the bisector
$blade = box ($blade_l + 6) $blade_w $blade_t center:(false, false, false) | translate -6 0 0
# arms: boxes whose inner faces are the lines at +-45 deg through the apex, extended 6 mm behind it
$arm0 = box ($arm_l + 6) $arm_w $h center:(false, false, false) | translate -6 0 0
$arm_p = $arm0 | rotate 0 0 45
$arm_m = $arm0 | translate 0 (-$arm_w) 0 | rotate 0 0 -45
# a heel joins the two arms behind the apex so the V is not a weak point
$hr = 6 * $c45 # polygon 4 is a diamond (vertices on the axes): its edges lie on y = +-x
$heel = polygon 4 $hr | extrude $h | translate (-$hr) 0 0
# apex relief: a square corner of stock must reach the true apex, so clear the inside corner
$relief = cylinder 1.5 ($h + 2) center:(true, true, false) | translate 0 0 -1
$body0 = union [$blade, $arm_p, $arm_m, $heel]
$body = $body0 - $relief
# --- Scale on the underside (the printed face, z = 0): ticks every 5 mm from the apex along
# the drawing edge, long ones every 10, with the value engraved every 20 -----------------
$n_tick = floor($blade_l / 5)
$tick = box 0.6 4 1.2 center:(true, false, false)
$tick_l = box 0.6 7 1.2 center:(true, false, false)
$ticks = union [(if i % 2 == 0 then $tick_l else $tick) | translate (i * 5) 0 -0.6 for i in range(1, $n_tick + 1)]
# numbers read from the underside, so they are flipped about X
$n_num = floor($blade_l / 20)
$nums = union [text ("" + (i * 20)) 4 | extrude 1 | rotate 180 0 0 | translate (i * 20) 11 0.6 for i in range(1, $n_num + 1)]
$name = text "CENTER" 5 | extrude 1 | rotate 180 0 0 | translate ($blade_l / 2) 19 0.6
$finder = $body - $ticks - $nums - $name
# --- Checks -------------------------------------------------------------------------
assert $finder.solids == 1
assert $finder.bbox.z ~ $h
assert $finder.bbox.x ~ ($blade_l + (6 + $arm_w) * $c45) tol:0.1 # the arms' outer back corners are the rearmost point
assert $finder.volume < $body.volume
# the largest circle must be reachable: blade longer than the far side of the circle
assert $blade_l > $max_dia / $c45 / 2 + $max_dia / 2
print "arm (mm)" $arm_l
print "blade (mm)" $blade_l
$finder