# Manim学习记录(2)

第一个案例

GraphingMovement

​ 这个开始再坐标轴上画函数图像以及移动

from manim import *
class GraphingMovement(Scene):
    def construct(self):
        axes = Axes(
        x_range=[0,5,1],  # x 轴范围:从 0 到 5,刻度间隔为 1
        y_range=[0,3,1],  # y 轴范围:从 0 到 3,刻度间隔为 1
        x_length=5,       # x 轴长度为 5(单位为 Manim 默认单位)
        y_length=3,       # y 轴长度为 3(单位为 Manim 默认单位)
        axis_config={
            "include_tip": True,      # 坐标轴末端添加箭头
            "numbers_to_exclude":[0]  # 排除坐标轴上显示的数字 0
        }
        ).add_coordinates()  # 添加坐标轴上的刻度值标签
        axes.to_edge(UR) # 将坐标轴移动到画布的右上角 (UP+RIGHT 方向)
        axes_labels = axes.get_axis_labels(x_label="x", y_label="f(x)")   #使用 get_axis_labels 方法为 x 轴和 y 轴添加标签,分别命名为 "x" 和 "f(x)"。


        # 使用 plot 方法绘制函数图像,函数为 y = sqrt(x)(即 lambda x: x**0.5),定义域为 [0, 4],颜色为红色(RED)。
        graph = axes.plot(lambda x: x**0.5, x_range=[0, 4], color=RED)  

        graphing_stuff = VGroup(axes, axes_labels, graph)

        self.play(DrawBorderThenFill(axes),Write(axes_labels))
        self.play(Create(graph))
        self.play(graphing_stuff.animate.shift(DOWN*4))
        self.play(axes.animate.shift(LEFT*3),run_time = 3)

​ 这段代码看起来没有什么难度,但是这一行里面

graph = axes.plot(lambda x: x**0.5, x_range=[0, 4], color=RED)  

我学习的时候发现我用Brian Amedee的代码再我的本地环境里面跑不起来

当时Brian Amedee的代码为

graph = axes.get_graph(lambda x: x**0.5, x_range=[0, 4], color=RED) 

后面才发现这和manim的版本有关,大家也可以试一下这两个方法有什么区别

这个动画首先是向下移动这个整体,然后再单独想左移动坐标轴,那么如果我在一次移动这个整体,也就是再代码的最后加一行self.play(graphing_stuff.animate.shift(LEFT*4))会出现什么效果呢,感兴趣的小伙伴可以试一下

第二个案例

​ 我在按照Brian Amedee视频中的例子学习的时候,现在有意识地先看效果图,然后先自己看看能不能自己写出来,出不出来的地方然后在看代码怎么写的

老规矩先上视频

Graphing

​ 首先我们可以先看到效果图,这个效果图首先时先出现坐标轴,然后再出现函数和函数式,最后再出现函数里面的面积,根据manim里面的三元素,上述的坐标轴,函数,面积其实都是我们需要创建的Object,那我们怎么创建呢

​ 我现在把注释标注在代码里

from manim import *
class Graphing(Scene):
    def construct(self):
       # 创建坐标系和函数
       my_plane = NumberPlane(x_range = [-6,6],x_length = 5,
                              y_range = [-10,10],y_length = 5 )
       my_plane.add_coordinates() # 给坐标轴标上数字
       my_plane.shift(RIGHT*3)

        # 创建函数和面积
       my_function = my_plane.plot(lambda x: 0.1*(x-5)*x*(x-5),x_range = [-5,5] ,color = BLUE) 
    
    # 面积
       area = my_plane.get_area(graph= my_function,x_range = [-5,5],color = [BLUE,YELLOW])

       label = MathTex("f(x) = 0.1(x-5)x(x-5)").next_to(my_plane,UP,buff=0.2)

       horiz_line = Line(
           start=my_plane.c2p(0,my_function.underlying_function(-2)),
           end=my_plane.c2p(-2,my_function.underlying_function(-2)),
           stroke_color = YELLOW,stroke_width = 10
       )

       self.play(DrawBorderThenFill(my_plane))
       self.play(Create(my_function),Write(label))
       self.play(FadeIn(area) , runTime = 4)
       self.play(Create(horiz_line),run_time = 3)

