Create a menu driven program to demonstrate graphics transformations using a wire frame object (cube?). Demonstrate translate, rotate, and scale.

Multiple transformation matrices can be collected into one transformation matrix for use. This is more efficient than multiple transforming matrices.

Center (Cartesian) coordinates are used by the program and only converted to window coordinates when it is time to draw something in the graphics window.

In modern computers transformations, etc. are done in special graphics hardware (GPU - Graphics Processing Unit).

Use the coordinate conversion, etc. functions provided.

import coordinate_conversion as cc
import transformation_matrix as tm
import user_interface as ui
import draw_xy_axes as ax
from graphics import *
import numpy as np
import copy
import re, os, platform, sys
win_height = 801 # window height
win_width = 801 # window width

# ---- wire frame (cube) corner points
pts = [ (-50,-50,50), (-50,50,50), (50,50,50), (50,-50,50),
(-50,-50,-50), (-50,50,-50), (50,50,-50), (50,-50,-50) ]
pivot = (0, 0, 0)
# ---- wire frame (cube) lines
lns = [ (pts[0],pts[1]), (pts[1],pts[2]),
(pts[2],pts[3]), (pts[3],pts[0]),
(pts[4],pts[5]), (pts[5],pts[6]),
(pts[6],pts[7]), (pts[7],pts[4]),
(pts[0],pts[4]), (pts[1],pts[5]),
(pts[2],pts[6]), (pts[3],pts[7]) ]

*Note: ask the instructor about using a wire frame soccer ball
or other 3D wire frame.*

-----------------------------------------------
------------- Transformation Demo -------------
-----------------------------------------------
[qQ] = quit
re = reset to initial conditions
dr = draw wire frame
mx = display transformation matrix
ii = display internal information
mxl = display matrix lines
cw = clear the graphics window (obj.undraw())
------- Build Transformation Matrix --------
tx distance = translate x distance
ty distance = translate y distance
tz distance = translate z distance
t0 = translate to origin (0,0,0)
rx angle = rotate around X axis
ry angle = rotate around Y axis
rz angle = rotate around Z axis
pp x y z = set/change pivot point
sxyz sx xy xz = scale x,y,z
Enter command:

Notes:

- objects (lines) are only drawn when the draw command is executed. any existing objects are erased.
- axes lines are never erased.
- transformation matrices accumulate and are only used when drawing an object.

This class is used as a data store for the wire frame; It also accumulates the transformation matrices used to draw the wire frame.

class WireFrame:
def _lns_to_mx(self,lines):
'''Internal function to convert wire frame lines into lists
(arrays of points) than can be used by the transformation
matrix functions.
- Each line has two points (start,end)
- Each point has a three axes values (x,y,z)
- X,Y,Z are center (Cartesian) coordinates.'''
mxlns = []
for l in lines:
# ---- line points (start,end)
p0 = l[0]
p1 = l[1]
# ---- line points for transformation matrix (start,end)
xyz0 = [ p0[0], p0[1], p0[2], 1.0 ]
xyz1 = [ p1[0], p1[1], p1[2], 1.0 ]
mxlns.append([xyz0,xyz1])
return mxlns
def __init__(self,lns,pivot):
'''Initialize the list of lines and the object's pivot point.''
def reset(self):
'''Reset to the initial conditions.'''
self.mtrx = np.identity(4)
self.mxlines = self._lns_to_mx(self.lns)
def reset_matrix(self):
'''Sets the transformation matrix to the identity matrix.'''
def set_pivot_point(self,x,y,z):
'''Set the coordinates of the object's pivot point.''
def get_line_count(self):
''''Return the number of lines.'''
def get_x(self):
'''return the wire frame's x location (pivot point)'''
return self.x
def get_y(self):
'''return the wire frame's y location (pivot point)'''
return self.x
def get_z(self):
'''return the wire frame's z location (pivot point)'''
return self.x
def translate_to_location(self,dx,dy,dz):
''''Translate object to a X,Y,Z location.'''
def translate_to_origin(self):
''''Translate the object's pivot to the origin.'''
def rotate_around_x_axis(self,degrees):
'''Rotate the object around the X axis.'''
def rotate_around_y_axis(self,degrees):
'''Rotate the object around the Y axis.'''
def rotate_around_z_axis(self,degrees):
'''Rotate the object around the Z axis.'''
def scale_xyz(self,sx,sy,sz):
'''Scale the objects. X,Y,Z have different scale factors.'''
def get_matrix(self):
return copy.deepcopy(self.mtrx)
def display_matrix(self):
'''Display the current transformation matrix.'''
def display_mx_lines(self):
'''Display the object's lines.'''

Assume the graphics objects is solid. Use normal vectors to determine which sides/faces to draw and which not to draw.

See graphics.py documentation for "Polygon Methods" for drawing sides/faces.

Draw each side/face in a different color?

Create animated GIF.

- decide what you want to animate and code it
- wire frame cube?
- Use a normal vector to determine which surfaces (lines) to draw?
- create images
- move/rotate the object
- screen capture the graphics window
- trim/process the captured image to the size you need
- save the image
- loop
- use the images to create an animated GIF file