MATLAB实现NURBS逼近曲线拟合及界面

article/2025/8/21 9:27:30

目录 

前言

一、数据点参数化

1.1原因

1.2方法

1.3代码(封装到类)

 二、节点矢量计算 

 2.1方法

 2.2代码

三、最小二乘反算控制点

四、基函数实现

五、豪斯多夫距离

六、离散曲率

总结


前言

        采用matlab实现NURBS逼近曲线的拟合,利用app designer实现拟合的界面,辅助验证各种方法。文中主要是自己实现写的算法,可以得到逼近曲线,以及进行曲线性能的简单评判。

        文中只简单介绍了一些理论,也是个人的一下理解,或许有误。详细理论看施法中《计算机辅助几何设计与非均匀有理B样条》一书,极其详细,好多论文里面提到的方法及背景,发展历史都能在里面找到。

       在哔哩哔哩上传了分开的内容,用于记录。全部内容总结在本文: 哔哩哔哩专栏地址

       实现的效果可以参考哔哩哔哩内视频:视频地址

       全部的代码内容:代码压缩文件 有问题联系。

       再次说明一下,使用的是逼近曲线,不是插值曲线,没有涉及切矢计算,采用最小二乘方法。


一、数据点参数化

1.1原因

        采用参数多项式构造插值函数,顺序通过n+1个点不超过n次的参数多项式曲线可能有无数条。欲使唯一确定一条插值曲线就需要先对数据点赋予参数化,使其形成严格递增序列: u0<u1……<um 。(我也没太明白,咋就有无数条了,传入数据点不就有数据顺序了嘛) 

1.2方法

         数据点参数化方法主要有均匀参数化、积累弦长、向心、福利参数化方法。只实现了前三个,最后一个没找到资料。  

        均匀参数化法使节点在参数轴上等距分布,在相邻弦长差距大的情况下,得到的曲线会出现弦长长段曲线扁平,弦长短段曲线凸起的现象,甚至出现尖点或自交点。这些问题其他方法也有。

        积累弦长引入弦长信息,得到改善;向心引入弦长折拐信息,改善;福利参数方法引入修正系数,使折拐不是简单的稳定数值。(仅个人理解) 三种方法比对图。

1.3代码(封装到类)

%数据参数化
classdef Parametrizationpropertiesp %数据endmethodsfunction obj = Parametrization(a)obj.p = a.data;endfunction dataPara = USM(obj)data = obj.p;n = size(data,1);dataPara = zeros(1,n);for i = 1:ndataPara(i) = (i-1)/(n-1);endendfunction dataPara = CLM(obj)data = obj.p;n = size(data,1);dataPara = zeros(1,n);L = GetTwoPointsDis(data, 1);for i = 2:(n-1)dataPara(i) = sum(L(1:i-1))/sum(L(:));enddataPara(n) = 1;endfunction dataPara = CM(obj)data = obj.p;n = size(data,1);dataPara = zeros(1,n);L = GetTwoPointsDis(data, 1/2);for i = 2:(n-1)dataPara(i) = sum(L(1:i-1))/sum(L(:));enddataPara(n) = 1;endend
end
function Dis = GetTwoPointsDis(data, p)%data控制点 n行2列   q次数(1,弦长 1/2向心)n = size(data, 1);Dis = zeros(1,n-1);for i = 1:n-1A = norm(data(i,:) - data(i+1,:));Dis(i) = A^(p);end
end

 二、节点矢量计算 

 2.1方法

        写了AVG+KTP的方法,和UAVG方法。这两个公式好找,好实现;特征点、支配点、遗传算法这些没找到公式。遗传算法迷宫时候学过概念,没掌握精髓。

 2.2代码

