【轨迹规划】贝塞尔曲线理解及C++实现n次贝塞尔曲线

文章介绍了贝塞尔曲线的基本概念,包括其数学原理、控制点的重要性以及在图形学中的应用。通过C++代码展示了如何实现n次贝塞尔曲线,并提供了一个数据输出到文件的例子,然后使用Matlab读取数据并作图。文章还提供了不同阶数贝塞尔曲线的控制点示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、贝塞尔曲线

贝塞尔曲线(Bezier Curve)是一种基于多项式的曲线表示方法,由法国工程师Pierre Bézier在20世纪50年代提出。它是图形学中广泛应用的一种曲线类型,用于在二维或三维空间中描述平滑曲线和曲面。

原理:基于控制点的概念,通过控制点来定义曲线的形状,控制点的坐标决定了曲线的起始点、终止点以及曲线在这些点和它们之间的形状。

贝塞尔曲线可以由一组控制点和一组权重函数构成,其中每个控制点都有一个对应的权重函数,这个权重函数决定了控制点对曲线的影响程度。

一次直线:

Px=P0​+(P1​-P0)t = (1−t)P0​+tP1

二次抛物线:

Pi​=(1−t)P0​+tP1  ;  ​Pj​=(1−t)P1​+tP2​;         Px​=(1−t)Pi​+tPj​

三次贝塞尔:

 ...更高阶

 n阶贝塞尔公式:

6个控制点,五次贝塞尔曲线

 性质:曲线的端点和曲线相切,曲线不一定通过控制点,但是肯定通过端点。

把控制点作为节点,可以拼接多段曲线,且拼接处是光滑的。

感谢使用贝塞尔曲线绘制多点连接曲线 - 简书提供的gif图片,一图胜千言!

感谢 博主 详解样条曲线(上)天真的和感伤的想象家的博客-CSDN博客细节好文!

下面用C++实现n次贝塞尔曲线,贝塞尔曲线控制点的数量(即vector<point>的size)决定贝塞尔曲线的阶数(n=size-1);

C++实现n次贝塞尔曲线

#include <vector>
#include <cmath>
#include <iostream>
#include <fstream>

using namespace std;
struct Point {
    float x, y, z;
    Point(float x = 0, float y = 0 ,float z=0):x(x),y(y),z(z){}
};
// 计算组合数
int binomial(int n, int i) {
    int res = 1;
    for (int j = 1; j <= i; ++j) {
        res *= (n - j + 1) / (double)j; //(double)十分关键,不然j=i=n时,j为分数=0;
    }
    return res;
}
// 计算n次贝塞尔曲线上的点
Point bezier_curve(const vector<Point>& points, float t) {
    int n = points.size() - 1;
    Point res;
    for (int i = 0; i <= n; ++i) {
        cout << "p:" << points[i].x << "," << points[i].y << endl;
        float b =  binomial(n, i)* pow(t, i) * pow(1 - t, n - i);
        cout << "bino=" << binomial(n, i) << endl;
        res.x = res.x + points[i].x * b;
        res.y = res.y + points[i].y * b;
        res.z = res.z + points[i].z * b;
    }
    return res;
}
int main() {
    cout << "OK!" << endl;      
    ofstream fout("D:/data.txt"); // 打开或创建名为 data.txt 的文件
    if (!fout) { // 检查文件是否打开成功
        cerr << "File open failed!" << endl;
        return 1;
    }
    vector<Point> points = {{10,10,0}, {20, 80,70},{40,120,32}}; // 贝塞尔曲线控制点,给定控制点的数量决定贝塞尔曲线的阶数
    
    cout << "size:" << points.size() << endl;
    const float step = 0.02; // 步长
    for (float t = 0; t <= 1; t += step) {
        Point p = bezier_curve(points, t);
        fout << p.x << ", " << p.y <<", " <<p.z<< endl;
    }
    fout.close(); // 关闭文件
    return 0;
}

把导出的数据文件,使用Matlab画图


