cosplay: Touhou/Houjuu Nue #4
|
@ -63,6 +63,7 @@ class ShoulderJoint(Model):
|
||||||
axis_rotate_top: float = -225.0
|
axis_rotate_top: float = -225.0
|
||||||
|
|
||||||
directrix_id: int = 0
|
directrix_id: int = 0
|
||||||
|
angle_neutral: float = 10.0
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
assert self.parent_lip_length * 2 < self.height
|
assert self.parent_lip_length * 2 < self.height
|
||||||
|
@ -189,8 +190,8 @@ class ShoulderJoint(Model):
|
||||||
)
|
)
|
||||||
theta = self.torsion_joint.spring.angle_neutral - self.torsion_joint.rider_slot_span
|
theta = self.torsion_joint.spring.angle_neutral - self.torsion_joint.rider_slot_span
|
||||||
loc_rotate = Cq.Location((0, 0, 0), (1, 0, 0), 180)
|
loc_rotate = Cq.Location((0, 0, 0), (1, 0, 0), 180)
|
||||||
loc_axis_rotate_bot = Cq.Location((0, 0, 0), (0, 0, 1), self.axis_rotate_bot)
|
loc_axis_rotate_bot = Cq.Location((0, 0, 0), (0, 0, 1), self.axis_rotate_bot + self.angle_neutral)
|
||||||
loc_axis_rotate_top = Cq.Location((0, 0, 0), (0, 0, 1), self.axis_rotate_top)
|
loc_axis_rotate_top = Cq.Location((0, 0, 0), (0, 0, 1), self.axis_rotate_top + self.angle_neutral)
|
||||||
result = (
|
result = (
|
||||||
Cq.Assembly()
|
Cq.Assembly()
|
||||||
.add(core, name="core", loc=Cq.Location())
|
.add(core, name="core", loc=Cq.Location())
|
||||||
|
|
|
@ -93,6 +93,8 @@ class WingProfile(Model):
|
||||||
self.wrist_s = math.sin(self.wrist_theta)
|
self.wrist_s = math.sin(self.wrist_theta)
|
||||||
self.wrist_top_x, self.wrist_top_y = self.wrist_to_abs(0, self.wrist_height)
|
self.wrist_top_x, self.wrist_top_y = self.wrist_to_abs(0, self.wrist_height)
|
||||||
|
|
||||||
|
self.shoulder_joint.angle_neutral = -self.shoulder_angle_neutral
|
||||||
|
|
||||||
@submodel(name="shoulder-joint")
|
@submodel(name="shoulder-joint")
|
||||||
def submodel_shoulder_joint(self) -> Model:
|
def submodel_shoulder_joint(self) -> Model:
|
||||||
return self.shoulder_joint
|
return self.shoulder_joint
|
||||||
|
@ -180,6 +182,17 @@ class WingProfile(Model):
|
||||||
#)
|
#)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def shoulder_angle_neutral(self) -> float:
|
||||||
|
"""
|
||||||
|
Returns the neutral angle of the shoulder
|
||||||
|
"""
|
||||||
|
dx = self.shoulder_mid_x - self.shoulder_tip_x
|
||||||
|
dy = -(self.shoulder_mid_y - (self.shoulder_tip_y - self.shoulder_width))
|
||||||
|
result = math.degrees(math.atan2(dy, dx))
|
||||||
|
assert result >= 0
|
||||||
|
return result
|
||||||
|
|
||||||
@target(name="profile-s0", kind=TargetKind.DXF)
|
@target(name="profile-s0", kind=TargetKind.DXF)
|
||||||
def profile_s0(self) -> Cq.Sketch:
|
def profile_s0(self) -> Cq.Sketch:
|
||||||
tip_x = self.shoulder_tip_x
|
tip_x = self.shoulder_tip_x
|
||||||
|
@ -270,10 +283,17 @@ class WingProfile(Model):
|
||||||
def surface_s0(self, top: bool = False) -> Cq.Workplane:
|
def surface_s0(self, top: bool = False) -> Cq.Workplane:
|
||||||
base_dx = -(self.base_width - self.base_plate_width) / 2
|
base_dx = -(self.base_width - self.base_plate_width) / 2
|
||||||
base_dy = self.base_joint.joint_height
|
base_dy = self.base_joint.joint_height
|
||||||
|
sw = self.shoulder_width
|
||||||
|
|
||||||
axle_dist = self.shoulder_joint.parent_lip_ext
|
axle_dist = self.shoulder_joint.parent_lip_ext
|
||||||
|
theta = math.radians(self.shoulder_joint.angle_neutral)
|
||||||
|
c, s = math.cos(-theta), math.sin(-theta)
|
||||||
tags = [
|
tags = [
|
||||||
("shoulder", (self.shoulder_tip_x + axle_dist, self.shoulder_tip_y - self.shoulder_width), 0),
|
# transforms [axle_dist, -sw/2] about the centre (tip_x, tip_y - sw/2)
|
||||||
|
("shoulder", (
|
||||||
|
self.shoulder_tip_x + axle_dist * c + (-sw/2) * s,
|
||||||
|
self.shoulder_tip_y - sw / 2 - axle_dist * s + (-sw/2) * c),
|
||||||
|
self.shoulder_joint.angle_neutral),
|
||||||
("base", (base_dx, base_dy), 90),
|
("base", (base_dx, base_dy), 90),
|
||||||
]
|
]
|
||||||
result = nhf.utils.extrude_with_markers(
|
result = nhf.utils.extrude_with_markers(
|
||||||
|
|
Loading…
Reference in New Issue