欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。
问题描述
利用三次bezier曲线制作一个类似于ppt里的曲线工具。
基本思路
对于给定点,每两个点之间再生成2个点,每段由4个点控制一个三次bezier曲线,每两段有一个公共点
bezier曲线介绍
曲线公式
P
(
t
)
=
∑
i
=
0
n
B
i
n
(
t
)
b
i
\boldsymbol P(t) = \displaystyle \sum_{i=0}^nB_i^n(t)\boldsymbol b_i
P(t)=i=0∑nBin(t)bi
B i n ( t ) = ( n i ) t i ( 1 − t ) n − i B_i^n(t)=\left (\begin{array}{l}n \\i \end{array} \right)t^i(1-t)^{n-i} Bin(t)=(ni)ti(1−t)n−i
矩阵表示
P ( t ) = [ B 0 n B 1 n ⋯ B n n ] [ b 0 b 1 ⋮ b n ] P(t) = \begin {bmatrix} B_0^n & B_1^n &\cdots& B_n^n \end{bmatrix} \begin {bmatrix} \boldsymbol b_0\\\boldsymbol b_1\\\vdots\\\boldsymbol b_n\end{bmatrix} P(t)=[B0nB1n⋯Bnn] b0b1⋮bn
上面的基称为Bernstein基, 可以看成是(t+(1-t))^n 多项式展开的每一项。
基本性质
Bernstein基的性质Besier曲线都有。
- n+1个控制点生成的曲线为n次多项式
- 正性+权性
B i n ( t ) > 0 , ∑ i = 0 n B i n ( t ) = ( t + ( 1 − t ) ) n = 1 B_i^n(t)> 0, \displaystyle \sum_{i=0}^nB_i^n(t)=(t+(1-t))^n =1 Bin(t)>0,i=0∑nBin(t)=(t+(1−t))n=1
是对所有控制点的加权平均 - 凸包性
可以认识Besier曲线是一个凸组合
所以曲线会被包含在控制点组成的凸包内。 - 端点插值性
曲线一定经过首尾两个控制点 - 仿射不变性
如果要于曲线做仿射变换,只需要对控制点进行仿射变换即可
6.控制点移动
P k ( t ) = [ B 0 n B 1 n ⋯ B k n ⋯ B n n ] [ b 0 b 1 ⋮ b k + v ⋮ b n ] = P ( t ) + B k n v \boldsymbol P_k(t) = \begin {bmatrix} B_0^n & B_1^n &\cdots&B_k^n&\cdots& B_n^n \end{bmatrix} \begin {bmatrix} \boldsymbol b_0\\\boldsymbol b_1\\\vdots\\\boldsymbol b_k+\boldsymbol v\\\vdots\\\boldsymbol b_n\end{bmatrix} = \boldsymbol P(t)+B_k^n \boldsymbol v Pk(t)=[B0nB1n⋯Bkn⋯Bnn] b0b1⋮bk+v⋮bn =P(t)+Bknv
u点求值
De Casteljau algorithm
Point deCasteljau(int i,int j,double u)
{
if(0==j)
return Pi;
else
return (1.0-u)*deCasteljau(i,j-1,u) + u*deCasteljau(i+1,j-1,u);
}
Point Evalute(double u)
{
return deCasteljau(0,n,u);
}
上面递归的代码会和菲波纳楔数列一样,存在很重复计算。
改成非递归式如下
Point Evaluate(Point A[],int n,double u)
{
for(int i=0;i<n;++i)
{
for(int j=0;j<n-i;++j)
A[j] = (1.0-u)*A[j]+u*A[j+1];
}
return A[0];
}
实现
代码:
https://gitcode.com/chenbb1989/geometric_model/tree/master/gohw4-2
演示视频
besier样条
本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接,帮忙转发,感激不尽。