python动画:manim中的目标位置移动,线条末端和两条线相切的位置处理

一,Manim中目标的位置移动

在 Manim 中,shift 函数用于在三维空间或二维平面上对对象进行平移。通过 shift 方法,用户可以快速移动场景中的物体,指定移动的方向和距离。方向通常由预定义的常量(如 UPDOWNLEFTRIGHTINOUT 等)来表示。这些常量代表了坐标系中的特定方向,例如,UP 表示在 Y 轴正方向上移动一个单位,而 RIGHT 则表示在 X 轴正方向上移动许多单位。

使用 shift 方法,可以将任何基于 Mobject 的对象(如图形、文本等)沿着指定的方向进行移动,这在动画制作中尤为重要。例如,可以通过 shift(UP) 将对象向上移动,从而在场景中创建生动的动画效果。结合其他动画方法,shift 可以有效地增强场景的表现力,使得图形的移动更加流畅和自然。这使得 Manim 成为制作数学视频和可视化工具的强大工具。

  1. ORIGIN(原点):表示三维坐标系统中的点 (0, 0, 0),是所有其他坐标的参考点。

  2. UP(向上):表示在正 Y 方向移动一个单位,通常对应于三维空间中的向上。

  3. DOWN(向下):表示在负 Y 方向移动一个单位,通常对应于三维空间中的向下。

  4. RIGHT(向右):表示在正 X 方向移动一个单位,通常对应于平面或立体空间中的向右。

  5. LEFT(向左):表示在负 X 方向移动一个单位,通常对应于向左的方向。

  6. IN(向内):表示在负 Z 方向移动一个单位,通常意味着朝屏幕内或者远离观察者的方向。

  7. OUT(向外):表示在正 Z 方向移动一个单位,通常意味着朝观察者或者屏幕外的方向。

  8. UL(左上):表示向上移动一个单位,然后向左移动一个单位。

  9. UR(右上):表示向上移动一个单位,然后向右移动一个单位。

  10. DL(左下):表示向下移动一个单位,然后向左移动一个单位。

  11. DR(右下):表示向下移动一个单位,然后向右移动一个单位。

  12. PI(圆周率):是圆的周长与直径的比值,约为3.14159。

  13. TAU(双圆周率):是圆的周长与半径的比值,等于2PI,约为6.28318。

  14. DEGREES(度数):表示弧度与角度之间的换算关系。通常用于在计算中进行角度转换。

 

from manim import *  

class CoordinateSystem(Scene):  
    def construct(self):  
        # 创建坐标系  
        axes = Axes(  
            x_range=(-5, 5, 1),  
            y_range=(-5, 5, 1),  
            axis_config={"color": BLUE},  
        )  

        # 显示坐标系  
        self.play(Create(axes))  

        # 创建一个点在原点  
        point = Dot(ORIGIN,radius=0.25, color=YELLOW)  
        self.play(FadeIn(point))  

        # 向上移动  
        self.play(point.animate.shift(UP))  
        self.wait(1)  

        # 向下移动  
        self.play(point.animate.shift(DOWN))  
        self.wait(1)  

        # 向右移动  
        self.play(point.animate.shift(RIGHT))  
        self.wait(1)  

        # 向左移动  
        self.play(point.animate.shift(LEFT))  
        self.wait(1)  

        # 向内移动  
        self.play(point.animate.shift(IN))  
        self.wait(1)  

        # 向外移动  
        self.play(point.animate.shift(OUT))  
        self.wait(1)  

        # 组合移动:左上  
        self.play(point.animate.shift(UL))  
        self.wait(1)  

        # 组合移动:右上  
        self.play(point.animate.shift(UR))  
        self.wait(1)  

        # 组合移动:左下  
        self.play(point.animate.shift(DL))  
        self.wait(1)  

        # 组合移动:右下  
        self.play(point.animate.shift(DR))  
        self.wait(1)  

        # 结束演示  
        self.play(FadeOut(point), FadeOut(axes))  

 二,设置线条的端点样式【CapStyleType】

在计算机图形学中,线条的端点样式(也称为线帽样式)对于实现图形的视觉效果至关重要。manim 库中的 CapStyleType 是一个用于设置线条端点样式的工具,提供了多种选项来定义线条的外观,从而加强视觉表现和美观程度。

常见的线条端点样式主要有三种:圆形(Round)、方形(Square)和平头(Butt)。圆形样式使得线条的两端呈现出光滑的半圆形效果,这种样式通常用于需要增加视觉柔和感的场景,例如演示动画中的渐变线条。方形样式的端点则是平坦的方形,这种效果给人一种坚固和明确的感觉,常用于技术化或现代风格的设计中。平头样式是直接剪裁在极限位置,没有任何延伸部分,因此在许多设计中应用广泛,例如用于描绘精确的几何形状时。

