如何绘制三次B样条曲线
B樣條的定義就不贅述了,同學(xué)們可以參考大神的博客:http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/,中文翻譯也有:http://blog.csdn.net/tuqu/article/details/4749586
我要說的是在理解定義之后,我們?nèi)绾螌崿F(xiàn)它,這里我只討論準(zhǔn)均勻B樣條,即三次B樣條曲線經(jīng)過首尾節(jié)點(用的最為廣泛), 非均勻及Nurbs曲線等等還沒有研究.
1、首先是節(jié)點向量的確定,節(jié)點向量的數(shù)目 l = 控制點數(shù)目 + 次數(shù)p(這里是3)+ 1. ?為了經(jīng)過首尾點,要求節(jié)點向量的前p+1個節(jié)點向量為0,中間的l-2(p+1)個節(jié)點向量依次加一,后p+1個節(jié)點為最大值,好多文章說前p個節(jié)點向量,其實他說的p指的是階數(shù),不是次數(shù),而階數(shù)=次數(shù)+1,我就被誤導(dǎo)過,總是畫得不對,坑死爹了.附上函數(shù):
void BSpline::InitKnots() const
{
std::size_t count = _vertexs.size();//_vertexs是控制點數(shù)組
for (int i = 0; i < _degree; i++)//degress表示次數(shù),這里為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個節(jié)點為0
{
if (i > 0)
dParam += 1.0;
_knots.push_back(dParam);
}
for (std::size_t i = 0; i < _degree; i++)//這里是后p個等于最大,實際上倒數(shù)第p+1個也是最大
{
_knots.push_back(dParam); //后p個 0
}
}
2、基函數(shù)的確定
本文是用deboor算法的遞歸形式,形式比較簡單,實現(xiàn)難度低,但是效率也低,效率高的方式我會在下一篇博客中介紹,deboor對B樣條基函數(shù)的定義如下:
基函數(shù)的代碼:
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、生成
根據(jù)B樣條的定義,生成B樣條離散點,這里用到了osg的數(shù)據(jù)結(jié)構(gòu),將就看吧
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<osg::Vec3dArray> 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
總結(jié)
以上是生活随笔為你收集整理的如何绘制三次B样条曲线的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【激光原理】多普勒烧孔原理的三维可视化图
- 下一篇: 【C语言】野指针