besier打断和升阶,高阶性质

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

问题描述

  1. 对besier曲线在u处打断,生成两条besier曲线
  2. 对besier曲线升阶处理

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

只要对每个系数求导即可

B i n ( t ) ′ = i ( n i ) t i − 1 ( 1 − t ) n − i − ( n − i ) ( n i ) t i ( 1 − t ) n − i − 1 ⋯ ( 1 ) B_i^n(t)'=i\left (\begin{array}{l}n \\i \end{array} \right)t^{i-1}(1-t)^{n-i}-(n-i)\left (\begin{array}{l}n \\i \end{array} \right)t^i(1-t)^{n-i-1} \cdots (1) Bin(t)=i(ni)ti1(1t)ni(ni)(ni)ti(1t)ni1(1)

对组合数展开可以发现

B i n ( t ) ′ = n ( n − 1 i − 1 ) t i − 1 ( 1 − t ) n − i − n ( n − 1 i ) t i ( 1 − t ) n − i − 1 = n B i − 1 n − 1 ( t ) − n B i n − 1 ( t ) B_i^n(t)'=n\left (\begin{array}{cl}n-1 \\i-1 \end{array} \right)t^{i-1}(1-t)^{n-i}-n\left (\begin{array}{cl}n-1 \\i \end{array} \right)t^i(1-t)^{n-i-1}=nB_{i-1}^{n-1}(t)-nB_i^{n-1}(t) Bin(t)=n(n1i1)ti1(1t)nin(n1i)ti(1t)ni1=nBi1n1(t)nBin1(t)

从(1)式可知,当i=0时, B i − 1 n − 1 ( t ) = 0 B_{i-1}^{n-1}(t)=0 Bi1n1(t)=0

设 q i = B i n − 1 ( t ) 设q_i = B_{i}^{n-1}(t) qi=Bin1(t)

P ′ ( t ) = n [ q 0   ⋯   q n − 1 ] [ b 1 ⋮ b n ] + n [ q 0   ⋯   q n − 1 ] [ − b 0 ⋮ − b n − 1 ] \boldsymbol P'(t)=n[q_0\ \cdots \ q_{n-1}] \begin {bmatrix} \boldsymbol b_1\\\vdots\\\boldsymbol b_n\end{bmatrix}+n[q_0\ \cdots \ q_{n-1}] \begin {bmatrix} -\boldsymbol b_0\\\vdots\\-\boldsymbol b_{n-1}\end{bmatrix} P(t)=n[q0  qn1] b1bn +n[q0  qn1] b0bn1

= ∑ i = 0 n − 1 B i n − 1 ( t ) ( b i + 1 − b i ) = \displaystyle \sum_{i=0}^{n-1}B_i^{n-1}(t)(\boldsymbol b_{i+1}-\boldsymbol b_i) =i=0n1Bin1(t)(bi+1bi)

上式一共是n项,所以n阶bezier曲线的导数可以由n-1阶bezier曲线得到

控制点如下

D i = n ( b i + 1 − b i ) , i ∈ [ 0 , n − 1 ] D_i = n(b_{i+1}-b_i), i\in[0, n-1] Di=n(bi+1bi),i[0,n1]

导数的计算也可以由De Casteljau algorithm 来算

端点导数

将t=0, t=1代入公式,发现首末端的导数刚好是初始两点和末端两点连线的n倍。

高阶导数

参数曲线的d阶导为在d-1阶导数基础上再求一次导。

P ′ ′ ( t ) = ∑ i = 0 n − 2 B i n − 2 ( t ) ( ( n − 1 ) ( D i + 1 − D i ) ) \boldsymbol P''(t)= \displaystyle \sum_{i=0}^{n-2}B_i^{n-2}(t)((n-1)(\boldsymbol D_{i+1}-\boldsymbol D_i)) P′′(t)=i=0n2Bin2(t)((n1)(Di+1Di))

= n ( n − 1 ) ∑ i = 0 n − 2 B i n − 2 ( t ) ( b i + 2 − 2 b i + 1 + b i ) =n(n-1) \displaystyle \sum_{i=0}^{n-2}B_i^{n-2}(t)(\boldsymbol b_{i+2} -2\boldsymbol b_{i+1}+\boldsymbol b_i) =n(n1)i=0n2Bin2(t)(bi+22bi+1+bi)

从u处打断

根据 De Casteljau algorithm 的过程可以观察到。

每次迭代后,数组中的第1个点和最后一个点,分别是左右子段的控制点。


/*!
 *\brief Bezier曲线的打断
*\ param const std::vector<Point> & A 控制点序列
*\ param double u 打断处的参数 (0,1)
*\ param std::vector<Point> & cv_left 打断后前半部分的控制点
*\ param std::vector<Point> & cv_right 打断后后半部分的控制点
*\ Returns:   std::pair<List2f, List2f>
*/
std::pair<List2f, List2f> subDevide(const std::vector<Eigen::Vector2f> &A, float u)
{
    List2f cv_left = A;
    List2f cv_right = A;
    if(A.size()<2)return {cv_left, cv_right};

    int p = A.size()-1;
    //p次迭代
    for (int i = 0;i<p;++i)
    {
        for (int j = 0;j<p - i;++j)
            cv_right[j] = (1.0 - u)*cv_right[j] + u*cv_right[j + 1];
        //左侧控制点为每次迭代的首点
        cv_left[i + 1] = cv_right[0];
    }

    return {cv_left, cv_right};
}

升阶

设原来曲线控制点为b0, b1, … bn n+1个控制点,

升阶后的点为c0, c1, … cn, cn+1 n+2个控制点

c0=b0, cn+1=bn

中间控制点

c i = i n + 1 b i − 1 + ( 1 + i n + 1 ) b i , i ∈ [ 1 , n ] c_i = \frac {i}{n+1}b_{i-1} + (1+\frac{i}{n+1})b_i, i \in[1,n] ci=n+1ibi1+(1+n+1i)bi,i[1,n]


List2f degreeElevation(const std::vector<Eigen::Vector2f> &A)
{
    int n=A.size(); // 为公式中的n+1
    List2f res (n+1);
    res.front() = A[0];
    res.back() = A.back();

    for(int i=1;i<n;++i) {
        float ratio = 1.0*i/n;
        res[i] = ratio *A[i-1] + (1-ratio)*A[i];
    }

    return res;
}

实现

代码:
https://gitcode.com/chenbb1989/geometric_model/tree/master/gohw4-3

演示视频

besier 打断与升阶

打断
在这里插入图片描述

升阶

在这里插入图片描述


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值