from dataclasses import dataclass import math import cadquery as Cq from nhf import Item, Role import nhf.utils @dataclass(frozen=True) class ThreaddedKnob(Item): """ Sourced from: > Othmro Black 12mm(M12) x 50mm Thread Replacement Star Hand Knob Tightening > Screws """ diam_rod: float height_rod: float diam_knob: float diam_neck: float height_neck: float height_knob: float @property def name(self) -> str: return f"Knob-M{int(self.diam_rod)}-{int(self.height_rod)}mm" def generate(self) -> Cq.Assembly: print(self.name) knob = Cq.Solid.makeCylinder( radius=self.diam_knob / 2, height=self.height_knob, ) neck = Cq.Solid.makeCylinder( radius=self.diam_neck / 2, height=self.height_neck, ) rod = ( Cq.Workplane('XY') .cylinder( radius=self.diam_rod / 2, height=self.height_rod, centered=(True, True, False)) ) rod.faces("Z").tag("root") return ( Cq.Assembly() .addS(rod, name="rod", role=Role.CONNECTION) .addS(neck, name="neck", role=Role.HANDLE, loc=Cq.Location((0, 0, self.height_rod))) .addS(knob, name="knob", role=Role.HANDLE, loc=Cq.Location((0, 0, self.height_rod + self.height_neck))) ) @dataclass(frozen=True) class HexNut(Item): diam: float pitch: float # FIXME: Measure these m: float s: float def __post_init__(self): assert self.s > self.diam @property def name(self): return f"HexNut-M{int(self.diam)}-{self.pitch}" @property def role(self): return Role.CONNECTION def generate(self) -> Cq.Workplane: print(self.name) r = self.s / math.sqrt(3) result = ( Cq.Workplane("XY") .sketch() .regularPolygon(r=r, n=6) .circle(r=self.diam/2, mode='s') .finalize() .extrude(self.m) ) result.faces("Z").tag("top") result.copyWorkplane(Cq.Workplane('XY')).tagPlane("dir", direction="+X") return result