Created
March 8, 2019 02:15
-
-
Save smeschke/a55760c89aa8e59f9d126303077a1e04 to your computer and use it in GitHub Desktop.
Draws a spiraling swirl?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cv2, numpy as np, math, random | |
# create a list for the particles | |
num_particles = 25000 | |
particles = np.zeros((num_particles,5), np.float32) | |
# x, y, angle, size | |
for i in range(particles.shape[0]): particles[i] = -234,-1234,0,0,i | |
# define parameters | |
hw = 1080 | |
center = int(hw/2),int(hw/2) | |
radius = 300 | |
marks = 9 | |
center_variability = 50 | |
vector_length = 80 | |
segment_length = 321 | |
# For writing video | |
vid_writer = cv2.VideoWriter('/home/stephen/Desktop/olga.avi', cv2.VideoWriter_fourcc('M','J','P','G'), 60, (hw,hw)) | |
# distance function | |
def distance(a,b): return math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2) | |
# creates a new particle | |
def new_particle(): | |
xy = (.5-random.random())*center_variability, (.5-random.random())*center_variability | |
return xy[0], xy[1], 0, 0, num_particles | |
# Sum of two vectors | |
def addVectors(a,b): | |
(angle1, length1), (angle2, length2) = a,b | |
x = math.sin(angle1) * length1 + math.sin(angle2) * length2 | |
y = math.cos(angle1) * length1 + math.cos(angle2) * length2 | |
angle = 0.5 * math.pi - math.atan2(y, x) | |
length = math.hypot(x, y) | |
return (angle, length) | |
# Get color | |
def get_color(d, h): | |
img = np.zeros((1,1,3), np.uint8) | |
r = d/4 | |
r = int(r) | |
img[:,:,:] = r,255,255 | |
img = cv2.cvtColor(img, cv2.COLOR_HSV2BGR) | |
return tuple(img[0,0]) | |
# main loop | |
idx = 0 | |
img = np.zeros((hw,hw,3), np.uint8) | |
for i in range(20): vid_writer.write(img) | |
while True: | |
idx += 1 | |
# create a blank image | |
img = np.zeros((hw,hw,3), np.uint8) | |
# draw the particles | |
for x,y,_,_, size in particles: | |
color = get_color(distance((0,0), (x,y)), hw) | |
color= int(color[0]), int(color[1]), int(color[2]) | |
cv2.circle(img, (int(x+center[0]),int(y+center[1])), 2, color, -1) | |
# move the particles | |
for i in range(particles.shape[0]): | |
x, y, angle, speed, size = particles[i] | |
new_x, new_y = math.sin(angle)*speed + x, math.cos(angle)*speed + y | |
# Draw the vector for the fluid | |
center_distance = distance((0,0), (x,y)) | |
flow_angle = math.atan2(x/center_distance,y/center_distance) + math.pi/2 | |
vector_end = x + math.sin(flow_angle)*67, y + math.cos(flow_angle)*67 | |
xy = tuple(np.array((x+center[0],y+center[0]), int)) | |
xy1 = tuple(np.array((vector_end[0]+center[0], vector_end[1]+center[0]), int)) | |
#cv2.line(img, xy, xy1, (255,0,255), 1) | |
flow_speed = .6*(hw-center_distance)/hw | |
speed = speed * .9 | |
new_angle, new_speed = addVectors((angle, speed), (flow_angle, flow_speed)) | |
particles[i] = new_x, new_y, new_angle, new_speed, size-1 | |
# replace the particles that are too small | |
new = 0 | |
for i in range(particles.shape[0]): | |
if new < 8: | |
if particles[i][4] < 1: particles[i], new = new_particle(), new+ 1 | |
if particles[i][0] < -hw/2: particles[i], new = new_particle(), new+ 1 | |
if particles[i][0] > hw/2: particles[i], new = new_particle(), new+ 1 | |
if particles[i][1] < -hw/2: particles[i], new = new_particle(), new+ 1 | |
if particles[i][1] > hw/2: particles[i], new = new_particle(), new+ 1 | |
cv2.imshow('img', img) | |
vid_writer.write(img) | |
k = cv2.waitKey(1) | |
if k == 27: break | |
cv2.destroyAllWindows() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment