【Android UI】贝塞尔曲线 ⑥ ( 贝塞尔曲线递归算法原理 | 贝塞尔曲线递归算法实现 )

举报
韩曙亮 发表于 2022/08/03 00:58:19 2022/08/03
【摘要】 文章目录 一、贝塞尔曲线递归算法二、贝塞尔曲线递归算法实现 贝塞尔曲线参考 : https://github.com/venshine/BezierMaker 一、贝塞...


贝塞尔曲线参考 : https://github.com/venshine/BezierMaker





一、贝塞尔曲线递归算法



一阶贝塞尔曲线 ( 起止点 + 0 0 0 个控制点 = 2 2 2 个点 ) 是一条直线 , 贝塞尔曲线上的点就是直线上的点 ;

二阶贝塞尔曲线 ( 起止点 + 1 1 1 个控制点 = 3 3 3 个点 ) 由 2 2 2 条 一阶贝塞尔曲线 确定 ,

三阶贝塞尔曲线 ( 起止点 + 2 2 2 个控制点 = 4 4 4 个点 ) 由 2 2 2 条 二阶贝塞尔曲线 确定 ,

四阶贝塞尔曲线 ( 起止点 + 3 3 3 个控制点 = 5 5 5 个点 ) 由 2 2 2 条 三阶贝塞尔曲线 确定 ,

⋮ \vdots

n n n阶贝塞尔曲线 ( 起止点 + n − 1 n-1 n1 个控制点 = n + 1 n + 1 n+1 个点 ) 由 2 2 2 n − 1 n-1 n1 阶贝塞尔曲线 确定 ;


贝塞尔曲线递推公式如下 :

P i k = { P i , k = 0 ( 1 − t ) P i k − 1 + t P i + 1 k − 1 , k = 1 , 2 , ⋯   , n ; i = 0 , 1 , ⋯   , n − k P_i^k =

{Pi,k=0(1t)Pk1i+tPk1i+1,k=1,2,,n;i=0,1,,nk { P i , k = 0 ( 1 t ) P i k 1 + t P i + 1 k 1 , k = 1 , 2 , , n ; i = 0 , 1 , , n k
Pik={Pi,k=0(1t)Pik1+tPi+1k1,k=1,2,,n;i=0,1,,nk


上述公式中 k + 1 k + 1 k+1 是贝塞尔曲线的阶数 , i i i 表示顶点序号 ;


根据上述 贝塞尔曲线递推公式 , 可以得到一个递归算法 , 算法核心公式如下 :

p ( i , j ) = ( 1 − u ) × p ( i − 1 , j ) + u × p ( i − 1 , j − 1 ) p(i, j) = (1-u) \times p (i - 1, j) + u \times p (i - 1 , j - 1) p(i,j)=(1u)×p(i1,j)+u×p(i1,j1)

上述递推公式中 , i i i 表示贝塞尔曲线的阶数 , j j j 表示贝塞尔曲线中的点个数 ( 包含起止点 + 控制点 ) , u u u 表示比例取值范围 0 0 0 ~ 1 1 1 ;

递归算法的递归终点是取到第 0 0 0 阶 ;





二、贝塞尔曲线递归算法实现



递归算法中最终的一阶贝塞尔曲线上的点计算公式如下 :

p ( i , j ) = ( 1 − u ) × p ( i − 1 , j ) + u × p ( i − 1 , j − 1 ) p(i, j) = (1-u) \times p (i - 1, j) + u \times p (i - 1 , j - 1) p(i,j)=(1u)×p(i1,j)+u×p(i1,j1)

根据上述计算公式 , 得到如下代码 :

(1 - u) * mControlPoints.get(j).x + u * mControlPoints.get(j + 1).x

  
 
  • 1

完整的贝塞尔曲线上的点坐标算法如下 :

  • BezierX 方法用于计算 贝塞尔曲线上的 X 轴坐标点 ;
  • BezierY 方法用于计算 贝塞尔曲线上的 Y 轴坐标点 ;
    // 贝塞尔曲线控制点集合
    private ArrayList<PointF> mControlPoints = new ArrayList<>();

    /**
     * 贝塞尔曲线递归算法, 本方法计算 X 轴坐标值
     * @param i 贝塞尔曲线阶数
     * @param j 贝塞尔曲线控制点
     * @param u 比例 / 时间 , 取值范围 0.0 ~ 1.0
     * @return
     */
    private float BezierX(int i, int j, float u) {
        if (i == 1) {
            // 递归退出条件 : 贝塞尔曲线阶数 降为一阶
            // 一阶贝塞尔曲线点坐标 计算如下 :
            return (1 - u) * mControlPoints.get(j).x + u * mControlPoints.get(j + 1).x;
        }
        return (1 - u) * BezierX(i - 1, j, u) + u * BezierX(i - 1, j + 1, u);
    }

    /**
     * 贝塞尔曲线递归算法, 本方法计算 Y 轴坐标值
     * @param i 贝塞尔曲线阶数
     * @param j 贝塞尔曲线控制点
     * @param u 比例 / 时间 , 取值范围 0.0 ~ 1.0
     * @return
     */
    private float BezierY(int i, int j, float u) {
        if (i == 1) {
            // 递归退出条件 : 贝塞尔曲线阶数 降为一阶
            return (1 - u) * mControlPoints.get(j).y + u * mControlPoints.get(j + 1).y;
        }
        return (1 - u) * BezierY(i - 1, j, u) + u * BezierY(i - 1, j + 1, u);
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

文章来源: hanshuliang.blog.csdn.net,作者:韩曙亮,版权归原作者所有,如需转载,请联系作者。

原文链接:hanshuliang.blog.csdn.net/article/details/126107789

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。