cosplay: Touhou/Houjuu Nue #4
|
@ -70,7 +70,7 @@ class Parameters(Model):
|
||||||
))
|
))
|
||||||
wing_l3: MW.WingL = field(default_factory=lambda: MW.WingL(
|
wing_l3: MW.WingL = field(default_factory=lambda: MW.WingL(
|
||||||
name="l3",
|
name="l3",
|
||||||
wrist_angle=0.0,
|
wrist_angle=-0.0,
|
||||||
))
|
))
|
||||||
|
|
||||||
trident: MT.Trident = field(default_factory=lambda: MT.Trident())
|
trident: MT.Trident = field(default_factory=lambda: MT.Trident())
|
||||||
|
|
|
@ -81,13 +81,9 @@ class WingProfile(Model):
|
||||||
role_panel: Role = Role.STRUCTURE
|
role_panel: Role = Role.STRUCTURE
|
||||||
|
|
||||||
# Subclass must populate
|
# Subclass must populate
|
||||||
elbow_x: float
|
elbow_bot_loc: Cq.Location
|
||||||
elbow_y: float
|
|
||||||
elbow_angle: float
|
|
||||||
elbow_height: float
|
elbow_height: float
|
||||||
wrist_x: float
|
wrist_bot_loc: Cq.Location
|
||||||
wrist_y: float
|
|
||||||
wrist_angle: float
|
|
||||||
wrist_height: float
|
wrist_height: float
|
||||||
|
|
||||||
flip: bool = False
|
flip: bool = False
|
||||||
|
@ -95,14 +91,8 @@ class WingProfile(Model):
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
super().__init__(name=self.name)
|
super().__init__(name=self.name)
|
||||||
|
|
||||||
self.elbow_theta = math.radians(self.elbow_angle)
|
self.elbow_top_loc = self.elbow_bot_loc * Cq.Location.from2d(0, self.elbow_height)
|
||||||
self.elbow_c = math.cos(self.elbow_theta)
|
self.wrist_top_loc = self.wrist_bot_loc * Cq.Location.from2d(0, self.wrist_height)
|
||||||
self.elbow_s = math.sin(self.elbow_theta)
|
|
||||||
self.elbow_top_x, self.elbow_top_y = self.elbow_to_abs(0, self.elbow_height)
|
|
||||||
self.wrist_theta = math.radians(self.wrist_angle)
|
|
||||||
self.wrist_c = math.cos(self.wrist_theta)
|
|
||||||
self.wrist_s = math.sin(self.wrist_theta)
|
|
||||||
self.wrist_top_x, self.wrist_top_y = self.wrist_to_abs(0, self.wrist_height)
|
|
||||||
|
|
||||||
self.shoulder_joint.angle_neutral = -self.shoulder_angle_neutral
|
self.shoulder_joint.angle_neutral = -self.shoulder_angle_neutral
|
||||||
|
|
||||||
|
@ -401,16 +391,6 @@ class WingProfile(Model):
|
||||||
"Axis", param=angle)
|
"Axis", param=angle)
|
||||||
)
|
)
|
||||||
|
|
||||||
def elbow_to_abs(self, x: float, y: float) -> Tuple[float, float]:
|
|
||||||
elbow_x = self.elbow_x + x * self.elbow_c - y * self.elbow_s
|
|
||||||
elbow_y = self.elbow_y + x * self.elbow_s + y * self.elbow_c
|
|
||||||
return elbow_x, elbow_y
|
|
||||||
def wrist_to_abs(self, x: float, y: float) -> Tuple[float, float]:
|
|
||||||
wrist_x = self.wrist_x + x * self.wrist_c - y * self.wrist_s
|
|
||||||
wrist_y = self.wrist_y + x * self.wrist_s + y * self.wrist_c
|
|
||||||
return wrist_x, wrist_y
|
|
||||||
|
|
||||||
|
|
||||||
def _mask_elbow(self) -> list[Tuple[float, float]]:
|
def _mask_elbow(self) -> list[Tuple[float, float]]:
|
||||||
"""
|
"""
|
||||||
Polygon shape to mask out parts above the elbow
|
Polygon shape to mask out parts above the elbow
|
||||||
|
@ -459,12 +439,12 @@ class WingProfile(Model):
|
||||||
]
|
]
|
||||||
h = self.elbow_height / 2
|
h = self.elbow_height / 2
|
||||||
tags_elbow = [
|
tags_elbow = [
|
||||||
("elbow_bot", Cq.Location.from2d(
|
("elbow_bot", self.elbow_bot_loc * Cq.Location.from2d(
|
||||||
*self.elbow_to_abs(-self.elbow_joint.parent_arm_radius, h - self.elbow_h2),
|
-self.elbow_joint.parent_arm_radius,
|
||||||
self.elbow_angle + 0)),
|
h - self.elbow_h2)),
|
||||||
("elbow_top", Cq.Location.from2d(
|
("elbow_top", self.elbow_bot_loc * Cq.Location.from2d(
|
||||||
*self.elbow_to_abs(-self.elbow_joint.parent_arm_radius, h + self.elbow_h2),
|
-self.elbow_joint.parent_arm_radius,
|
||||||
self.elbow_angle + 0)),
|
h + self.elbow_h2)),
|
||||||
]
|
]
|
||||||
profile = self.profile_s1()
|
profile = self.profile_s1()
|
||||||
tags = tags_shoulder + tags_elbow
|
tags = tags_shoulder + tags_elbow
|
||||||
|
@ -527,21 +507,23 @@ class WingProfile(Model):
|
||||||
def surface_s2(self, front: bool = True) -> Cq.Workplane:
|
def surface_s2(self, front: bool = True) -> Cq.Workplane:
|
||||||
h = self.elbow_height / 2
|
h = self.elbow_height / 2
|
||||||
tags_elbow = [
|
tags_elbow = [
|
||||||
("elbow_bot", Cq.Location.from2d(
|
("elbow_bot", self.elbow_bot_loc * Cq.Location.from2d(
|
||||||
*self.elbow_to_abs(self.elbow_joint.child_arm_radius, h - self.elbow_h2),
|
self.elbow_joint.child_arm_radius,
|
||||||
self.elbow_angle + 180)),
|
h - self.elbow_h2,
|
||||||
("elbow_top", Cq.Location.from2d(
|
180)),
|
||||||
*self.elbow_to_abs(self.elbow_joint.child_arm_radius, h + self.elbow_h2),
|
("elbow_top", self.elbow_bot_loc * Cq.Location.from2d(
|
||||||
self.elbow_angle + 180)),
|
self.elbow_joint.child_arm_radius,
|
||||||
|
h + self.elbow_h2,
|
||||||
|
180)),
|
||||||
]
|
]
|
||||||
h = self.wrist_height / 2
|
h = self.wrist_height / 2
|
||||||
tags_wrist = [
|
tags_wrist = [
|
||||||
("wrist_bot", Cq.Location.from2d(
|
("wrist_bot", self.wrist_bot_loc * Cq.Location.from2d(
|
||||||
*self.wrist_to_abs(-self.wrist_joint.parent_arm_radius, h - self.wrist_h2),
|
-self.wrist_joint.parent_arm_radius,
|
||||||
self.wrist_angle)),
|
h - self.wrist_h2)),
|
||||||
("wrist_top", Cq.Location.from2d(
|
("wrist_top", self.wrist_bot_loc * Cq.Location.from2d(
|
||||||
*self.wrist_to_abs(-self.wrist_joint.parent_arm_radius, h + self.wrist_h2),
|
-self.wrist_joint.parent_arm_radius,
|
||||||
self.wrist_angle)),
|
h + self.wrist_h2)),
|
||||||
]
|
]
|
||||||
profile = self.profile_s2()
|
profile = self.profile_s2()
|
||||||
tags = tags_elbow + tags_wrist
|
tags = tags_elbow + tags_wrist
|
||||||
|
@ -597,12 +579,14 @@ class WingProfile(Model):
|
||||||
front: bool = True) -> Cq.Workplane:
|
front: bool = True) -> Cq.Workplane:
|
||||||
h = self.wrist_height / 2
|
h = self.wrist_height / 2
|
||||||
tags = [
|
tags = [
|
||||||
("wrist_bot", Cq.Location.from2d(
|
("wrist_bot", self.wrist_bot_loc * Cq.Location.from2d(
|
||||||
*self.wrist_to_abs(self.wrist_joint.child_arm_radius, h - self.wrist_h2),
|
self.wrist_joint.child_arm_radius,
|
||||||
self.wrist_angle + 180)),
|
h - self.wrist_h2,
|
||||||
("wrist_top", Cq.Location.from2d(
|
180)),
|
||||||
*self.wrist_to_abs(self.wrist_joint.child_arm_radius, h + self.wrist_h2),
|
("wrist_top", self.wrist_bot_loc * Cq.Location.from2d(
|
||||||
self.wrist_angle + 180)),
|
self.wrist_joint.child_arm_radius,
|
||||||
|
h + self.wrist_h2,
|
||||||
|
180)),
|
||||||
]
|
]
|
||||||
profile = self.profile_s3()
|
profile = self.profile_s3()
|
||||||
return extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
|
return extrude_with_markers(profile, self.panel_thickness, tags, reverse=front)
|
||||||
|
@ -726,45 +710,34 @@ class WingR(WingProfile):
|
||||||
Right side wings
|
Right side wings
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
elbow_bot_loc: Cq.Location = Cq.Location.from2d(285.0, 5.0, 25.0)
|
||||||
elbow_height: float = 111.0
|
elbow_height: float = 111.0
|
||||||
elbow_x: float = 285.0
|
|
||||||
elbow_y: float = 5.0
|
|
||||||
# Tilt of elbow w.r.t. shoulder
|
|
||||||
elbow_angle: float = 25.0
|
|
||||||
|
|
||||||
|
wrist_bot_loc: Cq.Location = Cq.Location.from2d(403.0, 253.0, 40.0)
|
||||||
wrist_height: float = 60.0
|
wrist_height: float = 60.0
|
||||||
# Bottom point of the wrist
|
|
||||||
wrist_x: float = 403.0
|
|
||||||
wrist_y: float = 253.0
|
|
||||||
|
|
||||||
# Tile of wrist w.r.t. shoulder
|
|
||||||
wrist_angle: float = 40
|
|
||||||
# Extends from the wrist to the tip of the arrow
|
# Extends from the wrist to the tip of the arrow
|
||||||
arrow_height: float = 300
|
arrow_height: float = 300
|
||||||
arrow_angle: float = 8
|
arrow_angle: float = -8
|
||||||
|
|
||||||
# Relative (in wrist coordinate) centre of the ring
|
# Relative (in wrist coordinate) centre of the ring
|
||||||
ring_x: float = 45
|
ring_rel_loc: Cq.Location = Cq.Location.from2d(45.0, 25.0)
|
||||||
ring_y: float = 25
|
ring_radius_inner: float = 22.0
|
||||||
ring_radius_inner: float = 22
|
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
super().__post_init__()
|
super().__post_init__()
|
||||||
self.arrow_theta = math.radians(self.arrow_angle)
|
assert self.arrow_angle < 0, "Arrow angle cannot be positive"
|
||||||
self.arrow_x, self.arrow_y = self.wrist_to_abs(0, -self.arrow_height)
|
self.arrow_bot_loc = self.wrist_bot_loc \
|
||||||
self.arrow_tip_x = self.arrow_x + (self.arrow_height + self.wrist_height) \
|
* Cq.Location.from2d(0, -self.arrow_height)
|
||||||
* math.sin(self.arrow_theta - self.wrist_theta)
|
self.arrow_other_loc = self.arrow_bot_loc \
|
||||||
self.arrow_tip_y = self.arrow_y + (self.arrow_height + self.wrist_height) \
|
* Cq.Location.rot2d(self.arrow_angle) \
|
||||||
* math.cos(self.arrow_theta - self.wrist_theta)
|
* Cq.Location.from2d(0, self.arrow_height + self.wrist_height)
|
||||||
# [[c, s], [-s, c]] * [ring_x, ring_y]
|
self.ring_loc = self.wrist_top_loc * self.ring_rel_loc
|
||||||
self.ring_abs_x = self.wrist_top_x + self.wrist_c * self.ring_x - self.wrist_s * self.ring_y
|
|
||||||
self.ring_abs_y = self.wrist_top_y + self.wrist_s * self.ring_x + self.wrist_c * self.ring_y
|
|
||||||
assert self.ring_radius > self.ring_radius_inner
|
assert self.ring_radius > self.ring_radius_inner
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ring_radius(self) -> float:
|
def ring_radius(self) -> float:
|
||||||
dx = self.ring_x
|
(dx, dy), _ = self.ring_rel_loc.to2d()
|
||||||
dy = self.ring_y
|
|
||||||
return (dx * dx + dy * dy) ** 0.5
|
return (dx * dx + dy * dy) ** 0.5
|
||||||
|
|
||||||
def profile(self) -> Cq.Sketch:
|
def profile(self) -> Cq.Sketch:
|
||||||
|
@ -779,8 +752,8 @@ class WingR(WingProfile):
|
||||||
tag="shoulder")
|
tag="shoulder")
|
||||||
.spline([
|
.spline([
|
||||||
(0, self.shoulder_joint.height),
|
(0, self.shoulder_joint.height),
|
||||||
(self.elbow_top_x, self.elbow_top_y),
|
self.elbow_top_loc.to2d_pos(),
|
||||||
(self.wrist_top_x, self.wrist_top_y),
|
self.wrist_top_loc.to2d_pos(),
|
||||||
],
|
],
|
||||||
tag="s1_top")
|
tag="s1_top")
|
||||||
#.segment(
|
#.segment(
|
||||||
|
@ -789,31 +762,31 @@ class WingR(WingProfile):
|
||||||
# tag="wrist")
|
# tag="wrist")
|
||||||
.spline([
|
.spline([
|
||||||
(0, 0),
|
(0, 0),
|
||||||
(self.elbow_x, self.elbow_y),
|
self.elbow_bot_loc.to2d_pos(),
|
||||||
(self.wrist_x, self.wrist_y),
|
self.wrist_bot_loc.to2d_pos(),
|
||||||
],
|
],
|
||||||
tag="s1_bot")
|
tag="s1_bot")
|
||||||
)
|
)
|
||||||
result = (
|
result = (
|
||||||
result
|
result
|
||||||
.segment(
|
.segment(
|
||||||
(self.wrist_x, self.wrist_y),
|
self.wrist_bot_loc.to2d_pos(),
|
||||||
(self.arrow_x, self.arrow_y)
|
self.arrow_bot_loc.to2d_pos(),
|
||||||
)
|
)
|
||||||
.segment(
|
.segment(
|
||||||
(self.arrow_x, self.arrow_y),
|
self.arrow_bot_loc.to2d_pos(),
|
||||||
(self.arrow_tip_x, self.arrow_tip_y)
|
self.arrow_other_loc.to2d_pos(),
|
||||||
)
|
)
|
||||||
.segment(
|
.segment(
|
||||||
(self.arrow_tip_x, self.arrow_tip_y),
|
self.arrow_other_loc.to2d_pos(),
|
||||||
(self.wrist_top_x, self.wrist_top_y)
|
self.wrist_top_loc.to2d_pos(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# Carve out the ring
|
# Carve out the ring
|
||||||
result = result.assemble()
|
result = result.assemble()
|
||||||
result = (
|
result = (
|
||||||
result
|
result
|
||||||
.push([(self.ring_abs_x, self.ring_abs_y)])
|
.push([self.ring_loc.to2d_pos()])
|
||||||
.circle(self.ring_radius, mode='a')
|
.circle(self.ring_radius, mode='a')
|
||||||
.circle(self.ring_radius_inner, mode='s')
|
.circle(self.ring_radius_inner, mode='s')
|
||||||
.clean()
|
.clean()
|
||||||
|
@ -822,38 +795,39 @@ class WingR(WingProfile):
|
||||||
|
|
||||||
def _mask_elbow(self) -> list[Tuple[float, float]]:
|
def _mask_elbow(self) -> list[Tuple[float, float]]:
|
||||||
l = 200
|
l = 200
|
||||||
|
elbow_x, _ = self.elbow_bot_loc.to2d_pos()
|
||||||
|
elbow_top_x, _ = self.elbow_top_loc.to2d_pos()
|
||||||
return [
|
return [
|
||||||
(0, -l),
|
(0, -l),
|
||||||
(self.elbow_x, -l),
|
(elbow_x, -l),
|
||||||
(self.elbow_x, self.elbow_y),
|
self.elbow_bot_loc.to2d_pos(),
|
||||||
(self.elbow_top_x, self.elbow_top_y),
|
self.elbow_top_loc.to2d_pos(),
|
||||||
(self.elbow_top_x, l),
|
(elbow_top_x, l),
|
||||||
(0, l)
|
(0, l)
|
||||||
]
|
]
|
||||||
|
|
||||||
def _mask_wrist(self) -> list[Tuple[float, float]]:
|
def _mask_wrist(self) -> list[Tuple[float, float]]:
|
||||||
l = 200
|
l = 200
|
||||||
|
wrist_x, _ = self.wrist_bot_loc.to2d_pos()
|
||||||
|
_, wrist_top_y = self.wrist_top_loc.to2d_pos()
|
||||||
return [
|
return [
|
||||||
(0, -l),
|
(0, -l),
|
||||||
(self.wrist_x, -l),
|
(wrist_x, -l),
|
||||||
(self.wrist_x, self.wrist_y),
|
self.wrist_bot_loc.to2d_pos(),
|
||||||
(self.wrist_top_x, self.wrist_top_y),
|
self.wrist_top_loc.to2d_pos(),
|
||||||
#(self.wrist_top_x, self.wrist_top_y),
|
#(self.wrist_top_x, self.wrist_top_y),
|
||||||
(0, self.wrist_top_y),
|
(0, wrist_top_y),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@dataclass(kw_only=True)
|
@dataclass(kw_only=True)
|
||||||
class WingL(WingProfile):
|
class WingL(WingProfile):
|
||||||
|
|
||||||
elbow_x: float = 230.0
|
elbow_bot_loc: Cq.Location = Cq.Location.from2d(230.0, 110.0, -10.0)
|
||||||
elbow_y: float = 110.0
|
|
||||||
elbow_angle: float = -10.0
|
|
||||||
elbow_height: float = 80.0
|
elbow_height: float = 80.0
|
||||||
|
|
||||||
wrist_x: float = 480.0
|
wrist_angle: float = -45.0
|
||||||
wrist_y: float = 0.0
|
wrist_bot_loc: Cq.Location = Cq.Location.from2d(480.0, 0.0, -45.0)
|
||||||
wrist_angle: float = -45
|
|
||||||
wrist_height: float = 43.0
|
wrist_height: float = 43.0
|
||||||
|
|
||||||
shoulder_bezier_ext: float = 80.0
|
shoulder_bezier_ext: float = 80.0
|
||||||
|
@ -866,11 +840,14 @@ class WingL(WingProfile):
|
||||||
flip: bool = True
|
flip: bool = True
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
super().__post_init__()
|
|
||||||
assert self.wrist_height <= self.shoulder_joint.height
|
assert self.wrist_height <= self.shoulder_joint.height
|
||||||
|
self.wrist_bot_loc = self.wrist_bot_loc.with_angle_2d(self.wrist_angle)
|
||||||
|
|
||||||
|
super().__post_init__()
|
||||||
|
|
||||||
def arrow_to_abs(self, x, y) -> Tuple[float, float]:
|
def arrow_to_abs(self, x, y) -> Tuple[float, float]:
|
||||||
return self.wrist_to_abs(x * self.arrow_length, y * self.arrow_height / 2 + self.wrist_height / 2)
|
rel = Cq.Location.from2d(x * self.arrow_length, y * self.arrow_height / 2 + self.wrist_height / 2)
|
||||||
|
return (self.wrist_bot_loc * rel).to2d_pos()
|
||||||
|
|
||||||
def profile(self) -> Cq.Sketch:
|
def profile(self) -> Cq.Sketch:
|
||||||
result = (
|
result = (
|
||||||
|
@ -879,39 +856,29 @@ class WingL(WingProfile):
|
||||||
(0,0),
|
(0,0),
|
||||||
(0, self.shoulder_height)
|
(0, self.shoulder_height)
|
||||||
)
|
)
|
||||||
#.spline([
|
|
||||||
# (0, 0),
|
|
||||||
# self.elbow_to_abs(0, 0),
|
|
||||||
# self.wrist_to_abs(0, 0),
|
|
||||||
#])
|
|
||||||
#.spline([
|
|
||||||
# (0, self.shoulder_height),
|
|
||||||
# self.elbow_to_abs(0, self.elbow_height),
|
|
||||||
# self.wrist_to_abs(0, self.wrist_height),
|
|
||||||
#])
|
|
||||||
.bezier([
|
.bezier([
|
||||||
(0, 0),
|
(0, 0),
|
||||||
(self.shoulder_bezier_ext, 0),
|
(self.shoulder_bezier_ext, 0),
|
||||||
self.elbow_to_abs(-self.elbow_bezier_ext, 0),
|
(self.elbow_bot_loc * Cq.Location.from2d(-self.elbow_bezier_ext, 0)).to2d_pos(),
|
||||||
self.elbow_to_abs(0, 0),
|
self.elbow_bot_loc.to2d_pos(),
|
||||||
])
|
])
|
||||||
.bezier([
|
.bezier([
|
||||||
(0, self.shoulder_joint.height),
|
(0, self.shoulder_joint.height),
|
||||||
(self.shoulder_bezier_ext, self.shoulder_joint.height),
|
(self.shoulder_bezier_ext, self.shoulder_joint.height),
|
||||||
self.elbow_to_abs(-self.elbow_bezier_ext, self.elbow_height),
|
(self.elbow_top_loc * Cq.Location.from2d(-self.elbow_bezier_ext, 0)).to2d_pos(),
|
||||||
self.elbow_to_abs(0, self.elbow_height),
|
self.elbow_top_loc.to2d_pos(),
|
||||||
])
|
])
|
||||||
.bezier([
|
.bezier([
|
||||||
self.elbow_to_abs(0, 0),
|
self.elbow_bot_loc.to2d_pos(),
|
||||||
self.elbow_to_abs(self.elbow_bezier_ext, 0),
|
(self.elbow_bot_loc * Cq.Location.from2d(self.elbow_bezier_ext, 0)).to2d_pos(),
|
||||||
self.wrist_to_abs(-self.wrist_bezier_ext, 0),
|
(self.wrist_bot_loc * Cq.Location.from2d(-self.wrist_bezier_ext, 0)).to2d_pos(),
|
||||||
self.wrist_to_abs(0, 0),
|
self.wrist_bot_loc.to2d_pos(),
|
||||||
])
|
])
|
||||||
.bezier([
|
.bezier([
|
||||||
self.elbow_to_abs(0, self.elbow_height),
|
self.elbow_top_loc.to2d_pos(),
|
||||||
self.elbow_to_abs(self.elbow_bezier_ext, self.elbow_height),
|
(self.elbow_top_loc * Cq.Location.from2d(self.elbow_bezier_ext, 0)).to2d_pos(),
|
||||||
self.wrist_to_abs(-self.wrist_bezier_ext, self.wrist_height),
|
(self.wrist_top_loc * Cq.Location.from2d(-self.wrist_bezier_ext, 0)).to2d_pos(),
|
||||||
self.wrist_to_abs(0, self.wrist_height),
|
self.wrist_top_loc.to2d_pos(),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
# arrow base positions
|
# arrow base positions
|
||||||
|
@ -919,13 +886,13 @@ class WingL(WingProfile):
|
||||||
result = (
|
result = (
|
||||||
result
|
result
|
||||||
.bezier([
|
.bezier([
|
||||||
self.wrist_to_abs(0, self.wrist_height),
|
self.wrist_top_loc.to2d_pos(),
|
||||||
self.wrist_to_abs(self.wrist_bezier_ext, self.wrist_height),
|
(self.wrist_top_loc * Cq.Location.from2d(self.wrist_bezier_ext, 0)).to2d_pos(),
|
||||||
self.arrow_to_abs(base_u, base_v),
|
self.arrow_to_abs(base_u, base_v),
|
||||||
])
|
])
|
||||||
.bezier([
|
.bezier([
|
||||||
self.wrist_to_abs(0, 0),
|
self.wrist_bot_loc.to2d_pos(),
|
||||||
self.wrist_to_abs(self.wrist_bezier_ext, 0),
|
(self.wrist_bot_loc * Cq.Location.from2d(self.wrist_bezier_ext, 0)).to2d_pos(),
|
||||||
self.arrow_to_abs(base_u, -base_v),
|
self.arrow_to_abs(base_u, -base_v),
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
|
@ -954,22 +921,27 @@ class WingL(WingProfile):
|
||||||
|
|
||||||
def _mask_elbow(self) -> list[Tuple[float, float]]:
|
def _mask_elbow(self) -> list[Tuple[float, float]]:
|
||||||
l = 200
|
l = 200
|
||||||
|
elbow_bot_x, _ = self.elbow_bot_loc.to2d_pos()
|
||||||
|
elbow_top_x, _ = self.elbow_top_loc.to2d_pos()
|
||||||
return [
|
return [
|
||||||
(0, -l),
|
(0, -l),
|
||||||
(self.elbow_x, -l),
|
(elbow_bot_x, -l),
|
||||||
(self.elbow_x, self.elbow_y),
|
self.elbow_bot_loc.to2d_pos(),
|
||||||
(self.elbow_top_x, self.elbow_top_y),
|
self.elbow_top_loc.to2d_pos(),
|
||||||
(self.elbow_top_x, l),
|
(elbow_top_x, l),
|
||||||
(0, l)
|
(0, l)
|
||||||
]
|
]
|
||||||
|
|
||||||
def _mask_wrist(self) -> list[Tuple[float, float]]:
|
def _mask_wrist(self) -> list[Tuple[float, float]]:
|
||||||
l = 200
|
l = 200
|
||||||
|
elbow_bot_x, _ = self.elbow_bot_loc.to2d_pos()
|
||||||
|
_, elbow_top_y = self.elbow_top_loc.to2d_pos()
|
||||||
|
_, wrist_bot_y = self.wrist_bot_loc.to2d_pos()
|
||||||
return [
|
return [
|
||||||
(0, -l),
|
(0, -l),
|
||||||
(self.elbow_x, self.wrist_y),
|
(elbow_bot_x, wrist_bot_y),
|
||||||
(self.wrist_x, self.wrist_y),
|
self.wrist_bot_loc.to2d_pos(),
|
||||||
(self.wrist_top_x, self.wrist_top_y),
|
self.wrist_top_loc.to2d_pos(),
|
||||||
(self.elbow_x, self.elbow_top_y + l),
|
(elbow_bot_x, elbow_top_y + l),
|
||||||
(0, l),
|
(0, l),
|
||||||
]
|
]
|
||||||
|
|
23
nhf/utils.py
23
nhf/utils.py
|
@ -43,6 +43,10 @@ def from2d(x: float, y: float, rotate: float=0.0) -> Cq.Location:
|
||||||
return Cq.Location((x, y, 0), (0, 0, 1), rotate)
|
return Cq.Location((x, y, 0), (0, 0, 1), rotate)
|
||||||
Cq.Location.from2d = from2d
|
Cq.Location.from2d = from2d
|
||||||
|
|
||||||
|
def rot2d(angle: float) -> Cq.Location:
|
||||||
|
return Cq.Location((0, 0, 0), (0, 0, 1), angle)
|
||||||
|
Cq.Location.rot2d = rot2d
|
||||||
|
|
||||||
def is2d(self: Cq.Location) -> bool:
|
def is2d(self: Cq.Location) -> bool:
|
||||||
(_, _, z), (rx, ry, _) = self.toTuple()
|
(_, _, z), (rx, ry, _) = self.toTuple()
|
||||||
return z == 0 and rx == 0 and ry == 0
|
return z == 0 and rx == 0 and ry == 0
|
||||||
|
@ -59,6 +63,25 @@ def to2d(self: Cq.Location) -> Tuple[Tuple[float, float], float]:
|
||||||
return (x, y), rz
|
return (x, y), rz
|
||||||
Cq.Location.to2d = to2d
|
Cq.Location.to2d = to2d
|
||||||
|
|
||||||
|
def to2d_pos(self: Cq.Location) -> Tuple[float, float]:
|
||||||
|
"""
|
||||||
|
Returns position and angle
|
||||||
|
"""
|
||||||
|
(x, y, z), (rx, ry, _) = self.toTuple()
|
||||||
|
assert z == 0
|
||||||
|
assert rx == 0
|
||||||
|
assert ry == 0
|
||||||
|
return (x, y)
|
||||||
|
Cq.Location.to2d_pos = to2d_pos
|
||||||
|
|
||||||
|
def with_angle_2d(self: Cq.Location, angle: float) -> Tuple[float, float]:
|
||||||
|
"""
|
||||||
|
Returns position and angle
|
||||||
|
"""
|
||||||
|
x, y = self.to2d_pos()
|
||||||
|
return Cq.Location.from2d(x, y, angle)
|
||||||
|
Cq.Location.with_angle_2d = with_angle_2d
|
||||||
|
|
||||||
### Tags
|
### Tags
|
||||||
|
|
||||||
def tagPoint(self, tag: str):
|
def tagPoint(self, tag: str):
|
||||||
|
|
Loading…
Reference in New Issue