cosplay: Touhou/Houjuu Nue #4
|
@ -65,8 +65,6 @@ class Parameters(Model):
|
|||
shoulder_joint=MJ.ShoulderJoint(
|
||||
height=100.0,
|
||||
),
|
||||
elbow_joint=MJ.ElbowJoint(),
|
||||
wrist_joint=MJ.ElbowJoint(),
|
||||
elbow_height=110.0,
|
||||
))
|
||||
|
||||
|
|
|
@ -261,18 +261,22 @@ class Beam:
|
|||
plane.moveTo(-dx, 0).tagPlane("conn0")
|
||||
return result
|
||||
|
||||
def beam(self) -> Cq.Assembly:
|
||||
def generate(self, flip: bool = False) -> Cq.Assembly:
|
||||
beam = (
|
||||
Cq.Workplane('XZ')
|
||||
.box(self.spine_length, self.spine_thickness, self.spine_height)
|
||||
)
|
||||
h = self.spine_height / 2 + self.foot_height
|
||||
|
||||
tag_p, tag_n = "top", "bot"
|
||||
if flip:
|
||||
tag_p, tag_n = tag_n, tag_p
|
||||
result = (
|
||||
Cq.Assembly()
|
||||
.add(beam, name="beam")
|
||||
.add(self.foot(), name="top",
|
||||
.add(self.foot(), name=tag_p,
|
||||
loc=Cq.Location((0, h, 0)))
|
||||
.add(self.foot(), name="bot",
|
||||
.add(self.foot(), name=tag_n,
|
||||
loc=Cq.Location((0, -h, 0), (1, 0, 0), 180))
|
||||
)
|
||||
return result
|
||||
|
@ -301,7 +305,7 @@ class DiskJoint(Model):
|
|||
#disk_thickness_gap: float = 0.1
|
||||
|
||||
# Spring angle at 0 degrees of movement
|
||||
spring_angle_at_0: float = 30.0
|
||||
spring_angle_at_0: float = 60.0
|
||||
spring_slot_offset: float = 15.0
|
||||
|
||||
wall_inset: float = 2.0
|
||||
|
@ -493,6 +497,7 @@ class DiskJoint(Model):
|
|||
disk: str,
|
||||
angle: float = 0.0,
|
||||
) -> Cq.Assembly:
|
||||
assert 0 <= angle <= self.movement_angle
|
||||
deflection = angle - self.neutral_movement_angle
|
||||
spring_name = disk.replace("/", "__Z") + "_spring"
|
||||
(
|
||||
|
@ -541,7 +546,7 @@ class DiskJoint(Model):
|
|||
return result.solve()
|
||||
|
||||
|
||||
@dataclass
|
||||
@dataclass(kw_only=True)
|
||||
class ElbowJoint:
|
||||
"""
|
||||
Creates the elbow and wrist joints.
|
||||
|
@ -576,6 +581,9 @@ class ElbowJoint:
|
|||
|
||||
material: Material = Material.RESIN_TRANSPERENT
|
||||
|
||||
# If true, flip the top and bottom tags
|
||||
flip: bool = False
|
||||
|
||||
def __post_init__(self):
|
||||
assert self.child_arm_radius > self.disk_joint.radius_housing
|
||||
assert self.parent_arm_radius > self.disk_joint.radius_housing
|
||||
|
@ -605,7 +613,7 @@ class ElbowJoint:
|
|||
flip_x = Cq.Location((0, 0, 0), (1, 0, 0), 180)
|
||||
flip_z = Cq.Location((0, 0, 0), (0, 0, 1), 180)
|
||||
result = (
|
||||
self.child_beam.beam()
|
||||
self.child_beam.generate(flip=self.flip)
|
||||
.add(self.disk_joint.disk(), name="disk",
|
||||
loc=flip_x * flip_z * Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle))
|
||||
#.constrain("disk", "Fixed")
|
||||
|
@ -641,7 +649,7 @@ class ElbowJoint:
|
|||
-self.disk_joint.tongue_span / 2
|
||||
)
|
||||
result = (
|
||||
self.parent_beam.beam()
|
||||
self.parent_beam.generate(flip=self.flip)
|
||||
.add(housing, name="housing",
|
||||
loc=axial_offset * housing_loc)
|
||||
.add(connector, name="connector",
|
||||
|
|
|
@ -11,10 +11,10 @@ from nhf import Material, Role
|
|||
from nhf.build import Model, target, assembly
|
||||
from nhf.parts.box import box_with_centre_holes, MountingBox, Hole
|
||||
from nhf.parts.joints import HirthJoint
|
||||
from nhf.touhou.houjuu_nue.joints import ShoulderJoint, ElbowJoint
|
||||
from nhf.touhou.houjuu_nue.joints import ShoulderJoint, ElbowJoint, DiskJoint
|
||||
import nhf.utils
|
||||
|
||||
@dataclass
|
||||
@dataclass(kw_only=True)
|
||||
class WingProfile(Model):
|
||||
|
||||
name: str = "wing"
|
||||
|
@ -34,7 +34,12 @@ class WingProfile(Model):
|
|||
|
||||
s1_thickness: float = 25.0
|
||||
|
||||
elbow_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint())
|
||||
elbow_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
|
||||
disk_joint=DiskJoint(
|
||||
movement_angle=55,
|
||||
),
|
||||
flip=False,
|
||||
))
|
||||
elbow_height: float = 100
|
||||
elbow_x: float = 240
|
||||
elbow_y: float = 30
|
||||
|
@ -43,7 +48,12 @@ class WingProfile(Model):
|
|||
|
||||
s2_thickness: float = 25.0
|
||||
|
||||
wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint())
|
||||
wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
|
||||
disk_joint=DiskJoint(
|
||||
movement_angle=45,
|
||||
),
|
||||
flip=True,
|
||||
))
|
||||
wrist_height: float = 70
|
||||
# Bottom point of the wrist
|
||||
wrist_x: float = 400
|
||||
|
@ -548,6 +558,8 @@ class WingProfile(Model):
|
|||
parts: Optional[list[str]] = None,
|
||||
angle_elbow_wrist: float = 0.0,
|
||||
) -> Cq.Assembly():
|
||||
assert not self.elbow_joint.flip
|
||||
assert self.wrist_joint.flip
|
||||
if parts is None:
|
||||
parts = ["s0", "shoulder", "s1", "elbow", "s2", "wrist", "s3"]
|
||||
result = (
|
||||
|
@ -601,20 +613,20 @@ class WingProfile(Model):
|
|||
# Mounted backwards to bend in other direction
|
||||
(
|
||||
result
|
||||
.constrain("s2/wrist_top?conn0", "wrist/parent_upper/bot?conn0", "Plane")
|
||||
.constrain("s2/wrist_top?conn1", "wrist/parent_upper/bot?conn1", "Plane")
|
||||
.constrain("s2/wrist_bot?conn0", "wrist/parent_upper/top?conn0", "Plane")
|
||||
.constrain("s2/wrist_bot?conn1", "wrist/parent_upper/top?conn1", "Plane")
|
||||
.constrain("s2/wrist_top?conn0", "wrist/parent_upper/top?conn0", "Plane")
|
||||
.constrain("s2/wrist_top?conn1", "wrist/parent_upper/top?conn1", "Plane")
|
||||
.constrain("s2/wrist_bot?conn0", "wrist/parent_upper/bot?conn0", "Plane")
|
||||
.constrain("s2/wrist_bot?conn1", "wrist/parent_upper/bot?conn1", "Plane")
|
||||
)
|
||||
if "s3" in parts:
|
||||
result.add(self.assembly_s3(), name="s3")
|
||||
if "s3" in parts and "wrist" in parts:
|
||||
(
|
||||
result
|
||||
.constrain("s3/wrist_top?conn0", "wrist/child/bot?conn0", "Plane")
|
||||
.constrain("s3/wrist_top?conn1", "wrist/child/bot?conn1", "Plane")
|
||||
.constrain("s3/wrist_bot?conn0", "wrist/child/top?conn0", "Plane")
|
||||
.constrain("s3/wrist_bot?conn1", "wrist/child/top?conn1", "Plane")
|
||||
.constrain("s3/wrist_top?conn0", "wrist/child/top?conn0", "Plane")
|
||||
.constrain("s3/wrist_top?conn1", "wrist/child/top?conn1", "Plane")
|
||||
.constrain("s3/wrist_bot?conn0", "wrist/child/bot?conn0", "Plane")
|
||||
.constrain("s3/wrist_bot?conn1", "wrist/child/bot?conn1", "Plane")
|
||||
)
|
||||
if len(parts) > 1:
|
||||
result.solve()
|
||||
|
|
Loading…
Reference in New Issue