基础概念

在建模系统中,通常使用两种类型的曲面:参数曲面隐式曲面。参数曲面由以下函数定义:

f(u,v)=(x(u,v),y(u,v),z(u,v))\mathbf{f}(u, v) = (x(u, v), y(u, v), z(u, v))

其中参数 uuvv 在某个特定范围内,我们假设 uuvv 都在 [0,1][0,1] 范围内。(u,v)(u, v) 是在 uvuv-坐标平面中由 (0,0),(1,0),(0,1)(0,0), (1,0), (0,1)(1,1)(1,1) 定义的正方形中的一个点。下图说明了这个概念。

img

隐式曲面由三个变量的多项式定义:

p(x,y,z)=0p(x, y, z) = 0

与曲线类似,如果 x(u,v)x(u, v), y(u,v)y(u, v)z(u,v)z(u, v) 是多项式,参数曲面将无法表示 隐式曲面可以描述的许多曲面。球体是一个很好的例子。如果 x(u,v)x(u, v), y(u,v)y(u, v)z(u,v)z(u, v) 是有理多项式(即两个多项式的商),参数曲面可以表示球体、椭球体和许多其他曲面。然而,类似于曲线,许多隐式曲面没有任何参数形式表达。因此,在表达能力方面,隐式曲面比参数曲面更强大。

具有多项式(隐式)形式的曲面称为代数曲面。所有项的最高次数是代数曲面的次数。因此,球体和所有二次曲面都是二次代数曲面,而环面是四次代数曲面。下图显示了次数为3的代数曲面,其隐式方程为:

8x2xy2+xz2+y2+z28=08x^2 - xy^2 + xz^2 + y^2 + z^2 - 8 = 0

一些代数曲面具有有理参数形式,如球体和所有二次曲面。这种类型的代数曲面称为有理代数曲面。理论上,给定一个有理参数形式的代数曲面,总是可以消除参数 uuvv,使结果变为隐式形式。这个过程(从参数表达到隐式表达)称为隐式化。然而,并非所有代数曲面都是有理的。而且,确定一个代数曲面是否是有理的非常困难,尽管代数几何已经提供了这样的判别定理,但是在计算上,这是比较困难的。

参数曲面

通常,许多参数曲面片并排连接在一起,形成更复杂的形状。下图显示了四个参数曲面片连接在一起形成更大的表面区域:

img

要计算表面上一点 (u,v)(u, v) 的切向量和法向量,我们需要偏导数。假设参数曲面的定义如下:

f(u,v)=(x(u,v),y(u,v),z(u,v))\mathbf{f}(u, v) = (x(u, v), y(u, v), z(u, v))

关于 uuvv 的偏导数表示的是 f(u,v)\mathbf{f}(u, v) 处的切向量:

fu=(xu,yu,zu)andfv=(xv,yv,zv)\frac{\partial\mathbf{f}}{\partial u}=\left(\frac{\partial x}{\partial u},\frac{\partial y}{\partial u},\frac{\partial z}{\partial u}\right)\quad\mathrm{and}\quad\frac{\partial\mathbf{f}}{\partial v}=\left(\frac{\partial x}{\partial v},\frac{\partial y}{\partial v},\frac{\partial z}{\partial v}\right)

上式中左侧的是 uu 方向的切向量,而右侧的是 vv 方向的切向量。f(u,v)\mathbf{f}(u, v) 处的法向量 n(u,v)\mathbf{n}(u, v) 是这些偏导数的叉积,使用右手定则:

n=fu×fvfu×fv\mathbf{n}=\frac{\frac{\partial\mathbf{f}}{\partial u}\times\frac{\partial\mathbf{f}}{\partial v}}{\left|\frac{\partial\mathbf{f}}{\partial u}\times\frac{\partial\mathbf{f}}{\partial v}\right|}

参数曲面片可以被认为是(无限多的)曲线的集合。有许多方法可以划分出这些曲线,但是,最简单的是等参数曲线

给定参数曲面 f(u,v)\mathbf{f}(u, v),如果 uu 固定为一个值,比如说 0.1,让 vv 变化,这将在曲面上生成一条 uu 坐标为常数的曲线。这是 u=0.1u = 0.1 方向的等参数曲线。

类似地,固定 vv 到一个值并让 uu 变化,我们得到一个 vv 方向为常数的等参数曲线。因此,让 uu 固定在 0, 0.1, 0.2, …, 0.9 和 1,我们将有 11 条等参数曲线 f(0,v),f(0.1,v),f(0.2,v),...,f(0.9,v)\mathbf{f}(0, v), \mathbf{f}(0.1, v), \mathbf{f}(0.2, v), ..., \mathbf{f}(0.9, v)f(1,v)\mathbf{f}(1, v)。如果我们让 uu 从 0 连续变化到 1,类似地,生成的等参数曲线也会覆盖了整个曲面。下图显示了两个方向上的一些等参数曲线:

img

这些等参数曲线可以帮助渲染曲面。在许多应用中,参数曲面被 “三角化”(或多边化或网格化) 成三角形或多边形。然后,这些三角形和多边形可以非常高效地使用现有的图形编程库(如 OpenGL 和 PHIGS PLUS)进行渲染。

与其对曲面进行三角剖分,不如对 (u,v)(u,v) 参数域进行三角剖分。我们可以将 uu 方向细分为 mm 段,u0=0,u1,...,ui,...,um=1u_0=0, u_1, ..., u_i, ..., u_m=1,并将 vv 方向细分为 nn 段,v0=0,v1,...,vj,...,vn=1v_0=0, v_1, ..., v_j, ..., v_n=1。域被细分为 m×nm \times n 个矩形,每个矩形可以进一步细分为两个三角形。

img

假设 uiu_iui+1u_{i+1}uu 方向上的两个连续分割点,vjv_jvj+1v_{j+1}vv 方向上的两个连续分割点,如上图所示。我们在参数域中有一个矩形,其顶点为 (ui,vj),(ui+1,vj),(ui+1,vj+1)(u_i, v_j), (u_{i+1}, v_j), (u_{i+1}, v_{j+1})(ui,vj+1)(u_i, v_{j+1})。由于这个矩形有两个对角线,我们有两种方法划分成三角形。我们按照上图所示的方式划分。第一个三角形由 (ui,vj),(ui+1,vj)(u_i, v_j), (u_{i+1}, v_j)(ui,vj+1)(u_i, v_{j+1}) 定义,第二个三角形由 (ui+1,vj),(ui+1,vj+1)(u_{i+1}, v_j), (u_{i+1}, v_{j+1})(ui,vj+1)(u_i, v_{j+1}) 定义。

