Last active
September 5, 2016 03:30
-
-
Save bencrowder/b8f90e3058e8cf67edaf116033d1a2dd to your computer and use it in GitHub Desktop.
Line generation
This file contains 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
#!/usr/bin/env python | |
# Code for https://blogs.bencrowder.net/cg/2012/line-art-experiments/ | |
# Uses PIL (pip install pillow) | |
import random, math | |
from PIL import Image, ImageDraw | |
image_size = 4800 | |
num_lines = 80 | |
line_size = 2 | |
start_angle = 2.094 | |
angle_diff = 0.08 | |
max_angle = start_angle + angle_diff | |
min_angle = start_angle - angle_diff | |
change_chance = 10 | |
class Line: | |
x = 0 | |
y = 0 | |
angle = 0 | |
canvas = None | |
type = 0 # 0 = top, 1 = right | |
start_loc = 0 # where we're starting (x or y, depends on type) | |
target_loc = 0 # the target | |
def __init__(self, canvas, type, start_loc, target_loc): | |
self.canvas = canvas | |
self.type = type | |
self.start_loc = start_loc | |
self.target_loc = target_loc | |
if self.type == 0: # top | |
self.x = self.start_loc | |
self.y = 0 | |
elif self.type == 1: # right | |
self.x = image_size | |
self.y = self.start_loc | |
self.angle = start_angle + random.random() * angle_diff | |
def update(self): | |
# Only change angles once in a while | |
change_angle = random.randint(0, change_chance) | |
if change_angle == 0: | |
# Modify the angle | |
self.angle += (random.random() * angle_diff) - (angle_diff / 2) | |
# Cap the angle | |
if self.angle > max_angle: | |
self.angle = max_angle | |
if self.angle < min_angle: | |
self.angle = min_angle | |
# Move the location by the angle | |
self.x = 1 * math.cos(self.angle) + self.x | |
self.y = 1 * math.sin(self.angle) + self.y | |
def draw(self): | |
x1 = self.x - (line_size / 2) | |
x2 = self.x + (line_size / 2) | |
y1 = self.y - (line_size / 2) | |
y2 = self.y + (line_size / 2) | |
self.canvas.ellipse((x1, y1, x2, y2), fill="black") | |
def run(self): | |
if self.type == 0: # top | |
while (self.x > 0): | |
self.update() | |
self.draw() | |
elif self.type == 1: # right | |
while (self.y < image_size): | |
self.update() | |
self.draw() | |
# Create the image | |
img = Image.new('RGB', (image_size, image_size), (255, 255, 255)) | |
canvas = ImageDraw.Draw(img) | |
# Initialize the lines | |
top_line_locs = [] | |
right_line_locs = [] | |
for i in range(0, num_lines): | |
top_line_locs.append(random.random() * image_size) | |
if i < num_lines / 2: | |
right_line_locs.append(random.random() * image_size) | |
top_line_locs.sort() | |
right_line_locs.sort() | |
# Now create each line, setting its target appropriately | |
top_lines = [] | |
right_lines = [] | |
for i in range(0, num_lines): | |
# For the top, set the target to the equivalent right_lines[] | |
top_lines.append(Line(canvas, 0, top_line_locs[i], 5)) | |
# For the right, set the target to the equivalent top_lines[] | |
if i < num_lines / 2: | |
right_lines.append(Line(canvas, 1, right_line_locs[i], top_line_locs[i])) | |
# Now go through the image and draw | |
for line in top_lines: | |
line.run() | |
for line in right_lines: | |
line.run() | |
img.save("output.png", "PNG") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment