feat: 2nd wing segment with spacer

This commit is contained in:
Leni Aniva 2024-07-07 21:01:40 -07:00
parent 54593b9a4e
commit d43482f77d
Signed by: aniva
GPG Key ID: 4D9B1C8D10EA4C50
5 changed files with 121 additions and 41 deletions

View File

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

View File

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

View File

@ -104,12 +104,16 @@ class Parameters(Model):
shoulder_attach_diam: float = 8 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_thickness: float = 40
wing_s0_height: float = 100 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( trident_handle: Handle = field(default_factory=lambda: Handle(
diam=38, diam=38,
@ -121,6 +125,9 @@ class Parameters(Model):
simplify_geometry=False, simplify_geometry=False,
)) ))
material_panel: Material = Material.ACRYLIC_TRANSPARENT
material_bracket: Material = Material.ACRYLIC_TRANSPARENT
def __post_init__(self): def __post_init__(self):
super().__init__(name="houjuu-nue") super().__init__(name="houjuu-nue")
assert self.wing_root_radius > self.hs_hirth_joint.radius,\ assert self.wing_root_radius > self.hs_hirth_joint.radius,\
@ -258,6 +265,10 @@ class Parameters(Model):
result.faces("<Z").tag("base") result.faces("<Z").tag("base")
return result 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") @target(name="wing_root")
def wing_root(self) -> Cq.Assembly: def wing_root(self) -> Cq.Assembly:
""" """
@ -312,43 +323,42 @@ class Parameters(Model):
) )
return result return result
def wing_r1_profile(self) -> Cq.Sketch: @target(name="wing/s1-spacer", kind=TargetKind.DXF)
""" def wing_s1_spacer(self) -> Cq.Workplane:
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
result = ( result = (
Cq.Sketch() Cq.Workplane('XZ')
.segment((0, 0), (0, self.wing_r1_height)) .sketch()
.spline([ .rect(self.wing_s1_spacer_width, self.wing_s1_thickness)
(0, self.wing_r1_height), .finalize()
(0.5 * self.wing_r1_width, self.wing_r1_height - factor * bend), .extrude(self.wing_s1_spacer_thickness)
(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()
) )
result.faces("<Z").tag("mate1")
result.faces(">Z").tag("mate2")
result.faces(">Y").tag("dir")
return result return result
def wing_r1(self) -> Cq.Solid: @target(name="wing/r1s1", kind=TargetKind.DXF)
profile = self.wing_r1_profile() 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 = ( result = (
Cq.Workplane("XY") Cq.Workplane("XY")
.placeSketch(profile) .placeSketch(profile)
.extrude(self.panel_thickness) .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 return result
###################### ######################
@ -405,6 +415,29 @@ class Parameters(Model):
) )
return result 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: def wing_r1_assembly(self) -> Cq.Assembly:
result = ( result = (
Cq.Assembly() Cq.Assembly()

View File

@ -226,3 +226,34 @@ def wing_root(joint: HirthJoint,
loc=Cq.Location((0, 0, -joint.total_height))) loc=Cq.Location((0, 0, -joint.total_height)))
) )
return result 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` 2. `tagPlane`
""" """
import cadquery as Cq import cadquery as Cq
from typing import Union, Tuple
def tagPoint(self, tag: str): def tagPoint(self, tag: str):
@ -18,12 +19,16 @@ def tagPoint(self, tag: str):
Cq.Workplane.tagPoint = tagPoint 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 Adds a phantom `Cq.Edge` in the given location which can be referenced in a
`Axis`, `Point`, or `Plane` constraint. `Axis`, `Point`, or `Plane` constraint.
""" """
if isinstance(direction, str):
x, y, z = 0, 0, 0 x, y, z = 0, 0, 0
assert len(direction) == 2
sign, axis = direction
if axis in ('z', 'Z'): if axis in ('z', 'Z'):
z = 1 z = 1
elif axis in ('y', 'Y'): elif axis in ('y', 'Y'):
@ -32,7 +37,16 @@ def tagPlane(self, tag: str, axis='Z'):
x = 1 x = 1
else: else:
assert False, "Axis must be one of x,y,z" assert False, "Axis must be one of x,y,z"
edge = Cq.Edge.makeLine((-x, -y, -z), (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:
v = Cq.Vector(direction)
edge = Cq.Edge.makeLine(v * (-1), v)
self.eachpoint(edge.moved, useLocalCoordinates=True).tag(tag) self.eachpoint(edge.moved, useLocalCoordinates=True).tag(tag)
Cq.Workplane.tagPlane = tagPlane Cq.Workplane.tagPlane = tagPlane