利用三次bezier制作分段可编辑样条

欢迎关注更多精彩
关注我,学习常用算法与数据结构,一题多解,降维打击。

问题描述

利用三次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=0nBin(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(1t)ni

矩阵表示

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)=[B0nB1nBnn] b0b1bn

上面的基称为Bernstein基, 可以看成是(t+(1-t))^n 多项式展开的每一项。

基本性质

Bernstein基的性质Besier曲线都有。

  1. n+1个控制点生成的曲线为n次多项式
  2. 正性+权性
    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=0nBin(t)=(t+(1t))n=1
    是对所有控制点的加权平均
  3. 凸包性
    可以认识Besier曲线是一个凸组合
    所以曲线会被包含在控制点组成的凸包内。
  4. 端点插值性
    曲线一定经过首尾两个控制点
  5. 仿射不变性
    如果要于曲线做仿射变换,只需要对控制点进行仿射变换即可
    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)=[B0nB1nBknBnn] b0b1bk+vbn =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样条

在这里插入图片描述


本人码农,希望通过自己的分享,让大家更容易学懂计算机知识。创作不易,帮忙点击公众号的链接,帮忙转发,感激不尽。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值