Skip to content

Latest commit

 

History

History
702 lines (685 loc) · 68.2 KB

第15章 曲线.md

File metadata and controls

702 lines (685 loc) · 68.2 KB

边学边翻译,督促自己不能落下,同时也留点记忆

第十五章 曲线


15.1 曲线

    直观地说,可以把曲线想象成用笔画出来的东西。曲线是笔在一段时间内追踪的点的集合。虽然我们通常认为钢笔在纸上写字(例如,在2D空间中的曲线),但钢笔可以在3D中移动以生成空间曲线,或者你可以想象钢笔在其他空间中移动。     在数学上,曲线的定义至少可以从两方面来理解:

  1. n维空间中某个区间的连续像
  2. 从一维空间到n维空间的连续映射

   这两个定义都是从区间(笔沿着曲线移动的时间)的概念开始的。然而,这里有一个显著的区别:在第一个定义中,曲线是笔所跟踪的点集(图像),而在第二个定义中,曲线是时间和点集之间的映射。在本章中,我们使用第一个定义。     曲线是无限大的点集合。曲线中的点具有这样的特性:任何点都有两个相邻点,只有少数点只有一个相邻点(这些点是端点)除外。有些曲线没有端点,要么是因为它们是无限的(像直线一样),要么是因为它们是闭合的(环绕并连接自己)     因为曲线的“笔”很薄(非常小),所以很难创建填充区域。虽然空间填充曲线是可能的(通过让它们自己无限次折叠),但我们在这里不考虑这种数学上的奇怪现象。一般来说,我们认为曲线是事物的轮廓,而不是“内部”。     我们需要解决的问题是如何指定曲线——给曲线命名或表示,以便我们可以在计算机上表示它。对于一些曲线,命名它们的问题很容易,因为它们有已知的形状:线段、圆、椭圆弧等。一般的曲线没有“命名”的形状有时被称为自由曲线。因为自由形式的曲线几乎可以呈现任何形状,所以它们很难被指定。     有三种主要的方法在数学上指定曲线:

  1. 隐式曲线,表示通过给出一个程序来确定曲线上的点是否在曲线上,从而定义了曲线上的点集。通常,隐式曲线的表示是由隐式函数定义的 $$ f(x, y)=0 $$ 因此曲线是这个方程成立的点的集合。注意,隐式函数f是一个标量函数(它返回一个实数)。
  2. 参数曲线,表示提供了从自由参数到曲线上的点集的映射。也就是说,这个自由参数为曲线上的点提供了一个索引。曲线的参数形式是将位置赋给自由参数值的函数。直观地说,如果你把曲线想象成可以在纸上用笔画的东西,自由参数就是时间,从开始画曲线到结束画曲线的时间区间这条曲线的参数函数告诉我们钢笔在任何时刻的位置: $$ (x, y) = f(t) $$ 注意参数函数是向量值函数。这个例子是一个2D曲线,所以函数的输出是一个2维向量;在3D中,它是一个3维向量。
  3. 生成式或过程式曲线,表示提供了可以生成曲线上不属于前两类的点的过程。生成曲线描述的例子包括细分方案和分形。     记住,曲线是点的集合。这些表示为我们提供了指定这些集合的方法。任何曲线都有许多可能的表示。对于这个原因是,数学家通常会小心地区分曲线和它的表示形式。在计算机图形学中,我们常常是马虎的,因为我们通常只参考表示,而不是实际的曲线本身。所以当有人说"隐式曲线"指的要么是由隐式函数表示的曲线要么是由隐式函数表示的曲线之一。这种区别通常并不重要,除非我们需要考虑同一曲线的不同表示。我们将考虑不同的曲线表示.     根据本章开头给出的定义,曲线必须有参数表示。然而,许多曲线有其他的表现形式。例如,一个圆心在原点,半径为1的二维圆,可以用隐式表示为 $$ f(x, y) = x^2 + y^2 − 1=0 $$ 或者参数化形式: $$ (x, y) = f(t) = (cost,sin t), t\in [0, 2π) $$

    对于给定的曲线,参数形式不一定是最方便的表示形式。事实上,有可能有一些曲线具有简单的隐式或生成表示,但很难找到参数表示.    曲线的不同表示形式各有优缺点。例如,参数曲线更容易绘制,因为我们可以对自由参数进行抽样。一般来说,参数形式在计算机图形学中是最常用的,因为它们更容易处理。我们的重点将是曲线的参数表示。

15.1.1 参数化和Reparameterizations

    参数曲线是指由特定的参数函数在特定区间内给出的曲线。更准确地说,参数曲线具有一个给定的函数,该函数是从参数区间映射而来的。通常,让参数在从0到1的单位区间内运行是很方便的。当自由参数在单位区间内变化时,我们通常用u表示参数。     如果我们把参数曲线看作是用钢笔画的一条线,我们可以把u = 0看作是笔第一次在纸上落下来的时间,时间单位是画曲线所花的时间(u = 1是曲线的末端):曲线可以通过将时间(在这些单位坐标中)映射到位置的函数来指定。基本上,曲线的规格是一个函数,它可以回答这个问题,“笔在u时刻在哪里?”     如果给定函数f(t),它指定了在区间[a, b]上的一条曲线,我们可以很容易地定义一个新函数f2(u),它指定了在单位区间上的同一条曲线。我们可以先定义 $$ g(u) = a + (b − a)u, $$ 然后 $$f_2(u) = f(g(u)) $$     f和f2这两个函数都表示同一条曲线;然而,它们提供了不同的曲线参数化。为已有曲线创建新参数化的过程称为重新参数化,从旧参数到新参数的映射(在本例中为g)称为重新参数化函数     如果我们用一些参数化来定义一条曲线,还有无数其他的参数化存在(因为我们总是可以重新参数化)。能够对一条曲线进行多参数化是很有用的,因为它允许我们创建参数化。然而,它也可能是有问题的,因为它使它比较两个函数是否代表同一条曲线是很困难。     这个问题的本质更加普遍:自由参数(或时间元素)的存在为我们的曲线表示增加了一个看不见的、潜在未知的元素。当我们看到曲线绘制后,我们不一定知道时间。钢笔可能在整个时间间隔内以恒定的速度移动,或者它可能开始很慢,然后加速。 例如,虽然u = 0.5是穿过参数空间的一半,但如果笔的运动开始较慢,在结束时加速,那么它可能不是沿着曲线的一半。考虑下面的表示 $$ (x, y) = f(u)= (u, u),\ (x, y) = f(u)= (u^2, u^2),\ (x, y) = f(u)= (u^5, u^5). $$     这三个函数在单位区间上表示同一条曲线;然而,当u不是0或1时,f(u)指的是一个不同的点,这取决于曲线的表示形式     如果我们得到了曲线的参数化,我们可以直接用它作为曲线的说明,或者我们可以开发一个更方便的参数化。通常,自然参数化是以一种方便的方式创建的为了指定曲线,我们不需要知道速度沿着曲线是如何变化的     如果我们知道钢笔以恒定的速度移动,那么自由参数的值就有了更多的意义。穿过参数空间的一半就是沿着曲线的一半。该参数不是测量时间,而是测量沿曲线的长度。这样的参数化称为弧长参数化,因为它们通过从沿曲线的距离(称为弧长)映射到位置的函数来定义曲线。我们经常使用变量s来表示弧长参数。     从技术上讲,如果其切线的大小(即参数化对参数的导数)具有恒定的大小,则参数化就是弧长参数化。用方程表示 $$ \left |\frac{df(s)}{ds}^2 \right| = c $$     沿着曲线计算长度是很棘手的。一般来说,它由导数的大小的积分来定义(直观地说,导数的大小就是笔沿着曲线移动时的速度)。因此,给定参数v的值,可以计算s(从f(0)点到f(v)点沿曲线的弧长距离)为 $$ s = \int_0^v\left |\frac{df(t)}{dt}^2 \right| dt \tag{15.1} $$     f(t)是一个函数,它用自然参数化定义了曲线。     使用弧长参数化要求能够求解方程(15.1)对于t,给定s。对于我们所考察的许多类型的曲线,它不能以封闭的(简单的)方式来完成,必须用数值方法来完成。     通常,我们用变量u表示单位区间内的自由参数,用s表示弧长自由参数,用t表示不属于其他两个区间的参数

15.1.2 分段参数表征

    对于某些曲线,定义表示其形状的参数函数很容易。例如,直线、圆和椭圆都具有简单的函数,这些函数根据参数定义它们包含的点。对于许多曲线来说,找到一个指定其形状的函数是很困难的。我们用来创建复杂曲线的主要策略是分治法:我们将曲线分解成许多更简单的小片段,每个片段都有一个简单的描述     例如,考虑图15.1中的曲线。前两条曲线很容易用两段来表示。对于图15.1(b)中的曲线,我们需要两种不同的片段:线段和圆     要创建复合曲线的参数表示(如图15.1(b)中的曲线),我们需要让参数函数在表示各部分的函数之间切换。如果我们在0≤u≤1范围内定义参数函数,那么可以定义图15.1(a)或(b)中的曲线 $$ f(u) = \begin{cases} f_1(2u) & if ~ u\leq0.5\ f_2(2u-1) & if ~ u>0.5 \end{cases} $$     其中f1是第一部分的参数化,f2是第二部分的参数化,这两个函数都在单位区间内定义     我们在定义函数f1和f2时需要小心,以确保曲线的各个部分相互吻合。如果$f1(1)\not= f2(0)$,那么我们的曲线片段不会连接,不会形成单一的连续曲线。     为了表示图15.1(b)中的曲线,我们需要使用两种不同类型的片段:线段和圆弧。为了简单起见,我们可能更喜欢使用单一类型的部件。如果我们试图用一种类型的片段(线段)来表示图15.1(b)中的曲线,我们无法准确地重新创建曲线(除非我们使用无限数量的碎片)。虽然由线段组成的新曲线(如图15.1(c)所示)可能与图15.1(b)的形状不完全相同,但它可能足够接近于我们使用。在这种情况下,我们可能更喜欢使用si的简单性     同时,注意当我们使用越来越多的片段时,我们可以得到一个更好的近似。在极限情况下(使用无限多块),我们可以精确地表示原始形状。使用分段表示的一个优点是它允许我们在

  1. 我们所表示的曲线与我们试图表示的真实形状的近似程度;
  2. 我们使用的部件有多复杂;
  3. 我们用了多少块

    因此,如果我们试图表示一个复杂的形状,我们可能会决定一个粗略的近似是可以接受的,并使用少量的简单块。为了改进近似,我们可以选择使用更多的块和使用更复杂的块。     在计算机图形学实践中,我们倾向于使用相对简单的曲线片段(线段、弧段或多项式段)。

15.1.3 样条

    在计算机出现之前,绘图员想要画出一条光滑的曲线时,他们使用的一种工具是一块坚硬的金属,他们将其弯曲成所需的形状进行绘制。因为这种金属会弯曲,而不是折叠,所以它会有一个光滑的形状。这种硬度意味着金属会尽可能地不弯曲,以形成所需的形状。这块坚硬的金属被称为样条。     数学家们发现,他们可以用分段多项式函数来表示由绘图人的样条曲线所创造的曲线。最初,他们用样条这个术语来表示平滑的分段多项式函数。最近,术语样条被用来描述任何分段多项式函数。我们更喜欢后一种定义。     对我们来说,样条是分段多项式函数。这样的函数对于表示曲线非常有用。


15.2 曲线性质

    为了描述曲线,我们需要给出一些关于它的性质的事实。对于“命名”曲线,属性通常根据曲线的类型而确定。例如,要描述一个圆,我们可以提供它的半径和圆心的位置。对于一个椭圆,我们还可以提供它的长轴的方向和轴的长度之比。然而,对于自由形式的曲线,我们需要一组更一般的属性来描述各个曲线     曲线的某些特性只取决于曲线上的某个位置,而另一些特性则需要了解整个曲线。为了直观地理解两者的区别,可以把曲线想象成火车轨道。如果你在雾天站在轨道上,你可以分辨出轨道是直的还是弯的,以及你是否在终点。这些是局部属性。你无法判断轨迹是否是闭合曲线,或者是否交叉,或者它有多长。我们称这种类型的属性为全局属性     对几何物体(曲线和曲面)的局部性质的研究被称为微分几何。从技术上讲,要成为微分性质,这些性质有一些数学上的限制(粗略地说,在火车轨道类比中,你不可能有GPS或指南针)。与其担心这种区别,我们将使用术语局部性质而不是微分性质     局部性质是描述曲线的重要工具,因为它们不需要关于整个曲线的知识。当地的属性包括:

  • 连续性,
  • 位置在曲线上的特定位置,
  • 曲线上特定位置的方向,
  • 曲率(和其他导数)。

    通常,我们想要指定一条曲线包含一个特定的点。如果一个点是曲线的一部分,那么这个点就是曲线的内插点。函数f插值一个值v,如果参数u的某个值f(t) = v,我们称插值的位置,也就是t的值,为点。

15.2.1 连续性

    理解曲线的局部性质是非常重要的参数化的部分组合在一起。如果曲线是用方程来定义的(15.2)式,那么我们需要注意如何定义这些片段。如果F1 (1) �= f2(0),那么曲线将被“破坏”-我们将无法绘制曲线:钢笔连续一笔的曲线我们称这种情况为曲线.各个片段符合连续性条件因为如果它们保持不变,曲线就可以画成一个连续的部分。因为我们一开始对"曲线"的定义.本章要求曲线是连续的,技术上称为“断曲线”不是一个曲线。     除了位置,我们还可以检查每一项的导数正确匹配。如果f1 (1) != f2(0),则组合曲线将有一个突变它在开关点的一阶导数的变化;一阶导数不会是连续的。一般来说,我们说一条曲线是Cn连续的,如果所有的n以内的导数在各段之间匹配。我们把位置本身表示为第零导数,所以C0连续性条件意味着曲线是连续的,C1连续意味着位置和一阶导数是连续的。曲线的定义要求曲线为C0。     一些连续性条件的说明如图15.2所示。一阶导数的不连续(曲线是C0而不是C1)通常是明显的,因为它显示了一个尖角。二阶导数的不连续有时在视觉上是显而易见的。高阶导数的不连续可能有影响,这取决于应用。例如,如果曲线表示一个运动,二阶导数的突变是明显的,因此三阶导数的连续性通常是有用的。如果曲线上有流体流过(例如,如果曲线是飞机机翼或船壳的形状),四阶或五阶导数的不连续可能会引起乱流     我们刚刚介绍的连续性类型(Cn)通常被称为参数连续性,因为它取决于两个曲线段的参数化。如果每个片段的“速度”不同,那么它们就不会是连续的。对于我们关心曲线的形状,而不是它的参数化的情况,我们定义几何连续性,要求当曲线被等效参数化时,曲线片段的导数匹配。直观地说,这意味着相应的导数必须具有相同的方向,即使它们的大小不同。     如果C1的连续性条件是 $$ f_1'(1)=f_2'(0) $$     G1连续性条件为 $$ f_1'(1)=kf_2'(0) $$     一般来说,几何连续性的限制比参数连续性较小。$C^n$曲线也是$G^n$,除非参数外衍生品消失。


15.3 多边形片段

    在计算机图形学中,最广泛使用的曲线表示方法是将由多项式定义的基本元素拼接在一起,这些元素被称为多项式块。例如,线元素由线性多项式给出。     在第15.3.1节中,我们给出了一个形式化的定义,并解释了如何将多项式的片段组合在一起。

15.3.1多项式符号

    多项式是这种形式的函数 $$ f(t)=a_0+a_1t+a_2t^2+\cdots+a_nt^n. \tag{15.3} $$     $a_i$称为系数,n称为多项式的次数,如果an + 0。我们还将式(15.3)写成 $$ f(t) = \sum_{i=0}^na_it^i \tag{15.4} $$     我们称之为多项式的标准形式。     我们可以将标准形式推广到 $$ f(t) = \sum_{i=0}^nc_ib_i(t) \tag{15.4} $$     其中b;(t)是一个多项式。我们可以为不同的应用选择一种方便的形式的多项式,我们称之为基函数或混合函数(参见15.3.5节)。式(15.4)中,t为式(15.5)的ba (t)。如果基函数集的选择正确,任何n + 1次的多项式都可以用c的适当选择来表示。     标准形式并不总是有方便系数。为了实际目的,在本章中,我们将找到基函数集,这样的系数是控制多项式函数所表示的曲线的方便方法。     要在二维空间中指定一条曲线,可以在t中指定两个多项式:一个表示z随t的变化,另一个表示y随t的变化;或者指定一个多项式其中每个a都是一个2D点。n维空间中的任何曲线都存在类似的情况。

