티스토리 뷰

https://www.youtube.com/watch?v=KHGoFDB-raE

출처는 다음 영상입니다. 해당 포스팅은 파이썬에대한 기초적인 선행지식은 있다고 가정합니다.

모든 이미지는 클릭시 크게 볼 수 있습니다!

 

[3B1B 따라잡기 list]

2023.05.11 - [Computer/3B1B 따라잡기 with ManimLibrary] - [3B1B 따라잡기 with Manim] 1. Manim 설치 with vscode

2023.05.12 - [Computer/3B1B 따라잡기 with ManimLibrary] - [3B1B 따라잡기 with Manim] 2. How to create Scene

2023.05.15 - [Computer/3B1B 따라잡기 with ManimLibrary] - [3B1B 따라잡기 with Manim] 3. Error message 파악하기

2023.05.15 - [Computer/3B1B 따라잡기 with ManimLibrary] - [3B1B 따라잡기 with Manim] 4. Animation Updaters

2023.05.16 - [Computer/3B1B 따라잡기 with ManimLibrary] - [3B1B 따라잡기 with Manim] 5. ValueTracker

2023.05.16 - [Computer/3B1B 따라잡기 with ManimLibrary] - [3B1B 따라잡기 with Manim] 6. Graphing

 

이번에는 Graphing Scene에 Updater와 ValueTracker를 추가해보자. 먼저 다음 코드를 입력해서 간단한 Graph Scene을 만들어보자.

# 그림1. 

class UpdaterGraphing(Scene):
    def construct(self):

        ax = Axes(x_range=[-4,4,1], y_range = [-2,16,2], x_length=8, y_length=7.5).to_edge(DOWN).add_coordinates()
        func = ax.plot(lambda x : x**2, x_range=[-4,4], color=BLUE)
        slope = ax.get_secant_slope_group(x = 3, graph = func, dx = 0.01,
                                          secant_line_color=GREEN,
                                          secant_line_length=3)


        self.add(ax); self.wait(1)
        self.play(FadeIn(VGroup(func, slope))); self.wait(2)

ax변수에 Axes() Mobject를 저장한다. 이제부터 앞선 포스팅에서 다룬 옵션들에 대해서는 설명은 생략한다. func 변수에 ax위에 plot()할 함수를 지정한다. slope는 그 함수의 기울기를 담을 변수이다.

기울기를 나타내기 위해서는 ax.get_secant_slope_group() 메소드를 이용한다.

  • x = 3은 x = 3에서의 secant_slope를 얻겠다는 의미이다.
  • graph는 어떤 그래프의 기울기를 나타낼 것인지를 지정한다.
  • 기울기라는 것은 평균 변화율의 일종이라 x가 dx만큼 증가할 때 y도 dy만큼 증가함을 나타내는 것이기 때문에 dx의 길이를 지정해줘야 한다. dx길이가 매우 짧아 극한에 수렴할 때 우리는 이것을 그래프의 접선의 기울기라고 공부했던 것을 기억할 수 있을것이다. 이해가 안된다면 dx옵션을 길게줘서 만들어보면 바로 이해가능! 나머지 두 옵션은 이름만 봐도 자명하니까 pass!

그림1.

이제 그래프의 기울기를 움직여보자. 위에서 x=3으로 지정했는데 이러면 기울기를 움직일 방법이 없다. x를 float 형태의 변수로 줘야 변수값의 변경에 따라서 slope를 redraw할 수 있을 것이다. 코드를 다음과 같이 수정해보자

# 그림2.

class UpdaterGraphing(Scene):
    def construct(self):
        
        k = ValueTracker(-4) # 수정된 부분
        ax = Axes(x_range=[-4,4,1], y_range = [-2,16,2], x_length=7, 
                  y_length=7.2).to_edge(DOWN).add_coordinates().set_color(WHITE)
        func = ax.plot(lambda x : x**2, x_range=[-4,4], color=BLUE)
        slope = ax.get_secant_slope_group(x = k.get_value(), # 수정된 부분
                                          graph = func, dx = 0.01,
                                          secant_line_color=GREEN,
                                          secant_line_length=3)


        self.add(ax); self.wait(1)
        self.play(FadeIn(VGroup(func, slope))); self.wait(2)
        self.play(k.animate.set_value(4), run_time=4) # 수정된 부분

우선 k변수에 ValueTracker(-4)를 저장했다. ValueTracker는 값의 변동을 추적하면서 애니메이션을 줄 수 있는 class이다. slope의 x값에 따라 기울기의 변화를 보여주고 싶기 때문에 slope 내부 x가 3이 아니라 k.get_value()로 변수가 되었다. 그리고 마지막 줄에서 self.play()를 통해 k값이 -4에서 4로 점차 변하도록 지정해주고(k.animate.set_value(4)) 실행해보았다.

그림2.

slope는 -4에서 나타나는데 생각과 다르게 움직이지 않고 종료된다. 이것은 우리가 ValueTracker는 움직였지만, slope에 updater 기능을 지정하지 않았기 때문이다. 코드를 한번 더 수정해보자.

# 그림3.

class UpdaterGraphing(Scene):
    def construct(self):
        
        k = ValueTracker(-4)
        ax = Axes(x_range=[-4,4,1], y_range = [-2,16,2], x_length=7, 
                  y_length=7.2).to_edge(DOWN).add_coordinates().set_color(WHITE)
        func = ax.plot(lambda x : x**2, x_range=[-4,4], color=BLUE)
        
        # 수정된 부분 #
        slope = always_redraw(lambda : ax.get_secant_slope_group(
                                       x = k.get_value(), 
                                       graph = func, dx = 0.01,
                                       secant_line_color=GREEN,
                                       secant_line_length=3)
                                       )
                                          


        self.add(ax); self.wait(1)
        self.play(FadeIn(VGroup(func, slope))); self.wait(2)
        self.play(k.animate.set_value(4), run_time=4)

그림3.

이제 우리가 원하던 slope의 이동을 볼 수 있다. 마지막으로 slope의 중심에 Dot을 찍어서 표현해보자.

# 그림4.

class UpdaterGraphing(Scene):
    def construct(self):
        
        k = ValueTracker(-4.0)
        ax = Axes(x_range=[-4,4,1], y_range = [-2,16,2], x_length=7, 
                  y_length=7.2).to_edge(DOWN).add_coordinates().set_color(WHITE)
        func = ax.plot(lambda x : x**2, x_range=[-4,4], color=BLUE)
        slope = always_redraw(lambda : ax.get_secant_slope_group(
                                          x = k.get_value(), 
                                          graph = func, dx = 0.01,
                                          secant_line_color=GREEN,
                                          secant_line_length=3))
                                          
        # 수정된 부분 #
        pt = always_redraw(lambda : Dot().move_to(ax.c2p(k.get_value(), 
                                  func.underlying_function(k.get_value()))))

        self.add(ax); self.wait(1)
        self.play(FadeIn(VGroup(func, slope, pt))); self.wait(2) # 수정된부분
        self.play(k.animate.set_value(4.0), run_time=4) ;self.wait(3)

 

그림4.

 

  • pt변수에 Dot()을 찍으면 화면 정 중앙에 하나의 점이 생성된다.
  • move_to() 메소드를 이용해서 ax로 이동한다.
  • 이때 coordinate to point(c2p) 메소드를 이용해서 특히 ax좌표계에서도 어디로 이동할지를 명시해준다. c2p는 coordinate class에 적용가능한 메소드로 
  • k.get_value()를 이용해 x값을 얻고,
  • func.underlying_function()을 이용해서 k값에 따른 func의 계산값을 얻을 수 있다.

 

댓글