fork download
  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. from matplotlib.animation import FuncAnimation
  4.  
  5. def get_fourier_coefficients(points):
  6. """Transform spatial points into Fourier coefficients (DFT)."""
  7. N = len(points)
  8. # Convert points to complex numbers (x + iy)
  9. z = np.array([complex(p[0], p[1]) for p in points])
  10. # Compute the coefficients
  11. coeffs = np.fft.fft(z) / N
  12. return coeffs
  13.  
  14. def animate_fourier(points, num_circles=None):
  15. coeffs = get_fourier_coefficients(points)
  16. N = len(coeffs)
  17.  
  18. # Sort coefficients by frequency magnitude (largest circles first)
  19. # This makes the animation look much more organized
  20. freqs = np.fft.fftfreq(N, 1/N)
  21. indices = np.argsort(np.abs(coeffs))[::-1]
  22. if num_circles:
  23. indices = indices[:num_circles]
  24.  
  25. sorted_coeffs = coeffs[indices]
  26. sorted_freqs = freqs[indices]
  27.  
  28. fig, ax = plt.subplots(figsize=(8, 8))
  29. ax.set_aspect('equal')
  30. ax.set_xlim(np.min(points[:,0])-50, np.max(points[:,0])+50)
  31. ax.set_ylim(np.min(points[:,1])-50, np.max(points[:,1])+50)
  32.  
  33. line, = ax.plot([], [], color='orange', lw=2) # The path being traced
  34. circles = [ax.plot([], [], 'b-', alpha=0.3)[0] for _ in range(len(sorted_coeffs))]
  35. trace_x, trace_y = [], []
  36.  
  37. def update(t):
  38. # t goes from 0 to 1
  39. current_z = 0 + 0j
  40. prev_z = 0 + 0j
  41.  
  42. for i, (c, f) in enumerate(zip(sorted_coeffs, sorted_freqs)):
  43. prev_z = current_z
  44. # The heart of Fourier: sum of c * e^(i * 2pi * f * t)
  45. current_z += c * np.exp(2j * np.pi * f * t)
  46.  
  47. # Update circle visuals
  48. radius = np.abs(c)
  49. theta = np.linspace(0, 2*np.pi, 50)
  50. circles[i].set_data(prev_z.real + radius*np.cos(theta),
  51. prev_z.imag + radius*np.sin(theta))
  52.  
  53. trace_x.append(current_z.real)
  54. trace_y.append(current_z.imag)
  55. line.set_data(trace_x, trace_y)
  56. return [line] + circles
  57.  
  58. ani = FuncAnimation(fig, update, frames=np.linspace(0, 1, N), interval=20, blit=True)
  59. plt.show()
  60.  
  61. # --- Example: Hand-drawn "Bird-ish" Shape ---
  62. # Replace this with SVG path data parsed into a numpy array
  63. t = np.linspace(0, 2*np.pi, 100)
  64. x = 100 * (np.cos(t) + 0.5 * np.cos(2*t))
  65. y = 100 * (np.sin(t) - 0.5 * np.sin(2*t))
  66. bird_points = np.column_stack((x, y))
  67.  
  68. animate_fourier(bird_points, num_circles=50)
Success #stdin #stdout #stderr 3.67s 70420KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
Fontconfig error: No writable cache directories