Android Matrix的使用

[TOC]

使用方法

构造

单位矩阵

Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}

void setRotate(float degrees)

Set the matrix to rotate about (0,0) by the specified number of degrees.

旋转矩阵

matrix.setRotate(30);
Matrix{[0.8660254, -0.5, 0.0][0.5, 0.8660254, 0.0][0.0, 0.0, 1.0]}

Math.cos(Math.toRadians(30)) = 0.8660254037844387
Math.sin(Math.toRadians(30))  = 0.49999999999999994


旋转矩阵

cosθ    −sinθ   0
​sinθ    cosθ    0
​0       0       1

符合预期

setRotate(float degrees, float px, float py)

Set the matrix to rotate by the specified number of degrees, with a pivot point at (px, py).

围绕px,py旋转

//179, 192.5 为图片宽高一半,相当于中心
matrix.setRotate(30, 179, 192.5);

Matrix{[0.8660254, -0.5, 120.23145][0.5, 0.8660254, -63.709885][0.0, 0.0, 1.0]}

相当于旋转后做了平移操作

推导过程

验证

Math.cos(Math.toRadians(30)) = 0.8660254037844387
Math.sin(Math.toRadians(30))  = 0.49999999999999994
−cosθ.tx +sinθ.t​y +tx =  -0.8660254037844387 * 179 + 0.5 * 192.5 + 179 = 120.231452722

setSinCos(float sinValue, float cosValue)

Set the matrix to rotate by the specified sine and cosine values.

matrix.setSinCos((float) Math.sin(Math.toRadians(30)),(float) Math.cos(Math.toRadians(30)));
Matrix{[0.8660254, -0.5, 0.0][0.5, 0.8660254, 0.0][0.0, 0.0, 1.0]}

和setRotate(float degrees, float px, float py)等价

setSinCos(float sinValue, float cosValue, float px, float py)

Set the matrix to rotate by the specified sine and cosine values, with a pivot point at (px, py).

和setRotate(float degrees, float px, float py)等价

matrix.setSinCos((float) Math.sin(Math.toRadians(30)),(float) Math.cos(Math.toRadians(30)), mBitmapMan.getWidth() / 2.0f, mBitmapMan.getHeight() / 2.0f);

setScale(float sx, float sy)

Set the matrix to scale by sx and sy.

缩放变换矩阵

matrix.setScale(0.8f, 0.8f);
Matrix{[0.8, 0.0, 0.0][0.0, 0.8, 0.0][0.0, 0.0, 1.0]}

setScale(float sx, float sy, float px, float py)

Set the matrix to scale by sx and sy, with a pivot point at (px, py).

matrix.setScale(0.8f, 0.8f, 179, 192.5);


//Matrix{[0.8, 0.0, 35.800003][0.0, 0.8, 38.5][0.0, 0.0, 1.0]}
matrix.setScale(0.8f, 0.8f, 10, 10);

//Matrix{[0.8, 0.0, 2.0][0.0, 0.8, 2.0][0.0, 0.0, 1.0]}
matrix.setScale(1.2f, 1.2f, 179, 192.5);

Matrix{[1.2, 0.0, -35.800003][0.0, 1.2, -38.500015][0.0, 0.0, 1.0]}

相当于缩放后进行平移操作,默认图片左上角,如果指定了中心,相当于 平移 px * (1-sx)

上面相当于

matrix.setScale(0.8f, 0.8f);
matrix.postTranslate(0.2f * 179, 0.2f * 192.5);

//Matrix{[0.8, 0.0, 35.8][0.0, 0.8, 38.5][0.0, 0.0, 1.0]}

推导过程

void setTranslate(float dx, float dy)

Set the matrix to translate by (dx, dy).

matrix.setTranslate(50, 100);

//Matrix{[1.0, 0.0, 50.0][0.0, 1.0, 100.0][0.0, 0.0, 1.0]}

setSkew(float kx, float ky)

Set the matrix to skew by sx and sy.

错切,可以参考

k就是斜率

setSkew(float kx, float ky, float px, float py)

Set the matrix to skew by sx and sy, with a pivot point at (px, py).

设置中心点的错切

void setValues(float[] values)

Copy 9 values from the array into the matrix.

