# -*- coding: utf-8 -*- """ Gối đỡ trục Ø12 có kẹp, kiểu đế bích (dạng SHF12) – dựng lại từ bản vẽ "Trup", E-ENG-001. Mã mẫu: CAD-GDT12-01. Vật liệu: nhôm. Dung sai chung: ISO 2768-m. Đơn vị: mm. HỆ TRỤC Z = trục lỗ Ø12 (trục lắp), mặt bắt đế (mặt tì lên máy) nằm ở z = 0, mặt trên ở z = H = 13. XY = mặt phẳng hình chiếu đứng của bản vẽ: X ngang (rộng 47), Y hướng lên phía cụm kẹp. Tâm lỗ Ø12 tại gốc toạ độ. KÍCH THƯỚC LẤY TỪ BẢN VẼ (ghi số): 47, 36, Ø5.5, R6, R12.5, 17.85, 2.5 (rãnh xẻ), R2, 22.5°, Ø4.2, Ø3.3, 4.5 (tâm lỗ kẹp tới đỉnh), R4.5, 28, 13, 7 (dày đế), 6.5 (tâm lỗ kẹp tới mặt đế), Ø14, 1.5. SUY RA / GIẢI THÍCH (xem README): - Đỉnh cụm kẹp: 28 - 12.5 = 15.5 phía trên tâm. - Đầu tai: cạnh dưới nghiêng 22.5° TIẾP TUYẾN với R12.5 ⇒ nửa chiều cao đầu tai = 3.796 (đo trên hình ≈ 3.8–4). Cạnh trên nghiêng 22.5° đối xứng, gặp thành cụm kẹp tại Y ≈ 9.83 (đo trên hình ≈ 9.8). - R4.5 = mặt tựa đầu vít Ø9 đồng trục lỗ kẹp, khoét phần đế quanh cụm kẹp (khớp đường Y = 6.5 trên hình chiếu đứng và cung R4.5 trên hình chiếu cạnh). - Ø14 sâu 1.5 = bậc vào lỗ ở mặt trên (vòng tròn kép trên hình chiếu đứng, nét khuất cách mặt trên 1.5). - Lỗ kẹp: nửa trái Ø3.3 (khoan để ta-rô M4), nửa phải Ø4.2 (lỗ thoát vít M4). GIẢ ĐỊNH (bản vẽ không ghi): vát lỗ bắt Ø5.5 0.3×45°, vát miệng lỗ kẹp 0.4×45°. """ import math, os, json import cadquery as cq OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "out") os.makedirs(OUT, exist_ok=True) # ---------------- Thông số ---------------- W_TOTAL = 47.0 # chiều dài đế HOLE_PITCH = 36.0 # khoảng cách 2 lỗ bắt D_MOUNT = 5.5 # lỗ bắt đế D_BORE = 12.0 # lỗ trục (R6) R_RING = 12.5 # vành ngoài W_BOSS = 17.85 # rộng cụm kẹp SLIT = 2.5 # rãnh xẻ H_TOTAL = 28.0 # cao hình chiếu đứng (đỉnh cụm kẹp → đáy vành) Y_TOP = H_TOTAL - R_RING # 15.5 H = 13.0 # dày theo trục (chiều cao chi tiết khi đặt trên đế) T_FLANGE = 7.0 # dày đế ANG = math.radians(22.5) R_FIL = 2.0 # các góc R2 D_TAP, D_CLR = 3.3, 4.2 # lỗ kẹp: ta-rô M4 / thoát M4 CLAMP_Y = Y_TOP - 4.5 # 11.0 – tâm lỗ kẹp CLAMP_Z = 6.5 # tính từ mặt đế R_SPOT = 4.5 # mặt tựa đầu vít Ø9 D_CB, CB_DEPTH = 14.0, 1.5 # Kiểm tra chuỗi kích thước assert abs(R_RING + Y_TOP - 28.0) < 1e-9 assert abs(HOLE_PITCH / 2 + (W_TOTAL - HOLE_PITCH) / 2 - W_TOTAL / 2) < 1e-9 assert CLAMP_Y - D_CLR / 2 > R_RING * 0 + D_BORE / 2 # lỗ kẹp không cắt vào lỗ trục assert abs((H - CLAMP_Z) - 6.5) < 1e-9 # lỗ kẹp gần giữa chiều dày 13 s, c, t = math.sin(ANG), math.cos(ANG), math.tan(ANG) XE = W_TOTAL / 2 YE = (R_RING - XE * s) / c # nửa chiều cao đầu tai để cạnh dưới tiếp tuyến R12.5 TX, TY = R_RING * s, -R_RING * c # điểm tiếp tuyến (x>0) Y_BOSS_JOIN = YE + (XE - W_BOSS / 2) * t GEOM = {"YE": YE, "tangent": (TX, TY), "Y_boss_join": Y_BOSS_JOIN} def body(): # 1) Vành + cụm kẹp: cao suốt 13 ring = cq.Workplane("XY").circle(R_RING).extrude(H) boss = cq.Workplane("XY").center(0, Y_TOP / 2).rect(W_BOSS, Y_TOP).extrude(H) # 2) Đế bích dày 7: đa giác 2 tai, cạnh trên/dưới nghiêng 22.5° pts = [(XE, YE), (0, YE + XE * t), (-XE, YE), (-XE, -YE), (-TX, TY), (TX, TY), (XE, -YE)] flange = cq.Workplane("XY").polyline(pts).close().extrude(T_FLANGE) b = ring.union(boss).union(flange) # 3) Bo R2 các cạnh đứng: 2 góc đỉnh cụm kẹp, 4 góc đầu tai, 2 góc lõm nơi cạnh nghiêng gặp cụm kẹp def near(pts_xy, tol=0.05): class Sel(cq.Selector): def filter(self, objs): out = [] for e in objs: p = e.Center() if any(abs(p.x - x) < tol and abs(p.y - y) < tol for x, y in pts_xy): out.append(e) return out return Sel() corners = [(sx * W_BOSS / 2, Y_TOP) for sx in (1, -1)] + \ [(sx * XE, sy * YE) for sx in (1, -1) for sy in (1, -1)] + \ [(sx * W_BOSS / 2, Y_BOSS_JOIN) for sx in (1, -1)] b = b.edges("|Z").edges(near(corners)).fillet(R_FIL) # 4) Lỗ trục Ø12 suốt + bậc Ø14 sâu 1.5 ở mặt trên b = b.cut(cq.Workplane("XY").circle(D_BORE / 2).extrude(H)) b = b.cut(cq.Workplane("XY").workplane(offset=H - CB_DEPTH).circle(D_CB / 2).extrude(CB_DEPTH)) # 5) Rãnh xẻ 2.5 từ lỗ trục lên đỉnh cụm kẹp b = b.cut(cq.Workplane("XY").center(0, (Y_TOP + 1) / 2).rect(SLIT, Y_TOP + 1).extrude(H)) # 6) 2 lỗ bắt đế Ø5.5, vát 0.3 mặt trên đế (giả định) for sx in (1, -1): h = cq.Workplane("XY").center(sx * HOLE_PITCH / 2, 0).circle(D_MOUNT / 2).extrude(T_FLANGE) ch = cq.Solid.makeCone(D_MOUNT / 2, D_MOUNT / 2 + 0.6, 0.6, cq.Vector(sx * HOLE_PITCH / 2, 0, T_FLANGE - 0.3)) b = b.cut(h).cut(cq.Workplane().add(ch)) # 7) Mặt tựa đầu vít Ø9 (R4.5) đồng trục lỗ kẹp, ngoài 2 thành cụm kẹp for sx in (1, -1): x0 = sx * W_BOSS / 2 spot = cq.Solid.makeCylinder(R_SPOT, 20, cq.Vector(x0, CLAMP_Y, CLAMP_Z), cq.Vector(sx, 0, 0)) b = b.cut(cq.Workplane().add(spot)) # 8) Lỗ kẹp: phải Ø4.2 (thoát), trái Ø3.3 (ta-rô M4); vát miệng 0.4 (giả định) clr = cq.Solid.makeCylinder(D_CLR / 2, W_BOSS / 2, cq.Vector(0, CLAMP_Y, CLAMP_Z), cq.Vector(1, 0, 0)) tap = cq.Solid.makeCylinder(D_TAP / 2, W_BOSS / 2, cq.Vector(0, CLAMP_Y, CLAMP_Z), cq.Vector(-1, 0, 0)) b = b.cut(cq.Workplane().add(clr)).cut(cq.Workplane().add(tap)) for sx, d in ((1, D_CLR), (-1, D_TAP)): x0 = sx * W_BOSS / 2 cone = cq.Solid.makeCone(d / 2 + 0.4, d / 2, 0.4, cq.Vector(x0, CLAMP_Y, CLAMP_Z), cq.Vector(-sx, 0, 0)) b = b.cut(cq.Workplane().add(cone)) return b def shaft(L=30.0, d=11.99): # Trục minh hoạ Ø12 (vẽ Ø11.99 để không trùng mặt với lỗ), vát 0.5 hai đầu return cq.Workplane("XY").circle(d / 2).extrude(L).faces(">Z or X").edges().fillet(0.4) head = head.cut(cq.Workplane("YZ").workplane(offset=2.0).polygon(6, 3.0 / math.cos(math.pi / 6)).extrude(2.0)) shank = cq.Workplane("YZ").circle(2.0).extrude(-16.0).faces("