Search code examples
pythonanimationmanim

Manim: run_time of animation is not as expected


I want manim to spend 4 seconds animating the creation of a sector. Although the whole animation lasts 4 seconds, the creation portion is only half that. I've tried extending the run_time parameter but to get the full 4 seconds for creation I have to make the duration 8 seconds. The actual drawing is finished at 4 seconds but then I have an animation 50% longer than necessary with the second half just sitting there doing nothing. I must be doing something wrong but I'm very new to manim so I'm not sure what I'm doing wrong. Maybe it's the rate_func parameter.

MWE:

from manimlib.imports import *

class Circ(Scene):
    def construct(self):
        shape = Sector(color=GOLD_B,
                       fill_color=GOLD_B,
                       fill_opacity=1,
                       angle=360*DEGREES)
        self.play(ShowCreation(shape,
                               lag_ratio=0,
                               rate_func=lambda t: linear(1 - t),
                               run_time=4*2)) # because we want 4 seconds for the circle's creation

I have tried it without the lag_ratio (not actually sure yet what that does). I borrowed the rate_func from Uncreate in animation.py. My current best guess is that this function is taking the full time of the run_time parameter but only looks like its using half. I have tried other functions, the original Uncreate is smooth. It is different but still doesn't appear to fill the full 4 seconds.

Thanks in advance.


Solution

  • The problem is the following, if we print the control points of the curve we see the following:

    print(shape.points)
    

    Returns:

    [[ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 3.33333333e-01 -8.16431199e-17  0.00000000e+00]
     [ 6.66666667e-01 -1.63286240e-16  0.00000000e+00]
     [ 1.00000000e+00 -2.44929360e-16  0.00000000e+00]
     [ 1.00000000e+00 -2.44929360e-16  0.00000000e+00]
     [ 1.00000000e+00 -2.61799388e-01  0.00000000e+00]
     [ 8.92226904e-01 -5.21986659e-01  0.00000000e+00]
     [ 7.07106781e-01 -7.07106781e-01  0.00000000e+00]
     [ 7.07106781e-01 -7.07106781e-01  0.00000000e+00]
     [ 5.21986659e-01 -8.92226904e-01  0.00000000e+00]
     [ 2.61799388e-01 -1.00000000e+00  0.00000000e+00]
     [-1.83697020e-16 -1.00000000e+00  0.00000000e+00]
     [-1.83697020e-16 -1.00000000e+00  0.00000000e+00]
     [-2.61799388e-01 -1.00000000e+00  0.00000000e+00]
     [-5.21986659e-01 -8.92226904e-01  0.00000000e+00]
     [-7.07106781e-01 -7.07106781e-01  0.00000000e+00]
     [-7.07106781e-01 -7.07106781e-01  0.00000000e+00]
     [-8.92226904e-01 -5.21986659e-01  0.00000000e+00]
     [-1.00000000e+00 -2.61799388e-01  0.00000000e+00]
     [-1.00000000e+00  1.22464680e-16  0.00000000e+00]
     [-1.00000000e+00  1.22464680e-16  0.00000000e+00]
     [-1.00000000e+00  2.61799388e-01  0.00000000e+00]
     [-8.92226904e-01  5.21986659e-01  0.00000000e+00]
     [-7.07106781e-01  7.07106781e-01  0.00000000e+00]
     [-7.07106781e-01  7.07106781e-01  0.00000000e+00]
     [-5.21986659e-01  8.92226904e-01  0.00000000e+00]
     [-2.61799388e-01  1.00000000e+00  0.00000000e+00]
     [ 6.12323400e-17  1.00000000e+00  0.00000000e+00]
     [ 6.12323400e-17  1.00000000e+00  0.00000000e+00]
     [ 2.61799388e-01  1.00000000e+00  0.00000000e+00]
     [ 5.21986659e-01  8.92226904e-01  0.00000000e+00]
     [ 7.07106781e-01  7.07106781e-01  0.00000000e+00]
     [ 7.07106781e-01  7.07106781e-01  0.00000000e+00]
     [ 8.92226904e-01  5.21986659e-01  0.00000000e+00]
     [ 1.00000000e+00  2.61799388e-01  0.00000000e+00]
     [ 1.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 1.00000000e+00  0.00000000e+00  0.00000000e+00]
     [ 6.66666667e-01  0.00000000e+00  0.00000000e+00]
     [ 3.33333333e-01  0.00000000e+00  0.00000000e+00]
     [ 0.00000000e+00  0.00000000e+00  0.00000000e+00]]
    

    We can see that many of the first control points are zero vectors, we would have to analyze the Sector source code to solve this problem, I suggest do something like:

    class Circ(Scene):
        def construct(self):
            shape = Sector(
                           color=GOLD_B,
                           fill_color=GOLD_B,
                           fill_opacity=1,
                           stroke_width=4,
                           stroke_color=TEAL,
                           angle=360*DEGREES
            )
            shape.points = shape.points[32:-1] # <- because there are 33 zero vectors at the beginning and 1 at the end
            self.play(
                ShowCreation(
                    shape,
                    run_time=4,
                    rate_func=lambda t: linear(1-t)
                )
            )
            self.wait()
    

    Obviously, the amount of zeros can change depending on the Sector mobject that we use, so you will have to find a way to filter those zero vectors at the beginning that are not necessary, perhaps this can be easily corrected in the definition of the Sector class.