Search code examples
manim

Is it possible to change the center of a mobject in Manim?


I'm trying to make a spirograph like animation, with one "crank" turning above the other. This image corresponds to what I'd like, but I can't animate it properly :

Expected result

So I came up with the following code,

RADIUS = 0.2
class SpirographCranks(Scene):
    def construct(self):
      
      dot = Dot(ORIGIN)
      line = Line(ORIGIN,RIGHT * (2-RADIUS))
      arc = Arc(arc_center=RIGHT*2, angle=PI, start_angle=PI/2, radius=RADIUS)
      
      crank = VGroup(* [dot,line,arc])
      self.add(crank)

      crank2 = crank.copy()
      def update(mobj,dt) : 
        mobj.move_to(arc.get_center())
        mobj.rotate(dt*PI,about_point = arc.get_center())

      crank2.add_updater(update)
      self.add(crank2)

      self.play(Rotate(crank, angle=2*PI, rate_func=linear,about_point=ORIGIN),run_time = 4)

which is close to what I want, except from the fact that the crank2's center is not properly placed :

enter image description here

Is there a way I can change an mobject's center so that it doesn't correspond to it's mass center anymore ?


Solution

  • There are other anchor points than just the .get_center() of your complete VGroup:

    class SpirographCranks(Scene):
        def construct(self):
          RADIUS = .4
          dot = Dot(ORIGIN)
          line = Line(ORIGIN,RIGHT * (2-RADIUS))
          arc = Arc(arc_center=RIGHT*2, angle=PI, start_angle=PI/2, radius=RADIUS)
          
          crank = VGroup(* [dot,line,arc])
          
          self.add(crank)
    
          crank2 = crank.copy()
          def update(mobj,dt) : 
            mobj.shift(crank[2].get_arc_center()-mobj[1].get_start())
            mobj.rotate(dt*PI,about_point = mobj[1].get_start())
    
          crank2.add_updater(update)
          self.add(crank2)
    
          self.play(Rotate(crank, angle=2*PI, rate_func=linear,about_point=ORIGIN),run_time = 4)        
    

    enter image description here