Search code examples
manim

Using Manim, can I draw a new object in the background of existing ones?


I have illustrated the parallelogram spanned by two vectors, and would like to shade in the area of that parallelogram, which I tried to do like so:

from manim import *
import numpy as np

class DrawParallelogram( Scene ):
    def construct( self ):
        o = np.array( [ 0, -2, 0 ] )
        p1 = np.array( [ 3, 1, 0 ] ) # u
        p2 = np.array( [ 1, 3, 0 ] ) # v
        op1 = o + p1
        op2 = o + p2
        op3 = o + p1 + p2

        v1 = Arrow( start = o, end = op1, buff = 0, color = RED ) # u
        v2 = Arrow( start = o, end = op2, buff = 0, color = YELLOW ) # v
        v1p = Arrow( start = op2, end = op3, buff = 0, color = RED ) # u'
        v2p = Arrow( start = op1, end = op3, buff = 0, color = YELLOW ) # v'

        parallelogram = [ o, op1, op3, op2 ]
        poly = Polygon( *parallelogram, color = PURPLE, fill_opacity = 0.5 )

        self.play( AnimationGroup( Write( v1 ), Write( v2 ), Write( v1p ), Write( v2p ) ) )
        self.wait( )
        self.play( Write( poly ) )

However, this parallelogram colors over the arrows that I have already drawn, like so: yuck

and I'd like it to be in the background. Is there a way to introduce a new object into the scene so that it is logically behind any of the existing ones, as if I had drawn it first, so that it would look like:

desired


Solution

  • You can use the set_z_index method to set the z_index property of the parallelogram to a value less than that of the arrows.

    Here I have set it to a lower value than that of v1:

    poly.set_z_index(v1.z_index - 1)
    

    Alternatively you can manipulate the z_index property directly:

    poly.z_index = v1.z_index - 1
    

    Using the set_z_index method would be the cleaner solution.

    Complete code:

    from manim import *
    import numpy as np
    
    class DrawParallelogram( Scene ):
        def construct( self ):
            o = np.array( [ 0, -2, 0 ] )
            p1 = np.array( [ 3, 1, 0 ] ) # u
            p2 = np.array( [ 1, 3, 0 ] ) # v
            op1 = o + p1
            op2 = o + p2
            op3 = o + p1 + p2
    
            v1 = Arrow( start = o, end = op1, buff = 0, color = RED ) # u
            v2 = Arrow( start = o, end = op2, buff = 0, color = YELLOW ) # v
            v1p = Arrow( start = op2, end = op3, buff = 0, color = RED ) # u'
            v2p = Arrow( start = op1, end = op3, buff = 0, color = YELLOW ) # v'
    
            parallelogram = [ o, op1, op3, op2 ]
            poly = Polygon( *parallelogram, color = PURPLE, fill_opacity = 0.5 )
            # Set the z-index
            poly.set_z_index(v1.z_index - 1)
    
            self.play( AnimationGroup( Write( v1 ), Write( v2 ), Write( v1p ), Write( v2p ) ) )
            self.wait( )
            self.play( Write( poly ) )