human
I am working on the file "Lecture-09-Matrices-and-Rotations.ipynb".
The first task is:
Helper Classes, Drawing and Plane Groups

Let us explore a bit of how we can draw an image - and then we have everything we need to start building the plane group representations.  To build pictoral representations of plane groups, two classes have been created to simplify the organization of the motif.  
Below are the Point and Triangle classes for your use.  A Point has storage for an $(x,y)$ position.  Rather than building arrays and referencing specific positions within the array a more natural referencing of points is possible.  If we define a point p1 = Point(10,20) we can access the points by p1.x and p1.y.  The code is more easily read and debugged with this syntax.
Building on the Point class we define a Triangle class.  The Triangle permits access of each point and defines an affine() method that will take a Numpy array that represents a transformation matrix.  This method returns a new instance of a Triangle and preserves the original points.  Writing the code this way avoids explicit handling of the transformation matrices.
These two classes and methods are demonstrated in the second and third code blocks.  Building on this demonstration you will be able to complete the homework.
Can you write Python code for it?
assistant
#Here is the Python code you requested.

# Class definitions

from math import sqrt
import numpy as np

class Point:
    """
    A Point object to simplify storage of (x,y) positions.
    p1.x, p1.y, etc...
    """
    def __init__(self,x_init,y_init):
        self.x = x_init
        self.y = y_init

    def shift(self, x, y):
        self.x += x
        self.y += y

    def __repr__(self):
        return "".join(["Point(", str(self.x), ",", str(self.y), ")"])
    
class Triangle:
    """
    A Triangle class constructed from points.  Helps organize information on
    triangles.  Has a points() method for returning points in a form that 
    can be used with polygon drawing from Python Image Library (PIL) and a 
    method, affine(), that applies a matrix transformation to the points.
    """
    def __init__(self, p1_init, p2_init, p3_init):
        self.p1 = p1_init
        self.p2 = p2_init
        self.p3 = p3_init
        
    def points(self):
        x1, y1 = self.p1.x, self.p1.y
        x2, y2 = self.p2.x, self.p2.y
        x3, y3 = self.p3.x, self.p3.y
        
        return [(x1,y1),(x2,y2),(x3,y3)]
        
    def affine(self, affineMatrix):
        """
        Applies an affine transformation to a triangle and changes the 
        points of the triangle.  This code returns a new triangle.  Uses
        Points to simplify augmenting the matrix and dot products.
        """
        x1, y1 = self.p1.x, self.p1.y
        x2, y2 = self.p2.x, self.p2.y
        x3, y3 = self.p3.x, self.p3.y
        
        p1Vector = np.array([[x1, y1, 1]])
        p2Vector = np.array([[x2, y2 , 1]])
        p3Vector = np.array([[x3, y3, 1]])
        
        p1New = np.dot(affineMatrix, p1Vector.T)
        p2New = np.dot(affineMatrix, p2Vector.T)
        p3New = np.dot(affineMatrix, p3Vector.T)
        
        # This line needs to be cleaned up.
        newTriangle = Triangle(Point(p1New[0,0],p1New[1,0]),Point(p2New[0,0],p2New[1,0]),Point(p3New[0,0],p3New[1,0]))
        
        return newTriangle