NURBS曲线-节点插入(原理+代码)

目录

1.概念及作用

 2.原理及流程

        1)修改插入位置所在曲线的控制点

        2)修改受影响控制点的权值

        3)原节点矢量中新增目标节点

3.源码加注释

4.补充


1.概念及作用

        设N为在节点矢量U={u_0,u_1,......,u_m}上的NURBS曲线,将U’∈[u_k,u_k+1]插入曲线N中,生成新的节点矢量U={u'_0 = u_0,......,u'_k = u_k,u'_k+1= u_k,......,u'_m+1= u_m},此时仅改变向量空间基底,并不改变曲线的几何和参数化信息。

        通俗点讲,节点插入就是在曲线的节点矢量中新增一个节点,该节点既可以插入在原有两节点之间,也可以重复插入在某一原有节点上。在插入一个节点后,原有的曲线形态不发生改变,但会影响被插入部分的局部曲线控制点的位置(原因在后文解释)。        

 2.原理及流程

        节点插入实例如下图3次Nurbs(p = 3)所示,其中Pi(i∈0~6)为插入前控制点,红色标记为插入前节点矢量Uk[0,0,0,0,1,2,3,4,5,5,5,5],图下方横轴表示节点矢量轴,每一个标记为一个节点,紧密相邻的节点表示在该处有重复节点。现向其中插入节点U_Bar=2.5,由于U5 < U_Bar < U6,故插入位置k=5(如图中蓝色节点所示)。

        插入该节点后,为了保证曲线形态保持不变,会进行哪些操作呢?

        1)修改插入位置所在曲线的控制点

        根据Nurbs曲线的局部性可知,相邻节点间的曲线由p+1个控制点控制(图中节点U5-U6段对应控制点P2~P5)。当向这段曲线间插入一个节点时,首尾控制点的α值分别为1和0(图中P2和P5),故Q2 = P2,Q6 = P5,这两点不发生改变,内部p+1-2个控制点会因1个节点的插入而增加为p+1-2+1个控制点(即图中控制点P3和P4会经重新计算生成Q3、Q4、Q5),新生成的控制点计算公式为(公式推导可参考The NURBS book-Chapter.5.2):

        上述公式可以看出,先由相关被插入的节点U_Bar和相关的U计算出α,再根据α重新由相邻控制点计算出新的控制点。

        概括一下:由于新增节点,会导致该节点位置所在曲线的原有控制点发生改变,计算生成p个新的控制点。

        2)修改受影响控制点的权值

        其实2)对于有一定基础的人来说应该是放在1)中一起讲的,但不幸本人在刚开始学习的时候毫无基础,在权值这里踩了大坑,因此认为分开讲对于初学者来说会更容易理解些。

        请仔细看1)中的公式,这里的Q和P右上角都带了w(带有权值),其实这里每个控制点不单单包含三维空间中的x,y,z,它实际上是四维的,其中还包含了权值w,因此,除了受影响的p+1-2+1个控制点需按上述公式计算外,每个控制点本身对应的权值也需要按同样的方法计算。并且在控制点的计算过程中,新控制点不能单单的通过相邻控制点的x,y,z值得到,还需要将原本的权值也纳入公式计算,并在新的控制点生成后,将其除以权值。(这里但看有些抽象,可以结合文末的代码一起看)

        概括一下:不仅权值需要按上述公式计算,由于控制点是四维的,控制点的计算过程中也需代入权值。

        3)原节点矢量中新增目标节点

        这部分就比较简单,因为新插入了一个节点U=2.5,原有的节点向量中要在k=5的位置新加入这个节点。

3.源码加注释

//向Nurbs中插入新的控制点,返回新的曲线
//输入:Nurbs曲线,插入的节点值,位置(从0开始),重复度(插入前的重复度),插入次数
NURBSpline InsertPoint(const NURBSpline& Sp1, double u, int k, int s, int r) {
	std::vector<double> w_aft(Sp1.n + r);	//插入后的权值
	std::vector<double> w_tem(Sp1.k - s + 1);	//插入影响的权值
	int U_num1 = Sp1.n + Sp1.k + 1, U_num2;	//插入前Sp1节点个数和插入后Sp2节点个数
	int C_num2 = Sp1.n + r;	//插入后Sp2的控制点个数
	std::vector<POINT> C_aft(Sp1.n + r);	//插入后的控制点容器
	std::vector<double> U_aft(C_aft.size() + Sp1.k + 1);	//插入后的节点容器
	//为节点赋值
	for (int i = 0; i <= k; i++) U_aft[i] = Sp1.U[i];	//插入点前面不受影响的部分
	for (int i = 1; i <= r; i++)  U_aft[k + i] = u;	
	for (int i = k + 1; i < U_num1; i++) U_aft[i + r] = Sp1.U[i];	//插入点后面不受影响的部分
	//为控制点赋值
	for (int i = 0; i <= k - Sp1.k; i++) {		//插入点前面不受影响的部分
		C_aft[i] = Sp1.ControlPoint[i]; 
		w_aft[i] = Sp1.w[i];
	}
	for (int i = k - s; i < Sp1.n; i++) {		//插入点后面不受影响的部分
		C_aft[i + r] = Sp1.ControlPoint[i];
		w_aft[i + r] = Sp1.w[i];
	}
	//新生成的控制点赋初值
	std::vector<POINT> C_tem(Sp1.k - s + 1);
	for (int i = 0; i <= Sp1.k - s; i++) {
		C_tem[i] = Sp1.ControlPoint[k - Sp1.k + i];
		w_tem[i] = Sp1.w[k - Sp1.k + i];
	}
	//插入r次
	int L;
	for (int j = 1; j <= r; j++) {
		L = k - Sp1.k + j;	//此次插入位置
		for (int i = 0; i <= Sp1.k - j - s; i++) {			//计算控制该段曲线的k+1个控制点
			double alpha = (u - Sp1.U[L + i]) / (Sp1.U[i + k + 1] - Sp1.U[L + i]);
			C_tem[i].x = alpha * C_tem[i + 1].x * w_tem[i + 1] + (1.0 - alpha) *     C_tem[i].x * w_tem[i];    //新的控制点xyz值
			C_tem[i].y = alpha * C_tem[i + 1].y * w_tem[i + 1] + (1.0 - alpha) * C_tem[i].y * w_tem[i];
			C_tem[i].z = alpha * C_tem[i + 1].z * w_tem[i + 1] + (1.0 - alpha) * C_tem[i].z * w_tem[i];
			w_tem[i] = alpha * w_tem[i + 1] + (1.0 - alpha) * w_tem[i];    //新的权值
			C_tem[i].x /= w_tem[i];    //将新的点除以新的权值
			C_tem[i].y /= w_tem[i];
			C_tem[i].z /= w_tem[i];
		}
		//重新计算的k+1个控制点中,首尾点不变
		C_aft[L] = C_tem[0];				
		C_aft[k + r - j - s] = C_tem[Sp1.k - j - s];
		w_aft[L] = w_tem[0];
		w_aft[k + r - j - s] = w_tem[Sp1.k - j - s];
	}
	//载入剩下的控制点和权值
	for (int i = L + 1; i < k - s; i++) {
		C_aft[i] = C_tem[i - L];
		w_aft[i] = w_tem[i - L];
	}
    //由新生成的点、权值、节点构建新的NURBS曲线
	NURBSpline Nt(C_num2, Sp1.k);
	Nt.ControlPoint = C_aft;
	Nt.U = U_aft;
	Nt.w = w_aft;

	return Nt;
}

