Skip to content

Instantly share code, notes, and snippets.

@nickwan
Created August 31, 2018 02:47
Show Gist options
  • Save nickwan/e469d702c26951d05e348e8b7adcdfd5 to your computer and use it in GitHub Desktop.
Save nickwan/e469d702c26951d05e348e8b7adcdfd5 to your computer and use it in GitHub Desktop.
### Mostly taken from this blog post
# http://superfluoussextant.com/circlepusher.html
import random
from PIL import Image, ImageDraw
import math
class Circle:
def __init__(self, radius, location, color):
"""
:param radius: radius of circle in pixels
:param location: two tuple of x,y
"""
self.radius = radius
self.location = location
self.angle = random.randint(0, 360)
self.curve = random.randint(-45, 45)/100
self.active = True
self.color = color
@property
def x(self):
return self.location[0]
@property
def y(self):
return self.location[1]
def draw(self):
if not self.active:
return
image_draw.ellipse((self.x - self.radius,
self.y - self.radius,
self.x + self.radius,
self.y + self.radius),
fill=self.color)
def push(self):
if not self.active:
return
if self.should_make_baby():
circles.append(self.make_baby())
# Let's step by 1/4 of the radius each time
step = self.radius / 4
rad_angle = math.radians(self.angle)
next_step = (self.x + step*math.cos(rad_angle),
self.y + step*math.sin(rad_angle))
# Stepping by 1/4 of the radius will put us still inside our current radius, so let's look a bit further ahead
big_step = (self.x + self.radius*2*math.cos(rad_angle),
self.y + self.radius*2*math.sin(rad_angle))
if self.within_bounds(next_step) and self.free_spot(big_step):
# if self.within_bounds(next_step):
self.location = next_step
else:
self.active = False
if self in circles:
circles.remove(self)
self.angle = (self.angle + self.curve) % 360
@staticmethod
def within_bounds(location):
if location[0] < 0 or location[0] > image_bounds[0] or location[1] < 0 or location[1] > image_bounds[1]:
return False
return True
def free_spot(self, spot):
# Simply check the canvas to see if the passed spot is white
return self.within_bounds(spot) and image.getpixel(spot) == (0,0,0)
@staticmethod
def should_make_baby():
# 1/50 chance to make a baby
return not random.randint(0, 15)
def make_baby(self):
return Circle(self.radius*.75, self.location, self.color)
image_bounds = (600, 600)
image = Image.new('RGB', image_bounds, 'black')
image_draw = ImageDraw.Draw(image)
circles = []
for _ in range(13):
circles.append(Circle(random.randint(2,8),
(random.randint(0, image_bounds[0]),
random.randint(0, image_bounds[1])),
(random.randint(0,255),
random.randint(0,255),
random.randint(0,255))))
for _ in range(1000):
for circle in circles:
circle.draw()
circle.push()
image.save('img/01.png')
image.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment