java b样条_深入理解B样条曲线(上)

计算机中绘制曲线,通过贝塞尔曲线已经满足了我们大部分需求,但是其存在某些缺点,比如移动某一个控制点会导致整个曲线发生变化,即无法局部控制曲线的走向。所以 B 样条曲线(B-Spline)为了解决贝塞尔曲线的缺陷应运而生。

不了解贝塞尔曲线的同学,可以去看我以前写的另外一篇文章《深入理解贝塞尔曲线》,后面的内容会假设你已经了解并掌握贝塞尔曲线的相关内容。

什么是 B 样条曲线?

解释 B 样条曲线之前,首先要解释一下什么是样条。样条是通过一组指定点集而生成平滑曲线的柔性带。 简单地说,B 样条曲线就是通过控制点局部控制形状的曲线。不太理解的同学可以通过本文底部的 demo 查看 B 样条曲线中,控制点对曲线绘制的影响。

B 样条曲线比贝塞尔曲线的设计要复杂许多,我们先通过他们的公式大致比较一下贝塞尔曲线与 B 样条曲线的区别:

贝塞尔曲线:

B 样条曲线:

先简单介绍一下上述公式的组成:

表示曲线上的点坐标向量。

为控制点

数量。

为控制点坐标(

从 0 开始)。

为控制点坐标影响权重的多项式系数(式中

代表坐标的索引,

代表多项式最高的幂数)。

影响 B 样条曲线的次数:

就是曲线的次数。

是绘制曲线时的取值。

仔细观察这两个公式,我们可以看到以下的相同点:

都是求和公式。

都有一个

的多项式系数(式中贝塞尔曲线 x=n,B 样条曲线 x=d)。

可以看出有以下几个不同点:

贝塞尔曲线的多项式幂数与控制点数量一致,而 B 样条曲线的多项式幂数更自由。

贝塞尔曲线

的取值为固定的

,而 B 样条曲线是在最大和最小节点值之间。

计算多项式

公式中其他值其实都比较清晰,问题的关键是需要搞清楚那个多项式

是什么!

计算这个多项式,我们使用到了Cox-deBoor 递归公式,公式内容如下(需要注意一点,如果遇到分母为 0的情况时,需要特殊处理为整体值为 0):

从这个公式可以看出,递归公式的差异主要体现在

的取值上。需要注意的是节点的数量是由参数

决定的,数量等于

。根据这些节点

的取值,可以划分为一下三种类型:

均匀周期性(uniform)

开放均匀性(open uniform)

非均匀性(non-uniform)

想必大家现在已经非常头晕了吧 ,这都什么乱七八糟的,全是公式,完全看不懂啊!如果想讲清楚 B 样条曲线是非常困难的,因为其种类繁多,参数控制也非常自由。所以我还是通过讲解计算过程的栗子 来让大家更好地理解吧!

种类一: 均匀周期性 B 样条曲线

顾名思义,均匀周期性 B 样条曲线,就是节点

取值是均匀的,比如[-1, -0.5, 0, 0.5, 1],只要每个相邻的值间隔是相同的就可以了。不过为了方便计算,一般取值都是从 0 开始,并且间隔为 1。比如[0, 1, 2, 3, 4, 5, 6, 7, 8]。

均匀取节点值会导致每个多项式函数是周期性分布的,下面我会通过一个均匀二次 B 样条的计算过程,帮助大家理解这个周期性。

1.确定公式参数

因为是二次 B 样条曲线,所以我们可以确定以下参数:

曲线为二次,所以

,所以

控制点数量我们手动取值为 4(也可以取值为其他的值),即

节点

的数量为

,取值为 7,所以节点范围为:[0, 1, 2, 3, 4, 5, 6]。

确定这几个值后,我们就可以开始计算多项式 B 的值了。下面是迭代公式:

2.计算常量值的多项式

首先根据上面的公式 1,我们可以先得出常量值的多项式

:

时:

时:

时:

时:

因为 B 样条曲线公式为:

从上式可以很轻松地看出,我们需要知道以下几个多项式的函数:

所以我们现在依次求解这些多项式的函数。

3.计算非常量的多项式

的值(即

):

从上式中得出,我们需要得到

的值。

的值(即

):

equation?tex=B_%7B0%2C2%7D(u)%3D%0A%5Cfrac%7Bu-u_0%7D%7Bu_%7B1%7D-u_0%7DB_%7B0%2C1%7D(u)%2B%5Cfrac%7Bu_%7B2%7D-u%7D%7Bu_%7B2%7D-u_%7B1%7D%7DB_%7B1%2C1%7D(u)%5C%5C%0A%3D%20%5Cfrac%7Bu%7D%7B1%7DB_%7B0%2C1%7D(u)%2B%5Cfrac%7B2-u%7D%7B1%7DB_%7B1%2C1%7D(u)%5C%5C%0A%3D%20uB_%7B0%2C1%7D(u)%20%2B%20(2-u)B_%7B1%2C1%7D(u)%5C%5C%0A%0A%E5%B0%86B_%7B0%2C1%7D%E5%92%8CB_%7B1%2C1%7D%E5%B8%A6%E5%85%A5%E6%96%B9%E7%A8%8B%E5%BC%8F%5C%5C%0A%0A%3D%20%5Cleft%5C%7B%5Cbegin%7Bmatrix%7D%0Au%2C%20%26%200%7B%5Cleq%7Du%7B%5Cleq%7D1%5C%5C%0A%5C%5C%0A2-u%2C%20%26%201%7B%5Cleq%7Du%7B%5Cleq%7D2%5C%5C%0A%5C%5C%0A0%2C%20%26%20%E5%85%B6%E4%BB%96%0A%5Cend%7Bmatrix%7D%5Cright.

的值(即

):

equation?tex=B_%7B1%2C2%7D(u)%0A%3D%5Cfrac%7Bu-u_1%7D%7Bu_2-u_1%7DB_%7B1%2C1%7D(u)%2B%5Cfrac%7Bu_3-u%7D%7Bu_3-u_2%7DB_%7B2%2C1%7D(u)%5C%5C%0A%3D%5Cfrac%7Bu-1%7D%7B2-1%7DB_%7B1%2C1%7D(u)%2B%5Cfrac%7B3-u%7D%7B3-2%7DB_%7B2%2C1%7D(u)%5C%5C%0A%3D(u-1)B_%7B1%2C1%7D(u)%2B(3-u)B_%7B2%2C1%7D(u)%5C%5C%0A%E5%B0%86B_%7B1%2C1%7D%E5%92%8CB_%7B2%2C1%7D%E5%B8%A6%E5%85%A5%E6%96%B9%E7%A8%8B%E5%BC%8F%5C%5C%0A%3D%5Cleft%5C%7B%5Cbegin%7Bmatrix%7D%0Au-1%2C%20%26%201%7B%5Cleq%7Du%7B%5Cleq%7D2%5C%5C%0A%5C%5C%0A3-u%2C%20%26%202%7B%5Cleq%7Du%7B%5Cleq%7D3%5C%5C%0A%5C%5C%0A0%2C%20%26%20%E5%85%B6%E4%BB%96%0A%5Cend%7Bmatrix%7D%5Cright.

得出

继续迭代,我们就可以得出

了:

equation?tex=B_%7B0%2C3%7D(u)%0A%3D%20%5Cfrac%7B1%7D%7B2%7DuB_%7B0%2C2%7D(u)%20%2B%20%5Cfrac%7B1%7D%7B2%7D(3-u)B_%7B1%2C2%7D(u)%5C%5C%0A%0A%E5%B0%86%E5%85%B3%E7%B3%BB%E5%BC%8FB_%7B0%2C2%7D%E5%92%8CB_%7B1%2C2%7D%E5%B8%A6%E5%85%A5%5C%5C%0A%0A%3D%20%5Cleft%5C%7B%5Cbegin%7Bmatrix%7D%0A%5Cfrac%7B1%7D%7B2%7Du%5E2%2C%20%26%200%7B%5Cleq%7Du%7B%5Cleq%7D1%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7Du(2-u)%2B%5Cfrac%7B1%7D%7B2%7D(3-u)(u-1)%2C%20%26%201%7B%5Cleq%7Du%7B%5Cleq%7D2%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7D(3-u)%5E2%2C%20%26%202%7B%5Cleq%7Du%7B%5Cleq%7D3%5C%5C%0A%5C%5C%0A0%2C%20%26%20%E5%85%B6%E4%BB%96%0A%5Cend%7Bmatrix%7D%5Cright.

