def shear_from_matrix(matrix):
    """Return shear angle, direction and plane from shear matrix.

    >>> angle  = np.pi / 2.0
    >>> direct = [0.0, 1.0, 0.0]
    >>> point  = [0.0, 0.0, 0.0]
    >>> normal = np.cross(direct, np.roll(direct,1))
    >>> S0 = shear_matrix(angle, direct, point, normal)
    >>> angle, direct, point, normal = shear_from_matrix(S0)
    >>> S1 = shear_matrix(angle, direct, point, normal)
    >>> is_same_transform(S0, S1)
    True

    """
    M = np.array(matrix, dtype=np.float64, copy=False)
    M33 = M[:3, :3]
    # normal: cross independent eigenvectors corresponding to the eigenvalue 1
    w, V = np.linalg.eig(M33)

    i = np.where(abs(np.real(w) - 1.0) < 1e-4)[0]
    if len(i) < 2:
        raise ValueError("no two linear independent eigenvectors found %s" % w)
    V = np.real(V[:, i]).squeeze().T
    lenorm = -1.0
    for i0, i1 in ((0, 1), (0, 2), (1, 2)):
        n = np.cross(V[i0], V[i1])
        w = vector_norm(n)
        if w > lenorm:
            lenorm = w
            normal = n
    normal /= lenorm
    # direction and angle
    direction = np.dot(M33 - np.identity(3), normal)
    angle = vector_norm(direction)
    direction /= angle
    angle = math.atan(angle)
    # point: eigenvector corresponding to eigenvalue 1
    w, V = np.linalg.eig(M)

    i = np.where(abs(np.real(w) - 1.0) < 1e-8)[0]
    if not len(i):
        raise ValueError("no eigenvector corresponding to eigenvalue 1")
    point = np.real(V[:, i[-1]]).squeeze()
    point /= point[3]
    return angle, direction, point, normal
def shear_from_matrix ( matrix ) : M = np . array ( matrix , dtype = np . float64 , copy = False ) M33 = M [ : 3 , : 3 ] w , V = np . linalg . eig ( M33 ) i = np . where ( abs ( np . real ( w ) - 1.0 ) < 1e-4 ) [ 0 ] if len ( i ) < 2 : raise ValueError ( "no two linear independent eigenvectors found %s" % w ) V = np . real ( V [ : , i ] ) . squeeze ( ) . T lenorm = - 1.0 for i0 , i1 in ( ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) ) : n = np . cross ( V [ i0 ] , V [ i1 ] ) w = vector_norm ( n ) if w > lenorm : lenorm = w normal = n normal /= lenorm direction = np . dot ( M33 - np . identity ( 3 ) , normal ) angle = vector_norm ( direction ) direction /= angle angle = math . atan ( angle ) w , V = np . linalg . eig ( M ) i = np . where ( abs ( np . real ( w ) - 1.0 ) < 1e-8 ) [ 0 ] if not len ( i ) : raise ValueError ( "no eigenvector corresponding to eigenvalue 1" ) point = np . real ( V [ : , i [ - 1 ] ] ) . squeeze ( ) point /= point [ 3 ] return angle , direction , point , normal
Return shear angle, direction and plane from shear matrix.

    >>> angle  = np.pi / 2.0
    >>> direct = [0.0, 1.0, 0.0]
    >>> point  = [0.0, 0.0, 0.0]
    >>> normal = np.cross(direct, np.roll(direct,1))
    >>> S0 = shear_matrix(angle, direct, point, normal)
    >>> angle, direct, point, normal = shear_from_matrix(S0)
    >>> S1 = shear_matrix(angle, direct, point, normal)
    >>> is_same_transform(S0, S1)
    True