#! /usr/bin/python3
# ===================================================================
# demonstrate translation/rotation/fold of a graphics object made
# of line segments and points
# ===================================================================
import numpy as np
import user_interface as ui
import draw_xy_axes as ax
import transformation_matrix as tm
import coordinate_conversion as cc
from two_vector_angle import two_vector_angle
from graphics import *
# ---- object (line segments)
segs = [ ( 200.0, 200.0, 200.0,-200.0),
( 200.0,-200.0,-200.0,-200.0),
(-200.0,-200.0,-200.0, 50.0),
(-200.0, 50.0,-200.0, 200.0),
(-200.0, 200.0,-100.0, 200.0),
(-100.0, 200.0, 200.0, 200.0), ]
# ---- fold line (line segment)
fln = (-200.0,50.0,-100.0,200.0)
# -------------------------------------------------------------------
# ---- draw line segment
# -------------------------------------------------------------------
def draw_line_segment(win,ul,x1,y1,x2,y2,ends=True,
color1='black',color2='black'):
wx1,wy1 = cc.center_to_win_coords(x1,y1,win.width,win.height)
wx2,wy2 = cc.center_to_win_coords(x2,y2,win.width,win.height)
l = Line(Point(wx1,wy1),Point(wx2,wy2))
l.setWidth(2)
l.setFill(color1)
l.draw(win)
ul.append(l)
if ends:
draw_point(win,ul,x1,y1,color2)
draw_point(win,ul,x2,y2,color2)
# -------------------------------------------------------------------
# ---- draw point (small circle)
# -------------------------------------------------------------------
def draw_point(win,ul,x,y,color='red'):
wx,wy = cc.center_to_win_coords(x,y,win.width,win.height)
p = Circle(Point(wx,wy),4)
p.setFill(color)
p.draw(win)
ul.append(p)
# -------------------------------------------------------------------
# ---- draw object (made of line segments)
# ---- segs object line segments
# ---- fln fold line segment
# ---- cnt draw fold line center point
# -------------------------------------------------------------------
def draw_object(win,segs,fln,cnt=True):
# ---- undraw list
ul = []
# ---- draw object
for s in segs:
draw_line_segment(win,ul,s[0],s[1],s[2],s[3])
# ---- draw fold line
if fln is not None:
draw_line_segment(win,ul,fln[0],fln[1],fln[2],fln[3],
True,'red','white')
# ---- draw fold line center point
if cnt:
x = (fln[0]+fln[2])/2
y = (fln[1]+fln[3])/2
draw_point(win,ul,x,y,'white')
return ul
# -------------------------------------------------------------------
# ---- rotate/translate a list of line segments
# -------------------------------------------------------------------
def translate_rotate_segs(x,y,ang,segs_old=None):
segs_new = []
for seg in segs_old:
seg_new = translate_rotate_seg(x,y,ang,seg)
segs_new.append(seg_new)
return segs_new
# -------------------------------------------------------------------
# ---- rotate/translate a line segment
# -------------------------------------------------------------------
def translate_rotate_seg(x,y,ang,seg):
# ---- create a transformation matrix to:
# ---- 1. move fold line center to the origin (0,0)
# ---- 2. rotate fold line until vertical
t1 = tm.get_translation_matrix_2d(x,y)
tx = t1
if ang is not None:
t2 = tm.get_z_rotation_matrix_2d(ang)
tx = t2 @ t1
xy = [seg[0],seg[1],1]
xy1 = tx @ xy
xy = [seg[2],seg[3],1]
xy2 = tx @ xy
return (xy1[0],xy1[1],xy2[0],xy2[1])
# -------------------------------------------------------------------
# ---- main
# -------------------------------------------------------------------
if __name__ == '__main__':
win_width = 801
win_height = 801
# ---- create window
win = GraphWin("Test Fold",win_width,win_height)
win.setBackground("white")
# ---- draw axes
ax.draw_xy_axes(win,True)
# ---- draw the object, etc.
ul = draw_object(win,segs,fln)
# ---- calculate the middle of the fold line
x_fln = (fln[0]+fln[2])/2
y_fln = (fln[1]+fln[3])/2
# ---- make the fold line points vector "up"
# ---- (this will simplify the fold angle calculation. the Y axes
# ---- points "up" and the fold line vector also points up.
dx = fln[2] - fln[0]
dy = fln[3] - fln[1]
# ---- create a fold line / Y axis rotation angle
# ---- (used to rotate the fold line onto the Y axis)
v1 = [0.0,10.0] # Y axis
v2 = [dx,dy] # fold line
print(f'vector 1 = {v1}')
print(f'vector 2 = {v2}')
rot_rad = two_vector_angle(v1,v2) # rotation angle (rad)
rot_deg = np.rad2deg(rot_rad) # rotation angle (deg)
print(f'rotation angle = {rot_deg:.3f} degrees')
# ---- rotate/translate the line segments, etc.
# ---- put the center of the fold line at the origin (0,0)
print()
print('translate/rotate object, etc.')
ui.pause()
for o in ul:
o.undraw()
segs_new = \
translate_rotate_segs(-x_fln,-y_fln,rot_deg,segs)
fln_new = \
translate_rotate_seg(-x_fln,-y_fln,rot_deg,fln)
ul = draw_object(win,segs_new,fln_new)
# ---- fold the new object
print()
print('fold the new object, etc.')
ui.pause()
##????????????????????????????????????????????????
## much better code required here
segs_fold = []
for s in segs_new:
if s[0] < 0: # segment point0 X coord
x1 = -s[0]
else:
x1 = s[0]
if s[2] < 0: # segment point1 X coord
x2 = -s[2]
else:
x2 = s[2]
segs_fold.append((x1,s[1],x2,s[3]))
# ---- restore the object, etc.
# ---- put them back where they came from
print()
print('restore the original object, etc.')
ui.pause()
for o in ul:
o.undraw()
segs_restore = \
translate_rotate_segs(x_fln,y_fln,-rot_deg,segs_fold)
fln_restore = \
translate_rotate_seg(x_fln,y_fln,-rot_deg,fln_new)
ul = draw_object(win,segs_restore,None)
draw_line_segment(win,ul,fln_restore[0],
fln_restore[1],
fln_restore[2],
fln_restore[3],False)
# ---- end program
print()
print('exit the program')
ui.pause()
win.close()
print()