文章目录

  • 一、使用 德卡斯特里奥算法 公式计算的 方法绘制三阶贝塞尔曲线
  • 二、代码示例

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

一、使用 德卡斯特里奥算法 公式计算的 方法绘制三阶贝塞尔曲线


在之前的博客 【Android UI】贝塞尔曲线 ④ ( 使用 android.graphics.Path 提供的 cubicTo 方法绘制三阶贝塞尔曲线示例 ) 中 , 使用了 Android 官方提供的 API 绘制了贝塞尔曲线 ;

在本篇博客中 , 使用纯算法的方式 , 实现 三阶贝塞尔曲线 ;

使用的算法就是 根据 德卡斯特里奥算法 推导出的 递推公式 写出的算法 ;

递推公式如下 :

Pik={Pi,k=0(1−t)Pik−1+tPi+1k−1,k=1,2,⋯,n;i=0,1,⋯,n−kP_i^k = \begin{cases} P_i , k = 0\\ (1-t)P_i^{k-1} + tP_{i + 1}^{k-1} , k = 1,2,\cdots,n ; i = 0,1,\cdots,n-k \end{cases}Pik​={Pi​,k=0(1−t)Pik−1​+tPi+1k−1​,k=1,2,⋯,n;i=0,1,⋯,n−k​

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

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)=(1−u)×p(i−1,j)+u×p(i−1,j−1)

参考 【Android UI】贝塞尔曲线 ⑤ ( 德卡斯特里奥算法 | 贝塞尔曲线递推公式 )

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

  • 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);}

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

为贝塞尔曲线控制点填充数据 : 三阶贝塞尔曲线 , 需要设置一个 起始点 , 一个终止点 , 和 两个控制点 ;

        // 起始点 + 控制点 + 终止点mControlPoints = new ArrayList<>();// 三阶贝塞尔曲线加入 起始点 + 2 个控制点 + 终止点mControlPoints.add(new PointF(0, getHeight() / 2F));            // 起始点mControlPoints.add(new PointF(getWidth() / 4F, getHeight()));      // 控制点 1mControlPoints.add(new PointF(getWidth() * 3F / 4F, 0));        // 控制点 2mControlPoints.add(new PointF(getWidth(), getHeight() / 2F));      // 终止点

二、代码示例


使用 德卡斯特里奥算法 公式计算的 方法绘制三阶贝塞尔曲线示例 :

package kim.hsl.paintgradient.bezier;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;import java.util.ArrayList;public class BesselCurve3 extends View {// 贝塞尔曲线绘制画笔private Paint mPaint;// 贝塞尔曲线private Path mPath;// 贝塞尔曲线控制点集合private ArrayList<PointF> mControlPoints = new ArrayList<>();public BesselCurve3(Context context) {this(context, null);}public BesselCurve3(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public BesselCurve3(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {super.onSizeChanged(width, height, oldWidth, oldHeight);// 初始化 曲线 和 画笔 实例对象\mPaint = new Paint();mPaint.setColor(Color.BLACK);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStrokeWidth(5);// 贝塞尔曲线mPath = new Path();// 起始点 + 控制点 + 终止点mControlPoints = new ArrayList<>();// 三阶贝塞尔曲线加入 起始点 + 2 个控制点 + 终止点mControlPoints.add(new PointF(0, getHeight() / 2F));            // 起始点mControlPoints.add(new PointF(getWidth() / 4F, getHeight()));      // 控制点 1mControlPoints.add(new PointF(getWidth() * 3F / 4F, 0));        // 控制点 2mControlPoints.add(new PointF(getWidth(), getHeight() / 2F));      // 终止点}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 使用 Path 实例对象存放贝塞尔曲线上的点集mPath.reset();// 用于存放贝塞尔曲线上点的集合ArrayList<PointF> points = new ArrayList<>();// 计算阶数 , 点的个数减去一 , 就是阶数 ;// 一阶贝塞尔曲线有 2 个点// 二阶贝塞尔曲线有 3 个点// n - 1 阶贝塞尔曲线有 n 个点int order = mControlPoints.size() - 1;// 贝塞尔曲线由 1000 个点组成 , 也就是 比例 u 每次增加 0.001// 贝塞尔曲线上的点的集合中收集 1000 个点float delta = 1.0f / 1000;// 每次累加 0.0001for (float u = 0; u <= 1; u += delta) {// Bezier点集PointF pointF = new PointF(BezierX(order, 0, u), BezierY(order, 0, u));points.add(pointF);if(points.size() == 1){mPath.moveTo(points.get(0).x,points.get(0).y);}else{mPath.lineTo(pointF.x,pointF.y);}}// 绘制贝塞尔曲线canvas.drawPath(mPath,mPaint);}/*** 贝塞尔曲线递归算法, 本方法计算 X 轴坐标值* @param i 贝塞尔曲线阶数 3* @param j 贝塞尔曲线控制点, 设置 0 即可, 3 阶曲线 依赖于 第 0 个二阶曲线和第 1 个二阶曲线* @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);}
}

三阶贝塞尔曲线绘制效果 :

