转载自:http://blog.csdn.net/Mr_Grit/article/details/45603627

B样条曲线

B样条曲线定义

B样条方法具有表示与设计自由型曲线曲面的强大功能,是形状数学描述的主流方法之一,另外B样条方法是目前工业产品几何定义国际标准——有理B样条方法(NURBS)的基础。B样条方法兼备了Bezier方法的一切优点,包括几何不变性,仿射不变性等等,同时克服了Bezier方法中由于整体表示带来不具有局部性质的缺点(移动一个控制顶点将会影响整个曲线)。B样条曲线方程可写为:

p(u)=∑i=0ndiNi,k(u)

其中, di(i=0,1...n) 为控制顶点(坐标), Ni,k(i=0,1...n) 为 k 次规范B样条基函数,最高次数是 k 。基函数是由一个称为节点矢量的非递减参数 u 的序列 U : u0≤u1≤...≤un+k+1 所决定的 k 次分段多项式。 
B样条的基函数通常采用Cox-deBoor递推公式:

⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪Ni,0(u)={1,  if  ui≤u≤ui+10,  othersNi,k=u−uiui+k−uiNi,k−1(u)+ui+k+1−uui+k+1−ui+1Ni+1,k−1(u)define  00=0

式中  i  为节点序号,  k  是基函数的次数,共有 n+1 个控制顶点。 注意区分节点和控制顶点,节点是在节点矢量U中取得,控制顶点则是坐标点,决定B样条的控制多边形 。Cox-deBoor递推公式是B样条曲线的定义的核心,该部分在程序中实现可采用递归的方式:

% BaseFunction.m文件
function Nik_u = BaseFunction(i, k , u, NodeVector)
% 计算基函数Ni,k(u),NodeVector为节点向量if k == 0       % 0次B样条if (u >= NodeVector(i+1)) && (u < NodeVector(i+2))Nik_u = 1.0;elseNik_u = 0.0;end
elseLength1 = NodeVector(i+k+1) - NodeVector(i+1);Length2 = NodeVector(i+k+2) - NodeVector(i+2);      % 支撑区间的长度if Length1 == 0.0       % 规定0/0 = 0Length1 = 1.0;endif Length2 == 0.0Length2 = 1.0;endNik_u = (u - NodeVector(i+1)) / Length1 * BaseFunction(i, k-1, u, NodeVector) ...+ (NodeVector(i+k+2) - u) / Length2 * BaseFunction(i+1, k-1, u, NodeVector);
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

所给程序可用于计算基函数Ni,k(u)的值,程序中对不同类型的B样条曲线区别在于节点矢量 NodeVector 的取值不同。

B样条曲线的分类

根据节点矢量中节点的分布情况不同,可以划分4中类型的B样条曲线:

1. 均匀B样条曲线 
节点矢量中节点为沿参数轴均匀或等距分布。 
2. 准均匀B样条曲线 
其节点矢量中两端节点具有重复度k+1,即u0=u1=...=uk,un+1=un+2=...=un+k+1,所有的内节点均匀分布,具有重复度1。 
3. 分段Bezier曲线 
其节点矢量中两端节点的重复度与类型2相同,为k+1。不同的是内节点重复度为k。该类型有限制条件,控制顶点数减1必须等于次数的正整数倍,即nk=正整数。 
4. 一般非均匀B样条曲线 
对任意分布的节点矢量U=[u0,u1...un+k+1],只要在数学上成立都可选取。

B样条曲线的绘制

节点矢量的确定

不同类型的B样条曲线区别主要在于节点矢量,对于具有n+1个控制顶点(P0,P1,...,Pn)的 k 次B样条曲线,无论是哪种类型都具有n+k+2个节点([u0,u1...un+k+1])。

根据图示,三种类型的B样条曲线对应的节点矢量分别为:

[01727374757671]
[0 0 013231 1 1]
[0 0 012121 1 1]

需要注意的是分段Bezier曲线必须满足 nk=正整数 。

这里给出准均匀B样条和分段Bezier曲线的生成节点矢量的代码,均匀B样条的很简单就不列出了。假设共n+1个控制顶点,k次B样条,输入参数为 n, k ,输出节点矢量NodeVector。


准均匀B样条曲线的节点矢量生成:

% U_quasi_uniform.m文件
function NodeVector = U_quasi_uniform(n, k)
% 准均匀B样条的节点向量计算,共n+1个控制顶点,k次B样条
NodeVector = zeros(1, n+k+2);
piecewise = n - k + 1;       % 曲线的段数
if piecewise == 1       % 只有一段曲线时,n = kfor i = n+2 : n+k+2NodeVector(1, i) = 1;end
elseflag = 1;       % 不止一段曲线时while flag ~= piecewiseNodeVector(1, k+1+flag) = NodeVector(1, k + flag) + 1/piecewise;flag = flag + 1;endNodeVector(1, n+2 : n+k+2) = 1;
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

分段Bezier曲线的节点矢量生成:

% U_piecewise_Bezier.m文件
function NodeVector = U_piecewise_Bezier(n, k)
% 分段Bezier曲线的节点向量计算,共n+1个控制顶点,k次B样条
% 分段Bezier端节点重复度为k+1,内间节点重复度为k,且满足n/k为正整数if ~mod(n, k) && (~mod(k, 1) && k>=1)   % 满足n是k的整数倍且k为正整数NodeVector = zeros(1, n+k+2);   % 节点矢量长度为n+k+2NodeVector(1, n+2 : n+k+2) = ones(1, k+1);  % 右端节点置1piecewise = n / k;      % 设定内节点的值Flg = 0;if piecewise > 1for i = 2 : piecewisefor j = 1 : kNodeVector(1, k+1 + Flg*k+j) = (i-1)/piecewise;endFlg = Flg + 1;endendelsefprintf('error!\n');
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

B样条曲线的绘制

根据B样条曲线的定义公式,曲线上任一点坐标值是参数变量u的函数,用矩阵形式表示

p(u)=(d0d1…dn)⎛⎝⎜⎜⎜⎜⎜N0,k(u)N1,k(u)⋮Nn,k(u)⎞⎠⎟⎟⎟⎟⎟

只需要确定 控制顶点di、曲线的次数k 以及基函数Ni,k(u) ,就完全确定了曲线。


B样条曲线的绘制函数:

% DrawSpline.m文件
function DrawSpline(n, k, P, NodeVector)
% B样条的绘图函数
% 已知n+1个控制顶点P(i), k次B样条,P是2*(n+1)矩阵存控制顶点坐标, 节点向量NodeVector
plot(P(1, 1:n+1), P(2, 1:n+1),...'o','LineWidth',1,...'MarkerEdgeColor','k',...'MarkerFaceColor','g',...'MarkerSize',6);
line(P(1, 1:n+1), P(2, 1:n+1));
Nik = zeros(n+1, 1);
for u = 0 : 0.005 : 1-0.005for i = 0 : 1 : nNik(i+1, 1) = BaseFunction(i, k , u, NodeVector);endp_u = P * Nik;if u == 0tempx = p_u(1,1);tempy = p_u(2,1);line([tempx p_u(1,1)], [tempy p_u(2,1)],...'Marker','.','LineStyle','-', 'Color',[.3 .6 .9], 'LineWidth',3);elseline([tempx p_u(1,1)], [tempy p_u(2,1)],...'Marker','.','LineStyle','-', 'Color',[.3 .6 .9], 'LineWidth',3);tempx = p_u(1,1);tempy = p_u(2,1);end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

调用 DrawSpline(n, k, P, NodeVector) 函数就能绘制曲线,注意输入变量要正确。

—————————————————————————————————————————————————————————————

下面给出绘制三种不同B样条曲线的命令流,可以参考比较每种类型之间的区别。

% 绘制三种类型的B样条曲线,需要前面所给的所有.m文件
clear all;
%控制顶点
P = [9.036145, 21.084337, 37.607573, 51.893287, 61.187608;51.779661, 70.084746, 50.254237, 69.745763, 49.576271];n = 4; k = 2;flag = 2;
% flag = 1,绘制均匀B样条曲线
% flag = 2, 绘制准均匀B样条曲线
% flag = 3, 绘制分段Bezier曲线switch flagcase 1NodeVector = linspace(0, 1, n+k+2); % 均匀B样条的节点矢量% 绘制样条曲线plot(P(1, 1:n+1), P(2, 1:n+1),...'o','LineWidth',1,...'MarkerEdgeColor','k',...'MarkerFaceColor','g',...'MarkerSize',6);line(P(1, 1:n+1), P(2, 1:n+1));Nik = zeros(n+1, 1);for u = k/(n+k+1) : 0.001 : (n+1)/(n+k+1)% for u = 0 : 0.005 : 1for i = 0 : 1 : nNik(i+1, 1) = BaseFunction(i, k , u, NodeVector);endp_u = P * Nik;line(p_u(1,1), p_u(2,1), 'Marker','.','LineStyle','-', 'Color',[.3 .6 .9]);endcase 2NodeVector = U_quasi_uniform(n, k); % 准均匀B样条的节点矢量DrawSpline(n, k, P, NodeVector);case 3NodeVector = U_piecewise_Bezier(n, k);  % 分段Bezier曲线的节点矢量DrawSpline(n, k, P, NodeVector);otherwisefprintf('error!\n');
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

三种类型的B样条曲线:

1. 均匀B样条曲线

2. 准均匀B样条曲线

3. 分段Bezier曲线

参考文献:

[1] 施法中. 计算机辅助几何设计与非均匀有理B样条(修订版)[M]. 北京: 高等教育出版社, 2013 : 217-248.

MATLAB绘制B样条曲线相关推荐

  1. nyquist图怎么画matlab,用MATLAB绘制Nyquist图

    <用MATLAB绘制Nyquist图>由会员分享,可在线阅读,更多相关<用MATLAB绘制Nyquist图(9页珍藏版)>请在人人文库网上搜索. 1.用MATLAB绘制Nyqu ...

  2. matlab绘制圆,且求解两个圆的交点坐标

    前言 这里简单记录下对于matlab绘制圆,以及求解两圆交点的坐标的实现(包括C++). 一 绘制圆 circle.m文件: function [] = circle(x, y, r, color) ...

  3. matlab系统的根轨迹,实验五 利用MATLAB绘制系统根轨迹

    <实验五 利用MATLAB绘制系统根轨迹>由会员分享,可在线阅读,更多相关<实验五 利用MATLAB绘制系统根轨迹(6页珍藏版)>请在人人文库网上搜索. 1.实验五 利用MAT ...

  4. Matlab 绘制三维立体图(以地质异常体为例)

    Matlab 绘制三维立体图(以地质异常体为例) 参考文章: (1)Matlab 绘制三维立体图(以地质异常体为例) (2)https://www.cnblogs.com/yangwenbo214/p ...

  5. matlab绘制频散曲线,Matlab绘制频散曲线程序代码.docx

    Matlab绘制频散曲线程序代码.docx 下载提示(请认真阅读)1.请仔细阅读文档,确保文档完整性,对于不预览.不比对内容而直接下载带来的问题本站不予受理. 2.下载的文档,不会出现我们的网址水印. ...

  6. matlab绘制X,Y二维散点图并标出序号

    matlab绘制X,Y二维散点图并标出序号 标签: matlab 2016-11-22 12:20 193人阅读 评论(0) 收藏 举报  分类: matlab(1)  版权声明:本文为博主原创文章, ...

  7. 如何使用MATLAB绘制不同类型的二维图形

    如何使用MATLAB绘制不同类型的二维图形 听语音 | 浏览:360 | 更新:2014-11-30 18:10 | 标签:matlab 1 2 3 4 5 分步阅读 如何用MATLAB绘制各种二维图 ...

  8. 【新星计划】MATLAB绘制图形

    MATLAB绘图和图形功能,内容包括: 如何绘制二维条形图 如何绘制等值线 如何绘制三维图 MATLAB绘制条形图 MATLAB 中使用 bar 命令绘制一个二维条形图. 具体示例 如果有一个包含10 ...

  9. 2021-02-28 Matlab绘制短时傅里叶变换的频谱图和时间-频率-幅值三维图

    Matlab绘制短时傅里叶变换的频谱图和时间-频率-幅值三维图 function [t,frequency,f_spectrum]=fft_s(y,windowlength,Fs) % 输入 : % ...

  10. matlab画置信区间图,matlab绘制带置信区间的双y轴图形 | 学步园

    matlab的双y轴网上有很多方法,但是带置信区间的双y轴就很少了,并且由于网上给的例子一般都是使用红蓝两色,对于只想使用黑色或者灰色的俺们来说太鲜艳啦~ 上图为使用matlab绘制的双y轴带置信区间 ...

最新文章

  1. 阿里云OSS图片上传类
  2. 手把手实现YOLOv3(三)
  3. 搭建php docker环境日记
  4. Shell脚本:Linux下定时备份MySQL数据库
  5. python中的 同步与异步 互斥锁 和 死锁
  6. ROS功能包或其中一部分找不到的奇葩问题及对应解决方案
  7. exchange 2010 sp2系列之(二)证书配置
  8. 【哈工大SCIR Lab】Attention!注意力机制可解释吗?
  9. Harmony OS — TimePicker时间选择器
  10. 最速下滑法c语言程序,最速下降法 C语言.doc
  11. 【rmzt:suika动漫美女可爱主题】
  12. 生物特征识别:小面积指纹识别算法(三)
  13. 深度学习 黑白图片 着色
  14. 在Python中将图像转换为ASCII字符图
  15. 时统ptp_【学术论文】麒麟操作系统平台软时统同步方法研究
  16. 【12月原创】RT-thread - 柿饼UI学习心得分享
  17. 制作一个谷歌浏览器插件,实现网页数据爬虫
  18. (2)前端-初识HTML与CSS-table、form
  19. DPU-PYNQ使用笔记
  20. VUE学习(六) 高德地图常用功能总结

热门文章

  1. 《linux内核分析》第三次课 实验作业
  2. 两种方法实现卸载apk应用程序
  3. go包管理工具之govender
  4. 知识付费的内容变现有哪些方式?
  5. html表格打印分页无边框_excel怎么显示打印线-表格换页打印没有边框线
  6. mysql frm怎么打开_frm 文件怎么打开?
  7. C#如何在VS2015 2017版本中编写WPF UI界面引入第三方SVG图形
  8. Java学习手册:大疆创新2020届校园招聘——软件类岗位B卷题二
  9. 如何成为一家顶级域名注册商及如何提供域名注册
  10. Flutter系列之Navigator组件使用