Android: Matrix -> ¿cuál es la diferencia entre preconcat y postconcat?

Estoy usando Matrix para escalar y rotar Bitmaps. Ahora me pregunto cuál es la diferencia entre preconcat y postconcat, o más exactamente la diferencia entre:

  • Postratamiento
  • Pre-rotación
  • SetRotate

De lo que podría imaginar hasta ahora setRotate siempre sobrescribe toda la matriz, mientras que con preRotate y postRotate puedo aplicar múltiples cambios a una matriz (por ejemplo, escalado + rotación). Sin embargo, ya sea utilizando postRotate o preRotate no causó resultados diferentes para los casos que los usé.

La respuesta a su pregunta no es realmente específica para Android; Es una pregunta de gráficos y matemáticas. Hay mucha teoría en esta respuesta – ¡has sido advertido! Para una respuesta superficial a su pregunta, vaya a la parte inferior. Además, debido a que esta es una tirada tan larga, podría tener un error tipográfico o dos haciendo las cosas poco claras. Pido disculpas por adelantado si ese es el caso.

En gráficos por ordenador, podemos representar píxeles (o en 3D, vértices) como vectores. Si su pantalla es de 640×480, aquí hay un vector 2D para el punto en el centro de su pantalla (perdonar mi marcado shoddy):

[320] [240] [ 1] 

Voy a explicar por qué el 1 es importante más tarde. Las transformaciones a menudo se representan usando matrices porque es entonces muy simple (y muy eficiente) encadenarlas juntas, como usted mencionó. Para escalar el punto anterior por un factor de 1,5, puede multiplicarlo a la izquierda por la siguiente matriz:

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

Obtendrá este nuevo punto:

 [480] [360] [ 1] 

Que representa el punto original, con una escala de 1,5 en relación con la esquina de la pantalla (0, 0). Esto es importante: la escala siempre se hace con respecto al origen. Si desea escalar con algún otro punto como su centro (como el centro de un sprite), debe "ajustar" la escala en las traducciones hacia y desde el origen. Aquí está la matriz para traducir nuestro punto original al origen:

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

Cuyos rendimientos:

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

Reconocerá lo anterior como la matriz de identidad con las coordenadas de desplazamiento abofeteadas en la esquina superior derecha. Es por eso que el 1 (la "coordenada homogénea") es necesario: hacer espacio para estas coordenadas, haciendo así posible traducir usando multiplicación. De lo contrario, tendría que ser representado por la adición de matriz, que es más intuitiva para los seres humanos, pero haría tarjetas gráficas aún más complicado de lo que ya son.

Ahora bien, la multiplicación matricial generalmente no es conmutativa , por lo que al "sumar" una transformación ( multiplicando su matriz) es necesario especificar si se está multiplicando a la izquierda o multiplicando a la derecha. La diferencia que hace es en qué orden están encadenadas tus transformaciones. Mediante la multiplicación preRotate() tu matriz (usando preRotate() ) estás indicando que el paso de rotación debe ocurrir antes de todas las otras transformaciones que acabas de pedir. Esto puede ser lo que quieres, pero por lo general no lo es.

A menudo, no importa. Si solo tienes una transformación, por ejemplo, nunca importa 🙂 A veces, tus transformaciones pueden suceder en cualquier orden con el mismo efecto, como escalado y rotación – mi álgebra lineal está oxidada, pero creo que en este caso la La multiplicación de matriz es conmutativa porque la matriz de escala es simétrica , es decir, se refleja a sí misma a través de la diagonal. Pero en realidad, sólo pensar en ello: Si girar una imagen de 10 grados en el sentido de las agujas del reloj y luego la escala de 200%, se ve lo mismo que si me escalado en primer lugar, a continuación, lo giró.

Si estuvieras haciendo algunas transformaciones más extrañas de compuestos, empezarías a notar una discrepancia. Mi consejo es seguir con postRotate() .

He respondido a la pregunta de ayer, pero me siento sometiong equivocado hoy, Así que corregir la respuesta aquí:

 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, cuando hacemos la transformación como a continuación:

 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, cuando hacemos la transformación como a continuación:

 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, cuando hacemos la transformación como a continuación:

 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, cuando hacemos la transformación como a continuación:

  matrix.preSkew(0.4f,0.4f); 

Es igual a hacer la transformación de secuencia a matrix2 como a continuación:

  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}; 

Digamos que los valores de la matriz son los valores anteriores.

  1. Cuando hacemos la transformación como a continuación:

     matrix.preTranslate(-50, -50); 

    Es igual a hacer la transformación de secuencia a la matriz2 como se muestra a continuación:

     matrix2.postTranslate(-50, -50); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 
  2. Cuando hacemos la transformación como a continuación:

     matrix.preRotate(50); 

    Es igual a hacer la transformación de secuencia a matrix2 como a continuación:

     matrix2.postRotate(50); matrix2.postScale(1.2f, 1.2f); matrix2.postTranslate(30, 30); 
  3. Cuando hacemos la transformación como a continuación:

     matrix.preScale(1.3f,1.3f); 

    Es igual a hacer la transformación de secuencia a matrix2 como a continuación:

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

Sin embargo, si su matriz es rotada antes (por ejemplo, {1.2f,-1f,30,-1f,1.2f,30,0,0,1}; ), entonces no es tan simple como arriba porque cuando gira, También escaló la matriz al mismo tiempo.

  • DrawBitmap: ¿Cómo se pueden establecer coordenadas y utilizar una matriz?
  • Androide: ¿por qué devuelve la devolución de la matriz?
  • Obteniendo una imagen mediana de la secuencia de imágenes con OpenCV
  • Hacer una matriz para un efecto smuge / wobble (ver imágenes) en Android
  • ¿Cómo funciona Matrix.postScale (sx, sy, px, py)?
  • Distorsionar una imagen a un cuadrángulo falla en algunos casos en Android
  • ¿Cómo obtener el valor de zoom de la matriz arbitraria?
  • Multiplicación básica de matriz en OpenCV para Android
  • Android: aplica una transformación arbitraria a una vista
  • ¿Cómo obtengo una matriz en la que traducir, luego rotar, luego traducir y luego rotar una segunda vez?
  • Zoom y arrastrar una imagen en android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.