Android:Matrix - > preconcat和postconcat有什么不同?

时间:2010-10-04 13:18:10

标签: android matrix

我正在使用Matrix缩放和旋转位图。现在我想知道preconcat和amp;之间有什么区别? postconcat是,或更准确地说是:

之间的区别

从我到目前为止可以看出,setRotate总是覆盖整个矩阵,而使用preRotate和postRotate我可以对矩阵应用多个更改(例如缩放+旋转)。但是,使用postRotate或preRotate对我使用它们的情况没有任何不同的结果。

2 个答案:

答案 0 :(得分:129)

您的问题的答案并非真正针对Android;这是一个图形和数学问题。在这个答案中有很多理论 - 你已经被警告了!如果您对问题的表面答案,请跳到底部。此外,因为这是一个冗长的长篇大论,我可能会有一两个错误的错误。如果是这样,我会提前道歉。

在计算机图形学中,我们可以将像素(或3D,顶点)表示为矢量。如果您的屏幕是640x480,这里是屏幕中间点的2D矢量(原谅我的伪劣标记):

[320]
[240]
[  1]

我会解释为什么1后来很重要。转换通常使用matrices来表示,因为将它们链接在一起非常简单(并且非常有效),就像您提到的那样。要将上面的点缩放1.5倍,您可以通过以下矩阵left-multiply

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

你会得到这个新观点:

[480]
[360]
[  1]

代表原始点,相对于屏幕一角(0,0)缩放1.5。这很重要:始终根据原点进行缩放。如果您想要将其他点作为中心进行缩放(例如精灵的中间),则需要将缩放比例“换行”到原点的转换中。这是将原始点转换为原点的矩阵:

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

哪个收益率:

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

您将识别上面的identity矩阵,其中位移坐标位于右上角。这就是为什么1(“同质坐标”)是必要的:为这些坐标腾出空间,从而可以使用乘法进行平移。否则它必须用矩阵加法来表示,这对人类来说更直观,但会使图形卡比现在更加复杂。

现在,矩阵乘法通常为isn't commutative,因此在“添加”变换时(通过乘以矩阵),您需要指定是左对乘还是右乘。它的不同之处在于你的变换的顺序是什么。通过右乘你的矩阵(使用preRotate())你指出旋转步骤应该发生之前所有其他变换你刚刚要求的。这可能是你想要的,但通常不是。

通常,没关系。例如,如果你只有一个变换,它永远不会重要:)有时,你的变换可以以任何顺序发生,具有相同的效果,例如缩放和旋转 - 我的线性代数生锈,但我相信在这种情况下矩阵乘法实际上是可交换的,因为比例矩阵是symmetric,也就是说,它在对角线上反射自身。但实际上,只要想一想:如果我将一些图片顺时针旋转10度然后将其缩放到200%,它看起来就像我先缩放它然后旋转它一样。

如果你正在做一些更奇怪的化合物转换,你会发现一个差异。我的建议是坚持postRotate()

答案 1 :(得分:4)

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

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.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);