cosplay: Touhou/Houjuu Nue #4

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

View File

@ -129,6 +129,7 @@ class LinearActuator(Item):
combine='cut', combine='cut',
) )
) )
back.faces(">X").tag("dir")
back.copyWorkplane(Cq.Workplane('XZ')).tagPlane('conn') back.copyWorkplane(Cq.Workplane('XZ')).tagPlane('conn')
result = ( result = (
Cq.Assembly() Cq.Assembly()

View File

@ -170,23 +170,21 @@ class WingProfile(Model):
def shoulder_height(self) -> float: def shoulder_height(self) -> float:
return self.shoulder_joint.height return self.shoulder_joint.height
def outer_profile_s0(self) -> Cq.Sketch: def outer_profile_s0(self) -> Cq.Edge:
""" """
The outer boundary of s0 top/bottom slots The outer boundary of s0 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
return ( return Cq.Edge.makeSpline(
Cq.Sketch() [
.spline([ Cq.Vector(*p)
(0, 0), for p in [
(-30.0, 80.0), (0, 0),
(tip_x, tip_y) (-30.0, 80.0),
]) (tip_x, tip_y),
#.segment( ]
# (tip_x, tip_y), ]
# (tip_x - 10, tip_y),
#)
) )
def inner_profile_s0(self) -> Cq.Edge: def inner_profile_s0(self) -> Cq.Edge:
""" """
@ -199,18 +197,17 @@ class WingProfile(Model):
dx1 = self.shoulder_base_bezier_x dx1 = self.shoulder_base_bezier_x
dy1 = self.shoulder_base_bezier_y dy1 = self.shoulder_base_bezier_y
sw = self.shoulder_width sw = self.shoulder_width
points = [
(tip_x, tip_y - sw),
(tip_x + dx2, tip_y - sw + dy2),
(-self.base_width + dx1, dy1),
(-self.base_width, 0),
]
return Cq.Edge.makeBezier( return Cq.Edge.makeBezier(
[ [Cq.Vector(x, y) for x, y in points]
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:
""" """
@ -224,24 +221,16 @@ 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
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 sw = self.shoulder_width
sketch = ( sketch = (
self.outer_profile_s0() Cq.Sketch()
.edge(self.outer_profile_s0())
.segment((-self.base_width, 0), (0, 0)) .segment((-self.base_width, 0), (0, 0))
.segment( .segment(
(tip_x, tip_y), (tip_x, tip_y),
(tip_x, tip_y - sw), (tip_x, tip_y - sw),
) )
.bezier([ .edge(self.inner_profile_s0())
(tip_x, tip_y - sw),
(tip_x + dx2, tip_y - sw + dy2),
(-self.base_width + dx1, dy1),
(-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')
@ -265,7 +254,7 @@ class WingProfile(Model):
def outer_shell_s0(self) -> Cq.Workplane: def outer_shell_s0(self) -> Cq.Workplane:
t = self.panel_thickness_s0 t = self.panel_thickness_s0
profile = Cq.Wire.assembleEdges(self.outer_profile_s0().edges().vals()) profile = self.outer_profile_s0()
result = ( result = (
Cq.Workplane('XZ') Cq.Workplane('XZ')
.rect(t, self.root_height + t*2, centered=(False, False)) .rect(t, self.root_height + t*2, centered=(False, False))
@ -277,17 +266,35 @@ class WingProfile(Model):
return result return result
def inner_shell_s0(self) -> Cq.Workplane: def inner_shell_s0(self) -> Cq.Workplane:
t = self.panel_thickness_s0 t = self.panel_thickness_s0
#profile = Cq.Wire.assembleEdges(self.inner_profile_s0()) profile = self.inner_profile_s0()
result = ( result = (
Cq.Workplane('XZ') Cq.Workplane('XZ')
.moveTo(-t, 0)
.rect(t, self.root_height + t*2, centered=(False, False)) .rect(t, self.root_height + t*2, centered=(False, False))
.sweep(self.inner_profile_s0()) .sweep(profile, normal=(0,-1,0))
) )
plane = result.copyWorkplane(Cq.Workplane('XZ')) plane = result.copyWorkplane(Cq.Workplane('XZ'))
plane.moveTo(t, 0).tagPlane("bot") plane.moveTo(0, 0).tagPlane("bot")
plane.moveTo(t, self.root_height + t*2).tagPlane("top") plane.moveTo(0, self.root_height + t*2).tagPlane("top")
return result return result
@target(name="profile-s0-outer-shell", kind=TargetKind.DXF)
def outer_shell_s0_profile(self) -> Cq.Sketch:
"""
This part should be laser cut and then bent on a falsework to create the required shape.
"""
length = self.outer_profile_s0().Length()
height = self.root_height + self.panel_thickness_s0 * 2
return Cq.Sketch().rect(length, height)
@target(name="profile-s0-inner-shell", kind=TargetKind.DXF)
def inner_shell_s0_profile(self) -> Cq.Sketch:
"""
This part should be laser cut and then bent on a falsework to create the required shape.
"""
length = self.inner_profile_s0().Length()
height = self.root_height + self.panel_thickness_s0 * 2
return Cq.Sketch().rect(length, height)
@submodel(name="spacer-s0-shoulder-inner") @submodel(name="spacer-s0-shoulder-inner")
def spacer_s0_shoulder(self, left: bool=True) -> MountingBox: def spacer_s0_shoulder(self, left: bool=True) -> MountingBox:
""" """
@ -331,7 +338,7 @@ class WingProfile(Model):
) )
@submodel(name="spacer-s0-shoulder-outer") @submodel(name="spacer-s0-shoulder-outer")
def spacer_s0_shoulder_outer(self) -> MountingBox: def spacer_s0_shoulder_outer(self) -> MountingBox:
return self.spacer_s0_shoulder_inner(left=False) return self.spacer_s0_shoulder(left=False)
@submodel(name="spacer-s0-base") @submodel(name="spacer-s0-base")
def spacer_s0_base(self) -> MountingBox: def spacer_s0_base(self) -> MountingBox:
@ -428,7 +435,7 @@ class WingProfile(Model):
("shoulder_right", ("shoulder_right",
self.shoulder_axle_loc * axle_rotate * self.shoulder_joint.parent_lip_loc(left=False)), self.shoulder_axle_loc * axle_rotate * self.shoulder_joint.parent_lip_loc(left=False)),
("shoulder_act", ("shoulder_act",
self.shoulder_axle_loc * axle_rotate * Cq.Location.from2d(120, -40)), self.shoulder_axle_loc * axle_rotate * Cq.Location.from2d(120, -40, -30)),
("base", Cq.Location.from2d(base_dx, base_dy, 90)), ("base", Cq.Location.from2d(base_dx, base_dy, 90)),
("electronic_mount", Cq.Location.from2d(-35, 65, 60)), ("electronic_mount", Cq.Location.from2d(-35, 65, 60)),
] ]
@ -436,11 +443,11 @@ class WingProfile(Model):
self.profile_s0(top=top), self.profile_s0(top=top),
self.panel_thickness_s0, self.panel_thickness_s0,
tags, tags,
reverse=not top, reverse=top,
) )
h = self.panel_thickness if top else 0 h = 0 if top else self.panel_thickness_s0
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") result.copyWorkplane(Cq.Workplane('XZ')).moveTo(-self.base_width, self.panel_thickness_s0 - h).tagPlane("corner_left")
return result return result
@assembly() @assembly()
@ -449,9 +456,9 @@ class WingProfile(Model):
ignore_electronics: bool=False) -> Cq.Assembly: ignore_electronics: bool=False) -> Cq.Assembly:
result = ( result = (
Cq.Assembly() Cq.Assembly()
.addS(self.surface_s0(top=True), name="bot", .addS(self.surface_s0(top=False), name="bot",
material=self.mat_panel, role=self.role_panel) material=self.mat_panel, role=self.role_panel)
.addS(self.surface_s0(top=False), name="top", .addS(self.surface_s0(top=True), name="top",
material=self.mat_panel, role=self.role_panel, material=self.mat_panel, role=self.role_panel,
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")
@ -462,10 +469,10 @@ class WingProfile(Model):
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", .addS(self.inner_shell_s0(), name="inner_shell",
# material=self.mat_panel, role=self.role_panel) material=self.mat_panel, role=self.role_panel)
#.constrain("bot?corner_left", "inner_shell?bot", "Point") .constrain("bot?corner_left", "inner_shell?bot", "Plane", param=0)
#.constrain("top?corner_left", "inner_shell?top", "Point") .constrain("top?corner_left", "inner_shell?top", "Plane", param=0)
) )
for o, tag in [ for o, tag in [
(self.spacer_s0_shoulder(left=True).generate(), "shoulder_left"), (self.spacer_s0_shoulder(left=True).generate(), "shoulder_left"),
@ -1122,6 +1129,9 @@ class WingProfile(Model):
"Plane", param=0) "Plane", param=0)
.constrain("s0/shoulder_act?conn0", f"{tag_bracket}?conn_side", .constrain("s0/shoulder_act?conn0", f"{tag_bracket}?conn_side",
"Plane") "Plane")
# Directional constraints should be provided by the line
.constrain(f"{tag_bracket}?conn_mid", "s0/shoulder_act?top", "Axis", param=0)
.constrain(f"{tag_act}/back?dir", "s0/shoulder_act?conn0", "Axis", param=0)
) )
if "root" in parts: if "root" in parts:
result.addS(self.root_joint.assembly( result.addS(self.root_joint.assembly(