,

,

的值

这三个多项式的求解过程与

一致,有兴趣的小伙伴可以自己计算一下,加深理解。这里我仅给出最后的结果。

equation?tex=B_%7B1%2C3%7D(u)%0A%3D%20%5Cleft%5C%7B%5Cbegin%7Bmatrix%7D%0A%5Cfrac%7B1%7D%7B2%7D(u-1)%5E2%2C%20%26%201%7B%5Cleq%7Du%7B%5Cleq%7D2%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7D(u-1)(3-u)%2B%5Cfrac%7B1%7D%7B2%7D(4-u)(u-2)%2C%20%26%202%7B%5Cleq%7Du%7B%5Cleq%7D3%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7D(4-u)%5E2%2C%20%26%203%7B%5Cleq%7Du%7B%5Cleq%7D4%5C%5C%0A%5C%5C%0A0%2C%20%26%20%E5%85%B6%E4%BB%96%0A%5Cend%7Bmatrix%7D%5Cright.

equation?tex=B_%7B2%2C3%7D(u)%0A%3D%20%5Cleft%5C%7B%5Cbegin%7Bmatrix%7D%0A%5Cfrac%7B1%7D%7B2%7D(u-2)%5E2%2C%20%26%202%7B%5Cleq%7Du%7B%5Cleq%7D3%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7D(u-2)(4-u)%2B%5Cfrac%7B1%7D%7B2%7D(5-u)(u-3)%2C%20%26%203%7B%5Cleq%7Du%7B%5Cleq%7D4%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7D(5-u)%5E2%2C%20%26%204%7B%5Cleq%7Du%7B%5Cleq%7D5%5C%5C%0A%5C%5C%0A0%2C%20%26%20%E5%85%B6%E4%BB%96%0A%5Cend%7Bmatrix%7D%5Cright.

equation?tex=B_%7B3%2C3%7D(u)%0A%3D%20%5Cleft%5C%7B%5Cbegin%7Bmatrix%7D%0A%5Cfrac%7B1%7D%7B2%7D(u-3)%5E2%2C%20%26%203%7B%5Cleq%7Du%7B%5Cleq%7D4%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7D(u-3)(5-u)%2B%5Cfrac%7B1%7D%7B2%7D(5-u)(u-3)%2C%20%26%204%7B%5Cleq%7Du%7B%5Cleq%7D5%5C%5C%0A%5C%5C%0A%5Cfrac%7B1%7D%7B2%7D(6-u)%5E2%2C%20%26%205%7B%5Cleq%7Du%7B%5Cleq%7D6%5C%5C%0A%5C%5C%0A0%2C%20%26%20%E5%85%B6%E4%BB%96%0A%5Cend%7Bmatrix%7D%5Cright.

将四个函数分别绘制到坐标系中,大家就可以看到图像形状是完全相同的,只是在 x 轴方向做了平移,如下图所示。

:

:

:

:

4.确定曲线方程。

之前已经计算出了曲线的方程式,如下:

将上面的多项式带入到方程,就可以得到最终的曲线方程。然后将 t 从 0 取至 6,获得的点集就是我们想要的均匀周期性 B 样条曲线。

从多项式的取值,我们就可以看出 B 样条曲线的一个特点,就是控制点不会影响整个曲线的绘制,只是局部影响曲线的走向。

最后

我写了一个线上的demo,用于展示均匀周期性 B 样条曲线的绘制,有兴趣的同学可以去看一下。

下篇我将会介绍剩下两种 B 样条曲线的绘制过程,敬请期待!

你可能感兴趣的:(java,b样条)