(ui,vj),(ui+1,vj)(u_i, v_j), (u_{i+1}, v_j)(ui,vj+1)(u_i, v_{j+1}) 定义的三角形,这三个点分别映射到曲面上的三个点 f(ui,vj),f(ui+1,vj)\mathbf{f}(u_i, v_j), \mathbf{f}(u_{i+1}, v_j)f(ui,vj+1)\mathbf{f}(u_i, v_{j+1}),法向量为 n(ui,vj),n(ui+1,vj)\mathbf{n}(u_i, v_j), \mathbf{n}(u_{i+1}, v_j)n(ui,vj+1)\mathbf{n}(u_i, v_{j+1})。现在,我们有三个顶点,每个顶点都有一个法向量。这六个信息足以渲染出这个三角形。

因此,我们有一种方法可以渲染参数曲面。或者,换句话说,我们有一种方法可以生成一组近似给定参数曲面的三角形。这种近似可能不是一个好的近似,因为它可能有太多的三角形,其中一些三角形可能位置不正确或太小。然而,这种情况可以通过"自适应"技术来改进。自适应技术动态调整三角形的大小、数量和位置,可以很好的逼近原曲面的形状。

隐式曲面

隐式曲面在建模中非常有用。例如,假设我们给出了两个曲面,并希望找到一个可以平滑连接这两个曲面的第三个曲面。这个过程称为混合,第三个曲面是给定曲面的混合曲面。当然,这个混合曲面不是唯一的,通常以隐式形式出现。下图显示了一个混合曲面(黄色),它混合了绿色和蓝色曲面。混合曲面提供了从绿色曲面到蓝色曲面的平滑过渡。

img

除了混合,许多应用和计算,如偏移都会自然生成代数曲面。事实上,在许多情况下,代数曲面非常有用。点分类就是一个很好的例子。

点分类是确定给定点是位于曲面内部、上还是外部。为参数曲面设计这样的算法并不容易;然而,对于隐式曲面来说,这是一件简单的事情。假设给定点是 (a,b,c)(a, b, c),隐式曲面由 p(x,y,z)=0p(x, y, z) = 0 给出。那么,如果 p(a,b,c)p(a, b, c) 大于、等于或小于零,(a,b,c)(a, b, c) 位于曲面的外部、上还是内部。

要计算曲面的法向量,使用代数曲面的表达就很容易。多项式 p(x,y,z)=0p(x, y, z) = 0形式导数向量就是它的梯度,也被称为形式梯度形式导数向量。这个向量包含了多项式在各个变量方向上的导数信息:

(p)=(px,py,pz)\nabla(p)=\left(\frac{\partial p}{\partial x},\frac{\partial p}{\partial y},\frac{\partial p}{\partial z}\right)

一旦得到了某点的法向量,就可以很容易地计算曲面的切平面。

遗憾的是,要显示一个代数曲面并不容易。最简单但也最耗时的方法是光线追踪。许多光线追踪器允许用户指定一个隐式方程。POVRAYRadiance 是很好的例子。然而,光线追踪非常慢。另一种可能性是三角化曲面,这与我们之前对参数曲面所做的类似。

然而,对于隐式曲面,情况是不同的,因为没有可以进行三角剖分的区域,因为三角化必须直接在曲面上进行。能够将隐式曲面细分为多边形(不一定是三角形)的程序通常被称为多边形生成器。开发这样的多边形生成器并不容易,仍然是一个研究问题。

下图是使用多边形生成器生成的曲面,左侧的曲面是双曲抛物面,右侧的是环形杜宾环面,这是一个四次有理曲面。这两个曲面被三角化为大量小三角形,每个三角形都使用随机颜色着色。然而实际上,并不需要这么多的三角形。

imgimg

奇点

多边形生成器的一个普遍问题是,它们中的大多数并不很好地处理奇点。如果参数或隐式曲面上的一个点的所有偏导数都为零,则该点是奇点。奇点是曲面自相交或曲面上锐角的地方,下图显示了不同类型的奇点。

imgimgimg

第一个是一个立方曲面,其方程为:

x2+y3y2+z2=0x^2 + y^3 - y^2 + z^2 = 0

这个曲面的梯度为:

(2x,3y22y,2z)(2x, 3y^2 - 2y, 2z)

因此,(0,0,0)(0,0,0) 是一个奇点,因为在这一点上梯度的所有分量都为零,(0,2/3,0)(0, 2/3, 0) 处是另一个奇点。

中间的图形的方程如下:

x3+2xzyz2=0-x^3 + 2xz - yz^2 = 0

这个曲面的梯度向量为:

(2x2+2z,2yz,2xy2)(-2x^2 + 2z, -2yz, 2x - y^2)

若要求奇点,则每个分量都必须是0,根据第二个分量,我们有 y=0y = 0z=0z = 0。如果 y=0y = 0,第三个分量要求 xx 为零,第一个分量要求 zz 为零。如果 z=0z = 0,第一个分量要求 xx 为零,第三个分量要求 xx 为零。这两种情况得到的奇点都为 (0,0,0)(0,0,0)

前两种情况只有孤立的奇点,而奇点页可以在一条直线上,甚至可以在一条曲线上。我们看上面的右图,其方程为:

x2y+x2yz2z2=0-x^2y + x^2 - yz^2 - z^2 = 0

曲面的梯度向量为:

(2xy+2x,(x2+z2),2z)(-2xy + 2x, -(x^2 + z^2), -2z)

如果 z=0z = 0,根据第二个分量,意味着 xx 也必须为零。如果 xxzz 都为零,第一个分量也将为零,不管 yy 可能有什么值。意味着只要 x=z=0x = z = 0yy 有任意值,则该点就是奇点。因此,yy 轴包含所有奇点。图中画出了三条线。它们都位于曲面上;垂直的那条线是 yy 轴,即包含所有奇点的自交线。

构造贝塞尔(Bézier)曲面

