mirror of
https://github.com/3b1b/manim.git
synced 2025-08-02 19:46:21 +08:00
Fix up FillArrow
This commit is contained in:
@ -738,10 +738,11 @@ class Arrow(Line):
|
||||
self,
|
||||
start: Vect3 | Mobject = LEFT,
|
||||
end: Vect3 | Mobject = LEFT,
|
||||
buff: float = MED_SMALL_BUFF,
|
||||
path_arc: float = 0,
|
||||
fill_color: ManimColor = GREY_A,
|
||||
fill_opacity: float = 1.0,
|
||||
stroke_width: float = 0.0,
|
||||
buff: float = MED_SMALL_BUFF,
|
||||
thickness: float = 3.0,
|
||||
tip_width_ratio: float = 5,
|
||||
tip_angle: float = PI / 3,
|
||||
@ -760,19 +761,11 @@ class Arrow(Line):
|
||||
fill_opacity=fill_opacity,
|
||||
stroke_width=stroke_width,
|
||||
buff=buff,
|
||||
path_arc=path_arc,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def set_points_by_ends(
|
||||
self,
|
||||
start: Vect3,
|
||||
end: Vect3,
|
||||
buff: float = 0,
|
||||
path_arc: float = 0
|
||||
) -> Self:
|
||||
# Find the right tip length and thickness
|
||||
vect = end - start
|
||||
length = max(get_norm(vect), 1e-8)
|
||||
def get_key_dimensions(self, length):
|
||||
width = self.thickness * self.tickness_multiplier
|
||||
w_ratio = fdiv(self.max_width_to_length_ratio, fdiv(width, length))
|
||||
if w_ratio < 1:
|
||||
@ -785,25 +778,48 @@ class Arrow(Line):
|
||||
tip_length *= t_ratio
|
||||
tip_width *= t_ratio
|
||||
|
||||
# Find points for the stem
|
||||
return width, tip_width, tip_length
|
||||
|
||||
def set_points_by_ends(
|
||||
self,
|
||||
start: Vect3,
|
||||
end: Vect3,
|
||||
buff: float = 0,
|
||||
path_arc: float = 0
|
||||
) -> Self:
|
||||
vect = end - start
|
||||
length = max(get_norm(vect), 1e-8) # More systematic min?
|
||||
unit_vect = normalize(vect)
|
||||
|
||||
# Find the right tip length and thickness
|
||||
width, tip_width, tip_length = self.get_key_dimensions(length - buff)
|
||||
|
||||
# Adjust start and end based on buff
|
||||
if path_arc == 0:
|
||||
start = start + buff * unit_vect
|
||||
end = end - buff * unit_vect
|
||||
else:
|
||||
R = length / 2 / math.sin(path_arc / 2)
|
||||
midpoint = 0.5 * (start + end)
|
||||
center = midpoint + rotate_vector(0.5 * vect, PI / 2) / math.tan(path_arc / 2)
|
||||
sign = 1
|
||||
start = center + rotate_vector(start - center, buff / R)
|
||||
end = center + rotate_vector(end - center, -buff / R)
|
||||
path_arc -= (2 * buff + tip_length) / R
|
||||
vect = end - start
|
||||
length = get_norm(vect)
|
||||
|
||||
# Find points for the stem, imagining an arrow pointed to the left
|
||||
if path_arc == 0:
|
||||
points1 = (length - tip_length) * np.array([RIGHT, 0.5 * RIGHT, ORIGIN])
|
||||
points1 += width * UP / 2
|
||||
points2 = points1[::-1] + width * DOWN
|
||||
else:
|
||||
# Solve for radius so that the tip-to-tail length matches |end - start|
|
||||
a = 2 * (1 - np.cos(path_arc))
|
||||
b = -2 * tip_length * np.sin(path_arc)
|
||||
c = tip_length**2 - length**2
|
||||
R = (-b + np.sqrt(b**2 - 4 * a * c)) / (2 * a)
|
||||
|
||||
# Find arc points
|
||||
points1 = quadratic_bezier_points_for_arc(path_arc)
|
||||
points2 = np.array(points1[::-1])
|
||||
points1 *= (R + width / 2)
|
||||
points2 *= (R - width / 2)
|
||||
if path_arc < 0:
|
||||
tip_length *= -1
|
||||
rot_T = rotation_matrix_transpose(PI / 2 - path_arc, OUT)
|
||||
for points in points1, points2:
|
||||
points[:] = np.dot(points, rot_T)
|
||||
@ -820,10 +836,7 @@ class Arrow(Line):
|
||||
self.add_subpath(points2)
|
||||
self.add_line_to(points1[0])
|
||||
|
||||
if length > 0 and self.get_length() > 0:
|
||||
# Final correction
|
||||
super().scale(length / self.get_length())
|
||||
|
||||
# Reposition to match proper start and end
|
||||
self.rotate(angle_of_vector(vect) - self.get_angle())
|
||||
self.rotate(
|
||||
PI / 2 - np.arccos(normalize(vect)[2]),
|
||||
@ -847,6 +860,9 @@ class Arrow(Line):
|
||||
def get_end(self) -> Vect3:
|
||||
return self.get_points()[self.tip_index]
|
||||
|
||||
def get_start_and_end(self):
|
||||
return (self.get_start(), self.get_end())
|
||||
|
||||
def put_start_and_end_on(self, start: Vect3, end: Vect3) -> Self:
|
||||
self.set_points_by_ends(start, end, buff=0, path_arc=self.path_arc)
|
||||
return self
|
||||
|
Reference in New Issue
Block a user