Una matriz mueve, gira y escala una figura
Una transformación 2D mueve, gira o cambia de tamaño una figura aplicando la misma cuenta a cada uno de sus puntos. Con una matriz de 3 por 3 puedes hacer las tres cosas y encadenarlas.
Es lo que hace un programa de dibujo cuando arrastras o giras un objeto.
Al final de esta lección
Nota
Puedo mover, girar y escalar una figura con una matriz.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Traslación | mover todos los puntos la misma distancia |
| Escala | multiplicar las distancias al origen |
| Rotación | girar los puntos alrededor del origen |
| Matriz | una tabla de números en filas y columnas |
| Coordenadas homogéneas | el punto (x, y) escrito como (x, y, 1) |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Tres transformaciones básicas
Mover suma lo mismo a todas las x y a todas las y. Escalar multiplica las coordenadas. Girar cambia la dirección de cada punto alrededor del origen.
Cada una se escribe como una matriz de 3 por 3. Para poder mover con una multiplicación, el punto (x, y) se escribe como (x, y, 1): son las coordenadas homogéneas.
Ejemplo resuelto: tres matrices y su efecto
| Transformación | Filas de la matriz | Qué hace con (x, y) |
|---|---|---|
| Mover (5, 2) | [1, 0, 5], [0, 1, 2], [0, 0, 1] | Da (x + 5, y + 2) |
| Escalar por 3 | [3, 0, 0], [0, 3, 0], [0, 0, 1] | Da (3x, 3y) |
| Girar 90 grados | [0, -1, 0], [1, 0, 0], [0, 0, 1] | Da (-y, x) |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Aplica una matriz a un punto
# Mover el punto (4, 0) con la matriz de un movimiento de (5, 2).
matriz = [
[1, 0, 5],
[0, 1, 2],
[0, 0, 1],
]
x = 4
y = 0
nuevo_x = matriz[0][0] * x + matriz[0][1] * y + matriz[0][2]
nuevo_y = matriz[1][0] * x + matriz[1][1] * y + matriz[1][2]
print(nuevo_x, nuevo_y)
# Cambia la matriz por [[2, 0, 0], [0, 2, 0], [0, 0, 1]] para duplicar el tamaño.
Cada coordenada nueva sale de una fila
Para la x nueva, multiplicas la primera fila por (x, y, 1) y sumas: a * x + b * y + c. Para la y nueva, haces lo mismo con la segunda fila.
La tercera fila, [0, 0, 1], solo conserva el 1 final. Con una figura, repites la cuenta en cada vértice.
Mueve un triángulo con NumPy
docker exec jupyter python3 -c "import numpy as np; M = np.array([[1, 0, 5], [0, 1, 2], [0, 0, 1]]); P = np.array([[0, 4, 0], [0, 0, 3], [1, 1, 1]]); print(M @ P)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Cómo se lee el triángulo movido
Cada columna de P es un vértice: (0, 0), (4, 0) y (0, 3). El operador @ multiplica matrices.
Imprime tres filas: [5 9 5], [2 2 5] y [1 1 1]. Las columnas son los vértices nuevos: (5, 2), (9, 2) y (5, 5). El triángulo no ha cambiado de forma, solo de sitio.
Gira el punto (4, 0) noventa grados
docker exec jupyter python3 -c "import numpy as np; R = np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]]); print(R @ np.array([4, 0, 1]))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
El giro lleva (4, 0) a (0, 4)
Imprime [0 4 1]: el punto (4, 0) pasa a (0, 4). Sobre una gráfica con la y hacia arriba, el giro es contrario a las agujas del reloj. En una pantalla la y crece hacia abajo, así que el mismo giro parece ir a favor de ellas.
Los giros de otros ángulos usan seno y coseno. Con 90 grados salen solo 0, 1 y -1, y no hay decimales.
Importa el orden de las transformaciones
Para encadenar dos transformaciones se multiplican sus matrices. La matriz que está más cerca del punto actúa primero.
Con el punto (2, 1), escalar por 3 y luego mover (5, 2) da (11, 5). Mover primero y escalar después da (21, 9). No es lo mismo.
Ejemplo resuelto: dos órdenes, dos resultados
| Orden | Primer paso | Segundo paso |
|---|---|---|
| Escalar y luego mover | (2, 1) pasa a (6, 3) | (6, 3) pasa a (11, 5) |
| Mover y luego escalar | (2, 1) pasa a (7, 3) | (7, 3) pasa a (21, 9) |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Comprueba los dos órdenes
docker exec jupyter python3 -c "import numpy as np; T = np.array([[1, 0, 5], [0, 1, 2], [0, 0, 1]]); S = np.diag([3, 3, 1]); p = np.array([2, 1, 1]); print(T @ S @ p, S @ T @ p)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error muy común
Advertencia
Mucha gente cree que el orden de las transformaciones no importa, porque la suma sí lo permite. Con matrices no es así: escalar y mover no es lo mismo que mover y escalar. Escribe siempre qué pasa primero y pon esa matriz junto al punto.
Dibuja un triángulo y su copia movida
docker exec jupyter python3 -c "from PIL import Image, ImageDraw; im = Image.new('L', (100, 80), 255); d = ImageDraw.Draw(im); d.polygon([(10, 10), (50, 10), (10, 40)], outline=150); d.polygon([(40, 30), (80, 30), (40, 60)], outline=0); im.save('triangulos.png'); print(im.getpixel((10, 10)), im.getpixel((40, 30)), im.getpixel((50, 10)), im.getpixel((80, 30)), im.getpixel((90, 70)))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Para ir más lejos: abre los triángulos
El comando de la imagen guarda triangulos.png, de 100 por 80 píxeles. Ábrelo en JupyterLab desde la carpeta de trabajo.
Verás dos triángulos de contorno sobre blanco, uno gris arriba a la izquierda y otro negro más abajo y más a la derecha. Son iguales, y no se tocan. ¿Qué traslación lleva uno al otro?