python动画:实现目标的运动轨迹【paths】

一,介绍

在 Manim 库中,“路径(paths)”指的是一些功能函数,这些函数用于确定在点集之间进行变换时所需的路径。这些函数为动画制作提供了灵活性和表现力,使得物体在场景中的移动表现得更加生动和自然。

具体来说,路径函数能够根据给定的一组点,生成一条连贯的运动轨迹,控制物体在动画中的运动方式。例如,当你想让一个图形从一个位置移动到另一个位置时,简单的线性运动可能显得乏味,而使用路径函数则可以定义更复杂的运动轨迹,比如圆弧、贝塞尔曲线或螺旋形路线等。这种灵活的路径控制不仅可以增强动画的可视化效果,还可以让观众对运动的自然程度感到满意。

在使用路径函数时,用户只需提供起始点和目标点,路径函数会根据要求生成合适的运动路径。这些路径可以用来连接形状、插图或其他对象,使得它们在变换的过程中更具生动性和美感。此外,通过调整路径的参数,用户能够精细控制动画的速度、方向和曲率,从而创造出更加引人入胜的视觉效果。

总之,Manim 中的路径函数是动画制作的关键工具,它们赋予了创作更多的表现手法和艺术性,使得动画能更好地与观众沟通。

二,常见的路径

1.顺时针方向绘制的路径【clockwise_path()】

在 Manim 中,clockwise_path() 是用来生成一个按照顺时针方向绘制的路径的函数。通常,通过这个函数创建的路径可以用于动画,使物体沿着该路径移动。

重要函数参数

  • start: 起始点的坐标,通常是一个 np.array 对象。
  • end: 结束点的坐标,通常也是一个 np.array 对象。
  • radius: 圆弧的半径。
  • num_points: 绘制路径的离散点的数量,也是绘制精度的一个控制参数,默认值可以根据需要调整。

示例代码

以下是一个使用 clockwise_path() 函数的简单示例,演示了如何让一个圆形对象沿着顺时针路径移动:

from manim import *  

class ClockwisePathExample(Scene):  
    def construct(self):  
        colors = [RED, GREEN, BLUE]  

        starting_points = VGroup(  
            *[  
                Dot(LEFT + pos, color=color)  
                for pos, color in zip([UP, DOWN, LEFT], colors)  
            ]  
        )  

        finish_points = VGroup(  
            *[  
                Dot(RIGHT + pos, color=color)  
                for pos, color in zip([ORIGIN, UP, DOWN], colors)  
            ]  
        )  

        self.add(starting_points)  
        self.add(finish_points)  

        # 使用 VGroup 添加 TracedPath  
        traced_paths = VGroup(*[  
            TracedPath(dot.get_center, stroke_color=dot.get_color())  
            for dot in starting_points  
        ])  
        self.add(traced_paths)  

        self.wait()  
        self.play(  
            Transform(  
                starting_points,  
                finish_points,  
                path_func=utils.paths.clockwise_path(),  
                run_time=2,  
            )  
        )  
        self.wait()

 

2.逆时针运动路径的绘制【counterclockwise_path()

counterclockwise_path() 是 Manim 中用于创建一个逆时针运动路径的函数。它的主要用途是为动画中的对象提供沿着一个确定路径(通常是圆形)的运动轨迹,特别是那些希望对象沿着圆的逆时针方向运动的场景。

用法说明

通常情况下,counterclockwise_path 可以与其他动画结合使用,比如在 MoveAlongPath 动画中,让一个对象沿着这个路径移动。以下是一些相关要点:

  • 创建路径counterclockwise_path 通常不会单独调用,而是会与其他函数结合使用,帮助定义动画对象如何沿着给定路径移动。

  • 返回值: 调用 counterclockwise_path 函数后,它通常会返回一个能表示逆时针运动的路径(如圆弧)对象,通过这些对象可以为运动的方向和轨迹提供清晰的控制。

示例代码

以下是一个简单的示例,展示如何使用 counterclockwise_path() 创建一个逆时针路径,并让一个点沿着这个路径移动:

from manim import *

class CounterclockwisePathExample(Scene):
    def construct(self):
        colors = [RED, GREEN, BLUE]

        starting_points = VGroup(
            *[
                Dot(LEFT + pos, color=color)
                for pos, color in zip([UP, DOWN, LEFT], colors)
            ]
        )

        finish_points = VGroup(
            *[
                Dot(RIGHT + pos, color=color)
                for pos, color in zip([ORIGIN, UP, DOWN], colors)
            ]
        )

        self.add(starting_points)
        self.add(finish_points)
        for dot in starting_points:
            self.add(TracedPath(dot.get_center, stroke_color=dot.get_color()))

        self.wait()
        self.play(
            Transform(
                starting_points,
                finish_points,
                path_func=utils.paths.counterclockwise_path(),
                run_time=2,
            )
        )
        self.wait()

