Search code examples
manim

Manim draws a wrong line on a plotted graph


I'm working on a school project regarding derivatives and I've encountered a problem. I try to draw a secant line through points (2,4) and (2+dx, f(2+dx)) for f(x)=x^2. For some reason, manim first draws the line tangent to (2,4) and in one frame autocorrects to draw a secant through (2,4) and (2+dx, f(2+x)), as in an example: https://youtu.be/CDa7MdDdIT0.

I've isolated the lines that are responsible for this, but I can't figure out what's wrong. The code:

class TestingField(Scene):
def construct(self):
######## Definitions
    dx=ValueTracker(0.001)

    axes_begin=Axes(x_range=[-8,8,1], y_range=[-12,30, 3], x_length=10, y_length=10, tips=False)
    graph_begin=axes_begin.plot(lambda x: x**2, x_range=[-6,6], color=GREEN)

    ####Tangents to x^2
    tangent_begin_x2_RED=always_redraw(
    lambda: axes_begin.get_secant_slope_group(
    x=2,
    graph=graph_begin,
    dx=dx.get_value(),
    secant_line_color=RED,
    secant_line_length=15,
    dx_line_color=BLACK,
    dy_line_color=BLACK)
    )

    tangent_begin_x2_RED_2=always_redraw(
    lambda: axes_begin.get_secant_slope_group(
    x=2,
    graph=graph_begin,
    dx=dx.get_value(),
    secant_line_color=RED,
    secant_line_length=15,
    dx_line_color=YELLOW,
    dy_line_color=PURPLE)
    )

    tangent_begin_point_x2_1=always_redraw(
    lambda: Dot()
    .move_to(axes_begin.c2p(2+dx.get_value(), graph_begin.underlying_function(2+dx.get_value())))
    )

    tangent_begin_point_x2_2=always_redraw(
    lambda: Dot()
    .move_to(axes_begin.c2p(2, graph_begin.underlying_function(2)))
    )



######## Animation
    self.add(axes_begin, graph_begin, tangent_begin_point_x2_1, tangent_begin_point_x2_2,tangent_begin_x2_RED)

    self.wait(1)

    self.play(Uncreate(tangent_begin_x2_RED))
    self.play(dx.animate.set_value(1))

    self.play(Create(tangent_begin_x2_RED_2), run_time=2)

    self.play(dx.animate.set_value(0.7))
    self.play(dx.animate.set_value(0.3))
    self.play(dx.animate.set_value(1))

And rendering:

manim -pqh wstep.py TestingField

Could someone point out what's causing the problem?


Solution

  • The problem that you run into is that always_redraw basically creates a mobject with an updater function attached. Mobjects with updaters that are not yet added to the scene (which in your case tangent_begin_x2_RED_2 is not until it is Created) are not updated.

    You can fix the issue by adding

    tangent_begin_x2_RED_2.update()
    

    before the self.play-call where the secant group is created.