"""
 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()