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

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

一.控制点

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

例如,二次贝塞尔曲线:

三次贝塞尔曲线:

四次贝塞尔曲线:

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

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

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

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

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

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

二.数学表达式

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

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

P_{1} = (x_{1}, y_{1}) \\ P_{2} = (x_{2}, y_{2}) \\t[0,1]

  • 2 点曲线的公式:

    P = (1-t)P_{1} + tP_{2}

  • 对于 3 个控制点:

    P = (1−t) ^{2} P_1 + 2(1−t)tP_{2} + t^{2}P_{3}

  • 对于 4 个控制点:

    P = (1−t)^{3}P_{1} + 3(1−t)^{2}tP_{2} +3(1−t)t^{2}P_{3} + t^{3}P_{4}

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

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

  • x = (1−t)^2x_1 + 2(1−t)tx_2 + t^2x_3
  • x = (1−t)^2y_1 + 2(1−t)ty_2 + t^2y_3

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

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

  • x = (1−t)^2 * 0 + 2(1−t)t * 0.5 + t^2 * 1 = (1-t)t + t^2 = t
  • y = (1−t)^2 * 0 + 2(1−t)t * 1 + t^2 * 0 = 2(1-t)t = –2t2 + 2t

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

三,manim实现:应用函数

1.CubicBezier 曲线

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

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

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

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): 创建一条二次贝塞尔曲线。需要提供起点、控制点和终点。

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 中使用贝塞尔曲线时,您可以选择不同的类来创建线性、二次或三次贝塞尔曲线,具体取决于您所需的复杂性和形状。

四,实现贝塞尔曲线

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/89666944icon-default.png?t=N7T8https://download.csdn.net/download/qq_45449625/89666944

运行片段:

 

  • 20
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python 作为一种广泛使用的高级编程语言,对于处理图形和数学计算有着强大的支持库,例如 `matplotlib`、`numpy` 和 `scipy` 等。如果你想要读取贝塞尔曲线的信息,通常涉及到的数据可能是控制点坐标或者是贝塞尔曲线数学描述。 ### 使用 Python 读取贝塞尔曲线数据的基本步骤: #### 通过文件读取 假设你有一个存储了贝塞尔曲线信息的文本文件,文件内容可能像这样: ``` control_points = [[0, 0], [4, 6], [8, -5], [-4, -7]] t_values = [i / 9 for i in range(10)] ``` 你可以使用 Python 的标准库 `json` 或者 `pickle` 来解析这样的结构化数据。 **示例代码**: ```python import json # 读取 JSON 格式的数据 with open('bezier_data.json', 'r') as file: data = json.load(file) # 分离控制点列表和时间值列表 control_points = data['control_points'] t_values = data['t_values'] print("Control Points:", control_points) print("T Values:", t_values) ``` #### 直接从函数获取贝塞尔曲线数据 如果你有一个可以生成贝塞尔曲线的函数,并且该函数能够返回需要的数学表达式或数值,那么你可以在调用这个函数的时候直接得到贝塞尔曲线的信息。 **示例代码**: ```python from scipy.interpolate import Bezier def get_bezier_curve(control_points): return Bezier(control_points) # 定义控制点 control_points = [[0, 0], [4, 6], [8, -5], [-4, -7]] # 创建贝塞尔曲线实例 curve = get_bezier_curve(control_points) # 计算特定时刻的曲线点位置 t = 0.5 # 这是一个例子,表示中间位置 position = curve(t) # 返回的是 (x, y) 的坐标对 print(f"Position at t={t}: {position}") ``` ### 应用场景 - **动画制作**:用于创建平滑过渡效果或路径动画。 - **用户界面设计**:在设计软件的UI元素移动或变形时,贝塞尔曲线可以提供平滑的操作轨迹。 - **图形学**:在游戏和计算机辅助设计(CAD)中应用广泛的形状和路径绘制。 ### 相关问题: 1. 在 Python 中如何可视化贝塞尔曲线? 2. 如何调整贝塞尔曲线的控制点以改变其形状? 3. Python 中有哪些其他库可以帮助更高效地处理几何图形和数学操作?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Yasen.M

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

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

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

打赏作者

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

抵扣说明:

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

余额充值