Skip to content

Commit 7f6743e

Browse files
Fix :meth:VMobject.pointwise_become_partial failing when vmobject is self (#4193)
* Fix Line failing with buff and path_arc - make copy of vmobject.points if necessary * change self to self.copy() in Line, and remove the previous change in pointwise_become_partial() * Revert to first approach: copy points if self is vmobject * Add unit test for pointwise_become_partial and Line --------- Co-authored-by: Francisco Manríquez Novoa <[email protected]>
1 parent a2876dc commit 7f6743e

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

manim/mobject/types/vectorized_mobject.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,12 +1932,18 @@ def pointwise_become_partial(
19321932
upper_index, upper_residue = integer_interpolate(0, num_curves, b)
19331933

19341934
nppc = self.n_points_per_curve
1935+
1936+
# Copy vmobject.points if vmobject is self to prevent unintended in-place modification
1937+
vmobject_points = (
1938+
vmobject.points.copy() if self is vmobject else vmobject.points
1939+
)
1940+
19351941
# If both indices coincide, get a part of a single Bézier curve.
19361942
if lower_index == upper_index:
19371943
# Look at the "lower_index"-th Bézier curve and select its part from
19381944
# t=lower_residue to t=upper_residue.
19391945
self.points = partial_bezier_points(
1940-
vmobject.points[nppc * lower_index : nppc * (lower_index + 1)],
1946+
vmobject_points[nppc * lower_index : nppc * (lower_index + 1)],
19411947
lower_residue,
19421948
upper_residue,
19431949
)
@@ -1947,19 +1953,19 @@ def pointwise_become_partial(
19471953
# Look at the "lower_index"-th Bezier curve and select its part from
19481954
# t=lower_residue to t=1. This is the first curve in self.points.
19491955
self.points[:nppc] = partial_bezier_points(
1950-
vmobject.points[nppc * lower_index : nppc * (lower_index + 1)],
1956+
vmobject_points[nppc * lower_index : nppc * (lower_index + 1)],
19511957
lower_residue,
19521958
1,
19531959
)
19541960
# If there are more curves between the "lower_index"-th and the
19551961
# "upper_index"-th Béziers, add them all to self.points.
1956-
self.points[nppc:-nppc] = vmobject.points[
1962+
self.points[nppc:-nppc] = vmobject_points[
19571963
nppc * (lower_index + 1) : nppc * upper_index
19581964
]
19591965
# Look at the "upper_index"-th Bézier curve and select its part from
19601966
# t=0 to t=upper_residue. This is the last curve in self.points.
19611967
self.points[-nppc:] = partial_bezier_points(
1962-
vmobject.points[nppc * upper_index : nppc * (upper_index + 1)],
1968+
vmobject_points[nppc * upper_index : nppc * (upper_index + 1)],
19631969
0,
19641970
upper_residue,
19651971
)

tests/module/mobject/geometry/test_unit_geometry.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,12 @@
55
import numpy as np
66

77
from manim import (
8+
DEGREES,
9+
LEFT,
10+
RIGHT,
811
BackgroundRectangle,
912
Circle,
13+
Line,
1014
Polygram,
1115
Sector,
1216
Square,
@@ -142,3 +146,36 @@ def test_changing_Square_side_length_updates_the_square_appropriately():
142146
def test_Square_side_length_consistent_after_scale_and_rotation():
143147
sq = Square(side_length=1).scale(3).rotate(np.pi / 4)
144148
assert np.isclose(sq.side_length, 3)
149+
150+
151+
def test_line_with_buff_and_path_arc():
152+
line = Line(LEFT, RIGHT, path_arc=60 * DEGREES, buff=0.3)
153+
expected_points = np.array(
154+
[
155+
[-0.7299265, -0.12999304, 0.0],
156+
[-0.6605293, -0.15719695, 0.0],
157+
[-0.58965623, -0.18050364, 0.0],
158+
[-0.51763809, -0.19980085, 0.0],
159+
[-0.51763809, -0.19980085, 0.0],
160+
[-0.43331506, -0.22239513, 0.0],
161+
[-0.34760317, -0.23944429, 0.0],
162+
[-0.26105238, -0.25083892, 0.0],
163+
[-0.26105238, -0.25083892, 0.0],
164+
[-0.1745016, -0.26223354, 0.0],
165+
[-0.08729763, -0.26794919, 0.0],
166+
[0.0, -0.26794919, 0.0],
167+
[0.0, -0.26794919, 0.0],
168+
[0.08729763, -0.26794919, 0.0],
169+
[0.1745016, -0.26223354, 0.0],
170+
[0.26105238, -0.25083892, 0.0],
171+
[0.26105238, -0.25083892, 0.0],
172+
[0.34760317, -0.23944429, 0.0],
173+
[0.43331506, -0.22239513, 0.0],
174+
[0.51763809, -0.19980085, 0.0],
175+
[0.51763809, -0.19980085, 0.0],
176+
[0.58965623, -0.18050364, 0.0],
177+
[0.6605293, -0.15719695, 0.0],
178+
[0.7299265, -0.12999304, 0.0],
179+
]
180+
)
181+
np.testing.assert_allclose(line.points, expected_points)

tests/module/mobject/types/vectorized_mobject/test_vectorized_mobject.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,3 +526,25 @@ def test_proportion_from_point():
526526
abc.scale(0.8)
527527
props = [abc.proportion_from_point(p) for p in abc.get_vertices()]
528528
np.testing.assert_allclose(props, [0, 1 / 3, 2 / 3])
529+
530+
531+
def test_pointwise_become_partial_where_vmobject_is_self():
532+
sq = Square()
533+
sq.pointwise_become_partial(vmobject=sq, a=0.2, b=0.7)
534+
expected_points = np.array(
535+
[
536+
[-0.6, 1.0, 0.0],
537+
[-0.73333333, 1.0, 0.0],
538+
[-0.86666667, 1.0, 0.0],
539+
[-1.0, 1.0, 0.0],
540+
[-1.0, 1.0, 0.0],
541+
[-1.0, 0.33333333, 0.0],
542+
[-1.0, -0.33333333, 0.0],
543+
[-1.0, -1.0, 0.0],
544+
[-1.0, -1.0, 0.0],
545+
[-0.46666667, -1.0, 0.0],
546+
[0.06666667, -1.0, 0.0],
547+
[0.6, -1.0, 0.0],
548+
]
549+
)
550+
np.testing.assert_allclose(sq.points, expected_points)

0 commit comments

Comments
 (0)