基础知识
变换矩阵
下面这个3 x 3的矩阵,这个矩阵被分割成4部分
设:
依据矩阵乘法,可得到下面的等式:
x = a*x0 + b*y0 + c
y = d*x0 + e*y0 + f
当a=1,b=0,c=△x,d=0,e=1,f=△y时,有:
x = x0 + △x
y = y0 + △y
此时即为矩阵平移操作。
依上面的原理,可得下表:
常见应用
调试
通过matrix.toString());可以得到矩阵内容,便于调试。
平移
float dx = 10; //水平偏移量 float dy = 10; //垂直偏移量 matrix = new Matrix(); matrix.setTranslate(px,py); //canvas.drawBitmap(bmp, matrix, null);
或
float dx = 10; //水平偏移量 float dy = 10; //垂直偏移量 float f[]={1,0,dx, 0,1,dy, 0,0, 1}; Matrix matrix = new Matrix(); matrix.setValues(f); //canvas.drawBitmap(bmp, matrix, null);
即:
x = x0 + dx
y = y0 + dy
缩放
float kx = 10; //x坐标缩放倍数 float ky = 10; //y坐标缩放倍数 Matrix matrix = new Matrix(); matrix.setScale(kx, ky) //canvas.drawBitmap(bmp, matrix, null);
或
float kx = 10; //x坐标缩放倍数 float ky = 10; //y坐标缩放倍数 float f[]={kx, 0, 0, 0, ky, 0, 0, 0, 1}; Matrix matrix = new Matrix(); matrix.setValues(f); //canvas.drawBitmap(bmp, matrix, null);
即:
x = kx*x0
y = ky*y0
绕某点旋转
float a = 10; //旋转角度 float px = 10; //旋转点x坐标 float py = 10; //旋转点y坐标 Matrix matrix = new Matrix(); matrix.setRotate(a,px,py); //canvas.drawBitmap(bmp, matrix, null);
或
float a = 10; //旋转角度 float px = 10; //旋转点x坐标 float py = 10; //旋转点y坐标 matrix = new Matrix(); //平移 matrix.setTranslate(px,py); //旋转 matrix.preRotate(a); //平移 matrix.preTranslate(-px,-py); //canvas.drawBitmap(bmp, matrix, null);
或
float a = 10; //旋转角度 float px = 10; //旋转点x坐标 float py = 10; //旋转点y坐标 float f[]={Math.cos(a),-Math.sin(a),-px*Math.cos(a)+py*Math.sin(a)+px, Math.sin(a), Math.cos(a),-px*Math.sin(a)-py*Math.cos(a)+py, 0, 0, 1}; Matrix matrix = new Matrix(); matrix.setValues(f); //canvas.drawBitmap(bmp, matrix, null);
设:
x0=r*cos(A)
y0=r*Sin(A)
即:
x= x0*Cos(a)+ y0*Sin(a)=r*Cos(A-a)
y=-x0*Sin(a)+ y0*Cos(a)=r*Sin(A-a)
垂直镜像
float hh = 图像高度; float f[]={1, 0, 0, 0, -1, hh, 0, 0, 1}; Matrix matrix = new Matrix(); matrix.setValues(f); //canvas.drawBitmap(bmp, matrix, null);
即:
x = x0
y = hh-y0
水平镜像
float ww = 图像宽度; float f[]={-1, 0, ww, 0, 1, 0, 0, 0, 1}; Matrix matrix = new Matrix(); matrix.setValues(f); //canvas.drawBitmap(bmp, matrix, null);
即:
x = ww-x0
y = y0
关于某点对称
float px = 1; float py = 1; float f[]={-1, 0, -px, 0, -1, -py, 0, 0, 1}; Matrix matrix = new Matrix(); matrix.setValues(f); //canvas.drawBitmap(bmp, matrix, null);
即:
x = -(x0+px)
y = -(y0+py)
关于某直线对称
由点(x0,y0)关于直线Ax+By+C=0对称的点(x,y)的坐标公式:
x = x0 - 2A*(Ax+By+C)/(A^2+B^2)
y = y0 - 2B*(Ax+By+C)/(A^2+B^2)
可得:
x = [1-2*A^2/(A^2+B^2)]*x0 - 2*A*B/(A^2+B^2)*y0 - 2*A*C/(A^2+B^2)
y = -2*A*B/(A^2+B^2)*x0 + [1-2*B^2/(A^2+B^2)]*y0 - 2*A*B/(A^2+B^2)
float A,B,C; //直线方程参数 float f = A*A+B*B; float a = 1-2*A*A/f; float b = -2*A*B/f; float c = -2*A*C/f; float d = b; float e = 1-2*B*B/f; f = -2*B*C/f+y0; float f[]={a, b, c, d, e, f, 0, 0, 1}; Matrix matrix = new Matrix(); matrix.setValues(f); //canvas.drawBitmap(bmp, matrix, null);
透视/扭曲
float kx = 1; //x扭曲系数 float ky = 1; //y扭曲系数 Matrix matrix = new Matrix(); matrix.setSkew(kx, ky); //canvas.drawBitmap(bmp, matrix, null);
复合变换
由于矩阵的乘法不满足交换律,也就是说A*B ≠B*A,所以用矩阵B乘以矩阵A,需要考虑是左乘(B*A),还是右乘(A*B)。在Android的android.graphics.Matrix 中提供了类似的方法,也就是Preconcats matrix与Postconcats matrix。其中:
-
Preconcats matrix相当于右乘矩阵。
-
Postconcats matrix相当于左乘矩阵。