cosplay: Touhou/Houjuu Nue #4

Open
aniva wants to merge 189 commits from touhou/houjuu-nue into main
2 changed files with 38 additions and 34 deletions
Showing only changes of commit 7e7b9e1f64 - Show all commits

View File

@ -634,12 +634,15 @@ class ElbowJoint(Model):
axle is at position 0, and parent direction is -X
"""
return Cq.Location.from2d(-self.parent_arm_radius, 0, 0)
def child_arm_loc(self) -> Cq.Location:
def child_arm_loc(self, flip: bool = False) -> Cq.Location:
"""
2d Location of the centre of the arm surface on the child side, assuming
axle is at position 0, and parent direction is -X
Set `flip=True` to indicate that the joint is supposed to be installed upside down
"""
return Cq.Location.rot2d(self.angle_neutral) * Cq.Location.from2d(self.child_arm_radius, 0, 180)
result = Cq.Location.rot2d(self.angle_neutral) * Cq.Location.from2d(self.child_arm_radius, 0, 180)
return result.flip_y() if flip else result
def lip(self) -> Cq.Workplane:
holes = [

View File

@ -62,7 +62,7 @@ class WingProfile(Model):
wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
disk_joint=DiskJoint(
movement_angle=45,
movement_angle=30,
radius_disk=13.0,
radius_housing=15.0,
),
@ -91,6 +91,7 @@ class WingProfile(Model):
elbow_rotate: float = -5.0
wrist_rotate: float = 30.0
# False for the right side, True for the left side
flip: bool = False
def __post_init__(self):
@ -447,9 +448,9 @@ class WingProfile(Model):
h = self.elbow_height / 2
loc_elbow = Cq.Location.rot2d(self.elbow_rotate) * self.elbow_joint.parent_arm_loc()
tags_elbow = [
("elbow_bot", self.elbow_axle_loc * loc_elbow *\
("elbow_bot", self.elbow_axle_loc * loc_elbow *
Cq.Location.from2d(0, -self.elbow_h2)),
("elbow_top", self.elbow_axle_loc * loc_elbow *\
("elbow_top", self.elbow_axle_loc * loc_elbow *
Cq.Location.from2d(0, self.elbow_h2)),
]
profile = self.profile_s1()
@ -512,19 +513,19 @@ class WingProfile(Model):
return profile
def surface_s2(self, front: bool = True) -> Cq.Workplane:
h = self.elbow_height / 2
loc_elbow = Cq.Location.rot2d(self.elbow_rotate) * self.elbow_joint.child_arm_loc()
loc_elbow = Cq.Location.rot2d(self.elbow_rotate) * self.elbow_joint.child_arm_loc(flip=self.flip)
tags_elbow = [
("elbow_bot", self.elbow_axle_loc * loc_elbow *\
("elbow_bot", self.elbow_axle_loc * loc_elbow *
Cq.Location.from2d(0, self.elbow_h2)),
("elbow_top", self.elbow_axle_loc * loc_elbow *\
("elbow_top", self.elbow_axle_loc * loc_elbow *
Cq.Location.from2d(0, -self.elbow_h2)),
]
h = self.wrist_height / 2
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.parent_arm_loc().flip_y()
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.parent_arm_loc()
tags_wrist = [
("wrist_bot", self.wrist_axle_loc * loc_wrist *\
("wrist_bot", self.wrist_axle_loc * loc_wrist *
Cq.Location.from2d(0, -self.wrist_h2)),
("wrist_top", self.wrist_axle_loc * loc_wrist *\
("wrist_top", self.wrist_axle_loc * loc_wrist *
Cq.Location.from2d(0, self.wrist_h2)),
]
profile = self.profile_s2()
@ -580,11 +581,11 @@ class WingProfile(Model):
def surface_s3(self,
front: bool = True) -> Cq.Workplane:
h = self.wrist_height / 2
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.child_arm_loc().flip_y()
loc_wrist = Cq.Location.rot2d(self.wrist_rotate) * self.wrist_joint.child_arm_loc(flip=not self.flip)
tags = [
("wrist_bot", self.wrist_axle_loc * loc_wrist *\
("wrist_bot", self.wrist_axle_loc * loc_wrist *
Cq.Location.from2d(0, self.wrist_h2)),
("wrist_top", self.wrist_axle_loc * loc_wrist *\
("wrist_top", self.wrist_axle_loc * loc_wrist *
Cq.Location.from2d(0, -self.wrist_h2)),
]
profile = self.profile_s3()
@ -662,42 +663,42 @@ class WingProfile(Model):
if "s1" in parts and "elbow" in parts:
(
result
.constrain("s1/elbow_top?conn0", "elbow/parent_upper/lip?conn_top0", "Plane")
.constrain("s1/elbow_top?conn1", "elbow/parent_upper/lip?conn_top1", "Plane")
.constrain("s1/elbow_bot?conn0", "elbow/parent_upper/lip?conn_bot0", "Plane")
.constrain("s1/elbow_bot?conn1", "elbow/parent_upper/lip?conn_bot1", "Plane")
.constrain("s1/elbow_top?conn0", f"elbow/parent_upper/lip?conn_{tag_top}0", "Plane")
.constrain("s1/elbow_top?conn1", f"elbow/parent_upper/lip?conn_{tag_top}1", "Plane")
.constrain("s1/elbow_bot?conn0", f"elbow/parent_upper/lip?conn_{tag_bot}0", "Plane")
.constrain("s1/elbow_bot?conn1", f"elbow/parent_upper/lip?conn_{tag_bot}1", "Plane")
)
if "s2" in parts:
result.add(self.assembly_s2(), name="s2")
if "s2" in parts and "elbow" in parts:
(
result
.constrain("s2/elbow_top?conn0", "elbow/child/lip?conn_top0", "Plane")
.constrain("s2/elbow_top?conn1", "elbow/child/lip?conn_top1", "Plane")
.constrain("s2/elbow_bot?conn0", "elbow/child/lip?conn_bot0", "Plane")
.constrain("s2/elbow_bot?conn1", "elbow/child/lip?conn_bot1", "Plane")
.constrain("s2/elbow_top?conn0", f"elbow/child/lip?conn_{tag_top}0", "Plane")
.constrain("s2/elbow_top?conn1", f"elbow/child/lip?conn_{tag_top}1", "Plane")
.constrain("s2/elbow_bot?conn0", f"elbow/child/lip?conn_{tag_bot}0", "Plane")
.constrain("s2/elbow_bot?conn1", f"elbow/child/lip?conn_{tag_bot}1", "Plane")
)
if "wrist" in parts:
angle = self.wrist_joint.disk_joint.movement_angle * elbow_wrist_deflection
result.add(self.wrist_joint.assembly(angle=elbow_wrist_deflection), name="wrist")
result.add(self.wrist_joint.assembly(angle=angle), name="wrist")
if "s2" in parts and "wrist" in parts:
# Mounted backwards to bend in other direction
(
result
.constrain("s2/wrist_top?conn0", "wrist/parent_upper/lip?conn_bot0", "Plane")
.constrain("s2/wrist_top?conn1", "wrist/parent_upper/lip?conn_bot1", "Plane")
.constrain("s2/wrist_bot?conn0", "wrist/parent_upper/lip?conn_top0", "Plane")
.constrain("s2/wrist_bot?conn1", "wrist/parent_upper/lip?conn_top1", "Plane")
.constrain("s2/wrist_top?conn0", f"wrist/parent_upper/lip?conn_{tag_bot}0", "Plane")
.constrain("s2/wrist_top?conn1", f"wrist/parent_upper/lip?conn_{tag_bot}1", "Plane")
.constrain("s2/wrist_bot?conn0", f"wrist/parent_upper/lip?conn_{tag_top}0", "Plane")
.constrain("s2/wrist_bot?conn1", f"wrist/parent_upper/lip?conn_{tag_top}1", "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/lip?conn_bot0", "Plane")
.constrain("s3/wrist_top?conn1", "wrist/child/lip?conn_bot1", "Plane")
.constrain("s3/wrist_bot?conn0", "wrist/child/lip?conn_top0", "Plane")
.constrain("s3/wrist_bot?conn1", "wrist/child/lip?conn_top1", "Plane")
.constrain("s3/wrist_top?conn0", f"wrist/child/lip?conn_{tag_bot}0", "Plane")
.constrain("s3/wrist_top?conn1", f"wrist/child/lip?conn_{tag_bot}1", "Plane")
.constrain("s3/wrist_bot?conn0", f"wrist/child/lip?conn_{tag_top}0", "Plane")
.constrain("s3/wrist_bot?conn1", f"wrist/child/lip?conn_{tag_top}1", "Plane")
)
if len(parts) > 1:
result.solve()
@ -845,10 +846,10 @@ class WingL(WingProfile):
def __post_init__(self):
assert self.wrist_height <= self.shoulder_joint.height
self.wrist_bot_loc = self.wrist_bot_loc.with_angle_2d(self.wrist_angle)
self.elbow_joint.angle_neutral = -15.0
self.elbow_joint.angle_neutral = 15.0
self.elbow_rotate = 5.0
self.wrist_joint.angle_neutral = -self.wrist_bot_loc.to2d_rot() - 30.0
self.wrist_rotate = self.wrist_joint.angle_neutral
self.wrist_joint.angle_neutral = self.wrist_bot_loc.to2d_rot() + 30.0
self.wrist_rotate = -self.wrist_joint.angle_neutral
super().__post_init__()