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_diam: float = 20
hs_joint_axis_cbore_depth: float = 3 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 # Exterior radius of the wing root assembly
wing_root_radius: float = 40 wing_root_radius: float = 40
wing_root_wall_thickness: float = 8 wing_root_wall_thickness: float = 8
@ -347,6 +352,15 @@ class Parameters(Model):
result.moveTo(0, self.shoulder_attach_dist).tagPlane('conn1') result.moveTo(0, self.shoulder_attach_dist).tagPlane('conn1')
return result 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") @target(name="shoulder_joint_child")
def shoulder_joint_child(self) -> Cq.Assembly: def shoulder_joint_child(self) -> Cq.Assembly:
""" """
@ -470,18 +484,18 @@ class Parameters(Model):
.finalize() .finalize()
.extrude(self.wing_s1_spacer_thickness) .extrude(self.wing_s1_spacer_thickness)
) )
result.faces("<Z").tag("mate1") result.faces("<Z").tag("weld1")
result.faces(">Z").tag("mate2") result.faces(">Z").tag("weld2")
result.faces(">Y").tag("dir") result.faces(">Y").tag("dir")
return result return result
@target(name="wing/s1-shoulder-spacer", kind=TargetKind.DXF) @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 The mate tags are on the side closer to the holes.
geometry.
""" """
dx = self.wing_s1_shoulder_spacer_hole_dist dx = self.wing_s1_shoulder_spacer_hole_dist
h = self.wing_s1_spacer_thickness
result = ( result = (
Cq.Workplane('XZ') Cq.Workplane('XZ')
.sketch() .sketch()
@ -493,33 +507,35 @@ class Parameters(Model):
]) ])
.circle(self.wing_s1_spacer_hole_diam / 2, mode='s') .circle(self.wing_s1_spacer_hole_diam / 2, mode='s')
.finalize() .finalize()
.extrude(self.wing_s1_spacer_thickness) .extrude(h)
) )
# Tag the mating surfaces to be glued # Tag the mating surfaces to be glued
result.faces("<Z").tag("mate1") result.faces("<Z").workplane().moveTo(0, h).tagPlane("weld1")
result.faces(">Z").tag("mate2") result.faces(">Z").workplane().moveTo(0, -h).tagPlane("weld2")
# Tag the directrix # Tag the directrix
result.faces("<Y").tag("dir") result.faces("<Y").tag("dir")
# Tag the holes # Tag the holes
plane = result.faces("<Y" if flipped else ">Y").workplane() plane = result.faces(">Y").workplane()
# Side closer to the parent is 0 # 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") plane.tagPlane("conn1")
return result return result
@target(name="wing/r1s1", kind=TargetKind.DXF) @target(name="wing/r1s1", kind=TargetKind.DXF)
def wing_r1s1_profile(self) -> Cq.Sketch: 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: def wing_r1s1_panel(self, front=True) -> Cq.Workplane:
profile = self.wing_r1s1_profile() 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 = [ anchors = [
("shoulder_top", 10, 55), ("shoulder_top", w, h + self.shoulder_joint_child_height),
("shoulder_bot", 10, 5), ("shoulder_bot", w, h),
("middle", 50, -20), ("middle", 50, -20),
("tip", 390, -150), ("tip", 270, 50),
] ]
result = ( result = (
Cq.Workplane("XY") Cq.Workplane("XY")
@ -543,25 +559,30 @@ class Parameters(Model):
color=self.material_panel.color) color=self.material_panel.color)
.constrain("panel_front@faces@>Z", "panel_back@faces@<Z", "Point", .constrain("panel_front@faces@>Z", "panel_back@faces@<Z", "Point",
param=self.wing_s1_thickness) param=self.wing_s1_thickness)
) .add(self.wing_s1_shoulder_spacer(),
for tag in ["shoulder_top", "shoulder_bot"]: name="shoulder_bot_spacer",
name = f"{tag}_spacer"
flipped = tag.endswith("top")
(
result
.add(self.wing_s1_shoulder_spacer(flipped=flipped), name=name,
color=self.material_bracket.color) color=self.material_bracket.color)
.constrain(f"panel_front?{tag}", f"{name}?mate1", "Plane") .constrain("panel_front?shoulder_bot", "shoulder_bot_spacer?weld1", "Plane")
.constrain(f"panel_back?{tag}", f"{name}?mate2", "Plane") .constrain("panel_back?shoulder_bot", "shoulder_bot_spacer?weld2", "Plane")
.constrain(f"{name}?dir", "FixedAxis", param=(0, 1, 0)) .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"]: for tag in ["middle", "tip"]:
name = f"{tag}_spacer"
( (
result result
.add(self.wing_s1_spacer(), name=f"{tag}_spacer", .add(self.wing_s1_spacer(), name=name,
color=self.material_bracket.color) color=self.material_bracket.color)
.constrain(f"panel_front?{tag}", f"{tag}_spacer?mate1", "Plane") .constrain(f"panel_front?{tag}", f"{tag}_spacer?weld1", "Plane")
.constrain(f"panel_back?{tag}", f"{tag}_spacer?mate2", "Plane") .constrain(f"panel_back?{tag}", f"{tag}_spacer?weld2", "Plane")
.constrain(f"{name}?dir", "FixedAxis", param=(0, 1, 0)) .constrain(f"{name}?dir", "FixedAxis", param=(0, 1, 0))
) )
return result.solve() 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`. `__init__.py`.
""" """
import math import math
from dataclasses import dataclass
import cadquery as Cq import cadquery as Cq
from nhf import Material, Role from nhf import Material, Role
from nhf.parts.joints import HirthJoint from nhf.parts.joints import HirthJoint
import nhf.utils import nhf.utils
def wing_root_profiles( def wing_root_profiles(
base_sweep=150, base_sweep=150,
wall_thickness=8, wall_thickness=8,
@ -227,32 +229,49 @@ def wing_root(joint: HirthJoint,
) )
return result 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 Generates the first wing segment profile, with the wing root pointing in
the positive x axis. the positive x axis.
""" """
# Depression of the wing middle
h = 100
w = 400 w = 270
bend = 200 # 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 factor = 0.7
result = ( result = (
Cq.Sketch() Cq.Sketch()
.segment((0, 0), (0, h)) .segment((0, 0), (0, self.shoulder_height))
.spline([ .spline([
(0, h), (0, self.shoulder_height),
(0.5 * w, h - factor * bend), ((w - s_th * self.elbow_height) / 2, self.shoulder_height / 2 + (self.elbow_height * c_th - h) / 2 - bend),
(w, h - bend), (w - s_th * self.elbow_height, self.elbow_height * c_th - h),
]) ])
.segment( .segment(
(w, h - bend), (w - s_th * self.elbow_height, self.elbow_height * c_th -h),
(w, -bend), (w, -h),
) )
.spline([ .spline([
(w, - bend),
(0.5 * w, - factor * bend),
(0, 0), (0, 0),
(w / 2, -h / 2 - bend),
(w, -h),
]) ])
.assemble() .assemble()
) )