Numpy: Geometría
Descubre cómo NumPy se convierte en una herramienta fundamental para cálculos geométricos en Python. Aprende a trabajar con vectores, matrices de transformación, cálculos de distancias, ángulos y proyecciones para resolver problemas geométricos complejos
Aprende Numpy GRATIS y certifícateNumPy ofrece estructuras de datos y funciones optimizadas para realizar cálculos geométricos con gran eficiencia. Gracias a sus arrays n-dimensionales y operaciones vectorizadas, podemos representar y manipular entidades geométricas como puntos, vectores, rectas y planos de manera intuitiva y computacionalmente eficiente.
La geometría computacional es esencial en campos como la visión por computador, gráficos 3D, robótica y análisis de datos espaciales. NumPy nos proporciona las herramientas necesarias para implementar estos cálculos de forma sencilla y eficiente.
Trabajando con vectores en el espacio
Los vectores son los elementos básicos en geometría computacional. En NumPy, podemos representarlos como arrays unidimensionales:
import numpy as np
# Crear vectores en 2D y 3D
vector_2d = np.array([3, 4])
vector_3d = np.array([1, 2, 3])
# Calcular la magnitud (norma) de un vector
magnitud_2d = np.linalg.norm(vector_2d)
magnitud_3d = np.linalg.norm(vector_3d)
print(f"Magnitud del vector 2D: {magnitud_2d}")
print(f"Magnitud del vector 3D: {magnitud_3d}")
La normalización de vectores (obtener un vector unitario en la misma dirección) es una operación común:
# Normalizar vectores
vector_2d_normalizado = vector_2d / np.linalg.norm(vector_2d)
vector_3d_normalizado = vector_3d / np.linalg.norm(vector_3d)
print(f"Vector 2D normalizado: {vector_2d_normalizado}")
print(f"Magnitud del vector normalizado: {np.linalg.norm(vector_2d_normalizado)}")
Productos vectoriales y escalares
El producto escalar (o producto punto) nos permite calcular el ángulo entre vectores y realizar proyecciones:
# Definir dos vectores
v1 = np.array([1, 2, 3])
v2 = np.array([4, 5, 6])
# Producto escalar (dot product)
producto_escalar = np.dot(v1, v2)
print(f"Producto escalar: {producto_escalar}")
# Calcular el ángulo entre los vectores (en radianes)
coseno_angulo = np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))
angulo = np.arccos(coseno_angulo)
print(f"Ángulo entre vectores (radianes): {angulo}")
print(f"Ángulo entre vectores (grados): {np.degrees(angulo)}")
El producto vectorial (o producto cruz) es exclusivo para vectores tridimensionales y nos da un vector perpendicular a los dos vectores originales:
# Producto vectorial (cross product) - solo para vectores 3D
producto_vectorial = np.cross(v1, v2)
print(f"Producto vectorial: {producto_vectorial}")
# Verificar que el producto vectorial es perpendicular a ambos vectores originales
print(f"¿Es perpendicular a v1? {np.isclose(np.dot(producto_vectorial, v1), 0)}")
print(f"¿Es perpendicular a v2? {np.isclose(np.dot(producto_vectorial, v2), 0)}")
Proyecciones vectoriales
Las proyecciones son útiles para descomponer vectores y calcular distancias entre puntos y rectas:
# Proyección de v1 sobre v2
proyeccion_escalar = np.dot(v1, v2) / np.linalg.norm(v2)
vector_proyeccion = (np.dot(v1, v2) / np.dot(v2, v2)) * v2
print(f"Proyección escalar de v1 sobre v2: {proyeccion_escalar}")
print(f"Vector proyección de v1 sobre v2: {vector_proyeccion}")
# Componente perpendicular
componente_perpendicular = v1 - vector_proyeccion
print(f"Componente perpendicular: {componente_perpendicular}")
Distancias en geometría
El cálculo de distancias es fundamental en problemas geométricos. NumPy ofrece varias formas de calcularlo:
# Distancia entre dos puntos
punto1 = np.array([1, 2, 3])
punto2 = np.array([4, 5, 6])
# Método 1: Usando la norma de la diferencia
distancia = np.linalg.norm(punto2 - punto1)
print(f"Distancia entre puntos: {distancia}")
# Método 2: Usando la función de distancia de NumPy
from scipy.spatial import distance
distancia_scipy = distance.euclidean(punto1, punto2)
print(f"Distancia usando SciPy: {distancia_scipy}")
La distancia de un punto a una recta en 3D requiere el uso del producto vectorial:
# Distancia de un punto a una recta en 3D
# La recta está definida por un punto p0 y un vector director v
punto = np.array([1, 2, 3])
punto_recta = np.array([0, 0, 0]) # Un punto en la recta
vector_director = np.array([1, 1, 1]) # Vector director normalizado
vector_director = vector_director / np.linalg.norm(vector_director)
# Vector desde el punto en la recta hasta el punto dado
vector_punto = punto - punto_recta
# Componente perpendicular
componente_perpendicular = vector_punto - np.dot(vector_punto, vector_director) * vector_director
distancia_a_recta = np.linalg.norm(componente_perpendicular)
print(f"Distancia del punto a la recta: {distancia_a_recta}")
Matrices de transformación geométrica
Las transformaciones geométricas como traslaciones, rotaciones y escalados son esenciales en gráficos por computador y visión artificial. En NumPy podemos representarlas como matrices:
# Matrices de transformación 2D
# Matriz de rotación (ángulo en radianes)
def matriz_rotacion_2d(angulo):
"""Crea una matriz de rotación 2D para el ángulo dado en radianes."""
return np.array([
[np.cos(angulo), -np.sin(angulo)],
[np.sin(angulo), np.cos(angulo)]
])
# Rotar un punto 45 grados
punto = np.array([1, 0])
angulo = np.radians(45)
matriz_rot = matriz_rotacion_2d(angulo)
punto_rotado = np.dot(matriz_rot, punto)
print(f"Punto original: {punto}")
print(f"Punto rotado 45°: {punto_rotado}")
Para transformaciones en 3D, necesitamos matrices tridimensionales:
# Matrices de rotación 3D
def matriz_rotacion_x(angulo):
"""Matriz de rotación alrededor del eje X."""
return np.array([
[1, 0, 0],
[0, np.cos(angulo), -np.sin(angulo)],
[0, np.sin(angulo), np.cos(angulo)]
])
def matriz_rotacion_y(angulo):
"""Matriz de rotación alrededor del eje Y."""
return np.array([
[np.cos(angulo), 0, np.sin(angulo)],
[0, 1, 0],
[-np.sin(angulo), 0, np.cos(angulo)]
])
def matriz_rotacion_z(angulo):
"""Matriz de rotación alrededor del eje Z."""
return np.array([
[np.cos(angulo), -np.sin(angulo), 0],
[np.sin(angulo), np.cos(angulo), 0],
[0, 0, 1]
])
# Rotación de un punto 3D alrededor del eje Z
punto_3d = np.array([1, 0, 0])
angulo = np.radians(90)
punto_rotado_3d = np.dot(matriz_rotacion_z(angulo), punto_3d)
print(f"Punto 3D original: {punto_3d}")
print(f"Punto 3D rotado 90° alrededor del eje Z: {punto_rotado_3d}")
Coordenadas homogéneas para transformaciones afines
Las coordenadas homogéneas nos permiten representar traslaciones junto con rotaciones y escalados en una sola matriz:
# Transformación afín en coordenadas homogéneas
def matriz_traslacion_2d(tx, ty):
"""Crea una matriz de traslación 2D en coordenadas homogéneas."""
return np.array([
[1, 0, tx],
[0, 1, ty],
[0, 0, 1]
])
def matriz_rotacion_2d_homogenea(angulo):
"""Crea una matriz de rotación 2D en coordenadas homogéneas."""
c, s = np.cos(angulo), np.sin(angulo)
return np.array([
[c, -s, 0],
[s, c, 0],
[0, 0, 1]
])
# Punto en coordenadas homogéneas
punto_homogeneo = np.array([2, 3, 1]) # El tercer componente es 1 para puntos
# Aplicar una traslación seguida de una rotación
matriz_traslacion = matriz_traslacion_2d(1, 2)
matriz_rotacion = matriz_rotacion_2d_homogenea(np.radians(45))
# Combinar transformaciones (primero traslación, luego rotación)
matriz_combinada = np.dot(matriz_rotacion, matriz_traslacion)
punto_transformado = np.dot(matriz_combinada, punto_homogeneo)
print(f"Punto original (homogéneo): {punto_homogeneo}")
print(f"Punto transformado: {punto_transformado}")
print(f"En coordenadas cartesianas: {punto_transformado[:2] / punto_transformado[2]}")
Operaciones con polígonos y formas geométricas
NumPy facilita el trabajo con polígonos y otras formas geométricas:
# Representar un polígono como un array de puntos
triangulo = np.array([
[0, 0], # Vértice 1
[1, 0], # Vértice 2
[0.5, 1] # Vértice 3
])
# Calcular el centro del polígono
centro = np.mean(triangulo, axis=0)
print(f"Centro del triángulo: {centro}")
# Calcular el área de un triángulo usando la fórmula del producto cruzado
def area_triangulo(vertices):
"""Calcula el área de un triángulo dados sus tres vértices."""
# Convertir a 3D para usar producto cruzado
v1 = np.append(vertices[1] - vertices[0], 0)
v2 = np.append(vertices[2] - vertices[0], 0)
producto = np.cross(v1, v2)
return np.linalg.norm(producto) / 2
area = area_triangulo(triangulo)
print(f"Área del triángulo: {area}")
Para polígonos más complejos, podemos descomponerlos en triángulos:
# Calcular el área de un polígono convexo
def area_poligono(vertices):
"""Calcula el área de un polígono convexo dado como array de vértices."""
n = len(vertices)
area = 0.0
# Usar la fórmula del área de Gauss (o fórmula del zapato)
for i in range(n):
j = (i + 1) % n
area += vertices[i, 0] * vertices[j, 1]
area -= vertices[j, 0] * vertices[i, 1]
return abs(area) / 2.0
# Ejemplo con un cuadrado
cuadrado = np.array([
[0, 0],
[1, 0],
[1, 1],
[0, 1]
])
area_cuadrado = area_poligono(cuadrado)
print(f"Área del cuadrado: {area_cuadrado}")
Cálculos con círculos y esferas
NumPy es también útil para operaciones con figuras curvas como círculos y esferas:
# Definir un círculo (centro y radio)
centro_circulo = np.array([2, 3])
radio_circulo = 2.5
# Verificar si un punto está dentro del círculo
punto_prueba = np.array([3, 4])
distancia_al_centro = np.linalg.norm(punto_prueba - centro_circulo)
dentro_del_circulo = distancia_al_centro <= radio_circulo
print(f"¿El punto {punto_prueba} está dentro del círculo? {dentro_del_circulo}")
# Generar puntos en un círculo
t = np.linspace(0, 2*np.pi, 100)
puntos_circulo = np.zeros((100, 2))
puntos_circulo[:, 0] = centro_circu
Lecciones de este módulo de Numpy
Lecciones de programación del módulo Geometría del curso de Numpy.