贝塞尔曲面由一组二维的控制点集 pi,j\mathbf{p}_{i,j} 定义,其中 ii 的范围是 0 到 mmjj 的范围是 0 到 nn。因此,在这种情况下,我们有 m+1m + 1 行、n+1n + 1 列控制点,pi,j\mathbf{p}_{i,j} 表示第 ii 行第 jj 列的控制点。我们总共有 (m+1)(n+1)(m + 1)(n + 1) 个控制点。

以下是 m+1m + 1n+1n + 1 列控制点定义的贝塞尔曲面的方程:

p(u,v)=i=0mj=0nBm,i(u)Bn,j(v)pi,jp(u, v) = \sum_{i=0}^{m} \sum_{j=0}^{n} B_{m,i}(u) B_{n,j}(v)\mathbf{p}_{i,j}

其中 Bm,i(u)B_{m,i}(u)Bn,j(v)B_{n,j}(v) 分别是 uu 方向和 vv 方向的第 ii 个和第 jj 个贝塞尔基函数。这些基函数定义如下:

Bm,i(u)=m!i!(mi)!ui(1u)miBn,j(v)=n!j!(nj)!vj(1v)njB_{m,i}(u) = \frac{m!}{i!(m-i)!} u^i (1-u)^{m-i} \\ B_{n,j}(v) = \frac{n!}{j!(n-j)!} v^j (1-v)^{n-j}

由于 Bm,i(u)B_{m,i}(u)Bn,j(v)B_{n,j}(v)mm 阶和 nn 阶的函数,我们可以说这是一个 (m,n)(m,n) 阶的贝塞尔曲面。控制点集通常被称为 贝塞尔网控制网。参数 uuvv 在 0 到 1 的范围内,因此贝塞尔曲面将参数域上的单位正方形映射到空间中的一个矩形曲面片。

下图显示了一个由 3 行 3 列(9 个)控制点定义的贝塞尔曲面,因此是一个阶数为(2,2)的贝塞尔曲面。

基函数

贝塞尔曲面的基函数是控制点的系数。从定义中可以清楚地看出,这些二维基函数是两个一维贝塞尔基函数的乘积,因此贝塞尔曲面的基函数是定义在单位正方形上的两个变量 uuvv 的参数曲面

下图显示了控制点 p0,0\mathbf{p}_{0,0}(左)和 p1,1\mathbf{p}_{1,1}(右)的基函数。对于控制点 p0,0\mathbf{p}_{0,0},其基函数是 uu 方向上的一维贝塞尔基函数 B2,0(u)B_{2,0}(u)vv 方向上的 B2,0(v)B_{2,0}(v) 的乘积。在左图中,B2,0(u)B_{2,0}(u)B2,0(v)B_{2,0}(v) 以及它们的乘积(以线框图显示)都显示出来了。右图显示了 p1,1\mathbf{p}_{1,1} 的基函数,它是 uu 方向上的 B2,1(u)B_{2,1}(u)vv 方向上的 B2,1(v)B_{2,1}(v) 的乘积。

imgimg

张量积曲面

张量积通过两条曲线"相乘"来构造曲面。给定两条贝塞尔、B样条或NURBS曲线,张量积方法通过将第一条曲线的基函数与第二条曲线的基函数相乘,并将结果作为一组二维控制点的基函数来构造曲面。以这种方式生成的曲面称为张量积曲面。因此,贝塞尔曲面、B样条曲面和NURBS曲面都是张量积曲面。

贝塞尔曲面的重要性质

这里列出了几个贝塞尔曲面的重要性质。这些性质可以通过与贝塞尔曲线类似的方式证明。可以将这些重要性质与贝塞尔曲线的性质进行比较。

贝塞尔曲面的方程:

p(u,v)=i=0mj=0nBm,i(u)Bn,j(v)pi,jp(u, v) = \sum_{i=0}^{m} \sum_{j=0}^{n} B_{m,i}(u) B_{n,j}(v) p_{i,j}

其中两个一维基函数定义如下:

Bm,i(u)=m!i!(mi)!ui(1u)miBn,j(v)=n!j!(nj)!vj(1v)njB_{m,i}(u)=\frac{m!}{i!(m-i)!}u^i(1-u)^{m-i} \\ B_{n,j}(v)=\frac{n!}{j!(n-j)!}v^j(1-v)^{n-j}

性质

  • p(u,v)p(u, v) 经过控制网格四个角上的控制点:p0,0p_{0,0}, pm,0p_{m,0}, pm,np_{m,n}p0,np_{0,n}

    我们有 p(0,0)=p0,0p(0,0) = p_{0,0}, p(1,0)=pm,0p(1,0) = p_{m,0}, p(0,1)=p0,np(0,1) = p_{0,n}p(1,1)=pm,np(1,1) = p_{m,n}

  • 非负性: 对于所有的 m,n,i,jm, n, i, juuvv(取值范围为[0,1][0,1]),Bm,i(u)B_{m,i}(u)Bn,j(v)B_{n,j}(v) 都是非负的

  • 单位分割(Partition of Unity): 对于[0,1][0,1]范围内的所有 uuvvBm,i(u)Bn,j(v)B_{m,i}(u) B_{n,j}(v) 的和是1。

    uuvv位于[0,1][0,1]时,以下条件成立:

    i=0mj=0nBm,i(u)Bn,j(v)=1\sum_{i=0}^{m} \sum_{j=0}^{n} B_{m,i}(u) B_{n,j}(v) = 1

  • 凸包性质: 贝塞尔曲面 p(u,v)p(u, v) 位于由其控制网格定义的凸包内。

    由于 p(u,v)p(u, v) 是所有控制点的线性组合,并且系数之和为 1,因此曲面位于其控制点的凸包内。

  • 仿射不变性: 这意味着对贝塞尔曲面应用仿射变换,可以通过对所有控制点应用变换来实现,并且由变换后的控制点定义的曲面与将变换应用到曲面方程得到的新曲面是相同的。

  • 变差减少性质: 对于曲面来说,没有这样的性质。

等参数曲线

参数曲面的定义为:

f(u,v)=(x(u,v),y(u,v),z(u,v))\mathbf{f}(u, v) = (x(u, v), y(u, v), z(u, v))

固定参数 uuaa 时,等参数曲线的定义为 f(a,v)\mathbf{f}(a, v)。这个函数只有一个变量 vv,因此表示 vv 方向上的一条曲线。类似地,固定 vvbb 的等参数曲线为 f(u,b)\mathbf{f}(u, b)

贝塞尔曲面上的等参数曲线具有非常简单的结构,实际上在任何张量积曲面上的等参数曲线也是如此。在贝塞尔曲面的方程中,基函数 Bm,i(u)B_{m,i}(u) 仅依赖于索引 ii 并且可以独立出来,如下:

p(u,v)=i=0mBm,i(u)(j=0nBn,j(v)pi,j)\mathbf{p}(u,v)=\sum_{i=0}^mB_{m,i}(u)\left(\sum_{j=0}^nB_{n,j}(v)\mathbf{p}_{i,j}\right)

括号内的表达式为基函数 Bn,j(v)B_{n,j}(v) 和控制点 pi,jp_{i,j} 的乘积,虽然基函数不依赖于 ii;但控制点依赖于ii的取值。因此,我们可以定义一个新的函数 qi(v)q_i(v) 来简化一下:

qi(v)=j=0nBn,j(v)pi,jq_i(v) = \sum_{j=0}^{n}B_{n,j}(v) p_{i,j}

显然,每个 qi(v)q_i(v) 是由控制点 pi,0,pi,1,,pi,np_{i,0}, p_{i,1}, \ldots, p_{i,n} 定义的贝塞尔曲线(即第 ii 行控制点)。因此,我们有 m+1m + 1 个新的点 q0(v),q1(v),,qm(v)q_0(v), q_1(v), \ldots, q_m(v)。由于 vv 是固定的,可以视为常数,点 q0(v),q1(v),,qm(v)q_0(v), q_1(v), \ldots, q_m(v) 不会随着 uu 的变化而改变位置。因此,曲面方程变为:

p(u,v)=i=0mBm,i(u)qi(v)p(u, v) = \sum_{i=0}^{m} B_{m,i}(u) q_i(v)

由于 vv 是固定的,p(u,v)p(u, v) 实际上是一个关于uu的单变量参数方程,因此 p(u,v)p(u, v) 表示曲面上的一条曲线。这是一条由 m+1m + 1 个控制点 q0(v),q1(v),,qm(v)q_0(v), q_1(v), \ldots, q_m(v) 定义的 uu 方向的贝塞尔曲线。

因此,我们得出结论:固定参数 vv 得到的等参数曲线是由一组控制点定义的贝塞尔曲线,这些控制点可以从曲面方程计算得出。 若固定参数uu,可以得出相同的结论。以下显示了贝塞尔曲面上两个方向上等参数曲线的图:

Isoparametric curves on a Bézier surface

边界曲线

有四个特殊的等参数曲线:p(0,v),p(1,v),p(u,0)p(0, v), p(1, v), p(u, 0)p(u,1)p(u, 1)。这些是边界曲线(曲面片段的边界),因为它们将参数域上单位正方形的边界映射到曲面上。将 uu 设置为 0 和 1,将 vv 设置为 0 和 1,可以得到边界曲线的方程:

p(0,v)=j=0nBn,j(v)p0,jp(1,v)=j=0nBn,j(v)pm,jp(u,0)=i=0mBm,i(u)pi,0p(u,1)=i=0mBm,i(u)pi,n\begin{gathered} \mathbf{p}(0,v) =\sum_{j=0}^{n}B_{n,j}(v)\mathbf{p}_{0,j} \\ \mathbf{p}(1,v) =\sum_{j=0}^nB_{n,j}(v)\mathbf{p}_{m,j} \\ \mathbf{p}(u,0) =\sum_{i=0}^mB_{m,i}(u)\mathbf{p}_{i,0} \\ \mathbf{p}(u,1) =\sum_{i=0}^mB_{m,i}(u)\mathbf{p}_{i,n} \end{gathered}

因此,u=0u = 0u=1u = 1 对应的边界曲线是由第 00 行和第 mm 行控制点定义的贝塞尔曲线。类似地,v=0v = 0v=1v = 1 对应的边界曲线是由第 00 列和第 nn 列控制点定义的贝塞尔曲线。

uu 方向和 vv 方向

我们知道控制点的数量被分为 m+1m + 1n+1n + 1 列,那么行、列与 uuvv 方向之间的关系是什么?回想一下,vv 方向表示的是当 uu 固定为常数时的参数曲线。在这种情况下,控制点的定义可以重写成如下形式:

p(u,v)=i=0mBm,i(u)(j=0nBn,j(v)pi,j)\mathbf{p}(u,v)=\sum_{i=0}^mB_{m,i}(u)\left(\sum_{j=0}^nB_{n,j}(v)\mathbf{p}_{i,j}\right)

因此,随着 vv 的变化,括号内的表达式表示的是由控制点 pi,0,pi,1,,pi,np_{i,0}, p_{i,1}, \ldots, p_{i,n} 定义的贝塞尔曲线,这些是第 ii 行的控制点。

因此,vv 方向的曲线沿水平变化,类似的我们可以知道 uu 方向的曲线是沿着竖直方向变化的。

例如,边界曲线 p(0,v)p(0, v)p(1,v)p(1, v)vv 方向上,分别由第 0 行和第 nn 行控制点定义;边界曲线 p(u,0)p(u, 0)p(u,1)p(u, 1)uu 方向上,分别由第 0 列和第 mm 列控制点定义。

张量积曲面再探

现在研究一下张量积的实际含义。让我们回到上面的方程。如果我们将控制点排列成一个 m+1m + 1n+1n + 1 列的矩阵:

[p0,0p0,1p0,np1,0p1,1p1,npm,0pm,1pm,n]\left.\left[\begin{array}{cccc}\mathbf{p}_{0,0}&\mathbf{p}_{0,1}&\cdots&\mathbf{p}_{0,n}\\\mathbf{p}_{1,0}&\mathbf{p}_{1,1}&\cdots&\mathbf{p}_{1,n}\\\vdots&&\ddots&\vdots\\\mathbf{p}_{m,0}&\mathbf{p}_{m,1}&\cdots&\mathbf{p}_{m,n}\end{array}\right.\right]

并将 vv 方向贝塞尔曲线的基函数排列成一个 n+1n + 1 行的列矩阵:

[Bn,0(v)Bn,1(v)Bn,n(v)]\left.\left[\begin{array}{c}B_{n,0}(v)\\B_{n,1}(v)\\\vdots\\B_{n,n}(v)\end{array}\right.\right]

