Hose Adapter
A tapered adapter that joins two hoses or ports of different diameters, for a shop vacuum, a dust-extraction port on a power tool or a garden hose. Each end is either a plug that goes inside a hose (enter the hose's inner diameter) or a socket that goes over a port (enter the port's outer diameter), and each end tapers by an adjustable amount over its length so it wedges tight. A flange in the middle is the stop and the grip. The default joins a 32 mm hose to a 35 mm tool port and measures 41 x 41 x 68 mm. It prints standing on end A with no supports: the flange underside and the step in the bore are 45 degree cones. Adjustable parameters: diameter, fit type and length of each end, taper, wall thickness, flange thickness and socket clearance.
# Hose Adapter - joins two hoses or ports of different diameters, with a taper on each end
#
# Two ends on one tube, each either a plug (goes inside a hose: give the hose's inner
# diameter) or a socket (goes over a port: give the port's outer diameter). Each end
# tapers by `taper` over its length so it wedges tight; the middle flange is a stop and
# a grip. The flange underside and the step in the bore are 45 deg cones, so the adapter
# prints standing on end A with no supports.
@param 15..80 step:0.5 group:"End A (bottom)" desc:"Diameter at end A (mm): hose inner diameter for a plug, port outer diameter for a socket"
$d_a = 32
@param choices:["plug", "socket"] group:"End A (bottom)" desc:"End A goes inside a hose (plug) or over a port (socket)"
$fit_a = "plug"
@param 10..60 step:1 group:"End A (bottom)" desc:"Length of end A (mm)"
$len_a = 30
@param 15..80 step:0.5 group:"End B (top)" desc:"Diameter at end B (mm)"
$d_b = 35
@param choices:["plug", "socket"] group:"End B (top)" desc:"End B goes inside a hose (plug) or over a port (socket)"
$fit_b = "socket"
@param 10..60 step:1 group:"End B (top)" desc:"Length of end B (mm)"
$len_b = 30
@param 0.25..2 step:0.25 group:"Tube" desc:"Taper of each end over its length, on the diameter (mm)"
$taper = 1
@param 1.2..3 step:0.2 group:"Tube" desc:"Wall thickness (mm)"
$wall = 2
@param 2..5 step:0.5 group:"Tube" desc:"Flange thickness (mm)"
$flange_t = 3
@param 0..0.6 step:0.1 group:"Tube" desc:"Extra clearance of a socket on its port (mm, on the diameter)"
$socket_play = 0.2
# --- Radii at the ends of each section (0 = free end, 1 = flange end) -------------
# plug: outer = d/2, tip narrower by taper/2; inner = outer - wall
# socket: inner = d/2 + play/2, bottom narrower by taper/2; outer = inner + wall
$oa0 = if $fit_a == "plug" then $d_a / 2 - $taper / 2 else $d_a / 2 + $socket_play / 2 + $wall
$oa1 = if $fit_a == "plug" then $d_a / 2 else $d_a / 2 + $socket_play / 2 - $taper / 2 + $wall
$ia0 = $oa0 - $wall
$ia1 = $oa1 - $wall
$ob0 = if $fit_b == "plug" then $d_b / 2 - $taper / 2 else $d_b / 2 + $socket_play / 2 + $wall
$ob1 = if $fit_b == "plug" then $d_b / 2 else $d_b / 2 + $socket_play / 2 - $taper / 2 + $wall
$ib0 = $ob0 - $wall
$ib1 = $ob1 - $wall
$rf = max($oa1, $ob1) + 1.5 # flange radius
$ip = min($ia1, $ib1) # passage through the flange
$step = $ia1 - $ip # bore step at the flange, 45 deg cone
$z1 = $len_a # end A meets the flange cone
$fz = $z1 + ($rf - $oa1) # bottom of the flange disc
$z2 = max($fz + $flange_t, $z1 + $step + 1.5) # flange top: tall enough to hold the bore step
$z3 = $z2 + $len_b # free end of B
# --- Build from frustums (no polygon: equal bores would give zero-length edges) ---
$tube_a = (cone $oa0 $oa1 $len_a center:(true, true, false)) - (cone $ia0 $ia1 $len_a center:(true, true, false))
$flange_cone = cone $oa1 $rf ($rf - $oa1) center:(true, true, false) | translate 0 0 $z1
$flange_disc = cylinder $rf ($z2 - $fz) center:(true, true, false) | translate 0 0 $fz
$tube_b = ((cone $ob1 $ob0 $len_b center:(true, true, false)) - (cone $ib1 $ib0 $len_b center:(true, true, false)))
| translate 0 0 $z2
$passage = cylinder $ip ($z2 - $z1 + 2) center:(true, true, false) | translate 0 0 ($z1 - 1)
$base = ($tube_a + $flange_cone + $flange_disc + $tube_b) - $passage
# the bore step is cut only when end A's bore is the wider one (a cone needs two radii)
$step_cone = cone ($ip + max($step, 0.1)) $ip (max($step, 0.1)) center:(true, true, false) | translate 0 0 $z1
$adapter = if $step > 0.01 then ($base - $step_cone) else $base
assert $adapter.solids == 1
assert $adapter.bbox.z ~ $z3
assert $adapter.bbox.x ~ (2 * $rf)
assert $ia0 >= 4 # the bore is open at the narrow end
assert $ib0 >= 4
assert $wall >= 1.2
assert $z2 - $fz >= $flange_t
print "adapter" $adapter.bbox
print "end A outer / inner (mm)" (2 * $oa0) (2 * $ia0)
print "end B outer / inner (mm)" (2 * $ob0) (2 * $ib0)
$adapter