diff --git a/nhf/touhou/houjuu_nue/__init__.py b/nhf/touhou/houjuu_nue/__init__.py index 64c248b..779cdb5 100644 --- a/nhf/touhou/houjuu_nue/__init__.py +++ b/nhf/touhou/houjuu_nue/__init__.py @@ -88,8 +88,8 @@ class Parameters(Model): hs_joint_axis_cbore_depth: float = 3 wing_profile: MW.WingProfile = field(default_factory=lambda: MW.WingProfile( - shoulder_height = 100, - elbow_height = 120, + shoulder_height = 80, + elbow_height = 100, )) # Exterior radius of the wing root assembly @@ -115,7 +115,6 @@ class Parameters(Model): joint. """ wing_s0_thickness: float = 40 - wing_s0_height: float = 100 # Length of the spacer wing_s1_thickness: float = 20 @@ -312,7 +311,7 @@ class Parameters(Model): shoulder_attach_dist=self.shoulder_attach_dist, shoulder_attach_diam=self.shoulder_attach_diam, wall_thickness=self.wing_root_wall_thickness, - conn_height=self.wing_s0_height, + conn_height=self.wing_profile.shoulder_height, conn_thickness=self.wing_s0_thickness, ) @@ -359,7 +358,7 @@ class Parameters(Model): of the shoulder joint. """ joint = self.shoulder_torsion_joint - return self.wing_s0_height - 2 * joint.total_height + 2 * joint.rider_disk_height + return self.wing_profile.shoulder_height - 2 * joint.total_height + 2 * joint.rider_disk_height @target(name="shoulder_joint_child") def shoulder_joint_child(self) -> Cq.Assembly: @@ -369,7 +368,7 @@ class Parameters(Model): joint = self.shoulder_torsion_joint # Half of the height of the bridging cylinder - dh = self.wing_s0_height / 2 - joint.total_height + dh = self.wing_profile.shoulder_height / 2 - joint.total_height core_start_angle = 30 core_end_angle1 = 90 core_end_angle2 = 180 @@ -525,7 +524,7 @@ class Parameters(Model): @target(name="wing/r1s1", kind=TargetKind.DXF) def wing_r1s1_profile(self) -> Cq.Sketch: - return self.wing_profile.wing_r1s1_profile() + return self.wing_profile.wing_r1_profile() def wing_r1s1_panel(self, front=True) -> Cq.Workplane: profile = self.wing_r1s1_profile() diff --git a/nhf/touhou/houjuu_nue/wing.py b/nhf/touhou/houjuu_nue/wing.py index 57e1198..b6551b8 100644 --- a/nhf/touhou/houjuu_nue/wing.py +++ b/nhf/touhou/houjuu_nue/wing.py @@ -234,7 +234,101 @@ def wing_root(joint: HirthJoint, class WingProfile: shoulder_height: float = 100 + elbow_height: float = 120 + elbow_x: float = 270 + elbow_y: float = 10 + # Angle of elbow w.r.t. y axis + elbow_angle: float = -20 + + wrist_height: float = 70 + # Bottom point of the wrist + wrist_x: float = 400 + wrist_y: float = 200 + + # Angle of wrist w.r.t. y axis. should be negative + wrist_angle: float = -40 + + # Extends from the wrist to the tip of the arrow + arrow_height: float = 300 + arrow_angle: float = 7 + + # Relative (in wrist coordinate) centre of the ring + ring_x: float = 40 + ring_y: float = 20 + ring_radius_inner: float = 22 + + def __post_init__(self): + assert self.ring_radius > self.ring_radius_inner + + @property + def ring_radius(self) -> float: + dx = self.ring_x + dy = self.ring_y + return (dx * dx + dy * dy) ** 0.5 + + def wing_r1_profile(self) -> Cq.Sketch: + wrist_theta = math.radians(self.wrist_angle) + wrist_s = math.sin(wrist_theta) + wrist_c = math.cos(wrist_theta) + wrist_top_x = self.wrist_x + self.wrist_height * wrist_s + wrist_top_y = self.wrist_y + self.wrist_height * wrist_c + elbow_theta = math.radians(self.elbow_angle) + elbow_top_x = self.elbow_x + self.elbow_height * math.sin(elbow_theta) + elbow_top_y = self.elbow_y + self.elbow_height * math.cos(elbow_theta) + result = ( + Cq.Sketch() + .segment( + (0, 0), + (0, self.shoulder_height), + tag="shoulder") + .arc( + (0, self.shoulder_height), + (elbow_top_x, elbow_top_y), + (wrist_top_x, wrist_top_y), + tag="s1_top") + #.segment( + # (self.wrist_x, self.wrist_y), + # (wrist_top_x, wrist_top_y), + # tag="wrist") + .arc( + (0, 0), + (self.elbow_x, self.elbow_y), + (self.wrist_x, self.wrist_y), + tag="s1_bot") + ) + arrow_theta = math.radians(self.arrow_angle) + arrow_x = self.wrist_x - self.arrow_height * wrist_s + arrow_y = self.wrist_y - self.arrow_height * wrist_c + arrow_tip_x = arrow_x + (self.arrow_height + self.wrist_height) * math.sin(arrow_theta + wrist_theta) + arrow_tip_y = arrow_y + (self.arrow_height + self.wrist_height) * math.cos(arrow_theta + wrist_theta) + result = ( + result + .segment( + (self.wrist_x, self.wrist_y), + (arrow_x, arrow_y) + ) + .segment( + (arrow_x, arrow_y), + (arrow_tip_x, arrow_tip_y) + ) + .segment( + (arrow_tip_x, arrow_tip_y), + (wrist_top_x, wrist_top_y) + ) + ) + # Carve out the ring + result = result.assemble() + ring_x = wrist_top_x + wrist_c * self.ring_x + wrist_s * self.ring_y + ring_y = wrist_top_y - wrist_s * self.ring_x + wrist_c * self.ring_y + result = ( + result + .push([(ring_x, ring_y)]) + .circle(self.ring_radius, mode='a') + .circle(self.ring_radius_inner, mode='s') + .clean() + ) + return result def wing_r1s1_profile(self) -> Cq.Sketch: """