Cosplay/nhf/touhou/yasaka_kanako/shimenawa.py

237 lines
6.7 KiB
Python

from nhf.build import Model, TargetKind, target, assembly, submodel
from nhf.materials import Role, Material
import nhf.utils
from nhf.parts.fasteners import FlatHeadBolt, HexNut, Washer
from nhf.parts.electronics import ArduinoUnoR3, BatteryBox18650
from typing import Optional, Union
import math
from dataclasses import dataclass, field
import cadquery as Cq
BOLT_COMMON = FlatHeadBolt(
# FIXME: weigh
mass=0.0,
diam_head=12.8,
height_head=2.8,
diam_thread=6.0,
height_thread=30.0,
pitch=1.0,
)
@dataclass
class Shimenawa(Model):
"""
The ring
"""
diam_inner: float = 43.0
diam_outer: float = 43.0 + 9 * 2
diam_hole_outer: float = 8.0
hole_ext: float = 2.0
hole_z: float = 15.0
pipe_fitting_angle_span: float = 6.0
pipe_joint_length: float = 120.0
pipe_joint_outer_thickness: float = 8.0
pipe_joint_inner_thickness: float = 4.0
pipe_joint_inner_angle_span: float = 120.0
pipe_joint_taper: float = 5.0
pipe_joint_taper_length: float = 10.0
ear_dr: float = 6.0
ear_hole_diam: float = 10.0
ear_radius: float = 12.0
ear_thickness: float = 10.0
main_circumference: float = 3600.0
material_fitting: Material = Material.PLASTIC_PLA
def __post_init__(self):
assert self.diam_inner < self.diam_outer
@property
def main_radius(self) -> float:
return self.main_circumference / (2 * math.pi)
@target(name="pipe-fitting-curved")
def pipe_fitting_curved(self) -> Cq.Workplane:
r_minor = self.diam_outer/2 + self.pipe_joint_outer_thickness
a1 = self.pipe_fitting_angle_span
outer = Cq.Solid.makeTorus(
radius1=self.main_radius,
radius2=r_minor,
)
inner = Cq.Solid.makeTorus(
radius1=self.main_radius,
radius2=self.diam_outer/2,
)
angle_intersector = Cq.Solid.makeCylinder(
radius=self.main_radius + r_minor,
height=r_minor*2,
angleDegrees=a1,
pnt=(0,0,-r_minor)
).rotate((0,0,0),(0,0,1),-a1/2)
result = (outer - inner) * angle_intersector
ear_outer = Cq.Solid.makeCylinder(
radius=self.ear_radius,
height=self.ear_thickness,
)
ear_hole = Cq.Solid.makeCylinder(
radius=self.ear_hole_diam/2,
height=self.ear_thickness,
)
ear = (ear_outer - ear_hole).moved(self.main_radius - r_minor - self.ear_dr, 0, 0)
result += ear - inner
return result
@target(name="pipe-joint-outer")
def pipe_joint_outer(self) -> Cq.Workplane:
"""
Used to joint two pipes together (outside)
"""
r1 = self.diam_outer / 2 + self.pipe_joint_outer_thickness
h = self.pipe_joint_length
result = (
Cq.Workplane()
.cylinder(
radius=r1,
height=self.pipe_joint_length,
)
)
cut_interior = Cq.Solid.makeCylinder(
radius=self.diam_outer/2,
height=h,
pnt=(0, 0, -h/2)
)
rh = r1 + self.hole_ext
add_hole = Cq.Solid.makeCylinder(
radius=self.diam_hole_outer/2,
height=rh*2,
pnt=(-rh, 0, 0),
dir=(1, 0, 0),
)
cut_hole = Cq.Solid.makeCylinder(
radius=BOLT_COMMON.diam_thread/2,
height=rh*2,
pnt=(-rh, 0, 0),
dir=(1, 0, 0),
)
z = self.hole_z
result = (
result
+ add_hole.moved(0, 0, -z)
+ add_hole.moved(0, 0, z)
- cut_hole.moved(0, 0, -z)
- cut_hole.moved(0, 0, z)
- cut_interior
)
return result
@target(name="pipe-joint-inner")
def pipe_joint_inner(self) -> Cq.Workplane:
"""
Used to joint two pipes together (inside)
"""
r1 = self.diam_inner / 2
r2 = r1 - self.pipe_joint_taper
r3 = r2 - self.pipe_joint_inner_thickness
h = self.pipe_joint_length
h0 = h - self.pipe_joint_taper_length*2
core = Cq.Solid.makeCylinder(
radius=r2,
height=h0/2,
)
centre_cut = Cq.Solid.makeCylinder(
radius=r3,
height=h0/2,
)
taper = Cq.Solid.makeCone(
radius1=r2,
radius2=r1,
height=(h - h0) / 2,
pnt=(0, 0, h0/2),
)
centre_cut_taper = Cq.Solid.makeCone(
radius1=r3,
radius2=r3 + self.pipe_joint_taper,
height=(h - h0) / 2,
pnt=(0, 0, h0/2),
)
angle_intersector = Cq.Solid.makeCylinder(
radius=r1,
height=h,
angleDegrees=self.pipe_joint_inner_angle_span
).rotate((0,0,0), (0,0,1), -self.pipe_joint_inner_angle_span/2)
result = (taper + core - centre_cut - centre_cut_taper) * angle_intersector
result += result.mirror("XY")
add_hole = Cq.Solid.makeCylinder(
radius=self.diam_hole_outer/2,
height=self.hole_ext,
pnt=(r3, 0, 0),
dir=(-1, 0, 0),
)
cut_hole = Cq.Solid.makeCylinder(
radius=BOLT_COMMON.diam_thread/2,
height=r1,
pnt=(0, 0, 0),
dir=(r1, 0, 0),
)
z = self.hole_z
result = (
result
+ add_hole.moved(0, 0, z)
+ add_hole.moved(0, 0, -z)
- cut_hole.moved(0, 0, z)
- cut_hole.moved(0, 0, -z)
)
return result
@assembly()
def assembly_pipe_joint(self) -> Cq.Assembly:
a = (
Cq.Assembly()
.addS(
self.pipe_joint_outer(),
name="joint_outer",
material=self.material_fitting,
role=Role.STRUCTURE,
)
.addS(
self.pipe_joint_inner(),
name="joint_inner1",
material=self.material_fitting,
role=Role.STRUCTURE,
)
.addS(
self.pipe_joint_inner(),
name="joint_inner2",
material=self.material_fitting,
role=Role.STRUCTURE,
loc=Cq.Location.rot2d(180),
)
)
return a
@assembly()
def assembly(self) -> Cq.Assembly:
a = (
Cq.Assembly()
.addS(
self.pipe_fitting_curved(),
name="fitting1",
material=self.material_fitting,
role=Role.STRUCTURE,
)
.add(
self.assembly_pipe_joint(),
name="pipe_joint",
)
)
return a