探索贝塞尔曲线:计算机图形学中的关键技术

🧑‍🎓 个人主页:《爱蹦跶的大A阿》

🔥当前正在更新专栏:《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》

​ 

✨ 前言

        贝塞尔曲线是计算机图形学和设计领域中的重要工具。它们由皮埃尔·贝塞尔在19世纪初提出,并在20世纪被引入计算机图形学中,用于创建平滑的曲线和复杂的形状。无论是矢量图形设计、动画制作,还是计算机字体设计,贝塞尔曲线都有广泛的应用。本文将深入探讨贝塞尔曲线的定义、种类、数学原理及其在计算机图形学中的应用。

✨ 正文

什么是贝塞尔曲线?

贝塞尔曲线是一种参数曲线,通常用于二维或三维空间中的计算机图形学。它们由控制点定义,通过这些控制点,可以精确地控制曲线的形状。贝塞尔曲线最常见的类型是二次贝塞尔曲线和三次贝塞尔曲线。

贝塞尔曲线的种类

1. 二次贝塞尔曲线

二次贝塞尔曲线由三个控制点 P0P_0P0​、P1P_1P1​ 和 P2P_2P2​ 定义。其数学表达式为:

其中,t 是一个参数,范围为 0 到 1。

2. 三次贝塞尔曲线

三次贝塞尔曲线由四个控制点 P0P_0P0​、P1P_1P1​、P2P_2P2​ 和 P3P_3P3​ 定义。其数学表达式为:

同样,t的范围为 0 到 1。

贝塞尔曲线的数学原理

        贝塞尔曲线的核心在于利用控制点来定义曲线的形状。通过调整这些控制点,可以生成不同的曲线形状。贝塞尔曲线的计算基于多项式插值方法,其中二次和三次贝塞尔曲线分别基于二次和三次多项式。

递归定义

        贝塞尔曲线可以通过递归方法定义。对于一个给定的参数 ttt,可以通过线性插值计算控制点之间的中间点,逐级递归,直到得到最终的曲线点。

贝塞尔曲线的应用

        贝塞尔曲线在计算机图形学中有着广泛的应用,以下是一些常见的应用领域:

1. 矢量图形设计

        矢量图形设计软件(如 Adobe Illustrator 和 CorelDRAW)广泛使用贝塞尔曲线来创建和编辑平滑的曲线和复杂的形状。设计师可以通过控制点精确地调整曲线的形状,实现高度精细的设计。

2. 字体设计

        字体设计师使用贝塞尔曲线来定义字体的轮廓。通过调整控制点,可以创建各种字体样式,并保证字体在不同大小和分辨率下的清晰度。

3. 动画制作

        在动画制作中,贝塞尔曲线用于定义运动路径和插值关键帧。通过贝塞尔曲线,可以创建平滑的运动轨迹,实现自然的动画效果。

4. 图像处理

        贝塞尔曲线在图像处理中的应用包括图像裁剪、形状检测和边缘检测等。通过贝塞尔曲线,可以精确地描述和处理图像中的复杂形状。

示例代码

以下是一个使用 Python 和 Matplotlib 绘制二次和三次贝塞尔曲线的示例代码:

