cosplay: Touhou/Houjuu Nue #4

Open
aniva wants to merge 189 commits from touhou/houjuu-nue into main
3 changed files with 39 additions and 21 deletions
Showing only changes of commit 0cc6100d0e - Show all commits

View File

@ -65,8 +65,6 @@ class Parameters(Model):
shoulder_joint=MJ.ShoulderJoint( shoulder_joint=MJ.ShoulderJoint(
height=100.0, height=100.0,
), ),
elbow_joint=MJ.ElbowJoint(),
wrist_joint=MJ.ElbowJoint(),
elbow_height=110.0, elbow_height=110.0,
)) ))

View File

@ -261,18 +261,22 @@ class Beam:
plane.moveTo(-dx, 0).tagPlane("conn0") plane.moveTo(-dx, 0).tagPlane("conn0")
return result return result
def beam(self) -> Cq.Assembly: def generate(self, flip: bool = False) -> Cq.Assembly:
beam = ( beam = (
Cq.Workplane('XZ') Cq.Workplane('XZ')
.box(self.spine_length, self.spine_thickness, self.spine_height) .box(self.spine_length, self.spine_thickness, self.spine_height)
) )
h = self.spine_height / 2 + self.foot_height h = self.spine_height / 2 + self.foot_height
tag_p, tag_n = "top", "bot"
if flip:
tag_p, tag_n = tag_n, tag_p
result = ( result = (
Cq.Assembly() Cq.Assembly()
.add(beam, name="beam") .add(beam, name="beam")
.add(self.foot(), name="top", .add(self.foot(), name=tag_p,
loc=Cq.Location((0, h, 0))) loc=Cq.Location((0, h, 0)))
.add(self.foot(), name="bot", .add(self.foot(), name=tag_n,
loc=Cq.Location((0, -h, 0), (1, 0, 0), 180)) loc=Cq.Location((0, -h, 0), (1, 0, 0), 180))
) )
return result return result
@ -301,7 +305,7 @@ class DiskJoint(Model):
#disk_thickness_gap: float = 0.1 #disk_thickness_gap: float = 0.1
# Spring angle at 0 degrees of movement # Spring angle at 0 degrees of movement
spring_angle_at_0: float = 30.0 spring_angle_at_0: float = 60.0
spring_slot_offset: float = 15.0 spring_slot_offset: float = 15.0
wall_inset: float = 2.0 wall_inset: float = 2.0
@ -493,6 +497,7 @@ class DiskJoint(Model):
disk: str, disk: str,
angle: float = 0.0, angle: float = 0.0,
) -> Cq.Assembly: ) -> Cq.Assembly:
assert 0 <= angle <= self.movement_angle
deflection = angle - self.neutral_movement_angle deflection = angle - self.neutral_movement_angle
spring_name = disk.replace("/", "__Z") + "_spring" spring_name = disk.replace("/", "__Z") + "_spring"
( (
@ -541,7 +546,7 @@ class DiskJoint(Model):
return result.solve() return result.solve()
@dataclass @dataclass(kw_only=True)
class ElbowJoint: class ElbowJoint:
""" """
Creates the elbow and wrist joints. Creates the elbow and wrist joints.
@ -576,6 +581,9 @@ class ElbowJoint:
material: Material = Material.RESIN_TRANSPERENT material: Material = Material.RESIN_TRANSPERENT
# If true, flip the top and bottom tags
flip: bool = False
def __post_init__(self): def __post_init__(self):
assert self.child_arm_radius > self.disk_joint.radius_housing assert self.child_arm_radius > self.disk_joint.radius_housing
assert self.parent_arm_radius > self.disk_joint.radius_housing assert self.parent_arm_radius > self.disk_joint.radius_housing
@ -605,7 +613,7 @@ class ElbowJoint:
flip_x = Cq.Location((0, 0, 0), (1, 0, 0), 180) flip_x = Cq.Location((0, 0, 0), (1, 0, 0), 180)
flip_z = Cq.Location((0, 0, 0), (0, 0, 1), 180) flip_z = Cq.Location((0, 0, 0), (0, 0, 1), 180)
result = ( result = (
self.child_beam.beam() self.child_beam.generate(flip=self.flip)
.add(self.disk_joint.disk(), name="disk", .add(self.disk_joint.disk(), name="disk",
loc=flip_x * flip_z * Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle)) loc=flip_x * flip_z * Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle))
#.constrain("disk", "Fixed") #.constrain("disk", "Fixed")
@ -641,7 +649,7 @@ class ElbowJoint:
-self.disk_joint.tongue_span / 2 -self.disk_joint.tongue_span / 2
) )
result = ( result = (
self.parent_beam.beam() self.parent_beam.generate(flip=self.flip)
.add(housing, name="housing", .add(housing, name="housing",
loc=axial_offset * housing_loc) loc=axial_offset * housing_loc)
.add(connector, name="connector", .add(connector, name="connector",

View File

@ -11,10 +11,10 @@ from nhf import Material, Role
from nhf.build import Model, target, assembly from nhf.build import Model, target, assembly
from nhf.parts.box import box_with_centre_holes, MountingBox, Hole from nhf.parts.box import box_with_centre_holes, MountingBox, Hole
from nhf.parts.joints import HirthJoint from nhf.parts.joints import HirthJoint
from nhf.touhou.houjuu_nue.joints import ShoulderJoint, ElbowJoint from nhf.touhou.houjuu_nue.joints import ShoulderJoint, ElbowJoint, DiskJoint
import nhf.utils import nhf.utils
@dataclass @dataclass(kw_only=True)
class WingProfile(Model): class WingProfile(Model):
name: str = "wing" name: str = "wing"
@ -34,7 +34,12 @@ class WingProfile(Model):
s1_thickness: float = 25.0 s1_thickness: float = 25.0
elbow_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint()) elbow_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
disk_joint=DiskJoint(
movement_angle=55,
),
flip=False,
))
elbow_height: float = 100 elbow_height: float = 100
elbow_x: float = 240 elbow_x: float = 240
elbow_y: float = 30 elbow_y: float = 30
@ -43,7 +48,12 @@ class WingProfile(Model):
s2_thickness: float = 25.0 s2_thickness: float = 25.0
wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint()) wrist_joint: ElbowJoint = field(default_factory=lambda: ElbowJoint(
disk_joint=DiskJoint(
movement_angle=45,
),
flip=True,
))
wrist_height: float = 70 wrist_height: float = 70
# Bottom point of the wrist # Bottom point of the wrist
wrist_x: float = 400 wrist_x: float = 400
@ -548,6 +558,8 @@ class WingProfile(Model):
parts: Optional[list[str]] = None, parts: Optional[list[str]] = None,
angle_elbow_wrist: float = 0.0, angle_elbow_wrist: float = 0.0,
) -> Cq.Assembly(): ) -> Cq.Assembly():
assert not self.elbow_joint.flip
assert self.wrist_joint.flip
if parts is None: if parts is None:
parts = ["s0", "shoulder", "s1", "elbow", "s2", "wrist", "s3"] parts = ["s0", "shoulder", "s1", "elbow", "s2", "wrist", "s3"]
result = ( result = (
@ -601,20 +613,20 @@ class WingProfile(Model):
# Mounted backwards to bend in other direction # Mounted backwards to bend in other direction
( (
result result
.constrain("s2/wrist_top?conn0", "wrist/parent_upper/bot?conn0", "Plane") .constrain("s2/wrist_top?conn0", "wrist/parent_upper/top?conn0", "Plane")
.constrain("s2/wrist_top?conn1", "wrist/parent_upper/bot?conn1", "Plane") .constrain("s2/wrist_top?conn1", "wrist/parent_upper/top?conn1", "Plane")
.constrain("s2/wrist_bot?conn0", "wrist/parent_upper/top?conn0", "Plane") .constrain("s2/wrist_bot?conn0", "wrist/parent_upper/bot?conn0", "Plane")
.constrain("s2/wrist_bot?conn1", "wrist/parent_upper/top?conn1", "Plane") .constrain("s2/wrist_bot?conn1", "wrist/parent_upper/bot?conn1", "Plane")
) )
if "s3" in parts: if "s3" in parts:
result.add(self.assembly_s3(), name="s3") result.add(self.assembly_s3(), name="s3")
if "s3" in parts and "wrist" in parts: if "s3" in parts and "wrist" in parts:
( (
result result
.constrain("s3/wrist_top?conn0", "wrist/child/bot?conn0", "Plane") .constrain("s3/wrist_top?conn0", "wrist/child/top?conn0", "Plane")
.constrain("s3/wrist_top?conn1", "wrist/child/bot?conn1", "Plane") .constrain("s3/wrist_top?conn1", "wrist/child/top?conn1", "Plane")
.constrain("s3/wrist_bot?conn0", "wrist/child/top?conn0", "Plane") .constrain("s3/wrist_bot?conn0", "wrist/child/bot?conn0", "Plane")
.constrain("s3/wrist_bot?conn1", "wrist/child/top?conn1", "Plane") .constrain("s3/wrist_bot?conn1", "wrist/child/bot?conn1", "Plane")
) )
if len(parts) > 1: if len(parts) > 1:
result.solve() result.solve()