首先我们先看这一句,只一句就是创建函数这个Object

 my_function = my_plane.plot(lambda x: 0.1*(x-5)*x*(x-5),x_range = [-5,5] ,color = BLUE) 
参数 说明
lambda x: 0.1*(x-5)x(x-5) 在my_plane坐标轴上描绘函数
x_range = [-5,5] x的定义域【-5,5】
color = BLUE 颜色

然后就是创建我们想要的函数面积

  area = my_plane.get_area(graph= my_function,x_range = [-5,5],color = [BLUE,YELLOW])
参数 说明
graph= my_function 目标函数
x_range = [-5,5] x的定义域【-5,5】
color = BLUE 颜色

​ 然后就是一个水平与x轴的说水平线

     horiz_line = Line(
           start=my_plane.c2p(0,my_function.underlying_function(-2)),
           end=my_plane.c2p(-2,my_function.underlying_function(-2)),
           stroke_color = YELLOW,stroke_width = 10
       )
1. horiz_line = Line(...)
  • Line 是图形绘制库中用于创建线段对象的类。
  • horiz_line 是创建的线段对象的变量名,通过这个变量可以对该线段进行后续的操作,比如添加到场景中显示、修改其属性等。
2. start=my_plane.c2p(0, my_function.underlying_function(-2))
  • startLine 类的一个参数,用于指定线段的起点。
  • my_plane 是一个表示平面的对象,它应该有一个 c2p 方法。
  • c2p 方法的作用是将笛卡尔坐标(x, y)转换为该平面上的实际坐标。
  • my_function 是一个函数对象,my_function.underlying_function(-2) 表示调用 my_function 的底层函数,并传入参数 -2,得到函数在 x = -2 处的函数值。
  • 所以 my_plane.c2p(0, my_function.underlying_function(-2)) 表示将笛卡尔坐标 (0, my_function.underlying_function(-2)) 转换为平面 my_plane 上的实际坐标,作为线段的起点。
3. end=my_plane.c2p(-2, my_function.underlying_function(-2))
  • endLine 类的一个参数,用于指定线段的终点。
  • 同样使用 my_plane.c2p 方法将笛卡尔坐标 (-2, my_function.underlying_function(-2)) 转换为平面 my_plane 上的实际坐标,作为线段的终点。
4. stroke_color = YELLOW
  • stroke_colorLine 类的一个参数,用于指定线段的颜色。
  • YELLOW 是一个预定义的颜色常量,代表黄色。
5. stroke_width = 10
  • stroke_widthLine 类的一个参数,用于指定线段的宽度。这里将线段的宽度设置为 10。

第三个案例

Graphing

from manim import *
class Graphing(Scene):
    def construct(self):
        my_plane = NumberPlane(x_range=[-6,6],x_length= 5,
                               y_range = [-10,10],y_length = 5)
        my_plane.add_coordinates()
        my_plane.shift(RIGHT*3)

        # 添加函数
        my_function = my_plane.plot(lambda x: 0.1*x*(x-5)*(x+5),
                                     x_range=[-6,6],color = GREEN_B)
        
        # 添加阴影面积
        area1 = my_plane.get_riemann_rectangles(my_function,x_range=[-5,5],color=[RED,GREEN_B],
                                               dx=0.1,stroke_width=0,
                                               stroke_color=RED,fill_opacity=0.7).shift(LEFT*6)

        area = my_plane.get_area(graph = my_function,x_range = [-5,5],color = [BLUE,YELLOW,RED])
        
        label = MathTex("f(x) = 0.1x(x-5)(x+5)").next_to(my_plane,UP,buff=0.2)

        horiz_line = Line(
            start = my_plane.c2p(0,my_function.underlying_function(-2)),
            end = my_plane.c2p(-2,my_function.underlying_function(-2)),
            stroke_color = GREEN_B,stroke_width = 10
        )

        self.play(DrawBorderThenFill(my_plane))
        self.play(Create(my_function),Write(label))
        self.play(FadeIn(area))
        self.play(Create(horiz_line))

        group = VGroup(my_plane,my_function,label,horiz_line).copy().shift(LEFT*6)
        self.play(FadeIn(group))
        self.play(FadeIn(area1))

        

第四个案例

CoordinateSystem

from manim import *
class CoordinateSystem(Scene):
    def construct(self):
        plane = NumberPlane(
            x_range = [-4,4,1],x_length=4,
            y_range = [0,20,5],y_length=4,
            background_line_style = {"stroke_color": GREY, "stroke_width": 0.5, "stroke_opacity": 0.5}
        ).add_coordinates()
        plane.shift(LEFT*3+DOWN*1.5)

        plane_graph = plane.plot(lambda x: x**2, x_range = [-4,4],color=RED)

        plane_graph_area = plane.get_riemann_rectangles(
            plane_graph,
            x_range = [-4,4],
            dx = 0.5,
            stroke_width = 0,
            stroke_color = GREY,
            fill_opacity = 0.5,
            color = GREY
        )

        axes = Axes(x_range = [-4,4,1],x_length=4,
                    y_range=[-20,20,5],y_length = 4).add_coordinates()
        axes.shift(RIGHT*3+DOWN*1.5)
        axes_graph = axes.plot(lambda x: 2*x,x_range = [-4,4],color=RED)
        v_line = axes.get_vertical_lines_to_graph(
            graph=axes_graph,
            x_range=[-3,3],
            num_lines=12
        )

        self.play(Write(plane),Create(axes))
        self.play(Create(plane_graph),Create(axes_graph),run_time = 1)
        self.add(plane_graph_area,v_line)

​ 学习前三个案例相信你第四个一定能看懂

第五个案例

Tute2

from manim import *
import numpy as np

class Tute2(Scene):
    def construct(self):
        e = ValueTracker(0.01)

        plane = PolarPlane(radius_max=3).add_coordinates()
        plane.shift(LEFT * 2)

        graph1 = always_redraw(
            lambda: ParametricFunction(
                lambda t: plane.polar_to_point(2 * np.sin(3 * t), t),
                t_range=[0, e.get_value()],
                color=GREEN
            )
        )

        dot1 = always_redraw(
            lambda: Dot(fill_color=GREEN, fill_opacity=0.8).move_to(graph1.get_end())
        )

        axes = Axes(
            x_range=[0, 4, 1],
            x_length=3,
            y_range=[-3, 3, 1],
            y_length=3
        ).shift(RIGHT * 4)
        axes.add_coordinates()

        graph2 = always_redraw(
            lambda: axes.plot(
                lambda x: 2 * np.sin(3 * x),
                x_range=[0, e.get_value()],
                use_smoothing=False
            ).set_color(GREEN)
        )

        dot2 = always_redraw(
            lambda: Dot(fill_color=GREEN, fill_opacity=0.8)
            .scale(0.8)
            .move_to(axes.c2p(e.get_value(), 2 * np.sin(3 * e.get_value())))
        )

        title = MathTex("f(\\theta) = 2\\sin(3\\theta)", color=GREEN).next_to(axes, UP, buff=0.2)

        # 分别添加 Mobject
        # self.add(plane, axes, title)

        # 播放 LaggedStart 动画
        self.play(LaggedStart(Write(plane), Create(axes), Write(title), run_time=3, lag_ratio=0.5))

        self.add(graph1, graph2, dot1, dot2)
        self.play(e.animate.set_value(PI), run_time=10, rate_func=linear)
        self.wait()

创建值跟踪器

e = ValueTracker(0.01)
  • ValueTrackermanim 中的一个类,用于跟踪一个数值的变化。这里创建了一个初始值为 0.01 的值跟踪器 e,后续会通过改变 e 的值来控制函数的绘制过程。

创建极坐标平面

plane = PolarPlane(radius_max=3).add_coordinates()
plane.shift(LEFT * 2)
  • PolarPlane(radius_max=3):创建一个极坐标平面,最大半径为 3
  • add_coordinates():为极坐标平面添加坐标。
  • plane.shift(LEFT * 2):将极坐标平面向左移动 2 个单位。

创建极坐标函数图像

graph1 = always_redraw(
    lambda: ParametricFunction(
        lambda t: plane.polar_to_point(2 * np.sin(3 * t), t),
        t_range=[0, e.get_value()],
        color=GREEN
    )
)
  • always_redraw:这是 manim 中的一个函数,用于创建一个始终重新绘制的 Mobject。当 e 的值发生变化时,graph1 会自动重新绘制。

  • ParametricFunction
    

    :用于创建参数化函数图像。

    • lambda t: plane.polar_to_point(2 * np.sin(3 * t), t):定义参数化函数,将极坐标 ((r = 2\sin(3\theta), \theta)) 转换为平面上的点。
    • t_range=[0, e.get_value()]:指定参数 t 的范围,从 0e 的当前值。
    • color=GREEN:设置图像的颜色为绿色。

创建极坐标函数图像上的点

dot1 = always_redraw(
    lambda: Dot(fill_color=GREEN, fill_opacity=0.8).move_to(graph1.get_end())
)
  • Dot:创建一个点。
  • fill_color=GREEN:设置点的填充颜色为绿色。
  • fill_opacity=0.8:设置点的填充透明度为 0.8
  • move_to(graph1.get_end()):将点移动到 graph1 的末端。

创建直角坐标系

axes = Axes(
    x_range=[0, 4, 1],
    x_length=3,
    y_range=[-3, 3, 1],
    y_length=3
).shift(RIGHT * 4)
axes.add_coordinates()
  • Axes
    

    :创建一个直角坐标系。

    • x_range=[0, 4, 1]:指定 x 轴的范围从 04,刻度间隔为 1
    • x_length=3:指定 x 轴的长度为 3
    • y_range=[-3, 3, 1]:指定 y 轴的范围从 -33,刻度间隔为 1
    • y_length=3:指定 y 轴的长度为 3
  • axes.shift(RIGHT * 4):将直角坐标系向右移动 4 个单位。

  • axes.add_coordinates():为直角坐标系添加坐标。

创建直角坐标系下的函数图像

graph2 = always_redraw(
    lambda: axes.plot(
        lambda x: 2 * np.sin(3 * x),
        x_range=[0, e.get_value()],
        use_smoothing=False
    ).set_color(GREEN)
)
  • axes.plot
    

    :在直角坐标系上绘制函数图像。

    • lambda x: 2 * np.sin(3 * x):定义函数 (y = 2\sin(3x))。
    • x_range=[0, e.get_value()]:指定 x 的范围从 0e 的当前值。
    • use_smoothing=False:不使用平滑处理。
  • set_color(GREEN):设置图像的颜色为绿色。

创建直角坐标系下函数图像上的点

dot2 = always_redraw(
    lambda: Dot(fill_color=GREEN, fill_opacity=0.8)
    .scale(0.8)
    .move_to(axes.c2p(e.get_value(), 2 * np.sin(3 * e.get_value())))
)
  • Dot:创建一个点。
  • fill_color=GREEN:设置点的填充颜色为绿色。
  • fill_opacity=0.8:设置点的填充透明度为 0.8
  • .scale(0.8):将点的大小缩小为原来的 0.8 倍。
  • move_to(axes.c2p(e.get_value(), 2 * np.sin(3 * e.get_value()))):将点移动到直角坐标系中 ((e, 2\sin(3e))) 的位置。

创建标题

title = MathTex("f(\\theta) = 2\\sin(3\\theta)", color=GREEN).next_to(axes, UP, buff=0.2)
  • MathTex:创建一个数学公式对象。
  • "f(\\theta) = 2\\sin(3\\theta)":定义数学公式。
  • color=GREEN:设置公式的颜色为绿色。
  • next_to(axes, UP, buff=0.2):将标题放置在直角坐标系的上方,距离为 0.2

播放动画

self.play(LaggedStart(Write(plane), Create(axes), Write(title), run_time=3, lag_ratio=0.5))
  • self.play:播放动画。

  • LaggedStart
    

    :用于创建一个延迟开始的动画序列。

    • Write(plane):以书写的方式显示极坐标平面。
    • Create(axes):创建直角坐标系。
    • Write(title):以书写的方式显示标题。
    • run_time=3:动画的总时长为 3 秒。
    • lag_ratio=0.5:每个动画之间的延迟比例为 0.5

添加 Mobject

self.add(graph1, graph2, dot1, dot2)
  • self.add:将 graph1graph2dot1dot2 添加到场景中。

播放函数绘制动画

self.play(e.animate.set_value(PI), run_time=10, rate_func=linear)
  • e.animate.set_value(PI):将 e 的值从当前值动画地设置为 PI
  • run_time=10:动画的时长为 10 秒。
  • rate_func=linear:使用线性的动画速率函数。

你可能感兴趣的:(python,numpy,vscode,数学建模)