15.3.2 线段分片

    为了介绍分段多项式曲线表示的概念,我们将讨论线段。在实践中,线段是如此简单,以至于数学推导会显得过多。然而,通过理解这个简单的情况,当我们转向更复杂的多项式时,事情会更容易。     考虑一个连接点po到的线段。我们可以把这条线段的单位域上的参数函数写成 $$ f(u)=(1-u)p_0+up_1 \tag{15.6} $$     通过将其写成向量形式,我们隐藏了点的维度以及我们分别处理每个维度的事实。例如,如果我们在2D中工作,我们可以创建单独的方程: $$ f_x(u)=(1-u)x_0+ux_1 \ f_y(u)=(1-u)y_0+uy_1 $$     我们指定的直线是由两个端点决定的,但是从现在开始我们将坚持使用向量表示法,因为它更清晰。我们称控制参数的向量p为控制点,p的每一个元素都是控制点。 虽然用线段端点的位置来描述线段是很明显而且通常很方便的,但是还有其他的方法来描述线段。例如,

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

    很明显,给定线段的一种描述,我们可以切换到另一种。     描述线段的另一种方法是使用多项式的标准形式(如15.3.1节所述), $$ f(u)=a_0+ua_1 \tag{15.7} $$     任何线段都可以通过指定ao和ay或端点(po和pi)来表示。指定端点通常更方便,因为我们可以从端点计算其他参数。     为了将标准形式写成向量表达式,我们定义一个向量u,它是u的幂的向量: $$ u=[1uu^2u^3\cdots u^n] $$     使式(15.4)可以表示为 $$ f(u)=u\cdot a $$     这种向量表示法将使不同形式的曲线之间的转换更容易。     式(15.8)用多项式的简单形式的多项式系数集描述了曲线段。我们称这种表示法为规范形式。我们将用a表示标准形式的参数。     虽然标准形式在数学上很简单,但它并不总是指定曲线的最方便的方法。例如,我们可能更喜欢通过端点的位置来指定线段。如果我们想定义po为线段的开始(其中线段是u - 0时的线段)和pi为线段的结束(其中线段是u = 1时的线段),我们可以写 $$ P_0 = f(0)=[10]\cdot[a_0a_1],\ \tag{15.9} P_1 = f(1)=[11]\cdot[a_0~a_1]. $$     我们可以解出ao和ay的方程: $$ a_0=p_0,\ a_1=p_1 - p_0 $$

多项式的矩阵形式

    虽然第一个例子很容易求解,但对于更复杂的例子,将式(15.9)写成这种形式会更容易 $$ \begin{bmatrix} p_0 \ p_1 \end{bmatrix} = \begin{bmatrix} 1 & 0 \ 1 & 1 \end{bmatrix} \begin{bmatrix} a_0 \ a_1 \end{bmatrix} $$     或者,我们可以写 $$ p =Ca,\tag{15.10} $$     我们称C为约束矩阵。”如果点的向量让您感到困扰,您可以独立地考虑每个维度(因此p是[ro zi]或[y0 91], a是相应处理的)。     我们可以通过求c的逆来解a式(15.10)这个逆矩阵我们用B表示它叫做基矩阵。基矩阵非常方便,因为它告诉我们如何在方便的参数p和标准形式a之间转换,因此,给了我们一种简单的方法来求曲线 $$ f(u)=uBp $$     我们可以为我们想要的任何形式的曲线找到一个基矩阵,前提是在参数的定义中没有非线性。非线性定义参数的例子包括线段的长度和角度。     现在,假设我们想参数化线段,使po是中点(u = 0.5), pi是终点(u = 1)。为了推导这个参数化的基矩阵,我们设置 $$ p_0 = f(0.5)=1a_0+0.5a_1, p_1 = f(1)=1a_0+1a_1 $$     因此 $$ C = \begin{bmatrix}1&.5 \1&1\end{bmatrix} $$     然后, $$ B=C^{-1}=\begin{bmatrix}2&-1 \-2&2\end{bmatrix} $$

15.3.3 线段以外

    线段是如此简单,找一个基矩阵是微不足道的。但是,对于更高度的曲线,这是一个很好的练习。首先,让我们考虑二次曲线(二次曲线)。标准形式(式(15.4))的优点是它适用于这些更复杂的曲线,只要让n是一个更大的数字。     二次多项式(二次多项式)有三个系数,ao, aj和a2。这些系数不便于描述曲线的形状。但是,我们可以使用相同的基矩阵法来设计更方便的参数。如果我们知道u的值,式(15.4)在参数中成为线性方程,上一节的线性代数仍然有效。     假设我们想用u = 0开头的位置来描述曲线?(u = 0.5),结束(u = 1)。将相应值代入式(15.4): $$ \begin{aligned} p_0&=f(0)&&=a_0+0^1a_1+0^2a_2,\ p_1&=f(0.5)&&=a_0+0.5^1a_1+0.5^2a_2,\ p_2&=f(1)&&=a_0+1^1a_1+1^2a_2, \end{aligned} $$     所以约束矩阵是 $$ C=\begin{bmatrix}1&0&0\ 1&.5&.25\ 1&1&1\end{bmatrix} $$     基矩阵是 $$ B=C^{-1}=\begin{bmatrix}1&-.5&.125\ 0&1&-5\ 0&0&2.5\end{bmatrix} $$     还有一种附加类型的约束(或参数)有时很容易指定:曲线(对其自由参数)在特定值处的导数。直观上,导数告诉我们曲线是如何变化的,所以一阶导数告诉我们曲线的方向,二阶导数告诉我们曲线改变方向的速度,等等。我们将在后面看到为什么指定导数是有用的例子。对于二次方程组: $$ f(u)=a_0+a_1u+a_2u^2, $$     导数很简单: $$ f'(u)=\frac{df}{du}=a_1+2a_2u, $$     而且 $$ f''(u)=\frac{d^2f}{du^2}=\frac{df'}{du}=2a_2. $$     或者,更普遍的是, $$ f'(u)=\sum_{i=1}^niu^{i-1}a_i,\ f''(u)=\sum_{i=2}^ni(i-1)u^{i-2}a_i, $$     例如,考虑这样一种情况,我们想通过中间位置、一阶导数和二阶导数(u = 0.5)来指定一个二次曲线段。 $$ \begin{aligned} p0 &=f(0.5)&&=a_0+0.5^1a_1+0.5^2a_2,\ p1 &=f'(0.5)&&=a_1+20.5^1a_2,\ p2 &=f''(0.5)&&=2a_2 \end{aligned} $$     约束矩阵是 $$ C=\begin{bmatrix}1&.5&.25\ 0&1&1\ 0&0&2\ \end{bmatrix} $$     基矩阵是 $$ B=C^{-1}=\begin{bmatrix}1&-.5&.25\ 0&1&1\ 0&0&.5 \end{bmatrix} $$     我们将在15.5.2讨论埃尔米特三次样条曲线。

15.3.4立方的基矩阵

    三次多项式在图形学中很流行(见第15.5节)。各种形式的立方的推导就像我们已经在这一节中看到的推导一样。我们再做一个例子来练习。     三次多项式的一种非常有用的形式是埃尔米特形式,在这种形式中,我们指定了开始和结束时的位置和一阶导数,也就是说, $$ \begin{aligned} p0 &=f(0)&&=a_0+0^1a_1+0^2a_2+0^3a_3,\ p1 &=f'(0)&&=a_1+20^1a_2+30^2a_3,\ p2 &=f(1)&&=a_0+1^1a_1+1^2a_2+1^3a_3,\ p3 &=f'(1)&&=a_1+21^1a_2+31^2a_3, \end{aligned} $$     约束矩阵是 $$ C=\begin{bmatrix}1&0&0&0\ 0&1&0&0\ 1&1&1&-1\ 0&1&2&3\ \end{bmatrix} $$     基矩阵是 $$ B=C^{-1}=\begin{bmatrix}1&0&0&0\ 0&1&0&0\ -3&-2&3&-1\ 2&1&-2&1\ \end{bmatrix} $$     我们将在第15.5.2节讨论埃尔米特三次样条曲线。