【Android UI】贝塞尔曲线 ⑦ ( 使用 德卡斯特里奥算法 公式计算的 方法绘制三阶贝塞尔曲线示例 )相关推荐

  1. 德卡斯特里奥算法(De Casteljau’s Algorithm)绘制贝塞尔曲线

    原文:http://blog.csdn.net/Fioman/article/details/2578895 德卡斯特里奥算法可以计算贝塞尔曲线上的点C(u),u∈[0,1].因此,通过给定一组u的值 ...

  2. 德卡斯特里奥算法——找到Bezier曲线上的一个点

    http://www.cs.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/de-casteljau.html 随着Bezier曲线的构造,接下来最 ...

  3. 【Android UI】贝塞尔曲线 ⑤ ( 德卡斯特里奥算法 | 贝塞尔曲线递推公式 )

    文章目录 一.德卡斯特里奥算法 二.贝塞尔曲线递推公式 贝塞尔曲线参考 : https://github.com/venshine/BezierMaker 一.德卡斯特里奥算法 贝塞尔曲线的 三阶 / ...

  4. 贝塞尔曲线N阶实现-德卡斯特里奥算法(De Casteljau’s Algorithm)

    贝塞尔曲线很多客户端已经自行集成,安卓ios或是web,今天基于算法动手实现一次,今天只放源码,暂时不做说明了(还要加班,--~),源码在下面,直接看也能看懂 德卡斯特里奥算法的基础就是在向量AB上选 ...

  5. android高级UI之贝塞尔曲线<上>---基本概念、德卡斯特里奥算法

    在上一次android高级UI之Canvas综合案例操练 - cexo - 博客园对于Android UI绘制中核心的Canvas进行了相关的学习,这块的学习也中断一年多了,既然主业是Android开 ...

  6. 塞尔曲线德卡斯特里奥(de Casteljau)算法及程序

    贝塞尔曲线德卡斯特里奥(de Casteljau)算法及程序 设P0.P02.P2是一条抛物线上顺序三个不同的点.过P0和P2点的两切线交于P1点,在P02点的切线交P0P1和P2P1于P01和P11 ...

  7. 贝塞尔曲线德卡斯特里奥(de Casteljau)算法

    这篇文章比较好理解些~ 设P0.P02.P2是一条抛物线上顺序三个不同的点.过P0和P2点的两切线交于P1点,在P02点的切线交P0P1和P2P1于P01和P11,则如下比例成立: 这是所谓抛物线的三 ...

  8. 贝塞尔曲线是什么?如何用 Canvas 绘制三阶贝塞尔曲线?

    大家好,我是前端西瓜哥. 今天谈谈贝塞尔曲线是什么以及它的原理,并说说如何用 Canvas 技术绘制一条三阶贝塞尔曲线. 贝塞尔曲线是什么? 贝塞尔曲线,是通过几个简单的参数描述一条曲线的一种参数曲线 ...

  9. 【Android UI设计与开发】9:滑动菜单栏(一)开源项目SlidingMenu的使用和示例-转...

    一.SlidingMenu简介 相信大家对SlidingMenu都不陌生了,它是一种比较新的设置界面或配置界面的效果,在主界面左滑或者右滑出现设置界面效果,能方便的进行各种操作.很多优秀的应用都采用了 ...

最新文章

  1. 云计算架构设计6大原则,你遵循了吗?
  2. R语言使用ggpubr包的ggarrange函数组合多张结论图:使用ggpubr包将表格嵌套在可视化图像中
  3. python代码大全表解释-【初学】Python异常代码含义对照表
  4. python3.7.2安装-CentOS 7中Python3.7.2的安装
  5. 用linux搭建ntp服务,使用linux配置NTP Server
  6. “Survey of machine learning techniques for malware analysis ”
  7. 发送Gmail邀请.
  8. ROS与navigation教程——概述
  9. ajax实现下拉列表回显,layui实现下拉复选功能的例子(包括数据的回显与上传)
  10. LiteOS间歇计算技术:IOT终端真正感受“电量自由”
  11. 基于MDC的SOA方案
  12. html----学习笔记
  13. #数组元素相乘_C++ 矩阵相乘
  14. 容器技术Docker K8s 39 Serverless Kubernetes(ASK)详解-阿里云Serverless容器(ASK)适用场景与核心功能
  15. 360篡改html文件打开方式,Chrome浏览器被360导航篡改怎么办
  16. Cloudera Manager 环境搭建
  17. 【EXCEL】去除多余行列
  18. 全网首发国内联邦学习框架研究
  19. 生活中的定律——劣币驱逐良币
  20. html中splice向数组添加元素,js中splice()的强大(删除,插入或替换数组的元素)

热门文章

  1. 从Matlab的.fig图中导出数据
  2. 2019icpc上海站总结
  3. 开源监控软件Zabbix5部署实战
  4. MCU震荡电路晶振旁边两个22pf电容的作用
  5. PLS-00302: component 'SET_NO_OUTLINES' must be declared
  6. rhel6破解root密码
  7. java中默认是构造方法,只要类中显式地定义一个构造方法,那么Java默认的构造方法不再存在...
  8. 5G时代终将替换4G时代
  9. 华为手机摄影入门到精通pdf_华为P40 Pro+评测:100倍双目变焦再次改变手机摄影...
  10. Windows 10系统压缩C盘WSL虚拟磁盘文件