%计算节点矢量
classdef GetKnotspropertiesdatadataParakctrPnumsendmethodsfunction obj = GetKnots(a)obj.data = a.data;%数据点 得到个数obj.dataPara = a.dataPara;%数据点参数obj.k = a.k;%次数obj.ctrPnums = a.ctrPnums;%控制点个数endfunction knots = AVG_KTP(obj)m = size(obj.data,1);n = obj.ctrPnums;u = obj.dataPara;knots = zeros(1,n+obj.k+1);knots(n+1: n+obj.k+1) = 1;if m == nfor j = 1:(n-obj.k-1)knots(obj.k+j+1) = sum(u(j+1:j+obj.k)) / obj.k;endendif m>nc = m / (n - obj.k);for j = 1:n-obj.k-1i = floor(j * c);a = j*c - i;knots(obj.k+j+1) = (1-a)* u(i) + a * u(i+1);endendendfunction knots = UAVG(obj)m = size(obj.data,1);n = obj.ctrPnums;u = obj.dataPara;knots = zeros(1,n+obj.k+1);knots(n+1: n+obj.k+1) = 1;for j = 1:(n-obj.k-1)knots(j+obj.k+1) = sum(u(j+1:j+obj.k+m-n))/(obj.k+m-n);endendend
end

三、最小二乘反算控制点

         采用的是逼近曲线,用的最小二乘法,切矢这些不包含在内,原理就是采取曲线偏差的一个函数,令其偏导为0。得到反算的公式。

        输入是一个结构体。

function ctrP = InvCtrP(InputsStruct)data = InputsStruct.data;dataPara = InputsStruct.dataPara;knots = InputsStruct.knots;k = InputsStruct.k;ctrPnums = InputsStruct.ctrPnums;m = size(data,1);%计算r矩阵r = zeros(ctrPnums-2,2);for i = 2:(m-1)r(i-1,:) = data(i,:)-data(1,:).*GetBasisFcn(dataPara(i),knots,0,k)...-data(m,:).*GetBasisFcn(dataPara(i),knots,ctrPnums-1,k);end%计算N矩阵N = zeros(m-2,ctrPnums-2);for j = 2:(m-1)x = zeros(1,ctrPnums-2);for i = 2:(ctrPnums-1)x(i-1) = GetBasisFcn(dataPara(j),knots,i-1,k);endN(j-1,:) = x;endR = N'*r;ctrP = [data(1,:);(N'*N)\R; data(m,:)];
end

        其中主要是基函数的实现,一开始不知道什么问题老是在一点处变为2倍,后面一直没搞这个,再次运行又没事了。基函数实现在下一篇,不知道为什么基函数插入代码显示不出来。。。


四、基函数实现

不显示代码可能是因为&&这个

%%%%%%%%%%%这里的代码是

if (x>=knots(i+1)) && (x<knots(i+2))

没有这一句,matlab里面会显示红色提示的。


下面注释的代码是最开始采取的基函数计算方式

输入自变量,节点、第几个、k次数; 注释内容是第二种实现方式,本质一样。

function res = GetBasisFcn(x,knots,i,k)if k == 0%%%%%%%%%%%%%%%%%%%%%%%%%%%%res = 1;elseres = 0;endelseA = GetBasisFcn(x, knots, i, k-1);B = GetBasisFcn(x, knots, i+1, k-1);if A == 0w1 = 0;  %防止迭代过程中 出现分母为0情况elsew1 = (x - knots(i+1)) / (knots(i+k+1) - knots(i+1));endif B == 0w2 = 0;elsew2 = (knots(i+k+2) - x) / (knots(i+k+2) - knots(i+2));endres = w1 * A + w2 * B;end
end
% function res = GetBasisFcn(x,knots,fre,k)
%     N = [];
%     for i = 1:(size(knots,2)-1)
%         %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%             N(i,1) = 1;
%         else
%             N(i,1) = 0;
%         end
%     end
%     for i = 1:(size(knots,2)-1)
%         for j = 1:(size(knots,2)-i-1)
%             if N(j,i) == 0
%                 w1 = 0;
%             else
%                 w1 = (x-knots(j)) / (knots(i+j) - knots(j));
%             end
%             if N(j+1,i) == 0
%                 w2 = 0;
%             else
%                 w2 = (knots(i+j+1)-x) / (knots(i+j+1) - knots(j+1));
%             end
%             N(j,i+1) = w1*N(j,i) + w2*N(j+1,i);
%         end
%     end
%
%     res = N(fre+1,k+1);
% end