15.3.5混合功能

    如果我们知道基矩阵B,我们可以把它乘以参数向量u,得到一个函数的向量 $$ b(u) =uB. $$     注意,我们用b(u)来表示这个向量,以强调它的值依赖于自由参数u。我们称b(u)的元素为混合函数,因为它们说明了如何将控制点向量的值混合在一起: $$ f(u) =\sum_{i=}^n b_i(u)p_i. $$     值得注意的是,对于所选的u值,式(15.11)是一个指定控制点线性混合(或加权平均)的线性方程。这是正确的,无论什么次多项式“隐藏”在ba函数中。     混合函数为描述曲线提供了一种很好的抽象。任何类型的曲线都可以表示为其控制点的线性组合,其中这些权值计算为自由参数的任意函数。

15.3.6插值多项式

    一般来说,n次的多项式可以插值n + 1个值的集合。如果已知向量p = (po,....Pn)的点插值和一个向量t =(到....,tn)的递增参数值,t, +tj,我们可以使用这些方法 在前面的章节中描述过,确定一个n+ 1xn+1基矩阵,它给出一个函数f(t)使得f(ti) =。对于任意给定的向量t,我们需要建立并求解一个n = 1 X n + 1的线性系统。这为我们提供了一组执行插值的n + 1基函数: $$ f(t)=\sum{i=0}^np_ib_i(t). $$     这些插值基函数可以用其他方法推导出来。定义它们的一种特别优雅的方式是拉格朗日形式: $$ b_i=\prod_{j=0,j\not=i}^n \frac{x-t_j}{t_i-t_j}. \tag{15.12} $$     有比拉格朗日形式更有效的计算方法来表示插值基函数(详见De Boor(1978))。     插值多项式提供了一种定义插值一组点的曲线的机制。图15.3显示了一些示例。虽然可以创建一个多项式来插值任意数量的点,但在计算机图形学中我们很少使用高阶多项式来表示曲线。相反,插值样条(分段多项式函数)是首选。出现这种情况的一些原因在第15.5.3节中讨论。

15.4 合并片段

    现在我们已经知道了如何构造单独的多项式曲线片段,我们可以考虑如何将这些片段组合在一起。

15.4.1 结

    分段参数函数的基本思想是每一部分只在一定的参数范围内使用。例如,如果我们想定义一个函数,它有连接三个点的两个分段线性段(如图15.4(a)所示),我们可以定义 $$ f(u)=\begin{cases} f_1(2u) &if0\leq u<\frac{1}{2},\ f_2(2u-1) &if\frac{1}{2}\leq u<1, \tag{15.13} \end{cases} $$     其中fi和f2分别是两条线段的函数。注意,我们已经对每一部分的参数进行了缩放,以便于将它们的方程写成 $$ f_1(u)=(1-u)p_1+up_2. $$     对于分段函数中的每个多项式,都有一个起点和终点的位置(或参数值)。分段函数开始或结束的位置称为结。对于式(15.13)的例子,结的值为0、0.5和1。     我们也可以把分段多项式函数写成基函数的和,每个基函数乘以一个系数。例如,式(15.13)的两条线段可以重写为 $$ f(u)=p_1b_1(u)+p_2b_2(u)+p_3b_3(u), $$     函数bi(u)定义为 $$ b_1(u)=\begin{cases} 1-2u &if~0\leq u<\frac{1}{2},\ 0 &otherwise, \tag{15.14} \end{cases} $$     b2和b的定义是相似的。这些函数如图15.4(b)所示。     多项式函数的结是所有构成它的结点的结的组合。结向量是一个按升序存储所有结值的向量。     注意,在本节中,我们使用了两种不同的机制来组合多项式片段:对参数的不同范围使用独立的多项式片段,以及将分段多项式函数混合在一起。

15.4.2 使用独立块

    在第15.3节中,我们定义了单位参数范围内的多项式。如果我们想要组合这些片段,我们需要将整体函数的参数转换为片段的参数值。最简单的方法是定义参数范围[0,n]上的整体曲线,其中n是段的数量。根据参数的值,我们可以将其移动到所需的范围。

15.4.3 片段拼合

    如果我们想要用两条线段画一条曲线,我们需要确保第一个线段的末端与下一个线段的开始处于相同的位置。有三种方法连接两个段(为了简单起见):

  1. 将线段表示为它的两个端点,然后对这两个端点使用相同的点。我们称之为共享点方案。
  2. 每当第一个段的参数发生变化时,将第一个段的末尾的值复制到第二个段的开头。我们称之为依赖计划。
  3. 为连接写一个显式方程,并在其他参数改变时通过数值方法强制执行。

    虽然更简单的方案更可取,因为它们需要较少的工作,但它们也对线段的参数化方式有更多的限制。例如,如果我们想使用线段的中心作为参数(以便用户可以直接指定它),我们将使用每个线段的开头和线段的中心作为它们的参数。这将迫使我们使用依赖方案。     注意,如果我们使用共享点或依赖方案,控制点的总数小于n * m,其中n是段的数量,m。为每段控制点的个数;独立块的许多控制点将作为其他块的函数来计算。注意,如果我们对直线使用共享点方案(每个线段使用它的两个端点作为参数,并与它的邻居共享内部点),或者如果我们使用依赖方案(例如具有第一个端点和中点的示例),对于一个n段曲线,我们最终会得到n + 1个控件。     依赖计划有一个更严重的问题。曲线上某一处的变化可以传播到整个曲线。这被称为缺乏局部性。局部性意味着如果你在曲线上移动一个点它只会影响一个局部区域。局部区域可能很大,但它是有限的。如果曲线的控制没有局部性,改变一个控制点可能会影响无限远的点。     为了确定局部性和缺乏局部性,考虑两条线段链,如图15.5所示。一条链的各个部分由它们的端点参数化,并使用点共享来保持连续性。另一种是通过端点和中点参数化其片段,并使用依赖传播将片段保持在一起。两个线段链可以表示相同的曲线:它们都是n个相连线段的集合。但是,由于局部性问题,端点共享形式可能对用户更方便。考虑改变每个链中第一个控制点的位置。对于端点共享版本,只有第一个段会更改,而在中点版本中,所有段都会受到影响,如图15.5所示。事实上,对于端点共享版本中移动的任何点,最多会改变两条线段。在中点版本中,被移动的控制点之后的所有段都将改变,即使链是无限长的。     在本例中,依赖项传播方案是没有本地控制的方案。这并不总是正确的。有非本地的直接共享方案和本地的传播方案。     我们强调局部性是一个方便控制的问题。虽然每次都更改整个曲线并不方便,但可以对曲线进行相同的更改。它只需要同步移动几个点。


15.5 三次曲线

    在图形学中,当我们用分段多项式表示曲线时,我们通常用线段或三次多项式表示分段。立方体在计算机图形学中流行的原因有很多:

  1. 分段三次多项式允许C2连续性,这对于大多数视觉任务通常是足够的。二次方程提供的Cl平滑性是往往不足。高阶多项式所提供的更大的平滑性并不重要。
  2. 三次曲线为一组点提供了最小曲率插值。也就是说,如果你有一组n + 3个点,并定义通过它们的“最光滑”曲线(即曲率比其长度最小的曲线),这条曲线可以表示为具有n段的分段三次立方。
  3. 三次多项式具有很好的对称性,位置和导数可以在开始和结束处指定。
  4. 三次多项式在计算中的数值问题和平滑性之间有一个很好的权衡。

    注意,我们不需要使用立方;它们只是在流畅性和复杂性之间进行了很好的权衡。不同的应用程序可能有不同的权衡。我们关注立方体,因为它们是最常用的。     三次多项式的标准形式是 $$ f(u)=a_0+a_1u+a_2u^2+a_3u^3 $$     正如我们在第15.3节中讨论的,这些标准形式系数不是描述三次段的方便方法。     我们寻求三次多项式的形式,其中的系数是一种方便的方式来控制由三次表示的结果曲线。主要的便利之一将是提供方法来确保各个部分的连通性和各个部分之间的连续性。     每个三次多项式片段需要四个系数或控制点。这意味着对于一个有n段的分段多项式,如果没有在段之间进行共享或使用依赖性,我们可能需要多达4n个控制点。更常见的是,每个段的某些部分要么是共享的,要么依赖于相邻的段,因此控制点的总数要低得多。另外,注意控制点可能是曲线的一个位置或一个导数。     不幸的是,分段立方没有单一的“最佳”表示。不可能有一个分段多项式曲线表示具有以下所有理想的性质:

  • 曲线的每一段都是三次的;
  • 曲线插值控制点;
  • 曲线有局部控制;
  • 曲线有C2的连续性.

    我们可以拥有其中的任意三种属性,但不能拥有全部四种属性;有三种表示的任意组合。在本书中,我们将讨论三次b样条不插值它们的控制点(但有局部控制和C2);基数样条和卡特穆尔-罗姆样条插值它们的控制点和提供局部控制,但不是C2;和自然立方插值和C2,但没有局部控制。     立方体的连续性是指分段之间(在结点处)的连续性。立方块本身在它们的导数中具有无限的连续性(我们到目前为止一直在讨论连续性的方式)。注意,如果你有很多控制点(或结),曲线可能是摆动的,这可能看起来不“平滑”。

