[图形学]习题解析1:一文搞懂贝塞尔曲线题目的计算

给定4点 P 1 ( 0 , 0 , 0 ) P_1(0,0,0) P1(0,0,0) P 2 ( 1 , 1 , 1 ) P_2(1,1,1) P2(1,1,1) P 3 ( 2 , − 1 , − 1 ) P_3(2,-1,-1) P3(2,1,1) P 4 ( 3 , 0 , 0 ) P_4(3,0,0) P4(3,0,0),用其作为特征多边形来构造一条三次Bezier曲线,并计算参数为 0 , 1 / 3 , 2 / 3 , 1 0,1/3,2/3,1 0,1/3,2/3,1的值。


首先是贝塞尔曲线的定义:当给定空间 n + 1 n+1 n+1个点的位置矢量 P i P_i Pi n n n次贝塞尔曲线上个点坐标的插值公式是:

P ( t ) = ∑ i = 0 n P i B i , n ( t ) , t ∈ [ 0 , 1 ] P(t)=\sum_{i=0}^{n}P_iB_{i,n}(t), t\in[0,1] P(t)=i=0nPiBi,n(t),t[0,1]

具体到对于三次贝塞尔曲线,亦即当 n = 3 n=3 n=3时,有:

P ( t ) = ∑ i = 0 3 P i B i , 3 ( t ) = ( 1 − t ) 3 P 0 + 3 t ( 1 − t ) 2 P 1 + 3 t 2 ( 1 − t ) P 2 + t 3 P 3 , t ∈ [ 0 , 1 ] P(t)=\sum_{i=0}^{3}P_iB_{i,3}(t)=(1-t)^3P_0+3t(1-t)^2P_1+3t^2(1-t)P_2+t^3P_3,t\in[0,1] P(t)=i=03PiBi,3(t)=(1t)3P0+3t(1t)2P1+3t2(1t)P2+t3P3,t[0,1]

问题是如何给它具体过来的呢?

其实就是对 B e r n s t e i n Bernstein Bernstein调和函数 B i , n ( t ) B_{i,n}(t) Bi,n(t)带入 n = 3 n=3 n=3,该函数的定义是:

B i , n ( t ) = n ! i ! ( n − i ) ! t i ( i − t ) n − i = C n i t i ( i − t ) n − i B_{i,n}(t)=\frac{n!}{i!(n-i)!}t^i(i-t)^{n-i}=C_n^it^i(i-t)^{n-i} Bi,n(t)=i!(ni)!n!ti(it)ni=Cniti(it)ni

此式带入 n = 3 n=3 n=3可得上式。


对于式子:

P ( t ) = ∑ i = 0 n P i B i , n ( t ) P(t)=\sum_{i=0}^{n}P_iB_{i,n}(t) P(t)=i=0nPiBi,n(t)

要分为两部分看,一部分是不定的,即选取的点是不确定的,所以 P i P_i Pi具体取值不知道是多少,另一部分是固定的调和函数,在三次贝塞尔曲线的具体情况下,它就是

P ( t ) = ∑ i = 0 3 B i , 3 ( t ) P(t)=\sum_{i=0}^{3}B_{i,3}(t) P(t)=i=03Bi,3(t)

为了看起来,把它写为矩阵形式。 P i P_i Pi它本身就有 x , y , z x,y,z x,y,z分量,三次计算可以合到一个矩阵里进行计算,要不然就得按照下式分别计算

