Bspline实现没有按预期工作

时间:2015-05-17 22:37:43

标签: c math spline bspline

我实现了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;
}

问题在于,当我绘制计算点时,我发现在曲线的开头和结尾有一个意外的行为。 例如: enter image description here

我无法理解为什么会发生这种情况,尝试更改t的值,但似乎不是这样。

2 个答案:

答案 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次)。因此,显示的样条曲线在第一个/最后一个控制点开始/结束。你的建筑没有这个属性。