(matrix)
return angle, direction, point, normal
Return shear angle, direction and plane from shear matrix.

    >>> angle = (random.random() - 0.5) * 4*math.pi
    >>> direct = numpy.random.random(3) - 0.5
    >>> point = numpy.random.random(3) - 0.5
    >>> normal = numpy.cross(direct, numpy.random.random(3))
    >>> 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
Return shear angle, direction and plane from shear matrix.
Return shear angle direction and plane from shear matrix .
def shear_from_matrix(matrix):
    """Return shear angle, direction and plane from shear matrix.

    >>> angle = (random.random() - 0.5) * 4*math.pi
    >>> direct = numpy.random.random(3) - 0.5
    >>> point = numpy.random.random(3) - 0.5
    >>> normal = numpy.cross(direct, numpy.random.random(3))
    >>> 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 = numpy.array(matrix, dtype=numpy.float64, copy=False)
    M33 = M[:3, :3]
    # normal: cross independent eigenvectors corresponding to the eigenvalue 1
    w, V = numpy.linalg.eig(M33)
    i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-4)[0]
    if len(i) < 2:
        raise ValueError('no two linear independent eigenvectors found %s' % w)
    V = numpy.real(V[:, i]).squeeze().T
    lenorm = -1.0
    for i0, i1 in ((0, 1), (0, 2), (1, 2)):
        n = numpy.cross(V[i0], V[i1])
        w = vector_norm(n)
        if w > lenorm:
            lenorm = w
            normal = n
    normal /= lenorm
    # direction and angle
    direction = numpy.dot(M33 - numpy.identity(3), normal)
    angle = vector_norm(direction)
    direction /= angle
    angle = math.atan(angle)
    # point: eigenvector corresponding to eigenvalue 1
    w, V = numpy.linalg.eig(M)
    i = numpy.where(abs(numpy.real(w) - 1.0) < 1e-8)[0]
    if not len(i):
        raise ValueError('no eigenvector corresponding to eigenvalue 1')
    point = numpy.real(V[:, i[-1]]).squeeze()
    point /= point[3]
    return angle, direction, point, normal
def shear_from_matrix ( matrix ) : M = numpy . array ( matrix , dtype = numpy . float64 , copy = False ) M33 = M [ : 3 , : 3 ] # normal: cross independent eigenvectors corresponding to the eigenvalue 1 w , V = numpy . linalg . eig ( M33 ) i = numpy . where ( abs ( numpy . real ( w ) - 1.0 ) < 1e-4 ) [ 0 ] if len ( i ) < 2 : raise ValueError ( 'no two linear independent eigenvectors found %s' % w ) V = numpy . real ( V [ : , i ] ) . squeeze ( ) . T lenorm = - 1.0 for i0 , i1 in ( ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) ) : n = numpy . cross ( V [ i0 ] , V [ i1 ] ) w = vector_norm ( n ) if w > lenorm : lenorm = w normal = n normal /= lenorm # direction and angle direction = numpy . dot ( M33 - numpy . identity ( 3 ) , normal ) angle = vector_norm ( direction ) direction /= angle angle = math . atan ( angle ) # point: eigenvector corresponding to eigenvalue 1 w , V = numpy . linalg . eig ( M ) i = numpy . where ( abs ( numpy . real ( w ) - 1.0 ) < 1e-8 ) [ 0 ] if not len ( i ) : raise ValueError ( 'no eigenvector corresponding to eigenvalue 1' ) point = numpy . real ( V [ : , i [ - 1 ] ] ) . squeeze ( ) point /= point [ 3 ] return angle , direction , point , normal