Home > front end >  how can I rotate line with only changing theta?
how can I rotate line with only changing theta?

Time:03-13

I was making animation with manim and I tried to make line that one end is fixed, and one end moves along the arc. The way I wanted to solve this problem was to define each point with theta, and let the point move along the arc as it moves. However, even if the setta was changed, the line did not move, so the rotate was used, but the length of the line did not change, so the line deviated from the arc and failed. I wonder how to make the line move smoothly with the size of the angle when theta value is changed to an arbitrary value with theta as a parameter.

from manim import *
import numpy as np

class RotateVector(Scene):
    def construct(self):
        theta = 1/9*np.pi
        semicircle = Arc(angle=PI, radius=4, stroke_color = GREY, arc_center=np.array([0, -1.5, 0]))
        bottom_line = Line(start=np.array([-4.0,-1.5,0]), end=np.array([4.0,-1.5,0]), stroke_color = GREY)
        
        dot_A = np.array([-4.0,-1.5,0])
        dot_A_text = Text('A', font_size=35).next_to(dot_A, LEFT DOWN, buff=0.05)
        dot_P = np.array([4*np.cos(theta*2),4*np.sin(theta*2)-1.5,0])
        dot_P_text = Text('P', font_size=35).next_to(dot_P, RIGHT UP, buff=0.05)

        line_AP = Line(start=np.array([-4.0,-1.5,0]), end=np.array([4*np.cos(2*theta),4*np.sin(2*theta)-1.5,0]), stroke_color = GREY)

        self.play(Create(semicircle), Create(bottom_line), Create(dot_A_text))
        self.play(Create(line_AP), Create(dot_P_text))
        self.wait(3)

CodePudding user response:

Your mobjects do not change because the dependency on Theta is not retained after initializing the mobject -- but it doesn't take too much to make it work!

The solution to your Problem is using a ValueTracker for the value of theta (to easily allow animating changing it) and updater functions for the mobjects you would like to change. In other words:

theta_vt = ValueTracker(theta)

dot_P_text.add_updater(lambda mobj: mobj.next_to([4*np.cos(theta_vt.get_value()*2),4*np.sin(theta_vt.get_value()*2)-1.5,0]))
line_AP.add_updater(lambda mobj: mobj.put_start_and_end_on([-4, 1.5, 0], [4*np.cos(theta_vt.get_value()*2),4*np.sin(theta_vt.get_value()*2)-1.5,0]))

self.play(theta_vt.animate.set_value(2*PI))

You could even avoid the value tracker and use an auxiliary (empty) mobject for positioning:

P = Mobject().move_to([4*np.cos(theta*2),4*np.sin(theta*2)-1.5,0])

and then change the updaters to use the position of P instead of theta, and make the point move along the desired arc. (That point actually is the one that becomes slightly more complicated, while the updaters simplify a bit.)

  • Related