animationpermutationswapmanim

Swap method results in disappearing points in Manim scene


I am trying to make an animation where n points are equally distributed around a circle and an animation displays the permutations of those points by swapping their positions simultaeneously .

My issue is that when the animation ends either one of the points disappears from the scene or two distinct points get sent to the same position , here's the code :

from manim import*
import numpy as np
from itertools import*
import random

class CircleWithPoints(Scene):
    def construct(self):
        n = 6  # Number of points
        radius = 2
        colors = [RED, GREEN, GOLD, BLUE, PINK, PURPLE]

        # Create circle
        circle = Circle(radius=radius, color=WHITE)
        self.play(Create(circle))

        # Create points and assign colors
        points = []
        for i in range(n):
            angle = i * 2 * np.pi / n
            x = radius * np.cos(angle)
            y = radius * np.sin(angle)
            point = Dot(point=[x, y, 0], color=colors[i])
            points.append(point)
            self.play(Write((point)),run_animation=.25)

        all_permutations = list(permutations(range(n)))
        random_permutation =list(random.choice(all_permutations))
            # Permutation animation
        new_points=[]
        animated_new_points=[]
        animated_points=[]
        for i in range(n):
                next_index = random_permutation[i-1]
                next_point = points[next_index-1]
                if next_point is not points[i]:
                    animated_new_points.append(next_point)
                    animated_points.append(points[i])
        self.wait(1)
        
        self.play(*[Swap(animated_points[i],animated_new_points[i]) for i in range(len(animated_points))])

        self.wait(1)
        
       


I tried making a copy of the list of points to only take into account the points that are not fixed by the permutation however it doesn't seem like it worked


Solution

  • It's either a bug or an incorrect usage of Swap (which is only another name for CyclicReplace). I didn't investigate it further, but here is a simple solution: Replace Swap with Transform.

    self.play(*[Transform(animated_points[i],animated_new_points[i]) for i in range(len(animated_points))])
    

    If you want to see how Swap is intended to be used, you can do sth. like this:

    ...
    points = VGroup()
    for i in range(n):
        angle = i * 2 * np.pi / n
        x = radius * np.cos(angle)
        y = radius * np.sin(angle)
        point = Dot(point=[x, y, 0], color=colors[i])
        points.add(point)
        self.play(Write((point)),run_animation=.25)
    ...
    self.play(Swap(*points))
    ...
    

    Btw., when you are storing multiple VMobject like Dot I would recommend to use VGroup, which makes working with these objects much easier than a general python list.