solution_050e.py

#! /usr/bin/python3
# ===================================================================
# spin a blob (polygon)
# combine multiple transformation matrices into a single matrix
#
# How does it work:
# Rotation is around the origin (0,0). If you want to rotate
# an object in place you must:
#    1. transport the object to the origin (0,0) placing its pivot
#       point at the origin(0,0)
#    2. rotate the object
#    3. transport the object back to its original location
# These steps can be done by a combined transformation matrix
# ===================================================================

import transformation_matrix as tm
import coordinate_conversion as cc
import user_interface as ui
from graphics import *
import numpy as np
import os, sys

win_width  = 801
win_height = 801

# ---- blob (polygon) window coordinates
# ---- blob center is 100,100
blob_w_coords = [ [110,70], [140,70], [110,110], [110,140], [80,110],
                  [50,110], [70,100], [50,90], [90,90], [110,70] ]

# ---- blob (polygon) center (Cartesian) coordinates
# ---- blob is center around the origin (0.0,0.0)
blob_c_coords = [ [10,-30], [40,-30], [10,10], [10,40], [-20,10],
                  [-50,10], [-30,0], [-50,-10], [-10,-10], [10,-30] ]

# -------------------------------------------------------------------
# ---- function: draw X,Y Cartesian coordinate axes
# -------------------------------------------------------------------

def draw_xy_axes(win, line_width=1, line_color="black"):

    xl = Line(Point(0,win.height/2),Point(win.width-1,win.height/2))
    xl.setWidth(line_width)
    xl.setFill(line_color)
    xl.draw(win)

    yl = Line(Point(win.width/2,0),Point(win.width/2,win.height-1))
    yl.setWidth(line_width)
    yl.setFill(line_color)
    yl.draw(win)

# -------------------------------------------------------------------
# ---- function: create a list of polygon point objects
# ---- input coordinates are center (Cartesian) coordinates
# ---- output coordinates are window coordinates
# -------------------------------------------------------------------

def create_points_list(tm, coords, winwidth, winheight):

    points = []

    for c in coords:

        xy1 = [c[0],c[1],1]

        p = tm @ xy1

        xy = cc.center_to_win_coords(p[0],p[1],winwidth,winheight)

        points.append(Point(xy[0],xy[1]))

    return points

# -------------------------------------------------------------------
# ---- function: spin the blob
# -------------------------------------------------------------------

def spin_blob(win, c_coords, x, y, winwidth, winheight):

    # ---- draw the blob at its initial (starting) location
    # ---- centered at x,y (Cartesian) coordinates

    tm0 = tm.get_translation_matrix_2d(x,y)

    pts = create_points_list(tm0,c_coords,winwidth,winheight)

    blob = Polygon(pts)
    blob.setWidth(3)
    blob.setOutline("black")
    blob.setFill("red")
    blob.draw(win)

    # ---- spin

    angle = 10.0

    while True:

        tm1 = tm.get_translation_matrix_2d(0.0,0.0)
        tm2 = tm.get_z_rotation_matrix_2d(angle)
        tm3 = tm.get_translation_matrix_2d(x,y)
        tm4 = tm3 @ tm2 @ tm1

        pts = create_points_list(tm4,c_coords,winwidth,winheight)

        blob.undraw()
        blob = Polygon(pts)
        blob.setWidth(3)
        blob.setOutline("black")
        blob.setFill("red")
        blob.draw(win)

        angle += 10.0

        #---- enter y or Y to exit

        a = ui.get_user_input('Exit? ')
        if a == '':
            continue
        if a[0] == 'y' or a[0] == 'Y':
            return

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

# ---- create window

win = GraphWin("Spin Blob", win_width, win_height)
win.setBackground("white")

# ---- draw X,Y center (Cartesian) coordinate axes

draw_xy_axes(win)

# ---- spin the blob centered at 100,100

spin_blob(win,blob_c_coords,100.0,100.0,win_width,win_height)

# ---- end program

win.close()
print()