15.5.1 自然曲线

    对于分段三次曲线,可以创建C2曲线。为此,我们需要在每个段的开头指定位置以及一阶和二阶导数(这样我们就可以确保它与前一个段的末尾相同)。注意,每个曲线段的四个参数中的三个都来自链条中的前一个曲线。这些C2连续的三次链有时被称为自然三次样条。     对于自然立方的一个部分,我们需要通过其端点的位置以及初始点的一阶导数和二阶导数来参数化立方。因此控制点是 $$ \begin{aligned} p0 &=f(0)&&=a_0+0^1a_1+0^2a_2+0^3a_3,\ p1 &=f'(0)&&=a_1+20^1a_2+30^2a_3,\ p2 &=f''(0)&&=21^1a_2+6 0^1a_3,\ p3 &=f(1)&&=a_0+1^1a_1+1^2a_2+1^3a_3, \end{aligned} $$     约束矩阵是 $$ C=\begin{bmatrix}1&0&0&0\ 0&1&0&0\ 0&0&2&0\ 1&1&1&1\ \end{bmatrix} $$     基矩阵是 $$ B=C^{-1}=\begin{bmatrix}1&0&0&0\ 0&1&0&0\ 0&0&.5&0\ -1&-1&-.5&1\ \end{bmatrix} $$     给定一组n个控制点,自然三次样条有n-1个三次段。第一个段使用控制点来定义它的开始位置、结束位置以及开始时的一阶和二阶导数。一个依赖计划复制第一个段末尾的位置、一阶和二阶导数,以便在第二个段中使用。     自然三次样条的一个缺点是它们不是局部的。任何段的任何变化都可能要求整个曲线发生变化(至少是发生变化后的部分)。更糟糕的是,自然三次样条往往是病态的:曲线开始时的一个小变化可能导致随后的大变化。另一个问题是,我们只能控制曲线开始时的导数。曲线开始后的段决定了它们的导数从起点开始。

15.5.2埃尔米特三次曲线

    第15.3.4节介绍了埃尔米特三次多项式。三次埃尔米特样条的段允许指定其端点的位置和一阶导数。通过使用一个段的末端和下一个段的开始的位置和导数的相同值,可以将一串段连接成CI样条。     给定一组n个控制点,其中每一个控制点都是导数值,三次埃尔米特样条包含(n-2)/2个三次段。样条插值点,如图15.6所示,但只能保证C1连续性。     厄米特立方很方便,因为它们提供了对形状的局部控制,并提供氯的连续性。但是,由于用户必须同时指定位置和导数,因此必须为导数提供一个特殊的接口。一种可能是为用户提供一些点,这些点表示如果将导数向量“放置”在位置点上,它们将在哪里结束。

15.5.3基数三次曲线

    基数三次样条是一种由三次多项式段组成的CI插值样条。给定一组n个控制点,基数三次样条用n -2个三次多项式段来插值除第一个和最后一个点外的所有点。     基数样条有一个称为张力的参数,它控制曲线在插值点之间的“紧”程度。张力是[0,1)范围内的一个数字,它控制曲线如何向下一个控制点弯曲。对于t = 0的重要特殊情况,样条称为Catmull-Rom样条。     基数样条的每一段使用四个控制点。对于线段i,使用的点是i, i+ 1, i+ 2, i+ 3,因为线段与它们的邻居共享三个点。每段从它的第二个控制点开始,到第三个控制点结束。曲线起点的导数由第一控制点和第三控制点之间的向量决定,曲线末端的导数由第二控制点和第四控制点之间的向量决定,如图15.7所示。     张力参数调整了导数的比例。具体来说,导数乘以(1 - t)/2。因此,立方的约束条件是 $$ \begin{aligned} &f(0)=p_2,\ &f(1)=p_3,\ &f'(0)=\frac{1}{2}(1-t)(p_3-p_1),\ &f'(1)=\frac{1}{2}(1-t)(p_4-p_2). \end{aligned} $$     求解这些控制点的方程(定义s = (1 -t)/2)给出 $$ \begin{aligned} &p_0=f(1)-\frac{2}{1-t}f'(0) &&= a_0+(1-\frac{1}{s})a_1+a_2+a_3,\ &p_1=f(0) &&= a_0,\ &p_2=f(1) &&= a_0+a_1+{\boldsymbol{a}}_2+a_3,\ &p_2=f(0)+\frac{1}{s}f'(1) &&= a_0+\frac{1}{s}a_1 + 2\frac{1}{s}a_2+3\frac{1}{s}a_3. \end{aligned} $$     这就得到了基数矩阵 $$ B=C^{-1}=\begin{bmatrix}0&1&0&0\ -s&0&s&0\ 2s&s-3&3-2s&-s\ -s&2-s&s-2&s\ \end{bmatrix} $$     由于线段i的第三点是线段i+1的第二点,所以相邻的基数样条线段是相连的。类似地,同样的点被用来指定每个段的一阶导数,提供Cl连续性。     基数样条很有用,因为它们提供了一种简单的方法来插值一组具有CI连续性和局部控制的点。它们只有C',所以它们有时会有“扭结”。张力参数为插值点之间发生的事情提供了一些控制,如图15.8所示,其中显示了通过一组点的基数样条的集合。这些曲线使用相同的控制点,但它们使用不同的张力参数值。注意,第一个和最后一个控制点没有插值。     给定一组n个点来插值,你可能想知道为什么我们更喜欢使用基数三次样条(即n -2个三次块的集合),而不是15.3.6节中所述的单个n阶多项式。插值多项式的一些缺点是:

  • 插值多项式倾向于超越点,如图15.9所示。随着分数的增加,这种超调变得更糟。基数样条在点之间表现良好。
  • 插值多项式的控制不是局部的。改变样条开始处的一个点会影响整个样条。基数样条是局部的:样条上的任何位置最多受它的四个相邻点的影响。
  • 插值多项式的求值不是局部的。求多项式上的一个点需要访问它的所有点。对分段三次曲面上的一个点求值只需要固定的少量计算,不管点的总数有多大。

    随着点数的增加,在使用插值样条曲线时还会出现各种其他的数值和技术问题。更多信息请参见De Boor(2001)。     基数样条的缺点是它不插值第一个或最后一个点,这可以通过在序列的任意一端添加一个额外的点来轻松解决。基数样条也不是连续的——只在节处提供C1连续性。


15.6近似曲线

    控制曲线最简单的方法似乎是指定一组点,让它进行插值。然而,在实际操作中,插值方案通常具有不受欢迎的特性,因为它们的连续性较差,并且无法控制点之间发生的事情。只近似于点的曲线方案通常是首选的。在近似方案中,控制点影响曲线的形状,但不能精确地指定它。虽然我们放弃了直接指定曲线通过的点的能力,但我们获得了更好的曲线行为和局部控制。如果我们需要插值一组点,可以计算控制点的位置,这样曲线就可以通过这些插值点。     计算机图形学中最重要的两种近似曲线是Bézier曲线和b样条曲线。

