我实现了BSPLINE曲线。我遵循http://en.wikipedia.org/wiki/B-spline
中提出的通常定义t是结矢量。
#include <stdio.h>
double N(int i, int k, double u, double t[])
{
if(k == 1)
{
if(u >= t[i] && u < t[i+1])
return 1.0e0;
else {
return 0.0e0;
}
}
return ((u - t[i])*N(i, k -1, u, t))/(t[i+k-1] - t[i]) + ((t[i+k] - u)*N(i+1, k-1, u, t))/(t[i+k] - t[i+1]);
}
double pu(double u, double x[], int n, int k, double t[])
{
int i;
double r = 0.0e0;
for(i = 0; i < n; i++)
{
r += x[i]*N(i, k, u, t);
}
return r;
}
int main()
{
double t[] = {0.0, 0.5, 1, 2, 3, 4, 4.5, 5}; //knot vector
double x[] = {-30.0, 25.0, 9.0, 20.0, 25.0, 31.0}, y[] = {-5.0, -10.0, 3.0, -10.0, -5.0, 25.0}; //the points
double u;
for(u = 0.0e0; u < 5.0; u+=0.01e0)
{
printf("%lf %lf\n", pu(u, x, 6, 2, t), pu(u, y, 6, 2, t));
}
return 0;
}
问题在于,当我绘制计算点时,我发现在曲线的开头和结尾有一个意外的行为。 例如:
我无法理解为什么会发生这种情况,尝试更改t的值,但似乎不是这样。
答案 0 :(得分:2)
bspline有两种实现:统一和标准。在统一中,第一个和最后一个控制点不被内插,并且在标准结序列中都被内插。在制服,你可以有统一的结通常1,2,3,...对于标准的结节序列,如果你有k(k-1度)你应该有k个零,k个,并在中间用1 /( m-k + 2)其中m是控制点的数量。例如,有5个控制点和3阶,结节序列为0,0,0,0.25,0.5,0.75,1,1,1。
此外,使用delta函数可以获得更好的实现,而不是计算N函数。 Delta函数受益于bspline的本地支持。我建议你看看我在卡尔加里大学教授的课程笔记: http://pages.cpsc.ucalgary.ca/~amahdavi/pmwiki-2.2.8/uploads/Site/notes1.pdf
检查第40页算法3.3。
希望它有所帮助。
答案 1 :(得分:1)
一般情况下:如果你有n个控制点,你构造了一个k度的bspline曲线,你的结矢量有n + k + 1个结。曲线的域(即基函数的总和= 1)在区间[t_k,... t_n]中给出(就我的详细信息而言)。
在循环中,参数值的范围为0.0到5.0。这应该是t [k] = t [2] = 1.0到t [n] = t [6] = 4.0。
wiki示例以另一种方式执行,因为在那里给出的结矢量在开始和结束时具有多个值(即k次)。因此,显示的样条曲线在第一个/最后一个控制点开始/结束。你的建筑没有这个属性。