如何绘制三次B样条曲线

B样条的定义就不赘述了,同学们可以参考大神的博客:http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/,中文翻译也有:http://blog.csdn.net/tuqu/article/details/4749586

我要说的是在理解定义之后,我们如何实现它,这里我只讨论准均匀B样条,即三次B样条曲线经过首尾节点(用的最为广泛), 非均匀及Nurbs曲线等等还没有研究.


1、首先是节点向量的确定,节点向量的数目 l = 控制点数目 + 次数p(这里是3)+ 1.  为了经过首尾点,要求节点向量的前p+1个节点向量为0,中间的l-2(p+1)个节点向量依次加一,后p+1个节点为最大值,好多文章说前p个节点向量,其实他说的p指的是阶数,不是次数,而阶数=次数+1,我就被误导过,总是画得不对,坑死爹了.附上函数:

void BSpline::InitKnots() const
{
std::size_t count = _vertexs.size();//_vertexs是控制点数组


for (int i = 0; i < _degree; i++)//degress表示次数,这里为3
{
_knots.push_back(0.0); //前p个0
}


double dParam = 0.0;
for (std::size_t i = 0; i < count - _degree + 1; i++)//这里如果是0则,dParm = 0,也就是说前p+1个节点为0
{
if (i > 0)
dParam += 1.0;
_knots.push_back(dParam);
}


for (std::size_t i = 0; i < _degree; i++)//这里是后p个等于最大,实际上倒数第p+1个也是最大
{
_knots.push_back(dParam); //后p个 0
}
}

2、基函数的确定

本文是用deboor算法的递归形式,形式比较简单,实现难度低,但是效率也低,效率高的方式我会在下一篇博客中介绍,deboor对B样条基函数的定义如下:



基函数的代码:

double EvalBasis(double u, int i, int degree) 
{
if (degree == 0)
{
if (u >= _knots[i] && u < _knots[i + 1])
{
return 1.0;
}
else
{
return 0.0;
}
}
double l0 = u - _knots[i];
double l1 = _knots[i + degree] - _knots[i];
double l2 = Divide(l0, l1);


double k0 = _knots[i + degree + 1] - u;
double k1 = _knots[i + degree + 1] - _knots[i + 1];
double k2 = Divide(k0, k1);


double res = l2 * EvalBasis(u, i, degree - 1) + k2 * EvalBasis(u, i + 1, degree - 1);
return res;
}

double Divide(double x, double y) const
{
if (y == 0.0)
{
return 0.0;
}
return x / y;
}

3、生成

根据B样条的定义,生成B样条离散点,这里用到了osg的数据结构,将就看吧


osg::Vec3dArray* BSpline::Generate() const
 {
if (_vertexs.size() < 4)
{
return NULL;
}


InitKnots();


int iStep = 100;
int iLen = _knots.size();
double dStart = _knots[0];
double dEnd = _knots[iLen - 1];
double dDelta = (dEnd - dStart) / iStep;


osg::ref_ptr v3dArray = new osg::Vec3dArray;
for (int s = 0; s <= iStep; s++)
{
double u = s * dDelta;
osg::Vec3d v;
double sum = 0.0;


for (int i = 0; i < _vertexs.size(); i++)
{
double t = EvalBasis(u, i, _degree);
v += _vertexs.at(i) * t;
sum += t;
}


if (v != osg::Vec3d())
{
v3dArray->push_back(v);
}
}
return v3dArray.release();
}

下载地址:http://download.csdn.net/detail/qingcaichongchong/9697192

你可能感兴趣的:(计算机图形学)