二次貝塞爾曲線
貝塞爾曲線簡介
貝塞爾曲線(Bézier curve)声登,又稱貝茲曲線或貝濟埃曲線,是應(yīng)用于二維圖形應(yīng)用程序的數(shù)學(xué)曲線。一般的矢量圖形軟件通過它來精確畫出曲線悯嗓,貝茲曲線由線段與節(jié)點組成件舵,節(jié)點是可拖動的支點,線段像可伸縮的皮筋绅作,我們在繪圖工具上看到的鋼筆工具就是來做這種矢量曲線的芦圾。貝塞爾曲線是計算機圖形學(xué)中相當(dāng)重要的參數(shù)曲線,在一些比較成熟的位圖軟件中也有貝塞爾曲線工具俄认,如PhotoShop等。在Flash4中還沒有完整的曲線工具洪乍,而在Flash5里面已經(jīng)提供出貝塞爾曲線工具眯杏。
貝塞爾曲線于1962,由法國工程師皮埃爾·貝塞爾(Pierre Bézier)所廣泛發(fā)表壳澳,他運用貝塞爾曲線來為汽車的主體進行設(shè)計岂贩。貝塞爾曲線最初由Paul de Casteljau于1959年運用de Casteljau演算法開發(fā),以穩(wěn)定數(shù)值的方法求出貝茲曲線巷波。
以上內(nèi)容從采取自百度百科
貝塞爾曲線目前被廣泛應(yīng)用于計算機制圖中萎津,可以說貝塞爾曲線奠定了計算機制圖的基礎(chǔ)。
Android中繪制Path的API
Android中繪制Path常用方法:
作用 | 相關(guān)方法 | 備注 |
---|---|---|
移動起點 | moveTo | 移動下一次操作的起點位置 |
設(shè)置終點 | setLastPoint | 重置當(dāng)前path中最后一個點位置抹镊,如果在繪制之前調(diào)用锉屈,效果和moveTo相同 |
連接直線 | lineTo | 添加上一個點到當(dāng)前點之間的直線到Path |
閉合路徑 | close | 連接第一個點連接到最后一個點,形成一個閉合區(qū)域 |
添加內(nèi)容 | addRect, addRoundRect, addOval, addCircle, addPath, addArc, arcTo | 添加(矩形垮耳, 圓角矩形颈渊, 橢圓, 圓终佛, 路徑俊嗽, 圓弧) 到當(dāng)前Path (注意addArc和arcTo的區(qū)別) |
是否為空 | isEmpty | 判斷Path是否為空 |
是否為矩形 | isRect | 判斷path是否是一個矩形 |
替換路徑 | set | 用新的路徑替換到當(dāng)前路徑所有內(nèi)容 |
偏移路徑 | offset | 對當(dāng)前路徑之前的操作進行偏移(不會影響之后的操作) |
貝塞爾曲線 | quadTo, cubicTo | 分別為二次和三次貝塞爾曲線的方法 |
rXxx方法 | rMoveTo, rLineTo, rQuadTo, rCubicTo | 不帶r的方法是基于原點的坐標(biāo)系(偏移量), rXxx方法是基于當(dāng)前點坐標(biāo)系(偏移量) |
填充模式 | setFillType, getFillType, isInverseFillType, toggleInverseFillType | 設(shè)置,獲取,判斷和切換填充模式 |
提示方法 | incReserve | 提示Path還有多少個點等待加入(這個方法貌似會讓Path優(yōu)化存儲結(jié)構(gòu)) |
布爾操作(API19) | op | 對兩個Path進行布爾運算(即取交集铃彰、并集等操作) |
計算邊界 | computeBounds | 計算Path的邊界 |
重置路徑 | reset, rewind | 清除Path中的內(nèi)容 |
reset不保留內(nèi)部數(shù)據(jù)結(jié)構(gòu)绍豁,但會保留FillType.
rewind會保留內(nèi)部的數(shù)據(jù)結(jié)構(gòu),但不保留FillType |
| 矩陣操作 | transform | 矩陣變換 |
貝塞爾曲線應(yīng)用簡單場景:
- QQ小紅點拖拽效果
- 平滑的折線圖的制作
- 閱讀軟件的翻書效果
繪制貝塞爾曲線
一階貝塞爾曲線
一階貝塞爾曲線的原理就是一條直線牙捉,其實就是直接畫了一個Path出來竹揍,在這里不做過多的介紹,本文主要介紹的是二階的貝塞爾曲線鹃共。
二階貝塞爾曲線
二階貝塞爾曲線效果圖:
實現(xiàn)原理
二階曲線由兩個數(shù)據(jù)點(A 和 C)鬼佣,一個控制點(B)來描述曲線狀態(tài),大致如下:
上圖中紅色曲線部分就是傳說中的二階貝塞爾曲線霜浴,那么這條紅色曲線是如何生成的呢晶衷?接下來我們就以其中的一個狀態(tài)分析一下:
連接AB BC,并在AB上取點D,BC上取點E晌纫,使其滿足條件:
連接DE税迷,取點F,使得:
AD/AB = BE/BC = DF/DE
這樣獲取到的點F就是貝塞爾曲線上的一個點锹漱,動態(tài)過程如下:
實現(xiàn)代碼
public class Bezier2 extends View {
private Paint mPaint;
private int centerX, centerY;
private PointF start, end, control;
public Bezier2(Context context) {
super(context);
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(8);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setTextSize(60);
start = new PointF(0,0);
end = new PointF(0,0);
control = new PointF(0,0);
}
public Bezier2(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(8);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setTextSize(60);
start = new PointF(0,0);
end = new PointF(0,0);
control = new PointF(0,0);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
centerX = w/2;
centerY = h/2;
// 初始化數(shù)據(jù)點和控制點的位置
start.x = centerX-200;
start.y = centerY;
end.x = centerX+200;
end.y = centerY;
control.x = centerX;
control.y = centerY-100;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 根據(jù)觸摸位置更新控制點箭养,并提示重繪
control.x = event.getX();
control.y = event.getY();
invalidate();
return true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 繪制數(shù)據(jù)點和控制點
mPaint.setColor(Color.GRAY);
mPaint.setStrokeWidth(20);
canvas.drawPoint(start.x,start.y,mPaint);
canvas.drawPoint(end.x,end.y,mPaint);
canvas.drawPoint(control.x,control.y,mPaint);
// 繪制輔助線
mPaint.setStrokeWidth(4);
canvas.drawLine(start.x,start.y,control.x,control.y,mPaint);
canvas.drawLine(end.x,end.y,control.x,control.y,mPaint);
// 繪制貝塞爾曲線
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(8);
Path path = new Path();
path.moveTo(start.x,start.y);
path.quadTo(control.x,control.y,end.x,end.y);
canvas.drawPath(path, mPaint);
}
}