Transformaciones Lineales en el Plano con Python.

Hola y bienvenidos una vez más a vuestro blog sobre programación en Python en el que, siguiendo con nuestra línea de artículos sobre simulaciones y aplicación de conceptos matemáticos, hoy hablaremos de las Transformaciones Lineales en el Plano con Python. Estas constituyen una de las herramientas más potentes del álgebra lineal, ya que permiten modificar un conjunto de puntos del plano aplicando operaciones como rotaciones, escalados, cizallamientos y reflexiones. Transformaciones, las cuales, representaremos mediante matrices y cuya aplicación se realiza mediante la multiplicación matricial. En este artículo exploraremos cómo usar Python, junto a las librerías Numpy y Matplotlib, para simular y visualizar dichas transformaciones lineales en 2D, utilizando figuras geométricas simples.

CONCEPTO MATEMÁTICO:

En matemáticas, una transformación lineal en el plano es una función que toma puntos de un espacio bidimensional y los mapea en otros puntos del mismo espacio, preservando la linealidad. Esto significa que las líneas rectas permanecen rectas y el origen (0, 0) se mantiene fijo. Una forma muy útil de representar este tipo de transformaciones es mediante matrices, específicamente matrices de 2×2 cuando se trabaja en el plano.

Esta transformación se define mediante una matriz:

Donde los valores a, b, c, y d, determinan la naturaleza de la transformación. Esta matriz actúa sobre un vector columna que representa un punto del plano:

De modo que podremos aplicar la transformación T al vector v mediante el producto matricial:

IMPLEMENTACIÓN EN PYTHON:

A continuación nos disponemos a aplicar este tipo de transformaciones en Python sobre los vértices de una figura cuadrada definida en un plano 2D valiéndonos de las librerías numpy (para definir la figura) y matplotlib (para su representación). Dichos vértices los definiremos en un array al que hemos dado el sencillo nombre de figura. En dicho array, definiremos dos veces el punto (0,0) para que la figure quede correctamente cerrada en la representación:

OUTPUT:

Esta es la figura sobre la que aplicaremos las transformaciones.

MATRIZ IDENTIDAD.

A continuación, partiendo de la teoría vista, iremos aplicando cada una de las siguientes transformaciones lineales: Rotación, reflexión, escalado y cizallamiento, no sin antes, hacer notar que las 4 matrices de transformación podrían considerarse versiones alteradas de la matriz identidad que multiplicada por cada vértice de la figura original, nos da, precisamente esa misma figura y en la misma posición y forma en el plano, sin producir ningún cambio (por algo la llamamos matriz identidad).

Matriz Identidad de 2 dimensiones.

Para comprobarlo, realizaremos la aplicación de esta matriz en código Python (ahora más adelante, explicaremos, mas en detalle, el código):

OUTPUT:

Como se ve, el resultado de la transformación (en rojo) coincide exactamente con la original que queda oculta tras ella.

Pasemos, ahora sí, a ver las distintas transformaciones. Empezando por la más compleja de ellas.

ROTACIÓN.

Para aplicar una rotación (de 45º en este caso) introduciremos algunas modificaciones en nuestro código. Siendo la primera de ellas, la definición de la matriz de rotación que crearemos usando la librería numpy:

Dado que nuestra intención es aplicar una rotación de 45º a nuestro cuadrado, aplicaremos las operaciones de seno y coseno sobre el resultado de dividir pi (obtenido con np.pi) por 4. Una vez definida la matriz de rotación deberemos multiplicarla por la que contiene los vertices de nuestra figura. Para ello definiremos una función transformar() que tomará como argumentos, ambas matrices y empleará el método .dot() para realizar dicha operación. Esta figura devolverá una nueva matriz con cada uno de los vértices de la figura original, transformados. Una vez definida, haremos la llamada a dicha función, pasándole las referidas matrices:

Una vez aplicada la transformación, pasaremos a su representación en el plano, con matplotlib, incluyendo ahora la figura resultante de la multiplicación de matrices:

OUTPUT:

Obtenemos así la representación de nuestra figura original junto a la versión rotada 45º, respecto al punto 0,0, de la misma. Para recapitular el código completo que hemos ejecutado sería el que sigue:

A continuación y para el resto de transformaciones, la explicación es muy sencilla, ya que basta con definir la concreta matriz de transformación que vamos a multiplicar por nuestra matriz original, dejando intacta la función de multiplicación. Modificando, eso si, la matriz transformada a representar gráficamente.

ESCALADO.

En este caso, nos disponemos a realizar cambios en la escala, tanto para el eje x (0.5) como para el eje y (de 0.5). Estos valores aplicados sobre la matriz original, dará como resultado una nueva figura mas achatada por el eje x y alargada por el eje y, con respecto a la original. De este modo el código quedaría así:

OUTPUT:

Si eligiéramos el mismo valor para ambos ejes (por ejemplo 1.5):

OUTPUT:

Obtendríamos una versión de mayor tamaño, a la original, pero guardando las mismas proporciones.

REFLEXIÓN.

Aplicamos esta transformación para obtener un reflejo de la figura original, en el eje x, y o en ambos, mediante el cambio de signo del valor 1 en el eje correspondiente de la matriz identidad. Así, si lo que queremos es generar una versión refleja de nuestra figura justo debajo de ella, realizaremos el cambio de signo (a negativo) del valor correspondiente al eje y:

OUTPUT:

CIZALLAMIENTO.

