diff --git a/manim/mobject/types/vectorized_mobject.py b/manim/mobject/types/vectorized_mobject.py index e03825c96f..c407dd6a27 100644 --- a/manim/mobject/types/vectorized_mobject.py +++ b/manim/mobject/types/vectorized_mobject.py @@ -1039,7 +1039,7 @@ def close_path(self) -> None: if not self.is_closed(): self.add_line_to(self.get_subpaths()[-1][0]) - def add_points_as_corners(self, points: Point3DLike_Array) -> Point3D_Array: + def add_points_as_corners(self, points: Point3DLike_Array) -> Self: """Append multiple straight lines at the end of :attr:`VMobject.points`, which connect the given ``points`` in order starting from the end of the current path. These ``points`` would be @@ -1058,10 +1058,14 @@ def add_points_as_corners(self, points: Point3DLike_Array) -> Point3D_Array: path. """ points = np.asarray(points).reshape(-1, self.dim) + num_points = points.shape[0] + if num_points == 0: + return self + if self.has_new_path_started(): # Pop the last point from self.points and # add it to start_corners - start_corners = np.empty((len(points), self.dim)) + start_corners = np.empty((num_points, self.dim)) start_corners[0] = self.points[-1] start_corners[1:] = points[:-1] end_corners = points @@ -1078,8 +1082,7 @@ def add_points_as_corners(self, points: Point3DLike_Array) -> Point3D_Array: new_points[i::nppcc] = interpolate(start_corners, end_corners, t) self.append_points(new_points) - # TODO: shouldn't this method return self instead of points? - return points + return self def set_points_as_corners(self, points: Point3DLike_Array) -> Self: """Given an array of points, set them as corners of the diff --git a/tests/module/mobject/types/vectorized_mobject/test_vectorized_mobject.py b/tests/module/mobject/types/vectorized_mobject/test_vectorized_mobject.py index 4d604f2dfb..23d5e008d8 100644 --- a/tests/module/mobject/types/vectorized_mobject/test_vectorized_mobject.py +++ b/tests/module/mobject/types/vectorized_mobject/test_vectorized_mobject.py @@ -65,6 +65,37 @@ def test_vmobject_add(): assert len(obj.submobjects) == 1 +def test_vmobject_add_points_as_corners(): + points = np.array( + [ + [2, 0, 0], + [1, 1, 0], + [-1, 1, 0], + [-2, 0, 0], + [-1, -1, 0], + [1, -1, 0], + [2, 0, 0], + ] + ) + + # Test that add_points_as_corners(points) is equivalent to calling + # add_line_to(point) for every point in points. + obj1 = VMobject().start_new_path(points[0]).add_points_as_corners(points[1:]) + obj2 = VMobject().start_new_path(points[0]) + for point in points[1:]: + obj2.add_line_to(point) + np.testing.assert_allclose(obj1.points, obj2.points) + + # Test that passing an array with no points does nothing. + obj3 = VMobject().start_new_path(points[0]) + points3_old = obj3.points.copy() + obj3.add_points_as_corners([]) + np.testing.assert_allclose(points3_old, obj3.points) + + obj3.add_points_as_corners(points[1:]).add_points_as_corners([]) + np.testing.assert_allclose(obj1.points, obj3.points) + + def test_vmobject_point_from_proportion(): obj = VMobject()