n 阶贝塞尔曲线计算公式——Ts实现
文章目录
- 1、什么是贝塞尔曲线
- 2、常见贝塞尔曲线
- 3、贝塞尔曲线通用公式
- 3.1、贝塞尔曲线通用公式
- 3.2、思路解析
- 3.3、实现方法
- 3.4、效果展示
- 3.5、Demo下载
- 4、结束语
1、什么是贝塞尔曲线
Bézier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。 曲线定义:起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。 1962年,法国数学家Pierre Bézier第一个研究了这种矢量绘制曲线的方法,并给出了详细的计算公式,因此按照这样的公式绘制出来的曲线就用他的姓氏来命名,称为贝塞尔曲线。
看了这段话,相信你还是不大明白贝塞尔曲线到底是怎么样的,这里放上贝塞尔曲线扫盲贴,有需要的自行阅读!这里有个贝塞尔游戏,有兴趣的可以体验一下!
2、常见贝塞尔曲线
这里我们放上去常见的贝塞尔曲线效果演示图:
以下公式中:
B(t)为t时间下 点的坐标
P0为起点,Pn为终点,Pi为控制点
- 一阶贝塞尔曲线(线段):
一阶贝塞尔曲线通用公式:
B(t)=(1−t)P0+tP1,t∈[0,1]\begin{aligned} B(t)=(1-t)P_0+tP_1, t∈[0,1] \end{aligned} B(t)=(1−t)P0+tP1,t∈[0,1]
意义:由 P0 至 P1 的连续点, 描述的一条线段
- 二阶贝塞尔曲线(抛物线):
二阶贝塞尔曲线通用公式:
B(t)=(1−t)2P0+2t(1−t)P1+t2P2,t∈[0,1]\begin{aligned} B(t)=(1-t)^2P_0+2t(1-t)P_1+t^2P_2, t∈[0,1] \end{aligned} B(t)=(1−t)2P0+2t(1−t)P1+t2P2,t∈[0,1]
原理:
由 P0 至 P1 的连续点 Q0,描述一条线段。
由 P1 至 P2 的连续点 Q1,描述一条线段。
由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。
经验:P1-P0为曲线在P0处的切线
- 三阶贝塞尔曲线:
三阶贝塞尔曲线通用公式:
B(t)=(1−t)3P0+3t(1−t)2P1+3t2(1−t)P2+t3P3,t∈[0,1]\begin{aligned} B(t)=(1-t)^3P_0+3t(1-t)^2P_1+3t^2(1-t)P_2+t^3P_3, t∈[0,1] \end{aligned} B(t)=(1−t)3P0+3t(1−t)2P1+3t2(1−t)P2+t3P3,t∈[0,1]
- 四阶贝塞尔曲线:
- 五阶贝塞尔曲线:
3、贝塞尔曲线通用公式
3.1、贝塞尔曲线通用公式
我们查阅资料给出的一般公式是这样的:
B(t)=∑i=0n(ni)Pi(1−t)n−iti=(n0)P0(1−t)nt0+(n1)P1(1−t)n−1t1+...+(nn−1)Pn−1(1−t)1tn−1+(nn)Pn(1−t)0tn,t∈[0,1]\begin{aligned} B(t)=\sum_{i=0}^n \begin{pmatrix} n\\i \end{pmatrix} P_i(1-t)^{n-i}t^i= \begin{pmatrix} n\\0 \end{pmatrix} P_0(1-t)^nt^0+ \begin{pmatrix} n\\1 \end{pmatrix} P_1(1-t)^{n-1}t^1+...+ \begin{pmatrix} n\\n-1 \end{pmatrix} P_{n-1}(1-t)^1t^{n-1}+ \begin{pmatrix} n\\n \end{pmatrix} P_n(1-t)^0t^n, t\in[0,1] \end{aligned} B(t)=i=0∑n(ni)Pi(1−t)n−iti=(n0)P0(1−t)nt0+(n1)P1(1−t)n−1t1+...+(nn−1)Pn−1(1−t)1tn−1+(nn)Pn(1−t)0tn,t∈[0,1]
3.2、思路解析
观察上面公式,可以查看出,其公式是由一个格式固定的表达式之和来表示,这个表达式就是关键:
(ni)Pi(1−t)n−iti,t∈[0,1]\begin{aligned} \begin{pmatrix} n\\i \end{pmatrix} P_i(1-t)^{n-i}t^i, t\in[0,1] \end{aligned} (ni)Pi(1−t)n−iti,t∈[0,1]
该表达式可分为四个部分看:
- 从 i 递增到 n 的常数部分
- PiP_iPi 坐标部分
- (1−t)n−i(1 - t)^{n - i}(1−t)n−i
- tit^iti
可以看出这四部分都与 i 的值相关,此外 t 值的计算方式为:i/(n+1)
如果直接从上面的公式上找规律比较抽象,那就从具体的例子中找规律吧。
设 Bt 为要计算的贝塞尔曲线上的坐标,N 为控制点个数,P0,P1,P2…Pn 为贝塞尔曲线控制点的坐标,当 N 值不同时有如下计算公式:
如 N 为 3 表示贝塞尔曲线的控制点有 3 个点,这时 n 为 2 ,这三个点分别用 P0,P1,P2 表示。
- N = 3 P=(1−t)2P0+2(1−t)tP1+t2P2P=(1-t)^2P_0 + 2(1-t)tP_1 + t^2P_2P=(1−t)2P0+2(1−t)tP1+t2P2
- N = 4 P=(1−t)3P0+3(1−t)2tP1+3(1−t)t2P2+t3P3P= (1-t)^3P_0 + 3(1-t)^2tP_1 + 3(1-t)t^2P_2 + t^3P_3P=(1−t)3P0+3(1−t)2tP1+3(1−t)t2P2+t3P3
- N = 5 P=(1−t)4P0+4(1−t)3tP1+6(1−t)2t2P2+4(1−t)t3P3+t4P4P = (1-t)^4P_0 + 4(1-t)^3tP_1 + 6(1-t)^2t^2P_2 + 4(1-t)t^3P_3 + t^4P_4P=(1−t)4P0+4(1−t)3tP1+6(1−t)2t2P2+4(1−t)t3P3+t4P4
将贝塞尔曲线一般参数公式中的表达式用如下方式表示,设有常数 a,b 和 c,则该表达式可统一表示为如下形式:
a(1−t)btcPn,t∈[0,1]a(1 - t)^bt^cP_n, t\in[0,1] a(1−t)btcPn,t∈[0,1]
分析当 N 分别为3,4,5 时对应 a,b,c 的值:
如 N = 3 时,公式有三个表达式,第一个表达式为 (1−t)2P0(1-t)^2P_0(1−t)2P0,其对应 a,b,c 值分别为:1,2,0
- N = 3: 1,2,0 2,1,1 1,0,2
a: 1 2 1
b: 2 1 0
c: 0 1 2- N = 4: 1,3,0 3,2,1 3,1,2 1,0,3
a: 1 3 3 1
b: 3 2 1 0
c: 0 1 2 3- N = 5: 1,4,0 4,3,1 6,2,2 4,1,3 1,0,4
a: 1 4 6 4 1
b: 4 3 2 1 0
c: 0 1 2 3 4
根据上面的分析就可以总结出 a,b,c 对应的取值规则:
- b: (N - 1) 递减到 0 (b 为 1-t 的幂)
- c: 0 递增到 (N - 1) (c 为 t 的幂)
- a: 在 N 分别为 1,2,3,4,5 时将其值用如下形式表示:
N=1:———1
N=2:——–1 1
N=3:——1 2 1
N=4:—–1 3 3 1
N=5:—1 4 6 4 1
a 值的改变规则为: 杨辉三角
3.3、实现方法
好了,到这里我们基本上已经知道思路了,下面我们使用Ts写一下:
这里使用的是:
Vscode
Cocos Creator
/*** * @param ctrlPosArr 贝塞尔曲线控制点坐标* @param precison 精度,需要计算的该条贝塞尔曲线上的点的数目* @param resArr 该条贝塞尔曲线上的点(二维坐标)*/getBezierPos(ctrlPosArr:Array<cc.Vec2>,precison:number):Array<cc.Vec2>{cc.log(ctrlPosArr)let resArr:Array<cc.Vec2> = new Array<cc.Vec2>();/**贝塞尔曲线控制点数目(阶数)*/let number:number = ctrlPosArr.length;if(number < 2){cc.log("控制点数不能小于 2");return resArr;}/**杨辉三角数据 */let yangHuiArr:Array<number> = this.getYangHuiTriangle(number);//计算坐标for (let i = 0; i < precison; i++) {let t:number = i/precison;let tmpX:number = 0;let tmpY:number = 0;for (let j = 0; j < number; j++) {tmpX += Math.pow(1 - t,number - j - 1) * ctrlPosArr[j].x * Math.pow(t,j) * yangHuiArr[j];tmpY += Math.pow(1 - t,number - j - 1) * ctrlPosArr[j].y * Math.pow(t,j) * yangHuiArr[j];}// resArr[i].x = tmpX;// resArr[i].y = tmpY;resArr[i] = new cc.Vec2(tmpX,tmpY);}return resArr;}/*** 获取杨辉三角对应阶数的值* @param num 杨辉三角阶数*/getYangHuiTriangle(num:number):Array<number>{//计算杨辉三角let yangHuiArr = new Array<number>();if(num === 1){yangHuiArr[0] = 1;}else{yangHuiArr[0] = yangHuiArr[1] = 1;for (let i = 3; i <= num; i++) {let t = new Array<number>();for (let j = 0; j < i - 1; j++) {t[j] = yangHuiArr[j];}yangHuiArr[0] = yangHuiArr[i - 1] = 1;for (let j = 0; j < i - 2; j++) {yangHuiArr[j + 1] = t[j] + t[j + 1]; }}}cc.log(yangHuiArr);return yangHuiArr;}
3.4、效果展示
下面我取几个点,做一下演示:
let p1:cc.Vec2 = cc.v2(0,0);let p2:cc.Vec2 = cc.v2(200,200);let p3:cc.Vec2 = cc.v2(400,150);let p4:cc.Vec2 = cc.v2(500,200);this.drawPoint(p1);this.drawPoint(p2);this.drawPoint(p3);this.drawPoint(p4);this.drawLine(p1,p2,cc.Color.GREEN);this.drawLine(p2,p3,cc.Color.GREEN);this.drawLine(p3,p4,cc.Color.GREEN);let posArr1:Array<cc.Vec2> = [cc.v2(-150,80),cc.v2(1,80),cc.v2(48,92),cc.v2(167,159),cc.v2(309,271),cc.v2(421,394),cc.v2(514,498),cc.v2(597,572),cc.v2(658,590),cc.v2(745,550),cc.v2(802,465),cc.v2(841,320),cc.v2(866,266),cc.v2(951,163),cc.v2(1054,133),cc.v2(1228,126),cc.v2(1278,128),cc.v2(1430,128)]
为了验证正确性,我这里先用ts自带的贝塞尔曲线公式,通过四个点来画出三阶贝塞尔曲线,再用自己的点来画一遍,然后用自己的代码来画n阶贝塞尔曲线。效果如下:
3.5、Demo下载
为了方便大家,当然如果有不明白的童鞋也可以在这里点此下载Demo示例!
4、结束语
The End
好了,今天的分享就到这里,如有不足之处,还望大家及时指正,随时欢迎探讨交流!!!
喜欢的朋友们,请收藏、点赞、评论!您的肯定是我写作的不竭动力!
n 阶贝塞尔曲线计算公式——Ts实现相关推荐
- java实现的三阶贝塞尔曲线_n 阶贝塞尔曲线计算公式实现
n 阶贝塞尔曲线计算公式实现 关于贝塞尔曲线是什么,可以用来做什么,这里就不再介绍,如果你还不了解,可以先去看看下面这篇文章:贝塞尔曲线扫盲 1. 效果参考 2. 思路解析 百度百科上给出的一般参数公 ...
- n 阶贝塞尔曲线计算公式实现
n 阶贝塞尔曲线计算公式实现 关于贝塞尔曲线是什么,可以用来做什么,这里就不再介绍,如果你还不了解,可以先去看看下面这篇文章:贝塞尔曲线扫盲 1. 效果参考 2. 思路解析 百度百科上给出的一般参数公 ...
- js-三阶贝塞尔曲线计算公式
/*** 三阶贝塞尔曲线* B(t) = P0 * (1-t)^3 + 3 * P1 * t * (1-t)^2 + 3 * P2 * t^2 * (1-t) + P3 * t^3, t ∈ [0,1 ...
- canvas贝塞尔曲线爱心_canvas实现高阶贝塞尔曲线(N阶贝塞尔曲线生成器)
写在最前 由于原生的Canvas最高只支持到三阶贝塞尔曲线,那么我想添加多个控制点怎么办呢?(即便大部分复杂曲线都可以用3阶贝塞尔来模拟)与此同时,关于贝塞尔控制点的位置我们很难非常直观的清楚到底将控 ...
- 【Android UI】贝塞尔曲线 ② ( 二阶贝塞尔曲线公式 | 三阶贝塞尔曲线及公式 | 高阶贝塞尔曲线 )
文章目录 一.二阶贝塞尔曲线公式 二.三阶贝塞尔曲线 三.高阶贝塞尔曲线 贝塞尔曲线参考 : https://github.com/venshine/BezierMaker 一.二阶贝塞尔曲线公式 二 ...
- canvas实现高阶贝塞尔曲线
写在最前 由于原生的Canvas最高只支持到三阶贝塞尔曲线,那么我想添加多个控制点怎么办呢?(即便大部分复杂曲线都可以用3阶贝塞尔来模拟)与此同时,关于贝塞尔控制点的位置我们很难非常直观的清楚到底将控 ...
- 3阶贝塞尔曲线沿线长等距分割方法
3阶贝塞尔曲线等距分割 1.引言 2.数学计算 3.应用 4.demo下载 1.引言 贝塞尔(bezier)曲线又称样条曲线,常用的有2阶跟3阶形式,3阶曲线最为常用,其公式(1)为: P0/P1/P ...
- 用C语言绘制任意阶贝塞尔曲线(Bézier curve)
计算机图形学中贝塞尔曲线的绘制.使用的开发软件及版本为VS2015,以及 EasyX库.实现动态演示贝塞尔曲线实现的过程,且阶次不限! 源代码获取方式:1.添加微信(微信号:my_12581)获取.2 ...
- 转载:贝塞尔曲线计算公式
原文地址: https://zhuanlan.zhihu.com/p/33193050 用到贝塞尔曲线公式来计算出顶点,从而生成贝塞尔曲线. /*** 生成四阶贝塞尔曲线定点数据* @param p0 ...
最新文章
- easyUI样式之easyui-switchbutton
- 引进研究生:​50万房补+年薪13万起;本科生30万房补​
- sleep( ) 和 wait( ) 的这 5 个区别,你知道几个
- 关于window.history.back()后退问题
- golang调用java的函数_大话golang性能分析(一):profile基本原理
- 当当年中庆典,力度超前,花120买300的硬核书
- 笨办法学 Python · 续 练习 19:改善性能
- linux分区压力测试,stress-Linux系统压力测试工具使用及系统负载很高的几种场景测试...
- win10,Net Share 共享,每次开机都会出现 --- 彻底关闭的方法---禁用server服务
- vue中使用axios发送请求(二)
- 计算机二级教程48讲视频,天津大学 《线性代数》视频教程48讲 真人手写精品
- 利用uDig 快速生成 GeoServer 可用的 SLD 渲染文件
- 你还为给自己的IT团队起名字,写口号烦恼吗?(较为流行的团队名称)
- 让华为小米抱团 统一推送联盟究竟是何方神圣?
- PowerDesigner导入现有表结构
- HashMap中的hash与rehash
- offsetParent和parentElement的区别
- Pygame从0实战10(泡泡小游戏添加音效)
- Koreographer音乐插件基本使用
- TMS320C6747的emifa访问异步外部存储