#NEWLINE# def projection_from_matrix( matrix , pseudo = False ) : #NEWLINE# #INDENT# 'Return projection plane and perspective point from projection matrix.\n\n    Return values are same as arguments for projection_matrix function:\n    point, normal, direction, perspective, and pseudo.\n\n    >>> point = numpy.random.random(3) - 0.5\n    >>> normal = numpy.random.random(3) - 0.5\n    >>> direct = numpy.random.random(3) - 0.5\n    >>> persp = numpy.random.random(3) - 0.5\n    >>> P0 = projection_matrix(point, normal)\n    >>> result = projection_from_matrix(P0)\n    >>> P1 = projection_matrix(*result)\n    >>> is_same_transform(P0, P1)\n    True\n    >>> P0 = projection_matrix(point, normal, direct)\n    >>> result = projection_from_matrix(P0)\n    >>> P1 = projection_matrix(*result)\n    >>> is_same_transform(P0, P1)\n    True\n    >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=False)\n    >>> result = projection_from_matrix(P0, pseudo=False)\n    >>> P1 = projection_matrix(*result)\n    >>> is_same_transform(P0, P1)\n    True\n    >>> P0 = projection_matrix(point, normal, perspective=persp, pseudo=True)\n    >>> result = projection_from_matrix(P0, pseudo=True)\n    >>> P1 = projection_matrix(*result)\n    >>> is_same_transform(P0, P1)\n    True\n\n    ' #NEWLINE# M = numpy . array ( matrix , dtype = numpy . float64 , copy = False ) #NEWLINE# M33 = M [ : 3 , : 3 ] #NEWLINE# ( l , V ) = numpy . linalg . eig ( M ) #NEWLINE# i = numpy . where ( ( abs ( ( numpy . real ( l ) - 1.0 ) ) < 1e-08 ) ) [ 0 ] #NEWLINE# if ( ( not pseudo ) and len ( i ) ) : #NEWLINE# #INDENT# point = numpy . real ( V [ : , i [ ( - 1 ) ] ] ) . squeeze ( ) #NEWLINE# point /= point [ 3 ] #NEWLINE# ( l , V ) = numpy . linalg . eig ( M33 ) #NEWLINE# i = numpy . where ( ( abs ( numpy . real ( l ) ) < 1e-08 ) ) [ 0 ] #NEWLINE# if ( not len ( i ) ) : #NEWLINE# #INDENT# raise ValueError ( 'no eigenvector corresponding to eigenvalue 0' ) #NEWLINE# #UNINDENT# direction = numpy . real ( V [ : , i [ 0 ] ] ) . squeeze ( ) #NEWLINE# direction /= vector_norm ( direction ) #NEWLINE# ( l , V ) = numpy . linalg . eig ( M33 . T ) #NEWLINE# i = numpy . where ( ( abs ( numpy . real ( l ) ) < 1e-08 ) ) [ 0 ] #NEWLINE# if len ( i ) : #NEWLINE# #INDENT# normal = numpy . real ( V [ : , i [ 0 ] ] ) . squeeze ( ) #NEWLINE# normal /= vector_norm ( normal ) #NEWLINE# return ( point , normal , direction , None , False ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# return ( point , direction , None , None , False ) #NEWLINE# #UNINDENT# #UNINDENT# else : #NEWLINE# #INDENT# i = numpy . where ( ( abs ( numpy . real ( l ) ) > 1e-08 ) ) [ 0 ] #NEWLINE# if ( not len ( i ) ) : #NEWLINE# #INDENT# raise ValueError ( 'no eigenvector not corresponding to eigenvalue 0' ) #NEWLINE# #UNINDENT# point = numpy . real ( V [ : , i [ ( - 1 ) ] ] ) . squeeze ( ) #NEWLINE# point /= point [ 3 ] #NEWLINE# normal = ( - M [ 3 , : 3 ] ) #NEWLINE# perspective = ( M [ : 3 , 3 ] / numpy . dot ( normal [ : 3 ] , normal ) ) #NEWLINE# if pseudo : #NEWLINE# #INDENT# perspective -= normal #NEWLINE# #UNINDENT# return ( point , normal , None , perspective , pseudo )