solution_343.py

# ====================================================================
# draw a convex regular polygon
# --------------------------------------------------------------------
#
#       points that define a regular hexagon
#               (not to scale)
#
#                    P1
#               p6   |    p2
#                 \  |   /
#                  \ |  /
#                    p0
#                  / |  \
#                 /  |   \
#               p5   |    P3
#                    P4
#
# ====================================================================

import sys
import math
import graphics as gr
import user_interface as ui

VERBOSE = False

#---------------------------------------------------------------------
# ---- create/draw a line graphics-object
# ---- Note: x0,y0,x1,y1 are graphics window coordinates
# --------------------------------------------------------------------

def draw_line(win,x0,y0,x1,y1,width=1,color='black'):
    lobj = gr.Line(gr.Point(x0,y0),gr.Point(x1,y1))
    lobj.setWidth(width)
    lobj.setFill(color)
    lobj.draw(win)
    return lobj

# --------------------------------------------------------------------
# ---- create/draw a polygon (graphics-object)
# ---- draw a polygon around a center point scaled up
# ---- note: coordinates are graphics window coordinates
# --------------------------------------------------------------------

def draw_polygon(win,center_point,edges,scale,outline_width=2,
                 fill_color=None,outline_color='black'):

    # ---- create a list of polygon points

    points = []
    points.append(center_point)

    ang_start = 90
    ang_delta = 360/edges

    ang = ang_start

    for i in range(edges):
        x = math.cos(math.radians(ang)) * scale + center_point[0]
        y = math.sin(math.radians(ang)) * scale + center_point[1]
        point = (x,y,ang)
        points.append(point)
        ang -= ang_delta

    if VERBOSE:
        print()
        print(f'center    = {points[0]}')
        print(f'scale     = {scale}')
        print(f'ang start = {ang_start}')
        print(f'ang delta = {ang_delta}')
        print(f'point list size = {len(points)}')
        for idx in range(1,edges+1):
            p = f'({points[idx][0]:>8.4f},{points[idx][1]:>8.4f})' +\
                f'  ang={points[idx][2]:<.4f}'
            print(f'points[{idx}] {p}')

    # ---- convert x,y window coordinates to
    # ---- gr.Point objects (in a list)

    gr_points = []
    for idx in range(1,edges+1):
        gr_points.append(gr.Point(points[idx][0],points[idx][1]))

    # ---- draw a polygon

    hobj = gr.Polygon(gr_points)
    hobj.setOutline(outline_color)
    hobj.setWidth(outline_width)
    if fill_color is not None: hobj.setFill(fill_color)
    hobj.draw(win)
    return hobj

# --------------------------------------------------------------------
# ---- create a graphic window (with x,y axes)
# --------------------------------------------------------------------

def create_graphics_window():

    win_title  = 'Convex Regular Polygons'
    win_width  = 801
    win_height = 801
    win_color  = 'white'

    win = gr.GraphWin(win_title,win_width,win_height)
    win.setBackground(win_color)

    win_center_x = round(win_width/2.0)
    win_center_y = round(win_height/2.0)

    x_axis = draw_line(win,0,win_center_y,
                       win_width-1,win_center_y)

    y_axis = draw_line(win,win_center_x,0,
                       win_center_x,win_height-1)

    return (win,win_center_x,win_center_y)

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

if __name__ == '__main__':

    # ----------------------------------------------------------------
    # ---- get a polygon parameter (integer) from the user
    # ----------------------------------------------------------------

    def get_polygon_parameter(prompt):
        while True:
            print()
            s = ui.get_user_input(prompt)
            if not s: return None
            tf,n = ui.is_integer(s)
            if not tf:
                print()
                print('must enter an integer - try again')
                continue
            break
        return n

    # ---- create a graphics window

    win,win_center_x,win_center_y = create_graphics_window()

    # ---- user menu

    while(True):

        print()
        print('--------------------- polygon ---------------------')
        print('------------- (Integer values only) ---------------')

        while True:
            edges = get_polygon_parameter('enter the number of edges: ')
            if edges is None: break
            if edges < 3:
                print()
                print('must have 3 or more edges')
                sys.exit()
            break

        while True:
            scale = get_polygon_parameter('enter scale factor: ')
            if scale is None: break
            if scale < 50:
                print()
                print('error: scale must be 50 or greater')
                sys.exit()
            break

        while True:
            x = get_polygon_parameter('enter center X coord: ')
            if x is None: break
            if x < 20:
                print()
                print('error: x must be 20 or greater')
                sys.exit()
            break

        while True:
            y = get_polygon_parameter('enter center Y coord: ')
            if y is None: break
            if y < 20:
                print()
                print('error: y must be 20 or greater')
                sys.exit()
            break

        pobj = draw_polygon(win,(x,y),edges,scale)

    click = win.getMouse()
    win.close()
    print()