Create stunning mathematical art using complex parametric equations, trigonometry, and advanced animation techniques
Mathematics and art have been connected for centuries. From the golden ratio in classical architecture to the fractal patterns in nature, mathematical relationships create some of the most beautiful designs we see. In this lesson, we'll use advanced parametric equations to create stunning visual art that flows and evolves in real-time.
Parametric equations allow us to describe complex curves and patterns by expressing x and y coordinates as functions of a parameter (usually time). By combining multiple trigonometric functions with different frequencies and phases, we can create intricate, organic-looking patterns that seem to dance across the screen.
Instead of y = f(x), parametric equations use a parameter t:
This creates a flower-like pattern where the inner oscillations (2t) create petals, while the outer modulation (0.5t, 0.7t) makes the pattern evolve over time.
Here's the complete program that creates beautiful parametric mathematical art:
import tkinter as tk
import math
import time
class ParametricArt:
def __init__(self):
self.root = tk.Tk()
self.root.title("Advanced Parametric Mathematical Art")
self.root.geometry("800x600")
# Create canvas
self.canvas = tk.Canvas(self.root, width=800, height=600, bg='black')
self.canvas.pack()
# Animation parameters
self.t = 0
self.dt = 0.05
self.running = True
self.trail_length = 300
self.trails = [[] for _ in range(5)]
# Colors for different patterns
self.colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD']
# Create control panel
self.create_controls()
# Start animation
self.animate()
def create_controls(self):
"""Create the control panel"""
control_frame = tk.Frame(self.root, bg='#2C3E50')
control_frame.pack(fill=tk.X, pady=5)
# Animation controls
tk.Button(control_frame, text="⏯️ Pause/Resume",
command=self.toggle_pause, bg='#3498DB', fg='white').pack(side=tk.LEFT, padx=5)
tk.Button(control_frame, text="🗑️ Clear",
command=self.clear_canvas, bg='#E74C3C', fg='white').pack(side=tk.LEFT, padx=5)
tk.Button(control_frame, text="🔄 Reset",
command=self.reset, bg='#27AE60', fg='white').pack(side=tk.LEFT, padx=5)
# Speed control
tk.Label(control_frame, text="Speed:", bg='#2C3E50', fg='white').pack(side=tk.LEFT, padx=5)
self.speed_var = tk.DoubleVar(value=1.0)
speed_scale = tk.Scale(control_frame, from_=0.1, to=3.0, resolution=0.1,
orient=tk.HORIZONTAL, variable=self.speed_var,
bg='#2C3E50', fg='white', highlightthickness=0)
speed_scale.pack(side=tk.LEFT, padx=5)
# Pattern selector
tk.Label(control_frame, text="Pattern:", bg='#2C3E50', fg='white').pack(side=tk.LEFT, padx=5)
self.pattern_var = tk.IntVar(value=1)
for i in range(1, 4):
tk.Radiobutton(control_frame, text=str(i), variable=self.pattern_var,
value=i, bg='#2C3E50', fg='white',
selectcolor='#3498DB').pack(side=tk.LEFT)
def flower_pattern(self, t):
"""Create flowing flower-like patterns"""
center_x, center_y = 400, 300
points = []
for i in range(5):
# Each petal has different phase and frequency
phase = i * 2 * math.pi / 5
# Complex parametric equations for organic flow
r = 80 + 40 * math.cos(3 * t + phase)
x = center_x + r * math.cos(2 * t + phase) * (1 + 0.3 * math.sin(t * 0.5))
y = center_y + r * math.sin(2 * t + phase) * (1 + 0.3 * math.cos(t * 0.7))
# Add subtle secondary motion
x += 15 * math.cos(5 * t + i)
y += 15 * math.sin(4 * t + i)
points.append((x, y, i))
return points
def spirograph_pattern(self, t):
"""Create spirograph-like patterns"""
center_x, center_y = 400, 300
points = []
for i in range(3):
# Spirograph parameters
R = 100 + i * 30 # Outer circle radius
r = 25 + i * 10 # Inner circle radius
d = 50 + i * 20 # Distance from inner circle center
# Spirograph equations
ratio = (R - r) / r
angle = t * (1 + i * 0.2)
x = center_x + (R - r) * math.cos(angle) + d * math.cos(ratio * angle)
y = center_y + (R - r) * math.sin(angle) - d * math.sin(ratio * angle)
points.append((x, y, i))
return points
def lissajous_pattern(self, t):
"""Create modulated Lissajous curves"""
center_x, center_y = 400, 300
points = []
for i in range(4):
# Lissajous parameters
a = 3 + i * 0.5
b = 2 + i * 0.3
phase = i * math.pi / 4
# Modulated Lissajous equations
amplitude = 120 * (1 + 0.4 * math.sin(t * 0.3 + i))
x = center_x + amplitude * math.cos(a * t + phase)
y = center_y + amplitude * math.sin(b * t + phase)
points.append((x, y, i))
return points
def get_pattern_points(self, t):
"""Get points based on selected pattern"""
pattern = self.pattern_var.get()
if pattern == 1:
return self.flower_pattern(t)
elif pattern == 2:
return self.spirograph_pattern(t)
else:
return self.lissajous_pattern(t)
def draw_frame(self):
"""Draw one frame of animation with trailing effects"""
points = self.get_pattern_points(self.t)
# Add new points to trails
for i, (x, y, trail_id) in enumerate(points):
if trail_id < len(self.trails):
self.trails[trail_id].append((x, y))
# Limit trail length
if len(self.trails[trail_id]) > self.trail_length:
self.trails[trail_id].pop(0)
# Clear canvas and redraw trails
self.canvas.delete("all")
# Draw trails with fading effect
for trail_id, trail in enumerate(self.trails):
if len(trail) > 1:
color = self.colors[trail_id % len(self.colors)]
for i in range(1, len(trail)):
# Create fading effect
alpha = i / len(trail)
prev_x, prev_y = trail[i-1]
curr_x, curr_y = trail[i]
# Vary line width and color for depth
if alpha > 0.8:
line_color = color
width = 3
elif alpha > 0.5:
line_color = '#888888'
width = 2
else:
line_color = '#444444'
width = 1
self.canvas.create_line(prev_x, prev_y, curr_x, curr_y,
fill=line_color, width=width,
capstyle=tk.ROUND)
# Draw current points as bright dots
for x, y, trail_id in points:
color = self.colors[trail_id % len(self.colors)]
self.canvas.create_oval(x-3, y-3, x+3, y+3,
fill=color, outline='white', width=1)
def animate(self):
"""Main animation loop"""
if self.running:
self.draw_frame()
self.t += self.dt * self.speed_var.get()
# Schedule next frame (30 FPS)
self.root.after(33, self.animate)
def toggle_pause(self):
"""Toggle animation pause"""
self.running = not self.running
def clear_canvas(self):
"""Clear the canvas and trails"""
self.canvas.delete("all")
self.trails = [[] for _ in range(5)]
def reset(self):
"""Reset animation to beginning"""
self.t = 0
self.clear_canvas()
def run(self):
"""Start the application"""
print("🎨 Advanced Parametric Mathematical Art")
print("Controls:")
print("• ⏯️ Pause/Resume: Toggle animation")
print("• 🗑️ Clear: Clear all trails")
print("• 🔄 Reset: Start over from beginning")
print("• Speed slider: Adjust animation speed")
print("• Pattern buttons: Switch between different mathematical patterns")
print("\nPattern Types:")
print("1. Flower Pattern: Organic flowing petals")
print("2. Spirograph: Classic geometric curves")
print("3. Lissajous: Modulated harmonic motion")
self.root.mainloop()
if __name__ == "__main__":
app = ParametricArt()
app.run() Each pattern type uses different mathematical approaches:
The program creates beautiful trailing effects by:
The interface provides real-time control over:
Get the complete parametric art program to run on your computer:
The 3D version features mouse-controlled rotation, enhanced colorful trails that rotate with the view, glowing particle effects, and four different 3D mathematical patterns including DNA helixes!
Parametric equations are incredibly powerful because they separate the x and y coordinates, allowing each to follow its own mathematical relationship with time. This creates possibilities that regular y = f(x) equations cannot achieve.
When the frequencies in your parametric equations have simple ratios (like 2:3 or 3:4), you get closed, repeating patterns. When the ratios are irrational (like π:2), you get patterns that never exactly repeat, creating endless variety.
These same mathematical principles are used in:
🎨 Lesson 14 Complete! 🎨
You've mastered advanced parametric mathematical art!