android-View-Matrix

Matrix是一个矩阵,主要功能是坐标映射数值转换

Matrix特点

  • 作用广泛: Matrix在View,图片,动画,效果等各个方面均有运用.
  • 更加灵活: Matrix作为更接近底层的东西,必然要比画布操作更灵活.

Matrix基本原理

Matrix是一个矩阵,最根本的作用就是坐标转换.

基本变换有4种: 平移(translate)、缩放(scale)、旋转(rotate) 和 错切(skew).

Matrix复合原理

其实Matrix的多种复合操作都是使用矩阵乘法实现的,从原理上理解很简单,但是,使用矩阵乘法也有其弱点,后面的操作可能会影响到前面到操作,所以在构造Matrix时顺序很重要。

我们常用的四大变换操作,每一种操作在Matrix均有三类,前乘(pre),后乘(post)和设置(set),可以参见文末对Matrix方法表,由于矩阵乘法不满足交换律,所以前乘(pre),后乘(post)和设置(set)的区别还是很大的。

那么如何使用?

正确使用方式就是先构造正常的 Matrix 乘法顺序,之后根据情况使用 pre 和 post 来把这个顺序实现。

还是用一个最简单的例子理解,假设需要围绕某一点旋转。

可以用这个方法 xxxRotate(angle, pivotX, pivotY) ,由于我们这里需要组合构造一个 Matrix,所以不直接使用这个方法。

首先,有两条基本定理:

  • 所有的操作(旋转、平移、缩放、错切)默认都是以坐标原点为基准点的。
  • 之前操作的坐标系状态会保留,并且影响到后续状态。

基于这两条基本定理,我们可以推算出要基于某一个点进行旋转需要如下步骤:

1.先将坐标系原点移动到指定位置,使用平移 T

2.对坐标系进行旋转,使用旋转 S (围绕原点旋转)

3.再将坐标系平移回原来位置,使用平移 -T

按此写出来的伪代码如下:

Matrix matrix = new Matrix();
matrix.preTranslate(pivotX,pivotY);
matrix.preRotate(angle);
matrix.preTranslate(-pivotX, -pivotY);

原文

Matrix详解

方法:

方法类别相关API摘要
基本方法equals hashCode toString toShortString比较、 获取哈希值、 转换为字符串
数值操作set reset setValues getValues设置、 重置、 设置数值、 获取数值
数值计算mapPoints mapRadius mapRect mapVectors计算变换后的数值
设置(set)setConcat setRotate setScale setSkew setTranslate设置变换
前乘(pre)preConcat preRotate preScale preSkew preTranslate前乘变换
后乘(post)postConcat postRotate postScale postSkew postTranslate后乘变换
特殊方法setPolyToPoly setRectToRect rectStaysRect setSinCos一些特殊操作
矩阵相关invert isAffine(API21) isIdentity求逆矩阵、 是否为仿射矩阵、 是否为单位矩阵 …

构造方法:

1.无参构造

Matrix matrix = new Matrix();

通过这种方式创建出来的并不是一个数值全部为空的矩阵,而是一个单位矩阵,如下:

2.有参构造

Matrix (Matrix src)

这种方法则需要一个已经存在的矩阵作为参数,创建一个Matrix,并对src深拷贝(理解为新的matrix和src是两个对象,但内部数值相同即可)。

基本方法;

1.equals -> 比较两个Matrix的数值是否相同。

### 数值操作:

1.reset

void reset () //重置当前Matrix(为单位矩阵)

2.set

void set (Matrix src) //没有返回值,有一个参数,作用是将参数Matrix的数值复制到当前Matrix中。如果参数为空,则重置当前Matrix,相当于reset()。

3.setValues

void setValues (float[] values) //setValues的参数是浮点型的一维数组,长度需要大于9,拷贝数组中的前9位数值赋值给当前Matrix。

4.getValues

void getValues (float[] values) //很显然,getValues和setValues是一对方法,参数也是浮点型的一维数组,长度需要大于9,将Matrix中的数值拷贝进参数的前9位中。

数值计算

1.mapPoints

void mapPoints (float[] pts)

void mapPoints (float[] dst, float[] src)

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

