solution_123.py

#!/usr/bin/python3
# ===================================================================
# draw a multi-pointed star
# ===================================================================


import coordinate_conversion as cc
import user_interface as ui
import draw_xy_axes as ax

from   graphics import *
import numpy as np
import platform
import os
import sys


# ---- global variables

max_points = 20
verbose    = True


# -------------------------------------------------------------------
# ---- draw points
# ---- return a list of drawn points
# -------------------------------------------------------------------

def draw_points(win,pts,raidus=4):
    
    p_lst = []                  # list of points drawn

    for p in pts:

        c = Circle(p,raidus)
        c.setFill('black')
        c.draw(win)

        p_lst.append(c)

    return p_lst


# -------------------------------------------------------------------
# ----- draw lines connecting points
# ----- return a list of lines drawn
# -------------------------------------------------------------------

def draw_lines(win,pts,skip):

    i       = 0                # start of line point
    j       = i + 1 + skip     # end of line point
    pts_len = len(pts)         # length of points list
    l_lst   = []               # list of lines drawn

    while True:

        # ---- draw line
        
        l = Line(pts[i],pts[j])
        l.setWidth(3)
        l.setFill('black')
        l.draw(win)

        l_lst.append(l)

        i = (i+1) % pts_len    # do not exceed size of list
        j = (j+1) % pts_len    # do not exceed size of list

        # ---- back at the beginning of the list?
        
        if pts[i] is pts[0]:
            break

    return l_lst


# -------------------------------------------------------------------
# ---- calculate location (xy) of points
# ---- return a list of points
# -------------------------------------------------------------------

def calculate_points(win,points,radius=200):

    angle = 0.0                # starting angle
    pts   = []                 # point list

    for _ in range(points):

        rad = np.deg2rad(angle)

        x = np.sin(rad) * radius
        y = np.cos(rad) * radius

        (wx,wy) = cc.center_to_win_coords(x,y,win.width,win.height)

        pts.append(Point(wx,wy))

        angle += 360.0/points

    return pts


# -------------------------------------------------------------------
# ---- undraw graphics objects(remove from graphics window)
# -------------------------------------------------------------------

def undraw_graphics_objects(obj_lst):

    if verbose:
        print(f'undraw {len(obj_lst)} graphics objects')

    for o in obj_lst:
        o.undraw()


# -------------------------------------------------------------------
# ---- main
# -------------------------------------------------------------------

# ---- running Python3

if not ui.running_python3():
    print()
    print('Must run Python3 - exit program')
    print()
    sys.exit()

# ---- create graphics window

win = GraphWin("Five Multi-Pointed Object (Star?)", 801, 801)
win.setBackground("white")

ax.draw_xy_axes(win)

# ---- draw points and lines drawn in graphics window ----------------

err   = False                   # error occured flag
l_lst = []                      # list of lines drawn
p_lst = []                      # list of points drawn

while True:

    # ---- test error flag and pause

    if err:
        err = False
        ui.pause()

    # ---- ask the user for points input

    ## ui.clear_screen()
    print()
    print('------------------------------------------------------')

    s = ui.get_user_input('Enter number the of points: ')
    if not s:              # empty string?
        break

    tf,points = ui.is_int(s)
    if not tf:
        print()
        print(f'non-integer entered ({points})')
        err = True
        continue

    if points < 2 or points > max_points:
        print()
        print(f'bad point count ({points})')
        err = True
        continue

    # ---- ask the user for skip input

    print()
    s = ui.get_user_input('Enter number the of points to skip: ')
    if not s:              # empty string?
        break

    tf,skip = ui.is_int(s)
    if not tf:
        print()
        print(f'non-integer integer ({skip})')
        err = True
        continue    

    if skip < 0:
        print()
        print(f'bad skip count ({skip})')
        err = True
        continue

    max_skip = int(points/2) - 1

    if verbose:
        print()
        print(f'skip is {skip} and max skip is {max_skip}')
    
    if skip > max_skip:
        print()
        print(f'points/skip must be less than {max_skip}')
        err = True
        continue        

    # ---- undraw old points and lines (if any?)

    undraw_graphics_objects(p_lst)
    undraw_graphics_objects(l_lst)

    # ---- display new points and lines

    if verbose:
        print(f'draw {points} points (start/end of lines)')
        print(f'skip {skip} points when drawing a line')

    # ---- calculate points

    pts = calculate_points(win,points)

    if verbose:
        print(f'{len(pts)} points calculated')

    # ---- draw points
    
    p_lst = draw_points(win,pts)

    if verbose:
        print(f'{len(p_lst)} points drawn')

    # ---- draw lines

    l_lst = draw_lines(win,pts,skip)

    if verbose:
        print(f'{len(l_lst)} lines drawn')

    ##ui.pause()

# ---- exit program

win.close()