En la última transformación que vamos a ver, lo que hacemos es desplazar uno de los lados respecto al otro siguiendo uno de los ejes (el x en este caso) provocando una deformación respecto de la figura original. Para ello, simplemente cambiaremos el valor del 0 original de la matriz identidad. para dicho eje, tal y como se puede ver en el código:

OUTPUT:

CONCLUSIÓN:

En el presente artículo hemos visto, de forma muy gráfica, en que consisten y como pueden realizarse las distintas transformaciones lineales en un plano 2D, utilizando el lenguaje Python. A partir de este punto, el lector puede probar a combinar más de una transformación, empleando una misma matriz, e ir comprobando el resultado en la gráfica. Lo que sin duda le ayudará a entender la naturaleza y aplicación de este interesante concepto matemático.

Saludos.

Generando Curvas de Bézier en Python.

Las curvas de Bézier son herramientas matemáticas fundamentales para representar formas y trayectorias suaves en gráficos por computadora, diseño vectorial, animación y muchas otras aplicaciones. Estas curvas, definidas mediante un conjunto de puntos de control, ofrecen una manera intuitiva y flexible de modelar trayectorias y superficies, permitiendo una manipulación precisa y creativa de las formas. En el presente artículo aprenderemos cómo crear una curva de Bézier en Python utilizando las bibliotecas ‘numpy‘ y ‘matplotlib‘, valiéndonos de un sencillo ejemplo práctico para graficarlas en un espacio tridimensional (3D).

1)Introducción a las Curvas de Bézier.

Para empezar, diremos que una curva de Bézier de grado ‘n‘ es una curva paramétrica definida por un conjunto de puntos de control (concretamente ‘n’ + 1) los cuales son denotados como P0​,P1​,…,Pn‘. Siendo dicha curva, una combinación ponderada de dichos puntos, de modo que su forma es influenciada directamente por su disposición. A continuación mostramos una representación bidimensional de como se construyen estas curvas:

Creación de una curva de Bezier Cuadrática (de grado 2). Los valores de ‘t’ se mueven de 0 a 1.
Curva de Bézier de grado 4.

Generalizando, la curva de Bézier puede expresarse con la siguiente fórmula matemática:

2)Implementación en Python.

Una vez explicado someramente en que consisten las Curvas de Bezier, pasaremos, tal y como adelantamos en el primer apartado, a ver como generarlas utilizando Python y las librerías ‘numpy‘ y ‘matplotlib‘, las cuales, deberemos tener instaladas en nuestro equipo:

Una vez que tengamos ambas disponibles en nuestro sistema, pasaremos a crear un nuevo archivo ‘.py’ en el que empezaremos importando ambas librerías. Tras ello procederemos a generar tres arreglos aleatoriamente de tamaño 3 (ya que vamos a requerir 3 puntos de control), utilizando ‘np.random.random_sample((3,))‘, los cuales representarán las coordenadas ‘x‘, ‘y‘ y ‘z‘ (incluimos esta ultima dado que nuestra representación será tridimensional). De ese modo, la variable ‘x‘ contendrá el valor en dicho eje de cada uno de los puntos, sucediendo o mismo con las otras variables ‘y‘ y ‘z‘ :

Tras ello, pasaremos a definir las variables que vamos a necesitar para realizar el cálculo matemático de nuestra curva, tales como el numero de puntos de control (‘nCPTS‘), el número de puntos que contendrá la curva (‘CELLS‘), el número de segmentos de la curva (‘n‘) y que afectará a la suavidad de la misma, el arreglo que representa la variable paramétrica (entre 0 y 1) que usaremos para evaluar la curva (‘t‘), la lista que contendrá las funciones base de ‘Bernstein‘ (‘B‘) y finalmente las variables ‘xBezier‘, ‘yBezier’ y ‘zBezier‘ en donde se almacenarán las coordenadas de los puntos en la curva de Bezier calculada:

Una vez definidas las variables necesarias, pasaremos a definir las funciones encargadas de realizar las operaciones matemáticas encargadas de obtener las coordenadas de los puntos que conformarán la curva:

Como puede verse, en este fragmento de código se efectúa el calculo de los puntos de una curva de Bézier utilizando las funciones base de Bernstein. Aquí, la función ‘Ni()‘ calcula el coeficiente binomial, que es una parte esencial de dichas funciones para un índice ‘i‘ y un grado ‘n‘. Luego, la función ‘basisFunction()‘ utiliza dicho coeficiente para calcular la función base de Bernstein, que determina la influencia de cada punto de control en la curva para diferentes valores del parámetro ‘t‘ (que, recordemos, varía de 0 a 1). Finalmente un bucle ‘for‘ itera sobre cada punto de control, calculando su función base con ‘basisFunction()‘, para, a continuación, actualizar las coordenadas de la curva (‘xBezier‘, ‘yBezier‘ y ‘zBezier‘) sumando la contribución de cada punto de control ponderado por su función base. En dicho ciclo, el índice ‘i‘ se incrementa en cada iteración para calcular la siguiente función base.

Y con ello ya tendríamos definidos los 100 puntos que conformarán nuestra curva, ahora solo nos resta el utilizar la librería ‘matplotlib‘ para visualizar el resultado en la correspondiente gráfica especificando la proyección en 3D:

OUTPUT:

CONCLUSION:

Como se ve, implementar curvas de Bézier en Python, es un proceso accesible gracias a bibliotecas como ‘numpy‘ y ‘matplotlib‘, lo que permite a los desarrolladores y diseñadores experimentar con estas técnicas de manera efectiva para aplicaciones prácticas.

En el siguiente enlace podéis ver el código completo de este artículo:

https://github.com/antonioam82/ejercicios-python/blob/master/bezier.py

Saludos.