《Fundamentals of Computer Graphics》第五版 第十五章 曲线

489 阅读4分钟

曲线

任意维度空间中的曲线称为空间曲线(space curve)。曲线可通过以下两种方式来理解:

  1. n 维空间中的一维连续点集
  2. 一维空间到 n 维空间的连续映射

这里不考虑线的粗细。一条曲线包含无穷多个点,除端点外的每个点都有两个 “邻接点”。有些曲线没有端点,如:无限长的曲线、闭曲线。

指定一条曲线可以通过它的名字,比如:线段、圆、椭圆等,称为具名曲线(named curve)。没有特殊名字的曲线称为自由曲线(free-form curve)。数学上可通过以下三种方法指定曲线:

  1. 隐式曲线(implicit curve)表示通过形式如下的隐函数(implicit function)来定义:

    f(x,y)=0f(x, y) = 0
  2. 参数曲线(parametric curve)表示通过参数函数(parametric function)来定义:

    (x,y)=f(t)(x, y) = \vec{f}(t)

    其中,tt自由参数(free parameter)。

  3. 生成式(generative)或程序式(procedural)曲线,通过某个生成点的程序来表示,比如:分形。

一条曲线可能有多种表示。曲线本身和它的表示是两件事情,但经常混用。不同的表示方法各有优劣,计算机图形学中参数表示最常见,因为它更便于绘制。

参数化(Parameterizations)和重参数化(Reparameterizations)

对于区间 [a,b][a,b] 上的参数曲线 f(t)\vec{f}(t),可以给出另一种参数表示,它的参数在单位区间 [0,1][0,1] 上:

g(u)=a+(ba)uf2(u)=f(g(u))\begin{gathered} g(u) = a + (b - a)u \\ \vec{f_{2}}(u) = \vec{f}(g(u)) \end{gathered}

这种为已知参数曲线创建一个新的参数表示的过程称为重参数化(reparameterization),而自由参数之间的映射 gg 称为重参数化函数(reparameterization function)。重参数化可以让我们找到更方便的参数表示,但也让我们难以确认不同的参数表示是否对应同一条曲线。

通过弧长(arc length)——沿着曲线的距离——到位置的映射来定义参数曲线,称为弧长参数化(arc-length parameterization)。弧长参数通常使用 ss 来表示。弧长参数化可定义为:

df(s)ds=c\left|\frac{d\vec{f}(s)}{ds}\right| = c

弧长可通过下式计算:

