cosplay: Touhou/Houjuu Nue #4

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

View File

@ -238,9 +238,13 @@ class WingRoot:
"""
panel_thickness: float = 25.4 / 16
spacer_thickness: float = 25.4 / 8
height: float = 100.0
shoulder_width: float = 20.0
root_width: float = 60.0
shoulder_width: float = 30.0
root_width: float = 80.0
tip_x: float = -200.0
tip_y: float = 160.0
def outer_spline(self) -> list[Tuple[float, float]]:
"""
@ -248,34 +252,81 @@ class WingRoot:
"""
def profile(self) -> Cq.Sketch:
tip_x, tip_y = -100.0, 70.0
sketch = (
Cq.Sketch()
.segment((-self.root_width, 0), (0, 0))
.spline([
(0, 0),
(-30.0, 50.0),
(tip_x, tip_y)
(-30.0, 80.0),
(self.tip_x, self.tip_y)
])
.segment(
(tip_x, tip_y),
(tip_x, tip_y - self.shoulder_width)
(self.tip_x, self.tip_y),
(self.tip_x, self.tip_y - self.shoulder_width)
)
.segment(
(tip_x, tip_y - self.shoulder_width),
(self.tip_x, self.tip_y - self.shoulder_width),
(-self.root_width, 0)
)
.assemble()
)
return sketch
def xy_surface(self) -> Cq.Workplane:
def spacer(self) -> Cq.Workplane:
"""
Creates a rectangular spacer. This could be cut from acrylic.
return (
Cq.Workplane()
.placeSketch(self.profile())
.extrude(self.panel_thickness)
There are two holes on the top of the spacer. With the holes
"""
length = self.height
width = 10.0
h = self.spacer_thickness
result = (
Cq.Workplane('XY')
.sketch()
.rect(length, width)
.finalize()
.extrude(h)
)
# Tag the mating surfaces to be glued
result.faces("<X").workplane().tagPlane("left")
result.faces(">X").workplane().tagPlane("right")
# Tag the directrix
result.faces(">Z").tag("dir")
return result
def surface(self, top: bool = False) -> Cq.Workplane:
tags = [
("shoulder", (self.tip_x, self.tip_y + 30), 0),
("base", (-self.root_width, 0), 90),
]
return nhf.utils.extrude_with_markers(
self.profile(),
self.panel_thickness,
tags,
reverse=not top,
)
def assembly(self) -> Cq.Assembly:
result = (
Cq.Assembly()
.add(self.surface(top=True), name="bot")
.add(self.surface(top=False), name="top")
.constrain("bot@faces@>Z", "top@faces@<Z", "Point",
param=self.height)
)
for t in ["shoulder", "base"]:
name = f"{t}_spacer"
(
result
.add(self.spacer(), name=name)
.constrain(f"{name}?left", f"bot?{t}", "Plane")
.constrain(f"{name}?right", f"top?{t}", "Plane")
.constrain(f"{name}?dir", f"top?{t}_dir", "Axis")
)
return result.solve()
@dataclass
class WingProfile:

View File

@ -6,9 +6,34 @@ Adds the functions to `Cq.Workplane`:
2. `tagPlane`
"""
import math
import functools
import cadquery as Cq
from nhf import Role
from typing import Union, Tuple
from typing import Union, Tuple, cast
# Bug fixes
def _subloc(self, name: str) -> Tuple[Cq.Location, str]:
"""
Calculate relative location of an object in a subassembly.
Returns the relative positions as well as the name of the top assembly.
"""
rv = Cq.Location()
obj = self.objects[name]
name_out = name
if obj not in self.children and obj is not self:
locs = []
while not obj.parent is self:
locs.append(obj.loc)
obj = cast(Cq.Assembly, obj.parent)
name_out = obj.name
rv = functools.reduce(lambda l1, l2: l2 * l1, locs)
return (rv, name_out)
Cq.Assembly._subloc = _subloc
def tagPoint(self, tag: str):