Code cleanup: comments and typos
[blender.git] / source / tests / bl_pyapi_mathutils.py
1 # ./blender.bin --background -noaudio --python source/tests/bl_pyapi_mathutils.py
2 import unittest
3 from test import support
4 from mathutils import Matrix, Vector
5 from mathutils import kdtree
6 import math
7
8 # keep globals immutable
9 vector_data = (
10     (1.0, 0.0, 0.0),
11     (0.0, 1.0, 0.0),
12     (0.0, 0.0, 1.0),
13
14     (1.0, 1.0, 1.0),
15
16     (0.33783, 0.715698, -0.611206),
17     (-0.944031, -0.326599, -0.045624),
18     (-0.101074, -0.416443, -0.903503),
19     (0.799286, 0.49411, -0.341949),
20     (-0.854645, 0.518036, 0.033936),
21     (0.42514, -0.437866, -0.792114),
22     (-0.358948, 0.597046, 0.717377),
23     (-0.985413,0.144714, 0.089294),
24     )
25
26 # get data at different scales
27 vector_data = sum(
28     (tuple(tuple(a * scale for a in v) for v in vector_data)
29     for scale in (s * sign for s in (0.0001, 0.1, 1.0, 10.0, 1000.0, 100000.0)
30                            for sign in (1.0, -1.0))), ()) + ((0.0, 0.0, 0.0),)
31
32
33 class MatrixTesting(unittest.TestCase):
34     def test_matrix_column_access(self):
35         #mat =
36         #[ 1  2  3  4 ]
37         #[ 1  2  3  4 ]
38         #[ 1  2  3  4 ]
39         mat = Matrix(((1, 11, 111),
40                       (2, 22, 222),
41                       (3, 33, 333),
42                       (4, 44, 444)))
43
44         self.assertEqual(mat[0], Vector((1, 11, 111)))
45         self.assertEqual(mat[1], Vector((2, 22, 222)))
46         self.assertEqual(mat[2], Vector((3, 33, 333)))
47         self.assertEqual(mat[3], Vector((4, 44, 444)))
48
49     def test_item_access(self):
50         args = ((1, 4, 0, -1),
51                 (2, -1, 2, -2),
52                 (0, 3, 8, 3),
53                 (-2, 9, 1, 0))
54
55         mat = Matrix(args)
56
57         for row in range(4):
58             for col in range(4):
59                 self.assertEqual(mat[row][col], args[row][col])
60
61         self.assertEqual(mat[0][2], 0)
62         self.assertEqual(mat[3][1], 9)
63         self.assertEqual(mat[2][3], 3)
64         self.assertEqual(mat[0][0], 1)
65         self.assertEqual(mat[3][3], 0)
66
67     def test_item_assignment(self):
68         mat = Matrix() - Matrix()
69         indices = (0, 0), (1, 3), (2, 0), (3, 2), (3, 1)
70         checked_indices = []
71         for row, col in indices:
72             mat[row][col] = 1
73
74         for row in range(4):
75             for col in range(4):
76                 if mat[row][col]:
77                     checked_indices.append((row, col))
78
79         for item in checked_indices:
80             self.assertIn(item, indices)
81
82     def test_matrix_to_3x3(self):
83         #mat =
84         #[ 1  2  3  4  ]
85         #[ 2  4  6  8  ]
86         #[ 3  6  9  12 ]
87         #[ 4  8  12 16 ]
88         mat = Matrix(tuple((i, 2 * i, 3 * i, 4 * i) for i in range(1, 5)))
89         mat_correct = Matrix(((1, 2, 3), (2, 4, 6), (3, 6, 9)))
90         self.assertEqual(mat.to_3x3(), mat_correct)
91
92     def test_matrix_to_translation(self):
93         mat = Matrix()
94         mat[0][3] = 1
95         mat[1][3] = 2
96         mat[2][3] = 3
97         self.assertEqual(mat.to_translation(), Vector((1, 2, 3)))
98
99     def test_matrix_translation(self):
100         mat = Matrix()
101         mat.translation = Vector((1, 2, 3))
102         self.assertEqual(mat[0][3], 1)
103         self.assertEqual(mat[1][3], 2)
104         self.assertEqual(mat[2][3], 3)
105
106     def test_non_square_mult(self):
107         mat1 = Matrix(((1, 2, 3),
108                        (4, 5, 6)))
109         mat2 = Matrix(((1, 2),
110                        (3, 4),
111                        (5, 6)))
112
113         prod_mat1 = Matrix(((22, 28),
114                             (49, 64)))
115         prod_mat2 = Matrix(((9, 12, 15),
116                             (19, 26, 33),
117                             (29, 40, 51)))
118
119         self.assertEqual(mat1 * mat2, prod_mat1)
120         self.assertEqual(mat2 * mat1, prod_mat2)
121
122     def test_mat4x4_vec3D_mult(self):
123         mat = Matrix(((1, 0, 2, 0),
124                       (0, 6, 0, 0),
125                       (0, 0, 1, 1),
126                       (0, 0, 0, 1)))
127
128         vec = Vector((1, 2, 3))
129         
130         prod_mat_vec = Vector((7, 12, 4))
131         prod_vec_mat = Vector((1, 12, 5))
132
133         self.assertEqual(mat * vec, prod_mat_vec)
134         self.assertEqual(vec * mat, prod_vec_mat)
135
136     def test_mat_vec_mult(self):
137         mat1 = Matrix()
138
139         vec = Vector((1, 2))
140
141         self.assertRaises(ValueError, mat1.__mul__, vec)
142         self.assertRaises(ValueError, vec.__mul__, mat1)
143
144         mat2 = Matrix(((1, 2),
145                        (-2, 3)))
146
147         prod = Vector((5, 4))
148
149         self.assertEqual(mat2 * vec, prod)
150
151     def test_matrix_inverse(self):
152         mat = Matrix(((1, 4, 0, -1),
153                       (2, -1, 2, -2),
154                       (0, 3, 8, 3),
155                       (-2, 9, 1, 0)))
156
157         inv_mat = (1 / 285) * Matrix(((195, -57, 27, -102),
158                                       (50, -19, 4, 6),
159                                       (-60, 57, 18, 27),
160                                       (110, -133, 43, -78)))
161
162         self.assertEqual(mat.inverted(), inv_mat)
163
164     def test_matrix_mult(self):
165         mat = Matrix(((1, 4, 0, -1),
166                       (2, -1, 2, -2),
167                       (0, 3, 8, 3),
168                       (-2, 9, 1, 0)))
169
170         prod_mat = Matrix(((11, -9, 7, -9),
171                            (4, -3, 12, 6),
172                            (0, 48, 73, 18),
173                            (16, -14, 26, -13)))
174
175         self.assertEqual(mat * mat, prod_mat)
176
177
178 class VectorTesting(unittest.TestCase):
179
180     def test_orthogonal(self):
181
182         angle_90d = math.pi / 2.0
183         for v in vector_data:
184             v = Vector(v)
185             if v.length_squared != 0.0:
186                 self.assertAlmostEqual(v.angle(v.orthogonal()), angle_90d)
187
188
189 class KDTreeTesting(unittest.TestCase):
190
191     @staticmethod
192     def kdtree_create_grid_3d(tot):
193         k = kdtree.KDTree(tot * tot * tot)
194         index = 0
195         mul = 1.0 / (tot - 1)
196         for x in range(tot):
197             for y in range(tot):
198                 for z in range(tot):
199                     k.insert((x * mul, y * mul, z * mul), index)
200                     index += 1
201         k.balance()
202         return k
203
204     def test_kdtree_single(self):
205         co = (0,) * 3
206         index = 2
207
208         k = kdtree.KDTree(1)
209         k.insert(co, index)
210         k.balance()
211
212         co_found, index_found, dist_found = k.find(co)
213
214         self.assertEqual(tuple(co_found), co)
215         self.assertEqual(index_found, index)
216         self.assertEqual(dist_found, 0.0)
217
218     def test_kdtree_empty(self):
219         co = (0,) * 3
220
221         k = kdtree.KDTree(0)
222         k.balance()
223
224         co_found, index_found, dist_found = k.find(co)
225
226         self.assertIsNone(co_found)
227         self.assertIsNone(index_found)
228         self.assertIsNone(dist_found)
229
230     def test_kdtree_line(self):
231         tot = 10
232
233         k = kdtree.KDTree(tot)
234
235         for i in range(tot):
236             k.insert((i,) * 3, i)
237
238         k.balance()
239
240         co_found, index_found, dist_found = k.find((-1,) * 3)
241         self.assertEqual(tuple(co_found), (0,) * 3)
242
243         co_found, index_found, dist_found = k.find((tot,) * 3)
244         self.assertEqual(tuple(co_found), (tot - 1,) * 3)
245
246     def test_kdtree_grid(self):
247         size = 10
248         k = self.kdtree_create_grid_3d(size)
249
250         # find_range
251         ret = k.find_range((0.5,) * 3, 2.0)
252         self.assertEqual(len(ret), size * size * size)
253
254         ret = k.find_range((1.0,) * 3, 1.0 / size)
255         self.assertEqual(len(ret), 1)
256
257         ret = k.find_range((1.0,) * 3, 2.0 / size)
258         self.assertEqual(len(ret), 8)
259
260         ret = k.find_range((10,) * 3, 0.5)
261         self.assertEqual(len(ret), 0)
262
263         # find_n
264         tot = 0
265         ret = k.find_n((1.0,) * 3, tot)
266         self.assertEqual(len(ret), tot)
267
268         tot = 10
269         ret = k.find_n((1.0,) * 3, tot)
270         self.assertEqual(len(ret), tot)
271         self.assertEqual(ret[0][2], 0.0)
272
273         tot = size * size * size
274         ret = k.find_n((1.0,) * 3, tot)
275         self.assertEqual(len(ret), tot)
276
277     def test_kdtree_invalid_size(self):
278         with self.assertRaises(ValueError):
279             kdtree.KDTree(-1)
280
281     def test_kdtree_invalid_balance(self):
282         co = (0,) * 3
283         index = 2
284
285         k = kdtree.KDTree(2)
286         k.insert(co, index)
287         k.balance()
288         k.insert(co, index)
289         with self.assertRaises(RuntimeError):
290             k.find(co)
291
292
293 def test_main():
294     try:
295         support.run_unittest(MatrixTesting)
296         support.run_unittest(VectorTesting)
297         support.run_unittest(KDTreeTesting)
298     except:
299         import traceback
300         traceback.print_exc()
301
302         # alert CTest we failed
303         import sys
304         sys.exit(1)
305
306 if __name__ == '__main__':
307     test_main()