% 从文件中导入坐标点,dlmread函数用于从文件中读取数据,','表示分隔符,0表示读取文件的起始行数,0表示读取文件的起始列数。

points = dlmread('D:\data.txt', ',', 0, 0);
scatter3(points(:, 1), points(:, 2), points(:, 3), 'filled');

        二阶贝塞尔 points = {{10,10,0}, {20, 80,70},{40,120,32}}

 三阶贝塞尔 points = {{10,10,0}, {20, 80,70},{40,120,32},{70,0,90}}

### 使用贝塞尔曲线平滑三维路径的算法实现 贝塞尔曲线不仅适用于二维空间,在三维空间中同样能够用于生成和优化路径。通过扩展到三维坐标系,可以利用相同的数学原理来构建平滑的三维路径。 #### 数学基础 贝塞尔曲线的核心在于其参数化方程。对于三阶贝塞尔曲线而言,给定四个点 \(P_0, P_1, P_2, P_3\),其中 \(P_0\) 和 \(P_3\) 是端点,\(P_1\) 和 \(P_2\) 是控制点,曲线上的任意一点可通过以下公式计算: \[ B(t) = (1-t)^3P_0 + 3(1-t)^2tP_1 + 3(1-t)t^2P_2 + t^3P_3 \quad \text{for } t \in [0, 1] \] 当扩展至三维时,上述公式中的每一个点都由三个分量表示:\(P_i(x,y,z)\)[^1]。因此,最终的三维贝塞尔曲线可分解为分别沿 \(x\)、\(y\)、\(z\) 方向的独立多项式函数。 #### Python 实现 以下是基于三阶贝塞尔曲线的一个简单实现,展示如何在三维空间中创建并绘制一条平滑路径。 ```python import numpy as np from mpl_toolkits.mplot3d import Axes3D import matplotlib.pyplot as plt def bezier_curve(P0, P1, P2, P3, num_points=100): """ 计算三阶贝塞尔曲线上的点。 参数: P0, P1, P2, P3: 控制点,形式为[x, y, z] num_points: 曲线上的采样点数 返回: points: 曲线上所有的点组成的数组 """ t_values = np.linspace(0, 1, num_points) points = [] for t in t_values: point_x = (1 - t)**3 * P0[0] + 3*(1 - t)**2*t*P1[0] + 3*(1 - t)*t**2*P2[0] + t**3*P3[0] point_y = (1 - t)**3 * P0[1] + 3*(1 - t)**2*t*P1[1] + 3*(1 - t)*t**2*P2[1] + t**3*P3[1] point_z = (1 - t)**3 * P0[2] + 3*(1 - t)**2*t*P1[2] + 3*(1 - t)*t**2*P2[2] + t**3*P3[2] points.append([point_x, point_y, point_z]) return np.array(points) # 定义控制点 P0 = [0, 0, 0] P1 = [1, 2, 1] P2 = [2, 1, 3] P3 = [3, 3, 2] # 获取贝塞尔曲线上的一系列点 curve_points = bezier_curve(P0, P1, P2, P3) # 绘图 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot(curve_points[:, 0], curve_points[:, 1], curve_points[:, 2], label="Bezier Curve", color="blue") ax.scatter(*zip(P0, P1, P2, P3), color=["red"], s=100, label="Control Points") # 显示控制点 ax.legend() plt.show() ``` 此代码片段定义了一个 `bezier_curve` 函数,它接受四组三维控制点作为输入,并返回一系列位于贝塞尔曲线上的点。这些点随后被绘制成三维图像[^2]。 #### 关键技术细节 - **控制点的选择**: 对于实际应用来说,合理选取中间控制点 (\(P_1\) 和 \(P_2\)) 至关重要。它们决定了曲线的整体形状以及平滑程度。 - **数值稳定性**: 当处理大量数据或者复杂场景时,应考虑浮点精度误差可能带来的影响。 #### 结论 借助贝塞尔曲线理论及其对应的编程实践方法,可以在三维环境中轻松设计出既美观又精确的轨迹规划方案。这种方法广泛应用于动画制作、机器人运动规划等领域之中[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值