2024-06-24 16:13:15 -07:00
|
|
|
"""
|
2024-07-03 23:15:39 -07:00
|
|
|
To build, execute
|
|
|
|
```
|
|
|
|
python3 nhf/touhou/houjuu_nue/__init__.py
|
|
|
|
```
|
|
|
|
|
2024-06-24 16:13:15 -07:00
|
|
|
This cosplay consists of 3 components:
|
|
|
|
|
|
|
|
## Trident
|
|
|
|
|
|
|
|
The trident is composed of individual segments, made of acrylic, and a 3D
|
|
|
|
printed head (convention rule prohibits metal) with a metallic paint. To ease
|
|
|
|
transportation, the trident handle has individual segments with threads and can
|
|
|
|
be assembled on site.
|
|
|
|
|
|
|
|
## Snake
|
|
|
|
|
|
|
|
A 3D printed snake with a soft material so it can wrap around and bend
|
|
|
|
|
|
|
|
## Wings
|
|
|
|
|
|
|
|
This is the crux of the cosplay and the most complex component. The wings mount
|
|
|
|
on a wearable harness. Each wing consists of 4 segments with 3 joints. Parts of
|
|
|
|
the wing which demands transluscency are created from 1/16" acrylic panels.
|
|
|
|
These panels serve double duty as the exoskeleton.
|
|
|
|
|
|
|
|
The wings are labeled r1,r2,r3,l1,l2,l3. The segments of the wings are labeled
|
2024-06-25 06:11:48 -07:00
|
|
|
from root to tip s0 (root),
|
|
|
|
s1, s2, s3. The joints are named (from root to tip)
|
2024-06-24 16:13:15 -07:00
|
|
|
shoulder, elbow, wrist in analogy with human anatomy.
|
|
|
|
"""
|
2024-07-03 18:45:16 -07:00
|
|
|
from dataclasses import dataclass, field
|
2024-07-16 12:03:51 -07:00
|
|
|
from typing import Optional
|
2024-06-20 23:29:18 -07:00
|
|
|
import cadquery as Cq
|
2024-07-16 15:42:39 -07:00
|
|
|
from nhf.build import Model, TargetKind, target, assembly, submodel
|
2024-07-06 16:41:13 -07:00
|
|
|
from nhf.parts.joints import HirthJoint, TorsionJoint
|
2024-06-24 16:13:15 -07:00
|
|
|
import nhf.touhou.houjuu_nue.wing as MW
|
2024-06-25 06:11:48 -07:00
|
|
|
import nhf.touhou.houjuu_nue.trident as MT
|
2024-07-12 23:16:04 -07:00
|
|
|
import nhf.touhou.houjuu_nue.joints as MJ
|
2024-07-14 23:58:42 -07:00
|
|
|
import nhf.touhou.houjuu_nue.harness as MH
|
2024-07-06 16:41:13 -07:00
|
|
|
import nhf.utils
|
2024-06-19 15:54:09 -07:00
|
|
|
|
2024-06-28 20:07:37 -07:00
|
|
|
@dataclass
|
2024-07-03 23:15:39 -07:00
|
|
|
class Parameters(Model):
|
2024-06-19 21:23:41 -07:00
|
|
|
"""
|
2024-06-24 16:13:15 -07:00
|
|
|
Defines dimensions for the Houjuu Nue cosplay
|
2024-06-19 21:23:41 -07:00
|
|
|
"""
|
2024-06-24 16:13:15 -07:00
|
|
|
|
2024-06-23 22:27:15 -07:00
|
|
|
# Harness
|
2024-07-14 23:58:42 -07:00
|
|
|
harness: MH.Harness = field(default_factory=lambda: MH.Harness())
|
2024-06-23 22:27:15 -07:00
|
|
|
|
2024-07-16 17:18:28 -07:00
|
|
|
wing_r1: MW.WingR = field(default_factory=lambda: MW.WingR(name="r1"))
|
|
|
|
wing_r2: MW.WingR = field(default_factory=lambda: MW.WingR(name="r2"))
|
|
|
|
wing_r3: MW.WingR = field(default_factory=lambda: MW.WingR(name="r3"))
|
|
|
|
wing_l1: MW.WingL = field(default_factory=lambda: MW.WingL(
|
|
|
|
name="l1",
|
|
|
|
wrist_angle=-45.0,
|
|
|
|
))
|
|
|
|
wing_l2: MW.WingL = field(default_factory=lambda: MW.WingL(
|
|
|
|
name="l2",
|
|
|
|
wrist_angle=-30.0,
|
|
|
|
))
|
|
|
|
wing_l3: MW.WingL = field(default_factory=lambda: MW.WingL(
|
|
|
|
name="l3",
|
|
|
|
wrist_angle=0.0,
|
|
|
|
))
|
2024-07-06 16:41:13 -07:00
|
|
|
|
2024-07-16 15:42:39 -07:00
|
|
|
trident: MT.Trident = field(default_factory=lambda: MT.Trident())
|
2024-06-25 06:11:48 -07:00
|
|
|
|
2024-06-24 16:13:15 -07:00
|
|
|
def __post_init__(self):
|
2024-07-04 10:02:58 -07:00
|
|
|
super().__init__(name="houjuu-nue")
|
2024-07-16 21:20:45 -07:00
|
|
|
self.wing_r1.base_joint = self.harness.hs_hirth_joint
|
|
|
|
self.wing_r2.base_joint = self.harness.hs_hirth_joint
|
|
|
|
self.wing_r3.base_joint = self.harness.hs_hirth_joint
|
|
|
|
self.wing_l1.base_joint = self.harness.hs_hirth_joint
|
|
|
|
self.wing_l2.base_joint = self.harness.hs_hirth_joint
|
|
|
|
self.wing_l3.base_joint = self.harness.hs_hirth_joint
|
|
|
|
|
|
|
|
assert self.wing_r1.hs_joint_axis_diam == self.harness.hs_joint_axis_diam
|
|
|
|
assert self.wing_r2.hs_joint_axis_diam == self.harness.hs_joint_axis_diam
|
|
|
|
assert self.wing_r3.hs_joint_axis_diam == self.harness.hs_joint_axis_diam
|
|
|
|
assert self.wing_l1.hs_joint_axis_diam == self.harness.hs_joint_axis_diam
|
|
|
|
assert self.wing_l2.hs_joint_axis_diam == self.harness.hs_joint_axis_diam
|
|
|
|
assert self.wing_l3.hs_joint_axis_diam == self.harness.hs_joint_axis_diam
|
2024-07-16 15:42:39 -07:00
|
|
|
|
|
|
|
@submodel(name="harness")
|
|
|
|
def submodel_harness(self) -> Model:
|
|
|
|
return self.harness
|
|
|
|
|
|
|
|
@submodel(name="wing-r1")
|
|
|
|
def submodel_wing_r1(self) -> Model:
|
|
|
|
return self.wing_r1
|
|
|
|
@submodel(name="wing-r2")
|
|
|
|
def submodel_wing_r2(self) -> Model:
|
|
|
|
return self.wing_r2
|
|
|
|
@submodel(name="wing-r3")
|
|
|
|
def submodel_wing_r3(self) -> Model:
|
|
|
|
return self.wing_r3
|
2024-07-16 17:18:28 -07:00
|
|
|
@submodel(name="wing-r1")
|
|
|
|
def submodel_wing_l1(self) -> Model:
|
|
|
|
return self.wing_l1
|
|
|
|
@submodel(name="wing-l2")
|
|
|
|
def submodel_wing_l2(self) -> Model:
|
|
|
|
return self.wing_l2
|
|
|
|
@submodel(name="wing-l3")
|
|
|
|
def submodel_wing_l3(self) -> Model:
|
|
|
|
return self.wing_l3
|
2024-07-06 16:41:13 -07:00
|
|
|
|
2024-07-07 21:45:10 -07:00
|
|
|
@assembly()
|
2024-07-16 12:03:51 -07:00
|
|
|
def wings_harness_assembly(self, parts: Optional[list[str]] = None) -> Cq.Assembly:
|
2024-07-04 12:03:38 -07:00
|
|
|
"""
|
|
|
|
Assembly of harness with all the wings
|
|
|
|
"""
|
|
|
|
result = (
|
|
|
|
Cq.Assembly()
|
2024-07-16 15:42:39 -07:00
|
|
|
.add(self.harness.assembly(), name="harness", loc=Cq.Location((0, 0, 0)))
|
|
|
|
.add(self.wing_r1.assembly(parts), name="wing_r1")
|
|
|
|
.add(self.wing_r2.assembly(parts), name="wing_r2")
|
|
|
|
.add(self.wing_r3.assembly(parts), name="wing_r3")
|
2024-07-16 17:18:28 -07:00
|
|
|
.add(self.wing_l1.assembly(parts), name="wing_l1")
|
|
|
|
.add(self.wing_l2.assembly(parts), name="wing_l2")
|
|
|
|
.add(self.wing_l3.assembly(parts), name="wing_l3")
|
2024-07-04 12:03:38 -07:00
|
|
|
)
|
2024-07-16 21:20:45 -07:00
|
|
|
for tag, offset in [("r1", 10), ("r2", 8), ("r3", 6), ("l1", 6), ("l2", 7), ("l3", 8)]:
|
|
|
|
self.harness.hs_hirth_joint.add_constraints(
|
|
|
|
result,
|
|
|
|
f"harness/{tag}",
|
|
|
|
f"wing_{tag}/s0/hs",
|
|
|
|
offset=offset)
|
2024-07-15 22:57:38 -07:00
|
|
|
return result.solve()
|
2024-07-03 23:15:39 -07:00
|
|
|
|
2024-07-16 15:42:39 -07:00
|
|
|
@submodel(name="trident")
|
|
|
|
def submodel_trident(self) -> Model:
|
|
|
|
return self.trident
|
2024-07-07 21:45:10 -07:00
|
|
|
|
2024-07-16 17:18:28 -07:00
|
|
|
def stat(self) -> dict[str, float]:
|
|
|
|
a = self.wings_harness_assembly()
|
|
|
|
bbox = a.toCompound().BoundingBox()
|
|
|
|
return {
|
|
|
|
"wing-span": bbox.xlen,
|
|
|
|
"wing-thickness": bbox.ylen,
|
|
|
|
"wing-height": bbox.zlen,
|
|
|
|
}
|
|
|
|
|
2024-07-03 23:15:39 -07:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
p = Parameters()
|
|
|
|
p.build_all()
|