五、豪斯多夫距离

在得到拟合后的曲线后,需要评估效果。

目标函数采取豪斯多夫距离评定偏差,这个好理解,理论很多。

曲线光顺性采取的离散曲率,这个没细看,简单实现一下。

返回偏差、以及在两组数据中的序号


%豪斯多夫距离 单向
% function [dis,number] = Hausdorff(p,Q)
%     [pToQ_dis,number] = Hausdorff_pToQ(p,Q);
%     QTop_dis = Hausdorff_pToQ(Q,p); 
%     
%     dis = max(pToQ_dis, QTop_dis);
% end
function [dis, numberp, numberQ] = Hausdorff(p,Q)m = size(p, 1);n = size(Q, 1);   pAllToQ_MaxDis = 0;for i = 1:mpEach = p(i,:);pEachToQ_MinDis = 10;for j = 1:nQEach = Q(j,:);if pEachToQ_MinDis>norm(pEach-QEach)pEachToQ_MinDis = norm(pEach-QEach);x = j;endendif pAllToQ_MaxDis<pEachToQ_MinDispAllToQ_MaxDis = pEachToQ_MinDis;numberp = i;numberQ = x;end  enddis = pAllToQ_MaxDis;
end

六、离散曲率

曲线光顺性方法也有好多。基于曲率、基于能量、二者结合等等。

采取基于曲率,需要计算导数,但是计算导数前后两个点挺头疼的。

在一篇论文里找到一种方法。具体忘叫啥了,好像是第二类离散曲率。进行了转换 

function C = Curvature(data)%计算离散曲率图%增加-1 n+1点 变为Qdata_rows = size(data,1);Q = zeros(data_rows+2, 2);Q(1,:) = 2*data(1,:) - data(2,:);Q(2:data_rows+1,:) = data;Q(data_rows+2,:) = 2*data(data_rows,:) - data(data_rows-1,:);%迭代计算C = zeros(1,data_rows);for i = 2:data_rows+1Li = norm(Q(i,:) - Q(i-1,:));Li_1 = norm(Q(i+1,:) - Q(i,:));Mi = norm(Q(i+1,:) - Q(i-1,:));%三角形 有向面积D = ones(3);for j = 1:3D(j,1:2) = Q(i+j-2,:);endS = det(D) / 2;%计算离散曲率C(i-1) = 2*(Li+Li_1)^2 * S / (Li*Li_1 * Mi^3);end
end 

总结

        通过NURBS曲线的学习,对计算机图形学有了兴趣,尽管很难深入其中。理论方法多种多样,文中只是个人实现所采用的,一些内容如反插节点也没有包括进去。也学习了opengl部分知识。当然这些内容自然比不过matlab带的曲线拟合工具箱,所以用工具箱更方便。

        界面用的matlab2021版本的,新版本较旧版本多了许多回调函数,不需要自己去定义,方便很多。



http://chatgpt.dhexx.cn/article/ysAVOdZA.shtml

相关文章

NURBS Curves

文章目录 1. 定义2. 性质2.1 NURBS基函数的性质2.2 NURBS曲线的性质 3. 修改权重4. 相关算法4.1 节点插入&#xff1a;单点插入4.2 De Boors Algorithm 5. Rational Bzier Curves6. Rational Bzier Curves: Conic Sections7. Circular Arcs and Circles 1. 定义 NURBS&#xff…

Matlab中安装NURBS工具箱及使用

