Coge una cadena de círculos, haz que cada uno gire sobre la punta del anterior a su propia velocidad y fíjate en la punta del último: puede dibujar un corazón, una estrella o tu firma. No es un truco de ilustrador, sino una de las ideas más útiles de las matemáticas: la transformada de Fourier, la que dice que cualquier forma (o cualquier sonido) se puede descomponer en movimientos circulares sencillos. Aquí la verás funcionar con tus propios dibujos.
De los planetas a la fórmula de Fourier
La idea de explicar un movimiento complicado con círculos que giran sobre otros círculos tiene más de dos mil años. Los astrónomos griegos, de Apolonio de Perga a Hiparco y, sobre todo, Claudio Ptolomeo, la usaron para explicar por qué los planetas a veces parecen ir hacia atrás en el cielo: cada planeta giraba en un círculo pequeño, el epiciclo, cuyo centro giraba a su vez en uno grande alrededor de la Tierra. El modelo estaba equivocado sobre lo que pasa en el cielo, pero acertaba en algo: con suficientes círculos se puede imitar casi cualquier recorrido.
La explicación de por qué llegó en 1822, cuando Joseph Fourier publicó Théorie analytique de la chaleur. Estudiando cómo se reparte el calor en un objeto, Fourier sostuvo que cualquier función que se repite se puede escribir como una suma de ondas simples, senos y cosenos, de frecuencias cada vez más altas. Un círculo que gira es justo eso, una onda seno en horizontal y otra en vertical a la vez, así que los epiciclos de Ptolomeo eran, sin saberlo, una serie de Fourier.
Un círculo que gira son tres números
Para describir un círculo que gira basta con tres datos: su radio; el ángulo en el que empieza, que se llama fase, y cuántas vueltas da mientras se dibuja la figura una vez, la frecuencia k. Con k = 1 da una vuelta; con k = 2, dos; con k = −1, una vuelta en sentido contrario.
Los matemáticos lo escriben con un solo número complejo, c, cuyo tamaño es el radio y cuyo ángulo es la fase. La posición de la punta en cada instante t, de 0 a 1, es c · e2πikt: la fórmula de Euler convierte esa exponencial en un punto que da k vueltas al círculo. No hace falta dominar los números complejos para seguir el artículo: basta con pensar en cada círculo como una flecha que gira.
De la figura a los círculos
¿Cómo se saben los círculos que dibujan una figura concreta? Ese es el trabajo de la transformada discreta de Fourier. Los pasos son cuatro:
- Se recorre la figura y se toman 256 puntos a la misma distancia unos de otros. Cada punto se trata como un número complejo: la x es la parte real y la y, la imaginaria.
- Para cada frecuencia k, de −128 a 127, se calcula ck = (1/256) · Σ zj · e−2πikj/256. Es como hacer girar la figura en sentido contrario k veces y ver qué queda de media: si la figura tiene algo que gira a esa velocidad, sobrevive; si no, se cancela.
- Cada ck es un círculo: su radio es el tamaño de ck, su fase es su ángulo y da k vueltas. El de k = 0 no gira: es el centro de la figura, de donde sale la cadena.
- Se ordenan de mayor a menor y se encadenan. Con los 255 círculos, la punta pasa exactamente por los 256 puntos; con menos, se queda con lo esencial de la forma.
Lo bonito es que funciona igual para cualquier figura cerrada: no hay que diseñar nada a mano.
Pruébalo
Elige una figura o pulsa «Dibuja la tuya» y traza algo en el recuadro, con el dedo o el ratón, sin levantarlo. Luego mueve el control de «Círculos»: con 1 solo sale un círculo, con 5 aparece la forma general y con 50 el dibujo es casi perfecto. La figura original se ve en gris claro, debajo; la línea azul es lo que llevan dibujado los círculos, y el punto rojo, la punta de la cadena. El error medio que aparece debajo mide cuánto se aleja el dibujo de la figura.
Fíjate en la estrella: necesita bastantes más círculos que el corazón para que sus puntas salgan afiladas. Las esquinas son cambios bruscos de dirección, y para hacer un cambio brusco hacen falta círculos que giren muy deprisa. Con un garabato propio pasa lo mismo, y además verás que el punto rojo cruza en línea recta desde el final de tu trazo hasta el principio: la serie de Fourier siempre dibuja una figura cerrada.
Lo que enseña un cuadrado
El cuadrado es el mejor ejemplo para ver qué hace cada círculo. Con uno solo sale el círculo que mejor se le ajusta; con dos ya se adivinan las cuatro esquinas, y con ocho la diferencia apenas se ve:
Este programa hace el cálculo completo en Python, sin bibliotecas: reparte 256 puntos por el borde del cuadrado, calcula sus 256 coeficientes y mide el error al redibujarlo con cada vez más círculos.
"""Epiciclos de Fourier: dibujar un cuadrado con círculos que giran.
Se toman 256 puntos repartidos por el borde del cuadrado, se calcula su transformada
discreta de Fourier y cada coeficiente se convierte en un círculo: su radio es el
módulo del coeficiente, su velocidad, la frecuencia k, y su ángulo inicial, la fase.
"""
import cmath
import math
N = 256
def cuadrado(n):
"""n puntos a la misma distancia unos de otros por el borde de un cuadrado de lado 2."""
esquinas = [complex(1, 1), complex(-1, 1), complex(-1, -1), complex(1, -1)]
puntos = []
for i in range(n):
s = 4 * i / n # recorrido: 0 a 4, un lado por unidad
lado, f = int(s), s - int(s)
a, b = esquinas[lado], esquinas[(lado + 1) % 4]
puntos.append(a + (b - a) * f)
return puntos
def dft(z):
"""Coeficientes c_k de la serie, con k de -n/2 a n/2 - 1."""
n = len(z)
return {k: sum(z[j] * cmath.exp(-2j * math.pi * k * j / n) for j in range(n)) / n
for k in range(-n // 2, n // 2)}
def epiciclos(c, cuantos, t):
"""Punto que dibujan el centro (k = 0) y los `cuantos` círculos más grandes en el instante t (0 a 1)."""
orden = sorted((k for k in c if k != 0), key=lambda k: -abs(c[k]))[:cuantos]
return c[0] + sum(c[k] * cmath.exp(2j * math.pi * k * t) for k in orden)
z = cuadrado(N)
c = dft(z)
print("Los 8 círculos más grandes:")
print(" k radio fase radio × k²")
for k in sorted((k for k in c if k != 0), key=lambda k: -abs(c[k]))[:8]:
print(f"{k:5d} {abs(c[k]):.4f} {math.degrees(cmath.phase(c[k])):5.1f}° {abs(c[k]) * k * k:.4f}")
print()
print("Error medio al redibujar el cuadrado (lado 2):")
for cuantos in (1, 2, 4, 8, 16, 32, 64, 255):
error = sum(abs(epiciclos(c, cuantos, j / N) - z[j]) for j in range(N)) / N
print(f"{cuantos:4d} círculo{'s' if cuantos > 1 else ''}: {error:.4f}")
# ¿Cuántos círculos tienen un radio que no sea prácticamente cero?
print()
print("Círculos que cuentan:", sum(1 for k in c if k != 0 and abs(c[k]) > 1e-9), "de", N - 1)salidaLos 8 círculos más grandes:
k radio fase radio × k²
1 1.1464 45.0° 1.1464
-3 0.1274 45.0° 1.1468
5 0.0459 45.0° 1.1478
-7 0.0235 45.0° 1.1491
9 0.0142 45.0° 1.1510
-11 0.0095 45.0° 1.1533
13 0.0068 45.0° 1.1561
-15 0.0052 45.0° 1.1594
Error medio al redibujar el cuadrado (lado 2):
1 círculo: 0.1317
2 círculos: 0.0500
4 círculos: 0.0170
8 círculos: 0.0055
16 círculos: 0.0017
32 círculos: 0.0006
64 círculos: 0.0000
255 círculos: 0.0000
Círculos que cuentan: 64 de 255La salida esconde dos sorpresas. La primera: de los 255 círculos posibles, solo 64 tienen un radio que no es cero, los de k = 1, −3, 5, −7, 9…, y por eso con 64 círculos el error ya es nulo. Es consecuencia de la simetría: si giras el cuadrado un cuarto de vuelta, queda igual, y eso anula todas las demás frecuencias. La segunda: el radio de cada círculo es el del primero dividido entre k², como muestra la última columna. En un cuadrado perfecto, el radio vale exactamente 8√2 / (π² · k²), es decir, 1.1463 / k²; con 256 puntos los valores se separan un poco en los círculos más pequeños.
Hemos comprobado que la animación de arriba hace exactamente estas cuentas: en el cuadrado, sus coeficientes coinciden con los del programa en las 16 primeras cifras decimales, y en otras 53 figuras, las de ejemplo y 50 garabatos al azar, coinciden con los de NumPy con una diferencia máxima de menos de una billonésima.
Por qué todo el mundo usa la transformada de Fourier
Dibujar con círculos es la versión visual, pero la misma operación está en todas partes. Un sonido es una onda que se repite, y su transformada de Fourier dice qué frecuencias, qué notas, lo componen: es lo que muestran los ecualizadores y los afinadores. En las imágenes, el formato JPEG usa una prima cercana, la transformada discreta del coseno, para separar en cada bloque de 8 × 8 píxeles los cambios suaves de los detalles finos, y guardar con menos precisión los detalles que el ojo apenas nota.
Todo eso sería lentísimo con el método de este artículo, que hace 256 × 256 = 65,536 multiplicaciones para 256 puntos. En 1965, James Cooley y John Tukey publicaron la transformada rápida de Fourier (FFT), que obtiene el mismo resultado con del orden de N · log₂N operaciones: unas 2,048 para 256 puntos, y para un millón de puntos, unos 20 millones en lugar de un billón. Es la versión que usa NumPy, y una de las razones por las que el audio, las imágenes y las comunicaciones digitales funcionan en tiempo real.
Si te gustan los algoritmos que se entienden mejor viéndolos, tenemos más con animación: el algoritmo de Myers con el que Git encuentra las diferencias entre dos archivos, el juego del caos, que dibuja fractales con puntos al azar, y los boids, que imitan una bandada de pájaros con tres reglas.
Fuentes: J. Fourier, Théorie analytique de la chaleur (París, Didot, 1822); J. W. Cooley y J. W. Tukey, «An algorithm for the machine calculation of complex Fourier series», Mathematics of Computation 19, 297–301 (1965); la norma de JPEG, ITU-T T.81; la historia de los epiciclos, en Wikipedia. La animación de los círculos que dibujan figuras la popularizó 3Blue1Brown en su vídeo «But what is a Fourier series?» (2019). El programa se ejecutó con Python 3.13 y la comparación, con NumPy 2.3.4 y Node.js 24. La animación y las imágenes, incluida la portada, las generan los propios círculos: decodigo.com.
