B样条曲线曲面和NURBS曲线曲面C语言算法源程序
- 格式:doc
- 大小:210.50 KB
- 文档页数:27
权威3DMAX NURBS曲线和曲面教程一、NuRBS曲线作用:可制作圆滑的曲线外形‘Create(创建)‘shape(外形)‘NURBSpoint curve(点曲线)CV curve(控制点曲线):曲线在各控制点连接的多边形内参数:attach(附加):将其它曲线附加到当前曲线中二、NURBS曲面作用:可制作圆滑的面,如汽车外壳,床罩,窗帘丝织物品表面‘create(创建) →‘Geomotry(三维几何体) →‘NurBs surface(NurBs曲面) →‘point surface(点曲面)‘cv surface(控制点曲面)1、point surface(点曲面)参数:u lines:X轴节点数v lines:Y轴节点数次对象:point(点):选择1个顶点(单个):选择一行顶点(单行):选择一列顶点(单列):选择交叉的一行一列顶点(行列):选择所有顶点2、cv suface(控制点曲面)参数:Length cvs:长控制点数Width cvs:宽控制点次对象:与点曲面相同三、NurBs创建工具箱作用:方便创建曲线或者曲面1、Curves(曲线)工具箱第一个():建立cv curve(控制点曲线)第二个():建立Point curve(点曲面)第三个():连接两个顶点,限定在点曲线面类第四个():复制曲线第五个():连接2个顶点,点曲线,CV曲面都可相连第六个():产生曲线的轮廓线第七个():镜像复制曲线3、surface(曲面)工具箱第一个():建立cv surface(控制点曲面)第二个():建立point surface(点曲面)第三个():复制曲面第四个和第九个():将2个曲线连接成面第五个():复制曲面,不能分开第六个():镜向复制曲面第七个():将曲面拉伸成面第八个():将曲线旋转成面3DMAX 第十五讲(材质1)一、材质编辑器作用:赋于物体材质,表现出各种实际效果1、主窗口组成①样本窗②水平工具栏③垂直工具栏④材质名称类型⑤参数展示栏2、样本窗显示方式选择某样本球’→‘5╳3或‘6╳43、垂直工具栏①样本类型:以何种方式显示样本②背光:显示/隐藏样本球暗区光线③背景:检查透明材质效果④重复:检查透明材质效果⑤视频颜色检查:检查材质颜色以适应电视输出⑥材质动画预览⑦选项:设置材质,相关参数⑧按材质选择物体4、水平工具栏(1)获取材质(包括复合标准材质)(2)将冷材质重新赋予场景中的物体(3)将材质赋予场景中被选择的物体(4)清除材质(5)热材质变为冷材质(6)保存材质备以后使用(8)材质效果通道,给材质起编号(9)显示场景中物体的贴图(10)显示最后结果(11)回到父层级(12)到同一层次(13)材质/贴图导航器二、同步材质,异步材质1、同步材质称为热材质,当改变材质参数,场景中的物体材质会同步变化,样本球4个角为白三角形2、异步材质称为冷材质,当改变材质参数,场景中的物体材质不随之变化三、给物体贴图选择物体→(材质编辑器按钮)→选择一个样本球→diffuse(散播颜色) →‘(贴图按钮)→“Bitmap(位图) →选择某图片→‘打开→‘(显示贴图按钮)。
Bezier曲线、B样条曲线和NURBS曲线0.概述1. 贝塞尔曲线(Bezier Curve):贝塞尔曲线由一组控制点和控制点上的权重组成。
贝塞尔曲线的阶数由控制点的数量决定,阶数为n的贝塞尔曲线需要n+1个控制点。
贝塞尔曲线具有局部控制的特性,即曲线上的一段由相邻的几个控制点决定,不受其他控制点的影响。
贝塞尔曲线的计算相对简单,但在变形过程中可能会出现形状扭曲的问题。
2. B样条(B-Spline): B样条曲线是一种基于分段多项式的曲线表示方法。
与贝塞尔曲线不同,B样条曲线的每个控制点都有一个关联的基函数。
这些基函数决定了曲线上每一点的形状。
B样条曲线的阶数可以是任意的,较高阶的B样条曲线能够更灵活地描述复杂的曲线形状。
B样条曲线具有良好的局部控制性和平滑性,可以很好地避免贝塞尔曲线的形状扭曲问题。
3. NURBS曲线(Non-Uniform Rational B-Spline Curve):NURBS曲线是对B样条曲线的扩展,它引入了有理权重的概念。
NURBS曲线的每个控制点都有一个关联的权重,这些权重可以调节曲线上各个点的影响程度。
NURBS曲线能够表示更复杂的曲线形状,如圆弧和椭圆等。
总的来说Bezier曲线中的每个控制点都会影响整个曲线的形状,而B样条中的控制点只会影响整个曲线的一部分,显然B样条提供了更多的灵活性;Bezier和B样条都是多项式参数曲线,不能表示一些基本的曲线,比如圆,所以引入了NURBS,即非均匀有理B样条来解决这个问题;贝塞尔曲线适用于简单的曲线形状设计,B样条曲线具有更好的局部控制和平滑性,适用于复杂曲线的建模而NURBS曲线在B样条的基础上引入了有理权重,可以更准确地描述各种曲线形状Bezier曲线是B样条的一个特例,而B样条又是NURBS的一个特例1.Bezier曲线1.1 贝塞尔曲线的历史:贝塞尔曲线于 1962 年,由法国工程师皮埃尔·贝济埃(PierreBézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计,贝塞尔曲线最初由保尔·德·卡斯特里奥于1959年运用德卡斯特里奥算法开发,以稳定数值的方法求出贝塞尔曲线。
NURBS曲线理论第三章 NURBS 曲线理论基础NURBS ⽅法的提出是基于描述⾃由曲⾯曲线的B 样条⽅法。
B 样条基函数和B 样条曲线是UURBS 曲线的基础,UURBS 是⾮均匀有理B 样条的英⽂缩写。
因此在给出UURBS 曲线定义之前,先介绍⼀下B 样条基函数和B 样条曲线的相关知识。
3.1 B 样条基函数定义和性质B-Spline Function (简称B 样条)就是B 样条基函数,是样条函数的⼀种。
B 样条不但具有⼀般样条函数所具有的分段光滑⼜在各段交接处具有⼀定光滑性等特点,⽽且具有许多其他优良性质,如连续阶数可调、局部⽀撑性、递推性等。
有很多种⽅法可以⽤来定义B 样条基函数,我们这⾥采⽤de Boor-Cox 递推定义⽅法,是由这种递推法很容易和有效地在计算机上实现。
⽽且de Boor-Cox 递推定义很好地揭⽰了B 样条基函数的性质。
B 样条基函数的de Boor-Cox 递推定义如下:1,01,,11,1i 111[,N 0()()000i i i i i k i k i k i k i k i k i u u u u u u u N N u N u u u u u +++-+-++++?∈?=?--=+--=)其他规定: (3. 1) 上式(3.1)中k 为B 样条的次数(k+1阶);令U={u 0,u 1,…,u m }是⼀个单调不减的实数序列,u i 称为节点序列,U 称为节点⽮量,若存在ui-1,<u i =u i+1=…=u i+r-1B 样条具有良好的性质,简单概括主要有【18,20】:●递推性:定义式(3.1)很好的说明了这个性质。
●规范性:对于定义域内任意参数u ,所有的k 次B 样条基函数之和恒为1,即1)(0,=∑=u N mi k i 。
●局部⽀撑性质:对于定义域内参数u ∈[u i u i+1),⾄多有k+1个⾮零的k 次B 样条N j,k (u ),j=i —k ,i —k+l ,...,i ,其他k 次B 样条在该处均为零。
B 样条曲线曲面和NURBS 曲线曲面(学习笔记和上机练习)非均匀有理B 样条,通常简称为NURBS(Non-Uniform Rational B-Splines)。
NURBS 是非有理B 样条、有理以及非有理B ézier 曲线曲面的推广。
一、要对B 样条曲线曲面和NURBS 曲线曲面有所了解应先了解B 样条基函数 B 样条基函数的定义和性质令{}m u u u U ,...,,10=是一个实数列,即i u ≤1+i u ,i=0,1,…,m-1。
其中,i u 称为节点,U 称为节点矢量,用)(,u N p i 表示第i 个p 次(p +1阶)B 样条基函数,其定义为⎩⎨⎧=,0,1)(0,u N i 若i u ≤u <1+i u 值为1,其他值为0 )()()(1,11111,,u N u u u u u N u u u u u N p i i p i p i p i i p i ip i -++++++-+--+--= (2)由(2)式可知:(1))(0,u N i 是一个阶梯函数,它在半开区间),[1+∈i i u u u 外都为零; (2)当p >0时,)(,u N p i 是两个p -1次基函数的线性组合;(3)计算一组基函数时需要事先指定节点矢量U 和次数p ; (4)(2)式中可能出现0/0,我们规定0/0=0;(5))(,u N p i 是定义在整个实数轴上的分段多项式函数,只在区间][,0m u u 上有意义; (6)半开区间),[1+i i u u 称为第i 个节点区间,长度可以为零,因相邻节点可以相同; B 样条基函数的一些重要性质:1 如果),[1++∉p i i u u u ,则)(,u N p i =0。
2 对于所有的p i ,和u ,有)(,u N p i ≥0.3 对于任意的节点区间),[1+i i u u ,当),[1+∈i i u u u 时,∑-==ipi j pj u N1)(,。
occ生成nurbs样条曲线全文共四篇示例,供读者参考第一篇示例:在计算机辅助设计(CAD)和计算机图形学领域,NURBS(Non-Uniform Rational B-Spline,非均匀有理B样条)曲线是一种强大的数学表示工具,可以用来描述各种曲线和曲面形状。
与其他曲线表示方法相比,NURBS曲线具有许多优势,如灵活性、精度和精细控制等。
在本文中,我们将介绍如何使用OCC(Open CASCADE Technology)库生成NURBS样条曲线,并探讨其在实际应用中的价值。
OCC是一个开放源代码的CAD/CAM/CAE集成平台,在工程设计领域得到广泛应用。
它包含了大量的几何建模和图形算法,可以用来创建、编辑和分析几何实体。
OCC库中提供了丰富的函数和类来处理NURBS曲线,使得用户可以方便地生成各种复杂的曲线形状。
生成NURBS曲线的关键步骤是定义曲线的控制点、权重、节点和次数。
用户需要指定一组控制点,这些点将决定曲线的形状。
每个控制点都有一个权重值,用来影响该点对曲线的影响程度。
权重值越高,控制点对曲线的影响就越大。
节点是描述曲线弯曲和形状的参数,通过调整节点的位置和权重值,可以控制曲线的曲率和光滑度。
次数定义了NURBS曲线的阶数,影响了曲线的灵活性和精度。
在OCC库中,用户可以通过调用相应的函数和类来生成NURBS 曲线。
用户需要创建一个BSplineCurve对象,并设置曲线的控制点、权重、节点和次数。
然后,可以通过调用相应的函数来计算曲线上的点坐标、切线、曲率等信息。
用户还可以使用OCC库提供的绘图工具将生成的曲线显示在屏幕上,以便进行可视化查看和分析。
NURBS曲线在工程设计和制造中有着广泛的应用。
它们可以用来描述各种曲线形状,如自由曲面、汽车车身、船体等。
通过调整控制点和权重值,用户可以实现对曲线形状的精细控制,从而满足不同的设计需求。
NURBS曲线还可以用来进行曲线重构和拟合,从而实现曲线数据的压缩和处理,提高数据的处理效率和精度。
专升本计算机图形学与CAD技术一、共70题,共150分1. CAD的一个未来发展方向是实现跨部门或行业、跨地域的企业协同产品开发;描述的是: 2分A.集成化B.网络化C.智能化D.标准化.标准答案:B2. 有限元的基本思想是 2分A.弹性力学B.结构离散C.机构分析与综合D.面向对象编程.标准答案:B3. 以下是计算机辅助制造软件 2分.标准答案:C4. 以下属于CSG表达特点的是 2分A.以边界表示形体B.以二叉树表示形体C.数据结构复杂D.形体更新快.标准答案:B5. 以下结构划分合理的网格是 2分A.B.C..标准答案:C6. AutoCAD中,r是命令的缩写 2分.标准答案:A7. 以下不是形体在计算机内部表示的是 2分A.线框模型B.表面模型C.实体模型D.二叉树模型.标准答案:D8. 可以计算实体的质量和惯性矩 2分A.物性分析B.装配干涉检查C.装配树D.爆炸图;.标准答案:A9. 以下不属于Bezier曲线性质和特点的是: 2分A.曲线通过首末点且与首末控制多边形边相切B.曲线在控制多边形边的凸包内进行针对设计人员的人力资源管理.标准答案:A19. 下列算法不是递推的; 2分算法 B.简单的种子填充算法算法 D.中点画线法.标准答案:A20. 是基本体素 2分A.倒角B.拉伸C.球体.标准答案:C21. 在创成式CAPP系统中进行逻辑决策的常用方法为 2分A.决策树B.决策表C.逻辑联系图D.二叉树.标准答案:A,B22. 形体在计算机内部的表示常用模型; 2分A.线框模型B.表面模型C.实体模型D.渲染模型.标准答案:A,B,C23. 有限元分析软件由组成 2分A.前处理B.分析计算C.概率设计D.后处理.标准答案:A,B,D24. CAD系统的选型原则有: 2分A.具有专业应用足够的系统功能B.软件系统具有良好的用户界面C.具有良好的二次开发接口D.硬件系统要支持并行计算机.标准答案:A,B,C25. 优化数学模型的三要素是 2分A.设计变量B.设计对象C.约束条件D.目标函数.标准答案:A,C,D26. 线性插值的几何意义是 2分A.过三点做三角形B.两点做一直线C.以一点为中心过另一点做圆D.过三点做抛物线.标准答案:B27. 以计算机中所记录的形状参数与属性参数来表示图形的一种方法叫做 2分A.参数法B.图形C.点阵法D.图像.标准答案:A28. 下列不属于图形输出设备的是 2分C.绘图仪D.扫描仪.标准答案:D29. 4按照所构造的图形对象来分,下列哪项属于规则对象 2分A.山B.水C.平面D.云.标准答案:C30. 5均匀二次B样条曲线各曲线段之间具有阶函数连续性; 2分.标准答案:A31. NURBS曲线表达实现了曲线表达的统一 2分,B样条与解析样条,椭圆与正弦C.同一学科在不同场合的不同称呼而已D.完全不同的学科,两者毫不相干.标准答案:B45. 使用下列二维图形变换矩阵:将产生变换的结果为 2分A.图形放大2倍;B.图形放大2倍,同时沿X、Y坐标轴方向各移动1个绘图单位;C.沿X坐标轴方向各移动2个绘图单位;D.沿X坐标轴方向放大2倍,同时沿X、Y坐标轴方向各平移1个绘图单位;.标准答案:D46. 目前常用的特征表示方法有哪三种 2分A.基于B-rep的表达方法B.基于CSG的表达方法C.基于混合B-rep/CSG的表达方法D.基于主从关系的表达方法.标准答案:A,B,C47. 形位公差所指的是 2分A.形状公差B.位置公差C.平行公差D.垂直公差.标准答案:A,B48. 下列命令中属于编辑命令的有: 2分缩放修剪延伸打断.标准答案:A,B,C,D49. 优化数学模型的三要素是 2分A.设计变量B.设计对象C.约束条件D.目标函数.标准答案:A,C,D50. 平面几何投影可分为两大类,分别是 2分A.透视投影B.正投影C.平行投影D.平面投影.标准答案:A,C51齐次坐标就是把n维向量用维向量表示+1答案:B52STEP标准采用的描述语言是A CB C++C BasicD EXPRESSA AutoCADB Pro/EC UGD CATIA答案:A60三维模型中那种模型可以进行布尔运算A 线框模型B 实心体模型C 表面体模型答案:B61在AutoCAD中,如果0层是当前层,则它不可以被A 关闭和删除B 锁死和关闭C 冻结和锁死D 删除和冻结答案:D62下列关于特征的说法不正确的是A 特征可以表达为:产品特征=形状特征+语义信息B 特征不是体素,是某个或某几个加工表面C 特征是完整的零件D 通过定义简单特征,还可以生成组合特征答案:C63如图所示的模型是A 表面模型B 实体模型C 线框模型D CSG模型答案: C64自由曲线曲面指的是A 直线B 抛物线C NURBS曲线曲面D 直纹面答案: C65B样条曲线采用的是A 显式表示B 隐式表示C 参数形式答案: CC 参数D 混合表达答案:ABC73真实感图形显示在Phong模型基础上,常见的浓淡图绘制算法有A Z-Buffer算法B 扫描线Z-Buffer算法C 画家算法D 区间扫描线算法答案: A,B,D74以下属于现代设计方法的是A 有限元分析B 概率设计C 优化设计D 面向制造的设计答案: A,B,C,D75数据库系统一般由组成;A 硬件B 软件C 数据D 人员答案: A,B,C,D。
权威3DMAX NURBS曲线和曲面教程一、NuRBS曲线作用:可制作圆滑的曲线外形‘Create(创建)‘shape(外形)‘NURBSpoint curve(点曲线)CV curve(控制点曲线):曲线在各控制点连接的多边形内参数:attach(附加):将其它曲线附加到当前曲线中二、NURBS曲面作用:可制作圆滑的面,如汽车外壳,床罩,窗帘丝织物品表面‘create(创建) →‘Geomotry(三维几何体) →‘NurBs surface(NurBs曲面) →‘point surface(点曲面)‘cv surface(控制点曲面)1、point surface(点曲面)参数:u lines:X轴节点数v lines:Y轴节点数次对象:point(点):选择1个顶点(单个):选择一行顶点(单行):选择一列顶点(单列):选择交叉的一行一列顶点(行列):选择所有顶点2、cv suface(控制点曲面)参数:Length cvs:长控制点数Width cvs:宽控制点次对象:与点曲面相同三、NurBs创建工具箱作用:方便创建曲线或者曲面1、Curves(曲线)工具箱第一个():建立cv curve(控制点曲线)第二个():建立Point curve(点曲面)第三个():连接两个顶点,限定在点曲线面类第四个():复制曲线第五个():连接2个顶点,点曲线,CV曲面都可相连第六个():产生曲线的轮廓线第七个():镜像复制曲线3、surface(曲面)工具箱第一个():建立cv surface(控制点曲面)第二个():建立point surface(点曲面)第三个():复制曲面第四个和第九个():将2个曲线连接成面第五个():复制曲面,不能分开第六个():镜向复制曲面第七个():将曲面拉伸成面第八个():将曲线旋转成面3DMAX 第十五讲(材质1)一、材质编辑器作用:赋于物体材质,表现出各种实际效果1、主窗口组成①样本窗②水平工具栏③垂直工具栏④材质名称类型⑤参数展示栏2、样本窗显示方式选择某样本球’→‘5╳3或‘6╳43、垂直工具栏①样本类型:以何种方式显示样本②背光:显示/隐藏样本球暗区光线③背景:检查透明材质效果④重复:检查透明材质效果⑤视频颜色检查:检查材质颜色以适应电视输出⑥材质动画预览⑦选项:设置材质,相关参数⑧按材质选择物体4、水平工具栏(1)获取材质(包括复合标准材质)(2)将冷材质重新赋予场景中的物体(3)将材质赋予场景中被选择的物体(4)清除材质(5)热材质变为冷材质(6)保存材质备以后使用(8)材质效果通道,给材质起编号(9)显示场景中物体的贴图(10)显示最后结果(11)回到父层级(12)到同一层次(13)材质/贴图导航器二、同步材质,异步材质1、同步材质称为热材质,当改变材质参数,场景中的物体材质会同步变化,样本球4个角为白三角形2、异步材质称为冷材质,当改变材质参数,场景中的物体材质不随之变化三、给物体贴图选择物体→(材质编辑器按钮)→选择一个样本球→diffuse(散播颜色) →‘(贴图按钮)→“Bitmap(位图) →选择某图片→‘打开→‘(显示贴图按钮)。
OpenGL编程轻松入门之NURBS曲线和曲面2006-05-22 09:53作者:黄燕出处:天极开发责任编辑:方舟上一节讲了一般的曲线与曲面的绘制,本节讲NURBS曲线和曲面的绘制。
例11:此例绘制两个相同形状的NURBS曲面,不同之处是一个为线框式,一个是由实多边形组成。
运行后可以看到其中的区别,如图十三所示。
#include <windows.h>#include <GL/glut.h>GLUnurbsObj *theNurb1;GLUnurbsObj *theNurb2;GLfloat ctrlpoints[5][5][3] = {{{-3,0.5,0},{-1,1.5,0},{-2,2,0},{1,-1,0},{-5,0,0}},{{-3,0.5,-1},{-1,1.5,-1},{-2,2,-1},{1,-1,-1},{-5,0,-1}},{{-3,0.5,-2},{-1,1.5,-2},{-2,2,-2},{1,-1,-2},{-5,0,-2}},{{-3,0.5,-3},{-1,1.5,-3},{-2,2,-3},{1,-1,-3},{-5,0,-3}},{{-3,0.5,-4},{-1,1.5,-4},{-2,2,-4},{1,-1,-4},{-5,0,-4}}};//控制点GLfloat mat_diffuse[] = {1.0,0.5,0.1,1.0};GLfloat mat_specular[] = {1.0,1.0,1.0,1.0};GLfloat mat_shininess[] = {100.0};GLfloat light_position[] = {0.0,-10.0,0.0,1.0};void myInit(void){glClearColor(1.0,1.0,1.0,0.0);//设置背景色/*为光照模型指定材质参数*/glMaterialfv(GL_FRONT,GL_DIFFUSE,mat_diffuse);glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);glMaterialfv(GL_FRONT,GL_SHININESS,mat_shininess);glLightfv(GL_FRONT,GL_POSITION,light_position);//设置光源参数glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,GL_TRUE);//设置光照模型参数/*激活光照*/glEnable(GL_LIGHTING);glEnable(GL_LIGHT0);glDepthFunc(GL_LEQUAL);glEnable(GL_DEPTH_TEST);glEnable(GL_LEQUAL);glEnable(GL_AUTO_NORMAL);glEnable(GL_NORMALIZE);/*设置特殊效果*/glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);glHint(GL_LINE_SMOOTH_HINT,GL_DONT_CARE);glEnable(GL_BLEND);glFrontFace(GL_CW);glShadeModel(GL_SMOOTH);glEnable(GL_LINE_SMOOTH);theNurb1 = gluNewNurbsRenderer();//创建NURBS对象theNurb1 gluNurbsProperty(theNurb1,GLU_SAMPLING_TOLERANCE,25.0); gluNurbsProperty(theNurb1,GLU_DISPLAY_MODE,GLU_OUTLINE_POLYGON);theNurb2 = gluNewNurbsRenderer();//创建NURBS对象theNurb2 gluNurbsProperty(theNurb2,GLU_SAMPLING_TOLERANCE,25.0); gluNurbsProperty(theNurb2,GLU_DISPLAY_MODE,GLU_FILL);}int spin = 0;/*接收键盘指令*/static void myKey(unsigned char key,int x,int y){switch(key){case'd':spin = spin + 1;glRotatef(spin,1.0,1.0,0.0);glutPostRedisplay();break;case 27:exit(0);default:break;}}/*绘制曲面*/void myDisplay(void){GLfloat knots[10] = {0.0,0.0,0.0,0.0,0.0,1.0,1.0,1.0,1.0,1.0};glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glRotatef(50.0,1.0,1.0,0.0);/*第一个曲面*/glPushMatrix();glTranslatef(1.0,0.0,0.0);gluBeginSurface(theNurb1);/*定义曲面形状*/gluNurbsSurface(theNurb1,10,knots,10,knots,5*3,3,&ctrlpoints[0][0][0],5,5,GL_MAP2_VE RTEX_3);gluEndSurface(theNurb1);glPopMatrix();/*第二个曲面*/glPushMatrix();glTranslatef(7.0,0.0,0.0);gluBeginSurface(theNurb2);/*定义曲面形状*/gluNurbsSurface(theNurb2,10,knots,10,knots,5*3,3,&ctrlpoints[0][0][0],5,5,GL_MAP2_VE RTEX_3);gluEndSurface(theNurb2);glPopMatrix();glutSwapBuffers();}void myReshape(GLsizei w,GLsizei h){glViewport(0,0,w,h);glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(50.0,(GLfloat)w/(GLfloat)h,1.0,15.0);glMatrixMode(GL_MODELVIEW);glLoadIdentity();glTranslatef(0.0,0.0,-9.0);}int main(int argc,char ** argv){/*初始化*/glutInit(&argc,argv);glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB|GLUT_DEPTH); glutInitWindowSize(600,400);glutInitWindowPosition(200,200);/*创建窗口*/glutCreateWindow("NURBS surface");/*绘制与显示*/myInit();glutKeyboardFunc(myKey);glutReshapeFunc(myReshape);glutDisplayFunc(myDisplay);/*进入GLUT事件处理循环*/glutMainLoop();return(0);}·GLUnurbsObj* glNewNurbsRenderer()创建一个NURBS对象,并返回一个指向该对象的指针。
曲线数学NURBS之B样条曲线上一篇博客已经讲到了bezier曲线,本篇接着讲解B样条曲线。
B样条曲线是bezier曲线的更一般化,bezier曲线是B样条曲线的特列。
相比于Bezier曲线,B样条曲线是分段组成的,每一段参数的区间都是[0,1],这就克服了Bezier曲线改变任意一个控制点,曲线上所有的点都要改变的缺点。
B样条曲线的数学公式如下:其中di(i=0,1…n)为控制点,K为规定的基函数的次数,Ni,k(i=0,1…n)即为k次B样条基函数,最高次数为k。
u表示参数序列,即B样条分段函数中的参数。
B样条基函数的公式如下:其中i为节点序号,k是基函数的次数,规定:0/0等于0。
这就是Cox-deBoor算法公式。
节点和控制点是不一样的,满足控制关系m+1=n+k+2.即假如有3个控制点控制的2次B样条曲线,其节点的数量为3+2+2=7.Boehm 给出了节点的插入公式:其中r是新插入的节点t在节点序列中的重复度。
如上图,控制点Pj生成新的控制点Pj’。
B样条曲线总的分为均匀和非均匀的。
根据如上的讲解为了设计一个B-样条曲线,我们需要一系列的控制点,一系列的节点和一系列的系数,每个系数对应一个控制点,所有曲线段连接在一起满足某个连续条件,即为B样条曲线。
有了上边整体的了解,接着从B样条基函数开始讲起,如何根据几个控制点,以及给定的B样条基函数次数k画出B样条曲线。
如上图,基函数的系数定义如图中所述,可以看出,每一个系数范围都为(0,1)区间。
而基函数中的Ni,k(u) 可以表示为如下的杨辉三角形状,比如求第1段区间1次基函数N1,1 就要求出N1,0 和N2,0,其他依次类推。
如下三图为本人从基函数推导出来的B样条曲线。
其中控制点个数为3(n=2),基函数最高次数为2(k=2),则节点总数为m+1=n+k+2=6.推导中,为了便于计算,各个节点赋值分别为0,1,2,3,4,5。
最后得出B样条曲线的每一段的函数表示。
无序B样条曲线的曲面拟合算法1.引言-简要介绍无序B样条曲线-论述无序B样条曲线的曲面拟合问题-描述研究的主要问题和目标2. 相关研究-介绍曲面拟合算法的发展历程-论述其他曲面拟合算法的优缺点-简单介绍无序B样条曲线拟合算法的前置知识3.算法设计-描述无序B样条曲线的定义和性质-详细阐述无序B样条曲线的曲面拟合算法-主要包括控制点的选择、权重函数的设计和优化策略的实现4.实验与结果-利用自己实现的算法,对高维数据集进行实验-对比不同算法的效果,分析无序B样条曲线曲面拟合算法的优点和局限性-通过实例来展示算法的应用5.结论和展望-对论文进行总结,强调无序B样条曲线曲面拟合算法在实际应用中的重要性-提出进一步研究无序B样条曲线算法的方向和可能的改进方案第一章:引言无序B样条曲线是一种广泛应用于计算机图形学和计算几何领域中的数学工具。
与传统Bezier曲线相比,B样条曲线的控制点可以增删、移动,具有更强的灵活性和变形能力。
因此,B样条曲线被广泛应用于CAD设计、工程制图、物理仿真等领域。
曲面拟合是B样条曲线的一个重要应用,也是本文研究的主题。
曲面拟合的目标是根据给定的数据点集,构建一个能够尽可能地代表原始数据点的曲面模型。
通常,数据点集是从真实物体的点云数据中获得的,因此它们往往是不规则、噪声较大的。
曲面拟合算法的目标是以尽可能少的控制点构建合适的曲面模型,以逼近给定的点云数据。
B样条曲线的曲面拟合算法也分为有序B样条曲线拟合和无序B样条曲线拟合两种。
有序B样条曲线是指曲线上的控制点以固定顺序连接,控制点的顺序和其位置决定了曲线的形状和拟合精度。
而无序B样条曲线对控制点的顺序和位置没有限制,因此拟合出的曲线可以更好地与原始点云数据相匹配。
本文主要研究无序B样条曲线的曲面拟合算法,旨在解决无序B样条曲线拟合算法复杂性高、精度难以控制等问题,提升曲面拟合的效率和精度。
本论文内容包括5个章节。
第一章是引言,对无序B样条曲线的曲面拟合做了简要介绍。
B样条曲线是什么?小弟在很多cad的文章中看到B样条曲线,就是不知道到底什么是B样条曲线,希望各位大哥能给小弟一个明确的解释。
谢谢!2003-4-15 22:00 intaNURBS -- Non-Uniform Rational B-Splines中文大致叫“非均匀有理B样条”NURBS是一种描述曲面的 "参数表示法"。
基本上所有的曲面都可以用 polygon,也就是所谓的 "面" 来趋近表现,但绝大部份的东西其实都是平滑的,所以必须用代数式或参数式来表示。
NURBS 即是现在最流形的参数示表式法。
NURBS 基本上是用一组 "control point array" 来表示一个曲面,也就是说只要只定一组 control point 就可以造出一个曲面,而只要调整control point 就可以控制此曲面的形状。
用 NURBS 来拉塑的模型,只要改变其控制点的参数值,即能轻易的改变它的外型,此外,NURBS 只需要几条类似物体剖面的线段或是封闭曲线,即可拉塑出复杂的模型,比如在做人脸或是动物时就十分方便; 此外,因其很容易 Modify,所以在工业设计上也逐渐成为主流。
要特别强调的,Non-Uniform Rational B-Splines 其中的B并不是Bezier Curve,其定义比Bezier Curve还多出一关联项,所以不要把它跟Bezier Curve弄混。
在CAD/CAM中,常采用Bezier曲线曲面,这样便于理解曲线/曲面。
但采用Bezier形式的曲线曲面不能精确的表示二次曲线和二次曲面,如球体和圆。
将多项式改为有理形式,不仅能精确表示二次曲线和二次曲面,且增加了设计的自由度。
重复的进行两点线性插值,可以构造Bezier Curve。
重复的进行两点有理插值,可以构造有理Bezier Curve。
与控制顶点类似,有理Bezter曲线上的点可映射为Bezter曲线上的点或对应的控制多边形上的点。
学习小结:前面学习了Bezier 曲线,B 样条基函数和B 样条曲线的一些基础知识。
掌握关键问题是一条B 样条曲线间的多段曲线的光滑连接。
因为现在是用多段Bezier 曲线来描绘一条B 样条曲线,所以问题变为两段Bezier 曲线间光滑连接。
两段Bezier 曲线段(3次)B1和B2光滑连接的条件:(1).要求B1和B2有共同的连接点,即G 0连续。
(2).要求B1和B2在连接点处有成比例的一阶导数,即G 1连续。
由端点处的一阶导数)(3)0(2),(3)1(10123Q Q B P P B -='-=',为实现G 1连续,则有:)1(1)0(2B B '=' 即:2301P P Q Q -=- 这也表明,1032),(,Q Q P P 三点共线。
如下图表示了一条3次B 样条曲线的所有控制多边形: 1) P 2 P 3P 4 (P 1112)P 5 P 10 0 P 6 P 9 7 P 8 图5.3次B 样条曲线和所有控制多边形图5中,P0至P6为原始3次B 样条曲线控制多边形顶点,P 0至P 12是计算后最终形成B样条曲线控制多边形顶点。
图6.双二次(2x2)B 样条曲面6.B 样条曲线曲面和NURBS 曲线曲面的C 语言实现算法源程序#ifndef _mynurbs_h#ifndef _MYNURBS_H#include "gl\gl.h"#include "math.h"//*-*-*-*-*-*-*-*-*-*-*-*-*-*-* B样条基函数计算部分 *-*-*-*-*-*-*-*-*-*-*-*-*-* //确定参数u所在的节点区间下标//n=m-p-1//m为节点矢量U[]的最大下标//p为B样条函数次数int FindSource(int n,int p,float u,float U[]){int low,high,mid;if(u==U[n+1])//特殊情况return n;//进行二分搜索low=p;high=n+1;mid=(int)(low+high)/2;while(u<U[mid]||u>U[mid]){if(u<U[mid])high=mid;elselow=mid;mid=(int)(low+high)/2;if(u>=U[mid]&&u<U[mid+1])//找到u所在的节点区间的下标break; //退出二分搜索}return mid; //返回区间下标}//计算所有非零B样条基函数并返回其值//i为参数u所在的节点区间下标void BasisFunction(int i,int p,float u,float U[],float N[]){int j,di,dp,k;float tul,tur,left,right;float tmpN[50][50];for(k=0;k<=p;k++){dp=0;for(di=i+p-k;di>=i-k;di--){if(u>=U[di]&&u<U[di+1])tmpN[di][0]=1;elsetmpN[di][0]=0;dp+=1;for(j=1;j<dp;j++){tul=U[di+j]-U[di];tur=U[di+j+1]-U[di+1];if(tul!=0)left=(u-U[di])/tul;elseleft=0;if(tur!=0)right=(U[di+j+1]-u)/tur;elseright=0;tmpN[di][j]=left*tmpN[di][j-1]+right*tmpN[di+1][j-1];}}N[i-k]=tmpN[i-k][p];}}//----------------------------------------------------------------------- //计算基函数的1阶导数并保存在NP[]中//i为参数u所在的节点区间下标//p为B样条函数次数P>2void DerBasisFunc(int i,int p,float u,float U[],float NP[]){int j,di,dp,k;float tul,tur,left,right,saved,dl,dr;float tmpN[50][50];for(k=0;k<=p;k++){dp=0;for(di=i+p-k;di>=i-k;di--){if(u>=U[di]&&u<U[di+1])tmpN[di][0]=1;elsetmpN[di][0]=0;dp+=1;for(j=1;j<dp;j++){tul=U[di+j]-U[di];tur=U[di+j+1]-U[di+1];if(tul!=0)left=(u-U[di])/tul,dl=1/tul;elseleft=0,dl=0;if(tur!=0)right=(U[di+j+1]-u)/tur,dr=1/tur;elseright=0,dr=0;tmpN[di][j]=(left*tmpN[di][j-1]+right*tmpN[di+1][j-1]);saved=p*(dl*tmpN[di][j-1]-dr*tmpN[di+1][j-1])/(p+p-1);}}NP[i-k]=saved;}}//*-*-*-*-*-*-*-*-*-*-*-*-*-* Bezier曲线曲面部分*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*//计算参数u的p次基函数值并存在BC[]中void BernsteinFunc(int p,double t,float BC[]){for(int i=0;i<=p;i++){if(i==0)BC[0]=(float)pow(1-t,p);if(i==p)BC[p]=(float)pow(t,p);if(i>0&&i<p)BC[i]=p*(float)pow(t,i)*(float)pow(1-t,p-i);}}//获取p次Bezier曲线上的lines个点的值void BezierPoint(int p,float px[],float py[],float pz[],int lines,float tmp[][3]) {float BC[20];int i,j;for(j=0;j<=lines;j++){double t=j/(float)lines;BernsteinFunc(p,t,BC);tmp[j][0]=tmp[j][1]=tmp[j][2]=0;for(i=0;i<p+1;i++){tmp[j][0]+=BC[i]*px[i];tmp[j][1]+=BC[i]*py[i];tmp[j][2]+=BC[i]*pz[i];}}}//获取p次有理Bezier曲线上的lines个点的值void NBezierPoint(int p,float px[],float py[],float pz[],float pw[],int lines,float tmp[][4]){float x,y,z,w,BC[20];int i,j;for(j=0;j<=lines;j++){double t=j/(float)lines;BernsteinFunc(p,t,BC);x=y=z=w=0;for(i=0;i<p+1;i++){x+=BC[i]*px[i]*pw[i];y+=BC[i]*py[i]*pw[i];z+=BC[i]*pz[i]*pw[i];w+=BC[i]*pw[i];}tmp[j][0]=x/w;tmp[j][1]=y/w;tmp[j][2]=z/w;tmp[j][3]=w;}}//-----------------------------------------------------------------------------------//绘制p次的Bezier曲线void Bezier(int p,float px[],float py[],float pz[],int lines){float pt[100][3];int j;BezierPoint(p,px,py,pz,lines,pt);for(j=1;j<=lines;j++){glBegin(GL_LINES);glVertex3f(pt[j-1][0],pt[j-1][1],pt[j-1][2]);glVertex3f(pt[j][0],pt[j][1],pt[j][2]);glEnd();}}//------------------------------------------------------------------------------//绘制p次的有理Bezier曲线void NBezier(int p,float px[],float py[],float pz[],float w[],int lines){float pt[100][4];int j;NBezierPoint(p,px,py,pz,w,lines,pt);for(j=1;j<=lines;j++){glBegin(GL_LINES);glVertex3f(pt[j-1][0],pt[j-1][1],pt[j-1][2]);glVertex3f(pt[j][0],pt[j][1],pt[j][2]);glEnd();}}//---------------------------------------------------------------------------------//计算双p次Bezier曲面上所有的点并保存在Pt[][][]中//u和v分别为曲面(u,v)方向上的网格数void BezierFacePoint(int p,int u,int v,float px[][4],float py[][4],float pz[][4],float pt[161][161][3]){float urx[11][161],ury[11][161],urz[11][161];float tx[11],ty[11],tz[11],tmp[161][3];int i,j,k;for(j=0;j<p+1;j++){for(i=0;i<p+1;i++){tx[i]=px[i][j];ty[i]=py[i][j];tz[i]=pz[i][j];}BezierPoint(p,tx,ty,tz,v,tmp);for(k=0;k<=v;k++){urx[j][k]=tmp[k][0];ury[j][k]=tmp[k][1];urz[j][k]=tmp[k][2];}}for(i=0;i<=v;i++){for(k=0;k<p+1;k++){tx[k]=urx[k][i];ty[k]=ury[k][i];tz[k]=urz[k][i];}BezierPoint(p,tx,ty,tz,u,tmp);for(j=0;j<=u;j++){pt[i][j][0]=tmp[j][0];pt[i][j][1]=tmp[j][1];pt[i][j][2]=tmp[j][2];}}}//--------------------------------------------------------------------------------//计算双p次有理Bezier曲面上所有的点并保存在Pt[][][]中//u和v分别为曲面(u,v)方向上的网格数void NuBezierFacePoint(int p,int u,int v,float px[][4],float py[][4],float pz[][4],float w[][4],float pt[161][161][3]){float urx[11][161],ury[11][161],urz[11][161],urw[11][161];float tx[11],ty[11],tz[11],tw[11],tmp[161][4];int i,j,k;for(j=0;j<p+1;j++){for(i=0;i<p+1;i++){tx[i]=px[i][j];ty[i]=py[i][j];tz[i]=pz[i][j];tw[i]=w[i][j];}NBezierPoint(p,tx,ty,tz,tw,v,tmp);for(k=0;k<=v;k++){urx[j][k]=tmp[k][0];ury[j][k]=tmp[k][1];urz[j][k]=tmp[k][2];urw[j][k]=tmp[k][3];}}for(i=0;i<=v;i++){for(k=0;k<p+1;k++){tx[k]=urx[k][i];ty[k]=ury[k][i];tz[k]=urz[k][i];tw[k]=urw[k][i];}NBezierPoint(p,tx,ty,tz,tw,u,tmp);for(j=0;j<=u;j++){pt[i][j][0]=tmp[j][0];pt[i][j][1]=tmp[j][1];pt[i][j][2]=tmp[j][2];}}}//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* B样条曲线曲面部分-*-*-*-*-*-*-*-*-*-*-*-*-*-*-//计算样条曲线的1阶导矢(u所对应的所有点)保存在Der[]中//n=m-p-1//p为曲线的次数void BSplineDer(int n,int p,float U[],float P[],float Der[]){float N[100],tmp;int i,j;for(i=p+1;i<=n;i++){DerBasisFunc(i,p,U[i],U,N);tmp=0;for(j=i;j>=i-p;j--)tmp+=N[j]*P[j];Der[i-p]=tmp;}}//计算曲线上的点(u所对应的所有点)保存在Poi[]中//n=m-p-1//p为曲线的次数void BSplinePoint(int n,int p,float U[],float P[],float Poi[]) {float N[100],tmp;int i,j;for(i=p+1;i<=n;i++){BasisFunction(i,p,U[i],U,N);tmp=0;for(j=i;j>=i-p;j--)tmp+=N[j]*P[j];Poi[i-p]=tmp;}}//计算3次样条曲线上的所有控制多边形保存在CP[]中//m为节点矢量U[]的最大下标void B3SplineControlPoint(int m,float U[],float P[],float CP[]) {int n,k,i,cp,p;float Poi[100],Der[100],add;p=3;n=m-p-1;BSplinePoint(n,p,U,P,Poi);BSplineDer(n,p,U,P,Der);cp=(n-p)*3+p;for(i=0;i<2;i++){CP[i]=P[i];CP[cp-i]=P[n-i];}for(i=3;i<cp-1;i+=3){k=(int)i/3;add=Der[k]/p;CP[i]=Poi[k];CP[i-1]=CP[i]-add;CP[i+1]=CP[i]+add;}}//计算2次样条曲线上的所有控制多边形保存在CP[]中//m为节点矢量U[]的最大下标void B2SplineControlPoint(int m,float U[],float P[],float CP[]) {int n,k,tm,i,cp,p;float Poi[100];p=2;n=m-p-1;BSplinePoint(n,p,U,P,Poi);cp=(n-p)*2+p;for(i=0;i<2;i++)CP[i]=P[i];CP[cp]=P[n];tm=2;for(i=2;i<cp-1;i+=2){k=(int)i/2;CP[i]=Poi[k];CP[i+1]=P[tm];tm++;}}//绘制3次B样条曲线//m为节点矢量U[]的最大下标void BSpline3L(int m,float U[],float px[],float py[],float pz[]) {float pcx[100],pcy[100],pcz[100],drx[4],dry[4],drz[4];int i,j,tmcp;B3SplineControlPoint(m,U,px,pcx);B3SplineControlPoint(m,U,py,pcy);B3SplineControlPoint(m,U,pz,pcz);/*glColor3f(0.0f,0.0f,0.0f);for(i=1;i<3*m-17;i++){glBegin(GL_LINES);glVertex3f(pcx[i-1],pcy[i-1],pcz[i-1]);glVertex3f(pcx[i],pcy[i],pcz[i]);glEnd();}glColor3f(1.0f,0.0f,0.0f);*/tmcp=m-7;for(i=0;i<=tmcp;i++){for(j=i*3;j<i*3+4;j++){drx[j-i*3]=pcx[j];dry[j-i*3]=pcy[j];drz[j-i*3]=pcz[j];}Bezier(3,drx,dry,drz,20);}}//绘制2次B样条曲线//m为节点矢量U[]的最大下标void BSpline2L(int m,float U[],float px[],float py[],float pz[]){float pcx[100],pcy[100],pcz[100],drx[3],dry[3],drz[3];int i,j,tmcp;B2SplineControlPoint(m,U,px,pcx);B2SplineControlPoint(m,U,py,pcy);B2SplineControlPoint(m,U,pz,pcz);tmcp=m-5;for(i=0;i<=tmcp;i++){for(j=i*2;j<i*2+3;j++){drx[j-i*2]=pcx[j];dry[j-i*2]=pcy[j];drz[j-i*2]=pcz[j];}Bezier(2,drx,dry,drz,20);}}//计算双三次(3x3)B样条曲面所有控制多边形顶点,并保存在pt[][][]中//mu,mv分别为节点矢量U[],V[]的最大下标值void BS3FaceControlPoint(int mu,float U[],int mv,float V[],float px[],float py[],float pz[],float pt[100][100][3]){int i,j,k,dp;float tmx[50],tmy[50],tmz[50];float tmpx[50][100],tmpy[50][100],tmpz[50][100];float uvx[100][100],uvy[100][100],uvz[100][100];for(i=0;i<mv-3;i++){dp=i*(mu-3);for(j=dp;j<mu-3+dp;j++){tmx[j-dp]=px[j];tmy[j-dp]=py[j];tmz[j-dp]=pz[j];}B3SplineControlPoint(mu,U,tmx,tmpx[i]);B3SplineControlPoint(mu,U,tmy,tmpy[i]);B3SplineControlPoint(mu,U,tmz,tmpz[i]);}for(i=0;i<3*mu-17;i++){for(j=0;j<mv-3;j++){tmx[j]=tmpx[j][i];tmy[j]=tmpy[j][i];tmz[j]=tmpz[j][i];}B3SplineControlPoint(mv,V,tmx,uvx[i]);B3SplineControlPoint(mv,V,tmy,uvy[i]);B3SplineControlPoint(mv,V,tmz,uvz[i]);for(k=0;k<3*mv-17;k++){pt[i][k][0]=uvx[i][k];pt[i][k][1]=uvy[i][k];pt[i][k][2]=uvz[i][k];}}}//计算双二次(2x2)B样条曲面所有控制多边形顶点,并保存在pt[][][]中//mu,mv分别为节点矢量U[],V[]的最大下标值void BS2FaceControlPoint(int mu,float U[],int mv,float V[],float px[],float py[],float pz[],float pt[100][100][3]){int i,j,k,dp;float tmx[50],tmy[50],tmz[50];float tmpx[50][100],tmpy[50][100],tmpz[50][100];float uvx[100][100],uvy[100][100],uvz[100][100];for(i=0;i<mv-2;i++){dp=i*(mu-2);for(j=dp;j<mu-2+dp;j++){tmx[j-dp]=px[j];tmy[j-dp]=py[j];tmz[j-dp]=pz[j];}B2SplineControlPoint(mu,U,tmx,tmpx[i]);B2SplineControlPoint(mu,U,tmy,tmpy[i]);B2SplineControlPoint(mu,U,tmz,tmpz[i]);}for(i=0;i<2*mu-7;i++){for(j=0;j<mv-2;j++){tmx[j]=tmpx[j][i];tmy[j]=tmpy[j][i];tmz[j]=tmpz[j][i];}B2SplineControlPoint(mv,V,tmx,uvx[i]);B2SplineControlPoint(mv,V,tmy,uvy[i]);B2SplineControlPoint(mv,V,tmz,uvz[i]);for(k=0;k<2*mv-7;k++){pt[i][k][0]=uvx[i][k];pt[i][k][1]=uvy[i][k];pt[i][k][2]=uvz[i][k];}}}//-------------------------------------------------------------------------------//设置网格数void SetGridCount(int dt,int tu,int tmk[]){int i,tm;tm=tu%dt;for(i=0;i<dt-1;i++)tmk[i]=(tu-tm)/dt;tmk[dt-1]=tmk[0]+tm;}//------------------------------------------------------------------------------//计算双三次(3x3次)或双二次(2x2次)B样条曲面上所有的点并保存在bs[][][]中//nu,mv分别为节点矢量U[],V[]的最大下标//uk,vk分别为B样条曲面(u,v)方向上的网格数//p为曲面的次数void BSplineFace(int p,int nu,float U[],int uk,int mv,float V[],int vk,float px[],float py[],float pz[],float bs[161][161][3]) {int udk[20],vdk[20],i,j,k,l,hu,sv,du,dv;float tp[100][100][3],td[161][161][3];float tmx[4][4],tmy[4][4],tmz[4][4];du=nu-2*p;dv=mv-2*p;SetGridCount(du,uk,udk);SetGridCount(dv,vk,vdk);if(p==3)BS3FaceControlPoint(nu,U,mv,V,px,py,pz,tp);if(p==2)BS2FaceControlPoint(nu,U,mv,V,px,py,pz,tp);for(i=0;i<dv;i++){for(k=0;k<du;k++){for(j=i*p;j<p+1+i*p;j++)for(l=k*p;l<p+1+k*p;l++){tmx[j-i*p][l-k*p]=tp[l][j][0];tmy[j-i*p][l-k*p]=tp[l][j][1];tmz[j-i*p][l-k*p]=tp[l][j][2];}BezierFacePoint(p,udk[k],vdk[i],tmx,tmy,tmz,td);for(sv=i*vdk[0];sv<=vdk[i]+i*vdk[0];sv++)for(hu=k*udk[0];hu<=udk[k]+k*udk[0];hu++){bs[sv][hu][0]=td[sv-i*vdk[0]][hu-k*udk[0]][0];bs[sv][hu][1]=td[sv-i*vdk[0]][hu-k*udk[0]][1];bs[sv][hu][2]=td[sv-i*vdk[0]][hu-k*udk[0]][2];}}}}//-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Nurbs 样条曲线曲面部分-*-*-*-*-*-*-*-*-*-*-*-*-*-*-//计算Nurbs曲线上的点(u所对应的所有点)保存在Poi[]中//n=m-p-1//p为曲线的次数void NurbsPoint(int n,int p,float U[],float P[],float W[],float Poi[]) {float N[100],tmp,tmw;int i,j;for(i=p+1;i<=n;i++){BasisFunction(i,p,U[i],U,N);tmp=0;tmw=0;for(j=i;j>=i-p;j--){tmp+=N[j]*P[j]*W[j];tmw+=N[j]*W[j];}Poi[i-p]=tmp/tmw;}}//计算Nurbs曲线的1阶导矢(u所对应的所有点)保存在Der[]中//n=m-p-1//p为曲线的次数void NurbsDer(int n,int p,float U[],float P[],float W[],float Der[]) {float N[100],CP[100],NW[100],tmp,tw;int i,j;NurbsPoint(n,p,U,P,W,CP);BSplinePoint(n,p,U,W,NW);for(i=p+1;i<=n;i++){DerBasisFunc(i,p,U[i],U,N);tmp=0;tw=0;for(j=i;j>=i-p;j--){tmp+=N[j]*P[j]*W[j];tw+=N[j]*W[j];}Der[i-p]=(tmp-tw*CP[i-p])/NW[i-p];}}//计算3次Nurbs曲线上的所有控制多边形保存在CP[]中//m为节点矢量U[]的最大下标void Nurbs3ControlPoint(int m,float U[],float P[],float W[],float CP[]) {int n,k,i,cp,p;float Poi[100],Der[100],add;p=3;n=m-p-1;NurbsPoint(n,p,U,P,W,Poi);NurbsDer(n,p,U,P,W,Der);cp=(n-p)*3+p;for(i=0;i<2;i++){CP[i]=P[i];CP[cp-i]=P[n-i];}for(i=3;i<cp-1;i+=3){k=(int)i/3;add=Der[k]/p;CP[i]=Poi[k];CP[i-1]=CP[i]-add;CP[i+1]=CP[i]+add;}}//计算2次Nurbs曲线上的所有控制多边形保存在CP[]中//m为节点矢量U[]的最大下标void Nurbs2ControlPoint(int m,float U[],float P[],float W[],float CP[]) {int n,k,tm,i,cp,p;float Poi[100];p=2;n=m-p-1;NurbsPoint(n,p,U,P,W,Poi);cp=(n-p)*2+p;for(i=0;i<2;i++)CP[i]=P[i];CP[cp]=P[n];tm=2;for(i=2;i<cp-1;i+=2){k=(int)i/2;CP[i]=Poi[k];CP[i+1]=P[tm];tm++;}}//绘制3次Nurbs样条曲线//m为节点矢量U[]的最大下标void Nurbs3L(int m,float U[],float px[],float py[],float pz[],float W[]) {float pcx[100],pcy[100],pcz[100],drx[4],dry[4],drz[4];float pcw[100],drw[4];int i,j,tmcp;Nurbs3ControlPoint(m,U,px,W,pcx);Nurbs3ControlPoint(m,U,py,W,pcy);Nurbs3ControlPoint(m,U,pz,W,pcz);B3SplineControlPoint(m,U,W,pcw);tmcp=m-7;for(i=0;i<=tmcp;i++){for(j=i*3;j<i*3+4;j++){drx[j-i*3]=pcx[j];dry[j-i*3]=pcy[j];drz[j-i*3]=pcz[j];drw[j-i*3]=pcw[j];}NBezier(3,drx,dry,drz,drw,20);}}//绘制2次Nurbs样条曲线//m为节点矢量U[]的最大下标void Nurbs2L(int m,float U[],float px[],float py[],float pz[],float W[]) {float pcx[100],pcy[100],pcz[100],drx[3],dry[3],drz[3];float pcw[100],drw[3];int i,j,tmcp;Nurbs2ControlPoint(m,U,px,W,pcx);Nurbs2ControlPoint(m,U,py,W,pcy);Nurbs2ControlPoint(m,U,pz,W,pcz);B2SplineControlPoint(m,U,W,pcw);tmcp=m-5;for(i=0;i<=tmcp;i++){for(j=i*2;j<i*2+3;j++){drx[j-i*2]=pcx[j];dry[j-i*2]=pcy[j];drz[j-i*2]=pcz[j];drw[j-i*2]=pcw[j];}NBezier(2,drx,dry,drz,drw,20);}}//计算双三次(3x3)Nurbs样条曲面所有控制多边形顶点,并保存在pt[][][]中//mu,mv分别为节点矢量U[],V[]的最大下标值void Nurbs3FControlPoint(int mu,float U[],int mv,float V[],float px[],float py[],float pz[],float W[],float pt[100][100][4]){int i,j,k,dp;float tmx[50],tmy[50],tmz[50],tmw[50];float tmpx[50][100],tmpy[50][100],tmpz[50][100],tmpw[50][100];float uvx[100][100],uvy[100][100],uvz[100][100],uvw[100][100];for(i=0;i<mv-3;i++){dp=i*(mu-3);for(j=dp;j<mu-3+dp;j++){tmx[j-dp]=px[j];tmy[j-dp]=py[j];tmz[j-dp]=pz[j];tmw[j-dp]=W[j];}Nurbs3ControlPoint(mu,U,tmx,tmw,tmpx[i]);Nurbs3ControlPoint(mu,U,tmy,tmw,tmpy[i]);Nurbs3ControlPoint(mu,U,tmz,tmw,tmpz[i]);B3SplineControlPoint(mu,U,tmw,tmpw[i]);}for(i=0;i<3*mu-17;i++){for(j=0;j<mv-3;j++){tmx[j]=tmpx[j][i];tmy[j]=tmpy[j][i];tmz[j]=tmpz[j][i];tmw[j]=tmpw[j][i];}Nurbs3ControlPoint(mv,V,tmx,tmw,uvx[i]);Nurbs3ControlPoint(mv,V,tmy,tmw,uvy[i]);Nurbs3ControlPoint(mv,V,tmz,tmw,uvz[i]);B3SplineControlPoint(mv,V,tmw,uvw[i]);for(k=0;k<3*mv-17;k++){pt[i][k][0]=uvx[i][k];pt[i][k][1]=uvy[i][k];pt[i][k][2]=uvz[i][k];pt[i][k][3]=uvw[i][k];}}}//计算双二次(2x2)Nurbs样条曲面所有控制多边形顶点,并保存在pt[][][]中//mu,mv分别为节点矢量U[],V[]的最大下标值void Nurbs2FControlPoint(int mu,float U[],int mv,float V[],float px[],float py[],float pz[],float W[],float pt[100][100][4]){int i,j,k,dp;float tmx[50],tmy[50],tmz[50],tmw[50];float tmpx[50][100],tmpy[50][100],tmpz[50][100],tmpw[50][100];float uvx[100][100],uvy[100][100],uvz[100][100],uvw[100][100];for(i=0;i<mv-2;i++){dp=i*(mu-2);for(j=dp;j<mu-2+dp;j++){tmx[j-dp]=px[j];tmy[j-dp]=py[j];tmz[j-dp]=pz[j];tmw[j-dp]=W[j];}Nurbs2ControlPoint(mu,U,tmx,tmw,tmpx[i]);Nurbs2ControlPoint(mu,U,tmy,tmw,tmpy[i]);Nurbs2ControlPoint(mu,U,tmz,tmw,tmpz[i]);B2SplineControlPoint(mu,U,tmw,tmpw[i]);}for(i=0;i<2*mu-7;i++){for(j=0;j<mv-2;j++){tmx[j]=tmpx[j][i];tmy[j]=tmpy[j][i];tmz[j]=tmpz[j][i];tmw[j]=tmpw[j][i];}Nurbs2ControlPoint(mv,V,tmx,tmw,uvx[i]);Nurbs2ControlPoint(mv,V,tmy,tmw,uvy[i]);Nurbs2ControlPoint(mv,V,tmz,tmw,uvz[i]);B2SplineControlPoint(mv,V,tmw,uvw[i]);for(k=0;k<2*mv-7;k++){pt[i][k][0]=uvx[i][k];pt[i][k][1]=uvy[i][k];pt[i][k][2]=uvz[i][k];pt[i][k][3]=uvw[i][k];}}}//------------------------------------------------------------------------------//计算双三次(3x3次)或双二次(2x2次)Nurbs样条曲面上所有的点并保存在bs[][][]中//nu,mv分别为节点矢量U[],V[]的最大下标//uk,vk分别为B样条曲面(u,v)方向上的网格数//p为曲面的次数void NurbsFace(int p,int nu,float U[],int uk,int mv,float V[],int vk,float px[],float py[],float pz[],float w[],float bs[161][161][3]){int udk[20],vdk[20],i,j,k,l,hu,sv,du,dv;float tp[100][100][4],td[161][161][3];float tmx[4][4],tmy[4][4],tmz[4][4],tmw[4][4];du=nu-2*p;dv=mv-2*p;SetGridCount(du,uk,udk);SetGridCount(dv,vk,vdk);if(p==3)Nurbs3FControlPoint(nu,U,mv,V,px,py,pz,w,tp);if(p==2)Nurbs2FControlPoint(nu,U,mv,V,px,py,pz,w,tp);for(i=0;i<dv;i++){for(k=0;k<du;k++){for(j=i*p;j<p+1+i*p;j++)for(l=k*p;l<p+1+k*p;l++){tmx[j-i*p][l-k*p]=tp[l][j][0];tmy[j-i*p][l-k*p]=tp[l][j][1];tmz[j-i*p][l-k*p]=tp[l][j][2];tmw[j-i*p][l-k*p]=tp[l][j][3];}NuBezierFacePoint(p,udk[k],vdk[i],tmx,tmy,tmz,tmw,td);for(sv=i*vdk[0];sv<=vdk[i]+i*vdk[0];sv++)for(hu=k*udk[0];hu<=udk[k]+k*udk[0];hu++){bs[sv][hu][0]=td[sv-i*vdk[0]][hu-k*udk[0]][0];bs[sv][hu][1]=td[sv-i*vdk[0]][hu-k*udk[0]][1];bs[sv][hu][2]=td[sv-i*vdk[0]][hu-k*udk[0]][2];}}}}//*-*-*-*-*-*-*-*-*-*-*-*-*-*-* 绘制曲面部分*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*//计算多边形的外法线返回值tmN[]void getN(float x[3],float y[3],float z[3],float tmN[3]){float p1,p2,p3,q1,q2,q3;float nx,ny,nz;p1=x[1]-x[0];p2=y[1]-y[0];p3=z[1]-z[0];q1=x[2]-x[1];q2=y[2]-y[1];q3=z[2]-z[1];nx=p2*q3-q2*p3;ny=q1*p3-p1*q3;nz=p1*q2-p2*q1;tmN[0]=nx;tmN[1]=ny;tmN[2]=nz;}//-----------------------------------------------------------------------------------//显示B样条曲面//fill取值为0或1void ShowSurface(int u,int v,float bs[161][161][3],int fill){int i,j;float x[3],y[3],z[3],tmn[3];for(i=0;i<=v;i++)for(j=0;j<=u;j++){if(fill!=0){x[0]=bs[i][j][0];x[1]=bs[i+1][j][0];x[2]=bs[i+1][j+1][0];y[0]=bs[i][j][1];y[1]=bs[i+1][j][1];y[2]=bs[i+1][j+1][1];z[0]=bs[i][j][2];z[1]=bs[i+1][j][2];z[2]=bs[i+1][j+1][2];getN(x,y,z,tmn);glEnable(GL_NORMALIZE);glBegin(GL_QUADS);glNormal3f(tmn[0],tmn[1],tmn[2]);if(j<u){glVertex3f(bs[i][j][0],bs[i][j][1],bs[i][j][2]);glVertex3f(bs[i][j+1][0],bs[i][j+1][1],bs[i][j+1][2]);}if(i<v){glVertex3f(bs[i+1][j+1][0],bs[i+1][j+1][1],bs[i+1][j+1][2]);glVertex3f(bs[i+1][j][0],bs[i+1][j][1],bs[i+1][j][2]);}glEnd();glDisable(GL_NORMALIZE);}else{glBegin(GL_LINES);if(j<u){glVertex3f(bs[i][j][0],bs[i][j][1],bs[i][j][2]);glVertex3f(bs[i][j+1][0],bs[i][j+1][1],bs[i][j+1][2]);}if(i<v){glVertex3f(bs[i][j][0],bs[i][j][1],bs[i][j][2]);glVertex3f(bs[i+1][j][0],bs[i+1][j][1],bs[i+1][j][2]);}glEnd();}}}#endif#endif建立库文件“myNurbs.h”保存在include目录下,在文件开始处写上#include "myNurbs.h"即可用各函数的功能。