浅谈贝塞尔曲线

article/2025/10/18 10:56:41

浅谈贝塞尔曲线

前段时间做了一个手写板功能的东西,其中手写部分用二次贝塞尔曲线完成,今天就来总结一下贝塞尔曲线在Android中的应用,先简单介绍各阶贝塞尔曲线的原理,然后实现通过贝塞尔曲线实现波浪线功能,感兴趣的同学继续看下去吧!

概念

在数学的数值分析领域中,贝塞尔曲线(英语:Bézier curve,亦作“贝塞尔”)是计算机图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝兹曲面,其中贝兹三角是一种特殊的实例。

贝塞尔曲线于1962年,由法国工程师皮埃尔·贝兹(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由保尔·德·卡斯特里奥于1959年运用德卡斯特里奥算法开发,以稳定数值的方法求出贝塞尔曲线。

贝塞尔曲线主要用于二维图形应用程序中的数学曲线,曲线由起始点,终止点(也称锚点)和控制点组成,通过调整控制点,通过一定方式绘制的贝塞尔曲线形状会发生变化。根据方程的最高阶数,又分为线性贝赛尔曲线,二阶贝塞尔曲线、三阶贝塞尔曲线和高阶贝塞尔曲线。

线性贝塞尔曲线

一阶贝塞尔曲线有两个点,一个是贝塞尔曲线的起点,一个是曲线的终点,主要就是画一条线段

线性贝塞尔曲线函数中的t会经过由P0至P1的B(t)所描述的曲线。例如当t=0.25时,B(t)即一条由点P0至P1路径的四分之一处。就像由0至1的连续t,B(t)描述一条由P0至P1的直线。

一阶

二阶贝塞尔曲线

二阶贝塞尔曲线有三个点,一个是贝塞尔曲线的起点,一个是曲线控制点,一个是曲线终点,主要就是用来画不是很复杂的曲线,例如上面说的手写板功能,使用的就是二阶贝塞尔曲线

为建构二次贝塞尔曲线,可以中介点Q0和Q1作为由0至1的t:

  • 由P0至P1的连续点Q0,描述一条线性贝塞尔曲线。
  • 由P1至P2的连续点Q1,描述一条线性贝塞尔曲线。
  • 由Q0至Q1的连续点B(t),描述一条二次贝塞尔曲线。

二阶

p0是起始点,p1是控制点,p2是终点

三阶贝塞尔曲线

P0、P1、P2、P3四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于P0走向P1,并从P2的方向来到P3。一般不会经过P1或P2;这两个点只是在那里提供方向资讯。P0和P1之间的间距,决定了曲线在转而趋进P2之前,走向P1方向的“长度有多长”。

对于三次曲线,可由线性贝塞尔曲线描述的中介点Q0、Q1、Q2,和由二次曲线描述的点R0、R1所建构:

在这里插入图片描述
三阶

高阶贝塞尔曲线

在这里插入图片描述

不管是几阶,原理都一样,感兴趣的可以自己证明一下这个原理,下面给出四阶的原理图
在这里插入图片描述
高阶

贝塞尔曲线在android中的应用

贝塞尔曲线在android中主要用于各种自定义view,主要是实现曲线更平滑,例如上面说的手写板,波浪线等等,在Android中用的最多的是二阶和三阶贝塞尔曲线,下面我们一起用二阶贝塞尔曲线写一个实例了解一下在Android中的用法,最后附上贝塞尔曲线实现水波纹效果

二阶贝塞尔曲线:

quadTo(x1,y1,x2,y2)
  • x1:控制点x坐标
  • y1:在控制点y坐标
  • x2:终点x坐标
  • y2:终点y坐标
rQuadTo(dx1,dy1,dx2,dy2)
  • dx1:控制点相对起点的x位移
  • dy1:控制点相对起点的y位移
  • dx2:终点相对起点的x位移
  • dy2:终点相对起点的y位移

在这里插入图片描述

public class SecondOrderBezierView extends View {Path mPath;Paint mPaint;Paint mLinePaint;float centerX, centerY;float mX, mY;float startX, startY;float endX, endY;public SecondOrderBezierView(Context context) {super(context);init();}public SecondOrderBezierView(Context context, AttributeSet attrs) {super(context, attrs);init();}void init() {mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setColor(Color.RED);mPaint.setStrokeWidth(10f);mPaint.setStyle(Paint.Style.STROKE);mLinePaint = new Paint();mLinePaint.setAntiAlias(true);mLinePaint.setColor(Color.GRAY);mLinePaint.setStrokeWidth(2f);mLinePaint.setStyle(Paint.Style.STROKE);mPath = new Path();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);centerX = w/2;centerY = h/2;startX = centerX-250;startY = centerY;endX = centerX + 250;endY = centerY;mX = centerX;mY = centerY - 500;}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE:mX = event.getX();mY = event.getY();break;}invalidate();return true;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPath.reset();mPath.moveTo(startX, startY);mPath.quadTo(mX, mY, endX, endY);canvas.drawPath(mPath, mPaint);canvas.drawLine(startX, startY, mX, mY, mLinePaint);canvas.drawLine(mX, mY, endX, endY, mLinePaint);}
}

