def matrix_from_scale_factors(scale_factors, rtype='list'): """Returns a 4x4 scaling transformation. Parameters ---------- scale_factors : list of float Three numbers defining the scaling factors in x, y, and z respectively. Examples -------- >>> Sc = matrix_from_scale_factors([1, 2, 3]) Notes ----- .. code-block:: python [ 0 . . . ] [ . 1 . . ] [ . . 2 . ] [ . . . . ] """ M = identity_matrix(4) M[0][0] = float(scale_factors[0]) M[1][1] = float(scale_factors[1]) M[2][2] = float(scale_factors[2]) if rtype == 'list': return M if rtype == 'array': from numpy import asarray return asarray(M) raise NotImplementedError
def from_list(cls, numbers): """Creates a ``Transformation`` from a list of 16 numbers. Parameters ---------- numbers : :obj:`list` of :obj:`float` A list of 16 numbers Returns ------- Transformation The ``Transformation`` object. Examples -------- >>> numbers = [1, 0, 0, 3, 0, 1, 0, 4, 0, 0, 1, 5, 0, 0, 0, 1] >>> T = Transformation.from_list(numbers) Notes ----- Since the transformation matrix follows the row-major order, the translational components must be at the list's indices 3, 7, 11. """ matrix = identity_matrix(4) for i in range(4): for j in range(4): matrix[i][j] = float(numbers[i * 4 + j]) return cls(matrix)
def matrix_from_parallel_projection(point, normal, direction): """Returns an parallel projection matrix to project onto a plane defined by point, normal and direction. Parameters ---------- point : list of float Base point of the plane. normal : list of float Normal vector of the plane. direction : list of float Direction of the projection. Examples -------- >>> point = [0, 0, 0] >>> normal = [0, 0, 1] >>> direction = [1, 1, 1] >>> P = matrix_from_parallel_projection(point, normal, direction) """ T = identity_matrix(4) normal = normalize_vector(normal) scale = dot_vectors(direction, normal) for j in range(3): for i in range(3): T[i][j] -= direction[i] * normal[j] / scale T[0][3], T[1][3], T[2][3] = scale_vector( direction, dot_vectors(point, normal) / scale) return T
def matrix_from_shear_entries(shear_entries): """Returns a shear matrix from the 3 factors for x-y, x-z, and y-z axes. Parameters ---------- shear_entries : list of float The 3 shear factors for x-y, x-z, and y-z axes. Examples -------- >>> Sh = matrix_from_shear_entries([1, 2, 3]) Notes ----- .. code-block:: python [ . 0 1 . ] [ . . 2 . ] [ . . . . ] [ . . . . ] """ M = identity_matrix(4) M[0][1] = float(shear_entries[0]) M[0][2] = float(shear_entries[1]) M[1][2] = float(shear_entries[2]) return M
def matrix_from_translation(translation, rtype='list'): """Returns a 4x4 translation matrix in row-major order. Parameters ---------- translation : list of float The x, y and z components of the translation. Examples -------- >>> T = matrix_from_translation([1, 2, 3]) Notes ----- .. code-block:: python [ . . . 0 ] [ . . . 1 ] [ . . . 2 ] [ . . . . ] """ M = identity_matrix(4) M[0][3] = float(translation[0]) M[1][3] = float(translation[1]) M[2][3] = float(translation[2]) if rtype == 'list': return M if rtype == 'array': from numpy import asarray return asarray(M) raise NotImplementedError
def matrix_from_orthogonal_projection(point, normal): """Returns an orthogonal projection matrix to project onto a plane defined by point and normal. Parameters ---------- point : list of float Base point of the plane. normal : list of float Normal vector of the plane. Examples -------- >>> point = [0, 0, 0] >>> normal = [0, 0, 1] >>> P = matrix_from_orthogonal_projection(point, normal) """ T = identity_matrix(4) normal = normalize_vector(normal) for j in range(3): for i in range(3): T[i][j] -= normal[i] * normal[j] # outer_product T[0][3], T[1][3], T[2][3] = scale_vector(normal, dot_vectors(point, normal)) return T
def matrix_from_basis_vectors(xaxis, yaxis): """Creates a rotation matrix from basis vectors (= orthonormal vectors). Parameters ---------- xaxis : list of float The x-axis of the frame. yaxis : list of float The y-axis of the frame. Examples -------- >>> xaxis = [0.68, 0.68, 0.27] >>> yaxis = [-0.67, 0.73, -0.15] >>> R = matrix_from_basis_vectors(xaxis, yaxis) """ xaxis = normalize_vector(list(xaxis)) yaxis = normalize_vector(list(yaxis)) zaxis = cross_vectors(xaxis, yaxis) yaxis = cross_vectors(zaxis, xaxis) # correction R = identity_matrix(4) R[0][0], R[1][0], R[2][0] = xaxis R[0][1], R[1][1], R[2][1] = yaxis R[0][2], R[1][2], R[2][2] = zaxis return R
def from_plane(cls, plane): """Construct a reflection transformation that mirrors wrt the given plane. Parameters ---------- plane : [point, vector] | :class:`compas.geometry.Plane` The reflection plane. Returns ------- :class:`compas.geometry.Reflection` The reflection transformation. """ point, normal = plane normal = normalize_vector((list(normal))) matrix = identity_matrix(4) for i in range(3): for j in range(3): matrix[i][j] -= 2.0 * normal[i] * normal[j] for i in range(3): matrix[i][3] = 2 * dot_vectors(point, normal) * normal[i] R = cls() R.matrix = matrix return R
def from_list(cls, numbers): """Creates a transformation from a list of 16 numbers. Parameters ---------- numbers : list[float] A list of 16 numbers Returns ------- :class:`compas.geometry.Transformation` The transformation. Notes ----- Since the transformation matrix follows the row-major order, the translational components must be at the list's indices 3, 7, 11. Examples -------- >>> numbers = [1, 0, 0, 3, 0, 1, 0, 4, 0, 0, 1, 5, 0, 0, 0, 1] >>> T = Transformation.from_list(numbers) """ matrix = identity_matrix(4) for i in range(4): for j in range(4): matrix[i][j] = float(numbers[i * 4 + j]) return cls(matrix)
def __init__(self, matrix=None): """Construct a transformation from a 4x4 transformation matrix. """ super(Transformation, self).__init__() if not matrix: matrix = identity_matrix(4) self.matrix = matrix
def matrix_from_frame(frame): """Computes a change of basis transformation from world XY to the frame. Parameters ---------- frame : :class:`compas.geometry.Frame` A frame describing the targeted Cartesian coordinate system Examples -------- >>> from compas.geometry import Frame >>> f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) >>> T = matrix_from_frame(f) """ M = identity_matrix(4) M[0][0], M[1][0], M[2][0] = frame.xaxis M[0][1], M[1][1], M[2][1] = frame.yaxis M[0][2], M[1][2], M[2][2] = frame.zaxis M[0][3], M[1][3], M[2][3] = frame.point return M
def matrix_from_perspective_projection(point, normal, perspective): """Returns a perspective projection matrix to project onto a plane defined by point, normal and perspective. Parameters ---------- point : list of float Base point of the projection plane. normal : list of float Normal vector of the projection plane. perspective : list of float Perspective of the projection. Examples -------- >>> point = [0, 0, 0] >>> normal = [0, 0, 1] >>> perspective = [1, 1, 0] >>> P = matrix_from_perspective_projection(point, normal, perspective) """ T = identity_matrix(4) normal = normalize_vector(normal) T[0][0] = T[1][1] = T[2][2] = dot_vectors( subtract_vectors(perspective, point), normal) for j in range(3): for i in range(3): T[i][j] -= perspective[i] * normal[j] T[0][3], T[1][3], T[2][3] = scale_vector(perspective, dot_vectors(point, normal)) for i in range(3): T[3][i] -= normal[i] T[3][3] = dot_vectors(perspective, normal) return T
def matrix_from_perspective_entries(perspective): """Returns a matrix from perspective entries. Parameters ---------- values : list of float The 4 perspective entries of a matrix. Notes ----- .. code-block:: python [ . . . . ] [ . . . . ] [ . . . . ] [ 0 1 2 3 ] """ M = identity_matrix(4) M[3][0] = float(perspective[0]) M[3][1] = float(perspective[1]) M[3][2] = float(perspective[2]) M[3][3] = float(perspective[3]) return M
def __init__(self, matrix=None): if not matrix: matrix = identity_matrix(4) self.matrix = matrix
def test_identity_matrix(): assert identity_matrix(4) == [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]]
def __init__(self, matrix=None): super(Transformation, self).__init__() if not matrix: matrix = identity_matrix(4) self.matrix = matrix