Here is the formal class interface.
# - - - - - c l a s s X f o r m class Xform(object): '''Represents an arbitrary homogeneous coordinate transform. Exports: Xform(m): [ m is a 3x3 transform matrix as a num.array, or a sequence that num.array() will accept as a 3x3 array -> return a new Xform instance representing that transform ] .apply(p): [ p is a Pt instance -> return a new Pt instance representing p transformed by self ] .invert(p): [ p is a Pt instance -> return a new Pt instance pp such that self.apply(pp) == p ] .inverse(): [ return the inverse of self as an Xform instance ] .compose(t): [ t is an Xform instance -> return a new Xform representing the composition of self followed by t ] .offset(): [ return the net offset that self will shift the origin, as a Pt instance ] .angle(): [ return the net angle that self will rotate the unit vector from (0,0) to (1,1) ] .mag(): [ return the net magnification that self will apply to the unit vector ] .__str__(self): [ return a string representation of self ]
.__m attribute is the
actual transform matrix.
We use memoization to avoid computing the inverse of the
transform matrix every time the
method is called. We set an internal attribute
.__mInverse initially to
Then, when the
.inverse() method is called,
we store the inverted transform in this attribute for reuse
on the next call.
Also memoized are the results of the
.__analyze() method, which computes the net
translation, rotation, and uniform scaling components of
State/Invariants: self.__m: [ a 3x3 num.array representing the argument passed to the constructor ] self.__mInverse: [ the inverse of self.__m or None ] self.__offset: [ the net translation of self or None ] self.__angle: [ the net rotation of self or None ] self.__mag: [ the net uniform scaling of self or None ] ORIGIN: [ the origin as a Pt instance ] UNIT: [ a point 1.0 along the line x=y ] ''' ORIGIN = Pt(0,0) UNIT = ORIGIN.radial(1.0, RAD_45)