那么括号内的结果(j=0nBn,j(v)pi,j)\left(\sum_{j=0}^nB_{n,j}(v)\mathbf{p}_{i,j}\right)可以重写为一个矩阵乘积:

[p0,0p0,1p0,np1,0p1,1p1,npm,0pm,1pm,n].[Bn,0(v)Bn,1(v)Bn,n(v)]\left.\left[\begin{array}{cccc}\mathbf{p}_{0,0}&\mathbf{p}_{0,1}&\cdots&\mathbf{p}_{0,n}\\\mathbf{p}_{1,0}&\mathbf{p}_{1,1}&\cdots&\mathbf{p}_{1,n}\\\vdots&&\ddots&\vdots\\\mathbf{p}_{m,0}&\mathbf{p}_{m,1}&\cdots&\mathbf{p}_{m,n}\end{array}\right.\right].\left[\begin{array}{c}B_{n,0}(v)\\B_{n,1}(v)\\\vdots\\B_{n,n}(v)\end{array}\right]

如果我们将 uu 方向的贝塞尔曲线基函数写成一个 m+1m + 1 行的行矩阵,那么结果就是有 m+1m + 1 个元素的列矩阵:

[Bm,0(u),Bm,1(u),,Bm,m(u)][B_{m,0}(u),B_{m,1}(u),\cdots,B_{m,m}(u)]

因此,贝塞尔曲线的方程就变成了三个矩阵的乘积,如下所示:

p(u,v)=[Bm,0(u),Bm,1(u),,Bm,m(u)][p0,0p0,1p0,np1,0p1,1p1,npm,0pm,1pm,n][Bn,0(v)Bn,1(v)Bn,n(v)]\left.\mathbf{p}(u,v)=\left[B_{m,0}(u),B_{m,1}(u),\cdots,B_{m,m}(u)\right]\cdot\left[\begin{array}{cccc}\mathbf{p}_{0,0}&\mathbf{p}_{0,1}&\cdots&\mathbf{p}_{0,n}\\\mathbf{p}_{1,0}&\mathbf{p}_{1,1}&\cdots&\mathbf{p}_{1,n}\\\vdots&&\ddots&\vdots\\\mathbf{p}_{m,0}&\mathbf{p}_{m,1}&\cdots&\mathbf{p}_{m,n}\end{array}\right.\right]\cdot\left[\begin{array}{c}B_{n,0}(v)\\B_{n,1}(v)\\\vdots\\B_{n,n}(v)\end{array}\right]

因此,我们将贝塞尔曲面的定义转换为矩阵乘积形式。由于控制点矩阵中的每个元素也是一个矩阵(即,每个控制点可以被认为是一个向量,因此可以视为一个矩阵),这是数学中的张量积形式。因此,贝塞尔曲面是张量积曲面

贝塞尔曲面:de Casteljau算法

可以对 De Casteljau 算法扩展以处理贝塞尔曲面。准确地说,当给定 (u,v)(u, v) 时,可以使用De Casteljau 算法来找到贝塞尔曲面 p(u,v)\mathbf{p}(u, v) 上对应的点。下面将基于前面提到的等参数曲线的概念进行讨论。

回想一下贝塞尔曲面的方程:

p(u,v)=i=0mj=0nBm,i(u)Bn,j(v)pi,jp(u, v) = \sum_{i=0}^{m} \sum_{j=0}^{n} B_{m,i}(u) B_{n,j}(v)\mathbf{p}_{i,j}

可以重写为以下形式:

p(u,v)=i=0mBm,i(u)(j=0nBn,j(v)pi,j)\mathbf{p}(u,v)=\sum_{i=0}^mB_{m,i}(u)\left(\sum_{j=0}^nB_{n,j}(v)\mathbf{p}_{i,j}\right)

对于 i=0,1,,mi = 0, 1, \ldots, mqi(v)\mathbf{q}_i(v) 的定义如下:

qi(v)=j=0nBn,j(v)pi,j\mathbf{q}_i(v) = \sum_{j=0}^{n} B_{n,j}(v) \mathbf{p}_{i,j}

对于固定的 vv 值,我们有 m+1m + 1 个点 q0(v),q1(v),,qm(v)\mathbf{q}_0(v), \mathbf{q}_1(v), \ldots, \mathbf{q}_m(v)。每个 qi(v)\mathbf{q}_i(v) 是由控制点 pi,0,pi,1,,pi,n\mathbf{p}_{i,0}, \mathbf{p}_{i,1}, \ldots, \mathbf{p}_{i,n} 定义的贝塞尔曲线上的一个点。将上式代回曲面方程可以简化成:

p(u,v)=i=0mBm,i(u)qi(v)\mathbf{p}(u,v)=\sum_{i=0}^mB_{m,i}(u)\mathbf{q}_i(v)

这意味着 p(u,v)\mathbf{p}(u, v) 是由 m+1m + 1 个控制点 q0(v),q1(v),,qm(v)\mathbf{q}_0(v), \mathbf{q}_1(v), \ldots, \mathbf{q}_m(v) 定义的贝塞尔曲线上的一个点。因此,我们得出以下结论:

要在贝塞尔曲面上找到点 p(u,v)\mathbf{p}(u, v),我们可以找到 m+1m + 1 个点 q0(v),q1(v),,qm(v)\mathbf{q}_0(v), \mathbf{q}_1(v), \ldots, \mathbf{q}_m(v),然后根据这些控制点可以计算得出 p(u,v)\mathbf{p}(u, v)

这个结论为我们计算 p(u,v)\mathbf{p}(u, v) 提供了一个简单的方法。因为每个点 qi(v)\mathbf{q}_i(v) 是由第 ii 行控制点:pi,0,pi,1,,pi,n\mathbf{p}_{i,0}, \mathbf{p}_{i,1}, \ldots, \mathbf{p}_{i,n} 定义的贝塞尔曲线上的一个点:对于第 ii 行控制点(vv值已知),我们可以对贝塞尔曲线应用 De Casteljau 算法来计算 qi(v)\mathbf{q}_i(v)。对 m+1m + 1 行都使用 De Casteljau 算法之后(即,每行一次),我们就得到了 q0(v),q1(v),,qm(v)\mathbf{q}_0(v), \mathbf{q}_1(v), \ldots, \mathbf{q}_m(v)。然后,再对这 m+1m + 1 个控制点应用 De Casteljau 算法(uu值已知),最终可以得到曲面上的点 p(u,v)\mathbf{p}(u, v)