P ( t ) = { x ( t ) = a 3 x t 3 + a 2 x t 2 + a 1 x t + a 0 x y ( t ) = a 3 y t 3 + a 2 y t 2 + a 1 y t + a 0 y z ( t ) = a 3 z t 3 + a 2 z t 2 + a 1 z t + a 0 z P(t)=\left\{ \begin{aligned} x(t) & = & a_{3x}t^3+a_{2x}t^2+a_{1x}t+a_{0x} \\ y(t) & = & a_{3y}t^3+a_{2y}t^2+a_{1y}t+a_{0y} \\ z(t) & = & a_{3z}t^3+a_{2z}t^2+a_{1z}t+a_{0z} \end{aligned} \right. P(t)= x(t)y(t)z(t)===a3xt3+a2xt2+a1xt+a0xa3yt3+a2yt2+a1yt+a0ya3zt3+a2zt2+a1zt+a0z


按照上面的思路写出三次 B e r n s t e i n Bernstein Bernstein调和函数的矩阵形式:

在这里插入图片描述
矩阵的推导如下,对于:

P ( t ) = ∑ i = 0 3 P i B i , 3 ( t ) = ( 1 − t ) 3 P 0 + 3 t ( 1 − t ) 2 P 1 + 3 t 2 ( 1 − t ) P 2 + t 3 P 3 , t ∈ [ 0 , 1 ] P(t)=\sum_{i=0}^{3}P_iB_{i,3}(t)=(1-t)^3P_0+3t(1-t)^2P_1+3t^2(1-t)P_2+t^3P_3,t\in[0,1] P(t)=i=03PiBi,3(t)=(1t)3P0+3t(1t)2P1+3t2(1t)P2+t3P3,t[0,1]

取新函数 B i , 3 B_{i,3} Bi,3 P i P_i Pi的系数,则调和函数可写为矩阵形式(虽然是个单行矩阵)

B = [ B 0 , 3   B 1 , 3   B 2 , 3   B 3 , 3 ] B=[B_{0,3} \text{ }B_{1,3}\text{ }B_{2,3}\text{ }B_{3,3}] B=[B0,3 B1,3 B2,3 B3,3]

其中每个 B i , 3 B_{i,3} Bi,3最高次项系数最大为3,故可用左侧含 t t t矩阵乘右侧系数矩阵得到。

P 0 P_0 P0系数 ( 1 − t ) 3 (1-t)^3 (1t)3为例,拆开即为 1 − 3 t + 3 t 2 − t 3 1-3t+3t^2-t^3 13t+3t2t3

什么,你忘了怎么拆了?立方和公式为:

( a + b ) 3 = a 3 + 3 a 2 b + 3 a b 2 + b 3 (a+b)^3=a^3+3a^2b+3ab^2+b^3 (a+b)3=a3+3a2b+3ab2+b3


拆开的结果按 t t t从高次到低次排列为 − t 3 + 3 t 2 − 3 t + 1 -t^3+3t^2-3t+1 t3+3t23t+1,取系数分别为 − 1 , 3 , − 3 , 1 -1,3,-3,1 1,3,3,1,正对应右侧系数矩阵的第一列,按矩阵乘法乘到左面正好是 − t 3 + 3 t 2 − 3 t + 1 -t^3+3t^2-3t+1 t3+3t23t+1,也就是 B 0 , 3 ( t ) B_{0,3}(t) B0,3(t)

该矩阵乘回去的结果是:

∣ B 0 , 3   B 1 , 3   B 2 , 3   B 3 , 3 ∣ T { \left| {B_{0,3}\text{ } B_{1,3}\text{ }B_{2,3}\text{ }B_{3,3}} \right|^T } B0,3 B1,3 B2,3 B3,3T

(竖着这个矩阵忘了对应的markdown语法了,所以写成横着的并加个 T T T,其实竖着才更直观)

然后就是求 ∣ B 0 , 3   B 1 , 3   B 2 , 3   B 3 , 3 ∣ T ∗ ∣ P 0   P 1   P 2   P 3 ∣ T { \left| {B_{0,3}\text{ } B_{1,3}\text{ }B_{2,3}\text{ }B_{3,3}} \right|^T }*{ \left| {P_0\text{ } P_1\text{ }P_2\text{ }P_3} \right|^T } B0,3 B1,3 B2,3 B3,3TP0 P1 P2 P3T

于是最终式子长这样(敲Markdown真不如用ipad手写…虽然难看不整齐就是了)

在这里插入图片描述


说了这么多,最后就绕到本题的解法去了,请务必要注意, P ( t ) P(t) P(t)参数归根到底还是 t t t,所以先带入几个控制点 P i P_i Pi并化简之后,就要对着题意带入 t t t来做题了。

在这里插入图片描述

带入对应的 t t t,可把矩阵解为 ∣ x   y   z ∣ { \left| x \text{ }y \text{ }z \right| } x y z的形式,即三维坐标。

答案分别是 ( 0 , 0 , 0 ) (0,0,0) (0,0,0) ( 1 , 2 / 9 , 2 / 9 ) (1,2/9,2/9) (1,2/9,2/9) ( 2 , − 2 / 9 , 2 / 9 ) (2,-2/9,2/9) (2,2/9,2/9) ( 3 , 0 , 0 ) (3,0,0) (3,0,0)


图文无关

虽然图文无关,但是看图可以知道 t t t是干啥的。

事实上,参数t在de Casteljau算法中会更加直观

上文中的计算贝塞尔曲线,计算量大(尤其是阶数不止三阶时)还不通用(三阶的算法只能计算三阶的贝塞尔曲线),因此还有另一种算法值得学习,即de Casteljau算法,这一般也是计算机实现使用的代码。


图源:计算机图形学(孙家广)P303前后

在这里插入图片描述
在这里插入图片描述
n + 1 n+1 n+1个点(可以形成 n n n条线段),控制形成 n n n阶贝塞尔曲线,所以不难看出为什么一次Bezier曲线控制点矩阵有两个点(即 P 0 P_0 P0 P 1 P_1 P1),高阶类推。

从2阶到7阶的贝赛尔曲线 private static final int MAX_COUNT = 7; // 贝塞尔曲线最大阶数 private static final int REGION_WIDTH = 30; // 合法区域宽度 private static final int FINGER_RECT_SIZE = 60; // 矩形尺寸 private static final int BEZIER_WIDTH = 10; // 贝塞尔曲线线宽 private static final int TANGENT_WIDTH = 6; // 切线线宽 private static final int CONTROL_WIDTH = 12; // 控制点连线线宽 private static final int CONTROL_RADIUS = 12; // 控制点半径 private static final int TEXT_SIZE = 40; // 文字画笔尺寸 private static final int TEXT_HEIGHT = 60; // 文本高度 private static final int RATE = 10; // 移动速率 private static final int HANDLER_WHAT = 100; private static final int FRAME = 1000; // 1000帧 private static final String[] TANGENT_COLORS = {"#7fff00", "#7a67ee", "#ee82ee", "#ffd700", "#1c86ee", "#8b8b00"}; // 切线颜色 private static final int STATE_READY = 0x0001; private static final int STATE_RUNNING = 0x0002; private static final int STATE_STOP = 0x0004; private static final int STATE_TOUCH = 0x0010; private Path mBezierPath = null; // 贝塞尔曲线路径 private Paint mBezierPaint = null; // 贝塞尔曲线画笔 private Paint mMovingPaint = null; // 移动点画笔 private Paint mControlPaint = null; // 控制点画笔 private Paint mTangentPaint = null; // 切线画笔 private Paint mLinePaint = null; // 固定线画笔 private Paint mTextPointPaint = null; // 点画笔 private Paint mTextPaint = null; // 文字画笔 private ArrayList mBezierPoints = null; // 贝塞尔曲线点集 private PointF mBezierPoint = null; // 贝塞尔曲线移动点 private ArrayList mControlPoints = null; // 控制点集 private ArrayList<ArrayList<ArrayList>> mTangentPoints; // 切线点集 private ArrayList<ArrayList> mInstantTangentPoints; private int mR = 0; // 移动速率 private int mRate = RATE; // 速率 private int mState; // 状态 private boolean mLoop = false; // 设置是否循环 private boolean mTangent = true; // 设置是否显示切线 private int mWidth = 0, mHe
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值