运行结果:

 3.沿着弧线运动路径的绘制

path_along_arc() 是 Manim 中用于创建沿着弧线路径运动的函数。此函数允许你定义一个特定的弧形路径,通常用于对象的动画效果,使其沿着一个圆弧进行移动。

path_along_arc(arc_angle, axis=array([0., 0., 1.]))

 

函数参数解释

  1. arc_angle:
    • 类型: 数值(以弧度为单位)
    • 描述: 这是所需弧线的角度,决定了路径的长度和形状。例如,如果你设置为 PI / 2,这表示创建一个 90 度的弧形路径,而 PI 表示 180 度(半个圆),TAU 表示一个完整的圆。
  2. axis:
    • 类型: NumPy 数组(默认为 array([0., 0., 1.])
    • 描述: 这是定义弧线平面方向的矢量,指定了弧线在三维空间中的旋转方向。默认值为 [0, 0, 1],这表示弧线平面与 Z 轴平行(即在 XY 平面中)。
    • 其他值示例:
      • array([1., 0., 0.]):表示弧线在 YZ 平面中。
      • array([0., 1., 0.]):表示弧线在 XZ 平面中。

使用示例

以下是一个示例代码,使用 path_along_arc 创建一个沿着弧线运动的点:

 

from manim import *

class PathAlongArcExample(Scene):
    def construct(self):
        colors = [RED, GREEN, BLUE]

        starting_points = VGroup(
            *[
                Dot(LEFT + pos, color=color)
                for pos, color in zip([UP, DOWN, LEFT], colors)
            ]
        )

        finish_points = VGroup(
            *[
                Dot(RIGHT + pos, color=color)
                for pos, color in zip([ORIGIN, UP, DOWN], colors)
            ]
        )

        self.add(starting_points)
        self.add(finish_points)
        for dot in starting_points:
            self.add(TracedPath(dot.get_center, stroke_color=dot.get_color()))

        self.wait()
        self.play(
            Transform(
                starting_points,
                finish_points,
                path_func=utils.paths.path_along_arc(TAU * 2 / 3),
                run_time=3,
            )
        )
        self.wait()

 我们可以调试弧线的半径和角度。

from manim import *  

class PathAlongArcExample(Scene):  
    def construct(self):  
        colors = [RED, GREEN, BLUE]  

        starting_points = VGroup(  
            *[  
                Dot(LEFT + pos, color=color)  
                for pos, color in zip([UP, DOWN, LEFT], colors)  
            ]  
        )  

        finish_points = VGroup(  
            *[  
                Dot(RIGHT + pos, color=color)  
                for pos, color in zip([ORIGIN, UP, DOWN], colors)  
            ]  
        )  

        self.add(starting_points)  
        self.add(finish_points)  

        for dot in starting_points:  
            self.add(TracedPath(dot.get_center, stroke_color=dot.get_color()))  

        self.wait()  

        # 自定义弧线的半径和角度  
        arc_radius = 2  # 半径  
        arc_angle = TAU / 2  # 90度的弧  

        # 使用 path_along_arc 创建路径  
        arc_path = Arc(radius=arc_radius, angle=arc_angle)  

        # Transform 动画  
        self.play(  
            Transform(  
                starting_points,  
                finish_points,  
                path_func=path_along_arc(arc_angle=arc_angle),  
                run_time=3,  
            )  
        )  
        self.wait()  

代码说明

  1. 弧线的半径: 我们在代码中添加了 arc_radius = 2,这将半径设置为 2。

  2. 弧线的角度: 修改了 arc_angle = TAU / 2,以设置弧线的角度为 90 度(即 TAU / 4 代表 45 度,TAU / 2 代表 90 度)。你可以根据需要进一步调整角度。

  3. 创建弧线路径: 使用 arc_path = Arc(radius=arc_radius, angle=arc_angle) 来定义弧线的路径。然后用 path_func=lambda t: arc_path.point_from_proportion(t) 来指定在动画中使用的路径。

4. 沿着多个圆的路径绘制

path_along_circles() 是 Manim 中用来创建一个沿着多个圆的路径的函数。这使得对象可以沿着多个圆的弧形轨迹移动。

path_along_circles(arc_angle, circles_centers, axis=array([0., 0., 1.]))

函数参数解释

  1. arc_angle:

    • 类型: 数值(以弧度为单位)
    • 描述: 指定沿每个圆的移动角度。这个角度决定了对象在每个圆上的运动路径的范围。例如,如果 arc_angle 设置为 TAU / 4(90度),那么对象将在每个圆上移动90度。
  2. circles_centers:

    • 类型: 列表或数组
    • 描述: 这是一个点的集合,其中每个点代表一个圆的中心。对象将沿着以这些中心为中心的圆移动。这些中心的格式通常是二维或三维坐标数组。例如,[[0, 0, 0], [2, 0, 0], [0, 2, 0]] 表示三个圆心的位置。
  3. axis:

    • 类型: NumPy 数组(默认为 array([0., 0., 1.])
    • 描述: 定义了圆平面的法向量,决定弧线在三维空间中的方向。如果使用默认值 array([0., 0., 1.]),表示圆平面位于 XY 平面上。其他选项可能是 array([1., 0., 0.])(YZ 平面),或者 array([0., 1., 0.])(XZ 平面)。

使用示例

下面是一个使用 path_along_circles 创建沿着多个圆弧路径移动的点的示例代码:

from manim import *

class PathAlongCirclesExample(Scene):
    def construct(self):
        colors = [RED, GREEN, BLUE]

        starting_points = VGroup(
            *[
                Dot(LEFT + pos, color=color)
                for pos, color in zip([UP, DOWN, LEFT], colors)
            ]
        )

        finish_points = VGroup(
            *[
                Dot(RIGHT + pos, color=color)
                for pos, color in zip([ORIGIN, UP, DOWN], colors)
            ]
        )

        self.add(starting_points)
        self.add(finish_points)
        for dot in starting_points:
            self.add(TracedPath(dot.get_center, stroke_color=dot.get_color()))

        circle_center = Dot(3 * LEFT)
        self.add(circle_center)

        self.wait()
        self.play(
            Transform(
                starting_points,
                finish_points,
                path_func=utils.paths.path_along_circles(
                    2 * PI, circle_center.get_center()
                ),
                run_time=3,
            )
        )
        self.wait()

 

5.螺旋运动路径的绘制 

spiral_path() 是 Manim 中用于创建螺旋路径的函数。这个函数生成一个沿着螺旋线移动的路径,使得对象可以在动画中根据提供的参数沿着螺旋轨迹移动。

spiral_path(angle, axis=array([0., 0., 1.]))

函数参数解释

  1. angle:

    • 类型: 数值(以弧度为单位)
    • 描述: 这个参数指定了螺旋的每一圈所包含的角度。通过增大这个角度,你可以控制螺旋的紧密程度和形状。例如,如果你将角度设置为 TAU(一个完整的圆),则每次迭代将生成一个完整的圆;如果设置为 TAU / 2,则将生成半圈的螺旋。
  2. axis:

    • 类型: NumPy 数组(默认为 array([0., 0., 1.])
    • 描述: 该参数定义了螺旋线的方向,决定了其在三维空间中的旋转方向。默认为 [0, 0, 1],这表示螺旋在 XY 平面上;如果更改为 [1, 0, 0],则旋转将在 YZ 平面中;更改为 [0, 1, 0],则螺旋将在 XZ 平面上。

使用示例

下面是一个使用 spiral_path 创建沿着螺旋路径移动的点的示例代码:

from manim import *

class SpiralPathExample(Scene):
    def construct(self):
        colors = [RED, GREEN, BLUE]

        starting_points = VGroup(
            *[
                Dot(LEFT + pos, color=color)
                for pos, color in zip([UP, DOWN, LEFT], colors)
            ]
        )

        finish_points = VGroup(
            *[
                Dot(RIGHT + pos, color=color)
                for pos, color in zip([ORIGIN, UP, DOWN], colors)
            ]
        )

        self.add(starting_points)
        self.add(finish_points)
        for dot in starting_points:
            self.add(TracedPath(dot.get_center, stroke_color=dot.get_color()))

        self.wait()
        self.play(
            Transform(
                starting_points,
                finish_points,
                path_func=utils.paths.spiral_path(2 * TAU),
                run_time=5,
            )
        )
        self.wait()

 6.直线运动路径的绘制

straight_path() 是 Manim 中用于创建直线路径的函数。这个函数简单明了,主要用于定义一个沿直线移动的路径。通过该函数,可以将对象在动画中沿着一条直线进行移动。

函数概述

straight_path() 不需要任何参数,并返回一个用于移动的直线路径。默认情况下,该函数会生成一条从起始点到目标点的直线。通常,你会在 MoveAlongPath 动画中使用此函数来指定对象的移动路径。

典型用法示例

以下是一个示例,展示了如何使用 straight_path 来让一个点沿直线路径移动:

from manim import *

class StraightPathExample(Scene):
    def construct(self):
        colors = [RED, GREEN, BLUE]

        starting_points = VGroup(
            *[
                Dot(LEFT + pos, color=color)
                for pos, color in zip([UP, DOWN, LEFT], colors)
            ]
        )

        finish_points = VGroup(
            *[
                Dot(RIGHT + pos, color=color)
                for pos, color in zip([ORIGIN, UP, DOWN], colors)
            ]
        )

        self.add(starting_points)
        self.add(finish_points)
        for dot in starting_points:
            self.add(TracedPath(dot.get_center, stroke_color=dot.get_color()))

        self.wait()
        self.play(
            Transform(
                starting_points,
                finish_points,
                path_func=utils.paths.straight_path(),
                run_time=2,
            )
        )
        self.wait()

三,沿着指定函数绘制路径

实例1:

from manim import *  

class CirclePathExample01(Scene):  
    def construct(self):  
        # 创建一个点  
        dot = Dot(radius=0.25,color=BLUE)  

        # 创建 sin(x) 路径  
        # 使用 ParametricFunction 来定义 sin(x) 曲线  
        sin_curve = ParametricFunction(  
            lambda t: np.array([t, np.sin(t), 0]),  # x = t, y = sin(t)  
            t_range=[-TAU, TAU],  # 设置 t 的范围  
            color=WHITE  
        )  

        # 创建 TracedPath 来跟踪点的运动  
        traced_path = TracedPath(dot.get_center, stroke_color=YELLOW)  

        # 添加点和轨迹到场景中  
        self.add(traced_path, dot)  

        # 添加 sin(x) 曲线到场景中  
        #self.add(sin_curve)  

        # 使用 MoveAlongPath 将点沿着 sin(x) 曲线移动  
        self.play(MoveAlongPath(dot, sin_curve), run_time=4)  

        self.wait()  

代码说明

  1. 定义 sin(x) 曲线: 使用 ParametricFunction 创建 sin(x) 曲线。这里的 lambda t: np.array([t, np.sin(t), 0]) 定义了点在二维平面上的位置,其中 t 表示 x 坐标,np.sin(t) 表示 y 坐标。

  2. 设置参数范围t_range=[-TAU, TAU] 设置了参数 t 的范围,使得点能够在 sin(x) 曲线的完整一周上移动。

  3. 添加曲线到场景: 使用 self.add(sin_curve) 将 sin(x) 曲线添加到场景中。

  4. 沿曲线移动: 使用 MoveAlongPath 让点沿着 sin(x) 曲线移动。

运行代码

运行这个示例代码后,你应该能看到蓝色的点沿着 sin(x) 曲线移动,同时黄色的轨迹会显示出它的运动轨迹。

示例2:

from manim import *  

class CirclePathExample02(Scene):  
    def construct(self):  
        # 创建一个点  
        dot = Dot(radius=0.25, color=BLUE)  

        # 创建 sin(x) 路径  
        sin_curve = ParametricFunction(  
            lambda t: np.array([t, np.sin(t), 0]),  # x = t, y = sin(t)  
            t_range=[-TAU, TAU],  # 设置 t 的范围  
            color=WHITE  
        )  

        # 创建 cos(x) 路径  
        cos_curve = ParametricFunction(  
            lambda t: np.array([t, np.cos(t), 0]),  # x = t, y = cos(t)  
            t_range=[-TAU, TAU],  # 设置 t 的范围  
            color=GREEN  
        )  

        # 创建 arctan(x) 路径  
        arctan_curve = ParametricFunction(  
            lambda t: np.array([t, np.arctan(t), 0]),  # x = t, y = arctan(t)  
            t_range=[-TAU, TAU],  # 设置 t 的范围  
            color=RED  
        )  

        # 创建 TracedPath 来跟踪点的运动  
        traced_path = TracedPath(dot.get_center, stroke_color=YELLOW)  

        # 添加点和轨迹到场景中  
        self.add(traced_path, dot)  

        # 添加 sin(x)、cos(x) 和 arctan(x) 曲线到场景中  
        #self.add(sin_curve, cos_curve, arctan_curve)  

        # 使用 AnimationGroup 同时播放所有路径的移动  
        self.play(  
            MoveAlongPath(dot, sin_curve, run_time=4),  
            MoveAlongPath(dot, cos_curve, run_time=4),  
            MoveAlongPath(dot, arctan_curve, run_time=4)  
        )  

        # 等待一段时间  
        self.wait()  

代码说明

  1. arctan_curve:

    • 创建了 arctan_curve 作为 arctan(x) 的路径,使用 np.arctan(t) 来定义 y 轴的值。
  2. 添加所有曲线:

    • 将 sin_curvecos_curve 和 arctan_curve 添加到场景中,以便在动画中可见。
  3. 同时播放动画:

    • 使用 AnimationGroup(在这里通过直接在 play 中传递多个 MoveAlongPath 动画)来同时播放点沿 sin(x)cos(x) 和 arctan(x) 曲线的移动。每条路径的动画时间设置为 run_time=4

注意事项

  • 路径的可见性: 确保在场景中添加所有曲线,以便可以同时观察它们。
  • 动画效果: 由于同时移动,点可能在某些时刻重叠。可以根据需要调整动画的 run_time 或者使用不同的动画组合方式。

 

  • 9
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yasen.M

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值