日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何绘制三次B样条曲线

發(fā)布時間:2023/12/8 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何绘制三次B样条曲线 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。