|
16 | 16 | # along with this program; if not, write to the Free Software |
17 | 17 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | 18 |
|
19 | | - |
20 | | -import numpy as np |
21 | | - |
22 | 19 | class Matrix(object): |
23 | | - def __init__(self): |
| 20 | + def __init__(self, other=None, nice=None): |
24 | 21 | self.stack = [] |
25 | | - self.reset() |
| 22 | + if other is not None: |
| 23 | + if isinstance(other, list): |
| 24 | + self.m = other |
| 25 | + self.nice = False |
| 26 | + else: |
| 27 | + self.m = list(other.m) |
| 28 | + self.nice = other.nice |
| 29 | + else: |
| 30 | + self.reset() |
| 31 | + |
| 32 | + if nice is not None: |
| 33 | + self.nice = nice |
26 | 34 |
|
27 | 35 | def reset(self): |
28 | | - self.m = np.matrix([ |
29 | | - [1,0,0,0], |
30 | | - [0,1,0,0], |
31 | | - [0,0,1,0], |
32 | | - [0,0,0,1]], float) |
| 36 | + self.m = [ |
| 37 | + 1.0,0.0,0.0,0.0, |
| 38 | + 0.0,1.0,0.0,0.0, |
| 39 | + 0.0,0.0,1.0,0.0, |
| 40 | + 0.0,0.0,0.0,1.0 |
| 41 | + ] |
| 42 | + self.nice = True |
33 | 43 |
|
34 | 44 | def push(self): |
35 | | - self.stack.append(self.m.copy()) |
| 45 | + self.stack.append((self.m, self.nice)) |
| 46 | + self.m = list(self.m) |
36 | 47 |
|
37 | 48 | def pop(self): |
38 | | - self.m = self.stack.pop() |
| 49 | + self.m, self.nice = self.stack.pop() |
39 | 50 |
|
40 | 51 | def scale(self, sx, sy, sz=1.0): |
41 | | - self.m *= [ |
42 | | - [sx, 0, 0, 0], |
43 | | - [0, sy, 0, 0], |
44 | | - [0, 0, sz, 0], |
45 | | - [0, 0, 0, 1], |
46 | | - ] |
| 52 | + if not self.nice: |
| 53 | + self *= Matrix().scale(sx, sy, sz) |
| 54 | + return self |
| 55 | + else: |
| 56 | + self.m[0] *= sx |
| 57 | + self.m[5] *= sy |
| 58 | + self.m[10] *= sz |
| 59 | + return self |
47 | 60 |
|
48 | 61 | def translate(self, tx, ty, tz=0.0): |
49 | | - self.m *= [ |
50 | | - [1, 0, 0, tx], |
51 | | - [0, 1, 0, ty], |
52 | | - [0, 0, 1, tz], |
53 | | - [0, 0, 0, 1], |
| 62 | + if not self.nice: |
| 63 | + self *= Matrix().translate(tx, ty, tz) |
| 64 | + return self |
| 65 | + self.m[12] += tx * self.m[0] |
| 66 | + self.m[13] += ty * self.m[5] |
| 67 | + self.m[14] += tz * self.m[10] |
| 68 | + return self |
| 69 | + |
| 70 | + def __mul__(self, other): |
| 71 | + if self.nice and other.nice: |
| 72 | + return Matrix(self._nicemult(self.m, other.m), True) |
| 73 | + else: |
| 74 | + return Matrix(self._mult(self.m, other.m), False) |
| 75 | + |
| 76 | + def __imul__(self, other): |
| 77 | + if self.nice and other.nice: |
| 78 | + self.m = self._nicemult(self.m, other.m) |
| 79 | + else: |
| 80 | + self.m = self._mult(self.m, other.m) |
| 81 | + self.nice = False |
| 82 | + return self |
| 83 | + |
| 84 | + @staticmethod |
| 85 | + def _mult(B, A): |
| 86 | + C = [ |
| 87 | + A[0] * B[0] + A[1] * B[4] + A[2] * B[8] + A[3] * B[12], |
| 88 | + A[0] * B[1] + A[1] * B[5] + A[2] * B[9] + A[3] * B[13], |
| 89 | + A[0] * B[2] + A[1] * B[6] + A[2] * B[10] + A[3] * B[14], |
| 90 | + A[0] * B[3] + A[1] * B[7] + A[2] * B[11] + A[3] * B[15], |
| 91 | + A[4] * B[0] + A[5] * B[4] + A[6] * B[8] + A[7] * B[12], |
| 92 | + A[4] * B[1] + A[5] * B[5] + A[6] * B[9] + A[7] * B[13], |
| 93 | + A[4] * B[2] + A[5] * B[6] + A[6] * B[10] + A[7] * B[14], |
| 94 | + A[4] * B[3] + A[5] * B[7] + A[6] * B[11] + A[7] * B[15], |
| 95 | + A[8] * B[0] + A[9] * B[4] + A[10] * B[8] + A[11] * B[12], |
| 96 | + A[8] * B[1] + A[9] * B[5] + A[10] * B[9] + A[11] * B[13], |
| 97 | + A[8] * B[2] + A[9] * B[6] + A[10] * B[10] + A[11] * B[14], |
| 98 | + A[8] * B[3] + A[9] * B[7] + A[10] * B[11] + A[11] * B[15], |
| 99 | + A[12] * B[0] + A[13] * B[4] + A[14] * B[8] + A[15] * B[12], |
| 100 | + A[12] * B[1] + A[13] * B[5] + A[14] * B[9] + A[15] * B[13], |
| 101 | + A[12] * B[2] + A[13] * B[6] + A[14] * B[10] + A[15] * B[14], |
| 102 | + A[12] * B[3] + A[13] * B[7] + A[14] * B[11] + A[15] * B[15], |
| 103 | + ] |
| 104 | + return C |
| 105 | + |
| 106 | + @staticmethod |
| 107 | + def _nicemult(B, A): |
| 108 | + C = [ |
| 109 | + A[0] * B[0], 0.0, 0.0, 0.0, |
| 110 | + 0.0, A[5] * B[5], 0.0, 0.0, |
| 111 | + 0.0, 0.0, A[10] * B[10], 0.0, |
| 112 | + A[12] * B[0] + B[12], A[13] * B[5] + B[13], A[14] * B[10] + B[14], 1.0, |
54 | 113 | ] |
| 114 | + return C |
| 115 | + |
| 116 | + def __str__(self): |
| 117 | + s = "" |
| 118 | + for i in range(4): |
| 119 | + s += " [" + ",".join("%d" % self.m[4*j+i] for j in range(4)) + "],\n" |
| 120 | + return "[\n" + s + "]\n" |
| 121 | + |
| 122 | + def __eq__(self, other): |
| 123 | + return self.m == other.m |
| 124 | + |
| 125 | +if __name__ == "__main__": |
| 126 | + assert Matrix().translate(1,2).translate(3,4) == Matrix().translate(4,6) |
| 127 | + assert Matrix().scale(1,2).scale(3,4) == Matrix().scale(3,8) |
| 128 | + assert Matrix().scale(2,3).translate(4,5) == Matrix().translate(8,15).scale(2,3) |
| 129 | + assert Matrix().scale(2,3).translate(4,5) == Matrix().scale(2,3) * Matrix().translate(4,5) |
| 130 | + assert Matrix(nice=False).translate(1,2).translate(3,4) == Matrix().translate(4,6) |
| 131 | + assert Matrix(nice=False).scale(1,2).scale(3,4) == Matrix().scale(3,8) |
| 132 | + assert Matrix(nice=False).scale(2,3).translate(4,5) == Matrix().translate(8,15).scale(2,3) |
| 133 | + assert Matrix(nice=False).scale(2,3).translate(4,5) == Matrix().scale(2,3) * Matrix().translate(4,5) |
0 commit comments