Android:Matrix – > preconcat和postconcat有什么区别?

我正在使用matrix来缩放和旋转位图。 现在我想知道preconcat和postconcat之间的区别是什么,或者更准确地说是两者之间的区别:

  • postRotate
  • preRotate
  • setRotate

从我到目前为止可以弄清楚setRotate总是覆盖整个matrix,而与preRotate和postRotate我可以应用多个更改matrix(如缩放+旋转)。 但是,使用postRotate或preRotate不会导致我使用它们的情况下有任何不同的结果。

对于你的问题的答案是不是真的特定于Android; 这是一个graphics和math问题。 这个答案有很多理论 – 你已经被警告过了! 对于你的问题的表面答案,跳到底部。 另外,因为这是一个啰嗦的长篇大论,所以我可能会有一个错字,让事情不清楚。 如果是这样的话,我提前道歉。

在计算机graphics学中,我们可以将像素(或三维顶点)表示为vector。 如果你的屏幕是640×480,那么这个屏幕中间点的2Dvector(原谅我的伪劣标记):

[320] [240] [ 1] 

我会解释为什么1很重要。 转换通常用matrix来表示,因为如你所提到的那样,转换就非常简单(而且非常有效)。 要将上面的点缩放1.5倍,可以将它乘以以下matrix:

 [1.5 0 0] [ 0 1.5 0] [ 0 0 1] 

你会得到这个新的观点:

 [480] [360] [ 1] 

它代表原始点,相对于屏幕的angular(0,0)缩放1.5。 这一点很重要:缩放比例始终是针对原点完成的。 如果你想用其他点作为你的中心(比如精灵的中间部分)进行缩放,你需要在翻译中将“缩放”换成原点。 以下是将原始点转换为原点的matrix:

 [1 0 -320] [0 1 -240] [0 0 1] 

这产生:

 [320*1 + 1*-320] [0] [240*1 + 1*-240] = [0] [ 1*1 ] [1] 

你会认识到上面是位置坐标被打在右上angular的单位matrix。 这就是为什么1(“同质坐标”)是必要的:为这些坐标腾出空间,从而可以使用乘法来翻译。 否则,它将不得不用matrix加法表示,这对人类来说更直观,但会使graphics卡比以前更加复杂。

现在,matrix乘法一般是不可交换的 ,所以当“添加”一个变换( 乘以matrix)时,需要指定是左乘还是右乘。 它的差别在于你的转换链接的顺序。通过右乘你的matrix(使用preRotate() ),你表明旋转步骤应该发生你刚才要求的所有其他转换之前 。 这可能是你想要的,但通常不是。

通常,这并不重要。 例如,如果你只有一个转换,它永远不会有问题:)有时候,你的转换可能以相同的效果发生,比如缩放和旋转 – 我的线性代数是生锈的,但我相信在这种情况下,matrix乘法实际上是可交换的,因为尺度matrix是对称的 ,也就是说,它跨过对angular线镜像自身。 但是,真的,想一想:如果我顺时针旋转一些图片10度,然后将其缩放到200%,看起来和我先缩放它然后旋转它一样。

如果你正在做一些怪异的复合转换,你会开始注意到一个差异。 我的build议是坚持使用postRotate()

我昨天回答了这个问题,但今天我觉得有些不妥,所以我在这里更正了答案:

 matrix: float[] values ={1.2f,0.5f,30,0.5f,1.2f,30,0,0,1}; //as we all know, the basic value in matrix,means no transformation added matrix2: float[] values2 ={1f,0,0,0,1f,0,0,0,1}; Let's say our matrix values are the values above. 

1,当我们做如下的转换:

 matrix.preTranslate(-50, -50); is equals to do sequence transformation to matrix2 above like below: matrix2.postTranslate(-50, -50); matrix2.postSkew(0.5f/1.2f,0.5f/1.2f);// note here matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 

2,当我们做如下的转换:

 matrix.preRotate(50); is equals to do sequence transformation to matrix2 like below: matrix2.postRotate(50); matrix2.postSkew(0.5f/1.2f,0.5f/1.2f); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 

3,当我们做如下的变换:

 matrix.preScale(1.3f,1.3f); is equals to do sequence transformation to matrix2 like below: matrix2.postScale(1.3f,1.3f); matrix2.postSkew(0.5f/1.2f,0.5f/1.2f); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 

4,当我们做如下的转换:

  matrix.preSkew(0.4f,0.4f); 

等同于对matrix2进行如下的序列转换:

  matrix2.postSkew(0.4f,0.4f); matrix2.postSkew(0.5f/1.2f,0.5f/1.2f); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 
 matrix: float[] values ={1.2f,0,30,0,1.2f,30,0,0,1}; matrix2: float[] values2 ={1f,0,0,0,1f,0,0,0,1}; 

假设我们的matrix值是上面的值。

  1. 当我们做如下的转换:

     matrix.preTranslate(-50, -50); 

    等同于对上面的matrix2进行序列转换,如下所示:

     matrix2.postTranslate(-50, -50); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 
  2. 当我们做如下的转换:

     matrix.preRotate(50); 

    等同于对matrix2进行如下的序列转换:

     matrix2.postRotate(50); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 
  3. 当我们做如下的转换:

     matrix.preScale(1.3f,1.3f); 

    等同于对matrix2进行如下的序列转换:

     matrix2.postScale(1.3f,1.3f); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 

然而,如果你的matrix之前旋转了(例如, {1.2f,-1f,30,-1f,1.2f,30,0,0,1}; ),那么它不像上面那么简单,因为当你旋转的时候,也同时缩放matrix。