python动画:实现贝塞尔曲线【bezier】

贝塞尔曲线在计算机图形学中用于绘制形状、用于 CSS 动画和许多其他地方。它们是一件非常简单的事情,值得学习一次,然后在矢量图形和高级动画的世界中感到舒适。

一.控制点

贝塞尔曲线由控制点可能有 2、3、4 或更多。

例如,二次贝塞尔曲线:

三次贝塞尔曲线:

四次贝塞尔曲线:

如果你仔细观察这些曲线,你会立即注意到:

  1. **点并不总是在曲线上。**这是完全正常的,稍后我们将看到曲线是如何构建的。

  2. 曲线顺序等于点数减去 1。 对于两点,我们有一条线性曲线(一条直线),对于三点 -- 二次曲线(抛物线),对于四点 -- 三次曲线。

  3. 曲线始终位于控制点的凸包内:

|-------------------------------------------------------------------------------|-------------------------------------------------------------------------------|
| 1. | 1. |

由于最后一个属性,在计算机图形学中,可以优化交叉点测试。如果凸包不相交,则曲线也不相交。因此,首先检查凸包相交可以给出非常快速的"无相交"结果。检查凸壳的交点要容易得多,因为它们是矩形、三角形等(见上图),比曲线简单得多。

贝塞尔曲线用于绘图的主要价值 -- 通过移动点,曲线以直观、明显的方式发生变化。

二.数学表达式

贝塞尔曲线可以用数学公式来描述。正如我们所看到的------实际上没有必要知道它,大多数人只是通过用鼠标移动点来绘制曲线。但如果你喜欢数学------就在这里。

给定控制点的坐标:第一个控制点有坐标,第二个控制点有坐标:,依此类推,曲线坐标由依赖于线段参数的方程来描述

  • 2 点曲线的公式:

  • 对于 3 个控制点:

  • 对于 4 个控制点:

这些是向量方程。换句话说,我们可以把 and 而不是来获取相应的坐标。x,y,P

例如,3 点曲线由计算如下的点组成:(x,y)

相反,我们应该放置 3 个控制点的坐标,然后随着从 移动到 ,我们将拥有曲线的每个值。x1, y1, x2, y2, x3, y3,``t``0``1t(x,y)

例如,如果控制点为 , 和 ,则方程变为:(0,0)(0.5, 1)(1, 0)

现在,当从 到 运行时,每个值的集合构成了此类控制点的曲线。t``0``1(x,y)t

三,manim实现:应用函数

1.CubicBezier 曲线

在 Manim 中,CubicBezier 曲线需要指定起点、终点和两个控制点。CubicBezier 的构造函数的参数通常是 start, end, start_control, 和 end_control。

正确的使用方法 为了创建一条立方贝塞尔曲线,您需要提供开始和结束点,以及它们各自的控制点。下面是一个示例代码片段:

python 复制代码
from manim import *

    class BezierExample(Scene):
    def construct(self):
    # 定义起点、结束点和控制点
    start_point = LEFT
    end_point = RIGHT
    start_control = UP
    end_control = DOWN



# 创建三次贝塞尔曲线 
bezier_curve = CubicBezier(start_point, start_control, end_control, end_point) # 绘制曲线 self.play(Create(bezier_curve)) self.wait(2)

解释

start_point: 曲线的起始坐标(左边的点)。

end_point: 曲线的结束坐标(右边的点)。

start_control: 控制曲线形状的第一个控制点。

end_control: 控制曲线形状的第二个控制点。

总结 :

确保在实例化 CubicBezier 时提供了所有必需的参数:起点、终点、起始控制点和结束控制点。这样可以避免 TypeError 并正确创建贝塞尔曲线。

2.常见的贝塞尔相关类和函数

在 Manim 中,除了 CubicBezier 函数外,还有其他几种函数和方法用于绘制不同类型的贝塞尔曲线。以下是一些常见的贝塞尔相关类和函数:

Bezier Bezier(points): 这个类可以用来表示任意阶的贝塞尔曲线。它的构造函数接受一个点的列表,这些点可以是任意数量的控制点。适用于线性、二次、三次乃至更高阶的贝塞尔曲线。