文章目录 前言一、NURBS工具箱的安装1 打开matlab&#xff0c;点击附加功能2 输入nurbs3 下载后压缩包解压4 将解压后的文件夹放到matlab文件夹的toolbox文件夹里面5 选择“预设路径”上方的“预设” 二、NURBS工具箱的使用2.1 NURBS 结构&#xff1a;2.2 对NURBS工具箱的初步理…

计算几何07_NURBS曲线与曲面

B样条方法在表示与设计自由曲线曲面时展现出强大的威力&#xff0c;但在设计与表示初等曲线曲面时却遇到了麻烦。因为B样条曲线、及其特例的Bezier曲线都不能精确表示除抛物线以外的二次曲线弧&#xff0c;B样条曲面、及其特例的Bezier曲面都不能精确表示除抛物面以外的二次曲面…

利用NURBS曲线进行点云曲面拟合算法

文章目录 介绍NURBS曲线C实现思路代码实现读取点云数据对点云进行预处理创建曲面模型将曲面模型转换为NURBS曲面 完整代码opennurbs.h说明vs2019安装OpenNURBS库编译OpenNURBS库 介绍 点云拟合曲面算法是将点云数据拟合成一个二次或高次曲面模型的算法。这种算法主要用于三维模…

离散数据点NURBS曲线拟合算法

问题描述&#xff1a;对于离散数据点集来说&#xff0c;其主要特征点一般可以描述原始曲线轨迹的基本形状。对于大量的离散数据点来说&#xff0c;提取主要的特征点后在进行曲线拟合&#xff0c;这样可以降低计算次数&#xff0c;极高拟合效率。 可以描述原始曲线几何形状的 特…

Nurbs建模

多边形建模和Nurbs建模 Nurbs始终有四个侧面&#xff0c;由有理多项式方程创立的曲线&#xff0c;由控制点定义的曲线。 Nurbs曲线是由一系列多项式构成的&#xff1a;axb0,ax^2bxc0… 能够将任何平面转换为Nurbs NURBS能买构建几乎所有的形状

matlab中Nurbs库的简单使用

文章目录 前言一、简单例子二、复杂一点的NUrbs曲面nrbeval函数 前言 只是为方便学习&#xff0c;不做其他用途&#xff0c;记录matlab中Nurbs的使用&#xff0c;好像记得是添加的matlab中的一个Nurbs库来着。前一段使用&#xff0c;现在不记得了&#xff0c;使用这个程序得先安…

NURBS

非均匀有理样条NURBS( Non-Uniform Rational B-Splines ) 是近年来发展迅速&#xff0c;应用广泛的一种表示曲线曲面造型技术。它能够精确地表示二次规则曲线曲面&#xff0c;从而能用统一的数学形式表示规则曲面与自由曲面&#xff0c;具有可影响曲线曲面形状的权因子&#xf…

【Matlab-NURBS工具箱简要教程及实例 】

Matlab-NURBS工具箱使用教程 添加NURBS工具箱 在附加功能里添加NURBS工具箱 安装完成后可以在’函数’处查看API&#xff0c;也打开文件夹查看。 强烈推荐同步安装gnurbs工具&#xff0c;它完全代替nrbplot展示曲面&#xff0c;且允许用户进行节点拖拽等操作。 NURBS 结…

Nurbs曲线详解

NURBS&#xff08;Non Uniform Rational B-spline&#xff09;曲线通常称为非均匀有理B样条曲线&#xff0c;其数学定义如下&#xff1a; 基函数由递推公式定义&#xff1a; 非均匀&#xff1a;指节点向量的值与间距可以为任意值。这样我们可以在不同区间上得到不同的混合…

NURBS曲面结构及生成原理、修改方法

