Cosplay/nhf/parts/fasteners.py

121 lines
3.2 KiB
Python
Raw Normal View History

2024-07-19 00:58:10 -07:00
from dataclasses import dataclass
import math
import cadquery as Cq
from nhf import Item, Role
import nhf.utils
2024-07-19 14:06:13 -07:00
@dataclass(frozen=True)
class FlatHeadBolt(Item):
diam_head: float
height_head: float
diam_thread: float
height_thread: float
@property
def name(self) -> str:
return f"Bolt M{int(self.diam_thread)} h{int(self.height_thread)}mm"
def generate(self) -> Cq.Assembly:
head = Cq.Solid.makeCylinder(
radius=self.diam_head / 2,
height=self.height_head,
)
rod = (
Cq.Workplane('XY')
.cylinder(
radius=self.diam_thread/ 2,
height=self.height_thread,
centered=(True, True, False))
)
rod.faces("<Z").tag("tip")
rod.faces(">Z").tag("root")
return (
Cq.Assembly()
.addS(rod, name="thread", role=Role.CONNECTION)
.addS(head, name="head", role=Role.CONNECTION,
loc=Cq.Location((0, 0, self.height_thread)))
)
2024-07-19 00:58:10 -07:00
@dataclass(frozen=True)
class ThreaddedKnob(Item):
"""
2024-07-19 21:00:10 -07:00
A threaded rod with knob on one side
2024-07-19 00:58:10 -07:00
"""
2024-07-19 14:06:13 -07:00
diam_thread: float
height_thread: float
2024-07-19 00:58:10 -07:00
diam_knob: float
diam_neck: float
height_neck: float
height_knob: float
@property
def name(self) -> str:
2024-07-19 14:06:13 -07:00
return f"Knob M{int(self.diam_thread)} h{int(self.height_thread)}mm"
2024-07-19 00:58:10 -07:00
def generate(self) -> Cq.Assembly:
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,
)
2024-07-19 14:06:13 -07:00
thread = (
2024-07-19 00:58:10 -07:00
Cq.Workplane('XY')
.cylinder(
2024-07-19 14:06:13 -07:00
radius=self.diam_thread / 2,
height=self.height_thread,
2024-07-19 00:58:10 -07:00
centered=(True, True, False))
)
2024-07-19 14:06:13 -07:00
thread.faces("<Z").tag("tip")
thread.faces(">Z").tag("root")
2024-07-19 00:58:10 -07:00
return (
Cq.Assembly()
2024-07-19 14:06:13 -07:00
.addS(thread, name="thread", role=Role.CONNECTION)
2024-07-19 00:58:10 -07:00
.addS(neck, name="neck", role=Role.HANDLE,
2024-07-19 14:06:13 -07:00
loc=Cq.Location((0, 0, self.height_thread)))
2024-07-19 00:58:10 -07:00
.addS(knob, name="knob", role=Role.HANDLE,
2024-07-19 14:06:13 -07:00
loc=Cq.Location((0, 0, self.height_thread + self.height_neck)))
2024-07-19 00:58:10 -07:00
)
@dataclass(frozen=True)
class HexNut(Item):
2024-07-19 14:06:13 -07:00
diam_thread: float
2024-07-19 00:58:10 -07:00
pitch: float
2024-07-19 14:06:13 -07:00
thickness: float
width: float
2024-07-19 00:58:10 -07:00
def __post_init__(self):
2024-07-19 14:06:13 -07:00
assert self.width > self.diam_thread
2024-07-19 00:58:10 -07:00
@property
def name(self):
2024-07-19 14:06:13 -07:00
return f"HexNut M{int(self.diam_thread)}-{self.pitch}"
2024-07-19 00:58:10 -07:00
@property
2024-07-19 21:00:10 -07:00
def role(self) -> Role:
2024-07-19 00:58:10 -07:00
return Role.CONNECTION
def generate(self) -> Cq.Workplane:
2024-07-19 14:06:13 -07:00
r = self.width / math.sqrt(3)
2024-07-19 00:58:10 -07:00
result = (
Cq.Workplane("XY")
.sketch()
.regularPolygon(r=r, n=6)
2024-07-19 14:06:13 -07:00
.circle(r=self.diam_thread/2, mode='s')
2024-07-19 00:58:10 -07:00
.finalize()
2024-07-19 14:06:13 -07:00
.extrude(self.thickness)
2024-07-19 00:58:10 -07:00
)
result.faces("<Z").tag("bot")
result.faces(">Z").tag("top")
2024-07-19 15:06:57 -07:00
result.copyWorkplane(Cq.Workplane('XY')).tagPlane("dirX", direction="+X")
2024-07-19 00:58:10 -07:00
return result