import numpy as np
import matplotlib.pyplot as pltdef quadratic_bezier(t, p0, p1, p2):return (1 - t)**2 * p0 + 2 * (1 - t) * t * p1 + t**2 * p2def cubic_bezier(t, p0, p1, p2, p3):return (1 - t)**3 * p0 + 3 * (1 - t)**2 * t * p1 + 3 * (1 - t) * t**2 * p2 + t**3 * p3t_values = np.linspace(0, 1, 100)
p0 = np.array([0, 0])
p1 = np.array([1, 2])
p2 = np.array([3, 3])
p3 = np.array([4, 0])quadratic_points = [quadratic_bezier(t, p0, p1, p2) for t in t_values]
cubic_points = [cubic_bezier(t, p0, p1, p2, p3) for t in t_values]quadratic_points = np.array(quadratic_points)
cubic_points = np.array(cubic_points)plt.plot(quadratic_points[:, 0], quadratic_points[:, 1], label='Quadratic Bezier')
plt.plot(cubic_points[:, 0], cubic_points[:, 1], label='Cubic Bezier')
plt.scatter([p0[0], p1[0], p2[0]], [p0[1], p1[1], p2[1]], color='red')
plt.scatter([p0[0], p1[0], p2[0], p3[0]], [p0[1], p1[1], p2[1], p3[1]], color='blue')
plt.legend()
plt.title('Quadratic and Cubic Bezier Curves')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
 1、贝塞尔曲线运动示例代码
 // 贝塞尔曲线运动// 定义贝塞尔曲线函数bezier(t, P0, P1, P2, P3) {// 计算贝塞尔曲线上的点const x =Math.pow(1 - t, 3) * P0.x +3 * Math.pow(1 - t, 2) * t * P1.x +3 * (1 - t) * Math.pow(t, 2) * P2.x +Math.pow(t, 3) * P3.x;const y =Math.pow(1 - t, 3) * P0.y +3 * Math.pow(1 - t, 2) * t * P1.y +3 * (1 - t) * Math.pow(t, 2) * P2.y +Math.pow(t, 3) * P3.y;return { x, y };},animate(timestamp) {if (!this.startTime) this.startTime = timestamp;const elapsed = timestamp - this.startTime;const t = Math.min(elapsed / this.duration, 1);this.currentPosition = this.bezier(t, ...this.points);this.bsrNode.position(this.currentPosition.x, this.currentPosition.y); // Update node positionif (t < 1) {requestAnimationFrame(this.animate);}},

 

2、创建贝塞尔曲线组件
  1. src/components 目录下创建一个名为 BezierCurve.vue 的文件:
