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é.
- Android: obtener la rotación actual de una matriz
- Necesidad de calcular el vector de rotación a partir de los datos de Sensor.TYPE_ORIENTATION
- Cómo escalar un mapa de bits de más de 4096 píxeles?
- Android Matrix multiplyMM en detalle
- Android obtener acelerómetros en el sistema de coordenadas de la tierra
- ¿Cómo aprender y usar OpenGL ES 2.0? Simplemente no lo entiendo - Qn serio.
- Cómo usar los datos del sensor onSensorChanged en combinación con OpenGL
- ¿Textura al revés? | OpenGL-ES 2.0 (Android)
- Problemas con la cámara OpenGL ES 2.0
- Sensor de Android: getRotationMatrix () devuelve valores erróneos, ¿por qué?
- Obtener el valor de rotación de matriz en android?
- ¿Cómo animar una matriz para "recortar" una imagen?
- Comprensión del uso de ImageView Matrix
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.
-
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);
-
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);
-
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.
- Cómo conectar Android Source a Eclipse
- No se puede emitir Proveedor de acciones para compartir el proveedor de acciones