jardínBit

Transformaciones

Las transformaciones nos permiten modificar la ubicación de nuestro origen de dibujo, la dimensiones de las medidas del canvas, y su rotación.

Estas modificaciones se acumulan, y pueden ser temporales.

1 Funciones

1.1 translate(dx, dy);

Traslada la posición del origen dx pixeles sobre el eje x, y dy pixeles sobre el eje y, respecto a la posición anterior.

Los dos argumentos son de tipo float, por lo que pueden tener puntos decimales, y pueden ser positivos o negativos.

// dibuja un cuadrado en el origen
rect(0, 0, 100, 100);

// traslada el origen 200 pixeles a la derecha
translate( 200, 0);

// dibuja un cuadrado con la misma función que antes
rect(0, 0, 100, 100);

// traslada el origen 200 pixeles hacia abajo de donde estaba
translate(0, 200);

// dibuja un cuadrado con la misma función que antes
rect(0, 0, 100, 100);

Nota que el tercer cuadrado queda debajo del segundo.

translate(0, 200); no significa “traslada el origen a las coordenadas originales 0, 200”, sino “traslada el origen 0 pixeles en x, y 200 pixeles hacia abajo en y, respecto a donde estaba antes”

1.2 scale( k );

Multiplica las unidades de medida actuales por un factor k de tipo float.

Si k es mayor a 1.0, la escala crece, si k es menor a 1.0 y mayor a 0.0, la escala decrece.

Por ejemplo, escala al doble:

scale( 2 ); // escala al doble
rect(0, 0, 100, 50); // este rectángulo medirá 200x100 en el marco de referencia original

O escala a la mitad:

scale( 0.5 ); // escala a la mitad
rect(0, 0, 100, 50); // este rectángulo medirá 50x25 en el marco de referencia original

1.3 rotate( a );

Rota el lienzo una cantidad de a radianes respecto a su posición actual, tomando como centro de rotación al origen.

Una vuelta completa son 2π radianes, que en Processing podemos escribir TWO_PI. También tenemos disponible la palabra clave PI para referirnos a media vuelta (π).

// rota PI/2 radianes (un cuarto de vuelta)
rotate( PI/2 );

Podemos rotar en grados usando la función radians( grados ), que convierte una cantidad de grados a su valor en radianes.

// rota 90° (un cuarto de vuelta)
rotate( radians( 90 ) );

Ángulos positivos rotan con las manecillas de reloj (clockwise) y ángulos negativos rotan en contra (counter clockwise).

1.4 Guarda y recupera matriz de transformaciones: pushMatrix(), popMatrix()

En ocasiones necesitaremos regresar al estado del canvas (técnicamente, al estado de su matriz de transformaciones) previo a ciertas transformaciones.

Una opción es revertir las transformaciones manualmente, pero puede ser confuso y con mucha posibilidad de error.

La opción recomendada es guardar (pushMatrix()) la matriz antes de aplicar transformaciones, y recuperarla (popMatrix()) cuando terminemos y queramos regresar a un estado previo.

// guardamos matriz original
pushMatrix();

// aplicamos algunas transformaciones
translate( 200, 200);
rotate( PI/3 );
// todo lo que dibujemos aquí va a estar transformado
rect(0,0, 100, 100);

// recuperamos matriz guardada
popMatrix();

// todo lo que dibujemos a continuación estará "normal":
rect(0, 0, 100, 100);

push y pop se refieren a operaciones de una “pila” (stack), como si fuera una pila de libros.

push es poner un libro hasta arriba, y pop es quitar el libro de hasta arriba.

Es posible utilizar múltiples pushMatrix() para guardar distintos estados de la matriz; solo hay que tener presente que tiene que haber un número correspondiente de popMatrix().

2 Ejemplos

2.1 Rotar alrededor de cierto punto en específico

El siguiente código dibuja un rectángulo con esquina superior izquierda en 100,100, un ancho de 200 y una altura de 100 pixeles:

rect( 100, 100, 200, 100);

Podemos calcular que su centro está en las coordenadas 200, 150. En términos de variables x, y, ancho y altura las coordenadas del centro las calculamos de la siguiente forma:

cx = x + ancho/2; // 300 = 100 + 200/2 
cy = y + altura/2; // 150 = 100 + 100/2

Para rotar al rectángulo usando ese centro como ubicación del eje de rotación, usamos la siguiente secuencia de transformaciones:

// guarda el origen
pushMatrix();

// traslada al punto/eje de rotación
translate( 200, 150);

// rota 45 grados clockwise
rotate( radians(45) );

// translada "de regreso":
translate( -200, -150);

// dibuja el rectángulo
rect( 100, 100, 200, 100);

// recupera el origen
popMatrix();

3 Consideraciones

El orden de las transformaciones importa.

Será distinto escalar y luego trasladar, que trasladar y luego escalar.

Será distinto trasladar y luego rotar, que rotar y luego trasladar.

¡Haz las pruebas e identifica las diferencias! :)