B样条曲线方程和C++实现
功能:根据参数u值和k(大小为阶数值)与节点矢量,计算第i个k次B样条基数
输入参数: u—参数值;k—大小值为阶数;i—第i个k次B样条的支撑区间左端节点的下标;aNode为节点向量。
输出参数:返回函数值。
double GetBaseFunVal(double u, int i, int k, vector <double> m_aNode)
{
double Val = 0.0;
double Val1 = 0.0;
double Val2 = 0.0;
if (k==0)
{
if (u < m_aNode[i] || u > m_aNode[i+1])
return Val;
else
{
Val = 1.0;
return Val;
}
}
if (k>0)
{
if (u < m_aNode[i] || u > m_aNode[i+k+1])
{
return Val;
}
else
{
double alpha = 0.0;
double beta = 0.0;
double dTemp = 0.0;
dTemp = m_aNode[i+k] - m_aNode[i];
if (dTemp == 0.0)
{
alpha = 0;
}
else
alpha = (u - m_aNode[i])/dTemp;
dTemp = m_aNode[i+k+1] - m_aNode[i+1];
if (dTemp == 0.0)
{
beta = 0.0;
}
else
beta = (m_aNode[i+k+1] - u)/dTemp;
Val1 = alpha * GetBaseFunVal(u, i, k-1, m_aNode);
Val2 = beta * GetBaseFunVal(u, i+1, k-1, m_aNode);
Val = Val1 + Val2;
}
}
return Val;
}
上述功能模块摘自于计算机辅助几何设计与非均匀有理B样条。已知B样条的n+1控制点坐标,以及相应的节点向量,可求得对应的曲线方程。
先计算各个控制点的基函数

