cosplay: Touhou/Houjuu Nue #4
|
@ -21,7 +21,7 @@ class Role(Enum):
|
||||||
STRUCTURE = _color('gray', 0.4)
|
STRUCTURE = _color('gray', 0.4)
|
||||||
DECORATION = _color('lightseagreen', 0.4)
|
DECORATION = _color('lightseagreen', 0.4)
|
||||||
ELECTRONIC = _color('mediumorchid', 0.5)
|
ELECTRONIC = _color('mediumorchid', 0.5)
|
||||||
MARKER = _color('white', 1.0)
|
MARKER = _color('cyan', 1.0)
|
||||||
|
|
||||||
def __init__(self, color: Cq.Color):
|
def __init__(self, color: Cq.Color):
|
||||||
self.color = color
|
self.color = color
|
||||||
|
|
|
@ -599,7 +599,9 @@ class Parameters(Model):
|
||||||
"s2/elbow_top_spacer?conn1",
|
"s2/elbow_top_spacer?conn1",
|
||||||
"Plane")
|
"Plane")
|
||||||
)
|
)
|
||||||
return result.solve()
|
if len(parts) > 1:
|
||||||
|
result.solve()
|
||||||
|
return result
|
||||||
|
|
||||||
@assembly()
|
@assembly()
|
||||||
def wings_assembly(self) -> Cq.Assembly:
|
def wings_assembly(self) -> Cq.Assembly:
|
||||||
|
|
|
@ -262,7 +262,7 @@ class Beam:
|
||||||
.add(self.foot(), name="top",
|
.add(self.foot(), name="top",
|
||||||
loc=Cq.Location((0, h, 0)))
|
loc=Cq.Location((0, h, 0)))
|
||||||
.add(self.foot(), name="bot",
|
.add(self.foot(), name="bot",
|
||||||
loc=Cq.Location((0, -h, 0), (0, 0, 1), 180))
|
loc=Cq.Location((0, -h, 0), (1, 0, 0), 180))
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -424,7 +424,10 @@ class DiskJoint(Model):
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
result.faces(">Z").tag("mate")
|
result.faces(">Z").tag("mate")
|
||||||
result.faces(">Z").workplane().tagPlane("dir", direction="+X")
|
result.faces(">Z").workplane().tagPlane("dirX", direction="+X")
|
||||||
|
# two directional vectors are required to make the angle constrain
|
||||||
|
# unambiguous
|
||||||
|
result.faces(">Z").workplane().tagPlane("dirY", direction="+Y")
|
||||||
result = result.cut(
|
result = result.cut(
|
||||||
self
|
self
|
||||||
.wall()
|
.wall()
|
||||||
|
@ -486,17 +489,15 @@ class DiskJoint(Model):
|
||||||
housing_lower: str,
|
housing_lower: str,
|
||||||
housing_upper: str,
|
housing_upper: str,
|
||||||
disk: str,
|
disk: str,
|
||||||
angle: Tuple[float, float, float] = (0, 0, 0),
|
angle: float,
|
||||||
) -> Cq.Assembly:
|
) -> Cq.Assembly:
|
||||||
"""
|
|
||||||
The angle supplied must be perpendicular to the disk normal.
|
|
||||||
"""
|
|
||||||
(
|
(
|
||||||
assembly
|
assembly
|
||||||
.constrain(f"{disk}?mate_bot", f"{housing_lower}?mate", "Plane")
|
.constrain(f"{disk}?mate_bot", f"{housing_lower}?mate", "Plane")
|
||||||
.constrain(f"{disk}?mate_top", f"{housing_upper}?mate", "Plane")
|
.constrain(f"{disk}?mate_top", f"{housing_upper}?mate", "Plane")
|
||||||
.constrain(f"{housing_lower}?dir", f"{housing_upper}?dir", "Axis")
|
.constrain(f"{housing_lower}?dirX", f"{housing_upper}?dir", "Axis")
|
||||||
.constrain(f"{disk}?dir", "FixedRotation", angle)
|
.constrain(f"{housing_lower}?dirX", f"{disk}?dir", "Axis", param=angle)
|
||||||
|
.constrain(f"{housing_lower}?dirY", f"{disk}?dir", "Axis", param=angle - 90)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -519,7 +520,7 @@ class DiskJoint(Model):
|
||||||
housing_lower="housing_lower",
|
housing_lower="housing_lower",
|
||||||
housing_upper="housing_upper",
|
housing_upper="housing_upper",
|
||||||
disk="disk",
|
disk="disk",
|
||||||
angle=(0, 0, angle),
|
angle=angle,
|
||||||
)
|
)
|
||||||
return result.solve()
|
return result.solve()
|
||||||
|
|
||||||
|
@ -567,10 +568,16 @@ class ElbowJoint:
|
||||||
def child_joint(self) -> Cq.Assembly:
|
def child_joint(self) -> Cq.Assembly:
|
||||||
angle = -self.disk_joint.tongue_span / 2
|
angle = -self.disk_joint.tongue_span / 2
|
||||||
dz = self.disk_joint.disk_thickness / 2
|
dz = self.disk_joint.disk_thickness / 2
|
||||||
|
# We need to ensure the disk is on the "other" side so
|
||||||
|
flip = Cq.Location((0, 0, 0), (0, 0, 1), 180)
|
||||||
result = (
|
result = (
|
||||||
self.child_beam.beam()
|
self.child_beam.beam()
|
||||||
.add(self.disk_joint.disk(), name="disk",
|
.add(self.disk_joint.disk(), name="disk",
|
||||||
loc=Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle))
|
loc=flip * Cq.Location((-self.child_arm_radius, 0, -dz), (0, 0, 1), angle))
|
||||||
|
.constrain("disk", "Fixed")
|
||||||
|
.constrain("top", "Fixed")
|
||||||
|
.constrain("bot", "Fixed")
|
||||||
|
.solve()
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -600,24 +607,27 @@ class ElbowJoint:
|
||||||
loc=axial_offset * Cq.Location((0, 0, housing_dz)))
|
loc=axial_offset * Cq.Location((0, 0, housing_dz)))
|
||||||
.add(connector, name="connector",
|
.add(connector, name="connector",
|
||||||
loc=axial_offset)
|
loc=axial_offset)
|
||||||
|
.constrain("housing", "Fixed")
|
||||||
|
.constrain("connector", "Fixed")
|
||||||
|
.solve()
|
||||||
)
|
)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def assembly(self, angle: float = 0) -> Cq.Assembly:
|
def assembly(self, angle: float = 0) -> Cq.Assembly:
|
||||||
da = self.disk_joint.tongue_span / 2
|
da = self.disk_joint.tongue_span / 2 + 180
|
||||||
result = (
|
result = (
|
||||||
Cq.Assembly()
|
Cq.Assembly()
|
||||||
.add(self.child_joint(), name="child", color=Role.CHILD.color)
|
.add(self.child_joint(), name="child", color=Role.CHILD.color)
|
||||||
.add(self.parent_joint_lower(), name="parent_lower", color=Role.CASING.color)
|
.add(self.parent_joint_lower(), name="parent_lower", color=Role.CASING.color)
|
||||||
.add(self.parent_joint_upper(), name="parent_upper", color=Role.PARENT.color)
|
.add(self.parent_joint_upper(), name="parent_upper", color=Role.PARENT.color)
|
||||||
.constrain("parent_lower", "Fixed")
|
#.constrain("parent_lower", "Fixed")
|
||||||
)
|
)
|
||||||
self.disk_joint.add_constraints(
|
self.disk_joint.add_constraints(
|
||||||
result,
|
result,
|
||||||
housing_lower="parent_lower",
|
housing_lower="parent_lower",
|
||||||
housing_upper="parent_upper/housing",
|
housing_upper="parent_upper/housing",
|
||||||
disk="child/disk",
|
disk="child/disk",
|
||||||
angle=(0, 0, angle + da),
|
angle=angle,
|
||||||
)
|
)
|
||||||
return result.solve()
|
return result.solve()
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,9 @@ def make_arrow(size: float = 2) -> Cq.Workplane:
|
||||||
result.faces("<Z").tag("dir_rev")
|
result.faces("<Z").tag("dir_rev")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def to_marker_name(tag: str) -> str:
|
||||||
|
return tag.replace("?", "__T").replace("/", "__Z") + "_marker"
|
||||||
|
|
||||||
def mark_point(self: Cq.Assembly,
|
def mark_point(self: Cq.Assembly,
|
||||||
tag: str,
|
tag: str,
|
||||||
size: float = 2,
|
size: float = 2,
|
||||||
|
@ -77,7 +80,7 @@ def mark_point(self: Cq.Assembly,
|
||||||
"""
|
"""
|
||||||
Adds a marker to make a point visible
|
Adds a marker to make a point visible
|
||||||
"""
|
"""
|
||||||
name = f"{tag}_marker"
|
name = to_marker_name(tag)
|
||||||
return (
|
return (
|
||||||
self
|
self
|
||||||
.add(make_sphere(size), name=name, color=color)
|
.add(make_sphere(size), name=name, color=color)
|
||||||
|
@ -93,7 +96,7 @@ def mark_plane(self: Cq.Assembly,
|
||||||
"""
|
"""
|
||||||
Adds a marker to make a plane visible
|
Adds a marker to make a plane visible
|
||||||
"""
|
"""
|
||||||
name = tag.replace("?", "__") + "_marker"
|
name = to_marker_name(tag)
|
||||||
return (
|
return (
|
||||||
self
|
self
|
||||||
.add(make_arrow(size), name=name, color=color)
|
.add(make_arrow(size), name=name, color=color)
|
||||||
|
|
Loading…
Reference in New Issue