大家好,又见面了,我是你们的朋友全栈君。
关键字:NURBS,基函数,控制点,节点,
另一个讲的很好的 https://www.cnblogs.com/icmzn/p/5100761.html
看了网上很多相关资料才得以下笔,资料太多,这里就不一一列举了,感谢各位大佬的资料
本博客顺序不太好,看前面的东西可能需要提前看后面的东西。正在努力修炼,敬请谅解
写了个B样条曲线计算的完成程序,包括绘图,https://download.csdn.net/download/qq_40597317/10646881,BaseFunction部分参考了https://www.cnblogs.com/nobodyzhou/p/5451528.html 侵删 重点就是由于规定了0/0=0,所以最需要注意的地方,原作者的思路是如果除数为0,就让除数为1,然后继续运算。这个思路真的很棒,如果被除数为0的话,那么结果就是0,否则的话结果就是被除数了。显然也没有人要求到这点。运行图像结果如下:
一、定义
1.1 概述
是B-样条基曲线(给定区间上的所有样条函数组成一个线性空间。这个线性空间的基函数就叫做B样条基函数)的线性组合。
B-样条是贝兹曲线的一种一般化,B样条不能表示一些基本的曲线,比如圆,所以引入了NURBS,可以进一步推广为非均匀有理B-样条(NURBS)。三者关系可以表示为:
细分定义域
直接细分(Subdividing)曲线是很困难的。因此,我们细分曲线的定义域。因此,如果曲线的定义域是[0,1],这个闭区间被称为节点(knots)的点细分而成。设这些节点是 0 <= u0 <= u1 <= … <= um <= 1。那么点C(ui)的曲线细分如下图所示,因此,修改[0,1]的细分会改变曲线的形状。
如下图,这里有5段曲线组成了整个曲线。下面的直线定义域为[0,1],就是[0,1]被分成五段
可以看出,这里定义域被节点细分,节点分别是0, 0.2, 0.4, 0.6, 0.8,1,6个节点正好可以把定义域(即下面的黑色线段)分成5段。
可以看出,6个节点分别对应于曲线上的一个点,可以用代表对应的曲线上的点,被称为节点点(knot point),节点点把B-样条曲线划分成5个曲线段,每个都定义在一个节点区间上。这些曲线段都是 p 次的贝塞尔曲线。
节点(knots)
有
那么被称为节点,显然上述的m=5
设U是m+1个非递减数的集合,那么有,集合U称为节点向量(knot vector)。
如果,那么是一个重复度(multiplicity)为k的多重节点,k>1,否则如果一个节点只出现一次,那么这就 是一个简单节点。如果节点等间距,节点向量或节点序列称为均匀的;否则它是非均匀的。
是第i节点个区间,i=0,1,…,m
所有的B样条基函数都被假设在定义域上,通常为0,为1
1.2 组成
总之,为了设计一个B-样条曲线,我们需要一系列的控制点(就是下图折线的连接点,一共8个),一系列的节点和一系列的系数,每个系数对应一个控制点,所以所有曲线段连接在一起满足某个连续 条件。系数的计算可能是最复杂的步骤因为它们必须保证某个连续条件。
将多个贝塞尔曲线连接就可以得到B样条。
如下图所示,这里有8个控制点,依次用线段连接,B样条曲线由一系列5条3次的贝塞尔曲线连接形成。
一般次数越低(即p越小),那么B样条曲线就更容易逼近他的控制折线
二、特点
2.1 一般不经过控制点
B样条由一系列控制点决定,但是B样条不会经过其控制点。
2.2 分段
以上所有的分段都为Bezier曲线,对于分段Bezier曲线,不同的曲线段相互独立,移动控制点只会影响其所在的Bezier曲线段,而其他的Bezier曲线段都不会改变,甚至所有关于Bezier曲线的算法可以同样地适用于分段Bezier曲线。
核心思想就是:用分段低阶多项式通过连续的连接来代替高阶多项式
2.3 与Bezier对比
Bezier曲线/曲面不支持局部的修改和编辑;
Bezier曲线/曲面拼接时,满足几何连续条件是十分困难的。
三、数学表达
3.1 一般表达
有n+1个控制点Pi(i=0,1,…,n)和一个节点向量,依次连接这些控制点可以构成一个特征多边形,k+1阶(k次)B样条曲线的表达式为(2<=k<=n+1),必须满足m=n+k+1
其中是k次B样条基函数,也叫调和函数,或者 k次规范B样条基函数,下面为其递归公式(这个公式叫Cox-de Boor)的定义
显然,基函数由U定义,其中基函数满足微分方程:
上图是基函数的运算关系,从左向右,从上往下可以依次计算各个基函数
基函数:
基函数只在附近的一个子区间非0,这就是局部的概念。(不明白的)
基函数表示基函数的次数(degree)为k,这是第i个k次B样条基函数,i=0,1,…
四、性质
4.1 基函数的性质
1. 局部支撑性
若,那么
2.
在任意给定节点区间,最多p+1个非零,分别是
3.非负性
4.规范性
任意给定节点区间,时
可微性
在节点内部,无限次可微,时,
4.2 凸包包含
样条曲线包含在控制折线(ployline)的凸包内。更特别地,如果u 在节点区间[ui,ui+1)里,那么C(u)在控制点Pi-p, Pi-p+1, …, Pi的凸包里。
4.3 Pi 只影响在区间[ui, ui+p+1)上的曲线 C(u)。
五、分类(根据节点向量中节点的分布)
5.1 均匀B样条曲线
(这里的节点可以理解为控制点)
节点成等差数列均匀分布
5.2 准均匀B样条曲线
两端节点0,1重复度为次数k的基础上加1,即k+1,即,所有内部节点重复度为k+1.
显然,首尾两边是相切的
5.3 分段Bezier曲线
两端节点重复度为k+1,内部节点重复度为k,显然此时必须满足条件(m-1)%k==0
5.4 非均匀B样条
任意选取的一个序列[u0,…,um],只要在数学上成立即可,这是最一般的情况
六、计算B样条上的一点的值
7.1 修改曲线的形状
可以修改一个或多个控制参数:控制点的位置(n+1),节点位置(m+1),和曲线的次数p。
一般为开(open )B-样条曲线,也就是产生的曲线不会与控制折线(polyline)的第一边(leg)和最后一边(leg)接触,如下图,对于开曲线,区间不会有基函数的完全支持(“full support”),就是指在这些区间上,只有一个非零基函数。所以有以下结论,对于开B样条曲线,定义域为
强制第一个节点和最后一个节点的重复度为p+1,那么产生的曲线就会分别与第一个控制点和最后一个控制点的第一边和最后一边相切,如下图,这是clamped B-样条曲线。注意,Clamped B-样条曲线C(u)通过首尾两个控制点 P0 和Pn
通过重复某些节点和控制点,产生的曲线会是 闭(closed)曲线。会产生闭环,如下图
如何产生闭曲线?
1.Wrapping控制点
(1)设计一个均匀 m+1 个节点的节点序列:u0 = 0, u1 = 1/m, u1 = 2/m, …, um = 1。注意曲线的定义域是 [up, un-p].
(2)Wrap头p 个和最后p 个控制点。更准确地,设P0 = Pn–p+1, P1 = Pn–p+2, …, Pp-2 = Pn-1 and Pp-1 = Pn.
构建的曲线在连接点处 C(up) = C(un-p)是Cp-1 连续的。.
1.Wrapping节点
1)增加一个新控制点 Pn+1 = P0.因此,控制点的数目是 n+2.
(2)找到一个合适的有 n+1节点的节点序列u0, u1, …, un 。这些节点不必要是均匀的
(3)增加 p+2 个节点并 wrap 头 p+2个节点: un+1 = u0, un+2 = u1, …, un+p = up-1, un+p+1 = up, un+p+2 = up+1 ,如下图所示。这样,我们有n+p+2 = (n+1) + p + 1 个节点
(4)定义在上述构建的 n+1个控制点和n+p+2 个节点上的 p 次开B-样条曲线C(u)是一个闭曲线,在连接点处C(u0) = C(un+1)有Cp-1 连续性。注意闭曲线的定义域是 [u0, un+1]
七、例子
7.1 简单节点
节点向量是U = { 0, 0.25, 0.5, 0.75, 1 }
7.2 带正重复度的节点
这个比较简单,略略略
(4)后面的主要是B样条曲线的一些性质,暂时用不到,后续更新
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/150359.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...