Bezier 曲线 2D

news2024/12/22 6:33:59

Bezier 曲线于 1962 年由法国雪铁龙汽车公司的工程师 Bezier 所发表,主要应用于汽车的外形设计。虽然 Bezier 曲线早在 1959 年便由法国雷诺汽车公司的 De Casteljau 运用递推算法开发成功,但是 Bezier 却给出了曲线的详细的曲线计算公式。所以,命名为 Bezier 曲线.
Bezier 曲线由控制多边形唯一定义。
控制多边形的第一个顶点和最后一个顶点位于曲线上,多边形的第一条边和最后一条边表示了曲线在起点和终点的切矢量方向,其顶点则用于定义曲线的导数,阶次和形状。曲线的形状趋近于控制多边形并位于多边形所构成的土包内,改变控制多边形的顶点位置就会改变曲线的形状。
Bezier 曲线的直观交互性使得对设计对象的逼近达到了直接的集合化程度,使得起来非常方便。

Bezier 曲线的定义

给定 n + 1 n+1 n+1 个控制点 P i ( i = 0 , 1 , 2 , ⋯ n ) P_i (i=0, 1, 2, \cdots n) Pi(i=0,1,2,n),则 n n n次Bezier 曲线的定义为
P ( t ) = ∑ i = 0 n P i B i , n ( t ) , t ∈ [ 0 , 1 ] P(t) = \sum_{i=0}{n}P_i B_{i, n}(t), t\in[0, 1] P(t)=i=0nPiBi,n(t),t[0,1]
P i ( i = 0 , 1 , 2 , ⋯   , n ) P_i(i=0, 1, 2, \cdots, n) Pi(i=0,1,2,,n) 是控制多边形的 n + 1 n+1 n+1 个控制点. B i , n ( t ) B_{i, n}(t) Bi,n(t)是 Bernstein 基函数,其表达式为

B i , n ( t ) = n ! i ! ( n − i ) ! t i ( 1 − t ) n − i = C n i t i ( 1 − t ) n − i , i = 0 , 1 , 2 , ⋯ n \begin{equation} B_{i, n}(t) = \frac{n!}{i!(n-i)!}t^{i}(1-t)^{n-i} = C_{n}^{i}t^{i}(1-t)^{n-i}, \quad i=0, 1, 2, \cdots n \end{equation} Bi,n(t)=i!(ni)!n!ti(1t)ni=Cniti(1t)ni,i=0,1,2,n

Bezier 函数是控制点关于 Bernstein 基函数的加权和,Bezier 曲线的次数为 n , 需要 n+1 个顶点来定义。
在工程项目中,最常见的是三次Bezier 曲线,其次数是二次Bezier 曲线,高次Bezier 曲线一般很少用

一次 Bezier 曲线, 当 n=1 时,Bezier 曲线的控制多边形有两个控制点 P 0 P_0 P0 P 1 P_1 P1, Bezier 曲线是一次多项式,称为一次 Bezier 曲线,

P ( t ) = ∑ i = 0 1 P i B i , 1 ( t ) = ( 1 − t ) P 0 + t P 1 P(t) = \sum_{i=0}^{1}P_i B_{i, 1}(t) = (1-t)P_0 + tP_{1} P(t)=i=01PiBi,1(t)=(1t)P0+tP1

二次 Bezier 曲线,当 n=2 时,Bezier 曲线的控制多边形有 3 个控制点, KaTeX parse error: Expected group after '_' at position 2: P_̲$ 、 P 1 P_1 P1 P 2 P_2 P2, Bezier 曲线是二次多项式,称为二次 Bezier 曲线,

P ( t ) = ∑ i = 0 2 P i B i , 2 ( t ) = ( 1 − t ) 2 P 0 + 2 t ( 1 − t ) P 1 + t 2 P 2 P(t) = \sum_{i=0}^{2}P_i B_{i, 2}(t) = (1-t)^2P_0 + 2t(1-t)P_{1} + t^2P_2 P(t)=i=02PiBi,2(t)=(1t)2P0+2t(1t)P1+t2P2
三次 Bezier 曲线,当 n=3 时,Bezier 曲线控制多边形有 4 个控制点, P 0 P_0 P0 P 1 P_1 P1 P 2 P_2 P2 P 3 P_3 P3, Bezier 曲线是三次多项式,称为三次 Bezier 曲线