15.6.1贝塞尔曲线

    Bézier曲线是计算机图形学中自由曲线最常见的表示形式之一。这些曲线以Pierre Bézier的名字命名,他是其中一位对它们的开发起到了重要作用的人。Bézier曲线有一个有趣的历史,它们是由几个独立的小组同时开发的。     Bézier曲线是一个近似于其控制点的多项式曲线。曲线可以是任意次的多项式。d次曲线由d+ 1个控制点控制。曲线插值它的第一个控制点和最后一个控制点,形状直接受到其他点的影响。     通常,复杂的形状是通过连接一些Bézier的低度曲线而形成的,在计算机图形学中,三次(d = 3) Bézier曲线通常用于此目的。许多流行的插图程序,如Adobe Illus trator和字体表示方案(如Postscript中使用的)使用三次Bézier曲线。Bézier曲线在计算机图形学中非常受欢迎,因为它们易于控制,有许多有用的属性,并且有非常有效的算法来处理它们。     Bézier曲线是这样构造的:

  • 该曲线插值第一个和最后一个控制点,u分别为0和1。
  • 曲线开始(结束)处的一阶导数由第一和第二控制点(紧挨着最后和最后)之间的向量决定。
  • 导数是由这些点之间的向量根据曲线的度进行缩放得到的。曲线开始(结束)处的高导数取决于曲线开始(结束)处的点。n阶导数取决于第一个(最后一个)n + 1点。     例如,考虑如图15.10所示的3次(三次)Bézier曲线。曲线有4个(d + 1)控制点。它从第一个控制点(po)开始,到最后一个控制点(pi)结束。初始的一阶导数与第一和第二个控制点(P1 - Po)之间的向量成正比。具体来说,f'(0) = 3(p1 - Po)同样,曲线末端的一阶导数为f'(1) = 3(p3 - p2)。曲线起点的二阶导数可以从控制点po, P1和p2确定     利用上一段中关于Bézier立方体的事实,我们可以使用第15.5节的方法为它们创建参数函数。开始和结束的插值和导数的定义可以给出 $$ \begin{aligned} p_0 &=f(0) &&= a_30^3+a_20^2+a_10+a_0,\ p_3 &=f(1) &&= a_31^3+a_21^2+a_11+a_0,\ 3(p_1-p_0) &=f'(0) &&= 3a_30^2+2a_20+a_1,\ 3(p_3-p_2) &=f'(1) &&= 3a_1^2+2a_21+a_1.\ \end{aligned} $$     这可以用基矩阵来求解 $$ B=C^{-1}=\begin{bmatrix}1&0&0&0\ -3&3&0&0\ 3&-6&3&0\ -1&3&-3&1\ \end{bmatrix} $$     然后写成 $$ f(u)=(1-3u+3u^2-u^3)p_0+(3u-6u^2+3u^3)p_1+(3u^2-3u^3)p_2+(u^3)p_3,\ $$     或 $$ f(u) = \sum_{i=0}^db{i,3}\bf P_i $$     式中,$b_{i,3}$为3次的Bézier混合函数: $$ \begin{aligned} b_{0,3}&=(1-u)^3,\ b_{1,3}&=3u(1-u)^2,\ b_{2,3}&=3u^2(1-u),\ b_{3,3}&=u^3.\ \end{aligned} $$     幸运的是,Bézier曲线的混合函数有一个特殊的形式,适用于所有的度。这些函数被称为伯恩斯坦基多项式,具有一般形式 $$ b_{k,n}(u)=C(n,k)u^k(1-u)^{(n-k)} $$     其中n为Bézier曲线的阶数,k为0到n(含)之间的混合函数数。C(n, k)为二项式系数: $$ C(n,k)=\frac{n!}{k!(n-k)!} $$     给定控制点pe的位置,求n阶(n + 1个控制点)Bézier曲线的函数为 $$ p(u)=sum_{k=0}^np_kC(n,k)u^k(1-u)^{n-k} $$     一些Bézier段如图15.11所示。     Bézier段有几个有用的属性:
  • 曲线以控制点的凸包为界。
  • 任何直线与曲线相交的次数不得超过与连接控制点的线段集合的相交次数。这就是所谓的变异递减特性。这个属性如图15.12所示。
  • 曲线是对称的:反转控制点的顺序产生相同的曲线,带有反转的参数化。
  • 曲线是仿射不变的。这意味着平移、缩放、旋转或倾斜控制点与对曲线本身执行这些操作是相同的。
  • 有很好的简单算法来评估和细分Bézier曲线到片段本身Bézier曲线。因为细分可以使用后面描述的算法有效地完成,分治方法可以用于为重要任务创建有效的算法,如绘制Bézier曲线,用线段近似它们,以及确定两条曲线之间的交点。

    当Bézier段连接在一起形成样条曲线时,段之间的连接性是通过共享端点来创建的。然而,导数的连续性必须通过定位其他控制点来实现。这为Bézier样条的用户提供了对平滑度的控制。对于G连续,第一条曲线的倒数第二个点和第二条曲线的第二个点必须与相等的端点共线。对于Cl连续性,点之间的距离也必须相等。如图15.13所示。通过适当地定位更多的点,可以创造更高程度的连续性。

Bézier曲线的几何直觉

    Bézier曲线可以从几何原理推导,也可以从上面描述的代数方法推导。我们概述了几何原理,因为它们提供了Bézier曲线如何工作的直觉。     想象一下,我们有一组控制点,我们想从中创建一条平滑的曲线。简单地将点与线连接起来(形成控制多边形)将导致一些不光滑的东西。它会有锋利的弯角。我们可以想象通过切断棱角来“平滑”这个多边形,生成一个更光滑的新多边形,但在数学意义上仍然不是“光滑”的(因为曲线仍然是一个多边形,因此只有C’)。我们可以重复这个过程,每次产生一个更光滑的多边形,如图15.14所示。在极限情况下,也就是如果我们无限次地重复这个过程,我们会得到一条C1平滑曲线。     我们对抄近路所做的就是定义一个细分方案。也就是说,我们通过将一个简单的曲线分解成更小的部分(例如,细分它)来定义曲线。得到的曲线是通过无穷次应用这个过程得到的极限曲线。如果细分方案定义正确,结果将是一条光滑的曲线,它将具有参数形式。     让我们考虑将切角应用到单个角上。给定三个点(Po, P1, p2),我们重复“切角”,如图15.15所示。在每一步中,我们将每个线段分成两半,连接中点,然后将角点移动到新线段的中点。注意,在这个过程中,引入了新的点,移动了一次,然后在接下来的迭代中保持在这个位置。端点永远不会移动。     如果我们计算p2的“新”位置作为中点的中点,我们得到表达式 $$ p'2=\frac{1}{2}(\frac{1}{2}p_0+\frac{1}{2}p_1)+\frac{1}{2}(\frac{1}{2}p_1+\frac{1}{2}p_2) $$     这种结构实际上适用于沿着每段的其他比例的距离。如果我们设u为每一段的起始点和结束点之间的距离也就是我们设的中点,我们可以把这个表达式改写为 $$ p (u) = (1 - u )((1 - u)p_0 + up_1) + u ((1-u)p_1+up_2) $$     对术语进行重新分组得到二次函数Bézier: $$ B_2(u) = (1 - u )^2p_0 + 2u ((1-u)p_1+u^2p_2) $$

德卡斯特尔雅算法

    Bézier曲线的一个很好的特点是,有一个非常简单和通用的方法来计算和细分它们。该方法被称为de Casteljau算法,使用线性插值序列来计算沿Bézier曲线的任意urder。它是对上一节中描述的细分方案的推广。     de Casteljau算法首先将每一个相邻的点集合与直线连接起来,然后在这些直线上找到u插值点,给出n -1个点的集合。这些点与直线相连,这些直线被插值(同样是u),得到n-2个点。这个过程不断重复,直到出现一个点。这个过程的说明如图15.16所示。     在Bézier段上计算一个点的过程还提供了在该点上划分段的方法。在de Casteljau算法中计算的中间点形成新的、更小的段的新的控制点,如图15.17所示。     一个划分Bézier曲线的好算法的存在使得分治算法成为可能。例如,当绘制一条Bézier曲线时分段,很容易检查曲线是否接近直线,因为它的凸包为界。如果曲线的控制点都接近共线,则可以将曲线画成直线。否则,曲线可以被分割成更小的片段,这个过程可以重复。类似的算法可以用于确定两条曲线之间的交点。由于这种算法的存在,其他曲线表示通常被转换为Bézier形式进行处理。

