def coerce( self, value ): if isinstance( value, (str,unicode)): value = [ float(x) for x in value.replace( ',', ' ').replace('[',' ').replace(']').split() ] if isinstance( value, arrays.ArrayType ): if arrays.typeCode(value) not in self.acceptedTypes: value = value.astype( self.targetType ) elif isinstance( value, field.SEQUENCE_TYPES): try: value = arrays.array( value, self.targetType) except ValueError: value = arrays.array( map( float, collapse( value) ), self.targetType, ) elif isinstance( value, (int,long,float)): value = arrays.array( [value], self.targetType ) else: try: value = arrays.asarray( value, self.targetType ) except Exception: raise ValueError( """Attempted to set value for an %s field which is not compatible: %s"""%( self.typeName(), repr(value) )) # special casing, again, for explicitly structured arrays if not arrays.typeCode( value ) == 'V': value = arrays.contiguous( self.reshape(value) ) return value
def coerce(self, value): if isinstance(value, (str, unicode)): value = [ float(x) for x in value.replace(',', ' ').replace( '[', ' ').replace(']').split() ] if isinstance(value, arrays.ArrayType): if arrays.typeCode(value) not in self.acceptedTypes: value = value.astype(self.targetType) elif isinstance(value, field.SEQUENCE_TYPES): try: value = arrays.array(value, self.targetType) except ValueError: value = arrays.array( map(float, collapse(value)), self.targetType, ) elif isinstance(value, (int, long, float)): value = arrays.array([value], self.targetType) else: try: value = arrays.asarray(value, self.targetType) except Exception: raise ValueError( """Attempted to set value for an %s field which is not compatible: %s""" % (self.typeName(), repr(value))) # special casing, again, for explicitly structured arrays if not arrays.typeCode(value) == 'V': value = arrays.contiguous(self.reshape(value)) return value
def test_rotation_array( self ): path = self.empty + [ Transform( rotation = (0,1,0,pi/2 )), ] matrix = path.transformMatrix() projected = dot( array([ 0,0,1,1],'f'),matrix ) assert allclose( projected, array([1,0,0,1],'f'),atol=.0001), projected
def test_nest_simple( self ): path = self.empty + [ Transform( translation=(0,0,1), DEF='translate', ), Transform( scale=(1,1,.5),DEF='scale'), ] matrix = path.transformMatrix() projected = dot( array([0,0,10,1],'f'), matrix ) assert allclose( projected, array([0,0,6,1]),atol=.0001), projected
def test_complex_transform( self ): test = array( [0,0,10,1], 'f' ) matrix = self.fourth_child.transformMatrix( ) #inverse = self.fourth_child.transformMatrix( inverse=True ) projected = dot( test, matrix ) # projecting out of the screen, then rotated # counter-clockwise 90deg (to go right), then scaled up 2x (to 20) # then translated 5 to the right... target = array([25,0,0,1],'f') assert allclose( projected, target, atol=0.0001), projected
def test_change_translation( self ): self.first_child[-1].translation = (-1,0,0) m2 = self.second_child.transformMatrix() assert allclose( m2, array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],'f') ), m2
def test_forward_back( self ): for child in (self.second_child,self.third_child,self.fourth_child): matrix = child.transformMatrix( ) inverse = child.transformMatrix( inverse=True ) test = array( [10,20,30,1], 'f') projected = dot( matrix, test ) back = dot( inverse, projected ) assert allclose( test, back ), (test,back, child[-1], matrix, inverse)
def coerce( self, value ): """Base coercion mechanism for floating point field types""" if isinstance( value, (str,unicode)): value = [ float(x) for x in value.replace( ',', ' ').split()] if isinstance(value, field.NUMERIC_TYPES): return arrays.array([float(value)],self.targetType) elif isinstance( value, arrays.ArrayType ): if arrays.typeCode(value) not in self.acceptedTypes: value = value.astype(self.targetType) return arrays.contiguous( arrays.ravel(value) ) elif isinstance( value, field.SEQUENCE_TYPES): return arrays.array( map( float, collapse( value) ), self.targetType, ) elif not value: return arrays.array([],self.targetType) raise ValueError( """Attempted to set value for an %s field which is not compatible: %s"""%( self.typeName(), repr(value) ))
def rotMatrix( source=None ): """Convert a VRML rotation to rotation matrices Returns (R, R') (R and the inverse of R), with both being 4x4 transformation matrices. or None,None if the angle is an exact multiple of 2pi x,y,z -- (normalised) rotational vector a -- angle in radians """ if source is None: return None,None else: (x,y,z, a) = source if a % TWOPI: # normalize the rotation vector! squared = x*x + y*y + z*z if squared != 1.0: length = squared ** .5 x /= length y /= length z /= length c = cos( a ) c1 = cos( -a ) s = sin( a ) s1 = sin( -a ) t = 1-c R = array( [ [ t*x*x+c, t*x*y+s*z, t*x*z-s*y, 0], [ t*x*y-s*z, t*y*y+c, t*y*z+s*x, 0], [ t*x*z+s*y, t*y*z-s*x, t*z*z+c, 0], [ 0, 0, 0, 1] ] ) R1 = array( [ [ t*x*x+c1, t*x*y+s1*z, t*x*z-s1*y, 0], [ t*x*y-s1*z, t*y*y+c1, t*y*z+s1*x, 0], [ t*x*z+s1*y, t*y*z-s1*x, t*z*z+c1, 0], [ 0, 0, 0, 1] ] ) return R, R1 else: return None, None
def transMatrix( source=None ): """Convert a VRML translation to translation matrices Returns (T, T') (T and the inverse of T), with both being 4x4 transformation matrices. or None,None if x == y == z == 0.0 x,y,z -- scale vector """ if source is None: return None,None else: (x,y,z) = source[:3] if x == y == z == 0.0: return None, None T = array( [ [1,0,0,0], [0,1,0,0], [0,0,1,0], [x,y,z,1] ], 'f' ) T1 = array( [ [1,0,0,0], [0,1,0,0], [0,0,1,0], [-x,-y,-z,1] ], 'f' ) return T, T1
def SFArray( self, values, buffer, final=True ): """Process a vector-of-values data-set""" result = [] for (tag,start,stop,children) in values: if tag == 'vector': result.append( self.SFArray( children, buffer, final=False )) else: result.append( float(buffer[start:stop] ) ) if final: result = array( result, 'f' ) return result
def SFArray(self, values, buffer, final=True): """Process a vector-of-values data-set""" result = [] for (tag, start, stop, children) in values: if tag == 'vector': result.append(self.SFArray(children, buffer, final=False)) else: result.append(float(buffer[start:stop])) if final: result = array(result, 'f') return result
def coerce(self, value): """Base coercion mechanism for floating point field types""" if isinstance(value, (str, unicode)): value = [float(x) for x in value.replace(',', ' ').split()] if isinstance(value, field.NUMERIC_TYPES): return arrays.array([float(value)], self.targetType) elif isinstance(value, arrays.ArrayType): if arrays.typeCode(value) not in self.acceptedTypes: value = value.astype(self.targetType) return arrays.contiguous(arrays.ravel(value)) elif isinstance(value, field.SEQUENCE_TYPES): return arrays.array( map(float, collapse(value)), self.targetType, ) elif not value: return arrays.array([], self.targetType) raise ValueError( """Attempted to set value for an %s field which is not compatible: %s""" % (self.typeName(), repr(value)))
def coerce( self, value ): """Base coercion mechanism for multiple-value integer fields""" if isinstance( value, (str,unicode)): value = [ self.base_converter(x) for x in value.replace( ',', ' ').split() ] if isinstance(value, field.NUMERIC_TYPES): return arrays.array([int(value)],self.arrayDataType) elif isinstance( value, arrays.ArrayType ): if arrays.typeCode(value) not in self.acceptedTypes: value = value.astype( self.arrayDataType ) return arrays.contiguous( arrays.ravel(value) ) elif isinstance( value, field.SEQUENCE_TYPES): return arrays.array( [int(obj) for obj in value], self.arrayDataType, ) elif not value: return arrays.array([],self.arrayDataType) raise ValueError( """Attempted to set value for an %s field which is not compatible: %s"""%( self.typeName(), repr(value) ))
def test_perspectiveMatrix( self ): """Test that perspective matrix calculation matches expected values""" result = transformmatrix.perspectiveMatrix( 59.999999999999993*DEGTORAD, 1.0, 0.29999999999999999, 50000 ) inverse = transformmatrix.perspectiveMatrix( 59.999999999999993*DEGTORAD, 1.0, 0.29999999999999999, 50000, inverse=True, ) expected = array([ [ 1.73205081, 0., 0., 0., ], [ 0., 1.73205081, 0., 0., ], [ 0., 0., -1.000012, -1., ], [ 0., 0., -0.6000036, 0., ],],'f') assert allclose(result,expected), result test = array([ 20,8,5,1.0 ],'f') projected = dot( result, test ) print(projected) unprojected = dot( inverse, projected ) assert allclose( unprojected, test ), (unprojected, test)
def perspectiveMatrix( fovy, aspect, zNear, zFar, inverse=False ): """Create a perspective matrix from given parameters Note that this is the same matrix as for gluPerspective, save that we are using radians... """ f = 1.0/tan( (fovy/2.0) ) # cotangent( fovy/2.0 ) zDelta = zNear-zFar if inverse: return array([ [aspect/f,0,0,0], [0,1/(f or VERY_SMALL),0,0], [0,0,0,zDelta/(2*zFar*zNear)], [0,0,-1,(zFar+zNear)/(2*zFar*zNear)], ],'f') else: return array([ [f/aspect,0,0,0], [0,f,0,0], [0,0,(zFar+zNear)/zDelta,-1], [0,0,(2*zFar*zNear)/zDelta,0] ],'f')
def __set__(self, client, value, *arguments, **named): """Set value, and call setter(value, *arguments, **named)""" try: result = self.base.__set__(client, value, *arguments, **named) except ValueError as err: base = self.base.__get__(client, *arguments, **named) base = array(base, copy=True) base[:] = value value = base result = self.base.__set__(client, base, *arguments, **named) name = 'set_' + self.base.name if hasattr(client, name): getattr(client, name)(value, self.base, *arguments, **named) return result
def orthoMatrix( left=-1.0, right=1.0, bottom=-1.0, top=1.0, zNear=-1.0, zFar=1.0 ): """Calculate an orthographic projection matrix Similar to glOrtho """ tx = - ( right + left ) / float( right-left ) ty = - ( top + bottom ) / float( top-bottom ) tz = - ( zFar + zNear ) / float( zFar-zNear ) return array([ [2/(right-left), 0, 0, tx], [0, 2/(top-bottom), 0, ty], [0, 0, -2/(zFar-zNear), tz], [0, 0, 0, 1], ], dtype='f')
def scaleMatrix( source=None ): """Convert a VRML scale to scale matrices Returns (S, S') (S and the inverse of S), with both being 4x4 transformation matrices. or None,None if x == y == z == 1.0 x,y,z -- scale vector """ if source is None: return None,None else: (x,y,z) = source[:3] if x == y == z == 1.0: return None, None S = array( [ [x,0,0,0], [0,y,0,0], [0,0,z,0], [0,0,0,1] ], 'f' ) S1 = array( [ [1./(x or VERY_SMALL),0,0,0], [0,1./(y or VERY_SMALL),0,0], [0,0,1./(z or VERY_SMALL),0], [0,0,0,1] ], 'f' ) return S, S1
These are all of the "low-level" field-types (i.e. not nodes) defined by VRML97. Each has a canonical in-memory storage format so that code can rely on that format when dealing with the field values. We use Numeric Python arrays whereever possible. """ import operator from vrml import protonamespace, field, csscolors, arrays import types, sys from types import ListType, TupleType DOUBLE_TYPE = arrays.typeCode( arrays.array( [0],'d') ) FLOAT_TYPE = arrays.typeCode( arrays.array( [0],'f') ) INT_TYPE = arrays.typeCode( arrays.array( [0],'i') ) UINT_TYPE = arrays.typeCode( arrays.array( [0],'I') ) def _collapse(inlist, isinstance=isinstance, ltype=list, maxint= sys.maxint): ''' Destructively flatten a list hierarchy to a single level. Non-recursive, and (as far as I can see, doesn't have any glaring loopholes). Further speedups and obfuscations by Tim Peters :) ''' try: # for every possible index for ind in xrange( maxint): # while that index currently holds a list
def copyValue( self, value, copier=None ): """Copy a value for copier""" return arrays.array(value, arrays.typeCode(value) )
def test_second_child( self ): m = self.second_child.transformMatrix() assert allclose( m, array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[2,0,0,1]],'f') ), m
def test_empty_matrix( self ): m = self.empty.transformMatrix() assert allclose( m, array([[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]],'f') ), m
def copyValue(self, value, copier=None): """Copy a value for copier""" return arrays.array(value, arrays.typeCode(value))
These are all of the "low-level" field-types (i.e. not nodes) defined by VRML97. Each has a canonical in-memory storage format so that code can rely on that format when dealing with the field values. We use Numeric Python arrays whereever possible. """ import operator from vrml import protonamespace, field, csscolors, arrays import types, sys from types import ListType, TupleType DOUBLE_TYPE = arrays.typeCode(arrays.array([0], 'd')) FLOAT_TYPE = arrays.typeCode(arrays.array([0], 'f')) INT_TYPE = arrays.typeCode(arrays.array([0], 'i')) UINT_TYPE = arrays.typeCode(arrays.array([0], 'I')) def _collapse(inlist, isinstance=isinstance, ltype=list, maxint=sys.maxint): ''' Destructively flatten a list hierarchy to a single level. Non-recursive, and (as far as I can see, doesn't have any glaring loopholes). Further speedups and obfuscations by Tim Peters :) ''' try: # for every possible index for ind in xrange(maxint):