def test_decompose_matrix(R, T): assert decompose_matrix(R.matrix) == ([1.0, 1.0, 1.0], [0.0, 0.0, 0.0], [2.035405699485789, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 1.0]) assert decompose_matrix(T.matrix) == ([1.0, 1.0, 1.0], [0.0, 0.0, 0.0], [0.0, -0.0, 0.0], [1.0, 2.0, 3.0], [0.0, 0.0, 0.0, 1.0])
def __init__(self, matrix=None): if matrix: _, _, _, _, perspective = decompose_matrix(matrix) check = matrix_from_perspective_entries(perspective) if not allclose(flatten(matrix), flatten(check)): raise ValueError('This is not a proper projection matrix.') super(Projection, self).__init__(matrix=matrix)
def __init__(self, matrix=None): if matrix: _, _, _, translation, _ = decompose_matrix(matrix) check = matrix_from_translation(translation) if not allclose(flatten(matrix), flatten(check)): raise ValueError('This is not a proper translation matrix.') super(Translation, self).__init__(matrix=matrix)
def __init__(self, matrix=None): if matrix: _, _, angles, _, _ = decompose_matrix(matrix) check = matrix_from_euler_angles(angles) if not allclose(flatten(matrix), flatten(check)): raise ValueError('This is not a proper rotation matrix.') super(Rotation, self).__init__(matrix=matrix)
def from_matrix(cls, matrix): """Construct a frame from a matrix. Parameters ---------- matrix : :obj:`list` of :obj:`list` of :obj:`float` The 4x4 transformation matrix in row-major order. Returns ------- Frame The constructed frame. Examples -------- >>> from compas.geometry import Frame >>> from compas.geometry import matrix_from_euler_angles >>> ea1 = [0.5, 0.4, 0.8] >>> M = matrix_from_euler_angles(ea1) >>> f = Frame.from_matrix(M) >>> ea2 = f.euler_angles() >>> allclose(ea1, ea2) True """ sc, sh, a, point, p = decompose_matrix(matrix) R = matrix_from_euler_angles(a, static=True, axes='xyz') xaxis, yaxis = basis_vectors_from_matrix(R) return cls(point, xaxis, yaxis)
def __init__(self, matrix=None): if matrix: scale, _, _, _, _ = decompose_matrix(matrix) check = matrix_from_scale_factors(scale) if not allclose(flatten(matrix), flatten(check)): raise ValueError('This is not a proper scale matrix.') super(Scale, self).__init__(matrix=matrix)
def decompose(self): """Decomposes the ``Transformation`` into ``Scale``, ``Shear``, \ ``Rotation``, ``Translation`` and ``Perspective``. Example: >>> trans1 = [1, 2, 3] >>> angle1 = [-2.142, 1.141, -0.142] >>> scale1 = [0.123, 2, 0.5] >>> T1 = Translation(trans1) >>> R1 = Rotation.from_euler_angles(angle1) >>> S1 = Scale(scale1) >>> M = (T1 * R1) * S1 >>> Sc, Sh, R, T, P = M.decompose() >>> S1 == Sc True >>> R1 == R True >>> T1 == T True """ from compas.geometry.xforms import Scale from compas.geometry.xforms import Shear from compas.geometry.xforms import Rotation from compas.geometry.xforms import Translation from compas.geometry.xforms import Projection sc, sh, a, t, p = decompose_matrix(self.matrix) Sc = Scale(sc) Sh = Shear.from_entries(sh) R = Rotation.from_euler_angles(a, static=True, axes='xyz') T = Translation(t) P = Projection.from_entries(p) return Sc, Sh, R, T, P
def basis_vectors(self): """Returns the basis vectors from the ``Rotation`` component of the ``Transformation``. """ sc, sh, a, t, p = decompose_matrix(self.matrix) R = matrix_from_euler_angles(a, static=True, axes='xyz') xv, yv = basis_vectors_from_matrix(R) return Vector(*xv), Vector(*yv)
def basis_vectors(self): """Returns the basis vectors from the ``Rotation`` component of the ``Transformation``. """ # this has to be here to avoid circular import from compas.geometry.primitives import Vector sc, sh, a, t, p = decompose_matrix(self.matrix) R = matrix_from_euler_angles(a, static=True, axes='xyz') xv, yv = basis_vectors_from_matrix(R) return Vector(*xv), Vector(*yv)
def decomposed(self): """Decompose the `Transformation` into its components. Returns ------- :class:`compas.geometry.Scale` The scale component of the current transformation. :class:`compas.geometry.Shear` The shear component of the current transformation. :class:`compas.geometry.Rotation` The rotation component of the current transformation. :class:`compas.geometry.Translation` The translation component of the current transformation. :class:`compas.geometry.Projection` The projection component of the current transformation. Examples -------- >>> from compas.geometry import Scale, Translation, Rotation >>> trans1 = [1, 2, 3] >>> angle1 = [-2.142, 1.141, -0.142] >>> scale1 = [0.123, 2, 0.5] >>> T1 = Translation.from_vector(trans1) >>> R1 = Rotation.from_euler_angles(angle1) >>> S1 = Scale.from_factors(scale1) >>> M = T1 * R1 * S1 >>> S, H, R, T, P = M.decomposed() >>> S1 == S True >>> R1 == R True >>> T1 == T True """ from compas.geometry import Scale # noqa: F811 from compas.geometry import Shear from compas.geometry import Rotation # noqa: F811 from compas.geometry import Translation # noqa: F811 from compas.geometry import Projection s, h, a, t, p = decompose_matrix(self.matrix) S = Scale.from_factors(s) H = Shear.from_entries(h) R = Rotation.from_euler_angles(a, static=True, axes='xyz') T = Translation.from_vector(t) P = Projection.from_entries(p) return S, H, R, T, P
def decomposed(self): """Decompose the ``Transformation`` into its ``Scale``, ``Shear``, ``Rotation``, ``Translation`` and ``Perspective`` components. Returns ------- 5-tuple of Transformation The scale, shear, rotation, tranlation, and projection components of the current transformation. Examples -------- >>> trans1 = [1, 2, 3] >>> angle1 = [-2.142, 1.141, -0.142] >>> scale1 = [0.123, 2, 0.5] >>> T1 = Translation(trans1) >>> R1 = Rotation.from_euler_angles(angle1) >>> S1 = Scale(scale1) >>> M = (T1 * R1) * S1 >>> Sc, Sh, R, T, P = M.decomposed() >>> S1 == Sc True >>> R1 == R True >>> T1 == T True """ from compas.geometry.transformations import Scale # noqa: F811 from compas.geometry.transformations import Shear from compas.geometry.transformations import Rotation # noqa: F811 from compas.geometry.transformations import Translation # noqa: F811 from compas.geometry.transformations import Projection sc, sh, a, t, p = decompose_matrix(self.matrix) Sc = Scale(sc) Sh = Shear.from_entries(sh) R = Rotation.from_euler_angles(a, static=True, axes='xyz') T = Translation(t) P = Projection.from_entries(p) return Sc, Sh, R, T, P
f1 = Frame([2, 2, 2], [0.12, 0.58, 0.81], [-0.80, 0.53, -0.26]) f2 = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame_to_frame(f1, f2) f1.transform(T) print(f1 == f2) f = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame(f) p = Point(0, 0, 0) p.transform(T) print(allclose(f.point, p)) f1 = Frame([1, 1, 1], [0.68, 0.68, 0.27], [-0.67, 0.73, -0.15]) T = Transformation.from_frame(f1) points = [[1.0, 1.0, 1.0], [1.68, 1.68, 1.27], [0.33, 1.73, 0.85]] points = transform_points(points, T) trans1 = [1, 2, 3] angle1 = [-2.142, 1.141, -0.142] scale1 = [0.123, 2, 0.5] T = matrix_from_translation(trans1) R = matrix_from_euler_angles(angle1) S = matrix_from_scale_factors(scale1) M = multiply_matrices(multiply_matrices(T, R), S) # M = compose_matrix(scale1, None, angle1, trans1, None) scale2, shear2, angle2, trans2, persp2 = decompose_matrix(M) print(allclose(scale1, scale2)) print(allclose(angle1, angle2)) print(allclose(trans1, trans2))