轉載請註明出處:http://blog.csdn.net/ljmingcom304/article/details/49302395
本文出自:【梁敬明的博客】
1.矩陣表示二維圖形
在二維空間中,可以通過
2.矩陣的幾何變換
矩陣的基本幾何變換都是相對於原點或座標軸進行平移、旋轉、縮放、錯切等。
在操作矩陣的幾何變換前首先需要科普下齊次座標法,所謂的齊次座標法就是將n維的向量用n+1維來表示,主要用計算矩陣的幾何變換,例如平移、旋轉、縮放等。例如:將點A(1,1)用矩陣的二維行向量表示爲[1,1],採用齊次座標法用矩陣的三維行向量表示爲[1,1,1]。所以三角形ABC用矩陣也可以表示爲
矩陣的幾何變換的計算方式爲:變換前圖形矩陣×變換矩陣1×變換矩陣2…=變換後圖形矩陣(當一個矩陣進行多次幾何變換時,只需要連乘即可)。假設一個三角形三個頂點座標分別爲
public class MatrixUtils {
/**
* 多矩陣相乘
* @param arrays 變換前圖形矩陣
* @param arg 變換矩陣
* @return 變換後圖形矩陣
*/
public static float[][] matrixsMcl(float[][] arrays, float[][]... args) {
float[][] results = arrays;
for (float[][] arg : args) {
results = matrixMcl(results, arg);
}
return results;
}
/**
* 兩矩陣相乘
* @param arrays 變換前圖形矩陣
* @param arg 變換矩陣
* @return 變換後圖形矩陣
*/
private static float[][] matrixMcl(float[][] arrays, float[][] arg) {
int i, j, k;
float[][] results = new float[arrays.length][];
for (i = 0; i < arrays.length; i++) {
float[] array = arrays[i];
results[i] = new float[array.length];
float[][] newArg = transposeF(arg);
for (j = 0; j < newArg.length; j++) {
float[] newArgJ = newArg[j];
int count = 0;
for (k = 0; k < newArgJ.length; k++) {
count += array[k] * newArgJ[k];
}
results[i][j] = count;
}
}
return results;
}
/**
* 矩陣轉置:所有元素繞着一條從第1行第1列元素出發的右下方45度的射線作鏡面反轉
* @param arrays 轉置前矩陣
* @return 轉置後矩陣
*/
private static float[][] transposeF(float[][] arrays) {
int i, j;
float[][] newArrays = new float[arrays[0].length][arrays.length];
for (i = 0; i < arrays.length; i++) {
for (j = 0; j < arrays[i].length; j++) {
newArrays[j][i] = arrays[i][j]; // 轉置核心
}
}
return newArrays;
}
......
}
##2.1.平移變換
平移變換:圖形中的每一個點在給定方向上移動相同距離所進行的變換。
二維圖形的平移變換矩陣爲T=![平移](https://img-blog.csdn.net/20151021160844879)
public class MatrixUtils { ...... /** 平移 */ public static Point[] translate(float x, float y, Point... ps) { for (Point point : ps) { float[][] points = { { point.x, point.y, 1f } }; float[][] translate = { { 1, 0, 0 }, { 0, 1, 1 }, { x, y, 1 } }; //矩陣相乘 float[][] results = matrixMcl(points, translate); point.x = (int) results[0][0]; point.y = (int) results[0][1]; } return ps; } }##2.2.縮放變換 縮放變換:圖形以固定點爲中心,按相同比例進行放大或縮小所進行的變換。 二維圖形的以原點爲中心縮放變換矩陣爲T=
![縮放](https://img-blog.csdn.net/20151021160912756)
public class MatrixUtils { ...... /** 縮放 */ public static Point[] scale(float x, float y, Point... ps) { for (Point point : ps) { float[][] points = { { point.x, point.y, 1 } }; float[][] scale = { { x, 0, 0 }, { 0, y, 1 }, { 0, 0, 1 } }; //矩陣相乘 float[][] results = matrixMcl(points, scale); point.x = (int) results[0][0]; point.y = (int) results[0][1]; } return ps; } }##2.3.對稱變換 縮放變換:圖形中的每一個點關於某個點或某條線進行對稱後所得的變換。 二維圖形的關於原點或直線對稱變換矩陣爲T=
![對稱](https://img-blog.csdn.net/20151021160934656)
public class MatrixUtils { ...... /** X軸對稱 */ public static Point[] projectX(Point... ps) { for (Point point : ps) { float[][] points = { { point.x, point.y, 1 } }; float[][] project = { { 1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } }; //矩陣相乘 float[][] results = matrixMcl(points, project); point.x = (int) results[0][0]; point.y = (int) results[0][1]; } return ps; } /** Y軸對稱 */ public static Point[] projectY(Point... ps) { for (Point point : ps) { float[][] points = { { point.x, point.y, 1 } }; float[][] project = { { -1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } }; //矩陣相乘 float[][] results = matrixMcl(points, project); point.x = (int) results[0][0]; point.y = (int) results[0][1]; } return ps; } /** 原點對稱 */ public static Point[] projectP(Point... ps) { for (Point point : ps) { float[][] points = { { point.x, point.y, 1 } }; float[][] scale = { { -1, 0, 0 }, { 0, -1, 0 }, { 0, 0, 1 } }; //矩陣相乘 float[][] results = matrixMcl(points, scale); point.x = (int) results[0][0]; point.y = (int) results[0][1]; } return ps; } }##2.4.旋轉變換 旋轉變換:圖形中的中的每一個點按相同的方向、相同的旋轉角度旋轉所進行的變換。 二維圖形的關於原點的旋轉變換矩陣爲T=
![旋轉](https://img-blog.csdn.net/20151021160955944)
public class MatrixUtils { ...... /** 旋轉 */ public static Point[] rotate(float angle, Point... ps) { for (Point point : ps) { float cos = (float) Math.cos(angle); float sin = (float) Math.sin(angle); float[][] points = { { point.x, point.y, 1 } }; float[][] rotate = { { cos, -sin, 0 }, { sin, cos, 1 }, { 0, 0, 1 } }; //矩陣相乘 float[][] results = matrixMcl(points, rotate); point.x = (int) results[0][0]; point.y = (int) results[0][1]; } return ps; } }##2.5.錯切變換 錯切變換:圖形中的各點在某一方向上的座標保持不變,在另一方向上的座標進行線性變換,或在兩座標方向的座標都進行的線性變換。 二維圖形的錯切變換矩陣爲T=
![錯切](https://img-blog.csdn.net/20151021161021735)
public class MatrixUtils { ...... /** 錯切 */ public static Point[] skew(float x, float y, Point... ps) { for (Point point : ps) { float[][] points = { { point.x, point.y, 1 } }; float[][] skew = { { 1, y, 0 }, { x, 1, 0 }, { 0, 0, 1 } }; float[][] results = matrixMcl(points, skew); point.x = (int) results[0][0]; point.y = (int) results[0][1]; } return ps; } }#3.通過自定義控件實現矩陣幾何變換 首先在自定義控件中基於控制點繪製一個初始的矩形方框:
public class MatrixView extends View {
private Paint paint;
private Path path;
private Point[] ps;
private int w;
private int h;
private Point p1;
private Point p2;
private Point p3;
private Point p4;
public MatrixView(Context context) {
this(context, null);
}
public MatrixView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MatrixView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint();
paint.setAntiAlias(true);//抗鋸齒使邊緣更加平滑
paint.setStrokeWidth(3);//邊框寬度
paint.setStyle(Style.STROKE);
paint.setColor(Color.RED);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
this.w = w;//控件的寬度
this.h = h;//控件的高度
p1 = new Point(-w / 2, -h / 4);
p2 = new Point(0, -h / 4);
p3 = new Point(0, 0);
p4 = new Point(-w / 2, 0);
ps = new Point[] { p1, p2, p3, p4 };
path = new Path();
}
/**通過Path路徑繪製一個矩形*/
private void toShape(boolean isClose, Path path, Point... ps) {
for (int i = 0; i < ps.length; i++) {
if (i == 0) {
path.moveTo(ps[0].x, ps[0].y);
} else {
path.lineTo(ps[i].x, ps[i].y);
}
}
if (isClose)
path.close();
}
@Override
protected void onDraw(Canvas canvas) {
// 繪製初始圖形
toShape(true, path, ps);
//將畫布的原點移動到屏幕的中央
canvas.translate(w / 2, h / 2);
canvas.drawPath(path, paint);
path.reset();
}
......
}
然後基於控制點對當前View進行幾何變換:public class MatrixView extends View { ...... /**還原*/ public void clear() { ps = new Point[] { new Point(-w / 2, -h / 4), new Point(0, -h / 4), new Point(0, 0), new Point(-w / 2, 0) }; invalidate(); } /** 平移 */ public void translate() { ps = MatrixUtils.translate(200, 200, ps); invalidate(); } /** 錯切 */ public void skew() { ps = MatrixUtils.skew(-0.5f, 0, ps); invalidate(); } /** 縮放 */ public void scale() { ps = MatrixUtils.scale(0.5f, 0.5f, ps); invalidate(); } /** 旋轉 */ public void rotate() { ps = MatrixUtils.rotate(-(float) Math.PI / 4, ps); invalidate(); } /** X軸對稱 */ public void projectX() { ps = MatrixUtils.projectX(ps); invalidate(); } /** Y軸對稱 */ public void projectY() { ps = MatrixUtils.projectY(ps); invalidate(); } /** 原點對稱 */ public void projectP() { ps = MatrixUtils.projectP(ps); invalidate(); } }
最後顯示效果圖: