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

news2024/11/24 10:58:39

        贝塞尔曲线在计算机图形学中用于绘制形状、用于 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

运行片段:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2069212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于java教师课堂教学质量评价系统设计与实现

课题背景 高等学校的根本任务是培养人才,课堂教学是高校完成人才培养的重要环节,因此, 教师教学质量的高低对学生掌握和运用知识的程度有着密不可分的作用,为了保证教师的教学质量,教学评价成为了各高校衡量教师教学质…

大数据-92 Spark 集群 SparkRDD 原理 Standalone详解 ShuffleV1V2详解 RDD编程优化

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

盘古信息IMS MCM制造协同管理系统:为中小企业数字化转型量身打造的数字化方案

近年来,全球经济的不稳定性,给中小企业的经营和发展带来了巨大的挑战。为提升企业竞争力,中小企业纷纷谋求数字化转型路径,优化生产流程、提高运营效率、降低生产成本,以应对变幻莫测的市场环境。IMS MCM是盘古信息为广…

go中 panicrecoverdefer机制

go的defer机制-CSDN博客 常见panic场景 数组或切片越界,例如 s : make([]int, 3); fmt.Println(s[5]) 会引发 panic: runtime error: index out of range空指针调用,例如 var p *Person; fmt.Println(p.Name) 会引发 panic: runtime error: invalid m…

IT 人员配置的演变趋势:2024 年上半年的见解

随着我们深入研究 2024 年的动态格局,IT 人员配置领域在前六个月见证了几个值得注意的趋势和变化。 这些发展不仅反映了企业不断变化的需求,也凸显了技术对劳动力动态的变革性影响。 以下是在这个关键年份上半年塑造 IT 人员配置的一些关键趋势的详细介…

Python办公自动化smtplib实现自动发送邮件

学好python自动化,走遍天下都不怕!! 今天主要学习如何利用python自动化分析处理数据并以附件形式发送邮箱。需要安装配置python的运行环境,以及电脑支持Excel文件,有可以正常使用的邮箱。还需要用到python的第三方模块…

剧本杀门店预约小程序,提高消费者体验

当下,剧本杀行业一直处于活跃的状态,不管是线下聚会还是休闲娱乐,剧本杀游戏都是消费者的选择,剧本杀市场具有非常大的发展前景。 剧本杀门店预约系统是一个高效、便捷的游戏预约方式,能够帮助消费者便捷预约&#xf…

基于ssm的爱心捐赠管理系统的设计与实现(论文+源码)_kaic

摘 要 在互联网高速发展的现在,许多的办公与应用从传统的实体办理变为了在线处理。网购与网淘商品的浏览也从大街小巷变为了在线预览,从而使网上用户更好地对物品产生客观、全面立体的认知,并且对物品的对比也更加的省时省力。 爱心捐赠管…

一个简单的springboot项目(有源码)

开发一个springboot项目 代码迭代整合工具 gitee建模意义程序处理方式开发功能的步骤web服务网络状态码 web应用的开发分层springboot的作用 springboot框架搭建框架中各组件作用框架的演变如何提取hive中的表结构创建springboot 工程的引导模版 要选择aliyun ,否则…

java ssl使用自定义证书或忽略证书

1.证书错误 Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target 2.生成客户端证书 openssl x509 -in <(openssl s_client -connect 192.168.11.19:8101 -prexit 2>/dev/null) -ou…

linux neo4j 切换知识图谱

neo4j 安装 linux neo4j的安装可以浏览这篇文章&#xff1a; ubuntu sudo apt-get install neo4j 配置安装与设置远程访问 引言 如果你是window用户&#xff0c;直接下载桌面版进行安装与使用即可&#xff1b; 我有一台linux的服务器&#xff0c;想部署在上面&#xff0c;不…

UE5.4内容示例(5)UI_CommonUI - 学习笔记

https://www.unrealengine.com/marketplace/zh-CN/product/content-examples 《内容示例》是学习UE5的基础示例&#xff0c;可以用此熟悉一遍UE5的功能 UI_CommonUI可以看这个视频学习&#xff0c;此插件处于Beta状态&#xff0c;应用UI游戏方面&#xff0c;支持手柄等多输入端…

打饭-GYM

打饭 我还不信了&#xff0c;手动模拟一遍 再来了好看一点的图 ji12345a[i]21341120x3f0x3f0x3f0x3f0x3f114220x3f0x3f0x3f0x3f103520x3f0x3f0x3f0x3f9min(332,42)4020x3f0x3f0x3f8min(332,35)min(332,40)3190x3f0x3f7min(262,33)332490x3f0x3f6min(172,33)3120x3f0x3f0x3f5min…

【前端基础篇】JavaScript基础介绍

文章目录 前言初始JavaScriptJavaScript是什么发展历史JavaScript和HTML和CSS之间的关系JavaScript的运行过程JavaScript的组成 JavaScript的书写形式行内式内嵌式外部式注释 输入输出基础语法变量数据类型 运算符 JavaScript对象对象new关键字 常用对象数组创建数组数组操作函…

电影票api接口对接开发过程中需要注意什么?

电影票API接口对接过程需要考虑以下几个关键点&#xff1a; 1.了解API接口基础&#xff1a; 获取接口文档&#xff0c;理解其结构、请求方式、参数和返回数据格式。 2.接入流程&#xff1a; 使用API密钥或令牌进行身份验证。利用沙箱环境无风险测试。选择合适的编程语言实现…

Centos LVM磁盘合并方法

Centos LVM磁盘合并方法 使用fdisk -l命令查看机器增加了2块物理磁盘&#xff0c;一块40G另一块50G 需要将这两块盘的空间合并在一起&#xff0c;而且还需要动态扩展即在不关机的情况下操作 使用pvcreate将两块新增的物理磁盘加入物理卷 [rootlocalhost ~]# pvcreate /dev/sdb…

6G网络的关键技术、应用前景与挑战并存的科技征途

移动通信技术正以前所未有的速度迭代更新&#xff0c;而6G技术的研发与商用化进程渐渐成为了当前科技领域的热点与焦点。在5G技术尚未完全普及的今天&#xff0c;全球各国已纷纷将目光投向了更加充满想象的6G网络时代。本文将探讨全球6G研发的最新进展&#xff0c;特别是欧盟与…

Webots与ROS1、ROS2接口变迁-2024-

三大免费仿真器CoppeliaSim、Gazebo和Webots。 Gazebo接口总结&#xff1a; Gazebo与ROS1、ROS2接口变迁-2005-2024--CSDN博客 缺点&#xff1a;版本绑定策略 早期webots版本和ros版本绑定 后期&#xff0c;webots接口最新版本和ros特定版本最匹配。 例如&#xff1a; 最好按…

Ubuntu 中 SSH 服务的配置与原理详解

目录 1. 基本知识2. 配置步骤 1. 基本知识 一种用于在不安全的网络上安全登录和执行命令的协议 通过加密的方式保护通信数据&#xff0c;确保在传输过程中不被窃取或篡改 SSH 常用于远程登录服务器、传输文件以及执行命令 SSH 原理 公钥和私钥&#xff1a;SSH 使用公钥加密来…

UEFI 01记: 开发环境 在 ubuntu22 中搭建 edk2 开发环境并运行简单示例

https://uefi.org 1&#xff0c;预备环境 $ sudo apt install uuid-dev $ sudo apt install nasm $ sudo apt install bison flex $ sudo apt install build-essential $ sudo apt-get install x11proto-xext-dev $ sudo apt-get install libx11-dev $ sudo apt-get install l…