Skip to content

Commit a7927ab

Browse files
Merge pull request steam-bell-92#1230 from KunwarSidhu47/main
Add Fourier Series Visualizer project to Math Lab
2 parents 0fdf545 + 4e1097a commit a7927ab

52 files changed

Lines changed: 450 additions & 4 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import math
2+
import sys
3+
import time
4+
5+
try:
6+
import numpy as np
7+
import matplotlib.pyplot as plt
8+
from matplotlib.animation import FuncAnimation
9+
except ImportError:
10+
print("❌ This project requires numpy and matplotlib.")
11+
print("Install them using: pip install numpy matplotlib")
12+
sys.exit(1)
13+
14+
15+
def main():
16+
print("=" * 58)
17+
print("📈 WELCOME TO FOURIER SERIES VISUALIZER 📈")
18+
print("=" * 58)
19+
print("Explore how complex waveforms can be approximated using harmonics.\n")
20+
21+
while True:
22+
print("=" * 58)
23+
print("Choose a waveform type:")
24+
print("1️⃣ Square Wave")
25+
print("2️⃣ Sawtooth Wave")
26+
print("3️⃣ Triangle Wave")
27+
print("4️⃣ Exit")
28+
29+
choice = input("🎯 Enter choice (1-4): ").strip()
30+
31+
if choice == "4":
32+
print("\n👋 Exiting... Keep exploring math!\n")
33+
break
34+
35+
if choice not in ["1", "2", "3"]:
36+
print("❌ Invalid choice. Please pick 1, 2, 3, or 4.\n")
37+
continue
38+
39+
waveform_type = {"1": "square", "2": "sawtooth", "3": "triangle"}[choice]
40+
41+
# Get number of harmonics
42+
while True:
43+
harmonics_in = input("📝 Enter number of harmonics (N) (1-50): ").strip()
44+
try:
45+
n_harmonics = int(harmonics_in)
46+
if n_harmonics < 1:
47+
print("⚠️ Enter a value greater than or equal to 1.")
48+
continue
49+
if n_harmonics > 50:
50+
print("⚠️ For performance, keep harmonics up to 50.")
51+
continue
52+
break
53+
except ValueError:
54+
print("⚠️ Invalid number. Try again.")
55+
56+
print(f"\n⏳ Simulating {waveform_type} wave with {n_harmonics} harmonics...")
57+
time.sleep(0.6)
58+
59+
print("\n🖥️ Opening animation window... Close it to return to menu.")
60+
61+
# Setup figure
62+
fig, ax = plt.subplots(figsize=(10, 5))
63+
ax.set_title(f"Fourier Series Approximation: {waveform_type.capitalize()} Wave (N={n_harmonics})")
64+
65+
# We'll draw circles on the left and the wave on the right
66+
ax.set_xlim(-3, 10)
67+
ax.set_ylim(-3, 3)
68+
ax.set_aspect('equal', adjustable='box')
69+
ax.grid(True, linestyle='--', alpha=0.5)
70+
71+
# Plot elements
72+
wave_line, = ax.plot([], [], color="#10b981", linewidth=2, label="Approximated Wave")
73+
connect_line, = ax.plot([], [], color="gray", linestyle="--", alpha=0.5)
74+
drawing_point, = ax.plot([], [], 'ro', markersize=4)
75+
76+
circles = []
77+
radii_lines = []
78+
for _ in range(n_harmonics):
79+
circle, = ax.plot([], [], color="blue", alpha=0.2)
80+
circles.append(circle)
81+
radius_line, = ax.plot([], [], color="blue", alpha=0.5)
82+
radii_lines.append(radius_line)
83+
84+
time_val = 0
85+
wave_data = []
86+
87+
def update(frame):
88+
nonlocal time_val, wave_data
89+
90+
x = 0
91+
y = 0
92+
93+
for i in range(n_harmonics):
94+
prev_x = x
95+
prev_y = y
96+
97+
n = 0
98+
radius = 0
99+
100+
if waveform_type == 'square':
101+
n = i * 2 + 1
102+
radius = (4 / (n * math.pi))
103+
elif waveform_type == 'sawtooth':
104+
n = i + 1
105+
radius = (2 * (-1)**(n + 1) / (n * math.pi))
106+
elif waveform_type == 'triangle':
107+
n = i * 2 + 1
108+
radius = (8 * (-1)**((n - 1) / 2) / ((n**2) * (math.pi**2)))
109+
110+
x += radius * math.cos(n * time_val)
111+
y += radius * math.sin(n * time_val)
112+
113+
# Draw circle
114+
circle_theta = np.linspace(0, 2*np.pi, 50)
115+
circles[i].set_data(prev_x + abs(radius)*np.cos(circle_theta),
116+
prev_y + abs(radius)*np.sin(circle_theta))
117+
118+
# Draw radius line
119+
radii_lines[i].set_data([prev_x, x], [prev_y, y])
120+
121+
wave_data.insert(0, y)
122+
if len(wave_data) > 300:
123+
wave_data.pop()
124+
125+
wave_x = np.linspace(3, 3 + len(wave_data) * 0.03, len(wave_data))
126+
wave_line.set_data(wave_x, wave_data)
127+
128+
connect_line.set_data([x, 3], [y, wave_data[0]])
129+
drawing_point.set_data([x], [y])
130+
131+
time_val += 0.03
132+
133+
# Matplotlib requires returning an iterable of updated artists
134+
return [wave_line, connect_line, drawing_point] + circles + radii_lines
135+
136+
ani = FuncAnimation(fig, update, frames=400, interval=20, blit=True)
137+
plt.show()
138+
139+
if __name__ == "__main__":
140+
main()

projects_registry.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,5 +602,21 @@
602602
"accuracy"
603603
],
604604
"path": "utilities/Typing-Speed-Tester/Typing-Speed-Tester.py"
605+
},
606+
{
607+
"name": "Fourier Series Visualizer",
608+
"emoji": "📈",
609+
"category": "math",
610+
"difficulty": "intermediate",
611+
"description": "Explore how complex waveforms can be approximated using harmonics.",
612+
"keywords": [
613+
"fourier",
614+
"series",
615+
"visualizer",
616+
"math",
617+
"wave",
618+
"harmonics"
619+
],
620+
"path": "math/Fourier-Series-Visualizer/Fourier-Series-Visualizer.py"
605621
}
606622
]
-2.94 KB
-4.03 KB
-3.52 KB
-3.31 KB
-3.18 KB
-3.17 KB
-2.28 KB

web-app/assets/banners/chess.webp

39.6 KB

0 commit comments

Comments
 (0)