下图说明了这个概念。给定的曲面是一个由 3x3 控制网定义的二阶(2,2)贝塞尔曲面。假设 u=23u = \frac{2}{3}v=13v = \frac{1}{3}。为了求 q0(13)\mathbf{q}_0(\frac{1}{3}),我们取第 0 行的控制点 p0,0,p0,1\mathbf{p}_{0,0}, \mathbf{p}_{0,1}p0,2\mathbf{p}_{0,2}v=13v = \frac{1}{3},对这个贝塞尔曲线应用 De Casteljau 算法。对第一行和第二行重复这个过程(第一行和第二行都满足 v=13v = \frac{1}{3})。这产生了三个中间控制点 q0(13),q1(13)\mathbf{q}_0(\frac{1}{3}), \mathbf{q}_1(\frac{1}{3})q2(13)\mathbf{q}_2(\frac{1}{3})。最后,对这三个新的控制点应用 De Casteljau 算法(u=23u = \frac{2}{3} 已知)。结果是 p(23,13)\mathbf{p}(\frac{2}{3},\frac{1}{3}),图中用黄色显示。

img

下面显示的是给定贝塞尔曲面的示例。控制点显示为白色。该曲面控制网有四行五列,因此是一个阶数为 (3,4) 的贝塞尔曲面。对于每一行,首先会在红色线段上计算出一些中间控制点, 图中显示了四个中间控制点 q0,q1,q2\mathbf{q}_0, \mathbf{q}_1, \mathbf{q}_2q3\mathbf{q}_3,蓝色多段线表示由中间控制点 q0,q1,q2\mathbf{q}_0, \mathbf{q}_1, \mathbf{q}_2q3\mathbf{q}_3 连成的控制多段线,在这个曲面上的最终点 p(u,v)\mathbf{p}(u,v) 以黑色球体显示。

img

最后,下面是对这个算法的总结:

Inputm+1m + 1 行和 n+1n + 1 列的控制点和 (u,v)(u, v)
Output:曲面上的点 p(u,v)\mathbf{p}(u, v)
for i=0i = 0 to mm do:
begin
对第 ii 行控制点应用 De Casteljau 算法(vv已知);
设得到的点为 qi(v)\mathbf{q}_i(v)
end
q0(v),q1(v),,qm(v)\mathbf{q}_0(v), \mathbf{q}_1(v), \ldots, \mathbf{q}_m(v) 应用 De Casteljau 算法(uu 已知);
得到的点是 p(u,v)\mathbf{p}(u, v)

B样条曲面:构造

给定以下信息:

  1. 一组 m+1m + 1n+1n + 1 列的控制点 pi,j\mathbf{p}_{i,j},其中 0im0 \leq i \leq m0jn0 \leq j \leq n

  2. uu 方向上有 h+1h + 1 个节点,节点向量 U={u0,u1,,uh}U = \{ u_0, u_1, \ldots, u_h \}

  3. vv 方向上有 k+1k + 1 个节点,节点向量 V={v0,v1,,vk}V = \{ v_0, v_1, \ldots, v_k \}

  4. uu 方向的阶数为 pp

  5. vv 方向的阶数为 qq

根据这些信息定义的 B 样条曲面如下:

p(u,v)=i=0mj=0nNi,p(u)Nj,q(v)pi,jp(u, v) = \sum_{i=0}^{m} \sum_{j=0}^{n} N_{i,p}(u) N_{j,q}(v) \mathbf{p}_{i,j}

其中 Ni,p(u)N_{i,p}(u)Nj,q(v)N_{j,q}(v) 分别是 uu 方向和 vv 方向的 B 样条基函数,次数分别为 ppqq。注意,B样条曲面必须满足基本恒等式,即:h=m+p+1h = m + p + 1k=n+q+1k = n + q + 1

B 样条曲面是张量积曲面的另一个例子。与贝塞尔曲面一样,控制点集通常称为控制网uuvv 的范围是 0 到 1。因此,B 样条曲面是将参数空间中的单位正方形映射到一个空间中的矩形曲面片上。

下图显示了一个由 6 行 6 列控制点定义的 B 样条曲面:

img

uu 方向的节点向量为 U={0,0,0,0.25,0.5,0.75,1,1,1}U = \{ 0, 0, 0, 0.25, 0.5, 0.75, 1, 1, 1 \},阶数为 2。vv 方向的节点向量为 V={0,0,0,0,0.33,0.66,1,1,1,1}V = \{ 0, 0, 0, 0, 0.33, 0.66, 1, 1, 1, 1 \},阶数为 3。

基函数

控制点 pi,j\mathbf{p}_{i,j} 的系数是 uu 方向的一维 B 样条基函数 Ni,p(u)N_{i,p}(u)vv 方向的一维 B 样条基函数 Nj,q(v)N_{j,q}(v) 的乘积,这些乘积都是二维 B 样条函数。下图显示了控制点 p2,0,p2,1,p2,2,p2,3,p2,4\mathbf{p}_{2,0}, \mathbf{p}_{2,1}, \mathbf{p}_{2,2}, \mathbf{p}_{2,3}, \mathbf{p}_{2,4}p2,5\mathbf{p}_{2,5} 的基函数。

imgimgimgimgimgimg

二维基函数显示为线框曲面。由于控制点在同一行上,uu 方向的基函数是固定的,而 vv 方向的基函数会变化。由于 B 样条基函数通常只在几个连续的节点区间上非零(局部修改特性),因此至少存在一个节点区间,使得两个一维B样条基函数都不为0,因此它们的乘积,即二维B样条基函数不为零

Clamped、Closed和Open B 样条曲面

B 样条曲线有三种类型,可以是Clamped、Closed或Open的,因此B 样条曲面也可以在每个方向上具有三种类型。

也就是说,我们让 B 样条曲面在 uu 方向上是Clamped的,在 vv 方向上是Closed。如果一个 B 样条在两个方向上都是Clamped,那么这个曲面就会通过控制点 p0,0,pm,0,p0,n\mathbf{p}_{0,0}, \mathbf{p}_{m,0}, \mathbf{p}_{0,n}pm,n\mathbf{p}_{m,n} 并且在这四个控制点处与控制网的八个边相切。

