cosplay: Touhou/Houjuu Nue #4

Open
aniva wants to merge 189 commits from touhou/houjuu-nue into main
2 changed files with 97 additions and 57 deletions
Showing only changes of commit 48cfd52455 - Show all commits

View File

@ -87,6 +87,11 @@ class Parameters(Model):
hs_joint_axis_cbore_diam: float = 20
hs_joint_axis_cbore_depth: float = 3
wing_profile: MW.WingProfile = field(default_factory=lambda: MW.WingProfile(
shoulder_height = 100,
elbow_height = 120,
))
# Exterior radius of the wing root assembly
wing_root_radius: float = 40
wing_root_wall_thickness: float = 8
@ -347,6 +352,15 @@ class Parameters(Model):
result.moveTo(0, self.shoulder_attach_dist).tagPlane('conn1')
return result
@property
def shoulder_joint_child_height(self) -> float:
"""
Calculates the y distance between two joint surfaces on the child side
of the shoulder joint.
"""
joint = self.shoulder_torsion_joint
return self.wing_s0_height - 2 * joint.total_height + 2 * joint.rider_disk_height
@target(name="shoulder_joint_child")
def shoulder_joint_child(self) -> Cq.Assembly:
"""
@ -470,18 +484,18 @@ class Parameters(Model):
.finalize()
.extrude(self.wing_s1_spacer_thickness)
)
result.faces("<Z").tag("mate1")
result.faces(">Z").tag("mate2")
result.faces("<Z").tag("weld1")
result.faces(">Z").tag("weld2")
result.faces(">Y").tag("dir")
return result
@target(name="wing/s1-shoulder-spacer", kind=TargetKind.DXF)
def wing_s1_shoulder_spacer(self, flipped=False) -> Cq.Workplane:
def wing_s1_shoulder_spacer(self) -> Cq.Workplane:
"""
if `flipped = True`, tag on the bottom face. This does not change the
geometry.
The mate tags are on the side closer to the holes.
"""
dx = self.wing_s1_shoulder_spacer_hole_dist
h = self.wing_s1_spacer_thickness
result = (
Cq.Workplane('XZ')
.sketch()
@ -493,33 +507,35 @@ class Parameters(Model):
])
.circle(self.wing_s1_spacer_hole_diam / 2, mode='s')
.finalize()
.extrude(self.wing_s1_spacer_thickness)
.extrude(h)
)
# Tag the mating surfaces to be glued
result.faces("<Z").tag("mate1")
result.faces(">Z").tag("mate2")
result.faces("<Z").workplane().moveTo(0, h).tagPlane("weld1")
result.faces(">Z").workplane().moveTo(0, -h).tagPlane("weld2")
# Tag the directrix
result.faces("<Y").tag("dir")
# Tag the holes
plane = result.faces("<Y" if flipped else ">Y").workplane()
plane = result.faces(">Y").workplane()
# Side closer to the parent is 0
plane.moveTo(dx if flipped else -dx, 0).tagPlane("conn0")
plane.moveTo(-dx, 0).tagPlane("conn0")
plane.tagPlane("conn1")
return result
@target(name="wing/r1s1", kind=TargetKind.DXF)
def wing_r1s1_profile(self) -> Cq.Sketch:
return MW.wing_r1s1_profile()
return self.wing_profile.wing_r1s1_profile()
def wing_r1s1_panel(self, front=True) -> Cq.Workplane:
profile = self.wing_r1s1_profile()
w = self.wing_s1_shoulder_spacer_width / 2
h = (self.wing_profile.shoulder_height - self.shoulder_joint_child_height) / 2
anchors = [
("shoulder_top", 10, 55),
("shoulder_bot", 10, 5),
("shoulder_top", w, h + self.shoulder_joint_child_height),
("shoulder_bot", w, h),
("middle", 50, -20),
("tip", 390, -150),
("tip", 270, 50),
]
result = (
Cq.Workplane("XY")
@ -543,25 +559,30 @@ class Parameters(Model):
color=self.material_panel.color)
.constrain("panel_front@faces@>Z", "panel_back@faces@<Z", "Point",
param=self.wing_s1_thickness)
)
for tag in ["shoulder_top", "shoulder_bot"]:
name = f"{tag}_spacer"
flipped = tag.endswith("top")
(
result
.add(self.wing_s1_shoulder_spacer(flipped=flipped), name=name,
.add(self.wing_s1_shoulder_spacer(),
name="shoulder_bot_spacer",
color=self.material_bracket.color)
.constrain(f"panel_front?{tag}", f"{name}?mate1", "Plane")
.constrain(f"panel_back?{tag}", f"{name}?mate2", "Plane")
.constrain(f"{name}?dir", "FixedAxis", param=(0, 1, 0))
.constrain("panel_front?shoulder_bot", "shoulder_bot_spacer?weld1", "Plane")
.constrain("panel_back?shoulder_bot", "shoulder_bot_spacer?weld2", "Plane")
.constrain("shoulder_bot_spacer?dir", "FixedAxis", param=(0, 1, 0))
.add(self.wing_s1_shoulder_spacer(),
name="shoulder_top_spacer",
color=self.material_bracket.color)
.constrain("panel_front?shoulder_top", "shoulder_top_spacer?weld2", "Plane")
.constrain("panel_back?shoulder_top", "shoulder_top_spacer?weld1", "Plane")
.constrain("shoulder_top_spacer?dir", "FixedAxis", param=(0, -1, 0))
# Should be controlled by point value directly
#.constrain("shoulder_bot_spacer?dir", "shoulder_top_spacer?dir", "Point",
# self.shoulder_joint_child_height)
)
for tag in ["middle", "tip"]:
name = f"{tag}_spacer"
(
result
.add(self.wing_s1_spacer(), name=f"{tag}_spacer",
.add(self.wing_s1_spacer(), name=name,
color=self.material_bracket.color)
.constrain(f"panel_front?{tag}", f"{tag}_spacer?mate1", "Plane")
.constrain(f"panel_back?{tag}", f"{tag}_spacer?mate2", "Plane")
.constrain(f"panel_front?{tag}", f"{tag}_spacer?weld1", "Plane")
.constrain(f"panel_back?{tag}", f"{tag}_spacer?weld2", "Plane")
.constrain(f"{name}?dir", "FixedAxis", param=(0, 1, 0))
)
return result.solve()

View File

@ -3,11 +3,13 @@ This file describes the shapes of the wing shells. The joints are defined in
`__init__.py`.
"""
import math
from dataclasses import dataclass
import cadquery as Cq
from nhf import Material, Role
from nhf.parts.joints import HirthJoint
import nhf.utils
def wing_root_profiles(
base_sweep=150,
wall_thickness=8,
@ -227,32 +229,49 @@ def wing_root(joint: HirthJoint,
)
return result
def wing_r1s1_profile() -> Cq.Sketch:
@dataclass
class WingProfile:
shoulder_height: float = 100
elbow_height: float = 120
def wing_r1s1_profile(self) -> Cq.Sketch:
"""
Generates the first wing segment profile, with the wing root pointing in
the positive x axis.
"""
# Depression of the wing middle
h = 100
w = 400
bend = 200
w = 270
# Depression of the wing middle, measured
h = 0
# spline curve easing extension
theta = math.radians(30)
c_th, s_th = math.cos(theta), math.sin(theta)
bend = 30
ext = 40
ext_dh = -5
assert ext * 2 < w
factor = 0.7
result = (
Cq.Sketch()
.segment((0, 0), (0, h))
.segment((0, 0), (0, self.shoulder_height))
.spline([
(0, h),
(0.5 * w, h - factor * bend),
(w, h - bend),
(0, self.shoulder_height),
((w - s_th * self.elbow_height) / 2, self.shoulder_height / 2 + (self.elbow_height * c_th - h) / 2 - bend),
(w - s_th * self.elbow_height, self.elbow_height * c_th - h),
])
.segment(
(w, h - bend),
(w, -bend),
(w - s_th * self.elbow_height, self.elbow_height * c_th -h),
(w, -h),
)
.spline([
(w, - bend),
(0.5 * w, - factor * bend),
(0, 0),
(w / 2, -h / 2 - bend),
(w, -h),
])
.assemble()
)