---
title: "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.

# Funciones

## 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.

```java
// 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"

## 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:

```java
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:

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

## 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 (π).

```java
// 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.

```java
// 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*).

## 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.

```java
// 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()`.

# Ejemplos

## 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:

```java
rect( 100, 100, 200, 100);
```

![](/img/rectangulo-blanco.png)

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:

```java
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:

```java
// 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();
```

![](/img/rectangulo-blanco-rotado.png)

# 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! :)
