I've played around some with complex numbers in python and created a program that creates beautiful patterns using $E_n = e^{i(2\pi)/(R_n+1)} = A+Bi$ where R is a set of values between $0$ to $2\pi$ with an arbitary number of datapoints and then plotting $C_n = A_n \mod \sin(t) + B_n \mod \cos(t)$. I'm not that good with math and my question is: What is it that forms these patterns? Thanks
Here's the code:
Links to video & images: https://i.stack.imgur.com/pDauU.jpg https://i.stack.imgur.com/Gp9kU.jpg
# Import necessary libraries
from PIL import Image, ImageDraw
import numpy as np
import math
import time
import random
from numpy import complex, array
import colorsys
import os
# setting the width of the output image as 1024
WIDTH = 720
HEIGHT = 720
SCALE = 1.0
SPEED = 1/(10000) # SMALLER IS FASTER
RESOLUTION = 14*10**4
## Automatically set
PHI = ( 1 + math.sqrt(5) ) / 2
SPEED *= 10**4
RANDNAME = "TODOMAKERANDOM"
def make_frame(frame, length):
# creating the new image in RGB mode
img = Image.new('RGB', (WIDTH, HEIGHT))
pixels = img.load()
# 20**4 arbitary speed
vframe = (frame/(length*SPEED))*2*math.pi
R = np.linspace(0, 2*math.pi, RESOLUTION) # real numbers 0 to 2*pi, width number of datapoints
C = np.zeros((RESOLUTION),dtype=complex) # complex numbers, width number of data points
CR = np.zeros(RESOLUTION) # real parts of complex numbers, width number of ...
CI = np.zeros(RESOLUTION) # imaginary parts of complex nunmbers, width ...
for i, v in enumerate(R):
eiv = np.power(math.e, 1j*v)
# 0.1 IS SCALE
C[i] = complex(eiv.real % SCALE * math.sin(i*vframe), eiv.imag % SCALE * math.cos(i*frame)) #math.sin(i*phi*vframe) # % math.pi * (X2)
for i, c in enumerate(C):
#print("max: ", max(C.real))
c = c/(2+2j) + 0.5j + 0.5
x = math.floor(c.real*img.size[0]-1)
x = x if x > 0 else 0
x = x if x < img.size[0] else img.size[0]-1
y = math.floor(c.imag*img.size[1]-1)
y = y if y > 0 else 0
y = y if y < img.size[1] else img.size[1]-1
s = 2#int(random.random()*4+1)#2
for n in range(s**2):
x1 = x - s + n % s
y1 = y - s + math.floor(n / s)
oldhue = colorsys.rgb_to_hsv(pixels[x1, y1][0], pixels[x1, y1][1], pixels[x1, y1][2])
rgbhue = colorsys.hsv_to_rgb(
min(1.0, oldhue[0]+0.01),
min(1.0, oldhue[0]+0.95),
min(1.0, oldhue[0]+0.2)
)
res = tuple(
ele1 * ele2 for ele1, ele2 in zip(
rgbhue,
(255, 255, 255)
)
)
res = (int(res[0]), int(res[1]), int(res[2]))
if (rgbhue != (0, 0, 0)):
pixels[x1, y1] = res#(colorsys.hsv_to_rgb(30, 1.0, 1.0)*255)
print("frame: ", frame)
if not os.path.exists(RANDNAME):
os.mkdir(RANDNAME)
img.save(RANDNAME+"/frame_"+str(frame)+".png")
start = 1
stop = 500
for i in range(start, stop):
try:
make_frame(i, abs(stop-start))
except KeyboardInterrupt:
break#exit(1)
os.system("ffmpeg -i "+RANDNAME+"/frame_%d.png -c:v libx264 -vf fps=25 -pix_fmt yuv420p "+RANDNAME+"/out.mp4 -y")