#include
#include
using namespace std;// 定义二维坐标点结构体
struct Point {double x;double y;
};// 计算三阶贝塞尔曲线上某个参数t对应的点坐标
Point getBezierPoint(vector& 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& controlPoints, double t0, double t1, vector& 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 controlPoints = {{10, 10}, {50, 60}, {100, 30}, {150, 150}};// 定义采样个数int N = 10;// 计算初始和末尾点vector 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
函数中运行,包含以下步骤:
controlPoints
中。N
,并将采样结果存储在一个二维向量 pointList
中。recursiveDivide
来计算贝塞尔曲线上的等间距点。该函数通过二分法的方式递归计算左右两个子区间的点,直到整个区间小于某个阈值。pointList
中的各个元素。请注意,贝塞尔曲线是一种可描述平滑曲线的数学模型,三阶贝塞尔曲线由四个控制点确定。对于任意参数 t∈[0,1]t \in [0, 1]t∈[0,1],三阶贝塞尔曲线上可以计算出对应的点坐标。本程序利用递归方式计算贝塞尔曲线上等间距的点坐标,主要涉及递归算法和贝塞尔曲线的基本原理。
3阶贝塞尔曲线沿线长等距分割方法可以简述如下:
对于3阶贝塞尔曲线,上述分割方法稍加简化后的具体计算方式如下:
L=∫01(dx/dt)2+(dy/dt)2dtL=\int_{0}^{1} \sqrt{(dx/dt)^2+(dy/dt)^2} dt L=∫01(dx/dt)2+(dy/dt)2dt
其中 dx/dtdx/dtdx/dt 和 dy/dtdy/dtdy/dt 的计算公式如下:
dx/dt=3(1−t)2(x1−x0)+6t(1−t)(x2−x1)+3t2(x3−x2)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(1−t)2(x1−x0)+6t(1−t)(x2−x1)+3t2(x3−x2)
dy/dt=3(1−t)2(y1−y0)+6t(1−t)(y2−y1)+3t2(y3−y2)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(1−t)2(y1−y0)+6t(1−t)(y2−y1)+3t2(y3−y2)
其中 (x0,y0)(x_0,y_0)(x0,y0)、(x1,y1)(x_1,y_1)(x1,y1)、(x2,y2)(x_2,y_2)(x2,y2)、(x3,y3)(x_3,y_3)(x3,y3) 为3阶贝塞尔曲线的4个控制点坐标。
根据采样点数 NNN,计算出采样点的间隔 s=L/(N−1)s=L/(N-1)s=L/(N−1)。
初始化采样点列表,包括起始点 (x0,y0)(x_0,y_0)(x0,y0) 和终止点 (x3,y3)(x_3,y_3)(x3,y3) 并将起始点和终止点的参数值分别设为 t0=0t_0=0t0=0 和 tN=1t_N=1tN=1。
对于 i∈[1,N−1]i \in [1,N-1]i∈[1,N−1],通过二分法计算出满足以下条件的 tit_iti:
∫t0ti(dx/dt)2+(dy/dt)2dt=i×s\int_{t_0}^{t_i} \sqrt{(dx/dt)^2+(dy/dt)^2} dt = i \times s∫t0ti(dx/dt)2+(dy/dt)2dt=i×s
其中 (dx/dt)2+(dy/dt)2\sqrt{(dx/dt)^2+(dy/dt)^2}(dx/dt)2+(dy/dt)2 的计算公式如上。然后根据 tit_iti 计算出曲线上对应的点坐标,即 (xi,yi)(x_i,y_i)(xi,yi)。