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



    贝塞尔曲线参考 : 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

    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
  • 相关阅读:
    【OpenCV】【计算机图形学】DIBR: Depth Image Based Rendering/ 3D image warping 中的实现细节
    分析每一段的代码的代码及代码运行的结果
    C++ | 无root权限在centOS7.9上安装新版本gcc编译器
    win系统环境搭建(九)——Windows安装chatGPT
    某火车订票系统数据库中
    Opencv源码解析(2)算法
    PL/SQL编程
    chatgpt相关问题解答
    idea连接Redis教程
    972信息检索 | 第二章 信息检索的方法和技术
  • 原文地址:https://blog.csdn.net/han1202012/article/details/126107789