# 贝塞尔曲线的数学原理 贝塞尔曲线是“参数”方程的一种形式。从数学上讲,参数方程作弊了:“方程”实际上是一个从输入到唯一输出的、良好定义的映射关系。几个输入进来,一个输出返回。改变输入变量,还是只有一个输出值。参数方程在这里作弊了。它们基本上干了这么件事,“好吧,我们想要更多的输出值,所以我们用了多个方程”。举个例子:假如我们有一个方程,通过一些计算,将假设为x的一些值映射到另外的值: \[ f(x) = \cos(x) \] 记号f(x)是表示函数的标准方式(为了方便起见,如果只有一个的话,我们称函数为f),函数的输出根据一个变量(本例中是x)变化。改变xf(x)的输出值也会变。 到目前没什么问题。现在,让我们来看一下参数方程,以及它们是怎么作弊的。我们取以下两个方程: \[ \begin{matrix} f(a) = \cos(a) \\ f(b) = \sin(b) \end{matrix} \] 这俩方程没什么让人印象深刻的,只不过是正弦函数和余弦函数,但正如你所见,输入变量有两个不同的名字。如果我们改变了a的值,f(b)的输出不会有变化,因为这个方程没有用到a。参数方程通过改变这点来作弊。在参数方程中,所有不同的方程共用一个变量,如下所示: \[ \left \{ \begin{matrix} f_a(t) = \cos(t) \\ f_b(t) = \sin(t) \end{matrix} \right. \] 多个方程,但只有一个变量。如果我们改变了t的值,fa(t)fb(t)的输出都会发生变化。你可能会好奇这有什么用,答案其实很简单:对于参数曲线,如果我们用常用的标记来替代fa(t)fb(t),看起来就有些明朗了: \[ \left \{ \begin{matrix} x = \cos(t) \\ y = \sin(t) \end{matrix} \right. \] 好了,通过一些神秘的t值将x/y坐标系联系起来。 所以,参数曲线不像一般函数那样,通过x坐标来定义y坐标,而是用一个“控制”变量将它们连接起来。如果改变t的值,每次变化时我们都能得到两个值,这可以作为图形中的(x,y)坐标。比如上面的方程组,生成位于一个圆上的点:我们可以使t在正负极值间变化,得到的输出(x,y)都会位于一个以原点(0,0)为中心且半径为1的圆上。如果我们画出t从0到5时的值,将得到如下图像(你可以用上下键来改变画的点和值): 贝塞尔曲线是(一种)参数方程,并在它的多个维度上使用相同的基本方程。在上述的例子中x值和y值使用了不同的方程,与此不同的是,贝塞尔曲线的xy都用了“二项多项式”。那什么是二项多项式呢? 你可能记得高中所学的多项式,看起来像这样: \[ f(x) = a \cdot x^3 + b \cdot x^2 + c \cdot x + d \] 如果它的最高次项是就称为“三次”多项式,如果最高次项是,称为“二次”多项式,如果只含有x的项,它就是一条线(不过不含任何x的项它就不是一个多项式!) 贝塞尔曲线不是x的多项式,它是t的多项式,t的值被限制在0和1之间,并且含有ab等参数。它采用了二次项的形式,听起来很神奇但实际上就是混合不同值的简单描述: \[ \begin{aligned} linear &= (1-t) + t \\ square &= (1-t)^2 + 2 \cdot (1-t) \cdot t + t^2 \\ cubic &= (1-t)^3 + 3 \cdot (1-t)^2 \cdot t + 3 \cdot (1-t) \cdot t^2 + t^3 \end{aligned} \] 我明白你在想什么:这看起来并不简单,但如果我们拿掉t并让系数乘以1,事情就会立马简单很多,看看这些二次项: \[ \begin{aligned} linear &= \hspace{2.5em} 1 + 1 \\ square &= \hspace{1.7em} 1 + 2 + 1\\ cubic &= \hspace{0.85em} 1 + 3 + 3 + 1\\ quartic &= 1 + 4 + 6 + 4 + 1 \end{aligned} \] 需要注意的是,2与1+1相同,3相当于2+1或1+2,6相当于3+3...如你所见,每次我们增加一个维度,只要简单地将头尾置为1,中间的操作都是“将上面的两个数字相加”。现在就能很容易地记住了。 还有一个简单的办法可以弄清参数项怎么工作的:如果我们将(1-t)重命名为a,将t重命名为b,暂时把权重删掉,可以得到这个: \[ \begin{aligned} linear &= BLUE[a] + RED[b] \\ square &= BLUE[a] \cdot BLUE[a] + BLUE[a] \cdot RED[b] + RED[b] \cdot RED[b] \\ cubic &= BLUE[a] \cdot BLUE[a] \cdot BLUE[a] + BLUE[a] \cdot BLUE[a] \cdot RED[b] + BLUE[a] \cdot RED[b] \cdot RED[b] + RED[b] \cdot RED[b] \cdot RED[b]\\ \end{aligned} \] 基本上它就是“每个ab结合项”的和,在每个加号后面逐步的将a换成b。因此这也很简单。现在你已经知道了二次多项式,为了叙述的完整性,我将给出一般方程: \[ Bézier(n,t) = \sum_{i=0}^{n} \underset{binomial\ term}{\underbrace{\binom{n}{i}}} \cdot\ \underset{polynomial\ term}{\underbrace{(1-t)^{n-i} \cdot t^{i}}} \] 这就是贝塞尔曲线完整的描述。在这个函数中的Σ表示了这是一系列的加法(用Σ下面的变量,从...=<值>开始,直到Σ上面的数字结束)。
### 如何实现基本方程 我们可以用之前说过的方程,来简单地实现基本方程作为数学构造,如下: ``` function Bezier(n,t): sum = 0 for(k=0; k= lut.length): s = lut.length nextRow = new array(size=s+1) nextRow[0] = 1 for(i=1, prev=s-1; i 既然我们已经知道基本函数的样子,是时候添加一些魔法来使贝塞尔曲线变得特殊了:控制点。