""" string_art.py Draws a string art pattern of connected line segments using Zelle's graphics package. For more on string art patterns, see for example http://www.mathcats.com/crafts/stringart.html Jim Mahoney | GPL | Aug 2018 """ from graphics import * from math import sin, cos, pi radius = 1.0 # in dimensionless window coords border = 0.2 # space around circle header = 0.4 # space for text boxes text_height = 0.1 n_text_chars = 16 window_pixel_width = 600 # Calculate various other dimensions and print them out. top = radius + border + header right = radius + border bottom = -(radius + border) left = -(radius + border) print("top, right, bottom, left = {}, {}, {}, {}".format( top, right, bottom, left)) width = right - left height = top - bottom print("width, height = {}, {}".format(width, height)) window_pixel_height = int(window_pixel_width * height/width) print("pix_width, pix_height = {}, {}".format( window_pixel_width, window_pixel_height)) # Create the graphics window win = GraphWin("string art", window_pixel_width, window_pixel_height) win.setBackground("black") win.setCoords(left, bottom, right, top); # Text entry for number of points points_text = Entry(Point(0.0, top - text_height), n_text_chars) points_text.setFill(color_rgb(240, 240, 240)) points_text.draw(win) points_text.setText("37 # n points") # Text entry for skip number skip_text = Entry(Point(0.0, top - 2*text_height), n_text_chars) skip_text.setFill(color_rgb(240, 240, 240)) skip_text.draw(win) skip_text.setText('18 # skip number') # Text entry for layer color color_text = Entry(Point(0.0, top - 3*text_height), n_text_chars) color_text.setFill(color_rgb(240, 240, 240)) color_text.draw(win) color_text.setText('red') # Talk to the nice user instructions = Text(Point(0.0, top-4*text_height), "Fill in values and click the mouse. Repeat.") instructions.draw(win) ## This is the circle where the pattern will be drawn. # circle = Circle(Point(0,0), radius) # circle.draw(win) # Repeatedly draw a bunch of layers. for layer in range(100): wait_for_click = win.getMouse() # Pause until click. n_points = eval(points_text.getText()) # Get user input numbers. n_skip = eval(skip_text.getText()) color = color_text.getText() # Create a list of points around a circle. points = [] for i in range(n_points): angle = i * 2.0 * pi / n_points x = radius * cos(angle) y = radius * sin(angle) points = points + [Point(x,y)] # Create line segments between i'th and j'th # points on the circle,'skipping' around by n_skip. i = 0 for iteration in range(n_points): j = (i + n_skip) % n_points; segment = Line(points[i], points[j]) segment.setFill(color) segment.setOutline(color) segment.draw(win) i = j # If we get this far (after 100 layers - yeah, right) pause for final click. instructions.setText('100 layers! Click the mouse to quit.') wait_for_click = win.getMouse()