Cosplay/nhf/touhou/houjuu_nue/__init__.py

166 lines
5.3 KiB
Python
Raw Normal View History

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
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
import nhf.touhou.houjuu_nue.joints as MJ
import nhf.touhou.houjuu_nue.harness as MH
from nhf.parts.item import Item
import nhf.utils
2024-06-19 15:54:09 -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
harness: MH.Harness = field(default_factory=lambda: MH.Harness())
2024-06-23 22:27:15 -07:00
2024-07-16 22:26:06 -07:00
wing_r1: MW.WingR = field(default_factory=lambda: MW.WingR(
name="r1",
shoulder_angle_bias = 15.0,
2024-07-16 22:26:06 -07:00
))
wing_r2: MW.WingR = field(default_factory=lambda: MW.WingR(
name="r2",
))
wing_r3: MW.WingR = field(default_factory=lambda: MW.WingR(
name="r3",
shoulder_angle_bias = 15.0,
2024-07-16 22:26:06 -07:00
))
2024-07-16 17:18:28 -07:00
wing_l1: MW.WingL = field(default_factory=lambda: MW.WingL(
name="l1",
wrist_angle=-60.0,
2024-07-16 17:18:28 -07:00
))
wing_l2: MW.WingL = field(default_factory=lambda: MW.WingL(
name="l2",
wrist_angle=-30.0,
shoulder_angle_bias = 15.0,
2024-07-16 17:18:28 -07:00
))
wing_l3: MW.WingL = field(default_factory=lambda: MW.WingL(
name="l3",
wrist_angle=-0.0,
2024-07-16 17:18:28 -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-19 15:06:57 -07:00
self.wing_r1.root_joint = self.harness.root_joint
self.wing_r2.root_joint = self.harness.root_joint
self.wing_r3.root_joint = self.harness.root_joint
self.wing_l1.root_joint = self.harness.root_joint
self.wing_l2.root_joint = self.harness.root_joint
self.wing_l3.root_joint = self.harness.root_joint
self.wing_r1.shoulder_joint.torsion_joint
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-17 13:27:48 -07:00
@submodel(name="wing-l1")
2024-07-16 17:18:28 -07:00
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-07 21:45:10 -07:00
@assembly()
def wings_harness_assembly(self,
parts: Optional[list[str]] = None,
**kwargs) -> Cq.Assembly:
"""
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)))
2024-07-19 15:06:57 -07:00
.add(self.wing_r1.assembly(parts, root_offset=9, **kwargs), name="wing_r1")
.add(self.wing_r2.assembly(parts, root_offset=7, **kwargs), name="wing_r2")
.add(self.wing_r3.assembly(parts, root_offset=6, **kwargs), name="wing_r3")
.add(self.wing_l1.assembly(parts, root_offset=7, **kwargs), name="wing_l1")
.add(self.wing_l2.assembly(parts, root_offset=8, **kwargs), name="wing_l2")
.add(self.wing_l3.assembly(parts, root_offset=9, **kwargs), name="wing_l3")
)
2024-07-19 15:06:57 -07:00
for tag in ["r1", "r2", "r3", "l1", "l2", "l3"]:
self.harness.add_root_joint_constraint(
result,
2024-07-19 15:06:57 -07:00
"harness/base",
f"wing_{tag}/root",
tag
)
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,
2024-07-17 19:13:06 -07:00
"wing-depth": bbox.ylen,
2024-07-16 17:18:28 -07:00
"wing-height": bbox.zlen,
2024-07-17 19:13:06 -07:00
"wing-mass": a.total_mass(),
2024-07-21 00:08:14 -07:00
"wing-centre-of-mass": a.centre_of_mass().toTuple(),
"items": Item.count(a),
2024-07-16 17:18:28 -07:00
}
2024-07-03 23:15:39 -07:00
if __name__ == '__main__':
2024-07-17 19:13:06 -07:00
import sys
2024-07-03 23:15:39 -07:00
p = Parameters()
2024-07-17 19:13:06 -07:00
if len(sys.argv) == 1:
p.build_all()
sys.exit(0)
if sys.argv[1] == 'stat':
print(p.stat())