通过选择不同的 CapStyleType,用户可以在构建动画或插图时,根据特定情境强调或隐藏线条的特性。这种灵活性不仅增强了图形的可读性,还支持创作个性化的艺术风格,使得视觉表达更具吸引力和独特性。

构造函数

CapStyleType(value, names=None, *, module=None, qualname=None, type=None,
 start=1, boundary=None)

参数解释:

  1. value: 该样式的值,通常是一个整数,代表具体的线条样式。
  2. names: 可选的样式名称,可以是字符串或其他可迭代对象,描述该样式的名称。
  3. module: 指定定义此类型的模块。一般在使用 manim 时,这个参数会自动处理。
  4. qualname: 完全限定名称,可以是该类型的完整路径。
  5. type: 可选参数,指定对象的具体类型,这通常与渲染时的外观相关。
  6. start: 起始值,通常是索引的起始一点,序列的计数方式。
  7. boundary: 可选参数,表示该样式的边界条件。

示例代码1:

下面是一个 manim 使用 CapStyleType 的示例,展示如何创建一个带有不同端点样式的线段。

from manim import *  

class ExampleCapStyle(Scene):  
    def construct(self):  
        # 创建一个线段,使用已定义的 CapStyleType  
        line1 = Line(LEFT, RIGHT,color=RED,stroke_width=30, cap_style=CapStyleType.AUTO)  # 自动选择最合适的线条端点样式。 
        line2 = Line(LEFT * 2, RIGHT * 2,color=PURE_BLUE, stroke_width=30,
                     cap_style=CapStyleType.ROUND).shift(DOWN)  # 两端呈现出半圆形的边缘 
        line3 = Line(LEFT * 3, RIGHT * 3, color=PURE_GREEN,stroke_width=30, 
                     cap_style=CapStyleType.BUTT).shift(2*DOWN)# 结束部分是平坦的,没有任何突出部分
        line4 = Line(LEFT * 4, RIGHT * 4,color=PURPLE_A, stroke_width=30, 
                     cap_style=CapStyleType.SQUARE).shift(3*DOWN)  #线条端点呈现为正方形,线条在结束位置平直切割,形成方形的边缘

        # 将线段放置在场景中  
        self.add(line1)
        self.add(line2)
        self.add(line3)
        self.add(line4)

代码解释

  1. 导入所需的类:从 manim 库中导入*,这样就可以使用库中的所有基础对象和功能。
  2. 创建场景:定义一个场景类 ExampleCapStyle,并在其中的 construct 方法中创建线段。
  3. 使用预定义的 CapStyle:通过 CapStyle 类直接引用 ROUNDSQUARE 和 BUTT 属性,而不是尝试构造新实例。

在 manim 库中,AUTOROUNDBUTT 和 SQUARE 是定义线条端点样式(又称为线帽样式)的几种类型。这些样式决定了线条的两端如何呈现。下面是对每个样式的详细解释:

1. AUTO

  • 解释AUTO 样式允许 manim 根据上下文自动选择最合适的线条端点样式。这个选项通常用于希望简化设计而不需要明确指定具体样式的场景。当使用 AUTO 时,库将根据线条的宽度、背景及其他因素选择一个适当的端点样式。

2. ROUND

  • 解释ROUND 样式使得线条的两端呈现出半圆形的边缘。这样的样式通常用于需要视觉柔和感的场景。这类端点适合于动画、艺术效果或者任何需要使线条看起来更平滑的设计。它们通常给人一种更自然、更流动的感觉。

3. BUTT

  • 解释BUTT 样式表示线条的结束部分是平坦的,没有任何突出部分。这种样式在技术图纸或精确的几何形状中常常使用,因为它提供了一种清晰干净的效果。与圆形或方形样式相比,平头样式带来的视觉效果更加直接,适合用于强调线段的起止位置。

4. SQUARE

  • 解释SQUARE 样式的线条端点呈现为正方形,线条在结束位置平直切割,形成方形的边缘。这种风格在某些情况下提供了更为强烈和现代的视觉效果,适用于技术化、直线条的设计,常见于建筑或工程图纸中。方形样式给人一种坚固、明确的感觉。

总结

这四种样式为线条的视觉呈现提供了灵活性,设计师和动画制作者可以根据需要选择合适的样式来增强视觉效果或传达特定的信息。在不同的场景中,合适的端点样式能够显著提升设计的美观性和可读性。

 实例2:

from manim import *

