"""A module that should help create the affine transformations you would use for transforming GnomeCanvas items. As a little background, an affine transformation is a linear transformation and a translation. The linear transformationcan be represented by a matrix and the translation by a vector. So a general affine transformation looks like this: [ x ] -> [ a b ][ x ] + [ e ] [ y ] [ c d ][ y ] [ f ] As you can see, the affine transformation is defined by the six numbers in the matrix and column vector. For the GnomeCanvas item functions, affine transformations are represented by a flat sequence of the form (a, c, b, d, e, f) This module attempts to make it easy to create complex affine transformations from simpler ones like rotation, scaling and translation. """ import math # These functions create base affine transformations that can be used to build # more complex ones. def identity(): """The identity affine transformation""" return (1, 0, 0, 1, 0, 0) def scale(sx=1, sy=1): """Scale by a factor of sx in the X direction and sy in Y direction""" return (sx, 0, 0, sy, 0, 0) def rotate(radians=None, degrees=0): """Rotate in either degrees or radians""" if not radians: radians = degrees * math.pi / 180.0 s = math.sin(radians) c = math.cos(radians) return (c, s, -s, c, 0, 0) def shear(xshear=0, yshear=0): """Creates a shear transformation in either X and/or Y directoion""" return (1, yshear, xshear, 1, 0, 0) def translate(tx=0, ty=0): """Translate by (tx,ty)""" return (1, 0, 0, 1, tx, ty) # These functions can be used to combine or manipulate other affine # tranformations def compose(a1, *affines): """Compose a number of affine transformations together If the affines a1,a2,a3 are passed as arguments, then the resulting affine A will give A(x) == a1(a2(a3(x)))""" if affines == (): return a1 a2 = apply(compose, affines) return (a1[0]*a2[0] + a1[2]*a2[1], a1[1]*a2[0] + a1[3]*a2[1], a1[0]*a2[2] + a1[2]*a2[3], a1[1]*a2[2] + a1[3]*a2[3], a1[0]*a2[4] + a1[2]*a2[5] + a1[4], a1[1]*a2[4] + a1[3]*a2[5] + a1[5]) def invert(aff): det_inv = 1 / (aff[0]*aff[3] - aff[1]*aff[2]) return (aff[3] * det_inv, -aff[1] * det_inv, -aff[2] * det_inv, aff[0] * det_inv, (aff[2]*aff[5] - aff[3]*aff[4]) * det_inv, (aff[1]*aff[4] - aff[0]*aff[5]) * det_inv)