(1) void mapPoints (float[] pts) 方法仅有一个参数,pts数组作为参数传递原始数值,计算结果仍存放在pts中。

val pts = floatArrayOf(0f,0f,80f,100f,400f,300f)//初始数据为三个点 (0, 0) (80, 100) (400, 300) 
val matrix = Matrix()
matrix.setScale(0.5f,1f)//x坐标缩放0.5
log(src.contentToString())
matrix.mapPoints(pts)
log(src.contentToString())
>>>
//变换前:[0.0, 0.0, 80.0, 100.0, 400.0, 300.0]
//变换后:[0.0, 0.0, 40.0, 100.0, 200.0, 300.0]

(2) void mapPoints (float[] dst, float[] src) ,src作为参数传递原始数值,计算结果存放在dst中,src不变。

val src = floatArrayOf(0f,0f,80f,100f,400f,300f)
val dst = FloatArray(6)
val matrix = Matrix()
matrix.setScale(0.5f,1f)
log(src.contentToString())
log(dst.contentToString())
matrix.mapPoints(dst,src)
log(src.contentToString())
log(dst.contentToString())
>>>
//src:[0.0, 0.0, 80.0, 100.0, 400.0, 300.0]
//dst:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
//src:[0.0, 0.0, 80.0, 100.0, 400.0, 300.0]
//dst:[0.0, 0.0, 40.0, 100.0, 200.0, 300.0]

(3) void mapPoints (float[] dst, int dstIndex,float[] src, int srcIndex, int pointCount) 可以指定只计算一部分数值。

参数摘要
dst目标数据
dstIndex目标数据存储位置起始下标
src源数据
srcIndex源数据存储位置起始下标
pointCount计算的个数
val src = floatArrayOf(0f,0f,80f,100f,400f,300f)
val dst = FloatArray(6)
val matrix = Matrix()
matrix.setScale(0.5f,1f)
log(src.contentToString())
log(dst.contentToString())
matrix.mapPoints(dst,0,src,2,2)//注意是从2开始后的,两个点,有四个值,并非两个数值
log(src.contentToString())
log(dst.contentToString())
>>>
//src:[0.0, 0.0, 80.0, 100.0, 400.0, 300.0]
//dst:[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
//src:[0.0, 0.0, 80.0, 100.0, 400.0, 300.0]
//dst:[40.0, 100.0, 200.0, 300.0, 0.0, 0.0]

2.mapRect

boolean mapRect (RectF rect)//测量rect并将测量结果放入rect中,返回值是判断矩形经过变换后是否仍为矩形。
boolean mapRect (RectF dst, RectF src)//测量src并将测量结果放入dst中,返回值是判断矩形经过变换后是否仍为矩形

3.mapVectors

void mapVectors (float[] vecs)

void mapVectors (float[] dst, float[] src)

void mapVectors (float[] dst, int dstIndex, float[] src, int srcIndex, int vectorCount)

mapVectorsmapPoints 基本上是相同的,可以直接参照上面的mapPoints使用方法。

而两者唯一的区别就是mapVectors不会受到位移的影响,这符合向量的定律

set、pre 与 post

方法简介
set设置,会覆盖掉之前的数值,导致之前的操作失效。
pre前乘,相当于矩阵的右乘, M' = M * S (S指为特殊矩阵)
post后乘,相当于矩阵的左乘,M' = S * M (S指为特殊矩阵)

特殊方法

1.setPolyToPoly

boolean setPolyToPoly (
        float[] src,    // 原始数组 src [x,y],存储内容为一组点
        int srcIndex,   // 原始数组开始位置
        float[] dst,    // 目标数组 dst [x,y],存储内容为一组点
        int dstIndex,   // 目标数组开始位置
        int pointCount) // 测控点的数量 取值范围是: 0到4

有关于pointCount:

pointCount摘要
0相当于reset
1相当于translate
2可以进行 缩放、旋转、平移 变换
3可以进行 缩放、旋转、平移、错切 变换
4可以进行 缩放、旋转、平移、错切以及任何形变

1个点:

2个点:

3个点:

4个点:

由此可以直观的感受点数多带来的不同.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值