1'''functions for 2D affine transformations'''
2__all__ = (
3    'nullTransform',
4    'translate',
5    'scale',
6    'rotate',
7    'skewX',
8    'skewY',
9    'mmult',
10    'inverse',
11    'zTransformPoint',
12    'transformPoint',
13    'transformPoints',
14    'zTransformPoints',
15    )
16from math import pi, cos, sin, tan
17
18# constructors for matrices:
19def nullTransform():
20    return (1, 0, 0, 1, 0, 0)
21
22def translate(dx, dy):
23    return (1, 0, 0, 1, dx, dy)
24
25def scale(sx, sy):
26    return (sx, 0, 0, sy, 0, 0)
27
28def rotate(angle):
29    a = angle * pi/180
30    return (cos(a), sin(a), -sin(a), cos(a), 0, 0)
31
32def skewX(angle):
33    a = angle * pi/180
34    return (1, 0, tan(a), 1, 0, 0)
35
36def skewY(angle):
37    a = angle * pi/180
38    return (1, tan(a), 0, 1, 0, 0)
39
40def mmult(A, B):
41    "A postmultiplied by B"
42    # I checked this RGB
43    # [a0 a2 a4]    [b0 b2 b4]
44    # [a1 a3 a5] *  [b1 b3 b5]
45    # [      1 ]    [      1 ]
46    #
47    return (A[0]*B[0] + A[2]*B[1],
48            A[1]*B[0] + A[3]*B[1],
49            A[0]*B[2] + A[2]*B[3],
50            A[1]*B[2] + A[3]*B[3],
51            A[0]*B[4] + A[2]*B[5] + A[4],
52            A[1]*B[4] + A[3]*B[5] + A[5])
53
54def inverse(A):
55    "For A affine 2D represented as 6vec return 6vec version of A**(-1)"
56    # I checked this RGB
57    det = float(A[0]*A[3] - A[2]*A[1])
58    R = [A[3]/det, -A[1]/det, -A[2]/det, A[0]/det]
59    return tuple(R+[-R[0]*A[4]-R[2]*A[5],-R[1]*A[4]-R[3]*A[5]])
60
61def zTransformPoint(A,v):
62    "Apply the homogenous part of atransformation a to vector v --> A*v"
63    return (A[0]*v[0]+A[2]*v[1],A[1]*v[0]+A[3]*v[1])
64
65def transformPoint(A,v):
66    "Apply transformation a to vector v --> A*v"
67    return (A[0]*v[0]+A[2]*v[1]+A[4],A[1]*v[0]+A[3]*v[1]+A[5])
68
69def transformPoints(matrix, V):
70    r = [transformPoint(matrix,v) for v in V]
71    if isinstance(V,tuple): r = tuple(r)
72    return r
73
74def zTransformPoints(matrix, V):
75    return list(map(lambda x,matrix=matrix: zTransformPoint(matrix,x), V))
76