如果一个 B 样条曲面在某个方向上是Closed的,那么这个方向上的所有等参数曲线都是Closed曲线,并且曲面会变成管状。

如果一个 B 样条曲面在两个方向上都是Open的,那么曲面就不会通过控制点 p0,0,pm,0,p0,n\mathbf{p}_{0,0}, \mathbf{p}_{m,0}, \mathbf{p}_{0,n}pm,n\mathbf{p}_{m,n}。我们只讨论在两个方向上都是Clamped的 B 样条曲面。

下图显示了在两个方向上Clamped、Closed和Open的三个B 样条曲面。这三个曲面都同一组控制点定义,但是它们的节点向量不同,因为他们在uu方向和vv方向的曲线类型是不相同的。

imgimgimg

B 样条曲面的重要性质

这里列出了几个 B 样条曲面的重要性质。这些性质可以通过应用与B样条曲线中类似的方式证明

B 样条曲面的方程:

p(u,v)=i=0mj=0nNi,p(u)Nj,q(v)pi,jp(u, v) = \sum_{i=0}^{m} \sum_{j=0}^{n} N_{i,p}(u) N_{j,q}(v)\mathbf{p}_{i,j}

其中 uu 方向和 vv 方向的次数分别为 ppqq,有 m+1m + 1n+1n + 1 列个控制点。

  • 非负性: 对于所有的 p,q,i,jp, q, i, j 以及 0u10\le u \le10v10\le v \le 1Ni,p(u)N_{i,p}(u)Nj,q(v)N_{j,q}(v) 是非负的。

  • 单位分割(Partition of Unity): 对所有 0u10\le u \le10v10\le v \le 1 内的取值,Ni,p(u)Nj,q(v)N_{i,p}(u) N_{j,q}(v) 和为 1。

    准确地说,以下等式成立,其中 0u10\le u \le10v10\le v \le 1

    i=0mj=0nNi,p(u)Nj,q(v)=1\sum_{i=0}^{m} \sum_{j=0}^{n} N_{i,p}(u) N_{j,q}(v) = 1

  • 强凸包性质(Strong Convex Hull Property): 如果 (u,v)(u, v)[ui,ui+1)×[vj,vj+1)[u_i, u_{i+1}) \times [v_j, v_{j+1}) 内,则 p(u,v)p(u, v) 位于由控制点 ph,k\mathbf{p}_{h,k} 定义的凸包内,其中 iphii-p \leq h \leq ijqkjj-q \leq k \leq j

    B 样条曲面的这种强凸包性质源于B样条曲线的强凸包性质。对于 uu 方向,如果 uu[ui,ui+1)[u_i, u_{i+1}) 内,那么最多有 p+1p+1 个非零基函数,即 Ni,p(u),Ni1,p(u),,Nip,p(u)N_{i,p}(u), N_{i-1,p}(u), \ldots, N_{i-p,p}(u)。因此,只有在 ipi-pii 行的控制点在 uu 方向上有非零基函数。类似地,如果 vv[vj,vj+1)[v_j, v_{j+1}) 内,那么在这个结区间上最多有 q+1q+1 个非零基函数,即 Nj,q(v),Nj1,q(v),,Njq,q(v)N_{j,q}(v), N_{j-1,q}(v), \ldots, N_{j-q,q}(v)。因此,只有在 jqj-qjj 列的控制点在 vv 方向上有非零基函数。综合这两点,只有在 ipi-pii 行,jqj-qjj 列的控制点有非零基函数,这些基函数是非负的,并且它们的和是一,因此,p(u,v)p(u, v) 位于由这些控制点定义的凸包内。

    因此,定义在 [ui,ui+1)×[vj,vj+1)[u_i, u_{i+1}) \times [v_j, v_{j+1}) 上的曲面片位于凸包内。

  • 局部修改特性(Local Modification Scheme):

    如果 (u,v)(u, v) 在区域 [ui,ui+p+1)×[vj,vj+q+1)[u_i, u_{i+p+1}) \times [v_j, v_{j+q+1}) 外,那么 Ni,p(u)Nj,q(v)N_{i,p}(u) N_{j,q}(v) 是零。

    根据局部修改特性我们知道,在 uu 方向上,Ni,p(u)N_{i,p}(u)[ui,ui+p+1)[u_i, u_{i+p+1}) 上非零,并且在其他区间值为零。B 样条曲面的局部修改特性也继承于B样条曲线。下图中,如果控制点 p3,2\mathbf{p}_{3,2} 移动到一个新位置,只有移动的控制点上的邻近区域改变形状,其他地方保持不变。

    imgimg

  • 如果 uu 是重数为 ss 的节点,那么 p(u,v)p(u, v)uu 方向上是 CpsC^{p-s} 连续的,如果 vv 是重数为 tt 的节点,那么 p(u,v)p(u, v)vv 方向上是 CqtC^{q-t} 连续的。

  • 仿射不变性(Affine Invariance): 这意味着对 B 样条曲面应用仿射变换,可以通过对所有控制点应用变换来实现,并且由变换后的控制点定义的曲面与通过应用相同变换到曲面方程得到的曲面是相同的。

  • 变差减少性质(Variation Diminishing Property): 对于曲面来说,没有这样的性质。

  • 如果 m=pm = p, n=qn = q,并且 U={0,0,...,0,1,1,....,1}U = \{ 0, 0, ..., 0, 1, 1, ...., 1 \},那么 B 样条曲面就退化成贝塞尔曲面。

B-样条曲面: de Boor算法

前面我们提到了用 De Casteljau 算法计算贝塞尔曲面上一点,同样的,de Boor 算法也可以用于计算B样条曲面和 NURBS 曲面上一点。实际上,由于B样条曲面具有局部修改性质,de Boor 算法看起来非常类似于 De Casteljau 算法。将B样条曲面的方程写成如下形式:

p(u,v)=i=0mNi,p(u)(j=0nNj,q(v)pi,j)\mathbf{p}(u,v)=\sum_{i=0}^{m}N_{i,p}(u)\left(\sum_{j=0}^{n}N_{j,q}(v)\mathbf{p}_{i,j}\right)

