cosplay: Touhou/Houjuu Nue #4
|
@ -1,10 +1,70 @@
|
||||||
"""
|
"""
|
||||||
This schematics file contains all designs related to tool handles
|
This schematics file contains all designs related to tool handles
|
||||||
"""
|
"""
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Union, Optional
|
||||||
import cadquery as Cq
|
import cadquery as Cq
|
||||||
import nhf.parts.metric_threads as metric_threads
|
import nhf.parts.metric_threads as metric_threads
|
||||||
|
|
||||||
|
class TubeJoint:
|
||||||
|
|
||||||
|
def diam_insertion_internal(self):
|
||||||
|
"""
|
||||||
|
Maximum permitted diameter of the internal cavity
|
||||||
|
"""
|
||||||
|
def diam_connector_external(self):
|
||||||
|
"""
|
||||||
|
Maximum permitted diameter of the external size of the insertion
|
||||||
|
"""
|
||||||
|
def external_thread(self, length: float) -> Cq.Shape:
|
||||||
|
"""
|
||||||
|
Generates the external connector
|
||||||
|
"""
|
||||||
|
def internal_thread(self, length: float) -> Cq.Shape:
|
||||||
|
"""
|
||||||
|
Generates the internal connector
|
||||||
|
"""
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ThreadedJoint(TubeJoint):
|
||||||
|
|
||||||
|
pitch: float = 3
|
||||||
|
|
||||||
|
# Major diameter of the internal threads, following ISO metric screw thread
|
||||||
|
# standard. This determines the wall thickness of the insertion.
|
||||||
|
diam_threading: float = 27
|
||||||
|
|
||||||
|
def diam_insertion_internal(self):
|
||||||
|
r = metric_threads.metric_thread_major_radius(
|
||||||
|
self.diam_threading,
|
||||||
|
self.pitch,
|
||||||
|
internal=True)
|
||||||
|
return r * 2
|
||||||
|
def diam_connector_external(self):
|
||||||
|
r = metric_threads.metric_thread_minor_radius(
|
||||||
|
self.diam_threading,
|
||||||
|
self.pitch)
|
||||||
|
return r * 2
|
||||||
|
|
||||||
|
def external_thread(self, length: float):
|
||||||
|
return metric_threads.external_metric_thread(
|
||||||
|
self.diam_threading,
|
||||||
|
self.pitch,
|
||||||
|
length,
|
||||||
|
top_lead_in=True)
|
||||||
|
def internal_thread(self, length: float):
|
||||||
|
return metric_threads.internal_metric_thread(
|
||||||
|
self.diam_threading,
|
||||||
|
self.pitch,
|
||||||
|
length)
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BayonetJoint(TubeJoint):
|
||||||
|
"""
|
||||||
|
Bayonet type joint
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Handle:
|
class Handle:
|
||||||
"""
|
"""
|
||||||
|
@ -17,20 +77,16 @@ class Handle:
|
||||||
Note that all the radial sizes are diameters (in mm).
|
Note that all the radial sizes are diameters (in mm).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Outer and inner radius for the handle usually come in standard sizes
|
# Outer and inner radii for the handle usually come in standard sizes
|
||||||
diam: float = 38
|
diam: float = 38
|
||||||
diam_inner: float = 33
|
diam_inner: float = 33
|
||||||
|
|
||||||
# Major diameter of the internal threads, following ISO metric screw thread
|
joint: Optional[TubeJoint] = field(default_factory=lambda: ThreadedJoint())
|
||||||
# standard. This determines the wall thickness of the insertion.
|
|
||||||
diam_threading: float = 27.0
|
|
||||||
|
|
||||||
thread_pitch: float = 3.0
|
|
||||||
|
|
||||||
# Internal cavity diameter. This determines the wall thickness of the connector
|
# Internal cavity diameter. This determines the wall thickness of the connector
|
||||||
diam_connector_internal: float = 18.0
|
diam_connector_internal: float = 18.0
|
||||||
|
|
||||||
# If set to true, do not generate threads
|
# If set to true, do not generate the connections
|
||||||
simplify_geometry: bool = True
|
simplify_geometry: bool = True
|
||||||
|
|
||||||
# Length for the rim on the female connector
|
# Length for the rim on the female connector
|
||||||
|
@ -43,26 +99,12 @@ class Handle:
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
assert self.diam > self.diam_inner, "Material thickness cannot be <= 0"
|
assert self.diam > self.diam_inner, "Material thickness cannot be <= 0"
|
||||||
assert self.diam_inner > self.diam_insertion_internal, "Threading radius is too big"
|
if self.joint:
|
||||||
assert self.diam_insertion_internal > self.diam_connector_external
|
assert self.diam_inner > self.joint.diam_insertion_internal(), "Threading radius is too big"
|
||||||
assert self.diam_connector_external > self.diam_connector_internal, "Internal diameter is too large"
|
assert self.joint.diam_insertion_internal() > self.joint.diam_connector_external()
|
||||||
|
assert self.joint.diam_connector_external() > self.diam_connector_internal, "Internal diameter is too large"
|
||||||
assert self.insertion_length > self.rim_length
|
assert self.insertion_length > self.rim_length
|
||||||
|
|
||||||
@property
|
|
||||||
def diam_insertion_internal(self):
|
|
||||||
r = metric_threads.metric_thread_major_radius(
|
|
||||||
self.diam_threading,
|
|
||||||
self.thread_pitch,
|
|
||||||
internal=True)
|
|
||||||
return r * 2
|
|
||||||
|
|
||||||
@property
|
|
||||||
def diam_connector_external(self):
|
|
||||||
r = metric_threads.metric_thread_minor_radius(
|
|
||||||
self.diam_threading,
|
|
||||||
self.thread_pitch)
|
|
||||||
return r * 2
|
|
||||||
|
|
||||||
def segment(self, length: float):
|
def segment(self, length: float):
|
||||||
result = (
|
result = (
|
||||||
Cq.Workplane()
|
Cq.Workplane()
|
||||||
|
@ -76,20 +118,6 @@ class Handle:
|
||||||
result.faces(">Z").tag("mate2")
|
result.faces(">Z").tag("mate2")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _external_thread(self, length=None):
|
|
||||||
if length is None:
|
|
||||||
length = self.insertion_length
|
|
||||||
return metric_threads.external_metric_thread(
|
|
||||||
self.diam_threading,
|
|
||||||
self.thread_pitch,
|
|
||||||
length,
|
|
||||||
top_lead_in=True)
|
|
||||||
def _internal_thread(self):
|
|
||||||
return metric_threads.internal_metric_thread(
|
|
||||||
self.diam_threading,
|
|
||||||
self.thread_pitch,
|
|
||||||
self.insertion_length)
|
|
||||||
|
|
||||||
def insertion(self, holes=[]):
|
def insertion(self, holes=[]):
|
||||||
"""
|
"""
|
||||||
This type of joint is used to connect two handlebar pieces. Each handlebar
|
This type of joint is used to connect two handlebar pieces. Each handlebar
|
||||||
|
@ -121,11 +149,11 @@ class Handle:
|
||||||
.circle(self.diam / 2)
|
.circle(self.diam / 2)
|
||||||
.extrude(self.rim_length)
|
.extrude(self.rim_length)
|
||||||
.faces(">Z")
|
.faces(">Z")
|
||||||
.hole(self.diam_insertion_internal)
|
.hole(self.joint.diam_insertion_internal())
|
||||||
)
|
)
|
||||||
result.faces(">Z").tag("mate")
|
result.faces(">Z").tag("mate")
|
||||||
if not self.simplify_geometry:
|
if not self.simplify_geometry:
|
||||||
thread = self._internal_thread().val()
|
thread = self.joint.internal_thread(self.connector_length).val()
|
||||||
result = result.union(thread)
|
result = result.union(thread)
|
||||||
for h in holes:
|
for h in holes:
|
||||||
cyl = Cq.Solid.makeCylinder(
|
cyl = Cq.Solid.makeCylinder(
|
||||||
|
@ -157,13 +185,13 @@ class Handle:
|
||||||
result
|
result
|
||||||
.faces(selector)
|
.faces(selector)
|
||||||
.workplane()
|
.workplane()
|
||||||
.circle(self.diam_connector_external / 2)
|
.circle(self.joint.diam_connector_external() / 2)
|
||||||
.extrude(self.insertion_length)
|
.extrude(self.insertion_length)
|
||||||
)
|
)
|
||||||
if not solid:
|
if not solid:
|
||||||
result = result.faces(">Z").hole(self.diam_connector_internal)
|
result = result.faces(">Z").hole(self.diam_connector_internal)
|
||||||
if not self.simplify_geometry:
|
if not self.simplify_geometry:
|
||||||
thread = self._external_thread().val()
|
thread = self.joint.external_thread(self.insertion_length).val()
|
||||||
result = (
|
result = (
|
||||||
result
|
result
|
||||||
.union(
|
.union(
|
||||||
|
@ -193,11 +221,11 @@ class Handle:
|
||||||
result
|
result
|
||||||
.faces(">Z")
|
.faces(">Z")
|
||||||
.workplane()
|
.workplane()
|
||||||
.circle(self.diam_connector_external / 2)
|
.circle(self.joint.diam_connector_external() / 2)
|
||||||
.extrude(self.insertion_length)
|
.extrude(self.insertion_length)
|
||||||
)
|
)
|
||||||
if not self.simplify_geometry:
|
if not self.simplify_geometry:
|
||||||
thread = self._external_thread().val()
|
thread = self.joint.external_thread(self.insertion_length).val()
|
||||||
result = (
|
result = (
|
||||||
result
|
result
|
||||||
.union(
|
.union(
|
||||||
|
@ -215,7 +243,7 @@ class Handle:
|
||||||
result = (
|
result = (
|
||||||
Cq.Workplane('XY')
|
Cq.Workplane('XY')
|
||||||
.cylinder(
|
.cylinder(
|
||||||
radius=self.diam_connector_external / 2,
|
radius=self.joint.diam_connector_external / 2,
|
||||||
height=length,
|
height=length,
|
||||||
centered=(True, True, False),
|
centered=(True, True, False),
|
||||||
)
|
)
|
||||||
|
@ -223,7 +251,7 @@ class Handle:
|
||||||
result.faces(">Z").tag("mate")
|
result.faces(">Z").tag("mate")
|
||||||
result.faces("<Z").tag("base")
|
result.faces("<Z").tag("base")
|
||||||
if not self.simplify_geometry:
|
if not self.simplify_geometry:
|
||||||
thread = self._external_thread(length=length).val()
|
thread = self.joint.external_thread(length=length).val()
|
||||||
result = (
|
result = (
|
||||||
result
|
result
|
||||||
.union(thread)
|
.union(thread)
|
||||||
|
|
|
@ -127,9 +127,6 @@ class Parameters(Model):
|
||||||
trident_handle: Handle = field(default_factory=lambda: Handle(
|
trident_handle: Handle = field(default_factory=lambda: Handle(
|
||||||
diam=38,
|
diam=38,
|
||||||
diam_inner=38-2 * 25.4/8,
|
diam_inner=38-2 * 25.4/8,
|
||||||
# M27-3
|
|
||||||
diam_threading=27,
|
|
||||||
thread_pitch=3,
|
|
||||||
diam_connector_internal=18,
|
diam_connector_internal=18,
|
||||||
simplify_geometry=False,
|
simplify_geometry=False,
|
||||||
))
|
))
|
||||||
|
|
Loading…
Reference in New Issue