cosplay: Touhou/Houjuu Nue #4

Open
aniva wants to merge 189 commits from touhou/houjuu-nue into main
5 changed files with 121 additions and 41 deletions
Showing only changes of commit d43482f77d - Show all commits

View File

@ -33,6 +33,7 @@ class Material(Enum):
PLASTIC_PLA = 0.5, _color('azure3', 0.6)
RESIN_TRANSPARENT = 1.1, _color('cadetblue2', 0.6)
ACRYLIC_BLACK = 0.5, _color('gray50', 0.6)
ACRYLIC_TRANSPARENT = 0.5, _color('ghostwhite', 0.5)
def __init__(self, density: float, color: Cq.Color):
self.density = density

View File

@ -332,6 +332,7 @@ class TorsionJoint:
)
def track(self):
# TODO: Cover outer part of track only. Can we do this?
groove_profile = (
Cq.Sketch()
.circle(self.radius)

View File

@ -104,12 +104,16 @@ class Parameters(Model):
shoulder_attach_diam: float = 8
"""
Heights for various wing joints, where the numbers start from the first joint.
Heights for various wing joints, where the numbers start from the first
joint.
"""
wing_s0_thickness: float = 40
wing_s0_height: float = 100
wing_r1_height: float = 100
wing_r1_width: float = 400
# Length of the spacer
wing_s1_thickness: float = 20
wing_s1_spacer_thickness: float = 25.4 / 8
wing_s1_spacer_width: float = 20
trident_handle: Handle = field(default_factory=lambda: Handle(
diam=38,
@ -121,6 +125,9 @@ class Parameters(Model):
simplify_geometry=False,
))
material_panel: Material = Material.ACRYLIC_TRANSPARENT
material_bracket: Material = Material.ACRYLIC_TRANSPARENT
def __post_init__(self):
super().__init__(name="houjuu-nue")
assert self.wing_root_radius > self.hs_hirth_joint.radius,\
@ -258,6 +265,10 @@ class Parameters(Model):
result.faces("<Z").tag("base")
return result
#@target(name="wing/joining-plate", kind=TargetKind.DXF)
#def joining_plate(self) -> Cq.Workplane:
# return self.wing_joining_plate.plate()
@target(name="wing_root")
def wing_root(self) -> Cq.Assembly:
"""
@ -312,43 +323,42 @@ class Parameters(Model):
)
return result
def wing_r1_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
bend = 200
factor = 0.7
@target(name="wing/s1-spacer", kind=TargetKind.DXF)
def wing_s1_spacer(self) -> Cq.Workplane:
result = (
Cq.Sketch()
.segment((0, 0), (0, self.wing_r1_height))
.spline([
(0, self.wing_r1_height),
(0.5 * self.wing_r1_width, self.wing_r1_height - factor * bend),
(self.wing_r1_width, self.wing_r1_height - bend),
])
.segment(
(self.wing_r1_width, self.wing_r1_height - bend),
(self.wing_r1_width, -bend),
)
.spline([
(self.wing_r1_width, - bend),
(0.5 * self.wing_r1_width, - factor * bend),
(0, 0),
])
.assemble()
Cq.Workplane('XZ')
.sketch()
.rect(self.wing_s1_spacer_width, self.wing_s1_thickness)
.finalize()
.extrude(self.wing_s1_spacer_thickness)
)
result.faces("<Z").tag("mate1")
result.faces(">Z").tag("mate2")
result.faces(">Y").tag("dir")
return result
def wing_r1(self) -> Cq.Solid:
profile = self.wing_r1_profile()
@target(name="wing/r1s1", kind=TargetKind.DXF)
def wing_r1s1_profile(self) -> Cq.Sketch:
return MW.wing_r1s1_profile()
def wing_r1s1_panel(self, front=True) -> Cq.Workplane:
profile = self.wing_r1s1_profile()
anchors = [
("shoulder_bot", 10, 10),
("middle", 50, -20),
("tip", 390, -150),
]
result = (
Cq.Workplane("XY")
.placeSketch(profile)
.extrude(self.panel_thickness)
.val()
)
plane = result.faces(">Z" if front else "<Z").workplane()
sign = 1 if front else -1
tag_direction = "+Y" if front else "-Y"
for name, px, py in anchors:
plane.moveTo(px, sign * py).tagPlane(name)
#plane.moveTo(px, sign * py).tagPlane(f"{name}_dir", direction=tag_direction)
return result
######################
@ -405,6 +415,29 @@ class Parameters(Model):
)
return result
def wing_r1s1_assembly(self) -> Cq.Assembly:
result = (
Cq.Assembly()
.add(self.wing_r1s1_panel(front=True), name="panel_front",
color=self.material_panel.color)
.add(self.wing_r1s1_panel(front=False), name="panel_back",
color=self.material_panel.color)
.constrain("panel_front@faces@>Z", "panel_back@faces@<Z", "Point",
param=self.wing_s1_thickness)
)
for tag in ["shoulder_bot", "middle", "tip"]:
(
result
.add(self.wing_s1_spacer(), name=f"{tag}_spacer",
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")
)
result.solve()
return result
def wing_r1_assembly(self) -> Cq.Assembly:
result = (
Cq.Assembly()

View File

@ -226,3 +226,34 @@ def wing_root(joint: HirthJoint,
loc=Cq.Location((0, 0, -joint.total_height)))
)
return result
def wing_r1s1_profile() -> 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
factor = 0.7
result = (
Cq.Sketch()
.segment((0, 0), (0, h))
.spline([
(0, h),
(0.5 * w, h - factor * bend),
(w, h - bend),
])
.segment(
(w, h - bend),
(w, -bend),
)
.spline([
(w, - bend),
(0.5 * w, - factor * bend),
(0, 0),
])
.assemble()
)
return result

View File

@ -6,6 +6,7 @@ Adds the functions to `Cq.Workplane`:
2. `tagPlane`
"""
import cadquery as Cq
from typing import Union, Tuple
def tagPoint(self, tag: str):
@ -18,21 +19,34 @@ def tagPoint(self, tag: str):
Cq.Workplane.tagPoint = tagPoint
def tagPlane(self, tag: str, axis='Z'):
def tagPlane(self, tag: str,
direction: Union[str, Cq.Vector, Tuple[float, float, float]] = '+Z'):
"""
Adds a phantom `Cq.Edge` in the given location which can be referenced in a
`Axis`, `Point`, or `Plane` constraint.
"""
x, y, z = 0, 0, 0
if axis in ('z', 'Z'):
z = 1
elif axis in ('y', 'Y'):
y = 1
elif axis in ('x', 'X'):
x = 1
if isinstance(direction, str):
x, y, z = 0, 0, 0
assert len(direction) == 2
sign, axis = direction
if axis in ('z', 'Z'):
z = 1
elif axis in ('y', 'Y'):
y = 1
elif axis in ('x', 'X'):
x = 1
else:
assert False, "Axis must be one of x,y,z"
if sign == '+':
sign = 1
elif sign == '-':
sign = -1
else:
assert False, "Sign must be one of +/-"
v = Cq.Vector(x, y, z) * sign
else:
assert False, "Axis must be one of x,y,z"
edge = Cq.Edge.makeLine((-x, -y, -z), (x, y, z))
v = Cq.Vector(direction)
edge = Cq.Edge.makeLine(v * (-1), v)
self.eachpoint(edge.moved, useLocalCoordinates=True).tag(tag)
Cq.Workplane.tagPlane = tagPlane