B样条曲线
deBoor_Cox函数
// B样条基函数 deBoor_Cox 递推公式
// i: 控制点计数
// k: 次数
// t: 节点
// knots: 节点向量,用来分段
double deBoor_Cox(int i, int k, double t, double *knots)
{
// 递归出口
if (k == 0) // k=0, 零次基函数显示为一个阶梯函数
{
if (t >= knots[i] && t < knots[i + 1])
return 1.0;
else
return 0.0;
}
// 2个分母
double den1 = knots[i + k] - knots[i];
double den2 = knots[i + k + 1] - knots[i + 1];
// 2个系数
double a = 0, b = 0;
// 4个判定 设置 0/0=1 的情况
if (den1 == 0 && den2 == 0)
{
a = 1;
b = 1;
}
else if (den1 != 0 && den2 == 0)
{
a = (double)(t - knots[i]) / den1;
b = 1;
}
else if (den1 == 0 && den2 != 0)
{
a = 1;
b = (double)(knots[i + k + 1] - t) / den2;
}
else
{
a = (double)(t - knots[i]) / den1;
b = (double)(knots[i + k + 1] - t) / den2;
}
return a*deBoor_Cox(i, k - 1, t, knots) + b*deBoor_Cox(i + 1, k - 1, t, knots); // 尾递归
}
drawBSplineCurve
// 画B样条曲线 cubic.txt中的节点是不均匀分割点
void drawBSplineCurve()
{
// u_k <= u <= u_n+1 k:次数 n+1:控制点数
double tmin = b.knots[b.degree]; // 3
double tmax = b.knots[b.cntNum]; // 4
//double tmin = 0, tmax = 5; // 当指定 t 上下界为节点矢量上下界时,曲线会闭合
double steps = (tmax - tmin) / (insertNum - 1); // 步长
cout << "步长" << steps << endl << endl;
cout << "插入点数目" << insertNum << endl << endl;
cout << "插入点坐标" << endl;
glColor3f(0.0, 1.0, 0.0);
glLineWidth(3.0);
glBegin(GL_LINE_STRIP);
for (int i = 0; i < insertNum; i++)
{
// 顶点初始化
Point2D p;
p.x = 0.0;
p.y = 0.0;
double t = tmin + i*steps; // 均匀插值
for (int j = 0; j < b.cntNum; j++)
{
double Nik = deBoor_Cox(j, b.degree, t, b.knots); // 基函数
p.x += Nik*b.cnt_points[j].x;
p.y += Nik*b.cnt_points[j].y;
}
cout << p.x << "," << p.y << endl;
glVertex2f(p.x, p.y);
}
glEnd();
}