2

我做了这个 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 的值,但似乎不是这样。

4

2 回答 2

2

bspline 有两种实现方式:uniform 和standard。在统一的情况下,第一个和最后一个控制点没有被内插,而在标准节点序列中,两个控制点都被内插。在制服中,你可以有统一的结,通常是 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。

希望它会有所帮助。

于 2015-05-18T05:50:09.070 回答
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 次)。所以显示的样条曲线在第一个/最后一个控制点开始/结束。你的建筑没有给出这个属性。

于 2015-05-18T04:04:52.573 回答