cosplay: Touhou/Houjuu Nue #4

Open
aniva wants to merge 189 commits from touhou/houjuu-nue into main
1 changed files with 55 additions and 17 deletions
Showing only changes of commit be118be6cc - Show all commits

View File

@ -36,8 +36,10 @@ class WingProfile(Model):
shoulder_width: float = 36.0 shoulder_width: float = 36.0
shoulder_tip_x: float = -260.0 shoulder_tip_x: float = -260.0
shoulder_tip_y: float = 165.0 shoulder_tip_y: float = 165.0
shoulder_mid_x: float = -125.0 shoulder_tip_bezier_x: float = 100.0
shoulder_mid_y: float = 75.0 shoulder_tip_bezier_y: float = -50.0
shoulder_base_bezier_x: float = -30.0
shoulder_base_bezier_y: float = 30.0
s0_hole_loc: Cq.Location = Cq.Location.from2d(-25, 33) s0_hole_loc: Cq.Location = Cq.Location.from2d(-25, 33)
s0_hole_diam: float = 15.0 s0_hole_diam: float = 15.0
@ -153,8 +155,7 @@ class WingProfile(Model):
def outer_profile_s0(self) -> Cq.Sketch: def outer_profile_s0(self) -> Cq.Sketch:
""" """
The outer boundary of s0, used to produce the curved panel and the The outer boundary of s0 top/bottom slots
top/bottom slots
""" """
tip_x = self.shoulder_tip_x tip_x = self.shoulder_tip_x
tip_y = self.shoulder_tip_y tip_y = self.shoulder_tip_y
@ -170,15 +171,35 @@ class WingProfile(Model):
# (tip_x - 10, tip_y), # (tip_x - 10, tip_y),
#) #)
) )
def inner_profile_s0(self) -> Cq.Edge:
"""
The inner boundary of s0
"""
tip_x = self.shoulder_tip_x
tip_y = self.shoulder_tip_y
dx2 = self.shoulder_tip_bezier_x
dy2 = self.shoulder_tip_bezier_y
dx1 = self.shoulder_base_bezier_x
dy1 = self.shoulder_base_bezier_y
sw = self.shoulder_width
return Cq.Edge.makeBezier(
[
Cq.Vector(*p)
for p in [
(tip_x, tip_y - sw),
(tip_x + dx2, tip_y - sw + dy2),
(-self.base_width + dx1, dy1),
(-self.base_width, 0),
]
]
)
@property @property
def shoulder_angle_neutral(self) -> float: def shoulder_angle_neutral(self) -> float:
""" """
Returns the neutral angle of the shoulder Returns the neutral angle of the shoulder
""" """
dx = self.shoulder_mid_x - self.shoulder_tip_x result = math.degrees(math.atan2(-self.shoulder_tip_bezier_y, self.shoulder_tip_bezier_x))
dy = -(self.shoulder_mid_y - (self.shoulder_tip_y - self.shoulder_width))
result = math.degrees(math.atan2(dy, dx))
assert result >= 0 assert result >= 0
return result return result
@ -186,8 +207,10 @@ class WingProfile(Model):
def profile_s0(self, top: bool = True) -> Cq.Sketch: def profile_s0(self, top: bool = True) -> Cq.Sketch:
tip_x = self.shoulder_tip_x tip_x = self.shoulder_tip_x
tip_y = self.shoulder_tip_y tip_y = self.shoulder_tip_y
mid_x = self.shoulder_mid_x dx2 = self.shoulder_tip_bezier_x
mid_y = self.shoulder_mid_y dy2 = self.shoulder_tip_bezier_y
dx1 = self.shoulder_base_bezier_x
dy1 = self.shoulder_base_bezier_y
sw = self.shoulder_width sw = self.shoulder_width
sketch = ( sketch = (
self.outer_profile_s0() self.outer_profile_s0()
@ -196,14 +219,12 @@ class WingProfile(Model):
(tip_x, tip_y), (tip_x, tip_y),
(tip_x, tip_y - sw), (tip_x, tip_y - sw),
) )
.segment( .bezier([
(tip_x, tip_y - sw), (tip_x, tip_y - sw),
(mid_x, mid_y), (tip_x + dx2, tip_y - sw + dy2),
) (-self.base_width + dx1, dy1),
.segment(
(mid_x, mid_y),
(-self.base_width, 0), (-self.base_width, 0),
) ])
.assemble() .assemble()
.push([self.shoulder_axle_loc.to2d_pos()]) .push([self.shoulder_axle_loc.to2d_pos()])
.circle(self.shoulder_joint.radius, mode='a') .circle(self.shoulder_joint.radius, mode='a')
@ -231,6 +252,18 @@ class WingProfile(Model):
plane.moveTo(0, 0).tagPlane("bot") plane.moveTo(0, 0).tagPlane("bot")
plane.moveTo(0, self.root_height + t*2).tagPlane("top") plane.moveTo(0, self.root_height + t*2).tagPlane("top")
return result return result
def inner_shell_s0(self) -> Cq.Workplane:
t = self.panel_thickness
#profile = Cq.Wire.assembleEdges(self.inner_profile_s0())
result = (
Cq.Workplane('XZ')
.rect(t, self.root_height + t*2, centered=(False, False))
.sweep(self.inner_profile_s0())
)
plane = result.copyWorkplane(Cq.Workplane('XZ'))
plane.moveTo(t, 0).tagPlane("bot")
plane.moveTo(t, self.root_height + t*2).tagPlane("top")
return result
@submodel(name="spacer-s0-shoulder") @submodel(name="spacer-s0-shoulder")
def spacer_s0_shoulder(self) -> MountingBox: def spacer_s0_shoulder(self) -> MountingBox:
@ -318,6 +351,7 @@ class WingProfile(Model):
) )
h = self.panel_thickness if top else 0 h = self.panel_thickness if top else 0
result.copyWorkplane(Cq.Workplane('XZ')).moveTo(0, h).tagPlane("corner") result.copyWorkplane(Cq.Workplane('XZ')).moveTo(0, h).tagPlane("corner")
result.copyWorkplane(Cq.Workplane('XZ')).moveTo(-self.base_width, h).tagPlane("corner_left")
return result return result
@assembly() @assembly()
@ -331,12 +365,16 @@ class WingProfile(Model):
loc=Cq.Location((0, 0, self.root_height + self.panel_thickness))) loc=Cq.Location((0, 0, self.root_height + self.panel_thickness)))
.constrain("bot", "Fixed") .constrain("bot", "Fixed")
.constrain("top", "Fixed") .constrain("top", "Fixed")
#.constrain("bot@faces@>Z", "top@faces@<Z", "Point", .constrain("bot@faces@>Z", "top@faces@<Z", "Point",
# param=self.shoulder_joint.height) param=self.shoulder_height)
.addS(self.outer_shell_s0(), name="outer_shell", .addS(self.outer_shell_s0(), name="outer_shell",
material=self.mat_panel, role=self.role_panel) material=self.mat_panel, role=self.role_panel)
.constrain("bot?corner", "outer_shell?bot", "Plane", param=0) .constrain("bot?corner", "outer_shell?bot", "Plane", param=0)
.constrain("top?corner", "outer_shell?top", "Plane", param=0) .constrain("top?corner", "outer_shell?top", "Plane", param=0)
#.addS(self.inner_shell_s0(), name="inner_shell",
# material=self.mat_panel, role=self.role_panel)
#.constrain("bot?corner_left", "inner_shell?bot", "Point")
#.constrain("top?corner_left", "inner_shell?top", "Point")
) )
for o, tag in [ for o, tag in [
(self.spacer_s0_shoulder().generate(), "shoulder"), (self.spacer_s0_shoulder().generate(), "shoulder"),