--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/geometry.py Sun Dec 10 15:37:26 2017 +0200 @@ -0,0 +1,66 @@ +class Vertex: + def __init__(self, x, y, z): + self.x, self.y, self.z = x, y, z + def __repr__(self): + return str.format('Vertex({!r}, {!r}, {!r})', self.x, self.y, self.z) + def distance_to(self, other): + # can't use hypot because of 3 arguments + from math import sqrt + return sqrt( + (self.x - other.x) ** 2 + + (self.y - other.y) ** 2 + + (self.z - other.z) ** 2 + ) + +class LineSegment: + def __init__(self, v1, v2): + self.v1, self.v2 = v1, v2 + def __repr__(self): + return str.format('LineSegment({!r}, {!r})', self.v1, self.v2) + +def is_real(number): + return isinstance(number, int) or isinstance(number, float) + +class TransformationMatrix: + ''' + A 3×3 matrix forming the top-left portion of a full 4×4 transformation + matrix. + ''' + def __init__(self, values): + assert(all(is_real(x) for x in values)) + assert len(values) == 9 + self.values = values + def __repr__(self): + return str.format('TransformationMatrix({!r})', self.values) + def __getitem__(self, index): + return self.values[index] + +def complete_matrix(matrix, anchor): + ''' + Combines a 3×3 matrix and an anchor vertex into a full 4×4 + transformation matrix. + ''' + return [ + matrix[0], matrix[1], matrix[2], anchor.x, + matrix[3], matrix[4], matrix[5], anchor.y, + matrix[6], matrix[7], matrix[8], anchor.z, + 0, 0, 0, 1, + ] + +def transform(vertex, transformation_matrix): + ''' + Transforms a vertex by a 4×4 transformation matrix. + ''' + u = transformation_matrix[0] * vertex.x \ + + transformation_matrix[1] * vertex.y \ + + transformation_matrix[2] * vertex.z \ + + transformation_matrix[3] + v = transformation_matrix[4] * vertex.x \ + + transformation_matrix[5] * vertex.y \ + + transformation_matrix[6] * vertex.z \ + + transformation_matrix[7] + w = transformation_matrix[8] * vertex.x \ + + transformation_matrix[9] * vertex.y \ + + transformation_matrix[10] * vertex.z \ + + transformation_matrix[11] + return Vertex(u, v, w)