diff --git a/nhf/handle.py b/nhf/handle.py new file mode 100644 index 0000000..0509897 --- /dev/null +++ b/nhf/handle.py @@ -0,0 +1,156 @@ +""" +This schematics file contains all designs related to tool handles +""" +from dataclasses import dataclass +import cadquery as Cq + +@dataclass(frozen=True) +class Handle: + """ + Characteristic of a tool handle + """ + + # Outer radius for the handle + radius: float = 38 / 2 + + # Inner radius + radius_inner: float = 33 / 2 + + # Wall thickness for the connector + insertion_thickness: float = 4 + + # The connector goes in the insertion + connector_thickness: float = 4 + + # Length for the rim on the female connector + rim_length: float = 5 + + insertion_length: float = 60 + + connector_length: float = 60 + + def __post_init__(self): + assert self.radius > self.radius_inner + assert self.radius_inner > self.insertion_thickness + self.connector_thickness + assert self.insertion_length > self.rim_length + + @property + def _r1(self): + """ + Radius of inside of insertion + """ + return self.radius_inner - self.insertion_thickness + @property + def _r2(self): + """ + Radius of inside of connector + """ + return self._r1 - self.connector_thickness + + def segment(self, length: float): + result = ( + Cq.Workplane() + .cylinder(radius=self.radius, height=length) + ) + result.faces("Z").tag("mate2") + return result + + def insertion(self): + """ + This type of joint is used to connect two handlebar pieces. Each handlebar + piece is a tube which cannot be machined, so the joint connects to the + handle by glue. + + Tags: + * lip: Co-planar Mates to the rod + * mate: Mates to the connector + """ + result = ( + Cq.Workplane('XY') + .cylinder( + radius=self.radius_inner, + height=self.insertion_length - self.rim_length, + centered=[True, True, False]) + ) + result.faces(">Z").tag("lip") + result = ( + result.faces(">Z") + .workplane() + .circle(self.radius) + .extrude(self.rim_length) + .faces(">Z") + .hole(2 * self._r1) + ) + result.faces(">Z").tag("mate") + return result + + def connector(self, solid: bool = False): + """ + Tags: + * mate{1,2}: Mates to the connector + """ + result = ( + Cq.Workplane('XY') + .cylinder( + radius=self.radius, + height=self.connector_length, + ) + ) + for (tag, selector) in [("mate1", "Z")]: + result.faces(selector).tag(tag) + r1 = self.radius_inner + result = ( + result + .faces(selector) + .workplane() + .circle(self._r1) + .extrude(self.insertion_length) + ) + if not solid: + result = result.faces(">Z").hole(2 * self._r2) + return result + + def one_side_connector(self): + result = ( + Cq.Workplane('XY') + .cylinder( + radius=self.radius, + height=self.rim_length, + ) + ) + result.faces("Z").tag("base") + result = ( + result + .faces(" self.hs_joint_radius,\ "Wing root must be large enough to accomodate joint" @@ -301,3 +306,6 @@ class Parameters: result.constrain(f"harness?{name}_{i}", f"hs_{name}p?h{i}", "Point") result.solve() return result + + def trident_assembly(self): + return MT.trident_assembly(self.trident_handle) diff --git a/nhf/touhou/houjuu_nue/test.py b/nhf/touhou/houjuu_nue/test.py index 91808a7..2eb8cd7 100644 --- a/nhf/touhou/houjuu_nue/test.py +++ b/nhf/touhou/houjuu_nue/test.py @@ -18,6 +18,9 @@ class Test(unittest.TestCase): def test_harness(self): p = M.Parameters() p.harness_assembly() + def test_trident(): + p = M.Parameters() + p.trident_assembly() if __name__ == '__main__': unittest.main() diff --git a/nhf/touhou/houjuu_nue/trident.py b/nhf/touhou/houjuu_nue/trident.py new file mode 100644 index 0000000..e270e74 --- /dev/null +++ b/nhf/touhou/houjuu_nue/trident.py @@ -0,0 +1,30 @@ +import math +import cadquery as Cq +from nhf import Material +from nhf.handle import Handle + +def trident_assembly( + handle: Handle, + handle_segment_length: float = 24*25.4): + def segment(): + return handle.segment(handle_segment_length) + mat_i = Material.PLASTIC_PLA + mat_s = Material.ACRYLIC_BLACK + assembly = ( + Cq.Assembly() + .add(handle.insertion(), name="i0", color=mat_i.color) + .constrain("i0", "Fixed") + .add(segment(), name="s1", color=mat_s.color) + .constrain("i0?lip", "s1?mate1", "Plane", param=0) + .add(handle.insertion(), name="i1", color=mat_i.color) + .add(handle.connector(), name="c1", color=mat_i.color) + .add(handle.insertion(), name="i2", color=mat_i.color) + .constrain("s1?mate2", "i1?lip", "Plane", param=0) + .constrain("i1?mate", "c1?mate1", "Plane") + .constrain("i2?mate", "c1?mate2", "Plane") + .add(segment(), name="s2", color=mat_s.color) + .constrain("i2?lip", "s2?mate1", "Plane", param=0) + .add(handle.insertion(), name="i3", color=mat_i.color) + .constrain("s2?mate2", "i3?lip", "Plane", param=0) + ) + return assembly.solve()