<template><div><canvas ref="canvas" width="500" height="500"></canvas><div><label for="p0">P0: </label><input id="p0x" v-model.number="points.p0.x" type="number"><input id="p0y" v-model.number="points.p0.y" type="number"></div><div><label for="p1">P1: </label><input id="p1x" v-model.number="points.p1.x" type="number"><input id="p1y" v-model.number="points.p1.y" type="number"></div><div><label for="p2">P2: </label><input id="p2x" v-model.number="points.p2.x" type="number"><input id="p2y" v-model.number="points.p2.y" type="number"></div><div><label for="p3">P3: </label><input id="p3x" v-model.number="points.p3.x" type="number"><input id="p3y" v-model.number="points.p3.y" type="number"></div></div>
</template><script>
export default {data() {return {points: {p0: { x: 50, y: 450 },p1: { x: 150, y: 50 },p2: { x: 350, y: 50 },p3: { x: 450, y: 450 }}};},methods: {drawCurve() {const canvas = this.$refs.canvas;const ctx = canvas.getContext("2d");const { p0, p1, p2, p3 } = this.points;ctx.clearRect(0, 0, canvas.width, canvas.height);// Draw control pointsctx.fillStyle = "red";[p0, p1, p2, p3].forEach(p => {ctx.beginPath();ctx.arc(p.x, p.y, 5, 0, 2 * Math.PI);ctx.fill();});// Draw control linesctx.strokeStyle = "gray";ctx.beginPath();ctx.moveTo(p0.x, p0.y);ctx.lineTo(p1.x, p1.y);ctx.lineTo(p2.x, p2.y);ctx.lineTo(p3.x, p3.y);ctx.stroke();// Draw Bezier curvectx.strokeStyle = "blue";ctx.beginPath();ctx.moveTo(p0.x, p0.y);for (let t = 0; t <= 1; t += 0.01) {const x =(1 - t) ** 3 * p0.x +3 * (1 - t) ** 2 * t * p1.x +3 * (1 - t) * t ** 2 * p2.x +t ** 3 * p3.x;const y =(1 - t) ** 3 * p0.y +3 * (1 - t) ** 2 * t * p1.y +3 * (1 - t) * t ** 2 * p2.y +t ** 3 * p3.y;ctx.lineTo(x, y);}ctx.stroke();}},watch: {points: {handler: 'drawCurve',deep: true}},mounted() {this.drawCurve();}
};
</script><style scoped>
canvas {border: 1px solid black;
}
input {width: 50px;margin: 5px;
}
</style>
主应用程序

接下来,我们需要将这个组件添加到主应用程序中。

  1. src/App.vue 中,使用 BezierCurve 组件:
    <template><div id="app"><BezierCurve /></div>
    </template><script>
    import BezierCurve from './components/BezierCurve.vue';export default {name: 'App',components: {BezierCurve}
    };
    </script><style>
    #app {font-family: Avenir, Helvetica, Arial, sans-serif;text-align: center;color: #2c3e50;margin-top: 60px;
    }
    </style>
    
    运行应用

    现在,你可以在浏览器中打开 http://localhost:8080 查看你的贝塞尔曲线应用。你将看到一个绘制贝塞尔曲线的画布,以及用于控制贝塞尔曲线控制点的输入框。你可以通过输入框调整控制点的位置,实时更新贝塞尔曲线的形状。

  1. 模板部分(<template>

    • 画布(<canvas>)用于绘制贝塞尔曲线。
    • 输入框(<input>)用于动态调整控制点的位置。
  2. 数据部分(data()

    • points 对象存储了贝塞尔曲线的四个控制点的坐标。
  3. 方法部分(methods

    • drawCurve() 方法用于绘制贝塞尔曲线及其控制点和控制线。
  4. 观察者部分(watch

    • points 对象发生变化时,drawCurve 方法会自动调用,重新绘制贝塞尔曲线。
  5. 生命周期钩子(mounted

    • 在组件挂载后,立即调用 drawCurve 方法绘制初始的贝塞尔曲线。

 

✨ 结语

        贝塞尔曲线是计算机图形学中的关键技术,广泛应用于矢量图形设计、字体设计、动画制作和图像处理等领域。通过理解贝塞尔曲线的数学原理和应用场景,可以更好地利用这一强大的工具来创建精美的图形和动画。

        希望这篇博客能帮助你更好地理解和应用贝塞尔曲线。如果你有任何问题或建议,欢迎在下方留言讨论!

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

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

相关文章

Linux 查找命令

目录 1. 查看二进制文件 which 2. 查看指定文件 find ​2.1 文件名查找 2.2 文件大小查找 前面学习过的 Linux 命令&#xff0c;其实质是一个个的二进制可执行程序&#xff0c;与 Windows 系统中的 .exe 文件是一个意思。 1. 查看二进制文件 which 语法&#xff1a; w…

Origin制作线性拟合回归图

选中数据&#xff0c;点下方散点图 调整散点颜色 在分析中打开线性拟合回归 添加文本 显示上轴

【NPU 系列专栏 1.1 -- NPU TOPS 算力的计算方式】

请阅读【嵌入式及芯片开发学必备专栏】 文章目录 NPU 算力MAC 阵列简介MAC 阵列特点 MAC 阵列的结构MAC 阵列架构示例 MAC 阵列计算举例示例计算 TOPS 计算方法 NPU 算力 OpenCV 算法会消耗很大一部分自动驾驶芯片的算力&#xff0c;在车上堆摄像头的同时也需要堆TOPS&#xf…

卷积神经网络(二)-AlexNet

前言&#xff1a; AlexNet是2012年ImageNet竞赛冠军&#xff08;以领先第二名10%的准确率夺得冠军&#xff09;获得者Hinton和他的学生Alex Krizhevsky设计的,在ILSVRC-2010测试集上取得了top-1错误率37.5%,top-5错误率17.0%&#xff08;优于第二名的16.4%&#xff09;,明显优…

【微信小程序实战教程】之微信小程序 WXS 语法详解

WXS语法 WXS是微信小程序的一套脚本语言&#xff0c;其特性包括&#xff1a;模块、变量、注释、运算符、语句、数据类型、基础类库等。在本章我们主要介绍WXS语言的特性与基本用法&#xff0c;以及 WXS 与 JavaScript 之间的不同之处。 1 WXS介绍 在微信小程序中&#xff0c…

LeetCode 637, 67, 399

文章目录 637. 二叉树的层平均值题目链接标签思路代码 67. 二进制求和题目链接标签思路代码 399. 除法求值题目链接标签思路导入value 属性find() 方法union() 方法query() 方法 代码 637. 二叉树的层平均值 题目链接 637. 二叉树的层平均值 标签 树 深度优先搜索 广度优先…

四、GD32 MCU 常见外设介绍(9)9.FWDG 模块介绍

9.1.FWDG 简介 本章我们主要分析独立看门狗&#xff08;FWDG&#xff09;的功能框图和它的应用。独立看门狗用通俗一点的话来解释就是一个12位的递减计数器&#xff0c;当计数器的值从某个值一直减到0的时候&#xff0c;系统就会产生一个复位信号&#xff0c;即FWDGTRSTF。如果…

基于深度学习算法,支持再学习功能,不断提升系统精准度的智慧地产开源了。

智慧地产视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。通过计算机视觉和…

Java基础巩固——JDK 8、9新增接口的特性(接口中定义非抽象方法、静态方法和私有方法)

#Java学了这么久&#xff0c;项目也做了&#xff1f;基础知识还不巩固&#xff1f;快来关注我的这篇系列博客——Java基础复习巩固吧# 目录 引言 一、JDK8新特性&#xff1a;允许在接口中定义非抽象方法和静态方法。 注意事项 二、JDK9新特性&#xff1a;允许在接口中定义p…

ScriptableObject使用

资料 Scripting/Create modular game architecture in Unity with ScriptableObjects 脚本文档 基础 SO是一个Unity对象&#xff0c;继承UnityEngine.Objec&#xff0c; SO最大的特点是实例文件可共享&#xff0c;有点类似静态数据&#xff0c;同一个实例文件可被多个对象引…

matlab实验:实验六MATLAB 数值计算与符号运算

题目1&#xff1a;&#xff08;线性方程组数值求解&#xff09; 1&#xff0e; 用不同的方法求解下面方程&#xff1a;&#xff08;方程原式参考 P369 实验 10&#xff0c;第 1 题&#xff09; 第 1 种&#xff0c;左除和求逆函数(inv) 第 2 种 &#xff0c; 用 符 号 运 算 的…

JAVA基础知识4(static、继承)

JAVA基础知识4 static静态成员变量静态成员方法解释注意点 继承父类&#xff08;基类或超类&#xff09;子类&#xff08;派生类&#xff09;使用继承的示例解释运行结果 成员变量的访问特点成员方法的访问特点构造方法的访问特点 Java项目&#xff0c;包和类之间的联系包的概念…

vue elementui 在table里使用el-switch

<el-table-columnprop"operationStatus"label"状态"header-align"center"align"center"><template slot-scope"scope"><el-switch active-value"ENABLE" inactive-value"DISABLE" v-mod…

【C语言】两个数组比较详解

目录 C语言中两个数组比较详解1. 逐元素比较1.1 示例代码1.2 输出结果1.3 分析 2. 内置函数的使用2.1 示例代码2.2 输出结果2.3 分析 3. 在嵌入式系统中的应用3.1 示例代码3.2 输出结果3.3 分析 4. 拓展技巧4.1 使用指针优化比较4.2 输出结果4.3 分析 5. 表格总结6. 结论7. 结束…

Python写UI自动化--playwright(通过UI文本匹配实现定位)

本篇简单拓展一下元素定位技巧&#xff0c;通过UI界面的文本去实现定位 目录 匹配XPath 匹配文本元素 .count()统计匹配数量 处理匹配文本返回多个元素 1、使用.nth(index)选择特定元素: 2、获取所有匹配的元素并遍历: 3、错误处理: 匹配XPath 比如我们要定位到下图的…

C++笔试强训8

文章目录 一、选择题1-5题6-10题 二、编程题题目一题目二 一、选择题 1-5题 根据下面的定义故选A。 函数重载:在相同作用域中&#xff0c;函数名字相同&#xff0c;参数列表不同的一系列函数称为函数重载参数列表不同具体的体现:参数个数不同参数类型不同类型的次序不同注意:…

单元测试--Junit

Junit是Java的单元测试框架提供了一些注解方便我们进行单元测试 1. 常用注解 常用注解&#xff1a; TestBeforeAll&#xff0c;AfterAllBeforeEach&#xff0c;AfterEach 使用这些注解需要先引入依赖&#xff1a; <dependency><groupId>org.junit.jupiter<…

6 C 语言指针的奥秘:理论与实践详解

目录 1 变量访问机制 1.1 内存地址 1.2 变量的直接访问 1.3 变量的间接访问 2 指针变量及其内存大小 2.1 指针与指针变量 2.2 指针变量的定义格式 2.3 指针变量的内存大小 3 取地址操作符与取值操作符 3.1 取地址操作符 & 3.2 取值操作符 * 3.3 解引用与数据类…

【数据结构】顺序表(杨辉三角、简单的洗牌算法)

&#x1f387;&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳&#xff0c;欢迎大佬指点&#xff01; 欢迎志同道合的朋友一起加油喔 &#x1f4aa;&#x1f4aa;&#x1f4aa; 谢谢你这么帅…