对于固定的 ii 值,括号内的曲线就是由第 ii 行控制点定义的 B 样条曲线。我们定义 qi(v)\mathbf{q}_i(v) 如下:

qi(v)=j=0nNj,q(v)pi,j\mathbf{q}_i(v) = \sum_{j=0}^{n} N_{j,q}(v)\mathbf{p}_{i,j}

因此,qi(v)\mathbf{q}_i(v) 是由第 ii 行控制点定义的 B 样条曲线上的一个点。

如果 vv 在区间 [vd,vd+1)[v_d, v_{d+1}) 内,那么在计算 qi(v)\mathbf{q}_i(v) 时,只涉及 q+1q+1 个控制点,其中 qqNj,q(v)N_{j,q}(v) 的次数。
如果 vv 不等于 vdv_d,这些控制点是 pi,d,pi,d1,,pi,dq\mathbf{p}_{i,d}, \mathbf{p}_{i,d-1}, \ldots, \mathbf{p}_{i,d-q}
如果 vv 等于 vdv_d,一个重数为 tt 的节点,那么控制点是 pi,dt,pi,dt1,,pi,dq\mathbf{p}_{i,d-t}, \mathbf{p}_{i,d-t-1}, \ldots, \mathbf{p}_{i,d-q}

因此,从 dqd-qdtd-t 列的控制点,如果 vv 值不等于节点值,那么重数 tt 是零,我们可以对每一行应用 de Boor 算法,得到 m+1m + 1 个新的点 q0(v),q1(v),,qm(v)\mathbf{q}_0(v), \mathbf{q}_1(v), \ldots, \mathbf{q}_m(v),如下图所示:

img

将这些新点重新代入曲面方程,我们有:

p(u,v)=i=0mNi,p(u)qi(v)\mathbf{p}(u, v) = \sum_{i=0}^{m} N_{i,p}(u) \mathbf{q}_i(v)

因此,p(u,v)\mathbf{p}(u, v) 是由 q0(v),q1(v),,qm(v)\mathbf{q}_0(v), \mathbf{q}_1(v), \ldots, \mathbf{q}_m(v) 定义的 B 样条曲线上的一个点。因此,要找到 p(u,v)\mathbf{p}(u, v),我们需要找到这个曲线上对应于 uu 处的点。可以再次使用de Boor 算法计算得到。

uu 在节点区间 [uc,uc+1)[u_c, u_{c+1}) 内。根据局部修改性质,只有 p+1p+1 个控制点参与计算,其中 pp 是 B 样条曲线的次数。如果 uu 不等于 ucu_c,控制点是 qc(v),qc1(v),,qcp(v)\mathbf{q}_c(v), \mathbf{q}_{c-1}(v), \ldots, \mathbf{q}_{c-p}(v)。如果 uu 等于 ucu_c,则 uu 是重数为 ss 的节点,控制点是 qcs(v),qcs1(v),,qcp(v)\mathbf{q}_{c-s}(v), \mathbf{q}_{c-s-1}(v), \ldots, \mathbf{q}_{c-p}(v)

因此,尽管每一行控制点都可以产生一个 qi(v)\mathbf{q}_i(v),但并非所有行都是必需的,根据局部修改性质,只需要 p+1p+1 行。如下图所示:

img

总之,给定 uu[uc,uc+1)[u_c, u_{c+1}) 内和 vv[vd,vd+1)[v_d, v_{d+1}) 内,对于 cpc-pcsc-s 范围内的第 ii 行,对控制点 pi,dq,pi,dq+1,,pi,dt\mathbf{p}_{i,d-q}, \mathbf{p}_{i,d-q+1}, \ldots, \mathbf{p}_{i,d-t} 使用 de Boor 算法得到一个新的点 qi(v)\mathbf{q}_i(v)。然后,对控制点 qcp(v),qcp+1(v),,qcs(v)\mathbf{q}_{c-p}(v), \mathbf{q}_{c-p+1}(v), \ldots, \mathbf{q}_{c-s}(v) 使用 de Boor 算法计算得到 p(u,v)\mathbf{p}(u, v)

算法总结:

Input:一组 m+1m + 1n+1n + 1 列控制点,uu 方向和 vv 方向的节点向量,以及 (u,v)(u, v) 值。
**Output:**曲面上的点 p(u,v)\mathbf{p}(u, v)
算法
u[uc,uc+1)u \in [u_c, u_{c+1})
v[vd,vd+1)v \in [v_d, v_{d+1})
如果 uucu \neq u_c,让 ss 为零;否则,让 ssucu_c 的重数;
如果 vvdv \neq v_d,让 tt 为零;否则,让 ttvdv_d 的重数;
for i=cpi = c-p to csc-s do:
begin:
应用 de Boor 算法,控制点为 pi,dq,pi,dq+1,,pi,dt\mathbf{p}_{i,d-q}, \mathbf{p}_{i,d-q+1}, \ldots, \mathbf{p}_{i,d-t}vv 值给定;
结果为 qi(v)\mathbf{q}_i(v)
end
应用 de Boor 算法,控制点为 qcp(v),qcp+1(v),,qcs(v)\mathbf{q}_{c-p}(v), \mathbf{q}_{c-p+1}(v), \ldots, \mathbf{q}_{c-s}(v)uu 值给定;
结果为 p(u,v)\mathbf{p}(u, v)

下图显示了一个例子。B 样条曲面由 5×55 \times 5 个控制点和节点向量(uu方向和vv方向都是){0,0,0,0,0.5,1,1,1,1}\{0, 0, 0, 0, 0.5, 1, 1, 1, 1\} 定义。因此,两个方向的次数都是 3。

img

在图中,uuvv 都不是节点,uu 小于 0.5,而 vv 大于 0.5。对于 vv,由于它在 [0.5,1)[0.5, 1) 内,因此只有控制点 pi,1,pi,2,pi,3\mathbf{p}_{i,1}, \mathbf{p}_{i,2}, \mathbf{p}_{i,3}pi,4\mathbf{p}_{i,4} 参与 de Boor 算法的计算。由于 uu[0,0.5)[0,0.5) 内,在 uu 方向上,只使用了第 0 行、第 1 行、第 2 行和第 3 行控制点进行计算。在图中,红色折线用于计算点 qi(v)\mathbf{q}_i(v),而唯一的蓝色多段线用于计算曲面上的点(黑色球体)。