python 复制代码
from manim import *
class BezierExample(Scene):
    def construct(self):
    points = [LEFT, UP, RIGHT] # 三个控制点
    bezier_curve = Bezier(points) # 创建贝塞尔曲线
    self.play(Create(bezier_curve))  
    self.wait(2)  

QuadraticBezier QuadraticBezier(start, control, end): 创建一条二次贝塞尔曲线。需要提供起点、控制点和终点。

python 复制代码
from manim import *

class QuadraticBezierExample(Scene):
    def construct(self):
# 定义点
        start = LEFT
        control = UP
        end = RIGHT



# 创建二次贝塞尔曲线 
        bezier_curve = QuadraticBezier(start, control, end) self.play(Create(bezier_curve))                 
        self.wait(2)

CubicBezier CubicBezier(start, start_control, end_control, end): 创建一条三次贝塞尔曲线,使用起点、两个控制点和终点。 其他贝塞尔相关函数 在 Manim 中,除了以上类,您还可能遇到一些其他有用的函数和方法,如在动画中与路径相关的操作、插值和运动等。

使用示例 要使用这些不同类型的贝塞尔函数,您只需确保根据所需曲线类型提供适当数量和位置的点。

总结 在 Manim 中使用贝塞尔曲线时,您可以选择不同的类来创建线性、二次或三次贝塞尔曲线,具体取决于您所需的复杂性和形状。

四,实现贝塞尔曲线

python 复制代码
from manim import *  