class CapStyleVariants(Scene):
    def construct(self):
        arcs = VGroup(*[
            Arc(
                radius=1,
                start_angle=0,
                angle=TAU / 4,
                stroke_width=20,
                color=GREEN,
                cap_style=cap_style,
            )
            for cap_style in CapStyleType
        ])
        arcs.arrange(RIGHT, buff=1)
        self.add(arcs)
        for arc in arcs:
            label = Text(arc.cap_style.name, font_size=24).next_to(arc, DOWN)
            self.add(label)

三, 处理线段或连接的类型【LineJointType

LineJointType 是一个构造函数,通常用于定义线段或连接的类型,以便在图形或几何处理的上下文中使用。它的主要功能是创建一个表示特定连接方式的对象,该对象可以用于控制和描述线段之间的连接特性。

该构造函数有多个参数,包括 value,用于定义连接的基本特性,如“直线”或“曲线”。可选参数 names 可用于指明与该连接类型相关的名称,会在相关操作或处理流程中起到重要作用。module 和 qualname 则提供了命名空间的信息,有助于避免类型冲突并明确数据来源。

此外,type 参数可指定连接的具体类型,如“Bezier”曲线,而 start 提供了连接的起始点,通常默认设置为1。boundary 参数为连接的属性提供了附加约束条件。这使得 LineJointType 在构建复杂的几何图形或在动画生成等方面具有广泛的应用。通过这些参数,用户可以灵活控制线段的表现与交互特性。

LineJointType(value, names=None, *, module=None, qualname=None, type=None,
 start=1, boundary=None)

参数解释

  • value: 主参数,通常是描述连接类型的值,具体含义取决于上下文。
  • names: 可选参数,通常是一个字符串或字符串列表,用于定义与此连接类型相关联的名称。
  • module: 可选参数,指定模块的名称,可以用于关联或命名目的。
  • qualname: 可选参数,表示类型的限定名称(qualified name),在某些情况下它有助于维护类型的命名空间。
  • type: 可选参数,通常用于定义连接的特定类型,可能是某种自定义类型或标准类型。
  • start: 可选参数,默认值为1,通常表示连接的起始点。
  • boundary: 可选参数,可以代表连接的边界条件或约束。

示例代码

from manim import *  

class LineJointVariantsNoFOR(Scene):  
    def construct(self):  
        # 创建一个基本的线段作为模板  
        mob = VMobject(stroke_width=20, color=GREEN).set_points_as_corners([  
            np.array([-2, 0, 0]),  
            np.array([0, 0, 0]),  
            np.array([-1.5, 3, 0]),
        ])  

        # 所有连接类型的示例列表  
        joint_types = [  
            LineJointType.AUTO,   # 示例连接类型  
            LineJointType.ROUND,    # 示例连接类型  
            LineJointType.BEVEL,    # 示例连接类型  
            LineJointType.MITER,    # 示例连接类型  
        ]  

        # 为每种连接类型创建线段和标签  
        line1 = self.create_line_with_label(mob, joint_types[0], 0)  
        line2 = self.create_line_with_label(mob, joint_types[1], 1)  
        line3 = self.create_line_with_label(mob, joint_types[2], 2)
        line4 = self.create_line_with_label(mob, joint_types[3], 3)  

        # 将线段排列在一起  
        lines = VGroup(line1, line2, line3,line4)  
        lines.arrange(RIGHT, buff=1)  

        # 添加线段和标签到场景中  
        self.add(lines)  

    def create_line_with_label(self, mob, joint_type, index):  
        """创建带有标签的线段,避免代码重复。"""  
        line = mob.copy()  
        line.joint_type = joint_type  
        label = Text(line.joint_type.name).next_to(line, DOWN)  

        # 创建一个组,将线段和标签组合在一起  
        return VGroup(line, label).shift(RIGHT * index)  # 根据索引进行右移以排列线段

代码说明

  1. 创建新方法:添加了 create_line_with_label 方法以封装创建线段和标签的逻辑,从而减少代码重复。这个新方法接收一个 mob 对象、一个连接类型 joint_type,以及在水平排列中的索引 index

  2. 参数和返回值create_line_with_label 方法将创建传入连接类型的线段和标签,并返回组合在一起的 VGroup 对象。通过将每个线段和标签的组在 shift 方法中右移,这样就能控制它们的排列。

  3. 简化的 construct 方法:在 construct 方法中,调用 create_line_with_label 方法三次来创建每条线段和标签,使得代码结构更清晰,也更易于扩展。

功能与扩展性

使用这种方式,未来如果需要添加更多的连接类型,只需在 joint_types 列表中添加类型,并相应地调用 create_line_with_label 方法,而不需要重复代码的逻辑。这提高了代码的可读性和可维护性。

实例代码2:

from manim import *

