您的位置:首页 > 移动开发 > Android开发

Android自定义View【实战教程】6⃣️---深入理解 Android 中的 Matrix

2017-05-18 15:02 501 查看

矩阵基础知识

兄弟们,重新拿起手中的线性代数课本,重拾一下矩阵吧。

记住一条原则:小事问老婆,大事问Google!!!

矩阵的基础知识

基本概念

矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合 ,最早来自于方程组的系数及常数所构成的方阵。这一概念由19世纪英国数学家凯利首先提出。

矩阵是高等代数学中的常见工具,也常见于统计分析等应用数学学科中。

基本运算













转置



矩阵(Matrix)和图形变换的关系

什么是平面?

还记得上学时课本中讲到,平面上的元素,就是点,线,面,而线就是由一个个点组成的,而是由一条条线组成的,所以归根结底,平面上所有的图形都是由点组成的。

所以在平面中,是一对x,y值组成的,p = {x, y}。线段是由两点之间的直线组成,e = {p1, p2}。图形是由众多的点和点之间的的线段组成的。所以,其实平面上的图形变换,就是点坐标位置的变换。

二维平面常用的基本的图形变化:

1、Translate (平移)

2、Scale (缩放)

3、Rotate(旋转)

4、Skew(错切)

Translate (平移)

我们现在要平移绿线到蓝线的位置:

假设绿线初始位置:(0,0)—> (100.100)

那么向右200,向下100到达蓝线位置,则蓝线坐标为(200,100)—> (300,200)。

如图:



这样的一个变换translation也可以用一对值来表示,t = {tx, ty},其中tx是在x坐标上的偏移量,而ty是在y坐标上的偏移量。

移动点 p 到 p’,我们只要加上这个偏移就行,如果用矩阵或者向量来表示就是:



Scale (缩放)

我们现在要缩放绿线到蓝线的位置:

假设绿线初始位置:(0,100)—> (100.0)

那么放大两倍到达蓝线位置,则蓝线坐标为(0,200)—> (200,000)。

如图:



缩放的变换是由下面的矩阵来表示的:



那么缩放后的直线的点就是:



Rotate(旋转)

如图;这条直线顺时针旋转了45度,也就是往逆时针方向旋转了 - 45 度,



旋转的矩阵表示是:



同样的,旋转后的点就是根据下面的矩阵相乘而得出来的结果:



Skew(错切)



用矩阵表示:



了解了上面矩阵和图型变换的关系之后,我们来步入正题,看一看安卓中的矩阵和图形变换的关系。

安卓中矩阵和图形变换的关系

其实在安卓中矩阵和图形变换的关系和上面讲到的是一样的,只不过设计者比较聪明,采用了齐次坐标

那么你肯定会问:

什么是齐次坐标系?

齐次坐标就是将一个原本是n维的向量用一个n+1维向量来表示。

有什么优点?

n维的向量用一个n+1维向量来表示

为什么要用齐次坐标系呢 ?

许多图形应用涉及到几何变换,主要包括平移、旋转、缩放。以矩阵表达式来计算这些变换时,平移是矩阵相加,旋转和缩放则是矩阵相乘,综合起来可以表示为p’ = m1*p+ m2(注:因为习惯的原因,实际使用时一般使用变化矩阵左乘向量)(m1旋转缩放矩阵, m2为平移矩阵, p为原向量 ,p’为变换后的向量)。引入齐次坐标的目的主要是合并矩阵运算中的乘法和加法,表示为p’ = p*M的形式。即它提供了用矩阵运算把二维、三维甚至高维空间中的一个点集从一个坐标系变换到另一个坐标系的有效方法。

所以在安卓中,用Matrix进行过图像处理,是一个3 x 3的矩阵,如图:



接下来看一下四种变换的具体情形:

Translate (平移)

假定有一个点的坐标是 ,将其移动到 ,再假定在x轴和y轴方向移动的大小分别为:



不难知道:



如果用矩阵来表示的话,就可以写成:



Scale (缩放)

如果图像在x轴和y轴方向分别放大k1和k2倍的话,那么图像中的所有点的x坐标和y坐标均会分别放大k1和k2倍:



用矩阵表示就是:



Rotate(旋转)

假定有一个点 ,相对坐标原点顺时针旋转后的情形,同时假定P点离坐标原点的距离为r:



如果用矩阵,就可以表示为:



Skew(错切)

假定一个点经过错切变换后得到,对于水平错切而言,应该有如下关系:



用矩阵表示就是:



同理,对于垂直错切,可以有:



在数学上严格的错切变换就是上面这样的。在Android中除了有上面说到的情况外,还可以同时进行水平、垂直错切,那么形式上就是:



到这里我们对安卓中Matrix和图形变换关系就应该有了一定的了解了。

理论与实践相结合

Translate (平移)

如图:将图片从原点水平移动100,垂直移动100.



//原始图片        canvas.drawBitmap(bitmap,matrix,mPaint);

//一、 Translate (平移)
matrix.postTranslate(100,100);


按照前面讲过的公式进行计算:

我们计算右下角图标,其它点坐标同理:



Scale (缩放)

图像在x轴和y轴方向分别放大0.5倍,如图:



//原始图片        canvas.drawBitmap(bitmap,matrix,mPaint);

//二、 Scale (缩放)
matrix.postScale(0.5f,0.5f);


按照前面讲过的公式进行计算:

我们计算右下角图标,其它点坐标同理:



Rotate(旋转)

假定顺着原点顺时针旋转75度,如图:



//原始图片        canvas.drawBitmap(bitmap,matrix,mPaint);

//三、 Rotate(旋转)
matrix.postRotate(75);


按照上面讲的公式计算:

我们计算右下角图标,其它点坐标同理:



Skew(错切)

水平错切-1 ,效果如图:



//原始图片        canvas.drawBitmap(bitmap,matrix,mPaint);

//四、 Skew(错切)
matrix.setSkew(-1,0);


按照上面讲的公式计算:

我们计算右下角图标,其它点坐标同理:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