P ( t ) = ∑ i = 0 3 P i B i , 3 ( t ) = ( 1 − t ) 3 P 0 + 3 t ( 1 − t ) 2 P 1 + 3 t 2 ( 1 − t ) P 2 + t 3 P 3 = ( − t 3 + 3 t 2 − 3 t + 1 ) P 0 + ( 3 t 3 − 6 t 2 + 3 t ) P 1 + ( − 3 t 3 + 3 t 2 ) P 2 + t 3 P 3 P(t) = \sum_{i=0}^{3}P_i B_{i, 3}(t) = (1-t)^3 P_0 + 3t(1-t)^2P_{1} + 3t^2(1-t)P_2 + t^3P_3 = (-t^3 + 3t^2 -3t+1)P_0 + (3t^3 -6t^2 + 3t)P_1 + (-3t^3+3t^2)P_2 + t^3P_3 P(t)=i=03PiBi,3(t)=(1t)3P0+3t(1t)2P1+3t2(1t)P2+t3P3=(t3+3t23t+1)P0+3t36t2+3tP1+(3t3+3t2)P2+t3P3

写成矩阵的形式为

P ( t ) = [ t 3 t 2 t 1 ] [ − 1 3 − 3 1 3 − 6 3 0 − 3 3 0 0 1 0 0 0 ] [ P 0 P 1 P 2 P 3 ] P(t) = \begin{bmatrix} t^3 & t^2 & t & 1 \end{bmatrix} \begin{bmatrix} -1 & 3 &-3 & 1\\ 3 & -6 &3 & 0\\ -3 & 3 &0 & 0\\ 1 & 0 & 0 & 0\\ \end{bmatrix} \begin{bmatrix} P_0 \\ P_1 \\ P_2 \\ P_3 \\ \end{bmatrix} P(t)=[t3t2t1] 1331363033001000 P0P1P2P3

B 0 , 3 ( t ) = ( 1 − t ) 3 B 1 , 3 ( t ) = 3 t ( 1 − t ) 2 B 2 , 3 ( t ) = 3 t 2 ( 1 − t ) B 3 , 3 ( t ) = t 3 B_{0, 3}(t) = (1-t)^3 \\ B_{1, 3}(t) = 3t(1-t)^2 \\ B_{2, 3}(t) = 3t^2(1-t) \\ B_{3, 3}(t) = t^3 B0,3(t)=(1t)3B1,3(t)=3t(1t)2B2,3(t)=3t2(1t)B3,3(t)=t3

下面给出 QT + OPENGL 的二次的代码

#include <QtWidgets>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>

class BezierCurveWidget : public QOpenGLWidget, protected QOpenGLFunctions {
public:
    BezierCurveWidget(QWidget* parent = nullptr)
        : QOpenGLWidget(parent) {}

protected:
    void initializeGL() override {
        initializeOpenGLFunctions();
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    }

    void resizeGL(int w, int h) override {
        glViewport(0, 0, w, h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, w, h, 0, -1, 1);
        glMatrixMode(GL_MODELVIEW);
    }

    void paintGL() override {
        glClear(GL_COLOR_BUFFER_BIT);

        // 控制点坐标
        QPoint p0(100, 300);
        QPoint p1(300, 100);
        QPoint p2(500, 300);

        // 设置线的颜色
        glColor3f(0.0f, 0.0f, 1.0f); // Blue color for lines

        // 绘制Bezier曲线
        glBegin(GL_LINE_STRIP);
        for (float t = 0.0f; t <= 1.0f; t += 0.01f) {
            QPoint p = calculateBezierPoint(t, p0, p1, p2);
            glVertex2i(p.x(), p.y());
        }
        glEnd();

        // 绘制控制点
        glPointSize(5.0f);
        glColor3f(1.0f, 0.0f, 0.0f);
        glBegin(GL_POINTS);
        glVertex2i(p0.x(), p0.y());
        glVertex2i(p1.x(), p1.y());
        glVertex2i(p2.x(), p2.y());
        glEnd();

        // 绘制连接线
        glBegin(GL_LINES);
        glVertex2i(p0.x(), p0.y());
        glVertex2i(p1.x(), p1.y());
        glVertex2i(p1.x(), p1.y());
        glVertex2i(p2.x(), p2.y());
        glEnd();
    }

    QPoint calculateBezierPoint(float t, const QPoint& p0, const QPoint& p1, const QPoint& p2) {
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;

        float x = uu * p0.x() + 2 * u * t * p1.x() + tt * p2.x();
        float y = uu * p0.y() + 2 * u * t * p1.y() + tt * p2.y();

        return QPoint(x, y);
    }
};

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);

    QMainWindow window;
    BezierCurveWidget* bezierWidget = new BezierCurveWidget(&window);

    window.setCentralWidget(bezierWidget);
    window.resize(600, 400);
    window.show();

    return a.exec();
}

在这里插入图片描述

这里只需要替换一次和三次的计算部分即可。

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

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

相关文章

游戏、算法竞赛与退役(流水账版)

写在前面 不出意外的话&#xff0c;这东西本该咕到翻年之后再发的&#xff0c;但好像催稿催的有点厉害&#xff0c;于是就找个机会把他写了&#xff08;笑&#xff09; 最初是只想写个算法竞赛退役记的&#xff0c;后面发觉写起来就有点收不住&#xff0c;算法竞赛牵扯到太多…

linux网络管理_配置网络参数

11.2 配置网络参数 ls /etc/sysconfig/network-scripts/ 11.2.1 配置IP 配置网卡参数 # 可考虑先备份 # cp /etc/sysconfig/network-scripts/ifcfg-ens33 . # 复制到当前目录 ​ vim /etc/sysconfig/network-scripts/ifcfg-ens33 ifcfg-ens33文件中的内容 TYPEEthernet PROX…

MATLAB 平面拟合并可视化(34)

