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ícate

NumPy 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
Empezar curso de Numpy

Lecciones de este módulo de Numpy

Lecciones de programación del módulo Geometría del curso de Numpy.