class Bezier2305(Scene):  
    def construct(self):  
        # 定义控制点  
        P1 = np.array([-4, -2, 0])  
        P2 = np.array([0, 3, 0])  
        P3 = np.array([0, -1, 0])  # 二次贝塞尔曲线的控制点  
        P4 = np.array([2, 3, 0])    # 三次贝塞尔曲线的控制点  
        P5=np.array([5, 2, 0])
        
        

        # 根据控制点计算各种贝塞尔曲线  
        bezier_2_points = [self.bezier_2_points(P1, P2, t) for t in np.linspace(0, 1, 100)]  
        bezier_3_points = [self.bezier_3_points(P1, P2, P3, t) for t in np.linspace(0, 1, 50)]  
        bezier_4_points = [self.bezier_4_points(P1, P2, P3, P4, t) for t in np.linspace(0, 1, 100)] 
        bezier_5_points = [self.bezier_5_points(P1, P2, P3, P4,P5, t) for t in np.linspace(0, 1, 100)] 
        

        # 创建 Mobject  
        curve_2 = self.create_curve(bezier_2_points)
        curve_3 = self.create_curve(bezier_3_points)  
        curve_4 = self.create_curve(bezier_4_points)
        curve_5 = self.create_curve(bezier_5_points)

        # 动画展示
        
        #二次
        #点
        d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        self.add(d1)
        d2 = Dot(P2,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        self.add(d2)
        #线
        L1=Line(start=d1,end=d2,color=GREEN)
        
        self.play(Create(curve_2))
        self.play(Create(L1))
        a=Text("二次贝塞尔曲线",color=PINK).shift(2*DOWN)
        self.add(a)
        self.wait(1)  
        self.play(FadeOut(curve_2,L1,d1,d2,a)) 
        
        
        
        #三次
        d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        #self.add(d1)
        d2 = Dot(P2,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
        #self.add(d2)
        d3 = Dot(P3,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        #self.add(d3)
        L1=Line(start=d1,end=d2,color=GREEN)
        L2=Line(start=d2,end=d3,color=YELLOW)
        #self.play(Create(L1))
        b=Text("三次贝塞尔曲线",color=PINK).shift(2*DOWN)
        self.add(b)
        self.play(Create(curve_3))
        self.play(Create(L1))
        self.wait(1)  
        self.play(FadeOut(curve_3,d1,L1,d2,L2,d3,b)) 
        self.wait(1.5) 
        
        #四次
        d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        d2 = Dot(P2,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
        d3 = Dot(P3,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        d4 = Dot(P4,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
        #line
        L1=Line(start=d1,end=d2,color=GREEN)
        L2=Line(start=d2,end=d3,color=YELLOW)
        L3=Line(start=d3,end=d4,color=YELLOW)
        #曲线
        self.play(Create(curve_4)) 
        c=Text("四次贝塞尔曲线",color=PINK).shift(2*DOWN)
        self.add(c)
        self.wait(1)
        self.play(Create(d1),Create(L1),Create(d2),Create(L2),Create(d3),Create(L3),Create(d4))
        self.wait(1)
        self.play(FadeOut(curve_4,d1,L1,d2,L2,d3,L3,d4,c))
        
        #五次
        d1 = Dot(P1,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        d2 = Dot(P2,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
        d3 = Dot(P3,radius=0.2,color=GREEN,stroke_width=10, fill_opacity=0)
        d4 = Dot(P4,radius=0.2,color=RED,stroke_width=10, fill_opacity=0)
        d5=Dot(P5,radius=0.2,color=YELLOW,stroke_width=10, fill_opacity=0)
        #line
        L1=Line(start=d1,end=d2,color=GREEN)
        L2=Line(start=d2,end=d3,color=YELLOW)
        L3=Line(start=d3,end=d4,color=YELLOW)
        L4=Line(start=d4,end=d5,color=RED)
        
        #曲线
        self.play(Create(curve_5)) 
        d=Text("五次贝塞尔曲线",color=PINK).shift(2*DOWN)
        self.add(d)
        self.wait(1)
        self.play(Create(d1),Create(L1),Create(d2),Create(L2),Create(d3),
                  Create(L3),Create(d4),Create(L4),Create(d5))
        self.wait(1)
        self.play(FadeOut(curve_5,d1,L1,d2,L2,d3,L3,d4,L4,d5,d))
        self.wait(2)

    def bezier_2_points(self, P1, P2, t):  
        """计算2点贝塞尔曲线上的点"""  
        return (1 - t) * P1 + t * P2  

    def bezier_3_points(self, P1, P2, P3, t):  
        """计算3点贝塞尔曲线上的点"""  
        return (1 - t)**2 * P1 + 2 * (1 - t) * t * P2 + t**2 * P3  

    def bezier_4_points(self, P1, P2, P3, P4, t):  
        """计算4点贝塞尔曲线上的点"""  
        return (1 - t)**3 * P1 + 3 * (1 - t)**2 * t * P2 + 3 * (1 - t) * t**2 * P3 + t**3 * P4 
    
    def bezier_5_points(self, P1, P2, P3, P4,P5, t):  
        """计算4点贝塞尔曲线上的点"""  
        return (1 - t)**4 * P1 + 4 * (1 - t)**3 * t * P2 + 4 * (1 - t) * t**3 * P3+ 4 * (1 - t) * t**3 * P4 + t**4 * P5 

    def create_curve(self, points):  
        """创建通过给定点的曲线"""  
        return VMobject().set_points_smoothly(points)  

%manim -qm -v WARNING Bezier2305

完整运行结果:https://download.csdn.net/download/qq_45449625/89666944https://download.csdn.net/download/qq_45449625/89666944

运行片段:

|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| | |
| | |

相关推荐
写代码写到手抽筋1 分钟前
C++性能优化之访存优化(未完)
开发语言·c++
Dovis(誓平步青云)14 分钟前
基于面向对象设计的C++日期推算引擎:精准高效的时间运算实现与运算重载工程化实践
开发语言·c++·经验分享·笔记
HORSE RUNNING WILD17 分钟前
解决 PicGo 上传 GitHub图床及Marp中Github图片编译常见难题指南
css·python·github
夜晚中的人海27 分钟前
【C语言】初阶数据结构相关习题(二)
c语言·开发语言·数据结构
武昌库里写JAVA40 分钟前
MacOS Python3安装
java·开发语言·spring boot·学习·课程设计
ElenaYu41 分钟前
mac安装cast
python·macos·cast
Dxy123931021643 分钟前
python如何设置excel单元格边框样式
开发语言·python·excel
chaodaibing1 小时前
Python解析Excel入库如何做到行的拆分
开发语言·python·excel
dudly1 小时前
Python类的力量:第五篇:魔法方法与协议——让类拥有Python的“超能力”
开发语言·python
ghost1432 小时前
C#学习第22天:网络编程
开发语言·学习·c#