三阶贝塞尔曲线

cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
  • x1, y1控制点1的坐标
  • x2, y2控制点2的坐标
  • x2, y2终点的坐标
rCubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
  • x1, y1控制点1相对于起点的位置
  • x2, y2控制点2相对于起点的位置
  • x2, y2终点相对于起点的位置

实例省略,跟二阶贝塞尔曲线差不多,多了一个控制点

学习了贝塞尔曲线,下面来实际操作一下

一起实现波浪效果,首先先画出基本的波浪形状,起点,控制点,终点确定之后先画出一段的波浪线,再修改起点,终点,控制点画第二段波浪线

mPath.moveTo(startX, startY);
mPath.quadTo(mX, mY, centerX, centerY);
mPath.quadTo(centerX * 3 / 2, centerY + 300, endX, endY);

然后通过修改Paint的Style为FILL_AND_STROKE,通过path的lineto把下面部分填充

mPaint.setStyle(Paint.Style.FILL_AND_STROKE);mPath.lineTo(2 * centerX, 2 * centerY);
mPath.lineTo(0, 2 * centerY);

在这里插入图片描述

最后通过动画让波浪动起来, 说明由于使用的平移动画,所以需要在屏幕外多画一个完整的波浪线

demo仅供参考,当然也可以通过其他方式实现

public class WaveView extends View {Paint mPaint;Path mPath;float mX, mY, centerX, centerY, startX, startY, endX, endY;int waveCount, waveLength, mOffsetX;ValueAnimator mValueAnimator;public WaveView(Context context) {super(context);init();}public WaveView(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init() {mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setStyle(Paint.Style.STROKE);mPaint.setStyle(Paint.Style.FILL_AND_STROKE);mPaint.setStrokeWidth(10f);mPaint.setColor(Color.RED);mPath = new Path();waveLength = 800;startWave();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);waveLength = w;centerX = w / 2;centerY = h / 2;startX = 0;startY = centerY;endX = w;endY = centerY;mX = centerX / 2;mY = centerY - 300;waveCount = (int) Math.round(w / waveLength + 1.5);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);mPath.reset();mPath.moveTo(-waveLength + mOffsetX, centerY);for (int i = 0; i < waveCount; i++) {mPath.rQuadTo(waveLength / 4, -100, waveLength / 2, 0);mPath.rQuadTo(waveLength / 4, +100, waveLength / 2, 0);}mPath.lineTo(2 * centerX, 2 * centerY);mPath.lineTo(0, 2 * centerY);mPath.close();canvas.drawPath(mPath, mPaint);}void startWave() {mValueAnimator = ValueAnimator.ofInt(0, waveLength);mValueAnimator.setDuration(1000);mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);mValueAnimator.setInterpolator(new LinearInterpolator());mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {mOffsetX = (int) valueAnimator.getAnimatedValue();invalidate();}});mValueAnimator.start();}
}

参考文献

贝塞尔曲线

下面是我的公众号,不定时发送文章,欢迎关注

子墨公众号


http://chatgpt.dhexx.cn/article/8FVNXRQU.shtml

相关文章

View系列:贝塞尔曲线专栏:绘制二阶贝塞尔曲线(二)

