NURBS蒙皮/放样曲面生成算法

这篇具有很好参考价值的文章主要介绍了NURBS蒙皮/放样曲面生成算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考资料

《The NURBS Book 2nd》中文版(清华大学出版社)

nurbs曲线蒙皮,算法,几何学,图形渲染,数学建模
学习NURBS的经典书籍,对于NURBS相关的定义与算法进行了详细介绍,并对算法给出了类C风格的代码描述。在书的10.3节中,对生成蒙皮曲面的思路进行了介绍。

github仓库:tinynurbs

tinynurbs仓库地址
轻量级的NURBS库,定义了NURBS相关的数据结构,并实现了如NURBS曲线曲面求值、求切向、求法向、节点插入等基本算法,但没有实现高级曲面构造算法(如蒙皮曲面)。

问题引入

蒙皮/放样

给定空间中的一组NURBS曲线,生成一张经过它们的NURBS曲面,这一过程可以形象地看作是对由曲线形成的骨架蒙上一层皮,因此被称为蒙皮(skinning)或放样(lofting)。蒙皮只是放样的新名词,二者的含义是等价的。

算法思路

对于这组NURBS曲线(常被称为截面曲线),首先需要进行一定的预处理

  1. 如果这组曲线的次数(degree)不统一,使用升阶算法令其统一
    (次数=阶数-1,degree指次数,但常用阶数一词描述曲线)
  2. 如果这组曲线的节点向量(knots)不统一,使用节点细化算法令其统一
  3. 同阶且节点向量相同的曲线组,使用蒙皮算法
NURBS_Surface Skinning(vector<NURBS_Curve>curves){
	//参考《The NURBS Book 2nd》5.5节
	if(各曲线阶数不统一){
		//将所有曲线的阶数升到与最高阶的曲线相同
		newDegree = max(curves.degree);
		DegreeElevateCurve(curves,newDegree);
	}
	
	//参考《The NURBS Book 2nd》5.3节
	if(各曲线节点向量不统一){
		//合并各曲线节点向量
		new_knots = merge_knots(curves,knots);
		//令各曲线的节点向量改为新节点向量
		RefineKnotVectCurve(curves,new_knots);
	}
	
	//参考《The NURBS Book 2nd》10.3节
	skinSurface = BuildSkinSurface(curves);
	
	return skinSurface;
}

本文将重点讨论完成预处理后的情况,即对同阶且节点向量相同的曲线组生成蒙皮曲面,对于升阶和节点细化算法则仅作简单介绍。

蒙皮曲面生成算法

算法思路

tips:本文采用的NURBS数据结构及属性/方法命名与tinynurbs库一致。
要确定一个NURBS曲面,需要定义以下属性:

  1. u方向次数(degree_u)
  2. v方向次数(degree_v)
  3. u方向节点向量(knots_u)
  4. v方向节点向量(knots_v)
  5. 曲面控制点(cotrol_points)
  6. 曲面控制点的权重(weights)

以输入的曲线组的方向为u方向,蒙皮的方向为v方向,根据输入的曲线组可以直接确定蒙皮曲面的以下属性:

//各曲线的阶数和节点向量均相同,这就是预处理的意义
skinSurface.degree_u = curve.degree;
skinSurface.knots_u = curve.knots;

对于剩下的属性,分别采用以下方法得到:

  1. v方向次数(degree_v):任意选取,只要小于曲线数即可
  2. v方向节点向量(knots_v):参考《The NURBS Book 2nd》中公式10.8和9.8
  3. 曲面控制点(cotrol_points)和曲面控制点的权重(weights):将原曲线组的每列(v方向)控制点作为型值点,根据计算knots_v时得到的参数和节点向量进行曲线插值,反求控制点(参考《The NURBS Book 2nd》例9.1)

《The NURBS Book 2nd》10.3节描述这一过程的原文为:

基于B样条曲线,蒙皮曲面的构造过程如下,令
C k w ( u ) = ∑ i = 0 n N i , p ( u ) P i , k w ( k = 0 , 1 , . . . , K ) C_{k}^{w}(u) =\sum_{i=0}^{n} N_{i,p}(u)P_{i,k}^{w}\quad\quad\quad(k=0,1,...,K) Ckw(u)=i=0nNi,p(u)Pi,kw(k=0,1,...,K)
为有理或非有理的截面曲线。

注:即曲线组内共有0 ~ K条曲线,每条曲线有0 ~ n个控制点。

