cosplay: Touhou/Houjuu Nue #4
|
@ -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:
|
||||
|
|
27
nhf/utils.py
27
nhf/utils.py
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue