基础知识

变换矩阵

下面这个3 x 3的矩阵,这个矩阵被分割成4部分

300

设:

依据矩阵乘法,可得到下面的等式:

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相当于左乘矩阵。
posted on 2011-10-25 22:49  情定诺坎普  阅读(556)  评论(0编辑  收藏  举报