Tue, 12 Dec 2017 13:46:17 +0200
Added vertex operators
| 0 | 1 | class Vertex: |
| 2 | def __init__(self, x, y, z): | |
| 5 | 3 | if not all(is_real(coordinate) for coordinate in (x, y, z)): |
| 4 | raise ValueError(str.format('Bad vertex coordinates: {!r}', | |
| 5 | (x, y, z), | |
| 6 | )) | |
| 0 | 7 | self.x, self.y, self.z = x, y, z |
| 8 | def __repr__(self): | |
| 9 | return str.format('Vertex({!r}, {!r}, {!r})', self.x, self.y, self.z) | |
| 10 | def distance_to(self, other): | |
| 11 | # can't use hypot because of 3 arguments | |
| 12 | from math import sqrt | |
| 13 | return sqrt( | |
| 14 | (self.x - other.x) ** 2 + | |
| 15 | (self.y - other.y) ** 2 + | |
| 16 | (self.z - other.z) ** 2 | |
| 17 | ) | |
|
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
18 | @property |
|
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
19 | def coordinates(self): |
|
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
20 | return self.x, self.y, self.z |
| 5 | 21 | def __add__(self, other): |
| 22 | return Vertex(self.x + other.x, self.y + other.y, self.z + other.z) | |
| 23 | def __neg__(self): | |
| 24 | return Vertex(-self.x, -self.y, -self.z) | |
| 25 | def __sub__(self, other): | |
| 26 | return self + (-other) | |
| 27 | def __mul__(self, scalar): | |
| 28 | return Vertex(self.x * scalar, self.y * scalar, self.z * scalar) | |
| 29 | def __rmul__(self, other): | |
| 30 | return self * other | |
| 31 | def __truediv__(self, scalar): | |
| 32 | return Vertex(self.x / scalar, self.y / scalar, self.z / scalar) | |
| 33 | def __floordiv__(self, scalar): | |
| 34 | return Vertex(self.x // scalar, self.y // scalar, self.z // scalar) | |
| 35 | def __matmul__(self, transformation_matrix): | |
| 36 | return transform(self, transformation_matrix) | |
| 37 | def __eq__(self, other): | |
| 38 | return self.coordinates == other.coordinates | |
| 39 | def __lt__(self, other): | |
| 40 | return self.coordinates < other.coordinates | |
| 41 | def __hash__(self): | |
| 42 | return hash(self.coordinates) | |
| 43 | ||
| 44 | class VertexOp: | |
| 45 | def __init__(self, callable): | |
| 46 | self.callable = callable | |
| 47 | def __rmul__(self, coordinate): | |
| 48 | return self.callable(coordinate) | |
| 0 | 49 | |
| 50 | class LineSegment: | |
| 51 | def __init__(self, v1, v2): | |
| 52 | self.v1, self.v2 = v1, v2 | |
| 53 | def __repr__(self): | |
| 54 | return str.format('LineSegment({!r}, {!r})', self.v1, self.v2) | |
|
3
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
55 | @property |
|
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
56 | def vertices(self): |
|
1dc58f44d556
Can now write dat files, added direct color handling
Santeri Piippo
parents:
1
diff
changeset
|
57 | return self.v1, self.v2 |
| 0 | 58 | |
| 1 | 59 | class Polygon: |
| 60 | def __init__(self, vertices): | |
| 61 | self.vertices = vertices | |
| 62 | def __repr__(self): | |
| 63 | return str.format('Polygon({!r})', self.vertices) | |
| 64 | ||
| 0 | 65 | def is_real(number): |
| 66 | return isinstance(number, int) or isinstance(number, float) | |
| 67 | ||
| 68 | class TransformationMatrix: | |
| 69 | ''' | |
| 70 | A 3×3 matrix forming the top-left portion of a full 4×4 transformation | |
| 71 | matrix. | |
| 72 | ''' | |
| 73 | def __init__(self, values): | |
| 74 | assert(all(is_real(x) for x in values)) | |
| 75 | assert len(values) == 9 | |
| 76 | self.values = values | |
| 77 | def __repr__(self): | |
| 78 | return str.format('TransformationMatrix({!r})', self.values) | |
| 79 | def __getitem__(self, index): | |
| 80 | return self.values[index] | |
| 81 | ||
| 82 | def complete_matrix(matrix, anchor): | |
| 83 | ''' | |
| 84 | Combines a 3×3 matrix and an anchor vertex into a full 4×4 | |
| 85 | transformation matrix. | |
| 86 | ''' | |
| 87 | return [ | |
| 88 | matrix[0], matrix[1], matrix[2], anchor.x, | |
| 89 | matrix[3], matrix[4], matrix[5], anchor.y, | |
| 90 | matrix[6], matrix[7], matrix[8], anchor.z, | |
| 91 | 0, 0, 0, 1, | |
| 92 | ] | |
| 93 | ||
| 94 | def transform(vertex, transformation_matrix): | |
| 95 | ''' | |
| 96 | Transforms a vertex by a 4×4 transformation matrix. | |
| 97 | ''' | |
| 98 | u = transformation_matrix[0] * vertex.x \ | |
| 99 | + transformation_matrix[1] * vertex.y \ | |
| 100 | + transformation_matrix[2] * vertex.z \ | |
| 101 | + transformation_matrix[3] | |
| 102 | v = transformation_matrix[4] * vertex.x \ | |
| 103 | + transformation_matrix[5] * vertex.y \ | |
| 104 | + transformation_matrix[6] * vertex.z \ | |
| 105 | + transformation_matrix[7] | |
| 106 | w = transformation_matrix[8] * vertex.x \ | |
| 107 | + transformation_matrix[9] * vertex.y \ | |
| 108 | + transformation_matrix[10] * vertex.z \ | |
| 109 | + transformation_matrix[11] | |
| 110 | return Vertex(u, v, w) |