【chatgpt代码系列】三阶贝塞尔曲线等距点算法

该程序使用C++编写,通过递归算法计算三阶贝塞尔曲线上等间距的点。首先定义控制点,然后通过递归函数`recursiveDivide`以二分法计算参数t的中点并生成等间距点。程序涉及贝塞尔曲线的数学原理,包括计算曲线长度和使用导数确定点坐标。
摘要由CSDN通过智能技术生成

0x01 代码

#include <iostream>
#include <vector>
using namespace std;

// 定义二维坐标点结构体
struct Point {
    double x;
    double y;
};

// 计算三阶贝塞尔曲线上某个参数t对应的点坐标
Point getBezierPoint(vector<Point>& controlPoints, double t) {
    double x = pow((1 - t), 3) * controlPoints[0].x + 
               3 * t * pow((1 - t), 2) * controlPoints[1].x +
               3 * pow(t, 2) * (1 - t) * controlPoints[2].x +
               pow(t, 3) * controlPoints[3].x;
    double y = pow((1 - t), 3) * controlPoints[0].y +
               3 * t * pow((1 - t), 2) * controlPoints[1].y +
               3 * pow(t, 2) * (1 - t) * controlPoints[2].y +
               pow(t, 3) * controlPoints[3].y;
    Point p = {x, y};
    return p;
}

// 递归计算三阶贝塞尔曲线上的等间距点
void recursiveDivide(vector<Point>& controlPoints, double t0, double t1, 
                     vector<Point>& pointList, int& idx) {
    // 当参数范围小于1e-6时停止递归
    if ((t1 - t0) < 1e-6) {
        return;
    }
    // 计算参数区间的中点
    double tMid = (t0 + t1) / 2.0;
    // 计算中点对应的贝塞尔曲线上的坐标
    Point pMid = getBezierPoint(controlPoints, tMid);
    // 将中点添加到结果列表中
    pointList[idx++] = pMid;
    // 递归计算左右两段曲线上的等间距点
    recursiveDivide(controlPoints, t0, tMid, pointList, idx);
    recursiveDivide(controlPoints, tMid, t1, pointList, idx);
}

int main() {
    // 定义控制点
    vector<Point> controlPoints = {{10, 10}, {50, 60}, {100, 30}, {150, 150}};

    // 定义采样个数
    int N = 10;
    // 计算初始和末尾点
    vector<Point> pointList(N + 1);
    pointList[0] = controlPoints.front();
    pointList[N] = controlPoints.back();

    // 递归计算曲线上的等间距点
    int idx = 1;
    recursiveDivide(controlPoints, 0.0, 1.0, pointList, idx);

    // 输出等间距的点容器
    for (auto& p : pointList) {
        cout << "(" << p.x << ", " << p.y << ")" << endl;
    }

    return 0;
}

这是一个 C++ 的程序,用于计算三阶贝塞尔曲线上等间距的点。程序在 main 函数中运行,包含以下步骤:

  1. 定义四个控制点,并将它们存储在一个二维向量 controlPoints 中。
  2. 定义需要采样的点数 N,并将采样结果存储在一个二维向量 pointList 中。
  3. 调用递归函数 recursiveDivide 来计算贝塞尔曲线上的等间距点。该函数通过二分法的方式递归计算左右两个子区间的点,直到整个区间小于某个阈值。
  4. 输出等间距的点容器 pointList 中的各个元素。

请注意,贝塞尔曲线是一种可描述平滑曲线的数学模型,三阶贝塞尔曲线由四个控制点确定。对于任意参数 t ∈ [ 0 , 1 ] t \in [0, 1] t[0,1],三阶贝塞尔曲线上可以计算出对应的点坐标。本程序利用递归方式计算贝塞尔曲线上等间距的点坐标,主要涉及递归算法和贝塞尔曲线的基本原理。

0x02 公式