float[] copy = new float[9];
matrix.setValues(copy);

Matrix{[0.0, 0.0, 0.0][0.0, 0.0, 0.0][0.0, 0.0, 0.0]}

boolean postConcat(Matrix other)

Postconcats the matrix with the specified matrix.

后乘一个矩阵

postXX系列

  • boolean postRotate(float degrees, float px, float py)
    • Postconcats the matrix with the specified rotation.
  • boolean postRotate(float degrees)
    • Postconcats the matrix with the specified rotation.
  • boolean postScale(float sx, float sy, float px, float py)
    • Postconcats the matrix with the specified scale.
  • boolean postScale(float sx, float sy)
    • Postconcats the matrix with the specified scale.
  • boolean postSkew(float kx, float ky)
    • Postconcats the matrix with the specified skew.
  • boolean postSkew(float kx, float ky, float px, float py)
    • Postconcats the matrix with the specified skew.
  • boolean postTranslate(float dx, float dy)
    • Postconcats the matrix with the specified translation.

boolean preConcat(Matrix other)

Preconcats the matrix with the specified matrix.
前乘一个矩阵

preXX系列

  • boolean preRotate(float degrees)
    • Preconcats the matrix with the specified rotation.
  • boolean preRotate(float degrees, float px, float py)
    • Preconcats the matrix with the specified rotation.
  • boolean preScale(float sx, float sy)
    • Preconcats the matrix with the specified scale.
  • boolean preScale(float sx, float sy, float px, float py)
    • Preconcats the matrix with the specified scale.
  • boolean preSkew(float kx, float ky)
    • Preconcats the matrix with the specified skew.
  • boolean preSkew(float kx, float ky, float px, float py)
    • Preconcats the matrix with the specified skew.
  • boolean preTranslate(float dx, float dy)
    • Preconcats the matrix with the specified translation.

pre post set的执行顺序问题

set会清除前面pre和post的操作,pre前乘法、post后乘

//179, 192.5 为图片宽高一半,相当于中心
matrix.setRotate(30, 179, 192.5);



和下面等效
matrix.setRotate(30);
matrix.preTranslate(-179, - 192.5);
matrix.postTranslate(179, 192.5);

相当于左移上移 然后 旋转  再 右移下移

boolean setConcat(Matrix a, Matrix b)

Set the matrix to the concatenation of the two specified matrices and return true.

两个矩阵相乘

//179, 192.5 为图片宽高一半,相当于中心
Matrix preTransMatrix = new Matrix();
preTransMatrix.setTranslate(179,  192.5);
Matrix rotateMatrix = new Matrix();
rotateMatrix.setRotate(30);
Matrix tmpR1 = new Matrix();
tmpR1.setConcat(preTransMatrix,rotateMatrix);
Matrix postTransMatrix = new Matrix();
postTransMatrix.setTranslate(-179, - 192.5);
Matrix tmp5 = new Matrix();
tmp5.setConcat(tmpR1,postTransMatrix);


和下面等效
matrix.setRotate(30, 179, 192.5);


和下面等效
matrix.setRotate(30);
matrix.preTranslate(-179, - 192.5);
matrix.postTranslate(179, 192.5);

boolean isAffine()

Gets whether this matrix is affine.

是否是仿射变换矩阵

matrix.reset();
Log.d(TAG, "isAffine = " +matrix.isAffine() ); //true
float[] simple = new float[]{0,1,2,3,4,5,6,7,8};
matrix.setValues(simple);
Log.d(TAG, "isAffine = " +matrix.isAffine() );//false

boolean isIdentity()

Returns true if the matrix is identity.

boolean invert(Matrix inverse)

If this matrix can be inverted, return true and if inverse is not null, set inverse to be the inverse of this matrix.

求逆矩阵

matrix.setRotate(30);
Matrix invertTmp = new Matrix();
matrix.invert(invertTmp);
Matrix invertConcat = new Matrix();
invertConcat.setConcat(matrix, invertTmp);

最后invertConcat是单位矩阵,相当于顺时针转了30度又逆时针转了回来

float mapRadius(float radius)

Return the mean radius of a circle after it has been mapped by this matrix.

计算矩阵映射后的圆半径

float radius = 100.0f;
float radiusAfterMatrix;
Matrix matrixRadius = new Matrix();
matrixRadius.setScale(2,2, 1, 1);
radiusAfterMatrix = matrixRadius.mapRadius(radius);

结果200
和中心点无关

参考了 -Android Matrix 方法详解(另类)

mapPoints

二维点的变化

  • void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, int pointCount)

    • Apply this matrix to the array of 2D points specified by src, and write the transformed points into the array of points specified by dst.
  • void mapPoints(float[] dst, float[] src)

    • Apply this matrix to the array of 2D points specified by src, and write the transformed points into the array of points specified by dst.
  • void mapPoints(float[] pts)

    • Apply this matrix to the array of 2D points, and write the transformed points back into the array
float[] ptsTrans = {6,2};
matrix.setTranslate(-2,2);
matrix.mapPoints(ptsTrans);
//结果 4, 4

float[] resultTmp = new float[2];
matrix.setTranslate(-2,2);
matrix.mapPoints(resultTmp, ptsTrans);
// resultTmp  2, 6 因为上次结果是4, 4


mapRect

映射到矩形上

  • boolean mapRect(RectF rect)

    • Apply this matrix to the rectangle, and write the transformed rectangle back into it.
  • boolean mapRect(RectF dst, RectF src)

    • Apply this matrix to the src rectangle, and write the transformed rectangle into dst.
RectF rectF = new RectF(100,100,200,200);
matrix.reset();
matrix.setScale(2,2);
matrix.mapRect(rectF);
//[200.0,200.0][400.0,400.0]

mapVectors

矩阵变换作用于向量,和mapPoints比较类似,但是例如tranlate这种对vector没有变化

  • void mapVectors(float[] vecs)

    • Apply this matrix to the array of 2D vectors, and write the transformed vectors back into the array.
  • void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int vectorCount)

    • Apply this matrix to the array of 2D vectors specified by src, and write the transformed vectors into the array of vectors specified by dst.
  • void mapVectors(float[] dst, float[] src)

    • Apply this matrix to the array of 2D vectors specified by src, and write the transformed vectors into the array of vectors specified by dst.
float[] vector = {2,3};
float[] point = {2,3};
Matrix matrixTranslate = new Matrix();
matrixTranslate.setTranslate(2,3);
matrixTranslate.mapVectors(vector);
matrixTranslate.mapPoints(point);

// 输出:vector = [2.0,3.0]
System.out.println("vector = " + Arrays.toString(vector));
// 输出:point = [4.0,6.0]
System.out.println("point = " + Arrays.toString(point));

boolean rectStaysRect()

Returns true if will map a rectangle to another rectangle.

boolean setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)

Set the matrix such that the specified src points would map to the specified dst points.

根据SRC的点到DST的点,求的Matrix的变换矩阵

float[] src = {1,2};
float[] dst = {2,4};

Matrix matrix = new Matrix();
matrix.setPolyToPoly(src,0,dst,0,1);

//          [1.0, 0.0, 1.0]
// matrix = [0.0, 1.0, 2.0]
//          [0.0, 0.0, 1.0]

相当于平移 1,2

boolean setRectToRect(RectF src, RectF dst, Matrix.ScaleToFit stf)

Set the matrix to the scale and translate values that map the source rectangle to the destination rectangle, returning true if the the result can be represented.

将矩形填充到矩形中。其中在填充时可以指定4种填充模式.

void reset()

Set the matrix to identity

void set(Matrix src)

(deep) copy the src matrix into this matrix.

void getValues(float[] values)

Copy 9 values from the matrix into the array.

matrix.reset();
float[] copy = new float[9];
matrix.getValues(copy);

0 = 1.0
1 = 0.0
2 = 0.0
3 = 0.0
4 = 1.0
5 = 0.0
6 = 0.0
7 = 0.0
8 = 1.0

常量

  • int MSCALE_X = 0;
  • int MSKEW_X = 1;
  • int MTRANS_X = 2;
  • int MSKEW_Y = 3;
  • int MSCALE_Y = 4;
  • int MTRANS_Y = 5;
  • int MPERSP_0 = 6;
  • int MPERSP_1 = 7;
  • int MPERSP_2 = 8; //!< use with getValues/setValues

数学原理