曲线数学表达
前言
资料来源于网络,如有侵权请告知删除
图片资源挂载于github,若无法加载图片请检查网络
如有错误,清留言斧正
贝塞尔曲线
在讲述贝塞尔曲线的发展与表达之前,我们先回顾一下直线的表示方式。
回到小学数学,假设我们有两个点,他们相连即可构成一条直线。
用式子表达为:
$$
{\rm}(t) = t + (1 - t)
$$
仔细观察此时的t,我们已经完成了在计算机图形学中一个非常重要的表达方式:插值(lerp)
当然,我们提出这个概念肯定不是为了画一条直线……
我们可以画很多条直线,比如这两条:
然后,我们可以连接这两个点,在使用一次lerp,此时,随着t的变化,这个点在二维平面中也随之变化
于是,我们画出来了一条曲线,这个,就是经典的贝塞尔曲线。好了,讲完了(不是……)
接下来,才是我们正式开启曲线表达方式的旅程。
几种解释方式
曲线的表达是公式,而公式可以被写成许多种方式,下面我们介绍常见的表达方式:
lerp+递归
按照之前我们提到的绘制曲线的方式,从两点构成直线,到三个点画出曲线,我们可以加入更多的点,绘制出来的曲线也如出一辙:
这样的方式,我们称之为插值递归法。数学表达如下:
非常符合计算机直觉,但是,递归终归是一种昂贵的行为。所以我们也提供其他的表示方式。
Bernstein(基函数表示)
我们先放一张图:
这个就是国内大多数的教材在描述贝塞尔曲线时给出的解,可以看到,我们将每一个控制点单独列出来,并且每一个控制点所带的参数都是一个t为变量的方程。这样的方程组称为Bernstein基函数。
它们各自表示什么意思呢?
我们看向旁边的基函数曲线部分,我们可以将它理解为一种权重,或者“影响力”。
当t的参数函数值很大的时候,它乘以一个点,所得到的结果会靠近这个点,或者说(拉取)这个结果点【前提是所有的参数方程加起来的结果为1】
也就是说,在这个式子里面,我们有三个方向的力作用到结果点上面,这可以理解为Bernstein基函数的通俗解释方式。
polynomical coefficients(多项式系数)
既然我们可以用它组成以控制点为核心的基函数,那我们当然也可以将T提取出来,组成新的多项式
当然,还是先上图
由于系数变成了控制点,所以我们可以看到随着自变量t的变化,控制点所表示的系数却没有变化,
但是它仍然以类似(拉扯)的方式影响结果点,每一个系数的拉扯都是以控制点为最小单位的向量。
martix线性代数表示
挡然,你肯定已经发现了,使用一个简单的矩阵就可以完美的描述这个问题。线性代数的表达往往完备且优雅:
如图:
但这并不意味着其他方式不重要,相对于单纯的数学表达,带有显著物理特征的表达方式会有别样的美感。
我们这里放一张全家福吧:
主要应用场景
PS\设计软件等
贝塞尔曲线的优缺点
优点
光滑、连续、优雅……很适合一锤子买卖
缺点
1.lack local contorl
很显然,我们使用多项式系数表达贝塞尔曲线的时候,可以发现,每一个结果点都会收到每一个控制点的影响,这几乎是无法忽视的问题
假如我们每增加或者移动一个控制点,整条曲线就一起摇摆,那这曲线也太过于自由了。完全融入不了严肃的工作场景
2.没有精确地路径点
这一点来源于其计算性质,由于它受到了过多的“拉扯”,所以我们并不能让它通过某一点,出非精确计算达成某种巧合,
但是这个功能无论是在工业软件还是在游戏中都是十分重要的。
3.不稳定(指修改控制点时)
这一点和第一点可以算是师出同门了。我们急需一种方式约束他
4.计算困难
贝塞尔曲线的计算难度将随着阶数上升而显著提升
B样条
相信我们谈论了这么久的贝塞尔,你们一定猜到它不是重点
当然,由于贝塞尔曲线过于固执和不可控,它很难用于工业设计或者游戏设计领域,只能辅助人们做做PPT之类的活儿。
但是样条,他不一样。
样条的定义
样条,是早期人们在设计过程中为了得到自己想要的设计效果,利用细线、软管和一些固定方式扭曲得到的细长条。
我们现在借用这个词来描述曲线。
U的含义
正如大家想象的那样,样条线是使用类似压铁之类的外部工具进行曲线造型。
每次用一个压铁固定一段样条时,我们就会认为的将一条曲线分为两个部分,或者反过来说,把两条曲线拼接到一起。
诶……是不是想到了什么。如果说贝塞尔曲线被抛弃的原因是它不受控制,如果它足够短,那不受控就不受控吧,我们把这些
“元素”连接在一起,不一样可以拼接出曲线吗。可以说,这个想法也相当的计算机。
于是,每一段的曲线我们把它成为u,一条曲线将以u1,u2,u3等联系在一起。
contorl point & knots
我们将简单的三阶贝塞尔曲线相连,获得以下示意图:
相比之前的原始曲线,我们看看新的曲线有没有解决上面的四个问题?
1.它使得我们能够在节点(连接处)对曲线进行调整,同样的,也可以在控制点处进行调整,无疑解决了缺少控制点的情况。
2.精确路径点的问题,可以使用节点来解决。我们可以调整节点的位置,来使得曲线通过我们希望的方位。
3.不稳定的问题,是由不同曲线相连的方式解决的。由于分段曲线之间相互独立,所以不存在改变一个点,全局跟着动的情况
4.计算代价的问题,由于整条曲线由很多条三阶贝塞尔曲线相连而成,三阶贝塞尔曲线本身的计算开销低,连在一起也不会指数级上升。
由此来看,将3阶贝塞尔曲线相连仿佛是神之一笔,但是,这样就解决所有问题了吗?
虽然我们使用连接低阶贝塞尔曲线的方式规避了之前提出的问题,但是一条曲线终究是要落到实际的应用中。
我们接下来要讨论的就是关于曲线在应用中最重要的性质:连续性
样条线连续性分析
如果说样条线是由多条贝塞尔曲线相连形成,那么连接点必然是需要重点讨论的。
简单的连段相连,我们可以分为断开(broken)、接触(touch)、相接且切线同向(aligned)、相接且切线矢量相等(mirrored)。
连续性分析的物理意义
在游戏中,我们规划出一条曲线,可能是汽车的运动轨迹或者人物的行走轨迹,那么人物会以什么样的方式运动就是重点了。
我们在初中物理中学过,以时间t为自变量,路程l为因变量的一阶方程,其中,一阶导数为速度、二阶导数为加速度。
现在,我们把曲线看做一段距离,什么样的连接方式可以保证匀速、什么样的方式可以保证速度变化合理就是我们需要讨论的话题了。
连续的重要性
knots & alinged &mirror
连续性分析的应用场景
C连续与G连续
为什么我们要强调一条曲线的连续性?因为曲线的连续性在很大程度上决定了这条曲线的可用性。无论是工业设计、游戏开发、美术创作,我们都需要考虑在实际场景中赋予曲线特征的含义、比如形体、颜色、路径……
因此,能否让曲线符合我们所需的物理场景就是我们需要关心的内容了。
C0
倘若线段之间完全不相连,则不具备连续性。如下图的线段:
C1
c1的含义是曲线的一阶导数、或者是速度是连续的,注意,这里并不会同时要求C0连续,因为路径断开一样可以满足速度连续的要求
C2
如果说C1连续关心的速度是一阶导数,那么C2连续所关心的就是二阶导数,一阶导数我们可以用两个点连线计算出,而二阶导数就需要至少三个点了
所以我们需要当前点以及前面两个点加在一起才能完成二阶导数、也就是加速度的约束。
也就是说,我们需要牺牲一些控制自由度来完成这件事情,如下图:
C3
C3连续关心的是一种变化率的连续,英文里是jolt,这要求我们用当前点以及至少三个前置点去构建约束。
而巧合的是,我们使用的连接单位曲线时三阶的贝塞尔,也就是说,如果我们想要在当前的条件下实现C3连续的话,我们将锁死所有的可控点,如图:
也就是说,在不进行其他改变的情况下,曲线已经变成了一条贝塞尔曲线。换言之,他也是C无穷连续的曲线。
如果我们需要C3连续,就不得不升阶最小单位曲线。幸运的是,我们一般不会使用这么高连续性的曲线。
C与G
如果说,速度和加速度是物理运动的维度考量曲线,那么从设计角度来看,我们刚刚讨论的东西毫无用处
在设计中,我们往往只关心它长什么样子,也就是形体怎么样。
此时,我们就要引入一个工业设计中常用的概念,叫“光顺”,什么叫光顺,我们开灯看一下;
在这张图片中,我们使用了C0连续的曲线进行拉伸,并且加上了光源,此时,我们可以看到,在光的照射下,整个形体并不是很“丝滑”
这就是我们追求光顺的主观原因。
G1
G2
G3
B样条的数学表达
linear
Hermite
Catmull-Rom
B-Splines
nurbs曲线
未完待续……
Q.E.D.