Code Example: test_fold_02.py

#! /usr/bin/python3
# ===================================================================
# demonstrate translation/rotation 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)

# ---- test rotation angle (this is the angle between the
# ---- Y axis and the fold line)

# -------------------------------------------------------------------
# ---- 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

    # ---- create a test rotation angle

    r60 = np.deg2rad(60)       # deg -> rad
    x = np.cos(r60) * 10       # X expand
    y = np.sin(r60) * 10       # Y expand

    v1 = [0.0,10.0]            # Y axis
    v2 = [x,y]                 # fold line

    test_rad = two_vector_angle(v1,v2) # radians
    test_angle = np.rad2deg(test_rad)  # 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,None,segs)
    ####fln_new = \
    ####translate_rotate_seg(-x_fln,-y_fln,None,fln)

    segs_new = \
        translate_rotate_segs(-x_fln,-y_fln,test_angle,segs)
    fln_new = \
        translate_rotate_seg(-x_fln,-y_fln,test_angle,fln)

    ul = draw_object(win,segs_new,fln_new)

    # ---- 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,None,segs_new)
    ####fln_restore = \
    ####translate_rotate_seg(x_fln,y_fln,None,fln_new)

    segs_restore = \
        translate_rotate_segs(x_fln,y_fln,-test_angle,segs_new)
    fln_restore = \
        translate_rotate_seg(x_fln,y_fln,-test_angle,fln_new)

    ul = draw_object(win,segs_restore,fln_restore)

    # ---- end program

    print()
    print('exit the program')

    ui.pause()
    win.close()
    print()