NURBS全称是Non-Uniform Rational B-Splines中文叫做非均匀有理B样条曲线&#xff0c;Rhinoceros中的模型曲线便是通过NRUBS曲线进行描述&#xff0c;曲面则是通过U和V两个方向的曲线集合来得到&#xff0c;如图&#xff1a; Rhino如何生产曲面原理 由上图我们发现就像织布一样…

MySQL数据库增量备份及恢复方案

MySQL数据库增量备份及恢复方案 u 前言 操作系统崩溃、电源故障、文件系统崩溃和硬件故障等异常状况都可能导致我们正在使用的数据库出现故障而产生数据库中数据不一致的情况。为了保证数据库使用安全&#xff0c;必须定期备份数据库&#xff1b;数据库备份可以分为&#xff1…

差异增量备份和累积增量备份区别(有图)

所谓增量备份&#xff0c;顾名思义即是每次备份仅操作那些发生了"变化"的数据块。RMAN中增量备份有两种&#xff1a;Differential 方式和Cumulative方式。 1、差异增量备份Differential 说起Differential&#xff0c;相当有意思&#xff0c;大家可以这样理解。有一…

数据库的备份与恢复(完全备份,增量备份)

目录 1. 数据库备份的分类1.1 从物理与逻辑的角度&#xff0c;备份可分为1.2 从数据库的备份策略角度&#xff0c;备份可分为 2. 常见的备份方法3. MySQL完全备份与分类3.1 完全备份概述3.2 备份方式3.2.1 物理冷备份及恢复3.2.2 使用专用备份工具 mysqldump3.2.2.1 备份库3.2.…

图解完全备份,增量备份,差异备份

因为网上说的全部都是copy的&#xff0c;所以自己去理解了一下然后整理了一下。 完全备份 完成备份我相信大家都理解&#xff0c;就是一下子备份所有的内容。 增量备份 如上图所示&#xff0c;比如一家公司&#xff0c;周一这家公司进行完全备份&#xff0c;然后周二备份周一…

MySQL 增量备份与恢复

目录 引言一、MySQL 增量备份1. 增量备份特点2. 示例 二、MySQL 增量恢复1. 增量恢复的场景2. 丢失完全备份之后更改的数据的恢复3. 完全备份之后丢失所有数据4. 基于时间点与位置的恢复4.1 基于时间点的恢复4.2 基于位置的恢复 5. 指定企业备份策略的思路 总结 引言 完全备份…

增量备份恢复

** 增量备份恢复案例 **1、配置mysql&#xff0c;设置日志文件 [rootlocalhost bak]# vim /etc/my.cnf 添加&#xff1a; log-binmysql-bin2、重启mysqld服务 systemctl restart mysqld查看日志文件&#xff1a; mysqlbinlog /usr/local/mysql/data/mysql-bin.0000013、创…

mysql实现增量备份

有点要注意 如果你误删了表 想通过这个恢复 必须恢复日志里面有创建表的日志 不然的话是无法回复的 就是必须是从你开始创建表的时候就已经记录日志了 恢复到哪个位置 就按照哪个位置来计算 mysql 5.0不支持增量备份 增量备份定义 mysql数据库会以二进制形式 自动把用户对my…

什么是全量备份,增量备份,差异备份?

背景 今天我司服务器工程大牛看我在备份数据,冷不丁提到了差异备份;但是才疏学浅的我却不知何为差异备份,故而以此为引,开始了对全量备份,增量备份,差异备份这三者的研习;经过一番寻觅,最终找到了他们.呵呵 希望大家有所受益! 问题 1. 什么是全量备份&#xff1f; 2. 什么是增量…

MySQL完全备份和增量备份

MySQL日治管理、数据库备份与恢复 备份的主要目的是灾难恢复&#xff0c;备份还可以测试应用、回滚数据修改、查询历史数据、审计等。而备份、恢复中&#xff0c;日志起到了很重要的作用 一、日志 MySQL的日志默认保存位置为 /usr/local/mysql/data 1.日志类型与作用 ①re…