爱的贝塞尔曲线讲解
来源:互联网 发布:abb仿真软件track 编辑:程序博客网 时间:2024/05/18 22:56
1.贝塞尔曲线介绍
贝塞尔曲线的数学基础是早在 1912 年就广为人知的伯恩斯坦多项式。但直到 1959 年,当时就职于雪铁龙的法国数学家 Paul de Casteljau 才开始对它进行图形化应用的尝试,并提出了一种数值稳定的 de Casteljau 算法。然而贝塞尔曲线的得名,却是由于 1962 年另一位就职于雷诺的法国工程师 Pierre Bézier 的广泛宣传。他使用这种只需要很少的控制点就能够生成复杂平滑曲线的方法,来辅助汽车车体的工业设计。正是因为控制简便却具有极强的描述能力,贝塞尔曲线在工业设计领域迅速得到了广泛的应用。不仅如此,在计算机图形学领域,尤其是矢量图形学,贝塞尔曲线也占有重要的地位。
您或许不知道在生活中已经用过贝塞尔曲线,我举个例子您就恍然大悟,Photoshop中的钢笔工具就是用了贝塞尔曲线的原理.在android中,我们利用贝塞尔曲线能做出很炫酷的效果,如下图:
是不是很好看,下一章我们就做这么一个效果来练习一下!
2.贝塞尔曲线原理
接下来我们介绍一下贝塞尔曲线的原理:
2.1 贝塞尔二阶曲线
1.在平面内任选 3 个不共线的点,依次用线段连接。如下图:
2.在第一条线段上任选一个点 D。计算该点到线段起点的距离 AD,与该线段总长 AB 的比例。如下图:
3.根据上一步得到的比例,从第二条线段上找出对应的点 E,使得 AD:AB = BE:BC。如下图:
4.连接这两点 DE。如下图:
5.从新的线段 DE 上再次找出相同比例的点 F,使得 DF:DE = AD:AB = BE:BC。如下图:
到这里,我们就确定了贝塞尔曲线上的一个点 F。接下来,请稍微回想一下中学所学的极限知识,让选取的点 D 在第一条线段上从起点 A 移动到终点 B,找出所有的贝塞尔曲线上的点 F。所有的点找出来之后,我们也得到了这条贝塞尔曲线。如下图:
6.如果你实在想象不出这个过程,没关系,看动画!
回过头来看这条贝塞尔曲线,为了确定曲线上的一个点,需要进行两轮取点的操作,因此我们称得到的贝塞尔曲线为二次曲线。计算公式如下:
2.2 贝塞尔三阶曲线
当控制点个数为 4 时,情况是怎样的?
步骤都是相同的,只不过我们每确定一个贝塞尔曲线上的点,要进行三轮取点操作。如图,AE:AB = BF:BC = CG:CD = EH:EF = FI:FG = HJ:HI,其中点 J 就是最终得到的贝塞尔曲线上的一个点。
这样我们得到的是一条三次贝塞尔曲线。如下图:
三阶贝塞尔曲线的公式如下:
2.3 贝塞尔一阶曲线
看过了二次和三次曲线,更高次的贝塞尔曲线大家应该也知道要怎么画了吧。那么比二次曲线更简单的一次(线性)贝塞尔曲线存在吗?长什么样?根据前面的介绍,只要稍作思考,想必你也能猜出来了。哈!就是一条直线~
2.4 更复杂的贝塞尔曲线
更复杂的贝塞尔曲线原理是一样的,来看看更复杂的贝塞尔曲线,如下图:
好了原理篇就讲到这里吧,大家可以点击进入这个网站去加深一下理解。
3.android贝塞尔曲线简单实现
我们android也支持贝塞尔曲线,只不过sdk最多只支持3阶的。要想支持更多阶得找第三方的了。在android中我们看一下有那些用贝塞尔曲线实现的效果:
1.QQ小红点拖拽效果2.一些炫酷的下拉刷新控件3.阅读软件的翻书效果4.一些平滑的折线图的制作5.其他很多炫酷的动画效果
下面我们讲解一下如何用android实现2阶和3阶贝塞尔曲线。
画贝塞尔曲线我们需要用到的类除了cavans和paint,最重要是是path类,利用path的二个方法:
quadTo()//画二阶贝塞尔曲线cubicTo()//画三阶贝塞尔曲线
3.1 画2阶贝塞尔曲线代码
Path path = new Path();path.moveTo(start.x,start.y);path.quadTo(control.x,control.y,end.x,end.y);
由上面我们知道2阶贝塞尔曲线需要有3个点:
start.x,start.y是起始点的(x,y)坐标control.x,control.y是中间控制点的(x,y)坐标end.x,end.y是结束点的(x,y)坐标#3.2 画3阶贝塞尔曲线代码:
3.2 画3阶贝塞尔曲线代码
Path path = new Path(); path.moveTo(start.x, start.y); path.cubicTo(control1.x, control1.y, control2.x,control2.y, end.x, end.y); canvas.drawPath(path, mPaint);
由上面我们知道3阶贝塞尔曲线需要有4个点,所以在cubicTo方法只需要2个控制点和一个结束点。
4.讲解一个案例
我们来做一个小小的例子练习一下,以2阶的贝塞尔曲线为例,效果图如下:
代码如下:
public class MyLayout extends View { private Point startPoint;//开始点 private Point endPoint;//结束点 private Point controlPoint;//随意变动的控制点 private Paint mPaint; public MyLayout(Context context, AttributeSet attrs) { super(context, attrs); initPaint(); } //初始化paint,没什么可说的。 private void initPaint(){ mPaint = new Paint(); mPaint.setStyle(Paint.Style.STROKE); } /** * onlayout中定死2个起始点。 */ @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); int padding = getWidth()/6; startPoint = new Point(padding,getHeight()/2); endPoint = new Point(getWidth() - padding , getHeight()/2); controlPoint = new Point(getWidth()/2,getHeight()/2); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawPoint(canvas);//画点 drawHelpLine( canvas);//画辅助线 drawBezierLine(canvas);//画贝塞尔曲线 } /** * 绘制贝塞尔曲线 */ private void drawBezierLine(Canvas canvas){ mPaint.setColor(Color.RED); mPaint.setStrokeWidth(8); Path path = new Path(); path.moveTo(startPoint.x, startPoint.y); path.quadTo(controlPoint.x, controlPoint.y, endPoint.x, endPoint.y); canvas.drawPath(path, mPaint); } /** * 绘制辅助线 */ private void drawHelpLine(Canvas canvas){ mPaint.setColor(Color.LTGRAY); mPaint.setStrokeWidth(4); canvas.drawLine(startPoint.x,startPoint.y,controlPoint.x,controlPoint.y,mPaint); canvas.drawLine(endPoint.x,endPoint.y,controlPoint.x,controlPoint.y,mPaint); } /** * 画起始点和控制点 */ private void drawPoint(Canvas canvas){ // 绘制数据点和控制点 mPaint.setColor(Color.GRAY); mPaint.setStrokeWidth(20); canvas.drawPoint(startPoint.x,startPoint.y,mPaint); canvas.drawPoint(endPoint.x,endPoint.y,mPaint); canvas.drawPoint(controlPoint.x,controlPoint.y,mPaint); } @Override public boolean onTouchEvent(MotionEvent event) { // 根据触摸位置更新控制点,并提示重绘 controlPoint.x = (int) event.getX(); controlPoint.y = (int) event.getY(); invalidate(); return true; }}
这个代码挺简单的,我就不做详细介绍了,大家再想一下,把上面的2阶变成3阶怎么办,其实也很简单,再加一个控制点就行,代码如下:
// 绘制贝塞尔曲线 mPaint.setColor(Color.RED); mPaint.setStrokeWidth(8); Path path = new Path(); path.moveTo(start.x, start.y); path.cubicTo(control1.x, control1.y, control2.x,control2.y, end.x, end.y); canvas.drawPath(path, mPaint);
效果图如下:
5 补充Path类的API
这里对path类中的方法补充一下。
6.结尾
好了就讲到这里吧,下一章我们做一个文章开头的效果。
在技术上我依旧是个小渣渣,加油,勉励自己!
7.参考文档
【1】Android 贝塞尔曲线的浅析,android贝塞尔浅析
【2】玩玩这个网站加深对贝塞尔曲线的理解
【3】贝塞尔曲线扫盲
【4】安卓自定义View进阶 - 贝塞尔曲线
- 爱的贝塞尔曲线讲解
- 贝塞尔曲线知识讲解
- 贝塞尔曲线实例讲解
- 爱的贝塞尔曲线之属性动画之美
- 自定义View进阶(一)——爱的贝塞尔曲线
- 浅谈属性动画简单使用之实现爱的贝塞尔曲线浪漫告白效果(三)
- android画图之贝塞尔曲线讲解
- 大白话讲解ROC曲线
- twisted讲解(官方学习曲线最陡峭的部分)
- 贝塞尔曲线的应用
- 高效的贝塞尔曲线
- 贝塞尔曲线的应用
- 贝塞尔曲线的实现
- 贝塞尔曲线的应用
- 贝塞尔曲线的使用
- 曲线平滑-贝塞尔曲线
- 贝塞尔曲线的数学原理
- 贝塞尔曲线的数学原理
- virtio and vhost
- 中企动力大把推荣膺“中国IT市场年度创新产品”奖
- js中几种实用的跨域方法原理详解
- zookeeper命令行(zkCli.sh&zkServer.sh)使用及四字命令
- 视图
- 爱的贝塞尔曲线讲解
- shell
- Unity实现在3D模型上涂鸦
- 快捷安装Redis数据库和Redis Desktop Manage可视化界面工具
- SqlYog注册码
- NLP笔记(一)
- 墓碑上的字符
- kubernetes1.5新特性:新版本kubeadm
- MySQL/ 索引