Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions manim/scene/vector_space_scene.py
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ def __init__(self, **kwargs):
self,
show_coordinates=True,
leave_ghost_vectors=True,
*kwargs
**kwargs
)

def construct(self):
Expand Down Expand Up @@ -616,6 +616,8 @@ def __init__(
},
}

self.ghost_vectors = VGroup()

self.foreground_plane_kwargs = {
"x_range": np.array([-config["frame_width"], config["frame_width"], 1.0]),
"y_range": np.array([-config["frame_width"], config["frame_width"], 1.0]),
Expand Down Expand Up @@ -741,6 +743,13 @@ def add_moving_mobject(
mobject.target = target_mobject
self.add_special_mobjects(self.moving_mobjects, mobject)

def get_ghost_vectors(self) -> VGroup:
"""
Returns all ghost vectors ever added to ``self``. Each element is a ``VGroup`` of
two ghost vectors.
"""
return self.ghost_vectors

def get_unit_square(
self, color: str = YELLOW, opacity: float = 0.3, stroke_width: float = 3
):
Expand Down Expand Up @@ -996,8 +1005,11 @@ def get_piece_movement(self, pieces: list | tuple | np.ndarray):
"""
start = VGroup(*pieces)
target = VGroup(*(mob.target for mob in pieces))
if self.leave_ghost_vectors:
self.add(start.copy().fade(0.7))
# don't add empty VGroups
if self.leave_ghost_vectors and start.submobjects:
# start.copy() gives a VGroup of Vectors
self.ghost_vectors.add(start.copy().fade(0.7))
self.add(self.ghost_vectors[-1])
return Transform(start, target, lag_ratio=0)

def get_moving_mobject_movement(self, func: Callable[[np.ndarray], np.ndarray]):
Expand Down
24 changes: 24 additions & 0 deletions tests/test_linear_transformation_scene.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from manim import RIGHT, UP, LinearTransformationScene, Vector, VGroup

__module_test__ = "vector_space_scene"


def test_ghost_vectors_len_and_types():
scene = LinearTransformationScene()
scene.leave_ghost_vectors = True

# prepare vectors (they require a vmobject as their target)
v1, v2 = Vector(RIGHT), Vector(RIGHT)
v1.target, v2.target = Vector(UP), Vector(UP)

# ghost_vector addition is in this method
scene.get_piece_movement((v1, v2))

ghosts = scene.get_ghost_vectors()
assert len(ghosts) == 1
# check if there are two vectors in the ghost vector VGroup
assert len(ghosts[0]) == 2

# check types of ghost vectors
assert isinstance(ghosts, VGroup) and isinstance(ghosts[0], VGroup)
assert all(isinstance(x, Vector) for x in ghosts[0])