IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android N阶贝塞尔曲线构造工具 -> 正文阅读

[移动开发]Android N阶贝塞尔曲线构造工具

原理查看:https://juejin.cn/post/6844903760007790600
根据传入的Beizer曲线控制点来生成对应曲线上的点(n阶)

object Bezier {
    const val X_TYPE = 1L
    const val Y_TYPE = 2L

    fun buildBezierPonit(
        controlPointList: List<PointF>,
        frame: Int
    ): MutableList<PointF> {
        val pointList: MutableList<PointF> = ArrayList()
        // 此处注意,要用1f,否则得出结果为0
        val delta = 1f / frame

        // 阶数,阶数=绘制点数-1
        val order = controlPointList.size - 1

        // 循环递增
        var u = 0f
        while (u <= 1) {
            pointList.add(
                PointF(
                    calculatePointCoordinate(X_TYPE, u, order, 0, controlPointList),
                    calculatePointCoordinate(Y_TYPE, u, order, 0, controlPointList)
                )
            )
            u += delta
        }
        return pointList
    }

    fun calculatePointCoordinate(
        @IntRange(from = X_TYPE, to = Y_TYPE)
        type: Long,
        u: Float,
        k: Int,
        p: Int,
        controlPointList: List<PointF>
    ): Float {
        /**
         * 公式解说:(p表示坐标点,后面的数字只是区分)
         * 场景:有一条线p1到p2,p0在中间,求p0的坐标
         *      p1?--------○----------------?p2
         *            u    p0
         *
         * 公式:p0 = p1+u*(p2-p1) 整理得出 p0 = (1-u)*p1+u*p2
         */

        // 一阶贝塞尔,直接返回
        /**
         * 公式解说:(p表示坐标点,后面的数字只是区分)
         * 场景:有一条线p1到p2,p0在中间,求p0的坐标
         * p1?--------○----------------?p2
         * u    p0
         *
         * 公式:p0 = p1+u*(p2-p1) 整理得出 p0 = (1-u)*p1+u*p2
         */

        // 一阶贝塞尔,直接返回
        return if (k == 1) {
            val p1: Float
            val p2: Float

            // 根据是 x轴 还是 y轴 进行赋值
            if (type == X_TYPE) {
                p1 = controlPointList[p].x
                p2 = controlPointList[p + 1].x
            } else {
                p1 = controlPointList[p].y
                p2 = controlPointList[p + 1].y
            }
            (1 - u) * p1 + u * p2
        } else {
            /**
             * 这里应用了递归的思想:
             * 1阶贝塞尔曲线的端点 依赖于 2阶贝塞尔曲线
             * 2阶贝塞尔曲线的端点 依赖于 3阶贝塞尔曲线
             * ....
             * n-1阶贝塞尔曲线的端点 依赖于 n阶贝塞尔曲线
             *
             * 1阶贝塞尔曲线 则为 真正的贝塞尔曲线存在的点
             */
            ((1 - u) * calculatePointCoordinate(type, u, k - 1, p, controlPointList)
                    + u * calculatePointCoordinate(type, u, k - 1, p + 1, controlPointList))
        }
    }
}

使用方式(示例中为6Bezier曲线):

class BezierView @JvmOverloads constructor(
    context: Context,
    attributeSet: AttributeSet? = null
) : View(context, attributeSet) {
    private val bezierPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private val bezierPath = Path()
    private val bezierControlPointList = arrayListOf<PointF>(
        PointF(0f, 0f),
        PointF(300f, 0f),
        PointF(400f, 400f),
        PointF(600f, 0f),
        PointF(700f, 0f),
        PointF(1000f, 345f),
        PointF(435f, 500f),
    )

    init {
        bezierPaint.apply {
            style = Paint.Style.STROKE
            strokeWidth = 4f
            color = Color.RED
        }
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        Bezier.buildBezierPonit(bezierControlPointList, 1000).forEach {
            Log.d(BezierView::class.java.simpleName, "onDraw: $it")
            if (bezierControlPointList.indexOf(it) == 0) {
                bezierPath.moveTo(it.x, it.y)
            } else {
                bezierPath.lineTo(it.x, it.y)
            }
        }
        canvas.drawPath(bezierPath, bezierPaint)
    }
}

效果图:
在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 12:22:54  更:2022-04-04 12:23:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 20:45:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码