(matrix)
return scale, shear, angles, translate, perspective
Return sequence of transformations from transformation matrix.

    matrix : array_like
        Non-degenerative homogeneous transformation matrix

    Return tuple of:
        scale : vector of 3 scaling factors
        shear : list of shear factors for x-y, x-z, y-z axes
        angles : list of Euler angles about static x, y, z axes
        translate : translation vector along x, y, z axes
        perspective : perspective partition of matrix

    Raise ValueError if matrix is of wrong type or degenerative.

    >>> T0 = translation_matrix([1, 2, 3])
    >>> scale, shear, angles, trans, persp = decompose_matrix(T0)
    >>> T1 = translation_matrix(trans)
    >>> numpy.allclose(T0, T1)
    True
    >>> S = scale_matrix(0.123)
    >>> scale, shear, angles, trans, persp = decompose_matrix(S)
    >>> scale[0]
    0.123
    >>> R0 = euler_matrix(1, 2, 3)
    >>> scale, shear, angles, trans, persp = decompose_matrix(R0)
    >>> R1 = euler_matrix(*angles)
    >>> numpy.allclose(R0, R1)
    True
Return sequence of transformations from transformation matrix.
Return sequence of transformations from transformation matrix .
def decompose_matrix(matrix):
    """Return sequence of transformations from transformation matrix.

    matrix : array_like
        Non-degenerative homogeneous transformation matrix

    Return tuple of:
        scale : vector of 3 scaling factors
        shear : list of shear factors for x-y, x-z, y-z axes
        angles : list of Euler angles about static x, y, z axes
        translate : translation vector along x, y, z axes
        perspective : perspective partition of matrix

    Raise ValueError if matrix is of wrong type or degenerative.

    >>> T0 = translation_matrix([1, 2, 3])
    >>> scale, shear, angles, trans, persp = decompose_matrix(T0)
    >>> T1 = translation_matrix(trans)
    >>> numpy.allclose(T0, T1)
    True
    >>> S = scale_matrix(0.123)
    >>> scale, shear, angles, trans, persp = decompose_matrix(S)
    >>> scale[0]
    0.123
    >>> R0 = euler_matrix(1, 2, 3)
    >>> scale, shear, angles, trans, persp = decompose_matrix(R0)
    >>> R1 = euler_matrix(*angles)
    >>> numpy.allclose(R0, R1)
    True

    """
    M = numpy.array(matrix, dtype=numpy.float64, copy=True).T
    if abs(M[3, 3]) < _EPS:
        raise ValueError('M[3, 3] is zero')
    M /= M[3, 3]
    P = M.copy()
    P[:, 3] = 0.0, 0.0, 0.0, 1.0
    if not numpy.linalg.det(P):
        raise ValueError('matrix is singular')

    scale = numpy.zeros((3, ))
    shear = [0.0, 0.0, 0.0]
    angles = [0.0, 0.0, 0.0]

    if any(abs(M[:3, 3]) > _EPS):
        perspective = numpy.dot(M[:, 3], numpy.linalg.inv(P.T))
        M[:, 3] = 0.0, 0.0, 0.0, 1.0
    else:
        perspective = numpy.array([0.0, 0.0, 0.0, 1.0])

    translate = M[3, :3].copy()
    M[3, :3] = 0.0

    row = M[:3, :3].copy()
    scale[0] = vector_norm(row[0])
    row[0] /= scale[0]
    shear[0] = numpy.dot(row[0], row[1])
    row[1] -= row[0] * shear[0]
    scale[1] = vector_norm(row[1])
    row[1] /= scale[1]
    shear[0] /= scale[1]
    shear[1] = numpy.dot(row[0], row[2])
    row[2] -= row[0] * shear[1]
    shear[2] = numpy.dot(row[1], row[2])
    row[2] -= row[1] * shear[2]
    scale[2] = vector_norm(row[2])
    row[2] /= scale[2]
    shear[1:] /= scale[2]

    if numpy.dot(row[0], numpy.cross(row[1], row[2])) < 0:
        numpy.negative(scale, scale)
        numpy.negative(row, row)

    angles[1] = math.asin(-row[0, 2])
    if math.cos(angles[1]):
        angles[0] = math.atan2(row[1, 2], row[2, 2])
        angles[2] = math.atan2(row[0, 1], row[0, 0])
    else:
        # angles[0] = math.atan2(row[1, 0], row[1, 1])
        angles[0] = math.atan2(-row[2, 1], row[1, 1])
        angles[2] = 0.0

    return scale, shear, angles, translate, perspective
def decompose_matrix ( matrix ) : M = numpy . array ( matrix , dtype = numpy . float64 , copy = True ) . T if abs ( M [ 3 , 3 ] ) < _EPS : raise ValueError ( 'M[3, 3] is zero' ) M /= M [ 3 , 3 ] P = M . copy ( ) P [ : , 3 ] = 0.0 , 0.0 , 0.0 , 1.0 if not numpy . linalg . det ( P ) : raise ValueError ( 'matrix is singular' ) scale = numpy . zeros ( ( 3 , ) ) shear = [ 0.0 , 0.0 , 0.0 ] angles = [ 0.0 , 0.0 , 0.0 ] if any ( abs ( M [ : 3 , 3 ] ) > _EPS ) : perspective = numpy . dot ( M [ : , 3 ] , numpy . linalg . inv ( P . T ) ) M [ : , 3 ] = 0.0 , 0.0 , 0.0 , 1.0 else : perspective = numpy . array ( [ 0.0 , 0.0 , 0.0 , 1.0 ] ) translate = M [ 3 , : 3 ] . copy ( ) M [ 3 , : 3 ] = 0.0 row = M [ : 3 , : 3 ] . copy ( ) scale [ 0 ] = vector_norm ( row [ 0 ] ) row [ 0 ] /= scale [ 0 ] shear [ 0 ] = numpy . dot ( row [ 0 ] , row [ 1 ] ) row [ 1 ] -= row [ 0 ] * shear [ 0 ] scale [ 1 ] = vector_norm ( row [ 1 ] ) row [ 1 ] /= scale [ 1 ] shear [ 0 ] /= scale [ 1 ] shear [ 1 ] = numpy . dot ( row [ 0 ] , row [ 2 ] ) row [ 2 ] -= row [ 0 ] * shear [ 1 ] shear [ 2 ] = numpy . dot ( row [ 1 ] , row [ 2 ] ) row [ 2 ] -= row [ 1 ] * shear [ 2 ] scale [ 2 ] = vector_norm ( row [ 2 ] ) row [ 2 ] /= scale [ 2 ] shear [ 1 : ] /= scale [ 2 ] if numpy . dot ( row [ 0 ] , numpy . cross ( row [ 1 ] , row [ 2 ] ) ) < 0 : numpy . negative ( scale , scale ) numpy . negative ( row , row ) angles [ 1 ] = math . asin ( - row [ 0 , 2 ] ) if math . cos ( angles [ 1 ] ) : angles [ 0 ] = math . atan2 ( row [ 1 , 2 ] , row [ 2 , 2 ] ) angles [ 2 ] = math . atan2 ( row [ 0 , 1 ] , row [ 0 , 0 ] ) else : # angles[0] = math.atan2(row[1, 0], row[1, 1]) angles [ 0 ] = math . atan2 ( - row [ 2 , 1 ] , row [ 1 , 1 ] ) angles [ 2 ] = 0.0 return scale , shear , angles , translate , perspective