class LineJointVariants(Scene):
    def construct(self):
        mob = VMobject(stroke_width=20, color=GREEN).set_points_as_corners([
            np.array([-2, 0, 0]),
            np.array([0, 0, 0]),
            np.array([-2, 1, 0]),
        ])
        lines = VGroup(*[mob.copy() for _ in range(len(LineJointType))])
        for line, joint_type in zip(lines, LineJointType):
            line.joint_type = joint_type

        lines.arrange(RIGHT, buff=1)
        self.add(lines)
        for line in lines:
            label = Text(line.joint_type.name).next_to(line, DOWN)
            self.add(label)

 四,渲染器【RendererType】

RendererType 并不是 Manim 的内置类或方法,因此可能是你遇到的特定上下文或自定义代码的一部分。不过,基于你提供的参数,我们可以猜测这个函数被用作某个 Renderer(渲染器)的类型定义。

RendererType(value, names=None, *, module=None, qualname=None, type=None,
 start=1, boundary=None)

在这种情况下,我会试着解释每个参数的意义:

参数解释

  1. value: 这个参数很可能代表渲染器的主体类型或名称,定义了要渲染的基本类型(例如,图形、文本等)。

  2. names: 这是一个可选参数,可以接受包含一组名称的列表,这些名称可能对应于渲染器的不同特性或处理方式。

  3. module: 这个参数可能是指包含该渲染器的 Python 模块的名称,以帮助识别和组织渲染器。

  4. qualname: 表示该对象的限定名称(qualified name),通常用于调试和错误追踪,显示从模块和类的上下文中引用的名称。

  5. type: 该参数可能用来指定渲染器的具体行为或类型。比如它可能代表某种算法或渲染方式,比如“Bezier”或“线性渲染”。

  6. start: 默认值为1,可能用于指示某种计数或索引的开始位置。

  7. boundary: 这个参数可能用于定义渲染的边界条件,通常以一个元组的形式传递,表示最小和最大边界值。

使用场景

在一个图形处理或渲染框架中,RendererType 可能用于定义图形或对象如何在不同条件下呈现或显示。通过传递不同的参数,用户可以灵活地构造多种渲染器类型,以适应不同的需求和场景。

Manim 示例代码

以下是一个简单的 Manim 代码示例,展示如何绘制一个简单的图形,并为其创建渲染标签。同时包含代码注释帮助理解。

from manim import *  

# 假设 RendererType 是一个可以用来为不同渲染类型构建类的函数  
class RendererType:  
    def __init__(self, value, names=None, module=None, qualname=None, type=None, start=1, boundary=None):  
        self.value = value  
        self.names = names or []  
        self.module = module  
        self.qualname = qualname  
        self.type = type  
        self.start = start  
        self.boundary = boundary  

    def __repr__(self):  
        return f"RendererType(value={self.value}, names={self.names})"  

class RendererDemo(Scene):  
    def construct(self):  
        # 使用 RendererType 创建不同的渲染器实例  
        rectangle_renderer = RendererType("RectangleRenderer", names=["rect1", "rect2"], type="Shape")  
        circle_renderer = RendererType("CircleRenderer", names=["circle1"], type="Shape")  

        # 创建矩形  
        rectangle = Rectangle(width=4, height=2, color=BLUE).set_fill(BLUE, opacity=0.5).shift(3*LEFT+2*UP)  
        label_rectangle = Text(rectangle_renderer.value).next_to(rectangle, DOWN)  

        # 创建圆形  
        circle = Circle(radius=1, color=GREEN).shift(RIGHT * 3+1*DOWN)  
        label_circle = Text(circle_renderer.value).next_to(circle, DOWN)  

        # 动画展示  
        self.play(Create(rectangle), Write(label_rectangle))  
        self.wait(1)  
        self.play(Create(circle), Write(label_circle))  
        self.wait(2)  

代码说明

  1. 假设的 RendererType 类:我们定义了 RendererType 类,这个类接受多个参数来标识不同的渲染器,并保存这些参数。

    • value: 渲染器的名称或类型。
    • names: 可选参数,表示与该渲染器相关的一组名称。
    • modulequalname: 与渲染器的模块和限定名称相关的参数。
    • type: 用于指定渲染器的具体类型(例如,“Shape”)。
    • startboundary: 较高级的配置参数可能用于特定需求。
  2. 创建 RendererDemo 场景:我们在场景中实例化 RendererType 对象。

    • 一个用于矩形的渲染器 (rectangle_renderer)。
    • 一个用于圆形的渲染器 (circle_renderer)。
  3. 绘制和动画:随后,按照之前的示例创建矩形和圆形,并为它们添加相应的标签,展示出来。

应用场景

尽管实际的 Manim 类库不包含 RendererType,这种构造展示了如何在代码中组织渲染相关的信息,并将其与场景中的视觉元素关联起来。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Yasen.M

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

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

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

打赏作者

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

抵扣说明:

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

余额充值