15.6.2 B样条

    b样条提供了一种用d次多项式组成的曲线逼近n个点集合的方法,该曲线具有C(d-1)连续性。与上一节的Bézier样条不同,b样条允许生成任意所需连续性程度的曲线(几乎达到点的数量)。正因为如此,在计算机图形学中,b样条是指定非常平滑的曲线(高连续性)的首选方法。如果我们想通过任意数量的点得到C2或更高的曲线,b样条可能是正确的方法。     我们可以用b样条基函数的线性组合来表示曲线。由于这些基函数本身就是样条,我们称它们为基样条或简称为b样条。每个b样条或基函数都由一组d + 1次的多项式组成。b样条方法提供了定义这些函数的一般步骤。     b样条这个术语专门指基函数之一,而不是由一组b样条线性组合而成的函数。然而,在计算机图形学中如何使用这个术语是不一致的。通常,“b样条曲线”是指由b样条的线性组合表示的曲线。     将多项式表示为其他多项式的线性组合的想法已经在15.3.1节和15.3.5节中讨论过。将一个样条表示为其他样条的线性组合已在15.4.1节中演示过。事实上,给出的例子是b样条的一个简单例子。     将一个函数表示为其他函数的线性组合的一般符号是 $$ f(t)=\sum_{i=1}^np_ib_i(t), \tag{15.15} $$     p是系数b是基函数。如果系数是点(例如,2或3个向量),我们将它们称为控制点。使这种方法起作用的关键是适当地定义b。b样条提供了一种非常通用的方法。     一组b样条可以定义为若干系数n和一个参数值k.3k的值比用于生成b样条的多项式(k = d + 1)的次数大1。     b样条很重要,因为它们提供了一种非常通用的方法来创建具有许多有用属性的函数(这对表示曲线很有用)。由参数值为k的b样条构成的n点曲线:

  • 是C (k-2)连续;
  • 由k-1次的多项式构成;
  • 具有局部控制——曲线上的任何位置只依赖于k个控制点;
  • 以凸包为界的点;
  • 显示了如图15.12所示的变化递减特性。

    使用b样条创建的曲线不一定要插入控制点。     我们将介绍b样条曲线,首先看一个具体的、简单的例子来介绍概念。然后我们将概括这些方法并说明它们为什么有趣。因为计算b样条的方法是非常普遍的,我们推迟介绍它,直到我们展示了这些普遍是什么。

统一的线性b样

    考虑以下形式的一组基函数: $$ b_{i,2}(t)=\begin{cases} t-i &if~ i\leq t \leq i+1,\ 2-t+i &if~ i+1\leq t \leq i+2, \tag{15.16}\ 0 &otherwise. \end{cases} $$     每一个函数看起来都像一个小三角“帽子”在i和i+2之间,其峰值为ati | 1。每个都是一个分段多项式,结点在i, i | 1, i | 2。 其中两个如图15.18所示。     这些函数(bi,2)都是一条一阶(线性)b样条。因为我们稍后将考虑其他参数值的b样条曲线,所以我们在下标中用2来表示它们。     注意,我们选择将b样条的下缘(它的第一个结)放在i处。因此,第一个b样条(i = 1)的第一个结位于1处。对系数向量的b样条或元素的迭代从1到n(见式15.15)。 当b样条被实现时,以及在许多其他关于b样条的讨论中,它们的编号通常从0到n -1。     我们可以使用式15.15从n个控制点集合创建一个函数,这些函数用于b;创建一个受系数影响的“整体函数”。如果我们要用这些(k = 2)条b样条来定义整个函数,我们将定义一个分段多项式函数,它对t = k和t = n+ 1之间的系数p进行线性插值。注意,虽然(k = 2) b样条插值所有的系数,但在一些特定的条件下(我们将在15.6.3节讨论),更高次的b样条是这样做的。     在这个简单的例子中可以看出b样条的一些性质。我们将用k作为参数,n作为系数或控制点的数量,将这些写成一般形式:

  • 每条b样条有k + 1节。
  • 每个b样条在它的第一个结之前和最后一个结之后都是零。
  • 整体样条具有局部控制功能,因为每个系数只乘以一条b样条,且该b样条仅在k +1节之间非零。
  • 整个样条有n +k个结。
  • 每条b样条是C(k-2)连续的,因此整体的样条是C(k-2)连续的。
  • 对于结点k到n+1之间的所有参数值,b样条的集合和为I。这个范围是有k条非零b样条的范围。对l求和很重要,因为它意味着b样条是移位不变的:平移控制点将平移整个曲线。
  • 在它的每个结点之间,b样条是一个d=k-1次的单一多项式。因此,整个曲线(把这些加在一起)也可以表示为任何相邻结点之间的单次d多项式。

    在本例中,我们选择了均匀间隔的结。我们稍后将考虑具有非均匀间距的b样条曲线。当结间距相等时,除了移位之外,每条b样条都是相同的。具有均匀结间距的b样条有时被称为均匀b样条或周期b样条。

二次均匀b样条

    在上一节中列出的b样条的性质是针对任意n和k而编写的。构造b样条的一般步骤将在后面介绍,但首先,让我们考虑k = 3的另一个具体情况。     b样条曲线b2,3如图15.19所示。它由二次元(二次元)组成,有三个二次元。它是Cl连续的,并且只有在它跨越的四个结点内是非零的。注意,一个二次b样条是由三个部分组成的,一个在结1和2之间,一个在结2和3之间,一个在结3和4之间。在15.6.3节中,我们将看到构建这些函数的一般过程。现在,我们只考察这些函数: $$ b_{i,3}(t)=\begin{cases} \frac{1}{2}u^2 &if~ i\leq t \leq i+1,&&u=t-i,\ -u^2+u+\frac{1}{2} &if~ i+1\leq t \leq i+2, &&u=t-(i+1),\tag{15.17}\ \frac{1}{2}(1-)^2 &if~ i+1\leq t \leq i+2, &&u=t-(i+2),\ 0 &otherwise. \end{cases} $$     为了使表达式更简单,我们将每个部分的函数写成应用于0到1的范围。     如果我们计算由b样条求和得到的整体函数,在任何时候只有k(在本例中是3条)是非零的。其中一个在公式15.17的第一部分,两个在第二部分,还有一个在第三部分。因此,我们可以把整个函数中的任何一部分看作是 由d = k - 1次多项式组成,取决于k个系数。对于k = 3的情况,我们可以写 $$ f(u)=\frac{1}{2}(1-u)^2p_1+(-u^2+u+\frac{1}{2})P_{i+1}+\frac{1}{2}u^2 P_{i+2} $$     在u =t-i。它定义了i < t < i+1 整体函数的一部分。     如果我们有一组n个点,我们可以用b样条来画一条曲线。如果有7个点,我们就需要7条b样条。当k= 3时,一组7条b样条如图15.20所示。注意这里有n. + k(10)个结,b样条的和是k到n + 1范围内的1(结3到8)。使用这些b样条和一组点指定的曲线如图15.21所示。

均匀三次b样

    因为三次多项式在计算机图形学中非常流行,所以k = 4的b样条的特殊情况非常重要,所以我们在讨论一般情况之前要考虑它。三次b样条由四个三次多项式分段定义。确定这些零件的一般过程是 稍后描述,但结果是 如果< t < i + 1 u =我, -3u3 + 3u?+ 3u +1) ifi+1<t<i+2 u =t- (i+1), BI,4(t) =(3u3 - 6u2 + 4) ifi+2<t<i+3 u =t- (i+2), (- u + 3 u - 3 + 1)如果+ 3 < t <我+ 4 u = t - (i + 3),否则。 (15.18) i = 1时的3次b样条曲线如图15.22所示。 我们可以把i + 3和i +4之间的整体曲线的函数写成参数u在0到1之间的函数以及影响它的四个控制点: f(u) = (-u + 3u?- 3u + 1)pi + (3u - 6u)再+ 4)圆周率+ 1 +(-3u + 3u +1)Pi+2+Pi+3 的三次b样条的基矩阵可以用前几节的矩阵表示法重写

  • 1 毫米 -|ه 3 3
  • June 30 4 1 与从第15.5节的约束导出的矩阵不同,这个矩阵是从多项式中创建的,多项式由下一节定义的一般b样条程序确定。 15.6.3非均匀b样 b样条的一个很好的特性是它们可以定义为任何k> 1。因此,如果我们需要一个更平滑的曲线,我们可以简单地增加k的值,如图15.23所示。 到目前为止,我们已经说过b样条可以推广到任意k > 1和任意n b> d。 在我们演示如何计算b样条曲线之前,还要介绍最后一个泛化。对任意非递减的结向量定义b样条。 对于给定的n和k, b样条集合(以及由它们的线性组合创建的函数)有n +k个节。我们可以将这些结的值写成一个向量,我们将其表示为t。对于均匀b样条,结向量是[1,2,3,…然而,对于任何长度为n+ k的结向量,只要值不递减(例如,tit1 >t;),都可以生成b样条。 非均匀结间距有用的主要原因有两个:它让我们控制每个系数影响的整体函数的参数范围,它允许我们重复结(例如,创建没有间隔的结),以便在这些点周围创建具有不同属性的函数。后者将在本节后面讨论。 为b样条指定结值的能力类似于为插值样条曲线指定插值点的能力。它允许我们将曲线特征与参数值相关联。通过指定一个非均匀结向量,我们指定了b样条曲线的每个系数影响的参数范围。记住b样条i只有在i和knoti +k之间是非零的。因此,与之相关的系数只影响这些参数值之间的曲线。 对结值的控制特别有用的一个地方是插入或删除序列开头附近的结。为了说明这一点,考虑一个 曲线定义使用线性b样条(k = 2),如15.6.2节所述。对于n = 4,均匀结向量为[1,2,3,4,5,6]。该曲线由一组四个点控制,并跨越参数范围t = 2到t = 5。曲线的“末端”(t = 5)插入最后一个控制点。如果我们在点集中插入一个新的点,我们将需要一个更长的结向量。b样条的局部性防止这种插入影响曲线末端的值。较长的曲线仍然会在其末端插入最后的控制点。然而,如果我们选择保持统一的结间距,新的结向量将是[1,2,3,4,5,6,7)。曲线的端点将在t = 6处,最后一个控制点被插值时的参数值将与插入前的参数值不同。对于不均匀的结间距,我们可以使用结向量[1,2,3,3.5,4,5,6,这样曲线的端点就不受变化的影响。具有非均匀结间距的能力使b样条的局域性不仅是一个几何性质,也是一个代数性质。 现在我们介绍定义b样条的一般方法。给定系数n、b样条参数k和结向量(长度为n + k)的值,下面的递归方程定义了b样条: bi。1, t (t) = 1 ifti <h<ti+1, (15.19) 否则。 +bi+1.k-1(t)。(15.20) bi, k。t (t) 这个方程被称为考克斯-德布尔递归式。它可以用来计算特定b样条的特定值。然而。它更常用于代数推导方程,如式15.17或15.18。 作为一个例子,考虑一下我们如何推导出15.17式。使用统一的结向量[1,2,3,..]当t = i时,式15.20中k = 3时,得到 ს我3 (1) (i) t + 3 双+1.2 (15.21) (i+2) -i(i+3) - (i+1) (i + 3 双+1.2 继续递归,我们必须求递归表达式的值: 将这些结果代入公式15.22得到: (t
  • i)bi,1 + (i+2 -t)bi+1,1) (I+3 -T)(t-i+ 1)bi+1,1 + (i+3- t)bi+2,1 为了让这个表达式等价于公式15.17,我们注意到(k = 1)的每条b样条就像一个开关,只在特定的参数范围内打开。例如,bi,1只在i和i +1之间是非零的。所以,如果i<t<i+1,表达式中只有第一个(k = 1)条b样条是非零的,所以 bi,3(t) = (t-i)2 ifi<t<i+1。 类似的操作给出了公式15.17的其他部分。 重复结和b样条插值 虽然b样条有许多很好的性质,但用它们定义的函数通常不会插值系数。如果我们使用它们来定义一条曲线,我们想要插值一个特定的点,这可能会很不方便。我们简要介绍了如何使用b样条插值一个特定的点。更完整的讨论可以在章节注释中列出的书籍中找到。 使b样条插值它们的系数的一种方法是重复结。 如果一个特定b样条的所有内部结点都具有相同的值,那么整个函数将插值这个b样条的系数。如图15.24所示。 重复结点插值的代价很高:它去掉了b样条的平滑性,以及得到的整体函数和表示的曲线。 然而,在样条的开始和结束,连续性不是问题,结重复对于创建端点插值b样条很有用。虽然第一个(或最后一个)结的值对于插值并不重要,但为了简单起见,我们让前(或最后一个)k个结具有相同的值来实现插值。 端点插值二次b样条如图15.25所示。前两条和后两条b样条不同于统一的b样条。他们的表达 可以通过使用Cox-de Boor递归式得到: [(1 - t) 2如果0 < t < 1, b1 3(0, 0, 0、1、2…… 否则。 2 u -น2如果0 < t < 1 u = t, b2, 3。[0,0,0,1,2…)(t) = | (1 - u) 2如果1 < t < 2 u = t - 1, 否则。 15.6.4 NURBS 尽管b样条提供了所有的通用性,但仍有一些函数不能用它们精确地表示。特别地,b样条不能表示圆锥截面。为了表示这样的曲线,使用了两个多项式的比值。 用非均匀b样条来表示分子和分母 inator。它们最一般的形式是非均匀有理b样条,简称NURBS。 NURBS将标量权值h与每个控制点p关联,并对两者使用相同的b样条: f(u) i=1 hp(bi,k,t habi,k, bi。k,t是参数为k,结向量为t的b样条。 NURBS在几何建模中被广泛用于表示曲线和曲面,因为除了b样条的有用属性外,它们还提供了惊人的多功能性。 15.7总结 在本章中,我们讨论了自由形式曲线的一些表示方法。对于计算机图形来说,最重要的是: 基数样条使用一组三次块来插值控制点。它们通常比插值多项式更受欢迎,因为它们是局部的,更容易计算。 Bézier曲线近似它们的控制点,有许多有用的性质和相关的算法。因此,它们在图形应用程序中很受欢迎。 b样条曲线将曲线表示为b样条函数的线性组合。它们是一般的,有许多有用的性质,如被凸包限定和变化递减。当需要光滑的曲线时,通常使用b样条。 笔记 用数学方法表示形状的问题本身是一个完整的领域,通常称为几何建模。表示曲线只是开始,通常是曲面和固体建模的先驱。关于曲线的更深入的讨论可以在大多数几何建模文本中找到,例如,参见几何建模(Mortenson, 1985),这是计算机图形学学生可以访问的文本。许多几何建模钩子专门关注 在光滑的曲线和表面上。诸如《计算机图形学中使用样条曲线的介绍》(Bartels, Beatty, & Barsky, 1987)、《CAGD的曲线和曲面:实用指南》(Farin, 2002)和《用样条曲线进行几何建模:介绍》(E. Cohen, Riesenfeld, & Elber, 2001)等文本提供了大量关于曲线和曲面表示的细节。其他的书集中在样条曲线的数学:A Practical Guide to splines (De Boor, 2001)是一个标准的参考。 曲线和曲面表示的发展历史是复杂的,参见Farin在《计算机辅助几何设计手册》(Farin, Hoschek, & Kim, 2002)中的章节或NURBS导论:历史视角(D. F. Rogers, 2000)这一主题的书进行讨论。 许多想法是由来自不同学科的多个小组独立开发出来的。正因为如此,很难将想法归因于一个人或指出“原始”来源。它还导致了在文献中引入概念的符号、术语和方法的多样性。

15.7.1练习

对于练习1-4,找出约束矩阵、基矩阵和基函数。你可以使用matlab或OCTAVE(一种免费的类似于matlab的系统)这样的程序来求矩阵的逆。

  1. 线段:参数化的po位于线段的25%处(u = 0.25), pi位于线段的75%处。
  2. 二次方程:参数化po为起始点(u = 0)的位置,p1为起始点的一阶导数,p2为起始点的二阶导数。 3.立方:它的控制点是等间距的(po有u = 0, pi有u = 1/3)。P2的u = 2/3, p3的u = 1)
  3. 五次多项式:(一个五次多项式,所以矩阵是6x6)其中Po是起始位置,pi是起始导数,p2是中间位置(u = 0.5), p3是中间位置的一阶导数,p4是末端位置,ps是末端的一阶导数。
  4. 可以用拉格朗日式(式(15.12))表示练习3的插值三次。在几个不同的参数值处使用它,以确认它确实产生与练习3中推导的基函数相同的结果。
  5. 为参数函数表示的曲线设计弧长参数化方法 F (u) = (u, u2)
  6. 给定一个Hermite样条线段的四个控制点,计算一个等价的Bézier线段的控制点。
  7. 在参数值u = 0.5和u = 0.75时,使用de Casteljau算法计算三次Bézier曲线的控制点在(0,0),(0,1),(1,1)和(1,0)处的位置。画一个草图会帮助你做到这一点。
  8. 利用Cox-de Boor递归式推导(15.16)式。6. 为参数函数表示的曲线设计弧长参数化方法 F (u) = (u, u2)
  9. 给定一个Hermite样条线段的四个控制点,计算一个等价的Bézier线段的控制点。
  10. 在参数值u = 0.5和u = 0.75时,使用de Casteljau算法计算三次Bézier曲线的控制点在(0,0),(0,1),(1,1)和(1,0)处的位置。画一个草图会帮助你做到这一点。
  11. 利用Cox-de Boor递归式推导(15.16)式。