v v v方向,选择次数 q q q,确定参数 { v ˉ k } , ( k = 0 , . . . , K ) \left \{\bar v_{k} \right \},(k=0,...,K) {vˉk},(k=0,...,K)和节点矢量 V V V
然后,根据这些参数和节点矢量对截面曲线的控制点进行 n + 1 n+1 n+1次曲线插值,即得到蒙皮曲面的控制点 Q i , j w Q_{i,j}^{w} Qi,jw
具体地, Q i , j w Q_{i,j}^{w} Qi,jw是插值于 P i , 0 w , . . . , P i , K w P_{i,0}^{w},...,P_{i,K}^{w} Pi,0w,...,Pi,Kw q q q次曲线的第 j j j个控制点。

注:即蒙皮曲面的每列控制点,由对原曲线组的每列控制点插值得到。

注意,即使在截面曲线 C k w ( u ) C_{k}^{w}(u) Ckw(u)中只有一条是有理曲线,在 v v v方向对 P i , k w P_{i,k}^{w} Pi,kw的插值也要在四维空间中进行;否则,仅需插值三维点 P i , k w P_{i,k}^{w} Pi,kw

注:即应首先将控制点(x,y,z)变为带权控制点(wx,wy,wz,w)

计算v方向节点向量

计算参数 { v ˉ k } \left \{\bar v_{k} \right \} {vˉk}

首先,需要计算参数 { v ˉ k } \left \{\bar v_{k} \right \} {vˉk},其表示每条截面曲线在 v v v方向所对应的参数。
nurbs曲线蒙皮,算法,几何学,图形渲染,数学建模
根据《The NURBS Book 2nd》公式10.8, { v ˉ k } \left \{\bar v_{k} \right \} {vˉk}的计算方法如下:

v ˉ 0 = 0 , v ˉ K = 1 \bar v_{0}=0,\bar v_{K}=1 vˉ0=0,vˉK=1
v ˉ k = v ˉ k − 1 + 1 n + 1 ∑ i = 0 n ∣ P i , k w − P i , k − 1 w ∣ d i ( k = 1 , 2 , . . . , K − 1 ) \bar v_{k}=\bar v_{k-1}+\frac{1}{n+1}\sum_{i=0}^{n}\frac{\left | P_{i,k}^{w}- P_{i,k-1}^{w} \right |}{d_{i}}\quad\quad\quad(k=1,2,...,K-1) vˉk=vˉk1+n+11i=0ndiPi,kwPi,k1w(k=1,2,...,K1)
这里 d i d_{i} di表示 P i , 0 w , . . . , P i , K w P_{i,0}^{w},...,P_{i,K}^{w} Pi,0w,...,Pi,Kw的总弦长,即 d i = ∣ P i , 1 w − P i , 0 w ∣ + ∣ P i , 2 w − P i , 1 w ∣ + . . . + ∣ P i , K w − P i , K − 1 w ∣ d_{i}=\left | P_{i,1}^{w}- P_{i,0}^{w} \right |+\left | P_{i,2}^{w}- P_{i,1}^{w} \right |+...+\left | P_{i,K}^{w}- P_{i,K-1}^{w} \right | di= Pi,1wPi,0w + Pi,2wPi,1w +...+ Pi,KwPi,K1w

注:曲线组内共有0 ~ K条曲线,每条曲线有0 ~ n个控制点,第k条曲线的第i个控制点 P i , k w P_{i,k}^{w} Pi,kw
v ˉ 0 = 0 , v ˉ K = 1 \bar v_{0}=0,\bar v_{K}=1 vˉ0=0,vˉK=1表明了蒙皮曲面在 v v v方向将以第一条与最后一条截面线作为边界,接下来我们来理解 v ˉ k \bar v_{k} vˉk的表达式。
{ v ˉ k } \left \{\bar v_{k} \right \} {vˉk}表示截面曲线在 v v v方向的参数值,其中第 k k k条曲线的参数值 v ˉ k \bar v_{k} vˉk比第 k − 1 k-1 k1条曲线的参数值 v ˉ k − 1 \bar v_{k-1} vˉk1增加了
1 n + 1 ∑ i = 0 n ∣ P i , k w − P i , k − 1 w ∣ d i ( k = 1 , 2 , . . . , K − 1 ) \frac{1}{n+1}\sum_{i=0}^{n}\frac{\left | P_{i,k}^{w}- P_{i,k-1}^{w} \right |}{d_{i}}\quad\quad\quad(k=1,2,...,K-1) n+11i=0ndiPi,kwPi,k1w(k=1,2,...,K1)