各个基函数的求解可根据上述的功能模块求出。
下面是我的C++实现:曲线是二维的,三维的情况,就Z坐标做同X,Y求解方式相同即可。在求解的过程中,我自己在CAD上画了个样条曲线,然后通过GetBaseFunVal(double u, int i, int k, vector <double> m_aNode)和顶点坐标,及节点向量求各个点的坐标。随着u值的变化,计算各个X,Y,Z值。一个星期的摸爬滚打中,能输出图形,但是与原来的图形对应不上。最终找到的原因在与基函数出问题了。在书本等相关资源中,基函数成员中的k表示的是次数,在我画的样条曲线中,阶数显示为3(为什么是3?CAD的标注里,实体块中的 70 下一行,为3),所以我理所当然的写为了2,。一直有问题。我将它改为3以后,竟然奇迹般的可以用了。而且跟原来图形吻合。这个是我的相关经历,希望对你们能有用。另外,哪位热心人士可以说明下,为什么k改为阶数大小,就可以呢?
#include <iostream>
#include <fstream>
#include <afxtempl.h>
using namespace std;
struct tPoint
{
double x;
double y;
double z;
};
double GetBaseFunVal(double u, int i, int k, vector <double> m_aNode)
{
double Val = 0.0;
double Val1 = 0.0;
double Val2 = 0.0;
if (k==0)
{
if (u < m_aNode[i] || u > m_aNode[i+1])
return Val;
else
{
Val = 1.0;
return Val;
}
}
if (k>0)
{
if (u < m_aNode[i] || u > m_aNode[i+k+1])
{
return Val;
}
else
{
double alpha = 0.0;
double beta = 0.0;
double dTemp = 0.0;
dTemp = m_aNode[i+k] - m_aNode[i];
if (dTemp == 0.0)
{
alpha = 0;
}
else
alpha = (u - m_aNode[i])/dTemp;
dTemp = m_aNode[i+k+1] - m_aNode[i+1];
if (dTemp == 0.0)
{
beta = 0.0;
}
else
beta = (m_aNode[i+k+1] - u)/dTemp;
Val1 = alpha * GetBaseFunVal(u, i, k-1, m_aNode);
Val2 = beta * GetBaseFunVal(u, i+1, k-1, m_aNode);
Val = Val1 + Val2;
}
}
return Val;
}
int main()
{
tPoint tData;
vector <tPoint> vtData;
vtData.clear();
vector <double> nodeVector;
nodeVector.push_back(0);
nodeVector.push_back(0);
nodeVector.push_back(0);
nodeVector.push_back(0);
nodeVector.push_back(1);
nodeVector.push_back(2);
nodeVector.push_back(3);
nodeVector.push_back(4);
nodeVector.push_back(5);
nodeVector.push_back(6);
nodeVector.push_back(6);
nodeVector.push_back(6);
nodeVector.push_back(6);
//节点向量nodeVector, 控制点坐标(0,3),(200,100), (750, 200), k=2
for (double u = 0; u < 6; u=u+0.01)
{
// 样条的数据
tData.x = (GetBaseFunVal(u, 0, 3, nodeVector)*(-7585) + GetBaseFunVal(u, 1, 3, nodeVector)*(-3427.5) + GetBaseFunVal(u, 2, 3, nodeVector)*46087.5
+ GetBaseFunVal(u, 3, 3, nodeVector)*9220.0 + GetBaseFunVal(u, 4, 3, nodeVector)*(-14835.0) + GetBaseFunVal(u, 5, 3, nodeVector)*(-2002.5) + GetBaseFunVal(u, 6, 3, nodeVector)*71975
+ GetBaseFunVal(u, 7, 3, nodeVector)*45235 + GetBaseFunVal(u, 8, 3, nodeVector)*83150)/*/(GetBaseFunVal(u, 0, 3, nodeVector) + GetBaseFunVal(u, 1, 3, nodeVector) + GetBaseFunVal(u, 2, 3, nodeVector)
+ GetBaseFunVal(u, 3, 3, nodeVector) + GetBaseFunVal(u, 4, 3, nodeVector) + GetBaseFunVal(u, 5, 3, nodeVector))*/;
tData.y = (GetBaseFunVal(u, 0, 3, nodeVector)*(-3807.5) + GetBaseFunVal(u, 1, 3, nodeVector)*(19850.0) + GetBaseFunVal(u, 2, 3, nodeVector)*14335
+ GetBaseFunVal(u, 3, 3, nodeVector)*(-17582.5) + GetBaseFunVal(u, 4, 3, nodeVector)*(-5445.0) + GetBaseFunVal(u, 5, 3, nodeVector)*(-80735.0) + GetBaseFunVal(u, 6, 3, nodeVector)*(-23817.5)
+ GetBaseFunVal(u, 7, 3, nodeVector)*5037.5 + GetBaseFunVal(u, 8, 3, nodeVector)*(-9360))/*/(GetBaseFunVal(u, 0, 3, nodeVector) + GetBaseFunVal(u, 1, 3, nodeVector) + GetBaseFunVal(u, 2, 3, nodeVector)
+ GetBaseFunVal(u, 3, 3, nodeVector) + GetBaseFunVal(u, 4, 3, nodeVector) + GetBaseFunVal(u, 5, 3, nodeVector))*/;
tData.z = 0.0;
vtData.push_back(tData);
}
char *file = "C:/Users/Monkey/Desktop/新建文件夹 (2)/TEST/Last.txt";
ofstream out(file);
if (!out)
{
cout << "打开文件失败!!!!" << endl;
}
for (int n = 0; n < vtData.size(); n++)
{
out << vtData[n].x << " " << vtData[n].y <<" " << vtData[n].z << endl;
}
out.close();
return 0;
}
B样条曲线方程和C++实现的更多相关文章
- B样条曲线曲面(附代码)
1 B样条曲线 1.1 B样条曲线方程 B样条方法具有表示与设计自由型曲线曲面的强大功能,是形状数学描述的主流方法之一,另外B样条方法是目前工业产品几何定义国际标准——有理B样条方法 (NURBS)的 ...
- B样条基函数的定义和性质
定义:令U={u0,u1,…,um}是一个单调不减的实数序列,即ui≤ui+1,i=0,1,…,m-1.其中,ui称为节点,U称为节点矢量,用Ni,p(u)表示第i个p次(p+1阶)B样条基函数,其定 ...
- B样条基函数(cubic spline basis)
B样条基函数用作权重 reference http://blog.csdn.net/tuqu
- [图形学] Chp14 GLU曲面裁剪函数程序示例及样条表示遗留问题
样条表示这章已经看完,最后的GLU曲面裁剪函数,打算按书中的示例实现一下,其中遇到了几个问题. 先介绍一下GLU曲面裁剪函数的使用方法. 1 裁剪函数是成对出现的: gluBeginTrim和gluE ...
- [摘抄] Bezier曲线、B样条和NURBS
Bezier曲线.B样条和NURBS,NURBS是Non-Uniform Rational B-Splines的缩写,都是根据控制点来生成曲线的,那么他们有什么区别了?简单来说,就是: Bezier曲 ...
- B样条基函数的定义及系数的意义
原文链接:http://blog.csdn.net/tuqu/article/details/5177405 贝塞尔基函数用作权重.B-样条基函数也一样:但更复杂.但是它有两条贝塞尔基函数所没有的特性 ...
- 样条之拉格朗日Lagrange(一元全区间)插值函数
这是使用拉格朗日插值函数生成的样条曲线.在数值分析中,拉格朗日插值法是以法国十八世纪数学家约瑟夫·拉格朗日命名的一种多项式插值方法.许多实际问题中都用函数来表示某种内在联系或规律,而不少函数都只能通过 ...
- 样条之埃尔米特(Hermite)
埃尔米特(Charles Hermite,1822—1901) 法国数学家.巴黎综合工科学校毕业.曾任法兰西学院.巴黎高等师范学校.巴黎大学教授.法兰西科学院院士.在函数论.高等代数.微分方程等方面都 ...
- 样条之CatmullRom
所谓样条曲线是指给定一组控制点而得到一条曲线,曲线的大致形状由这些点予以控制,一般可分为插值样条和逼近样条两种,插值样条通常用于数字化绘图或动画的设计,逼近样条一般用来构造物体的表面.CatmullR ...
随机推荐
- 优雅写Java之一(常见编程技巧)
一.字符串相关 推荐使用Apache Commons Lang3库 创建Empty字符串:return StringUtils.EMPTY; 或者 return ""; 创建重复的 ...
- [总结]ACM模拟总结
1.心态一定要稳,千万不要慌. 2.内部交流要多点,说不定就讨论出有用的性质了. 3.题目细节一定要想清楚. 4.一道题绝对不能让多个人来写. 5.英语要好好学.
- [集训]Evocation
题意 一颗有根树,每个点有黑白两种颜色和阀值ai,若它的子树中(不包括自己)的黑色数量大于ai,则产生一点贡献.每次将一个点的颜色取反,求每次修改后的贡献.n,q<=1E5. 思考 树剖后直接分 ...
- 【WPF学习】第二十五章 日期控件
WPF包含两个日期控件:Calender和DatePicker.这两个控件都被设计为允许用户选择日期. Calendar控件显示日期,在与Windows操作系统中看到的日历(例如,当配置系统日期时看到 ...
- SUSE Linux Enterprise 11 离线安装 DLIB 人脸识别 python机器学习模块
python机器学习模块安装 我的博客:http://www.cnblogs.com/wglIT/p/7525046.html 环境:SUSE Linux Enterprise 11 sp4 离线安 ...
- java加解密算法--DES
ECB import sun.misc.BASE64Decoder; import javax.crypto.*; import javax.crypto.spec.DESKeySpec; impor ...
- DOCKER 学习笔记7 Docker Machine 在阿里云实例化ECS 以及本地Windows 实例化虚拟机实战
前言 通过以上6小节的学习,已经可以使用DOCKER 熟练的部署应用程序了.大家都可以发现使用 DOCKER 带来的方便之处,因为现在的话,只是在一台服务器上部署,这样部署,我们只需要一条命令,需要的 ...
- tmobst3
1.(单选题)如果数据库是oracle,则generator属性值不可以使用(). A)native B)identity C)hilo D)sequence 2.(单选题)为了获得用户提交的表单参数 ...
- C++读取MNIST数据集
MNIST是一个标准的手写字符测试集. Mnist数据集对应四个文件: train-images-idx3-ubyte: training set images train-labels-idx1- ...
- python书籍推荐以及杂七杂八
黄哥推荐学习Python 10本好书 Python3网络爬虫开发实战 github daily-reading 想对大家说的话 POJ 算法练习 http://openjudge.cn/ http:/ ...