3阶贝塞尔曲线沿线长等距分割方法可以简述如下:

  1. 计算曲线长度,即对参数 t t t [ 0 , 1 ] [0,1] [0,1] 区间上积分 ( d x / d t ) 2 + ( d y / d t ) 2 \sqrt{(dx/dt)^2+(dy/dt)^2} (dx/dt)2+(dy/dt)2 ,其中 d x / d t dx/dt dx/dt d y / d t dy/dt dy/dt 分别为贝塞尔曲线在 x x x y y y 方向上的导数。
  2. 根据总采样点数 N N N,计算出采样点的间隔 s = L / ( N − 1 ) s=L/(N-1) s=L/(N1),其中 L L L 为曲线长度。
  3. 初始化采样点列表,包括起始点和终止点,并将起始点和终止点的参数值分别设为 t 0 = 0 t_0=0 t0=0 t N = 1 t_N=1 tN=1
  4. 对于 i ∈ [ 1 , N − 1 ] i \in [1,N-1] i[1,N1],计算参数值 t i t_i ti 使得从起点到第 i i i 个采样点的长度为 i × s i \times s i×s,并计算对应的点坐标。

对于3阶贝塞尔曲线,上述分割方法稍加简化后的具体计算方式如下:

  1. 计算曲线长度公式为:

L = ∫ 0 1 ( d x / d t ) 2 + ( d y / d t ) 2 d t L=\int_{0}^{1} \sqrt{(dx/dt)^2+(dy/dt)^2} dt L=01(dx/dt)2+(dy/dt)2 dt

其中 d x / d t dx/dt dx/dt d y / d t dy/dt dy/dt 的计算公式如下:

d x / d t = 3 ( 1 − t ) 2 ( x 1 − x 0 ) + 6 t ( 1 − t ) ( x 2 − x 1 ) + 3 t 2 ( x 3 − x 2 ) dx/dt=3(1-t)^2(x_1-x_0)+6t(1-t)(x_2-x_1)+3t^2(x_3-x_2) dx/dt=3(1t)2(x1x0)+6t(1t)(x2x1)+3t2(x3x2)

d y / d t = 3 ( 1 − t ) 2 ( y 1 − y 0 ) + 6 t ( 1 − t ) ( y 2 − y 1 ) + 3 t 2 ( y 3 − y 2 ) dy/dt=3(1-t)^2(y_1-y_0)+6t(1-t)(y_2-y_1)+3t^2(y_3-y_2) dy/dt=3(1t)2(y1y0)+6t(1t)(y2y1)+3t2(y3y2)

其中 ( x 0 , y 0 ) (x_0,y_0) (x0,y0) ( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( x 2 , y 2 ) (x_2,y_2) (x2,y2) ( x 3 , y 3 ) (x_3,y_3) (x3,y3) 为3阶贝塞尔曲线的4个控制点坐标。

  1. 根据采样点数 N N N,计算出采样点的间隔 s = L / ( N − 1 ) s=L/(N-1) s=L/(N1)

  2. 初始化采样点列表,包括起始点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0) 和终止点 ( x 3 , y 3 ) (x_3,y_3) (x3,y3) 并将起始点和终止点的参数值分别设为 t 0 = 0 t_0=0 t0=0 t N = 1 t_N=1 tN=1

  3. 对于 i ∈ [ 1 , N − 1 ] i \in [1,N-1] i[1,N1],通过二分法计算出满足以下条件的 t i t_i ti

∫ t 0 t i ( d x / d t ) 2 + ( d y / d t ) 2 d t = i × s \int_{t_0}^{t_i} \sqrt{(dx/dt)^2+(dy/dt)^2} dt = i \times s t0ti(dx/dt)2+(dy/dt)2 dt=i×s

其中 ( d x / d t ) 2 + ( d y / d t ) 2 \sqrt{(dx/dt)^2+(dy/dt)^2} (dx/dt)2+(dy/dt)2 的计算公式如上。然后根据 t i t_i ti 计算出曲线上对应的点坐标,即 ( x i , y i ) (x_i,y_i) (xi,yi)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值