android贝塞尔曲线实例,android中贝塞尔曲线的应⽤⽰例前⾔:
贝塞尔曲线⼜称贝兹曲线,它的主要意义在于⽆论是直线或曲线都能在数学上予以描述。最初由保罗·德卡斯特⾥奥(Paul de Casteljau)于1959年运⽤德卡斯特⾥奥演算法开发(de Casteljau Algorithm),在1962,由法国⼯程师⽪埃尔·贝塞尔(Pierre Bézier)所⼴泛发表。⽬前⼴泛应⽤于图形绘制领域来模拟光滑曲线,为计算机⽮量图形学奠定了基础。在⼀些图形处理软件中都能见到贝塞尔曲线,⽐如CorelDraw中翻译成“贝赛尔⼯具”;⽽在Fireworks中叫“画笔”;Photoshop中叫“钢笔⼯具”。下图为Photoshop中⽤钢笔绘制的贝塞尔曲线,共绘制了三条贝塞尔曲线:
数学表达
术语:数据点、控制线、控制点、德卡斯特⾥奥算法、⼀阶,⼆阶,三阶,n阶……
数据点:⼀条贝塞尔曲线的起始点和终结点都叫数据点。
控制线:在图中可以看到那条中⼼点为数据点的线段,每个数据点对应⼀条控制线
控制点:就是控制线的端点,通过控制线随着控制点的变化⽽变化;数据点和控制点决定⼀条贝塞尔曲线。
⼀阶贝塞尔曲线:其实是⼀条直线段,没有控制点。
⼀阶贝塞尔曲线⽰意图
⼀阶贝塞尔曲线公式
⼆阶贝塞尔曲线:图中第⼆段为⼆阶贝塞尔曲线,只有⼀个控制点,即只有⼀个控制点和两个数据点来决定曲线形状。
⼆阶贝塞尔曲线公式
⼆阶公式推导:
⼆阶贝塞尔曲线t=0.6⽰意图.gif
根据控制点和数据点,对贝塞尔曲线进⾏约束,满⾜的条件为
问题变为:已知P0(x0,y0), P1(x1,y1), P2(x2,y2),根据上式求P点坐标?
先求出A、B点坐标,其坐标
PA=P0+(P1-P0)·t
PB=P1+(P2-P1)·t
之后求P点坐标,其坐标
P=PA+(PB-PA)·t
P=(1-t)2P0+2t(1-t)P1+t2P2, t∈[0,1]
三阶贝塞尔曲线:图中第三段为三阶贝塞尔曲线,有两个控制点和两个数据点决定的曲线,同样满⾜等⽐条件:
三阶贝塞尔曲线
三阶贝塞尔曲线公式
德卡斯特⾥奥算法的思想:给定数据点和控制点P0、P1…Pn,⾸先将数据点和控制点连接形成⼀条折线,计算出每条折线上⾯的⼀点,使得初始数据点(初始控制点)到该点的距离与初始数据点(初始控制点)到终⽌数据点(终⽌控制点)的距离之⽐为t:1。将这些点连接起来形成新的折线(折线少了⼀段),⽤递归的算法继续计算,指导只有两个点,在这两个点形成的线段上去⼀点,满⾜以上的⽐例关系。随着t的从0到1的变化,该点的集合形成了贝塞尔曲线。
n阶贝塞尔曲线公式如下。
Android中的应⽤
对android中如何获取贝塞尔曲线上的点,如何绘制贝塞尔曲线,以及结合贝塞尔曲线的知识做出的效果进⾏分析。
1. 获取贝塞尔曲线上点的坐标
在android中并没有直接获取的⽅法,因此需要利⽤上⾯的公式进⾏计算,以⼆阶贝塞尔曲线为例,获取51个点,主要是t从0开始到1间取51项的等差数列:
public class MainActivity extends AppCompatActivity {
private static final float mPointNum = 50f;
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
init();
}
private void init() {
PointF mStartPoint = new PointF(0, 0);
PointF mEndPoint = new PointF(0, 1200);
PointF mControlPoint = new PointF(500, 600);
List mPointList = new ArrayList<>();
for (int i = 0; i <= mPointNum; i++) {
mPointList.add(getBezierPoint(mStartPoint, mEndPoint, mControlPoint, i / mPointNum));
Log.d("Bezier", "X:" + (i).x + " Y:" + (i).y);
}
}
private PointF getBezierPoint(PointF start, PointF end, PointF control, float t) {
PointF bezierPoint = new PointF();
bezierPoint.x = (1 - t) * (1 - t) * start.x + 2 * t * (1 - t) * control.x + t * t * end.x;
bezierPoint.y = (1 - t) * (1 - t) * start.y + 2 * t * (1 - t) * control.y + t * t * end.y;
return bezierPoint;
}
}
如果需要更⾼阶,可以使⽤递归函数来运算
//⽤递归获取贝塞尔曲线点的x轴坐标
private float getBezierPointX(int n, int position, float t) {
if (n == 1) {
return (1 - t) * (position).x + t * (position + 1).x;
}
return (1 - t) * getBezierPointX(n - 1, position, t) + t * getBezierPointX(n - 1, position + 1, t);
}
//⽤递归获取贝塞尔曲线点的x轴坐标
private float getBezierPointX(int n, int position, float t) {
if (n == 1) {
return (1 - t) * (position).x + t * (position + 1).x;
}
return (1 - t) * getBezierPointX(n - 1, position, t) + t * getBezierPointX(n - 1, position + 1, t);
}
private ArrayList buildBezierPoints() {
ArrayList points = new ArrayList<>();
int order = mPointList.size() - 1;
float delta = 1.0f / POINT_NUM;
for (float t = 0; t <= 1; t += delta) {
// Bezier点集
points.add(new PointF(getBezierPointX(order, 0, t), getBezierPointY(order, 0, t)));
}
return points;
}
2. 绘制贝塞尔曲线
Android 中的Path类可以直接绘制⼀阶到三阶的贝塞尔曲线,在onDraw(Canvas canvas) ⽅法中使⽤:
绘制⼀阶贝塞尔曲线:
canvas.drawLine(start.x,start.y,end.x,end.y);
绘制⼆阶贝塞尔曲线:
mPath.quadTo(controlPoint1.x, controlPoint1.y, endPoint.x, endPoint.y);
canvas.drawPath(mPath, mPaint);
绘制三阶贝塞尔曲线:
mPath.cubicTo(controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y); canvas.drawPath(mPath, mPaint);canvas动画
绘制n阶贝塞尔曲线
n阶贝塞尔曲线绘制,需要结合递归函数,设定⼀条曲线由多少个点组成,通过循环获取每个点的坐标进⾏绘制。
7阶贝塞尔曲线
8阶贝塞尔曲线
3.Demo
贝塞尔曲线在android中最常⽤的是做出⼀些动画特效,如QQ消息数拖拽形变效果,⼀些炫酷的下拉刷新控件,阅读软件的翻书效果,⼀些平滑的折线图的制作,某图⽚的运动轨迹等……
3.1 形状变形
只需要知道变形前和变形后图形的数据点和控制点即可,通过改变数据点和控制点使得形状发⽣改变。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论