MATLAB 平面拟合并可视化(34) 一、效果二、代码一、效果 二、代码 % 生成三维点数据 x = rand(100, 1); y = rand(100, 1

LLaMA系列模型

1.LLama 1.1 简介 Open and Efficient Foundation Language Models (Open但没完全Open的LLaMA) 2023年2月&#xff0c;Meta&#xff08;原Facebook&#xff09;推出了LLaMA大模型&#xff0c;使用了1.4T token进行训练&#xff0c;虽然最大模型只有65B&#xff0c;但在相关评…

Python实战:信用卡客户历史数据挖掘与分析

Python实战&#xff1a;信用卡客户历史数据挖掘与分析 引言数据获取与预处理描述性分析模型建立与评估结果分析Web应用展示&#xff08;可选&#xff09; 引言 信用卡客户历史数据分析是金融领域中的重要课题之一。通过对公开数据集的挖掘&#xff0c;本文将利用Python编程语言…

51单片机LED与无源蜂鸣器模块

IO口的使用1 本文主要对51单片机的LED灯的使用以及蜂鸣器的使用进行介绍&#xff0c;其中包括一些实例分析&#xff1a; 1.实现发光二极管的从左到右的流水点亮 2.左右来回循环的流水灯 3.蜂鸣器以一定频率响 文章目录 IO口的使用1一、LED灯举个栗子一举个栗子二 二、蜂鸣器2.1…

华为OD机试 - 连续出牌数量 - 深度优先搜索dfs算法(Java 2023 B卷 200分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明 四、解题思路1、题目解读2、具体步骤 五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08…

Linux--学习记录(3)

G重要编译参数 -g&#xff08;GDB调试&#xff09; -g选项告诉gcc产生能被GNU调试器GDB使用的调试信息&#xff0c;以调试程序编译带调试信息的可执行文件g -g hello.c -o hello编译过程&#xff1a; -E&#xff08;预处理&#xff09; g -E hello.c -o hello.i-S&#xff08;编…

基于springboot+vue 的智能物流管理系统

简介 基于springbootvue 的智能物流管理系统 适用于 设计&#xff0c;课程设计参考与学习用途。仅供学习参考。 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料 **项目编号&#xff1a;springboot074 ** **…

C++刷题 -- KMP算法

C刷题 – KMP算法 文章目录 C刷题 -- KMP算法1.算法讲解2.算法实现 https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/ 1.算法讲解 KMP算法是一种字符串匹配算法&#xff0c;当出现字符串不匹配时&#xff0c;可以记录一部分之…

数据可视化---箱线图

类别内容导航机器学习机器学习算法应用场景与评价指标机器学习算法—分类机器学习算法—回归机器学习算法—聚类机器学习算法—异常检测机器学习算法—时间序列数据可视化数据可视化—折线图数据可视化—箱线图数据可视化—柱状图数据可视化—饼图、环形图、雷达图统计学检验箱…

【MySQL】Sql优化之索引的使用方式(145)

索引分类 1.单值索引 单的意思就是单列的值&#xff0c;比如说有一张数据库表&#xff0c;表内有三个字段&#xff0c;分别是 id name numberNo&#xff0c;我给name 这个字段加一个索引&#xff0c;这就是单值索引&#xff0c;因为只有name 这一列是索引&#xff1b; 一个表…

k8s-ingress特性 9

TLS加密 创建证书 测试访问 auth认证 创建认证文件 rewrite重定向 进入域名时&#xff0c;会自动重定向到hostname.html 示例&#xff1a; 测试 版本的升级迭代&#xff0c;之前利用控制器进行滚动更新&#xff0c;在升级过程中无法做到快速回滚 更加平滑的升级&#xff1…

猫头虎带您探索StringUtils3之StringUtils.isEmpty()和StringUtils.isBlank()的区别 ‍

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

低代码汹涌澎湃,真的是风口?

“中国的下一个风口是什么&#xff1f;低代码&#xff1f;你赞同吗&#xff1f;” 可以肯定的是&#xff0c;企业想站上未来产业的风口&#xff0c;”数字化“是必经之路。而低代码是企业向制高点突进的手段。产业的风口&#xff0c;就是产业发展的趋势&#xff0c;只有尽力站上…

SQL面试题挑战01:打折日期交叉问题

目录 问题&#xff1a;SQL解答&#xff1a;第一种方式&#xff1a;第二种方式&#xff1a; 问题&#xff1a; 如下为某平台的商品促销数据&#xff0c;字段含义分别为品牌名称、打折开始日期、打折结束日期&#xff0c;现在要计算每个品牌的打折销售天数&#xff08;注意其中的…

JNI 注册

一、 JNI 静态注册 ① 在 Android 的 Java 层定义方法 : 在 MainActivity 类中定义 如下 Native 方法 ; public native String stringFromJNI();② Native 方法实现 : 下面是一个 Native 方法实现的示例 ; extern "C" JNIEXPORT jstring JNICALL Java_kim_hsl_jni_…

VuePress安装及使用——使用 Markdown 创建你自己的博客网站和电子书

目录 前言一、依赖环境二、vuepress 安装和使用1.初始化2.将 VuePress 安装为本地依赖3. package.json 中添加脚本4. 新建 docs 文件夹5.启动6. 效果 三、进阶使用1.新增配置文件2.安装搜索插件3.config.js 中增加配置4.效果展示5.注意 四、使用主题1.安装2. 目录结构说明&…

fastjson反序列化 CVE-2017-18349

fastjson fastjson 是阿里巴巴开发的 java语言编写的高性能 JSON 库,用于将数据在 Json 和 Java Object之间相互转换。它没有用java的序列化机制,而是自定义了一套序列化机制。 提供两个主要接口&#xff1a; JSON.toJSONString 和 JSON.parseObject/JSON.parse 分别实现序列化…

双指针——找到字符串中的所有字母异位词

https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/?envTypestudy-plan-v2&envIdtop-100-liked 双指针&#xff0c;每次都统计出来p长度的滑动窗口里的数字,拿Arrays.equals进行对比,然后滑动一小格&#xff0c;减1加1继续比对即可。 class Solut…