65 assert is_real(scalar) |
65 assert is_real(scalar) |
66 return type(self)(self.x // scalar, self.y // scalar, self.z // scalar) |
66 return type(self)(self.x // scalar, self.y // scalar, self.z // scalar) |
67 def __matmul__(self, transformation_matrix): |
67 def __matmul__(self, transformation_matrix): |
68 return transform(self, transformation_matrix) |
68 return transform(self, transformation_matrix) |
69 def __eq__(self, other): |
69 def __eq__(self, other): |
70 return all( |
70 return self.is_close(other, threshold = 1e-10) |
71 abs(a - b) < 1e-8 |
|
72 for a, b in zip(self.coordinates, other.coordinates) |
|
73 ) |
|
74 def __ne__(self, other): |
71 def __ne__(self, other): |
75 return not self.__eq__(other) |
72 return not self.__eq__(other) |
76 def __lt__(self, other): |
73 def __lt__(self, other): |
77 return self.coordinates < other.coordinates |
74 return self.coordinates < other.coordinates |
78 def __hash__(self): |
75 def __hash__(self): |
79 return hash(self.coordinates) |
76 return hash(self.coordinates) |
|
77 def is_close(self, other, *, threshold): |
|
78 return all( |
|
79 abs(a - b) < threshold |
|
80 for a, b in zip(self.coordinates, other.coordinates) |
|
81 ) |
80 |
82 |
81 class VertexOp: |
83 class VertexOp: |
82 def __init__(self, callable): |
84 def __init__(self, callable): |
83 self.callable = callable |
85 self.callable = callable |
84 def __rmul__(self, coordinate): |
86 def __rmul__(self, coordinate): |
261 +(self[0, 2] * self[1, 0] * self[2, 1]), |
263 +(self[0, 2] * self[1, 0] * self[2, 1]), |
262 -(self[0, 2] * self[1, 1] * self[2, 0]), |
264 -(self[0, 2] * self[1, 1] * self[2, 0]), |
263 -(self[0, 1] * self[1, 0] * self[2, 2]), |
265 -(self[0, 1] * self[1, 0] * self[2, 2]), |
264 -(self[0, 0] * self[1, 2] * self[2, 1]), |
266 -(self[0, 0] * self[1, 2] * self[2, 1]), |
265 ]) |
267 ]) |
266 @property |
|
267 def scaling_vector(self): |
268 def scaling_vector(self): |
268 ''' |
269 ''' |
269 Extracts scaling factors from this transformation matrix. |
270 Extracts scaling factors from this transformation matrix. |
270 ''' |
271 ''' |
271 from math import sqrt |
272 from math import sqrt |
272 return Vector( |
273 return Vector( |
273 x = sqrt(self[0, 0] ** 2 + self[1, 0] ** 2 + self[2, 0] ** 2), |
274 x = sqrt(self[0, 0] ** 2 + self[1, 0] ** 2 + self[2, 0] ** 2), |
274 y = sqrt(self[0, 1] ** 2 + self[1, 1] ** 2 + self[2, 1] ** 2), |
275 y = sqrt(self[0, 1] ** 2 + self[1, 1] ** 2 + self[2, 1] ** 2), |
275 z = sqrt(self[0, 2] ** 2 + self[1, 2] ** 2 + self[2, 2] ** 2), |
276 z = sqrt(self[0, 2] ** 2 + self[1, 2] ** 2 + self[2, 2] ** 2), |
276 ) |
277 ) |
277 @property |
|
278 def rotation_component(self): |
278 def rotation_component(self): |
279 ''' |
279 ''' |
280 Extracts rotation from this matrix. |
280 Extracts rotation from this matrix. |
281 ''' |
281 ''' |
282 return self.split()[0] |
282 return self.split()[0] |
283 def split(self): |
283 def split(self): |
284 ''' |
284 ''' |
285 Extracts the rotation matrix and scaling vector. |
285 Extracts the rotation matrix and scaling vector. |
286 ''' |
286 ''' |
287 vec = self.scaling_vector |
287 vec = self.scaling_vector() |
288 return Matrix3x3([ |
288 return Matrix3x3([ |
289 self[i, j] / vec.coordinates[j] |
289 self[i, j] / vec.coordinates[j] |
290 for i, j in matrix_indices() |
290 for i, j in matrix_indices() |
291 ]), vec |
291 ]), vec |
292 @property |
|
293 def contains_scaling(self): |
292 def contains_scaling(self): |
294 ''' |
293 ''' |
295 Returns whether this matrix contains scaling factors. |
294 Returns whether this matrix contains scaling factors. |
296 ''' |
295 ''' |
297 vec = self.scaling_vector |
296 vec = self.scaling_vector() |
298 return abs((vec.x * vec.y * vec.z) - 1) >= 1e-10 |
297 return abs((vec.x * vec.y * vec.z) - 1) >= 1e-10 |
299 @property |
|
300 def contains_rotation(self): |
298 def contains_rotation(self): |
301 ''' |
299 ''' |
302 Returns whether this matrix contains rotation factors. |
300 Returns whether this matrix contains rotation factors. |
303 ''' |
301 ''' |
304 return self.rotation_component != Matrix3x3() |
302 return self.rotation_component() != Matrix3x3() |
305 def __eq__(self, other): |
303 def __eq__(self, other): |
306 ''' |
304 ''' |
307 Returns whether two matrices are equivalent. |
305 Returns whether two matrices are equivalent. |
308 ''' |
306 ''' |
309 return all( |
307 return all( |