4.补充

1)本篇文章的实例是向节点间插入新的节点,但实际上还可以向节点上插入重复的节点,如下图。此时可以观察到,同样向3次曲线插入了1个节点,这次却只有两个控制点改变,除首尾控制点外还有一个控制点没发生改变,这是因为重复插入节点时,有一个控制点在代入公式计算时,U_Bar和Ui相等了,从而得到结果α=0,使得该控制点未发生改变。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: NURBS曲线节点矢量数量是指定义和控制NURBS曲线形状的节点矢量的个数。 在NURBS曲线中,节点矢量是一个有序的实数序列,用来确定曲线上的控制点的位置和权重。节点矢量的长度决定了曲线的次数和曲线上的控制点数目。 节点矢量数量的确定通常需要考虑以下几个因素: 1. 曲线的次数:节点矢量数量至少要比曲线的次数大1。例如,如果曲线的次数为2,则节点矢量至少需要3个。 2. 控制点数量:节点矢量的数量一般要比控制点的数量大1。例如,如果有4个控制点,通常需要5个节点矢量。 3. 节点矢量的分布:节点矢量的分布对曲线的形状有很大的影响。可以通过调整节点矢量的位置和权重来改变曲线的形状。一般而言,节点矢量应该按照一定的规律分布,以获得更平滑的曲线。 因此,节点矢量数量的确定需要根据曲线的次数、控制点数量和期望的曲线形状来决定。如果节点矢量数量不合适,可能会导致曲线出现奇异点或形状变形等问题。 ### 回答2: NURBS曲线中的节点矢量数量取决于曲线的次数和控制点的数量。NURBS(Non-Uniform Rational B-Spline)是一种用于表示和生成曲线和曲面的数学模型。节点矢量是在NURBS曲线中定义控制点权重的位置。通过调整节点矢量的位置,可以对曲线进行形状和曲率的调整。 对于一个NURBS曲线,如果曲线的次数为n,控制点的数量为m,则节点矢量的数量为m+n+1。这是因为每个控制点都对应一个节点矢量,而次数n决定了曲线的阶数。节点矢量的数量比控制点多n+1是为了使曲线首尾相连,保证曲线的连续性。 节点矢量的位置对于曲线的形状和平滑度有重要影响。在节点矢量中,相邻的矢量之间的间距决定了曲线在该区域的紧密程度。间距越大,曲线的变化越平缓,而间距越小,曲线的变化越陡峭。 因此,通过调整节点矢量的数量和位置,可以灵活地控制NURBS曲线的形状。在建模和设计过程中,我们可以根据需要调整节点矢量的位置,以获得所需的曲线形状和平滑度。对于不同的曲线需求,我们可以使用不同数量的控制点和调整节点矢量的方法,实现曲线的准确建模和设计。 ### 回答3: NURBS(Non-Uniform Rational B-Spline)曲线是一种用于描述二维和三维几何形状的数学表示方法。它的节点矢量数量决定了曲线上的控制点数量和控制曲线的形状。 在NURBS曲线中,每个节点矢量对应一个控制点,节点矢量的数量决定了控制点的个数。当节点矢量的数量大于等于控制点的数量时,我们称为可定义NURBS曲线节点矢量的数量应该大于等于曲线的次数加1,即节点矢量数量≥(曲线次数+1)。 节点矢量的数量决定了曲线的灵活度和形状的变化程度。如果节点矢量的数量较少,曲线的形状变化会受限;如果节点矢量的数量较多,曲线的形状变化会更加灵活,可以创造出复杂的曲线形状。 节点矢量的位置也对NURBS曲线的形状有影响。节点矢量的位置决定了控制点在曲线上的分布情况。节点矢量的位置可以通过均匀分布、非均匀分布等方式确定,不同的位置分布会产生不同的曲线形状。 总而言之,节点矢量的数量对NURBS曲线的控制点数量和形状有着重要的影响。合理选择节点矢量的数量和位置可以得到满足需求的曲线形状。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值