∣ P i , k w − P i , k − 1 w ∣ \left | P_{i,k}^{w}- P_{i,k-1}^{w} \right | Pi,kwPi,k1w 表示第k条曲线的第i个控制点 P i , k w P_{i,k}^{w} Pi,kw和第k-1条曲线的第i个控制点 P i , k − 1 w P_{i,k-1}^{w} Pi,k1w间的距离, d i d_{i} di表示所有曲线的第i个控制点间的距离之和,因此 ∣ P i , k w − P i , k − 1 w ∣ d i \frac{\left | P_{i,k}^{w}- P_{i,k-1}^{w} \right |}{d_{i}} diPi,kwPi,k1w描述了前后两条曲线的间距在总距离中的占比。
对0 ~ n号控制点分别计算该比例后再取平均(除以 n + 1 n+1 n+1),以该值作为截面曲线的参数增加值。

std::vector<double> v;
v.push_back(0); //v_0=0;
double v_pre = 0;
for(int k = 1; k < K; k++) {
	double sum = 0;	//sum(P/d)
	for(int i = 0; i <= n; i++) {
		//第k条曲线的第i个控制点和第k-1条曲线的第i个控制点的距离
		double P_distance = distance(P[k][i], P[k-1][i]);
		//所有曲线第i个控制点间的距离之和
		double sum_P_distance = 0;	//di
		for(int l = 1;l <= K; l++) {
			sum_P_distance += distance(P[l][i], P[l-1][i]
		}
		sum += P_distance / sum_P_distance;	
	}
	double v_k = v_pre + sum / (n+1);
	v.push_back(v_k);
	v_pre = v_k;
}
v.push_back(1);	//v_K=1

计算节点向量

根据《The NURBS Book 2nd》公式9.8,可以用如下方法计算节点向量 U = { u 0 , u 1 , . . . , u m } U=\left \{u_{0},u_{1},...,u_{m}\right \} U={u0,u1,...,um}
u 0 = u 1 = . . . = u p = 0 , u m − p = u m − p − 1 = . . . = u m = 1 u_{0}=u_{1}=...=u_{p}=0,\quad u_{m-p}=u_{m-p-1}=...=u_{m}=1 u0=u1=...=up=0,ump=ump1=...=um=1
u j + p = 1 p ∑ i = j j + p − 1 v ˉ i ( j = 1 , 2 , . . . , n − p ) u_{j+p}=\frac{1}{p}\sum_{i=j}^{j+p-1}\bar v_{i}\quad\quad (j=1,2,...,n-p) uj+p=p1i=jj+p1vˉi(j=1,2,...,np)
其中, p p pv方向次数,即前文提到的degree_v。
节点值由参数值取平均得到,用这种方式定义的节点矢量能很好地反应参数值的分布情况。

计算曲面控制点及权重

计算曲面控制点的方法可以用一句话概括:以截面曲线组v方向的每列控制点为型值点反求曲面在v方向的每列控制点。这一过程被称为曲线插值,具体来说流程如下:
截面曲线组中共有 ( K + 1 ) (K+1) (K+1)条曲线,每条曲线均具有 ( n + 1 ) (n+1) (n+1)个控制点。以所有曲线的第 i ( i = 0 , 1 , . . . , n ) i\quad(i=0,1,...,n) i(i=0,1,...,n)个控制点为一列,构造一条经过这列控制点的NURBS曲线。这条新构造的曲线的控制点就是蒙皮曲面的第 i i i列控制点。
这一过程是曲线求值的逆过程,因此通过解线性方程组即可求得蒙皮曲面的控制点。
注意:虽然需要对每一列控制点都进行曲线插值,但只需要计算一次参数和节点向量,这对于每列控制点都是统一的。
为简化描述,前文常使用控制点一词替代带权控制点。实际上,即使在截面曲线组中只有一条是有理曲线,在 v v v方向对 P i , k w P_{i,k}^{w} Pi,kw的插值也要在四维空间中进行。因此,最后需要将计算得到的蒙皮曲面的带权控制点还原为控制点 ( x , y , z ) (x,y,z) (x,y,z)和权值 w w w

预处理截面曲线

升阶算法

参考《The NURBS Book 2nd》5.5节

节点细化算法

参考《The NURBS Book 2nd》5.3节
节点插入是指一次插入单个节点,而节点细化是指一次插入多个节点。显然,节点细化可以通过多次应用节点插入算法来实现,但节点细化存在更有效的算法。这一算法的实现,可以参考《The NURBS Book 2nd》中的算法A5.4。
对于节点插入算法,tinynurbs库进行了实现,是include/tinynurbs/core/modify.h中的curveKnotInsert方法。如果插入节点较少,也可以通过多次调用该方法来实现节点细化。

实验结果

截面曲线:
nurbs曲线蒙皮,算法,几何学,图形渲染,数学建模
蒙皮曲面:
nurbs曲线蒙皮,算法,几何学,图形渲染,数学建模文章来源地址https://www.toymoban.com/news/detail-802439.html

到了这里,关于NURBS蒙皮/放样曲面生成算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 曲线与曲面积分公式整理

    当f(x,y)=1时,表示曲线L的长度 表示线密度为f(x,y)的曲线质量 沿L运动的变力F=f(x,y)做的功 其中cosα与cosβ是L在(x,y)处的切向量相对于x轴和y轴的方向余弦 其中L是单连通区域D的正向边界 其中L是复连通区域D外部正向边界,l(小写L)是复连通区域D内部正向边界(假设D内只有一个“洞

    2024年02月04日
    浏览(46)
  • 曲线平滑算法:三次Hermite曲线生成

    目录  1.三次Hermite曲线的参数方程 2. 三次Hermite曲线的绘制          Hermite曲线是通过给定曲线的两个端点的位置矢量、以及两个端点处的切线矢量、来描述曲线的,如图1所示。这里先对Hermite曲线进行数学公式推导,然后讲述如何绘制Hermite曲线。(这里是算法代码) 图

    2024年02月16日
    浏览(68)
  • 曲线生成 | 图解B样条曲线生成原理(基本概念与节点生成算法)

    🔥附C++/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。 🚀详情:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法 为了解决贝塞尔曲线无

    2024年02月19日
    浏览(41)
  • 【计算机图形学】曲线和曲面

    模块5 曲线和曲面 一 实验目的 编写曲线和曲面的算法 二 实验内容 1 :绘制Bezier曲线,并采用自行设计输入和交互修改数据点的方式。 实验结果如下图所示: 第一步:输入特征多边形的顶点个数,并按照顺序输入顶点的坐标。 第二步:点击左键生成bezier曲线(白色部分)和

    2024年02月06日
    浏览(43)
  • Open CASCADE学习|曲线向曲面投影

    在三维空间中,将曲线向曲面投影通常涉及复杂的几何计算。这个过程可以通过多种方法实现,但最常见的是使用数学和几何库,如OpenCASCADE,来处理这些计算。 在OpenCASCADE中,投影曲线到曲面通常涉及以下步骤: 定义曲线(Curve)和曲面(Surface)。 使用适当的算法或类(如

    2024年02月19日
    浏览(42)
  • 宋浩高等数学笔记(十一)曲线积分与曲面积分

            个人认为同济高数乃至数学一中最烧脑的一章。。。重点在于计算方式的掌握,如果理解不了可以暂时不强求,背熟积分公式即可。此外本贴暂时忽略两类曲面积分之间的联系,以及高斯公式的相关内容,日后会尽快更新,争取高效率学习。         在数学中

    2024年02月13日
    浏览(42)
  • 【高等数学笔记】两类曲线积分、曲面积分的转化

    整体思想:局部均匀化,用很小的长度/面积元上一点某个量的数值来代替整个元的数值。 设曲线 Γ Gamma Γ 的参数方程为 x = x ( t ) , y = y ( t ) , z = z ( t ) x=x(t),y=y(t),z=z(t) x = x ( t ) , y = y ( t ) , z = z ( t ) 。令 r = ( x , y , z ) bm r=(x,y,z) r = ( x , y , z ) ,则方程为 r = r ( t ) bm r=bm r(t

    2024年02月04日
    浏览(40)
  • 第一型曲线积分与第一型曲面积分、第二型曲线积分与格林公式

    提示:本文的适用对象为已修过《微积分A1》的非数学系学生,文中题型方法为个人总结,为个人复习使用。部分理解虽然不太严谨,但对于解题的实用性较强。若有疏漏or错误,欢迎批评指正。 对于已经熟知第一型曲线积分和第一型曲面积分定义的朋友们来说,我在这里主

    2024年02月04日
    浏览(48)
  • 高等数学啃书汇总重难点(十一)曲线积分与曲面积分

    依旧是公式极其复杂恶心的一章,建议是: 掌握两种线面积分的计算套路即可 ,和第8章一样属于同济版教材中最不重要的章节,不会对底层理解做过多考察~ 1.弧长曲线积分的几何意义 2.弧长曲线积分的定义和性质 3.弧长曲线积分的计算方式 4.坐标曲线积分的几何意义 5.坐标

    2024年02月06日
    浏览(37)
  • 曲线生成 | 图解贝塞尔曲线生成原理(附ROS C++/Python/Matlab仿真)

    🔥附C++/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。 🚀详情:图解自动驾驶中的运动规划(Motion Planning),附几十种规划算法 贝塞尔曲线是一种数学

    2024年01月16日
    浏览(69)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包