whistle
大音量ホイッスル
# 大音量ホイッスル — 円筒の共鳴室 + 接線方向に吹き込むウィンドウェイ + エッジ
# 設計は X = 息の流れる向き(吹き口は -X 側)、Y = 共鳴室の軸、Z = 上(エッジのある側)で行い、
# 最後に X 軸まわりに 90° 起こして、ストラップ穴のある円筒の端面を Z = 0 の底面にする
@param 5..12 step:0.5 desc:"共鳴室の内半径 (mm)"
cham_r = 8.0
@param 6..20 desc:"共鳴室の内長さ = 軸方向 (mm)"
cham_l = 12
@param 1.6..3 step:0.1 desc:"肉厚 (mm)"
wall = 2.0
@param 4..12 desc:"ウィンドウェイの幅 (mm)"
ww = 8
@param 0.6..1.6 step:0.1 desc:"ウィンドウェイの高さ = 息の隙間 (mm)"
wh = 1.0
@param 1.5..4.5 step:0.1 desc:"窓の長さ = ウィンドウェイ出口からエッジ先端まで (mm)"
win = 2.8
@param 20..45 desc:"エッジ上面の傾斜 (度)"
bevel = 35
@param 15..35 desc:"吹き口の長さ (mm)"
mouth_l = 22
@param desc:"印刷の向きで出力する(オフにすると設計の向き)"
print_pose = true
floor_t = 0.6 # ウィンドウェイ出口での床の厚み
body_l = cham_l + 2 * wall
# --- 窓の位置を2次方程式で解く ---
a = wh / 2 + floor_t
k = 2 * a / win
m = -(a * a) / win - win
qa = k * k + 4
qb = 2 * k * m
qc = m * m - 4 * cham_r * cham_r
zl = (-qb + sqrt(qb * qb - 4 * qa * qc)) / (2 * qa) # 息の中心高さ = エッジ先端の高さ
x1 = -(k * zl + m) / 2 # エッジ先端
x0 = x1 - win # ウィンドウェイ出口
zf = zl - wh / 2 # ウィンドウェイの床
zr = zl + wh / 2 # ウィンドウェイの天井
mouth_bot = zf - 3 # 吹き口の下面
# 円柱の頂点と吹き口の上面を同じ高さにする
outer_r = max(cham_r + wall, zr + wall)
# 吹き口の下の角 P から円に引いた接線の接点 T
px = x0 - mouth_l
pd = sqrt(px * px + mouth_bot * mouth_bot)
ta = atan2(mouth_bot, px) + acos(outer_r / pd)
tx = outer_r * cos(ta)
tz = outer_r * sin(ta)
# Y 方向の中央に揃えた XZ 断面の押し出し
def yslab($pts, $w) = workplane XZ | polyline $pts | extrude $w | translate 0 (-$w / 2) 0
def ycyl($r, $l) = cylinder $r $l | rotate 90 0 0
# --- 外形 ---
$shell = workplane XZ
| sketch [(px, mouth_bot), (tx, tz), arc (tx, tz) (outer_r, 0) (0, outer_r), (px, outer_r)]
| extrude body_l | translate 0 (-body_l / 2) 0
$ring = ycyl(4.5, 4) - ycyl(2.5, 6) | translate (outer_r + 3) (-body_l / 2 + 2) 0 # ストラップ穴
# --- 空洞 ---
$chamber = ycyl(cham_r, cham_l)
$windway = yslab([(x0 - mouth_l - 1, zf), (x0 + 0.5, zf), (x0 + 0.5, zr), (x0 - mouth_l - 1, zr)], ww)
zt = outer_r + 3
zb = zl - win * tan(bevel)
$window = yslab([(x0, zb), (x1 + (zt - zl) / tan(bevel), zt), (x0, zt)], ww)
$whistle = union [$shell, $ring] | diff (union [$chamber, $windway, $window])
# 印刷の向き: X 軸まわりに 90° 起こすと、ストラップ穴の面が下に来る
if print_pose then ($whistle | rotate 90 0 0 | floor) else $whistle