# Tools and types for affine transformation of {\RR^d} # Last edited on 2021-02-15 17:17:59 by jstolfi import affine_IMP; from affine_IMP import Affine_IMP class Affine(Affine_IMP): # An object of this class represents an affine geometric transformation of # some real Cartesian space {\RR^d}. It is a subclass of {trafo.Trafo}. # # An {Affine} object {O} has a {d x d} matrix {A}, the /linear map/, and # a {d}-vector {b}, the /displacement/. The transformation # applied to a point {p} of {\RR^d} consists in multiplying {p} # (seen as a row vector) by the matrix {A} and adding {b} to the result. # # The object also stores the data for the inverse trafo, which is also # an affine transformation. The matrix {A'} is the inverse of {A}, and # the vector {b'} is {b} times {A'}. # # When {None} is supplied in a context where an {Affine} onject is expected, # this module understands it to mean the identiy trafo. # # An affine trafo is usually represented as a pair {(i,O)} where {O} is an {Affine} # object and {i} is {+1}, meaning the transformation implied by {O}, or {-1}, # meaning its inverse. We call this pair an /oriented affine trafo/. # In general, an {Affine} object {O} (or {None}) can be used were an oriented affine # trafo is expected; the {i} bit is then assumed to be {+1}. def make(name,Adir,bdir,Ainv,binv): # Creates an {Affine} object with linear map matrix {Adir} and displacement # vector {bdir}. Also requires the matrix and {Ainv} and vector {binv} of the # inverse transformation. The {name} is either {None} or a string used # for debugging. return affine_IMP.make(name,Adir,bdir,Ainv,binv) def apply(p,T): # Applies the oriented affine trafo {T} to the point {p}, which must be a list or tuple with at # least {d} elements, were {d} is {dimension(T)}. # # If {p} has more than {d} elements, the transformation is applied to # the first {d} only, leaving the rest unchanged. return affine_IMP.apply(p,T) def dimension(T): # Returns the dimenson {d} of the space for wich the oriented affine trafo {T} # applies to. return affine_IMP.dimension(T) def unpack(T): # Given an oriented affine trafo {T},returns two results: # the inversion bit ({+1} or {-1}), and the underlying {Affine} object {O}. # If {T} is already an {Affine} object or {None}, returns {+1} and {T}. # # Also does some type checking. return affine_IMP.unpack(T) def lin_matrix(T): # Returns the linear matrix of the oriented affine trafo {T}, # taking its direction bit into account. return affine_IMP.lin_matrix(T) def disp_vector(T): # Returns the linear matrix of the oriented affine trafo {T}, # taking its direction bit into account. return affine_IMP.disp_vector(T) def inv(T): # Returns the inverse of the oriented affine trafo {T}. This basically # negates the inversion bit, without copying or affecting the underlying # object. return affine_IMP.inv(T) def compose(T1,T2): # Composes the two oriented affine trafos {T1,T2}, applied in that order, # taking their orientations into account, into a single {Affine} object {T} return affine_IMP.compose(T1,T2)