1&#xff1a;Android贝塞尔曲线Api 作用相关Api备注移动起点moveTo移动下一次操作的起点位置连接直线lineTo添加上一个点到当前点的直线Path贝塞尔曲线qyadTo / cubicTo分别为绘制二次和三次贝塞尔曲线的方法闭合路径close从第一个点连接到最后一个点&#xff0c;形成一个闭合…

贝塞尔曲线原理

1 前言 贝塞尔曲线 (Bzier curve) 由法国数学家 Pierre Bzier 于 1962 年提出的一种矢量曲线&#xff0c;广泛应用于工程绘图、动画设计等领域。贝塞尔曲线是一种运动轨迹曲线&#xff0c;由 n 个点在 n 条线段上匀速运动&#xff08;不同线段上的速度可能不同&#xff09;&…

贝塞尔曲线简单介绍

什么是贝塞尔曲线&#xff1f; Bzier curve(贝塞尔曲线) 是应用于二维图形应用程序的数学曲线。 曲线定义&#xff1a;起始点、终止点&#xff08;也称锚点&#xff09;、控制点。通过调整控制点&#xff0c;贝塞尔曲线的形状会发生变化。 1962年&#xff0c;法国数学家Pierre…

贝塞尔曲线原理简述

1. 曲线算法简介&#xff1a; 贝塞尔曲线应用于二维图形应用程序的数学曲线&#xff0c;由一组控制点的向量来确定&#xff0c;给定的控制点按顺序连接构成控制多边形&#xff0c;贝塞尔曲线逼近这个多边形&#xff0c;进而通过调整控制点坐标改变曲线的形状。 2. 绘制曲线 …

贝塞尔曲线动画C++简单实践

目录 贝塞尔曲线简介一阶贝塞尔二阶贝塞尔三阶贝塞尔N阶贝塞尔曲线 贝塞尔曲线在动画中的应用实践求曲线散点坐标将曲线应用到动画动画框架cmd动画窗口动画 完整代码示例代码核心类代码BezierCurveAnimatorConsole 参考资料 贝塞尔曲线简介 由于用计算机画图大部分时间是操作鼠…

贝塞尔曲线及实践案例

文章目录 1. 前言2. 介绍2.1 一阶贝济埃曲线2.2 二阶贝塞尔曲线2.3 三阶贝塞尔曲线 3. 一、二、三阶贝塞尔曲线实现4. 案例5. 后记 1. 前言 贝塞尔曲线(Bzier curve)&#xff0c;又称贝兹曲线或贝济埃曲线&#xff0c;是应用于二维图形应用程序的数学曲线。一般的矢量图形软件…

贝塞尔曲线工具类

贝塞尔曲线工具类 先上一张效果图看效果 贝塞尔曲线 用于计算N阶贝塞尔曲线上的点&#xff0c;根据传入控制点的个数判定阶数N 贝塞尔曲线计算公式: 工具类源码 public class BezierUtils {/*** 获取二项式系数** param l 行(杨辉三角)* param c 列(杨辉三角)* return 系…

贝塞尔曲线打断生成两个贝塞尔曲线

问题&#xff1a;如何将一个三阶贝塞尔曲线打断生成两个三阶贝塞尔曲线&#xff0c;生成的两条贝塞尔曲线与原来的贝塞尔曲线重合&#xff1f; 输入&#xff1a;一条贝塞尔曲线的四个控制点P1,C1,C2,P2,和一个打断点E(E在曲线上) 输出&#xff1a;两条贝塞尔曲线: P1,F,I,E E,J…

html5贝塞尔曲线,Canvas学习:贝塞尔曲线

在绘制圆和圆弧一节中,了解到在Canvas中可以使用arc()和arcTo()绘制制圆或弧线,但很多时候,仅这两个方法还不能满足我们实际的需求,特别是绘制复杂的曲线。不过值得庆幸的是,在Canvas中还提供了其他的方法可以帮助我们绘制复杂的曲线。那就是我们今天要说的贝塞尔曲线,在…

贝塞尔曲线(Bezier Curve)

有兴趣的建议看这篇&#xff0c;比较新&#xff1a;https://zhuanlan.zhihu.com/p/366678047 曲线和曲面 在生活中存在着各种各样光滑的曲线或曲面&#xff0c;例如汽车的表面&#xff0c;钢珠球等。 在建模的时候&#xff0c;我们通常使用很多的小三角形来逼近这样的曲面&am…