s=0tdf(t)dtdts = \int_{0}^{t'}\left|\frac{d\vec{f}(t)}{dt}\right|dt

弧长参数化需要求解上述方程,一般情况下,无法找到封闭解,只能数值求解。通常,uu 表示单位区间上的自由参数,ss 表示弧长自由参数,tt 表示一般的自由参数。

分段参数表示

有些曲线无法用单个函数表示,可以将这种复杂曲线分成简单的曲线段:

f(u)={f1(2u)if u0.5f2(2u1)if u>0.5\vec{f}(u) = \left\{ \begin{aligned} &\vec{f_{1}}(2u) &&\text{if}\ u\leqslant 0.5 \\ &\vec{f_{2}}(2u - 1) &&\text{if}\ u > 0.5 \end{aligned} \right.

其中,f1\vec{f_{1}}f2\vec{f_{2}} 都是定义在单位区间上的参数曲线。有时为简单考虑,使用一种曲线类型来表示每个曲线段,这可能无法精确描述原始曲线,但是对具体应用场景而言已经足够了。

piecewise-parametric-curves.png

分段表示的一个优势是允许在如下因素间权衡:

  1. 与真实形状之间的接近程度
  2. 曲线段的复杂程度
  3. 曲线段数目

计算机图形学中通常倾向于使用相对简单的曲线段,如:线段、圆弧、多项式曲线段。

样条

样条(spline)最初指光滑的分段多项式函数(piecewise polynomial function),现如今指任意的分段多项式函数。

曲线性质

对于具名曲线,曲线性质由曲线类型决定。而自由曲线则需要一些通用性质来描述曲线。有些曲线性质从属于曲线上单个位置,称为局部性质(local property);有些则需要知道整条曲线上的信息,称为整体性质(global property)。局部性质包括:

  • 连续性(continuity)
  • 曲线上特定位置的坐标
  • 曲线上特定位置的方向
  • 曲率(curvature)

曲线穿过一个点,称为对该点插值(interpolate)。如果存在 tt 使得 f(t)=vf(t)=v,则称函数 ffvv 插值,插值的位置称为 site。

连续性

对于分段参数表示的曲线,一般要求,应满足连续性条件(continuity conditions)f1(1)=f2(0)\vec{f_{1}}(1)=\vec{f_{2}}(0)。如果曲线上任一点 nn 阶导数连续,则称曲线是 CnC^{n} 连续的。具体所需的连续性程度取决于应用场景。这种根据参数化来定义的连续性称为参数连续性(parametric continuity)。

如果只关心曲线本身的形状,可以定义几何连续性(geometric continuity):当曲线段以同样的方式参数化(比如弧长参数化)时曲线的导数互相匹配。一阶几何连续性 G1G^{1} 定义为:

f1(1)=kf2(0)\vec{f_{1}}'(1) = k\vec{f_{2}}'(0)

kk 是一个标量。几何连续性的限制比参数连续性更弱。

curve-continuity.png

多项式曲线段

计算机图形学中最常用的曲线表示是把多项式曲线段拼起来。

多项式表示

多项式的规范型(canonical form)如下:

f(t)=i=0naiti\mathbf{f}(t) = \sum_{i=0}^{n}\mathbf{a}_{i}t^{i}

上式可推广为:

f(t)=i=0ncibi(t)\mathbf{f}(t) = \sum_{i=0}^{n}\mathbf{c}_{i}\mathbf{b}_{i}(t)

其中,bi\mathbf{b}_{i} 是关于 tt 的多项式,称为基函数(basis function)或混合函数(blending function),它的选择取决于具体应用。高维空间中的曲线可以通过多个多项式来描述,或者使用上面的向量形式。

线段

p0\mathbf{p}_{0}p1\mathbf{p}_{1} 的线段的参数函数:

f(u)=(1u)p0+up1\mathbf{f}(u) = (1 - u)\mathbf{p}_{0} + u\mathbf{p}_{1}

其中,控制参数向量——也称为 control points——p=[p0,p1]\mathbf{p}=[\mathbf{p}_{0},\mathbf{p}_{1}] 中的每个元素称为控制点(control point)。

控制点可以是任意约束条件,而不一定是坐标。

除了端点之外,还有其它方式描述线段:

  1. 线段的中点、方向和长度;
  2. 一个端点和两端点间的相对位置;
  3. 线段的中点和一个端点。

线段也可以写为规范型:

f(u)=a0+ua1\mathbf{f}(u) = \mathbf{a}_{0} + u\mathbf{a}_{1}

线段可以通过 a0\mathbf{a}_{0}a1\mathbf{a}_{1} 来定义,但一般指定端点更方便。多项式的规范型可以表示为向量形式:

f(u)=uau=[1,u,u2,,un]\begin{gathered} \mathbf{f}(u) = \mathbf{u}\cdot\mathbf{a} \\ \mathbf{u} = [1, u, u^{2}, \cdots, u^{n}] \end{gathered}

其中,a\mathbf{a} 是规范型的系数。

多项式的矩阵形式

多项式的控制点可以通过规范型的系数表示为:

p=Ca\mathbf{p} = \mathbf{C}\mathbf{a}

其中,C\mathbf{C}约束矩阵(constraint matrix)。利用 C\mathbf{C} 的逆矩阵 B\mathbf{B}——基矩阵(basis matrix),可以从上式中求解出 a\mathbf{a},进而将多项式曲线表示为:

f(u)=uBp\mathbf{f}(u) = \mathbf{u}\mathbf{B}\mathbf{p}

任何形式的曲线都有相应的基矩阵,只要它是关于参数的线性组合。

二次多项式曲线

如果选取参数区间上的起点(u=0u=0)、中点(u=0.5u=0.5)、终点(u=1u=1)为控制点,约束矩阵和基矩阵如下:

C=[10010.50.25111]B=[100341242]\begin{aligned} \mathbf{C} &= \begin{bmatrix} 1 & 0 & 0 \\ 1 & 0.5 & 0.25 \\ 1 & 1 & 1 \end{bmatrix} \\ \mathbf{B} &= \begin{bmatrix} 1 & 0 & 0 \\ -3 & 4 & -1 \\ 2 & -4 & 2 \end{bmatrix} \end{aligned}

控制点 p=[f(0),f(0.5),f(1)]\mathbf{p}=[\mathbf{f}(0),\mathbf{f}(0.5),\mathbf{f}(1)]

参数曲线的导数是另一种常见的约束。多项式的一阶导数和二阶导数如下:

f(u)=i=1niui1aif(u)=i=2ni(i1)ui2ai\begin{aligned} \mathbf{f}'(u) &= \sum_{i=1}^{n}iu^{i-1}\mathbf{a}_{i} \\ \mathbf{f}''(u) &= \sum_{i=2}^{n}i(i-1)u^{i-2}\mathbf{a}_{i} \\ \end{aligned}

选择参数区间中点的位置、一阶导数、二阶导数为约束,则约束矩阵、基矩阵如下:

C=[10.50.25011002]B=[10.50.125010.5000.5]\begin{aligned} \mathbf{C} &= \begin{bmatrix} 1 & 0.5 & 0.25 \\ 0 & 1 & 1 \\ 0 & 0 & 2 \end{bmatrix} \\ \mathbf{B} &= \begin{bmatrix} 1 & -0.5 & 0.125 \\ 0 & 1 & -0.5 \\ 0 & 0 & 0.5 \end{bmatrix} \end{aligned}

控制点为 p=[f(0.5),f(0.5),f(0.5)]\mathbf{p}=[\mathbf{f}(0.5),\mathbf{f}'(0.5),\mathbf{f}''(0.5)]

三次多项式曲线

三次多项式曲线在图形学中很普遍。三次多项式的最常用的形式是厄米型(Hermite form),即指定起点和终点的位置和一阶导数。约束矩阵和基矩阵如下:

C=[1000010011110123]B=[1000010032312121]\begin{aligned} \mathbf{C} &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 1 & 1 & 1 & 1 \\ 0 & 1 & 2 & 3 \end{bmatrix} \\ \mathbf{B} &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ -3 & -2 & 3 & -1 \\ 2 & 1 & -2 & 1 \end{bmatrix} \end{aligned}

控制点为 p=[f(0),f(0),f(1),f(1)]\mathbf{p}=[\mathbf{f}(0),\mathbf{f}'(0),\mathbf{f}(1),\mathbf{f}'(1)]

混合函数(Blending Functions)

参数向量和基矩阵的乘积称为混合函数(blending function):

b(u)=uB\mathbf{b}(u) = \mathbf{u}\mathbf{B}

b(u)\mathbf{b}(u) 将控制点线性混合了起来:

f(u)=i=0nbi(u)pi\mathbf{f}(u) = \sum_{i=0}^{n}\mathbf{b}_{i}(u)\mathbf{p}_{i}

混合函数为曲线描述提供了一个很好的抽象。任何类型的函数都可以表示为控制点的线性组合,混合权重是自由参数的任意函数。

上式表明曲线拟合(插值)在一定程度上可以理解为混合型卷积滤波。

插值多项式(Interpolating Polynomials)

通常,一个 nn 次多项式可以穿过 n+1n+1 个值。如果给定需要穿过的值 p=[p0,,pn]\mathbf{p}=[\mathbf{p}_{0},\cdots,\mathbf{p}_{n}],和递增参数值 t=(t0,,tn)\vec{t}=(t_{0},\cdots,t_{n}),可以通过求解线性方程组得到插值多项式使得 f(ti)=pi\mathbf{f}(t_{i})=\mathbf{p}_{i}。此时混合函数 bi\mathbf{b}_{i} 称为插值基函数(interpolating basis function),一种优雅——尽管不是最高效的——的表示是拉格朗日型(Lagrange form):

bi(t)=j=0,jinttjtitj\mathbf{b}_{i}(t) = \prod_{j=0,j\neq i}^{n}\frac{t - t_{j}}{t_{i} - t_{j}}

插值多项式给出了一种定义插值曲线的机制。计算机图形学中很少使用高阶多项式表示曲线,而更常用插值样条曲线。

interpolating-polynomial.png

合并曲线段

结点(Knot)

分段参数函数的基本想法是将每一段限制在不同参数范围。每段的起点和终点称为结点(knot)。也可以把分段函数表述为基函数之和,其中每个基函数 bi\mathbf{b}_{i} 是一个分段函数。

knots.png

整个分段函数的结点就是每段结点的组合。将所有结点按升序存储为向量,称为结点向量(knot vector)。

可以看到,分段参数函数有两种表述方式:

  1. 不同参数范围相互独立的函数段
  2. 分段函数混合起来

相互独立的函数段

将每段函数组合起来,需要从整个函数的参数转换到每段函数的参数。最简单的做法是将整条曲线参数范围定义为 [0,n][0,n],其中曲线共 nn 段,然后再移动到所需范围。

合并曲线段

合并曲线段有以下三种方法:

  1. 共用点(shared-point)策略,相邻两条曲线段在交界处共用控制点。
  2. 依赖(dependency)策略,每当前一条曲线段的参数变化时,就将它在交界处的控制点复制给后一条曲线段。
  3. 使用显式方程描述曲线段的连接,每当其它参数变化时,就通过数值方法来保证曲线段连接。

虽然总是希望使用更简单的策略,但是所采用的策略本身也会限制曲线段的参数化方式。当使用共用点或依赖策略时,控制点的总数少于 nmn\ast mnn 是段数,mm 是每段的控制点数。

依赖策略可能没有局部性(locality)——曲线上一个控制点的变化只影响局部区域。局部区域可能较大,但一定是有限的。如果没有局部性,一个控制点的变化会沿着整条曲线传播到无穷远。

locality.png

共用点策略和依赖策略的局部性并非一成不变,而是取决于应用场景。局部性便于控制曲线,如果需要同时改变整条曲线,可以一致性地改变多个控制点。

三次曲线(Cubics)

图形学中经常使用三次多项式或线段来表示分段曲线。选择三次曲线的原因有:

  • C2C^{2} 连续性足以满足大多数视觉任务。
  • 三次曲线为一组点提供了最小曲率插值(minimum-curvature interpolant)。
  • 三次曲线可以在起点和终点指定位置和导数,因而具有很好的对称性
  • 三次曲线可以很好地权衡数值问题光滑性

然而,分段三次曲线没有一个完美的表示,任何三次曲线表示都无法同时满足如下三条性质:

  1. 插值性;
  2. 局部性;
  3. C2C^{2} 连续性。

这里的连续性是段间连续。

但是,对于上面任意两条,都可以找到一种同时满足它们的三次曲线表示。三次 B 样条曲线是 C2C^{2} 的,而且有局部性,但不是插值的;基样条曲线(Cardinal splines)和 Catmull-Rom 样条曲线是插值的,而且有局部性,但不是 C2C^{2} 的;自然三次曲线(natural cubics)是插值的,而且是 C2C^{2} 的,但没有局部性。

自然三次曲线(Natural Cubics)

分段三次曲线可以是 C2C^{2} 的,这需要在结点处将位置、一阶导数、二阶导数连接起来。每条曲线段都从前一条曲线段中接收三个参数。这条 C2C^{2} 连续的三次曲线链称为自然三次样条(natural cubic splines)。

每段自然三次曲线都需要通过端点位置、起点的一阶导数和二阶导数来参数化。相应的约束矩阵和基矩阵如下:

C=[1000010000201111]B=[10000100000.50110.51]\begin{aligned} \mathbf{C} &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 1 & 1 & 1 & 1 \end{bmatrix} \\ \mathbf{B} &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0.5 & 0 \\ -1 & -1 & -0.5 & 1 \end{bmatrix} \end{aligned}

控制点为 p=[f(0),f(0),f(0),f(1)]\mathbf{p}=[\mathbf{f}(0), \mathbf{f}'(0), \mathbf{f}''(0), \mathbf{f}(1)]。依赖策略将前一条曲线段的终点位置、一阶导数、二阶导数复制给后一条曲线段。如果有 nn 个控制点,则可以得到一条 n3n-3 段的自然三次样条。

自然三次样条的一个缺点是非局域,任何曲线段上的任何变化都要求整条曲线变化。另一个问题是自然三次样条只能控制整条曲线起点的导数。

厄米三次曲线(Hermite Cubics)

厄米三次样条允许指定曲线段端点的位置和一阶导数。通过指定结点处的位置和一阶导数,并采用共用点策略,可以得到一条 C1C^{1} 连续的样条曲线。如果控制点(包括位置、导数)共有 nn 个,那么所得到的厄米三次样条共有 (n2)/2(n-2)/2 段。

厄米三次样条可以保证局部性和 C1C^{1} 连续性。导数可以让用户通过导向量(derivative vector)终点来指定。

Hermite-cubics.png

三次基样条曲线(Cardinal Cubics)

三次基样条曲线(cardinal cubic spline)是一种 C1C^{1} 连续的插值曲线。对于 nn 个控制点,三次基样条曲线由 n3n-3 条穿过除首尾之外剩余所有点的曲线段构成。基样条曲线中,张力(tension)参数 t[0,1)t\in[0,1) 描述插值点间的曲线段绷得有多直,t=0t=0 对应 Catmull-Rom 样条曲线。

基样条曲线中的每一段由连续的四个控制点决定,曲线段连接第二和第三个点,起点的导数正比于第一个点指向第三个点的向量,终点的导数正比于第二个点指向第四个点的向量,张力参数决定了正比系数 s=(1t)/2s=(1-t)/2

f(0)=p2f(1)=p3f(0)=s(p3p1)f(1)=s(p4p2)\begin{aligned} \mathbf{f}(0) &= \mathbf{p}_{2} \\ \mathbf{f}(1) &= \mathbf{p}_{3} \\ \mathbf{f}'(0) &= s(\mathbf{p}_{3} - \mathbf{p}_{1}) \\ \mathbf{f}'(1) &= s(\mathbf{p}_{4} - \mathbf{p}_{2}) \end{aligned}

cardinal-cubic-segment.png

由上式可知,控制点 p=[f(1)f(0)/s,f(0),f(1),f(0)+f(1)/s]\mathbf{p}=[\mathbf{f}(1)-\mathbf{f}'(0)/s, \mathbf{f}(0), \mathbf{f}(1), \mathbf{f}(0)+\mathbf{f}'(1)/s],约束矩阵和基矩阵如下:

C=[111/s111000111111/s2/s3/s]B=[0100s0s02ss332sss2ss2s]\begin{aligned} \mathbf{C} &= \begin{bmatrix} 1 & 1-1/s & 1 & 1 \\ 1 & 0 & 0 & 0 \\ 1 & 1 & 1 & 1 \\ 1 & 1/s & 2/s & 3/s \end{bmatrix} \\ \mathbf{B} &= \begin{bmatrix} 0 & 1 & 0 & 0 \\ -s & 0 & s & 0 \\ 2s & s-3 & 3-2s & -s \\ -s & 2-s & s-2 & s \end{bmatrix} \end{aligned}

易知,基样条是 C1C^{1} 连续的、满足局部性的插值曲线,这让它变得很有用。

cardinal-splines.png

单个高次插值多项式相比于基样条三次曲线有如下缺点:

  • 容易过冲(overshoot),点数越多,过冲越糟。
  • 没有局部性。
  • 计算非局域,计算一个位置需要访问所有的点,而分段三次样条则只需访问附近的点。

基样条曲线无法穿过首尾两端的问题可以通过在两端各补一个点来解决。

contrast.png

近似曲线

插值策略(interpolation scheme)控制曲线的缺点是:低连续性、相邻控制点间曲线行为难以控制,因而近似策略(approximating scheme)更常用。在近似策略中,控制点虽然不会处于曲线上,但可以影响曲线形状,使得曲线行为更好,而且满足局部性。如果要对一组点插值,也可以先计算出控制点让近似曲线刚好穿过插值点。图形学中最重要的两类近似曲线是贝塞尔曲线(Bezier curves)和 B 样条曲线(B-spline curves)。

贝塞尔曲线(Bezier Curves)

以 Pierre Bezier 命名的贝塞尔曲线,是计算机图形学中最常用的自由曲线表示之一。贝塞尔曲线是多项式曲线,可以是任意次数。曲线穿过首尾两个控制点,剩余控制点决定其形状。复杂形状通常用多条低次贝塞尔曲线连接起来描述,计算机图形学中,三次贝塞尔曲线常用于此目的。

贝塞尔曲线可按如下方式构造:

  • 曲线在 u=0u=0u=1u=1 分别穿过首、尾控制点。
  • 曲线在起点的一阶导数等于第一个点指向第二个点的向量乘以曲线次数,终点同理。
  • 曲线在起点处的 nn 阶导数依赖于前 n+1n+1 个点,终点类似。

cubic-bezier-curve.png

三次贝塞尔曲线的控制点 p=[f(0),f(0)+f(0)/3,f(1)f(1)/3,f(1)]\mathbf{p}=[\mathbf{f}(0), \mathbf{f}(0)+\mathbf{f}'(0)/3, \mathbf{f}(1)-\mathbf{f}'(1)/3, \mathbf{f}(1)],约束矩阵和基矩阵如下:

C=[100011/30012/31/301111]B=[1000330036301331]\begin{aligned} \mathbf{C} &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ 1 & 1/3 & 0 & 0 \\ 1 & 2/3 & 1/3 & 0 \\ 1 & 1 & 1 & 1 \end{bmatrix} \\ \mathbf{B} &= \begin{bmatrix} 1 & 0 & 0 & 0 \\ -3 & 3 & 0 & 0 \\ 3 & -6 & 3 & 0 \\ -1 & 3 & -3 & 1 \end{bmatrix} \end{aligned}

因此,三次贝塞尔曲线可以表示为:

f(u)=(1u)3p0+3u(1u)2p1+3u2(1u)p2+u3p3\mathbf{f}(u) = (1-u)^{3}\mathbf{p}_{0} + 3u(1-u)^{2}\mathbf{p}_{1} + 3u^{2}(1-u)\mathbf{p}_{2} + u^{3}\mathbf{p}_{3}

一般地,nn 次贝塞尔曲线可以表示为:

p(u)=k=0nbk,n(u)pk\mathbf{p}(u) = \sum_{k=0}^{n}b_{k,n}(u)\mathbf{p}_{k}

其中,混合函数:

bk,n(u)=Cnkuk(1u)nk,0knb_{k,n}(u) = C_{n}^{k}u^{k}(1-u)^{n-k},\quad 0\leqslant k\leqslant n

上式也称为伯恩斯坦基多项式(Bernstein basis polynomials)。

bezier-segments.png

贝塞尔曲线有以下性质:

  • 曲线包在控制点的凸包内。
  • 变差减少(variation diminishing),即任意直线与曲线之间的交点数目不会超过与控制点间折线段的交点数目。 variation-diminishing.png
  • 对称性(symmetric),即控制点的顺序反过来所得到的曲线不变,只是参数反了过来。
  • 仿射不变(affine invariant),即对控制点做仿射变换等价于对曲线本身做仿射变换。
  • 计算(evaluating)和细分(subdividing)贝塞尔曲线都有一些好的、简单的算法。由于允许高效细分,因此可以用分治法给出一些高效的算法来完成某些重要任务,如渲染贝塞尔曲线、用线段近似、计算两条曲线的交点等。

当贝塞尔曲线段连成一个样条时,连通性(connectivity)可通过共用端点来保证,连续性(continuity)可以通过放置其它控制点来保证,这为用户提供了对样条的光滑程度的控制。

connect-bezier.png

贝塞尔曲线也可以从几何的角度来理解,以二次贝塞尔曲线为例,首先将控制点连成一条折线段,然后依次切掉那些不光滑的角(corner),重复无穷次之后便得到一条曲线。

角切法(corner cutting)实际上定义了一种细分(subdivision)策略,通过将一条简单曲线分解成更小曲线段的过程来定义曲线,最终可以得到一条极限曲线(limit curve)。细分策略如果定义得合适,可以得到一条拥有参数形式的光滑曲线。

subdivision-quadratic-bezier.png

上图中取中点的做法可以得到一系列形式如下的点:

p(u)=(1u)[(1u)p0+up1]+u[(1u)p1+up2]\mathbf{p}(u) = (1-u)[(1-u)\mathbf{p}_{0} + u\mathbf{p}_{1}] + u[(1-u)\mathbf{p}_{1} + u\mathbf{p}_{2}]

整理可得二次贝塞尔曲线:

B2(u)=(1u)2p0+2u(1u)p1+u2p2\mathbf{B}_{2}(u) = (1-u)^{2}\mathbf{p}_{0} + 2u(1-u)\mathbf{p}_{1} + u^{2}\mathbf{p}_{2}

德卡斯特里奥算法(de Casteljau algorithm)

德卡斯特里奥算法(de Casteljau algorithm)是一个非常简单而通用的计算和细分贝塞尔曲线的方法,它使用一个线性插值序列来计算任意次贝塞尔曲线。

首先,将每一对相邻控制点用线段连起来,找到这些线段上对应参数 uun1n-1 个线性插值点。对这些点做同样的操作,得到 n2n-2 个点。重复这一过程直到最终得到一个点为止。

de-Casteljau.png

上述计算过程中所生成的一系列中间点可作为新的、更小的贝塞尔曲线段的控制点,从而得到贝塞尔曲线的一种细分方法。

de-Casteljau-dividing.png

贝塞尔曲线的细分算法让分治算法成为可能。比如,当画一条贝塞尔曲线时,根据凸包可以很容易检查一条曲线是否接近于直线,如果控制点接近共线,则将曲线绘制为直线,否则将曲线分割为更小的曲线段,并重复这一过程。计算两条曲线交点的算法类似。由于这些算法的存在,其它曲线通常也转换为贝塞尔曲线来处理。

B 样条

B 样条提供了一种用 dd 次多项式近似 nn 个点的方法,它可以生成几乎任意连续性的曲线。因此,B 样条是计算机图形学中表示高度光滑的曲线的首选方法,对于 C2C^{2} 及以上连续性的曲线,B 样条可能更合适。

曲线可以用 B 样条基函数的线性组合来表示。这些基函数本身也是样条,称为基样条(basis splines)或 B 样条(B-splines),每个基函数由 d+1d+1dd 次多项式构成。

B 样条特指基函数,B 样条曲线指基函数的线性组合。

函数的线性组合可以表示为:

f(t)=i=1npibi(t)\mathbf{f}(t) = \sum_{i=1}^{n}\mathbf{p}_{i}b_{i}(t)

其中,bib_{i} 是基函数,pi\mathbf{p}_{i} 是系数,如果它是点,则称为控制点。这一方法的关键在于定义合适的基函数 bib_{i}

一组 B 样条可以通过系数的数目 nn 和参数值 k=d+1k=d+1 来定义,dd 是多项式的次数。这样的 B 样条曲线满足:

  • Ck2C^{k-2} 连续。
  • k1k-1 次多项式构成。
  • 局部性,曲线上任何位置仅依赖于 kk 个控制点。
  • 包围在控制点的凸包内。
  • 变差减少

均匀线性 B 样条(Uniform Linear B-Splines)

一次 B 样条基函数形式如下:

bi,2(t)={ti,if it<i+12t+i,if i+1ti+20,otherwiseb_{i,2}(t) = \left\{ \begin{aligned} &t-i, &&\text{if}\ i\leqslant t< i+1 \\ &2-t+i, &&\text{if}\ i+1\leqslant t\leqslant i+2 \\ &0, &&\text{otherwise} \end{aligned} \right.

linear-B-spline.png

bi,2b_{i,2} 作为基函数,可以得到一个参数值从 t=kt=kt=n+1t=n+1 依次穿过所有系数 pi\mathbf{p}_{i} 的分段线性函数。

一般地,B 样条具有如下性质:

  • 每个 B 样条有 k+1k+1 个结点。
  • 每个 B 样条在首结点前、尾结点后值为 00
  • 整条 B 样条曲线有局部性。
  • 整条 B 样条曲线有 n+kn+k 个结点。
  • 每个 B 样条和整条 B 样条曲线都是 Ck2C^{k-2} 连续的。
  • 对于结点 kk 到结点 n+1n+1 之间的参数范围(同时存在 kk 个值不为 00 的 B 样条的范围),B 样条求和为 11。这保证了平移不变性(shift invariant):平移所有控制点等价于平移整条曲线。

    给定 B 样条曲线上的任一点,都只有 kk 个 B 样条基函数有贡献。

  • 相邻结点间,每个 B 样条以及整条 B 样条曲线都是一个 d=k1d=k-1 次多项式。也就是说,B 样条曲线中的每一段都是一个依赖于 kk 个系数的 d=k1d=k-1 次多项式。

这里所考虑的是结点均匀排列的 B 样条,不考虑偏移,每个 B 样条完全相同。均匀结点间距的 B 样条称为均匀 B 样条(uniform B-splines)或周期 B 样条(periodic B-splines)。

均匀二次 B 样条(Uniform Quadratic B-Splines)

二次 B 样条基函数形式如下:

bi,3(t)={12u2,if it<i+1,u=tiu2+u+12,if i+1t<i+2,u=t(i+1)12(1u)2,if i+2ti+3,u=t(i+2)0,otherwiseb_{i,3}(t) = \left\{ \begin{aligned} &\frac{1}{2}u^{2}, &&\text{if}\ i\leqslant t< i+1, && u=t-i \\ &-u^{2}+u+\frac{1}{2}, &&\text{if}\ i+1\leqslant t< i+2, && u=t-(i+1) \\ &\frac{1}{2}(1-u)^{2}, &&\text{if}\ i+2\leqslant t\leqslant i+3, && u=t-(i+2) \\ &0, &&\text{otherwise} \end{aligned} \right.

quadratic-B-spline.png

均匀三次 B 样条(Uniform Cubic B-Splines)

三次 B 样条基函数形式如下:

bi,4(t)={16u3,if it<i+1,u=ti16(3u3+3u2+3u+1),if i+1t<i+2,u=t(i+1)16(3u36u2+4),if i+2t<i+3,u=t(i+2)16(u3+3u23u+1),if i+3ti+4,u=t(i+3)0,otherwiseb_{i,4}(t) = \left\{ \begin{aligned} &\frac{1}{6}u^{3}, &&\text{if}\ i\leqslant t< i+1, && u=t-i \\ &\frac{1}{6}(-3u^{3}+3u^{2}+3u+1), &&\text{if}\ i+1\leqslant t< i+2, && u=t-(i+1) \\ &\frac{1}{6}(3u^{3}-6u^{2}+4), &&\text{if}\ i+2\leqslant t< i+3, && u=t-(i+2) \\ &\frac{1}{6}(-u^{3}+3u^{2}-3u+1), &&\text{if}\ i+3\leqslant t\leqslant i+4, && u=t-(i+3) \\ &0, &&\text{otherwise} \end{aligned} \right.

cubic-B-spline.png

整个 B 样条曲线在节点 i+3i+3i+4i+4 之间的部分可以表示为以 p=[pi,pi+1,pi+2,pi+3]\mathbf{p}=[\mathbf{p}_{i},\mathbf{p}_{i+1},\mathbf{p}_{i+2},\mathbf{p}_{i+3}] 为控制点的三次多项式曲线,相应的基矩阵如下:

Mb=16[1410303036301331]\mathbf{M}_{\mathbf{b}} = \frac{1}{6} \begin{bmatrix} 1 & 4 & 1 & 0 \\ -3 & 0 & 3 & 0 \\ 3 & -6 & 3 & 0 \\ -1 & 3 & -3 & 1 \end{bmatrix}

非均匀 B 样条(Nonuniform B-Splines)

给定 nnkk,B 样条以及整条 B 样条曲线共有 n+kn+k 个结点,将结点值按增序构成一个非减结点向量(non-decreasing knot vector)t\mathbf{t},向量中的结点值可以推广到非均匀情形。非均匀结点间距可以:

  1. 控制系数起作用的参数范围
  2. 重复结点以生成在结点处具有各种性质的函数

通过结点值可以将曲线特征和参数值联系起来。当需要在序列起止位置插入和删除结点时,对结点值的控制特别有用。非均匀结点间距让 B 样条的局部性既是一个代数性质,又是一个几何性质。

给定系数数目 nn、B 样条参数 kk、结点向量 t\mathbf{t},下面是 B 样条的递推方程定义:

bi,1,t(t)={1,if tit<ti+10,otherwisebi,k,t(t)=ttiti+k1tibi,k1,t(t)+ti+ktti+kti+1bi+1,k1,t(t)\begin{aligned} b_{i,1,\mathbf{t}}(t) &= \left\{ \begin{aligned} &1, &&\text{if}\ \mathbf{t}_{i}\leqslant t< \mathbf{t}_{i+1} \\ &0, &&\text{otherwise} \end{aligned} \right. \\ b_{i,k,\mathbf{t}}(t) &= \frac{t-\mathbf{t}_{i}}{\mathbf{t}_{i+k-1}-\mathbf{t}_{i}}b_{i,k-1,\mathbf{t}}(t) + \frac{\mathbf{t}_{i+k}-t}{\mathbf{t}_{i+k}-\mathbf{t}_{i+1}}b_{i+1,k-1,\mathbf{t}}(t) \end{aligned}

上式也称为 Cox–de Boor 递推关系(Cox–de Boor recurrence),可用于数值计算,但更常用于公式推导。可以看出,分段由开关函数 bi,1,tb_{i,1,t} 控制。

重复结点可以让 B 样条曲线穿过它的系数。如果某个 B 样条基函数的所有内部结点都相同,那么其它基函数在该结点处的值均为 00,该基函数的值则为 11,这使得整条 B 样条曲线穿过相应系数。

repeated-knots.png

重复结点的代价是,B 样条基函数以及整条曲线失去了一定的光滑性。但是,由于曲线起止位置连续性不重要,因此结点重复常用于生成端点插值 B 样条(endpoint interpolating B-splines)。简单考虑,可以让前(后)kk 个结点值相同以实现端点插值。

endpoint-interpolating-B-spline.png

NURBS

仍有一些曲线形状是 B 样条无法表示的,为了表示这些曲线,可以使用有理分式。最常见的形式是非均匀有理 B 样条(nonuniform rational B-splines, 简称 NURBS),它为每个控制点 pi\mathbf{p}_{i} 赋予了一个标量权重 hih_{i}

f(u)=i=1nhipibi,k,ti=1nhibi,k,t\mathbf{f}(u) = \frac{\displaystyle\sum_{i=1}^{n}h_{i}\mathbf{p}_{i}b_{i,k,\mathbf{t}}}{\displaystyle\sum_{i=1}^{n}h_{i}b_{i,k,\mathbf{t}}}

NURBS 广泛应用于曲线、曲面的几何建模。