java贝塞尔曲线_贝塞尔曲线学习

贝塞尔曲线学习 1.贝塞尔曲线 以下公式中: B(t)为t时间下 点的坐标; P0为起点,Pn为终点,Pi为控制点 一阶贝塞尔曲线(线段): 一阶贝塞尔曲线公式 一阶贝塞尔曲线演示 意义:由 P0 至 P1 的连续点, 描述的一条线段 二阶贝塞尔曲线(抛物线): 二阶贝塞尔曲线公式 二阶贝塞尔曲…

贝塞尔曲线

一&#xff1a;简介 1962年&#xff0c;法国工程师贝塞尔发表&#xff0c;他运用贝塞尔曲线来为汽车的主体进行设计。 贝塞尔曲线是最基本的曲线&#xff0c;一般用在计算机 图形学和 图像处理。贝塞尔曲线可以用来创建平滑的曲线的道路、 弯曲的路径就像 祖玛游戏、 弯曲型的…

【Unity3d游戏开发】游戏中的贝塞尔曲线以及其在Unity中的实现

RT&#xff0c;马三最近在参与一款足球游戏的开发&#xff0c;其中涉及到足球的各种运动轨迹和路径&#xff0c;比如射门的轨迹&#xff0c;高吊球&#xff0c;香蕉球的轨迹。最早的版本中马三是使用物理引擎加力的方式实现的足球各种运动&#xff0c;后来的版本中使用了根据物…

Bezier Curve贝塞尔曲线概念

一、贝塞尔曲线的概念 对于两点之间的连线&#xff0c;我们可以用直线进行连接效果如下&#xff1a; 其中的每一个F点都在AB连接的线段上。 这就是一阶贝塞尔曲线。 如果我们加入一个控制点C&#xff0c;那么做图如下&#xff1a; 1、连接AC,BC&#xff1b; 2、在AC,B…

贝塞尔(贝兹尔)曲线介绍

2019独角兽企业重金招聘Python工程师标准>>> 贝塞尔(贝兹尔)曲线介绍 什么是贝塞尔曲线&#xff1f; “贝赛尔曲线”是由法国数学家Pierre Bzier所发明&#xff0c;由此为计算机矢量图形学奠定了基础。它的主要意义在于无论是直线或曲线都能在数学上予以描述。贝塞尔…

【ARM】-栈帧

ARM 栈帧 本系列均以 corter-A7(armv7-a) 为例 在 ARM 中&#xff0c;通常为满减栈&#xff08;Full Descending FD&#xff09;, 也就是说&#xff0c;堆栈指针指向堆栈内存中最后一个填充的位置&#xff0c;并且随着每个新数据项被压入堆栈而递减。 栈的本质 要理解栈的本…

JVM 栈和栈帧

tag: jvm,stack,stack frame,栈,栈帧 原文&#xff1a;JVM Stacks and Stack Frames 翻译&#xff1a;陈同学 欢迎访问陈同学博客原文&#xff0c;文章可读性更佳 前情提要 对于没有深度递归的函数来说&#xff0c;无需担心上篇文章中的算法。当知道正在处理数据集有限时&am…

C语言的函数栈帧

⭐️前面的话⭐️ &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4cc;本文由未见花闻原创&#xff0c;CSDN首发&#xff01; ✉️坚持和努力一定能换来诗与远方&#xff01; &…

【C语言】函数栈帧的创建和销毁(1)

前言&#xff1a; ❓ 在我们前期学习C语言时&#xff0c;你是否曾产生过很多困惑&#xff1f; &#x1f4ad; 比如&#xff1a;局部变量是怎么创建出来的&#xff1f;因为局部变量的值是随机值&#xff0c;我们建议将它初始化&#xff0c;那么为什么局部变量的值是随机值&am…

函数栈帧(详解版)

文章目录 前言1.浅谈C语言内存1.1 内存分配1.2 栈1.3 寄存器 2. 为main()函数开辟栈帧3.变量的初始化及函数调用4.ADD函数4.1 ADD函数的创建4.2 ADD函数使用与销毁 5.总结 前言 前期学习的时候&#xff0c;我们可能有很多困感? 比如: ●局部变量是怎么创建的?I为什么局部变量…