mgltools-dejavu-1.5.7~rc1~cvs.20130519/0000755000175000017500000000000012146207734016515 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/0000755000175000017500000000000012146210044017657 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/0000755000175000017500000000000012146207763022765 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/GeometryNodes.py0000644000175000017500000044762611260752120026132 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: Novembre 2005 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # ######################################################################### # # $Header$ # # $Id$ # # third party packages import os import sys from warnings import warn from weakref import ref from numpy.oldnumeric import array, identity from Tkinter import Menu from os.path import splitext # TSRI packages from mglutil.util.callback import CallBackFunction from NetworkEditor.items import NetworkNode from NetworkEditor.macros import MacroInputNode, MacroNetwork, \ MacroOutputNode, MacroOutputNode, MacroNode from DejaVu.Common2d3dObject import Common2d3dObject from DejaVu.Geom import Geom import DejaVu class GeometryNode(NetworkNode): """Base Class to hold a single geometry, should be only inherited, never instanciated. it handles naming and parenting. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty name is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combo box. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behaviour of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behaviour set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). THINGS TO DO TO INHERIT (the best is to follow what is done in class IndexedPolygonsNE bellow) 1- inherit : class IndexedPolygonsNE(GeometryNode): 2- at the beginning of init, call original init (the 'indexedPolygons' in quotes will be the name of the output port): kw['name'] = name apply( GeometryNode.__init__, (self, 'indexedPolygons'), kw ) 3- rearrange ports order after appending additionnal input and output: self.rearrangePorts() 4- at the beginning of doit, call original doit: GeometryNode.doit(self, name, instanceMatrices, geomOptions, parent) 5- the doit function should really immitate the class IndexedPolygonsNE example (parameters linked to input ports from the base class must be passed as last) def doit(self, coords, indices, vnormals=None, colors=None, name=None, instanceMatrices=None, geomOptions=None, parent=None): 6- override appendGeometry() def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.IndexedPolygons import IndexedPolygons self.geoms.append(IndexedPolygons(name)) return 1 # num of geoms appended 7- don't forget to use the new datatypes ip.append(datatype='coord3(0,3)', name='coords') GeomsFromFile bellow shows how the filename can be use as a director for the name. It shows also how to append several geoms from one file. If you want to read a new type of file the best is to add it inside the appendGeometry of GeomsFromFile """ def __init__(self, geomOutputPortName, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() apply( NetworkNode.__init__, (self,), kw ) self.geometriesOwner = True # tell if the node has created the geometries # or is just displaying geometries self.selectedGeomIndex = None self.geoms = [] # creat ports common to all geoemtry producing nodes ip = self.inputPortsDescr # for backward compatibility with old networks # name and instanceMatrices must be the first ones in this Base class ip.append(datatype='string', required=False, name='name') ip.append(datatype='string', required=False, name='geoms') ip.append(datatype='instancemat(0)', required=False, name='instanceMatrices') ip.append(datatype='dict', required=False, name='geomOptions') # even if it is not compulsory, # we try to keep the parent port in the last position ip.append(datatype='geomOrInsert2d', required=False, name='parent', singleConnection=True) # used in rearrange Port and in afterConnect and afterDisconnect self.numOfBaseClassInputPorts = len(ip) op = self.outputPortsDescr op.append(datatype='geomOrInsert2d', name=geomOutputPortName) op.append(datatype='geomOrInsert2d(0)', name='allGeometries') self.widgetDescr['name'] = { 'class':'NEEntryNotScheduling', 'master':'node', 'width':12, 'labelCfg':{'text':'new geom name:'}, 'initialValue':'',#geomOutputPortName, } self.widgetDescr['geoms'] = { 'class':'NEComboBox', 'master':'node', 'entryfield_entry_width':14, 'autoList':True, 'labelCfg':{'text':'current geom:'}, 'selectioncommand':self.selectionCommand_cb, } codeAfterConnectParent = """def afterConnect(self, conn): #print "codeAfterConnectParent", self.name GeometryNode.afterConnectParent(self.node, self, conn) """ # this code runs when we connect something to the parent port ip[self.numOfBaseClassInputPorts-1]['afterConnect'] = \ codeAfterConnectParent codeAfterDisconnectParent = """def afterDisconnect(self, p1, p2): #print "codeAfterDisconnectParent", self.name GeometryNode.afterDisconnectParent(self.node, p1) """ # this code runs when we disconnect something to the parent port ip[self.numOfBaseClassInputPorts-1]['afterDisconnect'] = \ codeAfterDisconnectParent codeAfterDisconnectChildren = """def afterDisconnect(self, p1, p2): #print "codeAfterDisconnectChildren", self.name GeometryNode.afterDisconnectChildren(self.node, p1, p2) """ # this code runs when we disconnect something to the children port op[0]['afterDisconnect'] = codeAfterDisconnectChildren def selectionCommand_cb(self, value): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if value != self.name \ and len(self.getInputPortByName('geoms').widget.widget.get(0, 'end')) != len(self.geoms): self.geoms[self.selectedGeomIndex].Set(name=value) self.rename(value) else: selInd = self.getInputPortByName('geoms').widget.widget.curselection() if len(selInd): self.selectedGeomIndex = int(selInd[0]) self.rename(self.inputPortByName['geoms'].getData()) self.drawParentAndChildrenConnections() def afterAddingToNetwork(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() NetworkNode.afterAddingToNetwork(self) if self.geometriesOwner is False: self.inputPortByName['parent'].cascadeMenuVariable.set('none') def doit(self, name=None, geoms=None, instanceMatrices=None, geomOptions=None, texture=None, parent=None): #print "GeometryNode.doit", self.name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # lgeomState = None # if self.selectedGeomIndex is not None and name == '': # lgeomState = self.geom().getState() if (self.selectedGeomIndex is None) \ or (self.inputPortByName['geoms'].hasNewValidData() is False) \ or (self.inputPortByName['geoms'].hasNewValidData() is True and self.inputPortByName['geoms'].getData() == self.name): if name is not None: if name == '': if self.name == 'the list is empty': name = self.getOutputPortByType('geomOrInsert2d').name else: name = self.name else: wn = self.inputPortByName['name'].widget if hasattr(wn,'widget'): wn.set('', run=0) if self.selectedGeomIndex is None: self.addingEntries(name) elif self.geom().name != name: self.addingEntries(name) self.reparentGeomType( self.inputPortByName['parent'].cascadeMenuVariable.get(), reparentCurrent=True) elif (self.selectedGeomIndex is not None) \ and (parent != self.geom().parent): #self.parenting(parent) self.reparentGeomType( self.inputPortByName['parent'].cascadeMenuVariable.get(), reparentCurrent=True) else: pass else: # if lgeomState is not None: # lgeomState.pop('name') self.naming(geoms) # we never want this to be set in the saved file, # the network will do it through the saved name self.inputPortByName['geoms'].widget._modified = False self.drawParentAndChildrenConnections() self.rebuildComboBoxList() if instanceMatrices: mat = array(instanceMatrices) else: mat = [identity(4).astype('f')] lOpts = {} if mat is not None and self.selectedGeomIndex is not None: #print self.geom(), mat if geomOptions is not None: lOpts = geomOptions.copy() if isinstance(self.geom(), Geom): lOpts['instanceMatrices'] = mat #lOpts['redo'] = 0 lOpts['tagModified'] = False apply( self.geom().Set, (), lOpts ) # if lgeomState is not None and self.selectedGeomIndex is not None: # for key in lOpts.keys(): # if key in lgeomState.keys(): # lgeomState.pop(key) # apply(self.geom().Set,(),lgeomState) def rearrangePorts(self): """reoder port list for backwards compatibility. (old network were saved with port indices instead of port names) the parent and instance matrices ports are created by the base class and therefore appear in position 1 and 2 but should move after the ports created by the subclass. the port 'name' used to be index #4. """ #print "rearrangePorts" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ip = self.inputPortsDescr if len(ip) > self.numOfBaseClassInputPorts: self.inputPortsDescr = ip[self.numOfBaseClassInputPorts:] \ + ip[:self.numOfBaseClassInputPorts] def geom(self): #print "geom" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() assert self.selectedGeomIndex is not None #if len(self.geoms) == 0: # self.selectedGeomIndex = None assert len(self.geoms) > 0 assert self.selectedGeomIndex >= 0, self.selectedGeomIndex assert self.selectedGeomIndex < len(self.geoms), self.selectedGeomIndex return self.geoms[self.selectedGeomIndex] def removeAndCleanMultipleGeometryies(self, geometryies): #print "removeAndCleanMultipleGeometryies", geometryies if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if geometryies is None: return if isinstance(geometryies, Common2d3dObject): if hasattr(geometryies, 'node'): for g in geometryies.node().geoms: self.removeAndCleanMultipleGeometryies(g.parent) self.removeSingleGeom(g) else: for g in geometryies: self.removeAndCleanMultipleGeometryies(g.parent) self.removeSingleGeom(g) def removeSingleGeomAndReparentChildren(self, geom): #print "removeSingleGeomAndReparentChildren", geom.name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not isinstance(geom, Common2d3dObject): return if hasattr(geom, 'viewer'): viewer = geom.viewer else: viewer = None from copy import copy lChildren = copy(geom.children) for c in lChildren: if hasattr(c, 'node'): c.node().parenting(None,c) elif viewer is not None: viewer.ReparentObject(c, geom.parent) if viewer is None: return if self.geometriesOwner is True: geom.viewer.RemoveObject(geom) geom.parent = None def removeSingleGeom(self, geom): #print "removeSingleGeom", geom.name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not isinstance(geom, Common2d3dObject): return if not hasattr(geom, 'viewer'): return if geom.viewer is None: return if self.geometriesOwner is True: lViewer = geom.viewer lViewer.RemoveObject(geom) if geom.parent == lViewer.rootObject: geom.parent = None def removeViewerConnection(self, doNotRemoveThisConnection = None): #print "removeViewerConnection", doNotRemoveThisConnection.port1, doNotRemoveThisConnection.port2 if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lOutputPort = self.getOutputPortByType('geomOrInsert2d') for c in lOutputPort.connections: from DejaVu.VisionInterface.DejaVuNodes import Viewer if c != doNotRemoveThisConnection: if isinstance(c.port2.node, Viewer): self.network.deleteConnectionsNoCB(c) elif isinstance(c.port2.node, MacroOutputNode): m = c.port2.node.macroNode lOutputPortMacro = m.getOutputPortByName(c.port2.name) for cm in lOutputPortMacro.connections: if cm == doNotRemoveThisConnection: break elif isinstance(cm.port2.node, Viewer): cm.network.deleteConnectionsNoCB(cm) break def removeViewerConnections(self, doNotRemoveThisConnection = None): #print "removeViewerConnections", doNotRemoveThisConnection if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() for g in self.geoms: p = g.LastParentBeforeRoot() for c in p.AllObjects(): if hasattr(c,'node'): c.node().removeViewerConnection(doNotRemoveThisConnection) def ensureNameOfNodeAndDescendants(self, obj): #print "ensureNameOfNodeAndDescendants" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if len(self.geoms) > 0: for geom in obj.AllObjects(): if hasattr(geom,'node'): geom.node().rebuildComboBoxList() def getIndexFromName(self, name): """returns the index of the geom returns -1 if entry is not in the list """ #print "getIndexFromName" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() for i in range(len(self.geoms)): if name == self.geoms[i].name: return i return -1 def removePreviousGeomWithSameName(self, name): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lSelfGeomNames = [] for g in self.geoms: lSelfGeomNames.append(g.name) if name in lSelfGeomNames: self.naming(name) def removePreviousGeomsStartingWith(self, name): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lSelfGeomNames = [] for g in self.geoms: lSelfGeomNames.append(g.name) for lSelfGeomName in lSelfGeomNames: if lSelfGeomName.startswith(name): self.naming(lSelfGeomName) def removePreviousGeomsWithSameName(self, geoms): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lSelfGeomNames = [] for g in self.geoms: lSelfGeomNames.append(g.name) for g in geoms: if g.name in lSelfGeomNames: self.naming(g.name) def naming(self, name): """ """ #print "Naming old:" , self.name, "new:", name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if name is None: return w0 = self.inputPortByName['geoms'].widget if hasattr(w0,'widget'): w = w0.widget else: w = None self.inputPortByName['geoms']._previousWidgetDescr['choices'] = [] if name == '' or (self.selectedGeomIndex is not None and name == self.geom().name): #print "deleting entry", self.name if w.size() == 0: return if self.selectedGeomIndex is None: #print "the list is empty 1" # w1 = self.inputPortByName['name'].widget # if hasattr(w1,'widget'): # w1.set(self.name, run=0) self.rename("the list is empty") if w is not None: w.delete(0,'end') return assert self.geom().name == self.name lRemovedName = self.name #remove self.geom in the viewer #and verify children renaming/reparenting self.removeSingleGeomAndReparentChildren(self.geom()) if w is not None: if w.get(self.selectedGeomIndex) == self.name: w.delete(self.selectedGeomIndex) self.geoms.remove(self.geom()) if len(self.geoms) > 0: self.selectedGeomIndex = 0 self.rebuildComboBoxList() if w is not None: w.selectitem(self.selectedGeomIndex,setentry=1) self.rename(self.geom().name) else: #print "the list is empty 2" self.selectedGeomIndex = None self.rename("the list is empty") #self.inputPortByName['name'].widget.set(lRemovedName, run=0) return lRemovedName index = self.getIndexFromName(name) if index >= 0: # name is found in the geoms list #remove corresponding geom from the viewer #and verify children renaming/reparenting self.removeSingleGeomAndReparentChildren(self.geoms[index]) self.geoms.remove(self.geoms[index]) self.selectedGeomIndex = 0 self.rebuildComboBoxList() if w is not None: w.selectitem(self.selectedGeomIndex,setentry=1) self.rename(self.geom().name) # #print "selecting entry", name # self.selectedGeomIndex = index assert self.selectedGeomIndex < len(self.geoms) , len(self.geoms) # self.rename(self.geom().name) return elif self.selectedGeomIndex is not None: #print "renaming entries", name self.geom().Set(name=name) self.rename(self.geom().name) return def addingEntries(self, name): #print "addingEntries", name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lenMoreGeoms = self.appendGeometry(name) self.selectedGeomIndex = len(self.geoms) - 1 if lenMoreGeoms > 0: for i in range(lenMoreGeoms): lIndex = self.selectedGeomIndex -lenMoreGeoms + i + 1 self.geoms[lIndex].node = ref(self) self.geoms[lIndex].replace = False self.rename(self.geom().name) elif len(self.geoms) > 0: self.selectedGeomIndex = len(self.geoms) - 1 else: self.selectedGeomIndex = None assert self.selectedGeomIndex < len(self.geoms) , self.geoms #to silent pychecker def appendGeometry(self, name): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() assert False, name pass def nodeOnlyGeomRemoval(self, geom): #print "cleanNodeForGeomRemoval", geom.name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() assert geom in self.geoms if self.geom() == geom: lThatIsTheSelectedOne = True else: lThatIsTheSelectedOne = False self.geoms.remove(geom) if lThatIsTheSelectedOne is True: if len(self.geoms) > 0: self.selectedGeomIndex = 0 self.rename(self.geom().name) w0 = self.inputPortByName['geoms'].widget if hasattr(w0,'widget'): w0.widget.selectitem(self.selectedGeomIndex,setentry=1) else: #print "the list is empty 3" self.selectedGeomIndex = None #self.inputPortByName['name'].widget.set(self.name, run=0) self.rename("the list is empty") def parenting(self, parent, geom=None): """ prepare the parenting and launch it if applicable it will parent the selectedGeomIndex unless geom is provided """ #print "Parenting", parent , geom if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #import traceback;traceback.print_stack() #import pdb;pdb.set_trace() if geom is None: if self.selectedGeomIndex is None: return 'Go' geom = self.geom() if geom.viewer is not None and parent is None: parent = geom.viewer.rootObject else: if isinstance(parent, Common2d3dObject): if hasattr(parent, 'node'): if parent.node().selectedGeomIndex is not None: parent = parent.node().geom() else: return 'Go' #else: # parent = parent elif isinstance(parent, list): if len(parent) > 0 and hasattr(parent[0], 'node'): #Get the correct parent in the list parent = parent[0].node().geom() #parent = parent[parent[0].node().selectedGeomIndex] #same thing else: parent = None else: assert parent is None geom.parent = None if parent is not None and parent!=geom.parent: #print "le parent" , parent #print "le geom.parent" , geom.parent if not self.effectiveParenting(parent, geom): warn( \ 'the parent is either in another viewer or is a child of the geometry') return 'Stop' # node fails to execute return 'Go' def effectiveParenting(self, lParent, geom=None): """try to reparent geometry, return True upon success after this call the geometry has a valid name it will parent the selectedGeomIndex unless geom is provided """ #print "EffectiveParenting" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if geom is None: geom = self.geom() if geom.viewer is None: # we cannot do anything yet because we do geom.parent = lParent # not know the viewer yet geom.fullName = geom.BuildFullName() return True # lParent will be used when geom is added to Viewer if lParent is None: lParent = geom.viewer.rootObject # try to reparent geometry if lParent.viewer is None: lHighestModifiedParent = \ geom.viewer.AddObjectAndParents(lParent, parent=lParent.parent, local=False) else: lHighestModifiedParent = geom # get unique name among new parent's children name = geom.viewer.ensureUniqueName(geom.name, lParent, local=False, exclude=geom) #name = geom.viewer.ensureUniqueName(name, lParent, local=False, exclude=geom) # set the geometry's name NOT using geom.Set() because parent is still # the old one and geom.Set(name=..) checks name validity geom.name = name geom.viewer.ReparentObject(geom, lParent, objectRetainsCurrentPosition=self.inputPortByName['parent'].retainPosition.get()) self.ensureNameOfNodeAndDescendants(lHighestModifiedParent) #except AssertionError: # if parent is different viewer than geom # # or ... # return False return True def drawParentAndChildrenConnections(self): """ finds the selected children and parent and draws the connections if they are selected in their own node """ #print "DrawParentAndChildrenConnections", self.name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.selectedGeomIndex is None: return # first we remove the existing parent connection self.removeParentConnection() # we remove the existing children connections self.removeChildrenConnections() # set the parent connection if parent is selected in his own node self.setParentConnection() # set the children connections when the children are selected self.setChildrenConnections() def setParentConnection(self): """ set the parent connection if parent is selected in his own node """ #print "setParentConnection", self if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # first we set corectly the parent node children port for g in self.geoms: p = g.parent v = g.viewer if p is not None and v is not None and p != v.rootObject: if hasattr(p,'node'): p.node().setPortsOfTheChildrenConnections() # then we set this node parent port lParentPort = self.inputPortByName['parent'] lParentPort.hasHiddenConnections = False lParent = self.geom().parent if lParent is None: lParentPort.deleteIcon() lParentPort.createIcon() return viewer = self.geom().viewer if viewer is not None and lParent == viewer.rootObject: lParentPort.deleteIcon() lParentPort.createIcon() return if hasattr(lParent,'node'): lParentNode = lParent.node() if (lParentNode.selectedGeomIndex is not None) \ and (self.geom().parent == lParentNode.geom() ): lParentNodeOutputPort = lParentNode.getOutputPortByType('geomOrInsert2d') if lParentNode.network == self.network: self.network.connectNodes(lParentNode, self, lParentNodeOutputPort.name, 'parent', doNotSchedule=True, doNotCb=True) elif isinstance(self.network, MacroNetwork): #import pdb;pdb.set_trace() lMacroNode = self.network.macroNode while lParentNode.network != lMacroNode.network: lMacroNode = lMacroNode.network.macroNode lPortNameInMacro = self.name + '_parent' if lMacroNode.inputPortByName.has_key(lPortNameInMacro) is False: for p in lMacroNode.inputPorts: if p.name.endswith('_parent'): lPortNameInMacro = p.name break else: #we didn't break assert "weird! we should have found the port _parent" lParentNode.network.connectNodes( lParentNode, lMacroNode, lParentNodeOutputPort.name, lPortNameInMacro, doNotSchedule=True, doNotCb=True) elif isinstance(lParentNode.network, MacroNetwork): #import pdb;pdb.set_trace() lMacroNode = lParentNode.network.macroNode while self.network != lMacroNode.network: lMacroNode = lMacroNode.network.macroNode lPortNameInMacro = lParentNode.name + '_' + lParentNodeOutputPort.name if lMacroNode.outputPortByName.has_key(lPortNameInMacro) is False: for p in lMacroNode.outputPorts: if p.name.endswith('_' + lParentNodeOutputPort.name): lPortNameInMacro = p.name break else: #we didn't break assert "weird! we should have found the port _%s"%lParentNodeOutputPort.name lMacroNode.network.connectNodes( lMacroNode, self, lPortNameInMacro, 'parent', doNotSchedule=True, doNotCb=True) # TODO: make sure the white/black outline is set on the ports #lMacroNode.inputPortByName[lPortNameInMacro].deleteIcon() #lMacroNode.inputPortByName[lPortNameInMacro].createIcon() else: lParentPort.hasHiddenConnections = True else: # if len(lParentPort.connections) == 1: # #if lParent != lParentPort.connections[0].port1.data: # if lParent != lParentPort.getData(): # lParentPort.hasHiddenConnections = True # if len(lParentPort.connections) == 0: # if not ( (lParent is None) \ # or ( (self.geom().viewer is not None) \ # and (lParent == self.geom().viewer.rootObject) ) ): # lParentPort.hasHiddenConnections = True if lParent != lParentPort.getData(): if not ( (lParent is None) \ or ( (self.geom().viewer is not None) \ and (lParent == self.geom().viewer.rootObject) ) ): lParentPort.hasHiddenConnections = True lParentPort.deleteIcon() lParentPort.createIcon() def removeParentConnection(self): #print "removeParentConnection", self if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lParentPort = self.inputPortByName['parent'] for c in lParentPort.connections[::-1]: # going backwards if isinstance(c.port1.node, GeometryNode) is True: self.network.deleteConnectionsNoCB(c) elif isinstance(c.port1.node, MacroInputNode) is True: if self.geom().parent is None: continue if self.geom().viewer is not None \ and self.geom().parent == self.geom().viewer.rootObject: continue lParentNode = self.geom().parent.node() lParentNetwork = lParentNode.network lMacroNode = c.port1.node lMacroNetwork = lMacroNode.network while lParentNetwork != lMacroNetwork: lMacroNode = lMacroNetwork.macroNode lMacroNetwork = lMacroNode.network lPortNameInMacro = self.name + '_parent' if lMacroNode.inputPortByName.has_key(lPortNameInMacro) is False: for p in lMacroNode.inputPorts: if p.name.endswith('_parent'): lPortNameInMacro = p.name break; else: #we didn't break assert "weird! we should have found the port _parent" lConnections = lMacroNode.inputPortByName[lPortNameInMacro].connections if len(lConnections) > 0: # there is a unique connection lMacroNetwork.deleteConnectionsNoCB(lConnections[0]) else: #needed for macro node self.effectiveParenting(None) elif self.selectedGeomIndex is not None: if self.geom().parent is None: self.network.deleteConnectionsNoCB(c) elif self.geom().viewer is not None \ and self.geom().parent == self.geom().viewer.rootObject: self.network.deleteConnectionsNoCB(c) elif self.geom().parent != lParentPort.getData(): self.network.deleteConnectionsNoCB(c) def setChildrenConnections(self): #print "setChildrenConnections" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() for lChild in self.geom().children: if hasattr(lChild, 'node'): if lChild == lChild.node().geom(): # the child is selected in its node lChild.node().setParentConnection() self.setPortsOfTheChildrenConnections() def setPortsOfTheChildrenConnections(self): #print "setPortsOfTheChildrenConnections" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lChildPort = self.getOutputPortByType('geomOrInsert2d') lChildPort.hasHiddenConnections = False for lChild in self.geom().children: if hasattr(lChild, 'node'): lOtherPort = lChild.node().inputPortByName['parent'] if lChild == lChild.node().geom(): # the child is selected in its node lOtherPort.hasHiddenConnections = False lOtherPort.deleteIcon() lOtherPort.createIcon() else: lChildPort.hasHiddenConnections = True lChildPort.deleteIcon() lChildPort.createIcon() def removeChildrenConnections(self): #print "removeChildrenConnections" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() for lChild in self.geom().children: if hasattr(lChild, 'node'): if lChild == lChild.node().geom(): # the child is selected in its node lChild.node().removeParentConnection() def rebuildComboBoxList(self): """ """ #print "RebuildComboBoxList" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() w0 = self.inputPortByName['geoms'].widget if not hasattr(w0,'widget'): return w = w0.widget w.delete(0,'end') if self.selectedGeomIndex is None: w.setentry('') return for g in self.geoms: w.insert('end',g.name) w.selectitem(self.selectedGeomIndex,setentry=1) lName = self.geom().name if self.name != lName: self.rename(lName) def reparentGeoms(self, list): #print "reparentGeoms", list if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() parent = self.inputPortByName['parent'].getData() #print "parent", parent for g in list: self.parenting(parent,g) def reparentGeomType(self, type, reparentCurrent = True): #print "reparentGeomType", type if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.selectedGeomIndex is None: return lGeomsToReparent = [] geom = self.geom() if type == 'current': lGeomsToReparent.append(geom) elif type == 'siblings': # build list of siblings for g in self.geoms: if g is not geom or reparentCurrent is True: #print g.parent #print geom.parent if g.parent is geom.parent: lGeomsToReparent.append(g) elif type == 'all': # build list assert type == 'all' , type for g in self.geoms: if g is not geom or reparentCurrent is True: lGeomsToReparent.append(g) else: assert type == 'none' , type self.reparentGeoms(lGeomsToReparent) def getViewerConnection(self, node): #print "getViewerConnection", self.name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lOutputPort = node.getOutputPortByType('geomOrInsert2d') if lOutputPort is None: return None for c in lOutputPort.connections: from DejaVu.VisionInterface.DejaVuNodes import Viewer if isinstance(c.port2.node, Viewer): return c elif isinstance(c.port2.node, MacroOutputNode): m = c.port2.node.macroNode lOutputPortMacro = m.getOutputPortByName(c.port2.name) for cm in lOutputPortMacro.connections: if isinstance(cm.port2.node, Viewer): return cm # elif isinstance(c.port2.node, MacroNode): # lViewerNode = self.getViewerConnection(c.port2.node) # if lViewerNode is not None: # return lViewerNode # elif hasattr(c.port2.node, 'getViewerConnection'): # lViewerNode = c.port2.node.getViewerConnection(c.port2.node) # if lViewerNode is not None: # return lViewerNode else: lViewerNode = self.getViewerConnection(c.port2.node) if lViewerNode is not None: return lViewerNode else: return None def afterDisconnectParent(self, p1): #print "GeometryNode afterDisconnectParent" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #import pdb;pdb.set_trace() lViewerConnection = self.getViewerConnection(self) if lViewerConnection is not None: lParentNode = p1.node if isinstance(lParentNode, GeometryNode): lParentOutputPort = lParentNode.getOutputPortByType('geomOrInsert2d') lViewerGeomPort = lViewerConnection.port2 if lParentNode.network == lViewerGeomPort.node.network: self.network.connectNodes( lParentNode, lViewerGeomPort.node, lParentOutputPort.name, lViewerGeomPort.name, doNotSchedule=True, doNotCb=True) self.parenting(None) self.rebuildComboBoxList() def afterConnectParent(self, port, conn): #print "GeometryNode afterConnectParent" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if port.getData() == 'Stop': port.data = None else: if self.selectedGeomIndex is not None: self.reparentGeomType(conn.port2.cascadeMenuVariable.get(), reparentCurrent=True) self.rebuildComboBoxList() def afterDisconnectChildren(self, p1, p2): #print "GeometryNode afterDisconnectChildren", self.name if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #import pdb;pdb.set_trace() if hasattr(p2, 'node'): lChidrenNode = p2.node if isinstance(lChidrenNode, MacroNode): lViewerConnection = self.getViewerConnection(lChidrenNode) if lViewerConnection is not None: lParentNode = p1.node lParentOutputPort = lParentNode.getOutputPortByType('geomOrInsert2d') lViewerGeomPort = lViewerConnection.port2 if lParentNode.network == lViewerGeomPort.node.network: self.network.connectNodes( lParentNode, lViewerGeomPort.node, lParentOutputPort.name, lViewerGeomPort.name, doNotSchedule=True, doNotCb=True) def beforeRemovingFromNetwork(self): #print "beforeRemovingFromNetwork" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #self.removeParentConnection() if len(self.geoms) > 0: #self.removeChildrenConnections() for g in self.geoms: self.removeSingleGeomAndReparentChildren(g) del(g.node) def textureManagement(self, image, textureCoordinates=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if image is not None and self.selectedGeomIndex is not None: g = self.geom() from DejaVu.Texture import Texture lTexture = Texture(enable=1, image=image) if textureCoordinates is not None: g.Set(texture=lTexture, textureCoords=textureCoordinates) else: g.Set(texture=lTexture) if hasattr(g.vertexSet, 'texCoords'): g.vertexSet.texCoords.array = \ lTexture.getTextureCoordinatesAfterResizeRatio( g.vertexSet.texCoords.array) class IndexedPolygonsNE(GeometryNode): """Build a geometry for drawing a set of polygons sharing vertices. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: coords: Nx3 floating points values (type coordinates3D) indices: nested lists of indices (1 tuple per object) vnormals: normal vectors at each vertex colors: list of RGB tuples (optional) image: images from PIL can be use as texture textureCoordinates: used if their number match coords or indices """ def __init__(self, name='indexedPolygons', **kw): kw['name'] = name apply( GeometryNode.__init__, (self, 'indexedPolygons'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords') ip.append(datatype='indice3or4(0)', name='indices') ip.append(datatype='normal3(0)', required=False, name='vnormals') ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') ip.append(datatype='image', required=False, name='image') ip.append(datatype='coord2(0)', required=False, name='textureCoordinates') # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() code = """def doit(self, coords, indices, vnormals, colors, image, textureCoordinates, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name #apply( GeometryNode.doit, (self,)+args ) GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(vertices=coords, faces=indices, materials=colors, tagModified=False, vnormals=vnormals, inheritMaterial=inheritMaterial ) GeometryNode.textureManagement(self, image=image, textureCoordinates=textureCoordinates) self.outputData(indexedPolygons=self.geom(), allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.IndexedPolygons import IndexedPolygons self.geoms.append(IndexedPolygons(name=name)) return 1 # num of geoms appended class IndexedPolylinesNE(GeometryNode): """Build a geometry for drawing a set of lines sharing vertices. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: coords: Nx3 floating points values (type coordinates3D) indices: nested lists of indices (1 tuple per polygon) vnormals: normal vectors at each vertex colors: list of RGB tuples (optional) image: images from PIL can be use as texture textureCoordinates: used if their number match coords or indices """ def __init__(self, name='indexedPolylines', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'indexedPolylines'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords') ip.append(datatype='indice2+(0)', name='indices') ip.append(datatype='normal3(0)', required=False, name='vnormals') ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') ip.append(datatype='image', required=False, name='image') ip.append(datatype='coord2(0)', required=False, name='textureCoordinates') # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() code = """def doit(self, coords, indices, vnormals, colors, image, textureCoordinates, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(vertices=coords, faces=indices, materials=colors, tagModified=False, vnormals=vnormals, inheritMaterial=inheritMaterial) GeometryNode.textureManagement(self, image=image, textureCoordinates=textureCoordinates) self.outputData(indexedPolylines=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.IndexedPolylines import IndexedPolylines self.geoms.append(IndexedPolylines(name)) return 1 # num of geoms appended class Cylinders(GeometryNode): """Build a geometry for drawing a set of cylinders. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: coords: Nx3 floating points values (type coordinates3D) indices: nested lists of indices (1 tuple per polygon) colors: list of RGB tuples (optional) image: images from PIL can be use as texture radius: float or list of floats of same length as coords (default is 1.0) quality: cylinder quality, the hight, the more polygons are drawn (default 5) """ def __init__(self, name='cylinders', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'cylinders'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords', required=False, defaultValue=((0,0,0),(10,0,0)) ) ip.append(datatype='indice2+(0)', name='indices', required=False, defaultValue=((0,1),) ) ip.append(datatype='colorfloat3or4(0)', name='colors', required=False) ip.append(datatype='float(0)', name='radius', required=False, defaultValue=1.) ip.append(datatype='int', name='quality', required=False, defaultValue=5) ip.append(datatype='image', name='image', required=False) # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() self.widgetDescr['quality'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':5, 'labelCfg':{'text':'quality:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['radius'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':1.0, 'labelCfg':{'text':'radius:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.1, 'wheelPad':2 } code = """def doit(self, coords, indices, colors, radius, quality, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(vertices=coords, faces=indices, materials=colors, tagModified=False, radii=radius, quality=quality, inheritMaterial=inheritMaterial) GeometryNode.textureManagement(self, image=image) self.outputData(cylinders=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.Cylinders import Cylinders self.geoms.append(Cylinders(name)) return 1 # num of geoms appended class AxisNE(GeometryNode): """Build a CylinderArrow geometry for drawing an AXIS. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: coords: Nx3 floating points values (type coordinates3D) indices: nested lists of indices (1 tuple per polygon) colors: list of RGB tuples (optional) image: images from PIL can be use as texture radius: float or list of floats of same length as coords (default is 1.0) quality: cylinder quality, the hight, the more polygons are drawn (default 5) headLength: headRadius: """ def __init__(self, name='axis', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'axis'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords', required=False, defaultValue=((0,0,0),(10,0,0)) ) ip.append(datatype='indice2+(0)', name='indices', required=False, defaultValue=((0,1),) ) ip.append(datatype='colorfloat3or4(0)', name='colors', required=False) ip.append(datatype='float(0)', name='radius', required=False, defaultValue=.6) ip.append(datatype='int', name='quality', required=False, defaultValue=5) ip.append(datatype='float', name='headLength', required=False) ip.append(datatype='float', name='headRadius', required=False) ip.append(datatype='image', name='image', required=False) # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() self.widgetDescr['quality'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':5, 'labelCfg':{'text':'quality:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':1, 'wheelPad':2 } self.widgetDescr['radius'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':1.0, 'labelCfg':{'text':'radius:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.1, 'wheelPad':2 } self.widgetDescr['headLength'] = { 'class':'NEThumbWheel', 'initialValue':1., 'labelCfg':{'text':'headLength:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['headRadius'] = { 'class':'NEThumbWheel', 'initialValue':2., 'labelCfg':{'text':'headRadius:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } code = """def doit(self, coords, indices, colors, radius, quality, headLength, headRadius, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() from opengltk.OpenGL import GL if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(vertices=coords, faces=indices, materials=colors, tagModified=False, culling=GL.GL_NONE, inheritCulling=False, backPolyMode=GL.GL_FILL, inheritBackPolyMode=False, quality=quality, radii=radius, inheritMaterial=inheritMaterial) GeometryNode.textureManagement(self, image=image) self.outputData(axis=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.Cylinders import CylinderArrows self.geoms.append(CylinderArrows(name)) return 1 # num of geoms appended class Spheres(GeometryNode): """Build a geometry for drawing a set of spheres. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Output Ports: first output port: currently selected geometry allGeometries: list of all the geometries in the node Input Ports: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) coords: Nx3 floating points values (type coordinates3D) colors: list of RGB tuples (optional) image: images from PIL can be use as texture radius: float or list of floats of same length as coords (default is 1.0) quality: cylinder quality, the hight, the more polygons are drawn (default 5) """ def __init__(self, name='spheres', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'spheres'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords', required=False, defaultValue=((0,0,0),)) ip.append(datatype='colorfloat3or4(0)', name='colors', required=False) ip.append(datatype='float(0)', name='radius', required=False, defaultValue=1.) ip.append(datatype='int', name='quality', required=False, defaultValue=5) ip.append(datatype='image', name='image', required=False) # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() self.widgetDescr['quality'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':5, 'labelCfg':{'text':'quality:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['radius'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':1.0, 'labelCfg':{'text':'radius:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.0000001, 'wheelPad':2 } code = """def doit(self, coords, colors, radius, quality, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) try: len(radius) islist = True except TypeError: islist = False if islist: assert (len(radius)==1) or (len(radius)==len(coords)) if self.selectedGeomIndex is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(vertices=coords, materials=colors, tagModified=False, radii=radius, quality=quality, inheritMaterial=inheritMaterial) GeometryNode.textureManagement(self, image=image) self.outputData(spheres=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.Spheres import Spheres self.geoms.append(Spheres(name)) return 1 # num of geoms appended class Points(GeometryNode): """Build a geometry for drawing a set of 3D Points The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Output Ports: first output port: currently selected geometry allGeometries: list of all the geometries in the node Input Ports: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) coords: Nx3 floating points values (type coordinates3D) colors: list of RGB tuples (optional) size: point size as an integer """ def __init__(self, name='points', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'points'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords', required=False, defaultValue=((0,0,0),)) ip.append(datatype='colorfloat3or4(0)', name='colors', required=False) ip.append(datatype='int', name='size', required=False, defaultValue=3) # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() self.widgetDescr['size'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':3, 'labelCfg':{'text':'size:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':1, 'wheelPad':2 } code = """def doit(self, coords, colors, size, name, geoms, instanceMatrices, geomOptions, parent): GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(vertices=coords, materials=colors, tagModified=False, pointWidth=size, inheritPointWidth=False, inheritMaterial=inheritMaterial) self.outputData(points=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.Points import Points self.geoms.append(Points(name)) return 1 # num of geoms appended class CrossSet(GeometryNode): """Build a geometry for drawing a set of 3D crosses. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Output Ports: first output port: currently selected geometry allGeometries: list of all the geometries in the node Input Ports: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) coords: Nx3 floating points values (type coordinates3D) colors: list of RGB tuples (optional) size: float, cross size """ def __init__(self, name='crossSet', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'crossSet'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords', required=False, defaultValue=((0,0,0),)) ip.append(datatype='colorfloat3or4(0)', name='colors', required=False) ip.append(datatype='float', name='size', required=False, defaultValue=1.) # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() self.widgetDescr['size'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':3., 'labelCfg':{'text':'quality:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10., 'lockBMin':0., 'min':0., 'wheelPad':2 } code = """def doit(self, coords, colors, size, name, geoms, instanceMatrices, geomOptions, parent): GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(vertices=coords, materials=colors, tagModified=False, offset=size, inheritMaterial=inheritMaterial) self.outputData(crossSet=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.Points import CrossSet self.geoms.append(CrossSet(name)) return 1 # num of geoms appended class GeomContainer(GeometryNode): """Build a geometry that can be used as a container for other geometries. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: """ """Set of polygons sharing vertices.""" def __init__(self, name='geomContainer', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'geomContainer'), kw ) #ip = self.inputPortsDescr # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) # AS THERE IS NO INPUT PORT HERE, WE DON'T NEED TO CALL THIS #self.rearrangePorts() code = """def doit(self, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() #g.Set( tagModified=False) self.outputData(geomContainer=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) self.geoms.append(Geom(name)) return 1 # num of geoms appended class Ellipsoids(GeometryNode): """Build a geometry for drawing a set of Ellipsoids. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: ellipsoids: list of ellipsoid objects (can be generated using the EllipsoidFit node) colors: list of RGB tuples (optional) image: images from PIL can be use as texture """ def __init__(self, name='ellipsoids', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'ellipsoids'), kw ) ip = self.inputPortsDescr ip.append(datatype='list', name='ellipsoids') ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') ip.append(datatype='image', required=False, name='image') # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() code = """def doit(self, ellipsoids, colors, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if ellipsoids is not None: centers = [] size = [] orient = [] for ellipse in ellipsoids: centers.append( ellipse.getPosition() ) size.append( ellipse.getAxis().astype('f') ) orint = identity(4, 'f') orint[:3, :3] = ellipse.getOrientation() orient.append( orint ) if self.selectedGeomIndex is not None and ellipsoids is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None g.Set(centers=centers, scaling=size, orientation=orient, materials=colors, tagModified=False, quality=30, inheritMaterial=inheritMaterial) GeometryNode.textureManagement(self, image=image) self.outputData(ellipsoids=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.Ellipsoids import Ellipsoids self.geoms.append(Ellipsoids(name)) return 1 # num of geoms appended class Array2DToHeightFieldGeom(GeometryNode): """ convert a 2D array of values into a height field The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: data: 2Darray scaleZ: Z scaling factor """ def __init__(self, name='heightField', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'heightField'), kw) ip = self.inputPortsDescr ip.append({'name': 'data', 'datatype': '2Darray'}) ip.append({'name': 'scaleZ', 'datatype': 'float', 'defaultValue':1.}) self.rearrangePorts() self.widgetDescr['scaleZ'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':1.0, 'labelCfg':{'text':'scale Z:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0.0, 'wheelPad':2 } code = """def doit(self, data, scaleZ, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None and data is not None: # normalize the data to range from 0 to 255 maxi = max(data.ravel()) mini = min(data.ravel()) delta = maxi-mini data2 = (data-mini)/delta verts = [] quads = [] sx, sy = data.shape for xi in xrange(sx): base = sy*xi for yi in xrange(sy): verts.append( (xi,yi,data[xi,yi]/scaleZ) ) if xi 0: self.outputData(allGeometries=self.geoms) """ self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.IndexedPolygons import IndexedPolygons self.geoms.append(IndexedPolygons(name)) return 1 # num of geoms appended class GeomsFromFile(GeometryNode): """inheriting GeometryNode, this node reads several file formats, STL, OBJ, VERT ... and generates the correcponding geoms. the geom's names are deducted from the filename. you can easily add new file types to this node. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: filename: image: images from PIL can be use as texture """ def __init__(self, name='geomsFromFile', **kw): kw['name'] = name apply( GeometryNode.__init__, (self,'geomsFromFile'), kw ) ip = self.inputPortsDescr ip.append(datatype='string', name='filename') ip.append(datatype='image', required=False, name='image') self.rearrangePorts() self.widgetDescr['filename'] = { 'class':'NEEntryWithFileBrowser', 'master':'node', 'width':10, 'initialValue':'', 'labelCfg':{'text':'Filename: '}, 'filetypes': [('3d object', '*.stl *.obj *.vert *.indpolvert'), ('all', '*')]} self.filenames = [] code = """def doit(self, filename, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit",name, self.name lName = os.path.split(os.path.splitext(filename)[0])[-1] if filename not in self.filenames: self.filenames.append(filename) name = lName else: for g in self.geoms: if (g.name == lName) or g.name.startswith(lName + '+'): break else: #we didn't break if geoms == '': self.filenames.remove(filename) else: name = lName GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() #g.Set( tagModified=False ) GeometryNode.textureManagement(self, image=image) self.outputData(geomsFromFile=g, allGeometries=self.geoms) elif len(self.geoms) > 0: self.outputData(allGeometries=self.geoms) """ self.setFunction(code) def appendGeometry(self, name): # in this, we dont use the parameter "name" at all filename = self.inputPortByName['filename'].getData() if filename is None or filename == '': return # read the geoms from the file lExt = os.path.splitext(filename)[-1][1:].lower() if lExt == 'stl': moreGeoms = self.readFileSTL(filename) elif lExt == 'vert': moreGeoms = self.readMsmsFile(filename) elif lExt == 'indpolvert': moreGeoms = self.readFileIndexedPolygons(filename) elif lExt == 'obj': moreGeoms = self.readFileOBJ(filename) else: assert False # append the geoms if moreGeoms is not None: self.removePreviousGeomsWithSameName(moreGeoms) self.geoms.extend(moreGeoms) return len(moreGeoms) else: return 0 def nameGeoms(self, listOfGeoms, filename): """renames each geom differently """ if len(listOfGeoms) > 0: nameSplit = os.path.splitext(filename) name = os.path.split(nameSplit[0])[-1] listOfGeoms[0].name = name for i in range(1, len(listOfGeoms)): listOfGeoms[i].name = name + '+' + str(i) def readFileSTL(self, filename): """from a filename, returns a list of geoms """ from DejaVu.DataInput import readAnySTL moreGeoms = readAnySTL(filename) return moreGeoms def readMsmsFile(self, filename): """from a filename, returns a list of geoms """ try: from mslib.msmsParser import MSMSParser faceFilename = os.path.splitext(filename)[0] + '.face' vertFilename = filename print "faceFilename", faceFilename from mslib.msmsParser import MSMSParser lMsmsParser = MSMSParser() from DejaVu.IndexedPolygons import IndexedPolygons vertices, faces = lMsmsParser.parse(vertFilename, faceFilename) singleGeom = IndexedPolygons(vertices=vertices, faces=faces) moreGeoms = [ singleGeom ] self.nameGeoms(moreGeoms, filename) return moreGeoms except: return None def readFileIndexedPolygons(self, filename): """from a filename, returns a list of geoms """ from DejaVu.IndexedPolygons import IndexedPolygonsFromFile singleGeom = IndexedPolygonsFromFile(filename) moreGeoms = [ singleGeom ] self.nameGeoms(moreGeoms, filename) return moreGeoms def readFileOBJ(self, filename): """from a filename, returns a list of geoms """ from DejaVu.DataInput import readOBJ moreGeoms = readOBJ(filename) return moreGeoms #class GlutLabelsNE(GeometryNode): # """Build a geometry for drawing a set of polygons sharing vertices. # #The geometry nodes handle a list of geometries. When the name changes, #a new geom is generated. If an empty name is provided, the current geometry #is deleted. # #The parent and children connections reflect the state of the geometry selected #in the combo box. If the parent or children geoms are currently selected in #their own node: the connections are present. If the parent or a child is not #visible (for the selected geometry) the parent port or/and the output port #contour lines are white (instead of black). Before parenting you can set the #behaviour of the 'parent' inputport. Right clicking on the port allows you to #extend the parenting to the sibling geometries present in the node or to all #the geometries of the node. This behaviour set by right clicking will only #affect the next parenting. In the same way, deleting the parent connection, #reparent to 'root' the selected geometry or the sibling geometries or all the #geometries in the child node (depending on the right click menu choice). # #Input Ports: # coords: Nx3 floating points values (type coordinates3D) # labels: list of labels ex:['label1', 'label2', 15.56, 'label4', 4, 5.78] # if one label only, it applies to all coords, # otherwise len(coords) should equal len(labels) # font: # colors: list of RGB tuples (optional) # name: name of the geometry # instanceMatrices: stream of 4x4 transformation matrices (default identity) # parent: a geometry to parent the selected geometry (default root) # #Output Ports: # indexedPolygons: IndexedPolygons geometry # allGeometries: list of all the geometries in the node #""" # # def __init__(self, name='glutlabels', **kw): # # kw['name'] = name # apply( GeometryNode.__init__, (self, 'glutlabels'), kw ) # # ip = self.inputPortsDescr # ip.append(datatype='coord3(0)', name='coords') # ip.append(datatype='string(0)', name='labels') # ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') # ip.append(datatype='string', required=False, name='font') # # # for backward compatibility # # this make sure that the first ports in the node are the ones # # that use to be there before we introduced the GeometryNode class # # (old network were saved with port indices instead of port names) # self.rearrangePorts() # # self.widgetDescr['font'] = { # 'class':'NEComboBox', # 'master':'node', # 'entryfield_entry_width':14, # 'choices':[ 'glutTimesRoman10', # 'glut9by15', # 'glut8by13', # 'glutTimesRoman10', # 'glutTimesRoman24', # 'glutHelvetica10', # 'glutHelvetica12', # 'glutHelvetica18' # ], # 'initialValue':'glutTimesRoman10', # 'autoList':True, # 'labelCfg':{'text':'font:'}, # } # # self.widgetDescr['labels'] = { # 'class':'NEEntry', 'master':'node', 'width':10, # 'labelCfg':{'text':'labels:'}, # } # # code = """def doit(self, coords, labels, colors, font, #name, geoms, instanceMatrices, geomOptions, parent): # #print "doit", self.name # #apply( GeometryNode.doit, (self,)+args ) # GeometryNode.doit(self, name=name, geoms=geoms, # instanceMatrices=instanceMatrices, # geomOptions=geomOptions, parent=parent) # # if self.selectedGeomIndex is not None: # g = self.geom() # if colors is not None: # inheritMaterial = False # else: # inheritMaterial = None # import types # if type(labels) == types.StringType: # if len(labels): # labels = eval(labels) # if (labels is not None) and (labels != ''): # g.Set( inheritMaterial=inheritMaterial, # materials=colors, # tagModified=False, # visible=1, # labels=labels, # vertices=coords, # font=font) # else: # g.Set(visible=0) # self.outputData(glutlabels=g, allGeometries=self.geoms) # else: # self.outputData(glutlabels=None, allGeometries=self.geoms) #""" # if code: self.setFunction(code) # # # def appendGeometry(self, name): # self.removePreviousGeomWithSameName(name) # from DejaVu.Labels import Labels # self.geoms.append( Labels(name=name, shape=(0,3) ) ) # return 1 # num of geoms appended class GlfLabelsNE(GeometryNode): """Build a geometry for drawing a set of polygons sharing vertices. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: coords: Nx3 floating points values (type coordinates3D) vnormals: normal vectors at each vertex colors: list of RGB tuples (optional) image: images from PIL can be use as texture labels: list of labels ex:['label1', 'label2', 15.56, 'label4', 4, 5.78] if one label only, it applies to all coords, otherwise len(coords) should equal len(labels) font: """ def __init__(self, name='glflabels', **kw): kw['name'] = name apply( GeometryNode.__init__, (self, 'glflabels'), kw ) ip = self.inputPortsDescr ip.append(datatype='coord3(0)', name='coords', required=False, defaultValue=((0,0,0),) ) ip.append(datatype='string(0)', name='labels', required=False) ip.append(datatype='normal3(0)', name='vnormals', required=False) ip.append(datatype='colorfloat3or4(0)', name='colors', required=False) ip.append(datatype='boolean', name='billboard', required=False) ip.append(datatype='boolean', name='includeCameraRotationInBillboard', required=False) ip.append(datatype='string', name='font', required=False) ip.append(datatype='string', name='fontstyle', required=False) ip.append(datatype='float', name='fontSpacing', required=False) ip.append(datatype='float', name='scaleXYZ', required=False) ip.append(datatype='float', name='scaleX', required=False) ip.append(datatype='float', name='scaleY', required=False) ip.append(datatype='float', name='scaleZ', required=False) ip.append(datatype='float', name='fontRotateAngleX', required=False) ip.append(datatype='float', name='fontRotateAngleY', required=False) ip.append(datatype='float', name='fontRotateAngleZ', required=False) ip.append(datatype='float', name='fontTranslateX', required=False) ip.append(datatype='float', name='fontTranslateY', required=False) ip.append(datatype='float', name='fontTranslateZ', required=False) ip.append(datatype='image', name='image', required=False) # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() from DejaVu.glfLabels import GlfLabels self.widgetDescr['labels'] = { 'class':'NEEntry', 'master':'node', 'initialValue':['Aa','Bb','Cc'], 'width':10, 'labelCfg':{'text':'labels:'}, } self.widgetDescr['billboard'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelCfg':{'text':'billboard:'}, } self.widgetDescr['includeCameraRotationInBillboard'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelCfg':{'text':'includeCameraRotationInBillboard:'}, } self.widgetDescr['font'] = { 'class':'NEComboBox', 'master':'node', 'entryfield_entry_width':14, 'choices':GlfLabels.fontList, 'initialValue':GlfLabels.fontList[0], 'autoList':True, 'labelCfg':{'text':'font:'}, } self.widgetDescr['fontstyle'] = { 'class':'NEComboBox', 'master':'node', 'entryfield_entry_width':14, 'choices':GlfLabels.fontStyleList, 'initialValue':GlfLabels.fontStyleList[3], 'autoList':True, 'labelCfg':{'text':'font style:'}, } self.widgetDescr['fontSpacing'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':1, 'min':0., 'max':1., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':.2, 'labelCfg':{'text':'fontSpacing'}, } self.widgetDescr['scaleXYZ'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':1, 'min':0., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':1., 'labelCfg':{'text':'scale XYZ'}, } self.widgetDescr['scaleX'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':1, 'min':0., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':1., 'labelCfg':{'text':'scale X'}, } self.widgetDescr['scaleY'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':1, 'min':0., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':1., 'labelCfg':{'text':'scale Y'}, } self.widgetDescr['scaleZ'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':1, 'min':0., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':1., 'labelCfg':{'text':'scale Z'}, } self.widgetDescr['fontRotateAngleX'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':90, 'min':-180., 'max':180., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':0., 'labelCfg':{'text':'font rotation angle X'}, } self.widgetDescr['fontRotateAngleY'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':90, 'min':-180., 'max':180., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':0., 'labelCfg':{'text':'font rotation angle Y'}, } self.widgetDescr['fontRotateAngleZ'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':90, 'min':-180., 'max':180., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':0., 'labelCfg':{'text':'font rotation angle Z'}, } self.widgetDescr['fontTranslateX'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':10, 'min':-100., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':0., 'labelCfg':{'text':'font translation X'}, } self.widgetDescr['fontTranslateY'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':10, 'min':-100., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':0., 'labelCfg':{'text':'font translation Y'}, } self.widgetDescr['fontTranslateZ'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':10, 'min':-100., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':0., 'labelCfg':{'text':'font translation Z'}, } code = """def doit(self, coords, labels, vnormals, colors, billboard, includeCameraRotationInBillboard, font, fontstyle, fontSpacing, scaleXYZ, scaleX, scaleY, scaleZ, fontRotateAngleX, fontRotateAngleY, fontRotateAngleZ, fontTranslateX, fontTranslateY, fontTranslateZ, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name #apply( GeometryNode.doit, (self,)+args ) GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() if colors is not None: inheritMaterial = False else: inheritMaterial = None import types if type(labels) == types.StringType: if len(labels): labels = eval(labels) if (labels is not None) and (labels != ''): g.Set( inheritMaterial=inheritMaterial, materials=colors, polyFace='frontandback', tagModified=False, visible=1, labels=labels, vertices=coords, vnormals=vnormals, billboard=billboard, includeCameraRotationInBillboard=includeCameraRotationInBillboard, font=font, fontStyle=fontstyle, fontSpacing=fontSpacing, fontScales=(scaleXYZ*scaleX, scaleXYZ*scaleY, scaleXYZ*scaleZ), fontRotateAngles=(fontRotateAngleX, fontRotateAngleY, fontRotateAngleZ), fontTranslation=(fontTranslateX, fontTranslateY, fontTranslateZ), ) else: g.Set(visible=0) GeometryNode.textureManagement(self, image=image) self.outputData(glflabels=g, allGeometries=self.geoms) else: self.outputData(glflabels=None, allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.glfLabels import GlfLabels self.geoms.append( GlfLabels(name=name, shape=(0,3) ) ) return 1 # num of geoms appended class BoxNE(GeometryNode): """Displays a 3-dimensional box whose colors depict the different axes upon which they lie: x-axis: Red y-axis: Green z-axis: Blue The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: image: images from PIL can be use as texture if textureCoordinates are provided textureCoordinates: used if their number match coords or indices """ def __init__(self, name='box', **kw): kw['name'] = name apply( GeometryNode.__init__, (self, 'box'), kw ) ip = self.inputPortsDescr ip.append(datatype='float', required=False, name='centerx') ip.append(datatype='float', required=False, name='centery') ip.append(datatype='float', required=False, name='centerz') ip.append(datatype='float', required=False, name='lengthx') ip.append(datatype='float', required=False, name='lengthy') ip.append(datatype='float', required=False, name='lengthz') ip.append(datatype='int', required=False, name='constrProps') ip.append(datatype='image', required=False, name='image') ip.append(datatype='coord2(0)', required=False, name='textureCoordinates') # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() wd = self.widgetDescr wd['centerx'] = { 'class':'NEThumbWheel', 'width':60, 'height':10, 'type':'float', 'showLabel':1, 'oneTurn':50., 'lockMin':True, 'labelCfg':{'text':'x center'}, 'master':'node', 'initialValue':0.0 } wd['centery'] = { 'class':'NEThumbWheel', 'width':60, 'height':10, 'type':'float', 'showLabel':1, 'oneTurn':50., 'lockMin':True, 'labelCfg':{'text':'y center'}, 'master':'node', 'initialValue':0.0 } wd['centerz'] = { 'class':'NEThumbWheel', 'width':60, 'height':10, 'type':'float', 'showLabel':1, 'oneTurn':50., 'lockMin':True, 'labelCfg':{'text':'z center'}, 'master':'node', 'initialValue':0.0 } wd['constrProps'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':1, 'labelCfg':{'text':'Constrain scale:'} } wd['lengthx'] = { 'class':'NEThumbWheel', 'width':60, 'height':10, 'type':'float', 'showLabel':1, 'oneTurn':50., 'lockMin':True, 'labelCfg':{'text':'x length'}, 'min':0.01, 'master':'node', 'initialValue':12.0 } wd['lengthy'] = { 'class':'NEThumbWheel', 'width':60, 'height':10, 'type':'float', 'showLabel':1, 'oneTurn':50., 'lockMin':True, 'labelCfg':{'text':'y length'}, 'min':0.01, 'master':'node', 'initialValue':12.0 } wd['lengthz'] = { 'class':'NEThumbWheel', 'width':60, 'height':10, 'type':'float', 'showLabel':1, 'oneTurn':50., 'lockMin':True, 'labelCfg':{'text':'z length'}, 'min':0.01, 'master':'node', 'initialValue':12.0 } code = """xyzprop='' #global set so that the set scale proportion is remembered. def doit(self, centerx, centery, centerz, lengthx, lengthy, lengthz, constrProps, image, textureCoordinates, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name #apply( GeometryNode.doit, (self,)+args ) GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) global xyzprop if self.selectedGeomIndex is not None: g = self.geom() if constrProps: if xyzprop=='': xratio=(lengthy/lengthx,lengthz/lengthx) yratio=(lengthx/lengthy,lengthz/lengthy) zratio=(lengthx/lengthz,lengthy/lengthz) xyzprop=(xratio,yratio,zratio) if self.inputPorts[3].hasNewValidData(): #x-length changed lengthy,lengthz=xyzprop[0][0]*lengthx,xyzprop[0][1]*lengthx if self.inputPorts[4].hasNewValidData(): #y-length changed lengthx,lengthz=xyzprop[1][0]*lengthy,xyzprop[1][1]*lengthy if self.inputPorts[5].hasNewValidData(): #z-length changed lengthx,lengthy=xyzprop[2][0]*lengthz,xyzprop[2][1]*lengthz if self.inputPorts[3]: self.inputPorts[3].widget.set(lengthx, run=0) if self.inputPorts[4]: self.inputPorts[4].widget.set(lengthy, run=0) if self.inputPorts[5]: self.inputPorts[5].widget.set(lengthz, run=0) else: xyzprop='' center = (centerx,centery,centerz) side = (lengthx,lengthy,lengthz) g.Set(center=center, xside=side[0], yside=side[1], zside=side[2]) GeometryNode.textureManagement(self, image=image, textureCoordinates=textureCoordinates) self.outputData(box=g, allGeometries=self.geoms) else: self.outputData(box=None, allGeometries=self.geoms) """ if code: self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) from DejaVu.Box import Box self.geoms.append( Box(name=name, center=(0.,0.,0.), side=10., inheritMaterial=0, frontPolyMode='line') ) return 1 # num of geoms appended class StickerTextNE(GeometryNode): """Build an insert2d for drawing a Sticker containing a 2d text Label. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: label: the string to be written in the sticker """ def __init__(self, name='stickerText', **kw): kw['name'] = name apply( GeometryNode.__init__, (self, 'stickerText'), kw ) self.widgetDescr['label'] = { 'class':'NEEntry', 'master':'node', 'width':12, 'labelCfg':{'text':'label'}, 'initialValue':'stickerText' } ip = self.inputPortsDescr ip.append(datatype='string', required=False, name='label', defaultValue='') # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() code = """def doit(self, label, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name lgeomState = None if self.selectedGeomIndex is not None and label == '': label = self.geom().label GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() g.Set(label=label, transparent=True) self.outputData(stickerText=g, allGeometries=self.geoms) else: self.outputData(stickerText=None, allGeometries=self.geoms) wn = self.inputPortByName['label'].widget if hasattr(wn,'widget'): wn.set('', run=0) """ self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) #print "appendGeometry" from DejaVu.glfSticker import Sticker self.geoms.append(Sticker(name)) return 1 # num of geoms appended class StickerImageNE(GeometryNode): """Build an insert2d for drawing a Sticker containing an Image. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: image: the Image to be applied on the sticker """ def __init__(self, name='stickerImage', **kw): kw['name'] = name apply( GeometryNode.__init__, (self, 'stickerImage'), kw ) ip = self.inputPortsDescr ip.append(datatype='image', required=True, name='image') # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() code = """def doit(self, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() from Image import FLIP_TOP_BOTTOM g.Set(image=image.transpose(FLIP_TOP_BOTTOM), transparent=True) self.outputData(stickerImage=g, allGeometries=self.geoms) else: self.outputData(stickerImage=None, allGeometries=self.geoms) """ self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) #print "appendGeometry" from DejaVu.StickerImage import StickerImage self.geoms.append(StickerImage(name)) return 1 # num of geoms appended class OneTexturedQuadNE(GeometryNode): """Build an quad in 3d for drawing a Sticker containing an Image. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: image: the Image to be applied on the sticker """ def __init__(self, name='oneTexturedQuad', **kw): kw['name'] = name apply( GeometryNode.__init__, (self, 'oneTexturedQuad'), kw ) ip = self.inputPortsDescr ip.append(datatype='image', required=False, name='image') # for backward compatibility # this make sure that the first ports in the node are the ones # that use to be there before we introduced the GeometryNode class # (old network were saved with port indices instead of port names) self.rearrangePorts() code = """def doit(self, image, name, geoms, instanceMatrices, geomOptions, parent): #print "doit", self.name GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() if image is not None: from DejaVu.Texture import Texture lTexture = Texture(enable=1, image=image) g.Set(texture=lTexture, textureCoords=( (0, 0), (1, 0), (1, 1), (0, 1))) g.vertexSet.texCoords.array = lTexture.getTextureCoordinatesAfterResizeRatio( g.vertexSet.texCoords.array) self.outputData(oneTexturedQuad=g, allGeometries=self.geoms) else: self.outputData(oneTexturedQuad=None, allGeometries=self.geoms) """ self.setFunction(code) def appendGeometry(self, name): self.removePreviousGeomWithSameName(name) #print "appendGeometry" w = 10 h = 10 from DejaVu.IndexedPolygons import IndexedPolygons lIndexedPolygons = IndexedPolygons( name, vertices=[(0, 0, 0), (w, 0, 0), (w, h, 0), (0, h, 0)], faces = ((0,1,2,3), ) ) self.geoms.append(lIndexedPolygons) return 1 # num of geoms appended import types class DecimateGeom(GeometryNode): """Uses QSlim library to decimate a surface. Creates a QSlim model from the input geometry, decimates it and outputs a new geometry with new number of faces, vertices, colors. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: geometry - any DejaVu.IndexedPolgons geometry (required); percent - percentage of faces to be retained in decimated model (required); targetfaces - corresponding to percent number of faces; rebuild - (boolean), when true, rebuilds the QSlim model (takes current parameters of selected geometry). """ def __init__(self, name = "decimateGeom", **kw): kw['name'] = name apply( GeometryNode.__init__, (self,"decimateGeom"), kw ) self.widgetDescr['name']['initialValue'] = "" self.widgetDescr['percent'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':100, 'min':0., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':50., 'labelCfg':{'text':'percent'}, } self.widgetDescr['targetfaces'] = { 'class':'NEEntry', 'master':'ParamPanel', 'width':10, 'labelCfg':{'text':'num of faces:'}, } self.widgetDescr['newgeom'] = { 'class':'NECheckButton', 'initialValue':0, 'master':'ParamPanel', 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'create new geometry'}, } self.widgetDescr['rebuild'] = { #'class':'NECheckButton', 'class':'NEButton', 'master':'ParamPanel', 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'rebuild Qslim model'} } ip = self.inputPortsDescr ip.append(datatype='geom', name='geometry') ip.append(name='percent', datatype='float') ip.append(name='targetfaces', datatype = "int", required=False) ip.append (name='rebuild', datatype='boolean', required=False) ip.append(datatype='None', name='u', required=False) ip.append(datatype='None', name='v', required=False) op = self.outputPortsDescr #op.append(datatype='geom', name='geometry') op.append(datatype='None', name='u') op.append(datatype='None', name='v') from DejaVu.VisionInterface.DejaVuNodes import QSlimDecimate self.model = QSlimDecimate() self.geometry = None # Current geometry self.rearrangePorts() code = """def doit(self, geometry , percent, targetfaces, rebuild, u, v, name, geoms, instanceMatrices, geomOptions, parent): #print 'DecimateGeom: name=', name, 'percent=', percent, 'targetfaces=', targetfaces, 'rebuild=', rebuild, self.inputPortByName['rebuild'].hasNewValidData() # DecimateGeom node can only handle 1 geom so far, so print out a message if there # are more comming in if type(geometry)==types.ListType: if len(geometry)>1: warnings.warn('Only first geometry is being processed by DecimateGeom') geometry = geometry[0] # check that the incomming geom can be represented as IndexedPolygons if not geometry.asIndexedPolygons(run=0): warnings.warn(geometry.name , 'DecimateGeom Node: %s can not be represented as IndexedPolygons', geometry.name) return if name == '': #if self.selectedGeomIndex is not None: # name = self.geom().name selInd = self.getInputPortByName('geoms').widget.widget.curselection() if len(selInd): self.selectedGeomIndex = int(selInd[0]) name = self.geom().name if name != self.name: self.name = name else: name = geometry.name # if there is new data on the first input port (geom) rebuild the model #if self.inputPortByName['geometry'].hasNewValidData() or \ #(self.inputPortByName['rebuild'].hasNewValidData() and rebuild): if self.inputPortByName['geometry'].hasNewValidData() or \ self.inputPortByName['rebuild'].hasNewValidData(): if len(geometry.vertexSet.vertices): print 'DecimateGeom Node BUILDING MODEL' self.model.build_model(geometry, u, v) else: return from DejaVu.IndexedPolygons import IndexedPolygons # compute the number of triangles to be kept maxFaces = self.model.maxFaces if self.inputPortByName['percent'].hasNewValidData(): #percent has changed targetfaces = int(maxFaces*percent/100.) elif self.inputPortByName['targetfaces'].hasNewValidData() and targetfaces: #targetfaces has changed targetfaces = int(targetfaces) else: # use the percentage targetfaces = int(maxFaces*percent/100.) #print 'ELSE', maxFaces*percent, targetfaces # make sure targetfaces is OK if targetfaces > maxFaces: targetfaces = maxFaces if self.inputPortByName['percent'].widget: self.inputPortByName['percent'].widget.set(100, 0) if self.inputPortByName['targetfaces'].widget: self.inputPortByName['targetfaces'].widget.set(maxFaces, 0) if self.model: decimVerts, decimFaces, decimNormals, decimColors, decimTex = self.model.decimate(targetfaces) #print 'creating geometry:', name self.geometry = IndexedPolygons(name, vertices=decimVerts, faces=decimFaces, vnormals=decimNormals) numFaces = len(decimFaces) nvert = len(decimVerts) clen = len(decimFaces) if self.model.newcolors is not None: if self.model.colorBind == 'vertex': clen = nvert #print 'len colors:', clen if clen > 0: self.geometry.Set(materials=decimColors[:clen], inheritMaterial=False, redo=True) else: self.geometry.Set(inheritMaterial=False, redo=True) # set the target face widget to the actual number of faces after # decimation if self.inputPortByName['targetfaces'].widget: self.inputPortByName['targetfaces'].widget.set(numFaces, run=0) realpercent = 100.*(float(numFaces)/maxFaces) if percent != realpercent and self.inputPortByName['percent'].widget: self.inputPortByName['percent'].widget.set(realpercent, run=0) u = None v = None if self.model.newtexcoords is not None: if hasattr(geometry.vertexSet, 'texCoords'): self.geometry.Set(textureCoords=decimTex[:nvert]) u = decimTex[:nvert,0] v = decimTex[:nvert,1] GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) if self.selectedGeomIndex is not None: g = self.geom() self.outputData(decimateGeom=g, allGeometries=self.geoms, u = u, v = v ) else: self.outputData(decimateGeom=None, allGeometries=self.geoms, u=u, v=v) """ self.setFunction(code) def appendGeometry(self, name): #print "append geometry, name:", name #print "self.geoms:", self.geoms self.removePreviousGeomsStartingWith(name) self.geoms.append(self.geometry) return 1 class ConnectedComponents(GeometryNode): """ Node to split connected surfaces. The geometry nodes handle a list of geometries. When the name changes, a new geom is generated. If an empty string is provided, the current geometry is deleted. The parent and children connections reflect the state of the geometry selected in the combobox. If the parent or children geoms are currently selected in their own node: the connections are present. If the parent or a child is not visible (for the selected geometry) the parent port or/and the output port contour lines are white (instead of black). Before parenting you can set the behavior of the 'parent' inputport. Right clicking on the port allows you to extend the parenting to the sibling geometries present in the node or to all the geometries of the node. This behavior set by right clicking will only affect the next parenting. In the same way, deleting the parent connection, reparent to 'root' the selected geometry or the sibling geometries or all the geometries in the child node (depending on the right click menu choice). Input Ports common to all GeometryNodes: new geom name: name of a new geometry to be created with the new data. when the node runs, this new geometry will be selected in the 'current geom' field and sent to the first output port. current geom: if 'new geom name' is empty, the new data coming from the input ports are applied to the current geom. at the end of the run the selected geometry is sent to the first output port. instanceMatrices: stream of 4x4 transformation matrices (default identity) geomOptions: accept a dictionary of properties with values. can be fed with node "SetGeom Options" parent: a geometry to parent the selected geometry (default root) Output Ports common to all GeometryNodes: first output port: currently selected geometry allGeometries: list of all the geometries in the node Specific Input Ports: -geometry or a list of geometries(the first object in the list will be used as input) - onegeom (check button) - if checked, the largest component is output -name of output geometries . Index (0-n) will be attached to the name """ def __init__(self, name='ConnectedComponents', **kw): kw['name'] = name apply( GeometryNode.__init__, (self, 'ConnectedComponents'), kw ) self.geometry = None self.outgeoms = [] ip = self.inputPortsDescr ip.append(name='geometry', datatype='geom', required=True) ip.append(name = 'onegeom', datatype='int', required=False, defaultValue=0) op = self.outputPortsDescr #op.append(name='outgeoms', datatype='geom') wd = self.widgetDescr wd['onegeom'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelCfg':{'text':'Output one component:'} } self.rearrangePorts() code = """def doit(self, geometry, onegeom, name, geoms, instanceMatrices, geomOptions, parent): #print 'ConnectedComponents', geometry, 'onegeom=', onegeom , 'name=', name, 'geoms=', geoms, 'geomOptions=', geomOptions if type(geometry)==types.ListType: if len(geometry): geometry = geometry[0] from DejaVu.IndexedPolygons import IndexedPolygons outgeoms = [] #from time import time #t1 = time() newfaces , newverts = self.findComponents(geometry) #t2 = time() #print 'time to find %d connected components : %.2f'%(len(newfaces), t2-t1) if name == '': name = geometry.name if onegeom == 1: # find the largest set of faces: maxn = 0 maxind = None for i, newfs in enumerate(newfaces): lenf = len(newfs) if lenf > maxn: maxn = lenf maxind = i #print 'len faces of %s is %d'%(name, len(newfaces[maxind])) outgeoms.append(IndexedPolygons(name, vertices = newverts[maxind], faces = newfaces[maxind])) else: for i, newfs in enumerate(newfaces): newname = '%s%d' % (name, i) #print 'len faces of %s is %d'%(newname, len(newfs)) outgeoms.append(IndexedPolygons(newname, vertices = newverts[i], faces = newfs)) self.outgeoms = outgeoms GeometryNode.doit(self, name=name, geoms=geoms, instanceMatrices=instanceMatrices, geomOptions=geomOptions, parent=parent) self.geometry = geometry if self.selectedGeomIndex is not None: g = self.geom() #GeometryNode.textureManagement(self, image=image) self.outputData(ConnectedComponents=g, allGeometries=self.geoms) else: self.outputData(ConnectedComponents=None, allGeometries=self.geoms) """ self.setFunction(code) def appendGeometry(self, name): #print "append geometry, name:", name self.removePreviousGeomsStartingWith(name) # append the geoms if self.outgeoms is not None: self.removePreviousGeomsWithSameName(self.outgeoms) self.geoms.extend(self.outgeoms) return len(self.outgeoms) else: return 0 def findComponents(self, geometry): faces = geometry.getFaces() verts = geometry.getVertices() fdict = {} vdict = {} #dictionary with key - vertex index, #value - list of face indices in which the vertex is found flag1 = True; flag2 = True newfaces = []; newverts = [] while flag2: for i, fs in enumerate(faces): for v in fs: if not vdict.has_key(v): vdict[v] = [i] else: vdict[v].append(i) fdict[i] = fs Vco = faces[0][:] newfaces1 = []; newverts1 = [] vertinds = {} # keys - vertex indices from the input verts list # values - new vertex indices of current surface vcount = 0 # find a surface while flag1: _Vco = [] flag1 = False # find all vertices that share the same triangles with the vertices in Vco. for vert in Vco: vfs = vdict[vert] for i in vfs: if fdict.has_key(i): flag1 = True fs = fdict.pop(i) fsnew = [] # remapped face (with new vertex idices) for v in fs: if v not in Vco: if v not in _Vco: _Vco.append(v) if not vertinds.has_key(v): vertinds[v] = vcount newverts1.append(verts[v]) fsnew.append(vcount) vcount = vcount + 1 else: fsnew.append(vertinds[v]) newfaces1.append(fsnew) # add found triangle to the list of triangles of current surface Vco = _Vco newfaces.append(newfaces1) newverts.append(newverts1) if len(fdict): faces = fdict.values() fdict = {} vdict = {} flag1 = True else: flag2 = False return newfaces, newverts mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/MapPotOnGeom.py0000644000175000017500000010552510405363606025647 0ustar debiandebian######################################################################## # # Vision Macro - Python source code - file generated by vision # Monday 06 March 2006 12:05:47 # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header$ # # $Id$ # from NetworkEditor.macros import MacroNode class MapPotOnGeom(MacroNode): def __init__(self, constrkw={}, name='Map Pot On Geom', **kw): kw['name'] = name apply( MacroNode.__init__, (self,), kw) def beforeAddingToNetwork(self, net): MacroNode.beforeAddingToNetwork(self, net) ## loading libraries ## from Volume.VisionInterface.VolumeNodes import vollib net.editor.addLibraryInstance(vollib,"Volume.VisionInterface.VolumeNodes", "vollib") from Vision.StandardNodes import stdlib net.editor.addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") from DejaVu.VisionInterface.DejaVuNodes import vizlib net.editor.addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") def afterAddingToNetwork(self): from NetworkEditor.macros import MacroNode MacroNode.afterAddingToNetwork(self) ## loading libraries ## from Volume.VisionInterface.VolumeNodes import vollib from Vision.StandardNodes import stdlib from DejaVu.VisionInterface.DejaVuNodes import vizlib ## building macro network ## Map_Pot_On_Geom_0 = self from traceback import print_exc ## loading libraries ## from Volume.VisionInterface.VolumeNodes import vollib self.macroNetwork.getEditor().addLibraryInstance(vollib,"Volume.VisionInterface.VolumeNodes", "vollib") from Vision.StandardNodes import stdlib self.macroNetwork.getEditor().addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") from DejaVu.VisionInterface.DejaVuNodes import vizlib self.macroNetwork.getEditor().addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") try: ## saving node input Ports ## input_Ports_1 = self.macroNetwork.ipNode except: print "WARNING: failed to restore MacroInputNode named input Ports in network self.macroNetwork" print_exc() input_Ports_1=None try: ## saving node output Ports ## output_Ports_2 = self.macroNetwork.opNode output_Ports_2.move(230, 578) except: print "WARNING: failed to restore MacroOutputNode named output Ports in network self.macroNetwork" print_exc() output_Ports_2=None try: ## saving node getSurfaceVFN ## from DejaVu.VisionInterface.DejaVuNodes import getSurfaceVFN getSurfaceVFN_3 = getSurfaceVFN(constrkw = {}, name='getSurfaceVFN', library=vizlib) self.macroNetwork.addNode(getSurfaceVFN_3,55,83) apply(getSurfaceVFN_3.inputPortByName['geometry'].configure, (), {'color': 'red', 'cast': True, 'shape': 'rect'}) apply(getSurfaceVFN_3.outputPortByName['geom'].configure, (), {'color': 'red', 'shape': 'rect'}) apply(getSurfaceVFN_3.outputPortByName['vertices'].configure, (), {'color': 'green', 'shape': 'rect'}) apply(getSurfaceVFN_3.outputPortByName['faces'].configure, (), {'color': 'purple', 'shape': 'rect'}) apply(getSurfaceVFN_3.outputPortByName['normals'].configure, (), {'color': 'blue', 'shape': 'rect'}) except: print "WARNING: failed to restore getSurfaceVFN named getSurfaceVFN in network self.macroNetwork" print_exc() getSurfaceVFN_3=None try: ## saving node mul ## from Vision.StandardNodes import Operator2 mul_4 = Operator2(constrkw = {}, name='mul', library=stdlib) self.macroNetwork.addNode(mul_4,309,139) apply(mul_4.inputPortByName['data1'].configure, (), {'datatype': 'normals3D', 'cast': True, 'shape': 'rect', 'color': 'blue'}) apply(mul_4.inputPortByName['data2'].configure, (), {'datatype': 'float', 'cast': True, 'shape': 'circle', 'color': 'green'}) apply(mul_4.inputPortByName['operation'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(mul_4.inputPortByName['applyToElements'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(mul_4.outputPortByName['result'].configure, (), {'color': 'white', 'shape': 'diamond'}) mul_4.inputPortByName['operation'].widget.set("mul", run=False) mul_4.inputPortByName['applyToElements'].widget.set(1, run=False) apply(mul_4.configure, (), {'expanded': False}) except: print "WARNING: failed to restore Operator2 named mul in network self.macroNetwork" print_exc() mul_4=None try: ## saving node Offset ## from Vision.StandardNodes import DialNE Offset_5 = DialNE(constrkw = {}, name='Offset', library=stdlib) self.macroNetwork.addNode(Offset_5,390,20) apply(Offset_5.inputPortByName['dial'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Offset_5.inputPortByName['mini'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Offset_5.inputPortByName['maxi'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Offset_5.outputPortByName['value'].configure, (), {'color': 'green', 'shape': 'circle'}) Offset_5.inputPortByName['dial'].widget.set(1.01, run=False) except: print "WARNING: failed to restore DialNE named Offset in network self.macroNetwork" print_exc() Offset_5=None try: ## saving node add ## from Vision.StandardNodes import Operator2 add_6 = Operator2(constrkw = {}, name='add', library=stdlib) self.macroNetwork.addNode(add_6,253,183) apply(add_6.inputPortByName['data1'].configure, (), {'datatype': 'coordinates3D', 'cast': True, 'shape': 'rect', 'color': 'green'}) apply(add_6.inputPortByName['data2'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(add_6.inputPortByName['operation'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(add_6.inputPortByName['applyToElements'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(add_6.outputPortByName['result'].configure, (), {'color': 'white', 'shape': 'diamond'}) add_6.inputPortByName['operation'].widget.set("add", run=False) add_6.inputPortByName['applyToElements'].widget.set(1, run=False) apply(add_6.configure, (), {'expanded': False}) except: print "WARNING: failed to restore Operator2 named add in network self.macroNetwork" print_exc() add_6=None try: ## saving node triInterp ## from Volume.VisionInterface.VolumeNodes import TriInterp triInterp_7 = TriInterp(constrkw = {}, name='triInterp', library=vollib) self.macroNetwork.addNode(triInterp_7,189,270) apply(triInterp_7.inputPortByName['grid'].configure, (), {'color': '#995699', 'cast': True, 'shape': 'diamond'}) apply(triInterp_7.inputPortByName['points'].configure, (), {'datatype': 'list', 'cast': True, 'shape': 'oval', 'color': 'cyan'}) apply(triInterp_7.outputPortByName['data'].configure, (), {'color': 'cyan', 'shape': 'oval'}) except: print "WARNING: failed to restore TriInterp named triInterp in network self.macroNetwork" print_exc() triInterp_7=None try: ## saving node Color Map ## from DejaVu.VisionInterface.DejaVuNodes import ColorMapNE Color_Map_9 = ColorMapNE(constrkw = {}, name='Color Map', library=vizlib) self.macroNetwork.addNode(Color_Map_9,213,433) apply(Color_Map_9.inputPortByName['colorMap'].configure, (), {'color': 'magenta', 'cast': True, 'shape': 'rect'}) apply(Color_Map_9.inputPortByName['values'].configure, (), {'color': 'cyan', 'cast': True, 'shape': 'oval'}) apply(Color_Map_9.inputPortByName['mini'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Color_Map_9.inputPortByName['maxi'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Color_Map_9.inputPortByName['filename'].configure, (), {'color': 'white', 'cast': True, 'shape': 'oval'}) apply(Color_Map_9.outputPortByName['mappedColors'].configure, (), {'color': 'orange', 'shape': 'rect'}) apply(Color_Map_9.outputPortByName['colorMap'].configure, (), {'color': 'magenta', 'shape': 'rect'}) apply(Color_Map_9.outputPortByName['legend'].configure, (), {'color': 'red', 'shape': 'rect'}) Color_Map_9.inputPortByName['colorMap'].widget.set({'mini': None, 'maxi': None, 'ramp': [[1.0, 0.0, 0.0, 1.0], [1.0, 0.0060000000000000053, 0.0060000000000000053, 1.0], [1.0, 0.01100000000000001, 0.01100000000000001, 1.0], [1.0, 0.02300000000000002, 0.02300000000000002, 1.0], [1.0, 0.029000000000000026, 0.029000000000000026, 1.0], [1.0, 0.03400000000000003, 0.03400000000000003, 1.0], [1.0, 0.046000000000000041, 0.046000000000000041, 1.0], [1.0, 0.051000000000000045, 0.051000000000000045, 1.0], [1.0, 0.057000000000000051, 0.057000000000000051, 1.0], [1.0, 0.06899999999999995, 0.06899999999999995, 1.0], [1.0, 0.073999999999999955, 0.073999999999999955, 1.0], [1.0, 0.085999999999999965, 0.085999999999999965, 1.0], [1.0, 0.09099999999999997, 0.09099999999999997, 1.0], [1.0, 0.096999999999999975, 0.096999999999999975, 1.0], [1.0, 0.10899999999999999, 0.10899999999999999, 1.0], [1.0, 0.11399999999999999, 0.11399999999999999, 1.0], [1.0, 0.12, 0.12, 1.0], [1.0, 0.13100000000000001, 0.13100000000000001, 1.0], [1.0, 0.13700000000000001, 0.13700000000000001, 1.0], [1.0, 0.14300000000000002, 0.14300000000000002, 1.0], [1.0, 0.15400000000000003, 0.15400000000000003, 1.0], [1.0, 0.16000000000000003, 0.16000000000000003, 1.0], [1.0, 0.17100000000000004, 0.17100000000000004, 1.0], [1.0, 0.17700000000000005, 0.17700000000000005, 1.0], [1.0, 0.18300000000000005, 0.18300000000000005, 1.0], [1.0, 0.19399999999999995, 0.19399999999999995, 1.0], [1.0, 0.19999999999999996, 0.19999999999999996, 1.0], [1.0, 0.20599999999999996, 0.20599999999999996, 1.0], [1.0, 0.21699999999999997, 0.21699999999999997, 1.0], [1.0, 0.22299999999999998, 0.22299999999999998, 1.0], [1.0, 0.23399999999999999, 0.23399999999999999, 1.0], [1.0, 0.23999999999999999, 0.23999999999999999, 1.0], [1.0, 0.246, 0.246, 1.0], [1.0, 0.25700000000000001, 0.25700000000000001, 1.0], [1.0, 0.26300000000000001, 0.26300000000000001, 1.0], [1.0, 0.26900000000000002, 0.26900000000000002, 1.0], [1.0, 0.28000000000000003, 0.28000000000000003, 1.0], [1.0, 0.28600000000000003, 0.28600000000000003, 1.0], [1.0, 0.29100000000000004, 0.29100000000000004, 1.0], [1.0, 0.30300000000000005, 0.30300000000000005, 1.0], [1.0, 0.30900000000000005, 0.30900000000000005, 1.0], [1.0, 0.31999999999999995, 0.31999999999999995, 1.0], [1.0, 0.32599999999999996, 0.32599999999999996, 1.0], [1.0, 0.33099999999999996, 0.33099999999999996, 1.0], [1.0, 0.34299999999999997, 0.34299999999999997, 1.0], [1.0, 0.34899999999999998, 0.34899999999999998, 1.0], [1.0, 0.35399999999999998, 0.35399999999999998, 1.0], [1.0, 0.36599999999999999, 0.36599999999999999, 1.0], [1.0, 0.371, 0.371, 1.0], [1.0, 0.377, 0.377, 1.0], [1.0, 0.38900000000000001, 0.38900000000000001, 1.0], [1.0, 0.39400000000000002, 0.39400000000000002, 1.0], [1.0, 0.40600000000000003, 0.40600000000000003, 1.0], [1.0, 0.41100000000000003, 0.41100000000000003, 1.0], [1.0, 0.41700000000000004, 0.41700000000000004, 1.0], [1.0, 0.42900000000000005, 0.42900000000000005, 1.0], [1.0, 0.43400000000000005, 0.43400000000000005, 1.0], [1.0, 0.43999999999999995, 0.43999999999999995, 1.0], [1.0, 0.45099999999999996, 0.45099999999999996, 1.0], [1.0, 0.45699999999999996, 0.45699999999999996, 1.0], [1.0, 0.46899999999999997, 0.46899999999999997, 1.0], [1.0, 0.47399999999999998, 0.47399999999999998, 1.0], [1.0, 0.47999999999999998, 0.47999999999999998, 1.0], [1.0, 0.49099999999999999, 0.49099999999999999, 1.0], [1.0, 0.497, 0.497, 1.0], [1.0, 0.503, 0.503, 1.0], [1.0, 0.51400000000000001, 0.51400000000000001, 1.0], [1.0, 0.52000000000000002, 0.52000000000000002, 1.0], [1.0, 0.52600000000000002, 0.52600000000000002, 1.0], [1.0, 0.53699999999999992, 0.53699999999999992, 1.0], [1.0, 0.54299999999999993, 0.54299999999999993, 1.0], [1.0, 0.55400000000000005, 0.55400000000000005, 1.0], [1.0, 0.56000000000000005, 0.56000000000000005, 1.0], [1.0, 0.56600000000000006, 0.56600000000000006, 1.0], [1.0, 0.57699999999999996, 0.57699999999999996, 1.0], [1.0, 0.58299999999999996, 0.58299999999999996, 1.0], [1.0, 0.58899999999999997, 0.58899999999999997, 1.0], [1.0, 0.59999999999999998, 0.59999999999999998, 1.0], [1.0, 0.60599999999999998, 0.60599999999999998, 1.0], [1.0, 0.61699999999999999, 0.61699999999999999, 1.0], [1.0, 0.623, 0.623, 1.0], [1.0, 0.629, 0.629, 1.0], [1.0, 0.64000000000000001, 0.64000000000000001, 1.0], [1.0, 0.64600000000000002, 0.64600000000000002, 1.0], [1.0, 0.65100000000000002, 0.65100000000000002, 1.0], [1.0, 0.66300000000000003, 0.66300000000000003, 1.0], [1.0, 0.66900000000000004, 0.66900000000000004, 1.0], [1.0, 0.67399999999999993, 0.67399999999999993, 1.0], [1.0, 0.68599999999999994, 0.68599999999999994, 1.0], [1.0, 0.69100000000000006, 0.69100000000000006, 1.0], [1.0, 0.70300000000000007, 0.70300000000000007, 1.0], [1.0, 0.70900000000000007, 0.70900000000000007, 1.0], [1.0, 0.71399999999999997, 0.71399999999999997, 1.0], [1.0, 0.72599999999999998, 0.72599999999999998, 1.0], [1.0, 0.73099999999999998, 0.73099999999999998, 1.0], [1.0, 0.73699999999999999, 0.73699999999999999, 1.0], [1.0, 0.749, 0.749, 1.0], [1.0, 0.754, 0.754, 1.0], [1.0, 0.76000000000000001, 0.76000000000000001, 1.0], [1.0, 0.77100000000000002, 0.77100000000000002, 1.0], [1.0, 0.77700000000000002, 0.77700000000000002, 1.0], [1.0, 0.78900000000000003, 0.78900000000000003, 1.0], [1.0, 0.79400000000000004, 0.79400000000000004, 1.0], [1.0, 0.80000000000000004, 0.80000000000000004, 1.0], [1.0, 0.81099999999999994, 0.81099999999999994, 1.0], [1.0, 0.81699999999999995, 0.81699999999999995, 1.0], [1.0, 0.82299999999999995, 0.82299999999999995, 1.0], [1.0, 0.83399999999999996, 0.83399999999999996, 1.0], [1.0, 0.83999999999999997, 0.83999999999999997, 1.0], [1.0, 0.85099999999999998, 0.85099999999999998, 1.0], [1.0, 0.85699999999999998, 0.85699999999999998, 1.0], [1.0, 0.86299999999999999, 0.86299999999999999, 1.0], [1.0, 0.874, 0.874, 1.0], [1.0, 0.88, 0.88, 1.0], [1.0, 0.88600000000000001, 0.88600000000000001, 1.0], [1.0, 0.89700000000000002, 0.89700000000000002, 1.0], [1.0, 0.90300000000000002, 0.90300000000000002, 1.0], [1.0, 0.90900000000000003, 0.90900000000000003, 1.0], [1.0, 0.92000000000000004, 0.92000000000000004, 1.0], [1.0, 0.92600000000000005, 0.92600000000000005, 1.0], [1.0, 0.93700000000000006, 0.93700000000000006, 1.0], [1.0, 0.94299999999999995, 0.94299999999999995, 1.0], [1.0, 0.94899999999999995, 0.94899999999999995, 1.0], [1.0, 0.95999999999999996, 0.95999999999999996, 1.0], [1.0, 0.96599999999999997, 0.96599999999999997, 1.0], [1.0, 0.97099999999999997, 0.97099999999999997, 1.0], [1.0, 0.98299999999999998, 0.98299999999999998, 1.0], [1.0, 0.98899999999999999, 0.98899999999999999, 1.0], [1.0, 1.0, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0], [0.98902199999999996, 0.98899999999999999, 1.0, 1.0], [1.0, 1.0, 1.0, 1.0], [0.97105799999999998, 0.97099999999999997, 1.0, 1.0], [0.96606800000000004, 0.96599999999999997, 1.0, 1.0], [0.95409199999999994, 0.95399999999999996, 1.0, 1.0], [0.949102, 0.94899999999999995, 1.0, 1.0], [0.93712600000000013, 0.93700000000000006, 1.0, 1.0], [0.93113800000000013, 0.93100000000000005, 1.0, 1.0], [0.92614800000000008, 0.92600000000000005, 1.0, 1.0], [0.9141720000000001, 0.91400000000000003, 1.0, 1.0], [0.90918200000000005, 0.90900000000000003, 1.0, 1.0], [0.90319400000000005, 0.90300000000000002, 1.0, 1.0], [0.89121800000000007, 0.89100000000000001, 1.0, 1.0], [0.88622800000000013, 0.88600000000000001, 1.0, 1.0], [0.87425200000000003, 0.874, 1.0, 1.0], [0.86926200000000009, 0.86899999999999999, 1.0, 1.0], [0.8632740000000001, 0.86299999999999999, 1.0, 1.0], [0.85129800000000011, 0.85099999999999998, 1.0, 1.0], [0.84630800000000006, 0.84599999999999997, 1.0, 1.0], [0.84032000000000007, 0.83999999999999997, 1.0, 1.0], [0.82934200000000002, 0.82899999999999996, 1.0, 1.0], [0.82335400000000014, 0.82299999999999995, 1.0, 1.0], [0.81137800000000004, 0.81099999999999994, 1.0, 1.0], [0.80638800000000022, 0.80600000000000005, 1.0, 1.0], [0.80040000000000022, 0.80000000000000004, 1.0, 1.0], [0.78942200000000018, 0.78900000000000003, 1.0, 1.0], [0.78343400000000019, 0.78300000000000003, 1.0, 1.0], [0.77744600000000019, 0.77700000000000002, 1.0, 1.0], [0.76646800000000015, 0.76600000000000001, 1.0, 1.0], [0.76048000000000016, 0.76000000000000001, 1.0, 1.0], [0.74950200000000011, 0.749, 1.0, 1.0], [0.74351400000000023, 0.74299999999999999, 1.0, 1.0], [0.73752600000000013, 0.73699999999999999, 1.0, 1.0], [0.72654800000000019, 0.72599999999999998, 1.0, 1.0], [0.72056000000000009, 0.71999999999999997, 1.0, 1.0], [0.71457200000000021, 0.71399999999999997, 1.0, 1.0], [0.70359400000000027, 0.70300000000000007, 1.0, 1.0], [0.69760600000000028, 0.69700000000000006, 1.0, 1.0], [0.68662800000000013, 0.68599999999999994, 1.0, 1.0], [0.68064000000000013, 0.67999999999999994, 1.0, 1.0], [0.67465200000000014, 0.67399999999999993, 1.0, 1.0], [0.66367400000000032, 0.66300000000000003, 1.0, 1.0], [0.65768600000000021, 0.65700000000000003, 1.0, 1.0], [0.64670800000000028, 0.64600000000000002, 1.0, 1.0], [0.64072000000000018, 0.64000000000000001, 1.0, 1.0], [0.6347320000000003, 0.63400000000000001, 1.0, 1.0], [0.62375400000000025, 0.623, 1.0, 1.0], [0.61776600000000026, 0.61699999999999999, 1.0, 1.0], [0.61177800000000027, 0.61099999999999999, 1.0, 1.0], [0.60080000000000022, 0.59999999999999998, 1.0, 1.0], [0.59481200000000023, 0.59399999999999997, 1.0, 1.0], [0.58383400000000019, 0.58299999999999996, 1.0, 1.0], [0.5778460000000003, 0.57699999999999996, 1.0, 1.0], [0.5718580000000002, 0.57099999999999995, 1.0, 1.0], [0.56088000000000027, 0.56000000000000005, 1.0, 1.0], [0.55489200000000038, 0.55400000000000005, 1.0, 1.0], [0.54990200000000022, 0.54899999999999993, 1.0, 1.0], [0.53792600000000024, 0.53699999999999992, 1.0, 1.0], [0.53193800000000035, 0.53100000000000003, 1.0, 1.0], [0.52096000000000031, 0.52000000000000002, 1.0, 1.0], [0.51497200000000032, 0.51400000000000001, 1.0, 1.0], [0.50998200000000038, 0.50900000000000001, 1.0, 1.0], [0.49800600000000028, 0.497, 1.0, 1.0], [0.49201800000000029, 0.49099999999999999, 1.0, 1.0], [0.48702800000000035, 0.48599999999999999, 1.0, 1.0], [0.47505200000000036, 0.47399999999999998, 1.0, 1.0], [0.47006200000000031, 0.46899999999999997, 1.0, 1.0], [0.45808600000000033, 0.45699999999999996, 1.0, 1.0], [0.45209800000000033, 0.45099999999999996, 1.0, 1.0], [0.44710800000000028, 0.44599999999999995, 1.0, 1.0], [0.43513200000000041, 0.43400000000000005, 1.0, 1.0], [0.43014200000000047, 0.42900000000000005, 1.0, 1.0], [0.42415400000000048, 0.42300000000000004, 1.0, 1.0], [0.41217800000000038, 0.41100000000000003, 1.0, 1.0], [0.40718800000000044, 0.40600000000000003, 1.0, 1.0], [0.39521200000000045, 0.39400000000000002, 1.0, 1.0], [0.3902220000000004, 0.38900000000000001, 1.0, 1.0], [0.38423400000000041, 0.38300000000000001, 1.0, 1.0], [0.37225800000000042, 0.371, 1.0, 1.0], [0.36726800000000037, 0.36599999999999999, 1.0, 1.0], [0.36128000000000038, 0.35999999999999999, 1.0, 1.0], [0.35030200000000045, 0.34899999999999998, 1.0, 1.0], [0.34431400000000045, 0.34299999999999997, 1.0, 1.0], [0.33233800000000036, 0.33099999999999996, 1.0, 1.0], [0.32734800000000042, 0.32599999999999996, 1.0, 1.0], [0.32136000000000042, 0.31999999999999995, 1.0, 1.0], [0.31038200000000049, 0.30900000000000005, 1.0, 1.0], [0.3043940000000005, 0.30300000000000005, 1.0, 1.0], [0.29241800000000051, 0.29100000000000004, 1.0, 1.0], [0.28742800000000046, 0.28600000000000003, 1.0, 1.0], [0.28144000000000047, 0.28000000000000003, 1.0, 1.0], [0.27046200000000054, 0.26900000000000002, 1.0, 1.0], [0.26447400000000054, 0.26300000000000001, 1.0, 1.0], [0.25848600000000055, 0.25700000000000001, 1.0, 1.0], [0.24750800000000051, 0.246, 1.0, 1.0], [0.24152000000000051, 0.23999999999999999, 1.0, 1.0], [0.23054200000000047, 0.22899999999999998, 1.0, 1.0], [0.22455400000000048, 0.22299999999999998, 1.0, 1.0], [0.21856600000000048, 0.21699999999999997, 1.0, 1.0], [0.20758800000000044, 0.20599999999999996, 1.0, 1.0], [0.20160000000000045, 0.19999999999999996, 1.0, 1.0], [0.19561200000000045, 0.19399999999999995, 1.0, 1.0], [0.18463400000000063, 0.18300000000000005, 1.0, 1.0], [0.17864600000000064, 0.17700000000000005, 1.0, 1.0], [0.16766800000000059, 0.16600000000000004, 1.0, 1.0], [0.1616800000000006, 0.16000000000000003, 1.0, 1.0], [0.15569200000000061, 0.15400000000000003, 1.0, 1.0], [0.14471400000000056, 0.14300000000000002, 1.0, 1.0], [0.13872600000000057, 0.13700000000000001, 1.0, 1.0], [0.13273800000000058, 0.13100000000000001, 1.0, 1.0], [0.12176000000000053, 0.12, 1.0, 1.0], [0.11577200000000054, 0.11399999999999999, 1.0, 1.0], [0.10479400000000061, 0.10299999999999998, 1.0, 1.0], [0.098806000000000616, 0.096999999999999975, 1.0, 1.0], [0.092818000000000622, 0.09099999999999997, 1.0, 1.0], [0.081840000000000579, 0.07999999999999996, 1.0, 1.0], [0.075852000000000586, 0.073999999999999955, 1.0, 1.0], [0.070862000000000536, 0.06899999999999995, 1.0, 1.0], [0.05888600000000066, 0.057000000000000051, 1.0, 1.0], [0.052898000000000667, 0.051000000000000045, 1.0, 1.0], [0.041920000000000623, 0.040000000000000036, 1.0, 1.0], [0.03593200000000063, 0.03400000000000003, 1.0, 1.0], [0.030942000000000691, 0.029000000000000026, 1.0, 1.0], [0.018966000000000705, 0.017000000000000015, 1.0, 1.0], [0.012978000000000711, 0.01100000000000001, 1.0, 1.0], [0.0020000000000006679, 0.0, 1.0, 1.0]], 'name': 'cmap'}, run=False) except: print "WARNING: failed to restore ColorMap named Color Map in network self.macroNetwork" print_exc() Color_Map_9=None try: ## saving node call method ## from Vision.StandardNodes import CallMethod call_method_10 = CallMethod(constrkw = {}, name='call method', library=stdlib) self.macroNetwork.addNode(call_method_10,179,501) apply(call_method_10.inputPortByName['objects'].configure, (), {'datatype': 'geom', 'cast': True, 'shape': 'rect', 'color': 'red'}) apply(call_method_10.inputPortByName['signature'].configure, (), {'color': 'white', 'cast': True, 'shape': 'oval'}) apply(call_method_10.addInputPort, (), {'name': 'materials', 'cast': True, 'datatype': 'colorfloat3or4(0)', 'required': False, 'height': 8, 'width': 12, 'shape': 'rect', 'color': 'orange'}) apply(call_method_10.addInputPort, (), {'name': 'inheritMaterial', 'cast': True, 'datatype': 'int', 'required': False, 'height': 12, 'width': 12, 'shape': 'circle', 'color': 'yellow'}) apply(call_method_10.outputPortByName['objects'].configure, (), {'color': 'white', 'shape': 'diamond'}) apply(call_method_10.outputPortByName['results'].configure, (), {'color': 'white', 'shape': 'diamond'}) call_method_10.inputPortByName['signature'].widget.set("Set materials inheritMaterial", run=False) except: print "WARNING: failed to restore CallMethod named call method in network self.macroNetwork" print_exc() call_method_10=None try: ## saving node Checkbutton ## from Vision.StandardNodes import CheckButtonNE Checkbutton_11 = CheckButtonNE(constrkw = {}, name='Checkbutton', library=stdlib) self.macroNetwork.addNode(Checkbutton_11,346,478) apply(Checkbutton_11.inputPortByName['button'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(Checkbutton_11.outputPortByName['value'].configure, (), {'color': 'yellow', 'shape': 'circle'}) except: print "WARNING: failed to restore CheckButtonNE named Checkbutton in network self.macroNetwork" print_exc() Checkbutton_11=None try: ## saving node Redraw ## from DejaVu.VisionInterface.DejaVuNodes import Redraw Redraw_12 = Redraw(constrkw = {}, name='Redraw', library=vizlib) self.macroNetwork.addNode(Redraw_12,41,518) apply(Redraw_12.inputPortByName['viewer'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'rect'}) apply(Redraw_12.inputPortByName['trigger'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) except: print "WARNING: failed to restore Redraw named Redraw in network self.macroNetwork" print_exc() Redraw_12=None try: ## saving node neg ## from Vision.StandardNodes import Operator1 neg_13 = Operator1(constrkw = {}, name='neg', library=stdlib) self.macroNetwork.addNode(neg_13,288,321) apply(neg_13.inputPortByName['data'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(neg_13.inputPortByName['operation'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(neg_13.inputPortByName['applyToElements'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(neg_13.outputPortByName['result'].configure, (), {'color': 'white', 'shape': 'diamond'}) neg_13.inputPortByName['operation'].widget.set("neg", run=False) apply(neg_13.configure, (), {'expanded': False}) except: print "WARNING: failed to restore Operator1 named neg in network self.macroNetwork" print_exc() neg_13=None try: ## saving node Get viewer ## from Vision.StandardNodes import GetAttr Get_viewer_14 = GetAttr(constrkw = {}, name='Get viewer', library=stdlib) self.macroNetwork.addNode(Get_viewer_14,18,324) apply(Get_viewer_14.inputPortByName['objects'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(Get_viewer_14.inputPortByName['attr'].configure, (), {'color': 'white', 'cast': True, 'shape': 'oval'}) apply(Get_viewer_14.outputPortByName['attrs'].configure, (), {'color': 'cyan', 'shape': 'oval'}) apply(Get_viewer_14.inputPortByName['attr'].widget.configure, (), {'choices': ('viewer',)}) Get_viewer_14.inputPortByName['attr'].widget.set("viewer", run=False) except: print "WARNING: failed to restore GetAttr named Get viewer in network self.macroNetwork" print_exc() Get_viewer_14=None try: ## saving node Slice Data ## from Vision.StandardNodes import SliceData Slice_Data_15 = SliceData(constrkw = {}, name='Slice Data', library=stdlib) self.macroNetwork.addNode(Slice_Data_15,29,421) apply(Slice_Data_15.inputPortByName['data'].configure, (), {'datatype': 'list', 'cast': True, 'shape': 'oval', 'color': 'cyan'}) apply(Slice_Data_15.inputPortByName['_slice'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(Slice_Data_15.outputPortByName['data'].configure, (), {'color': 'white', 'shape': 'diamond'}) Slice_Data_15.inputPortByName['_slice'].widget.set("[0]", run=False) except: print "WARNING: failed to restore SliceData named Slice Data in network self.macroNetwork" print_exc() Slice_Data_15=None try: ## saving node stddev ## from Vision.StandardNodes import StdDev stddev_16 = StdDev(constrkw = {}, name='stddev', library=stdlib) self.macroNetwork.addNode(stddev_16,339,230) apply(stddev_16.inputPortByName['values'].configure, (), {'color': 'cyan', 'cast': True, 'shape': 'oval'}) apply(stddev_16.outputPortByName['stddev'].configure, (), {'color': 'green', 'shape': 'circle'}) except: print "WARNING: failed to restore StdDev named stddev in network self.macroNetwork" print_exc() stddev_16=None try: ## saving node Dial ## from Vision.StandardNodes import DialNE Dial_17 = DialNE(constrkw = {}, name='Dial', library=stdlib) self.macroNetwork.addNode(Dial_17,412,152) apply(Dial_17.inputPortByName['dial'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Dial_17.inputPortByName['mini'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Dial_17.inputPortByName['maxi'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Dial_17.outputPortByName['value'].configure, (), {'color': 'green', 'shape': 'circle'}) Dial_17.inputPortByName['dial'].widget.set(5.0, run=False) except: print "WARNING: failed to restore DialNE named Dial in network self.macroNetwork" print_exc() Dial_17=None try: ## saving node mul ## from Vision.StandardNodes import Operator2 mul_18 = Operator2(constrkw = {}, name='mul', library=stdlib) self.macroNetwork.addNode(mul_18,369,347) apply(mul_18.inputPortByName['data1'].configure, (), {'datatype': 'float', 'cast': True, 'shape': 'circle', 'color': 'green'}) apply(mul_18.inputPortByName['data2'].configure, (), {'datatype': 'float', 'cast': True, 'shape': 'circle', 'color': 'green'}) apply(mul_18.inputPortByName['operation'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(mul_18.inputPortByName['applyToElements'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(mul_18.outputPortByName['result'].configure, (), {'color': 'white', 'shape': 'diamond'}) mul_18.inputPortByName['operation'].widget.set("mul", run=False) apply(mul_18.configure, (), {'expanded': False}) except: print "WARNING: failed to restore Operator2 named mul in network self.macroNetwork" print_exc() mul_18=None self.macroNetwork.freeze() ## saving connections for network Map Pot On Geom ## if Offset_5 is not None and mul_4 is not None: self.macroNetwork.connectNodes( Offset_5, mul_4, "value", "data2", blocking=True) if getSurfaceVFN_3 is not None and mul_4 is not None: self.macroNetwork.connectNodes( getSurfaceVFN_3, mul_4, "normals", "data1", blocking=True) if mul_4 is not None and add_6 is not None: self.macroNetwork.connectNodes( mul_4, add_6, "result", "data2", blocking=True) if getSurfaceVFN_3 is not None and add_6 is not None: self.macroNetwork.connectNodes( getSurfaceVFN_3, add_6, "vertices", "data1", blocking=True) if add_6 is not None and triInterp_7 is not None: self.macroNetwork.connectNodes( add_6, triInterp_7, "result", "points", blocking=True) if getSurfaceVFN_3 is not None and call_method_10 is not None: self.macroNetwork.connectNodes( getSurfaceVFN_3, call_method_10, "geom", "objects", blocking=True) if Checkbutton_11 is not None and call_method_10 is not None: self.macroNetwork.connectNodes( Checkbutton_11, call_method_10, "value", "inheritMaterial", blocking=True) if call_method_10 is not None and Redraw_12 is not None: self.macroNetwork.connectNodes( call_method_10, Redraw_12, "objects", "trigger", blocking=True) input_Ports_1 = self.macroNetwork.ipNode if input_Ports_1 is not None and getSurfaceVFN_3 is not None: self.macroNetwork.connectNodes( input_Ports_1, getSurfaceVFN_3, "new", "geometry", blocking=True) if getSurfaceVFN_3 is not None and Get_viewer_14 is not None: self.macroNetwork.connectNodes( getSurfaceVFN_3, Get_viewer_14, "geom", "objects", blocking=True) if Get_viewer_14 is not None and Slice_Data_15 is not None: self.macroNetwork.connectNodes( Get_viewer_14, Slice_Data_15, "attrs", "data", blocking=True) if Slice_Data_15 is not None and Redraw_12 is not None: self.macroNetwork.connectNodes( Slice_Data_15, Redraw_12, "data", "viewer", blocking=True) if input_Ports_1 is not None and triInterp_7 is not None: self.macroNetwork.connectNodes( input_Ports_1, triInterp_7, "new", "grid", blocking=True) if triInterp_7 is not None and stddev_16 is not None: self.macroNetwork.connectNodes( triInterp_7, stddev_16, "data", "values", blocking=True) if neg_13 is not None and Color_Map_9 is not None: self.macroNetwork.connectNodes( neg_13, Color_Map_9, "result", "mini", blocking=True) if mul_18 is not None and neg_13 is not None: self.macroNetwork.connectNodes( mul_18, neg_13, "result", "data", blocking=True) if mul_18 is not None and Color_Map_9 is not None: self.macroNetwork.connectNodes( mul_18, Color_Map_9, "result", "maxi", blocking=True) if Dial_17 is not None and mul_18 is not None: self.macroNetwork.connectNodes( Dial_17, mul_18, "value", "data2", blocking=True) if stddev_16 is not None and mul_18 is not None: self.macroNetwork.connectNodes( stddev_16, mul_18, "stddev", "data1", blocking=True) if triInterp_7 is not None and Color_Map_9 is not None: self.macroNetwork.connectNodes( triInterp_7, Color_Map_9, "data", "values", blocking=True) if Color_Map_9 is not None and call_method_10 is not None: self.macroNetwork.connectNodes( Color_Map_9, call_method_10, "mappedColors", "materials", blocking=True) output_Ports_2 = self.macroNetwork.opNode if Color_Map_9 is not None and output_Ports_2 is not None: self.macroNetwork.connectNodes( Color_Map_9, output_Ports_2, "legend", "new", blocking=True) self.macroNetwork.unfreeze() Map_Pot_On_Geom_0.shrink() ## reset modifications ## Map_Pot_On_Geom_0.resetTags() Map_Pot_On_Geom_0.buildOriginalList() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/DejaVuWidgets.py0000644000175000017500000004756710715124367026065 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: 2003 Authors: Daniel Stoffler, Michel Sanner # # stoffler@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/VisionInterface/DejaVuWidgets.py,v 1.43 2007/11/09 18:37:43 vareille Exp $ # # $Id: DejaVuWidgets.py,v 1.43 2007/11/09 18:37:43 vareille Exp $ # import numpy.oldnumeric as Numeric import Tkinter, Pmw from NetworkEditor.widgets import TkPortWidget, PortWidget from DejaVu.colorMap import ColorMap from DejaVu.ColormapGui import ColorMapGUI from DejaVu.colorTool import RGBRamp from DejaVu.ColorWheel import ColorWheel from mglutil.gui.BasicWidgets.Tk.colorWidgets import ColorEditor from mglutil.util.callback import CallBackFunction class NEDejaVuGeomOptions(PortWidget): """widget allowing to configure a DejaVuGeometry Handle all things that can be set to a finite list of values in a Geometry """ configOpts = PortWidget.configOpts.copy() ownConfigOpts = {} ownConfigOpts['initialValue'] = { 'defaultValue':{}, 'type':'dict', } configOpts.update(ownConfigOpts) def __init__(self, port, **kw): # call base class constructor apply( PortWidget.__init__, (self, port), kw) self.booleanProps = [ 'disableTexture', 'faceNormals', 'inheritBackPolyMode', 'inheritCulling', 'inheritFrontPolyMode', 'inheritLighting' 'inheritStippleLines', 'inheritLineWidth', 'inheritMaterial', 'inheritPointWidth', 'inheritStipplePolygons', 'inheritShading', 'inheritSharpColorBoundaries', 'inheritXform', 'invertNormals', 'lighting', 'protected', 'scissor', 'sharpColorBoundaries', 'vertexNormals', 'visible', ] from DejaVu import viewerConst self.choiceProps = { 'frontPolyMode':viewerConst.Front_POLYGON_MODES_keys, 'backPolyMode':viewerConst.Back_POLYGON_MODES_keys, 'shading':viewerConst.SHADINGS.keys(), 'culling':viewerConst.CULLINGS.keys(), } self.frame = Tkinter.Frame(self.widgetFrame, borderwidth=3, relief = 'ridge') self.propWidgets = {} # will hold handle to widgets created self.optionsDict = {} # widget's value import Pmw items = self.booleanProps + self.choiceProps.keys() w = Pmw.Group(self.frame, tag_text='Add a Property Widget') self.chooser = Pmw.ComboBox( w.interior(), label_text='', labelpos='w', entryfield_entry_width=20, scrolledlist_items=items, selectioncommand=self.addProp) self.chooser.pack(padx=2, pady=2, expand='yes', fill='both') w.pack(fill = 'x', expand = 1, side='top') w = Pmw.Group(self.frame, tag_text='Property Widgets') self.propWidgetMaster = w.interior() w.pack(fill='both', expand = 1, side='bottom') # configure without rebuilding to avoid enless loop apply( self.configure, (False,), kw) self.frame.pack(expand='yes', fill='both') if self.initialValue is not None: self.set(self.initialValue, run=0) self._setModified(False) # will be set to True by configure method def addProp(self, prop): if self.propWidgets.has_key(prop): return l = Tkinter.Label(self.propWidgetMaster, text=prop) l.grid(padx=2, pady=2, row=len(self.propWidgets)+1, column=0, sticky='e') if prop in self.booleanProps: var = Tkinter.IntVar() var.set(0) cb = CallBackFunction( self.setBoolean, (prop, var)) widget = Tkinter.Checkbutton(self.propWidgetMaster, variable=var, command=cb) self.propWidgets[prop] = (widget, var) self.setBoolean( (prop, var) ) else: items = self.choiceProps[prop] var = None cb = CallBackFunction( self.setChoice, (prop,)) widget = Pmw.ComboBox( self.propWidgetMaster, entryfield_entry_width=15, scrolledlist_items=items, selectioncommand=cb) self.propWidgets[prop] = (widget, var) self.setChoice( (prop,), items[0] ) widget.grid(row=len(self.propWidgets), column=1, sticky='w') def setBoolean(self, args): prop, var = args self.optionsDict[prop] = var.get() if self.port.node.paramPanel.immediateTk.get(): self.scheduleNode() def setChoice(self, prop, value): self.optionsDict[prop[0]] = value self.propWidgets[prop[0]][0].selectitem(value) if self.port.node.paramPanel.immediateTk.get(): self.scheduleNode() def set(self, valueDict, run=1): self._setModified(True) for k,v in valueDict.items(): self.addProp(k) if k in self.booleanProps: self.propWidgets[k][1].set(v) self.setBoolean( (k, self.propWidgets[k][1]) ) else: self.setChoice((k,), v) self._newdata = True if run: self.scheduleNode() def get(self): return self.optionsDict def configure(self, rebuild=True, **kw): action, rebuildDescr = apply( PortWidget.configure, (self, 0), kw) # this methods just creates a resize action if width changes if self.widget is not None: if 'width' in kw: action = 'resize' if action=='rebuild' and rebuild: action, rebuildDescr = self.rebuild(rebuildDescr) if action=='resize' and rebuild: self.port.node.autoResize() return action, rebuildDescr class NEColorMap(PortWidget): # description of parameters that can only be used with the widget's # constructor configOpts = PortWidget.configOpts.copy() ownConfigOpts = { 'mini':{'type':'float', 'defaultValue':None}, 'maxi':{'type':'float', 'defaultValue':None}, #'ramp':{'defaultValue':None}, 'filename':{'type':'string', 'defaultValue':''}, 'viewer':{'defaultValue':None}, } configOpts.update( ownConfigOpts ) def configure(self, rebuild=True, **kw): action, rebuildDescr = apply( PortWidget.configure, (self, 0), kw) # handle ownConfigOpts entries if self.widget is not None: widgetOpts = {} # handle viewer first so that legend exists if min or max is set viewer = kw.get('viewer', None) if viewer: if self.widget.viewer != viewer: self.widget.SetViewer(viewer) for k, v in kw.items(): if k=='viewer': continue elif k=='mini' or k=='maxi': apply( self.widget.update, (), {k:v} ) elif k=='filename': self.widget.read(v) def __init__(self, port, **kw): # create all attributes that will not be created by configure because # they do not appear on kw for key in self.ownConfigOpts.keys(): v = kw.get(key, None) if v is None: # self.configure will not do anyting for this key setattr(self, key, self.ownConfigOpts[key]['defaultValue']) # get all arguments handled this widget and not by PortWidget widgetcfg = {} for k in self.ownConfigOpts.keys(): if k in kw: widgetcfg[k] = kw.pop(k) # we build 2 widgets here, let's do the first: cmkw = {} # dict for ColorMap keywords ramp = widgetcfg.pop('ramp', None) #if ramp is None: #ramp = RGBRamp(size=16) #cmkw['ramp'] = ramp cmkw['mini'] = widgetcfg.pop('mini', None) cmkw['maxi'] = widgetcfg.pop('maxi', None) # create an instance of the ColorMap which is required to instanciate # the ColorMapGUI (i.e. the widget) cM = apply( ColorMap, ('cmap',), cmkw) # call base class constructor apply( PortWidget.__init__, ( self, port), kw) # create the widget widgetcfg['master'] = self.widgetFrame widgetcfg['modifyMinMax'] = True #try: #tries to assign viewer when called from Pmv # widgetcfg['viewer'] = self.vEditor.vf.GUI.VIEWER #except: # pass self.widget = apply( ColorMapGUI, (cM,), widgetcfg) # we call cmCallback because cm passed the color map as an argument # and node.schedule takes no argument self.widget.addCallback(self.cmCallback) # configure without rebuilding to avoid enless loop #apply( self.configure, (False,), widgetcfg) if self.initialValue: self.set(self.initialValue, run=0) self.modified = False # will be set to True by configure method # and destroy the Apply and Dismiss buttons of the ColorMapGUI self.widget.dismiss.forget() self.widget.apply.forget() self.widget.frame2.forget() # overwrite the paramPanel Appply button method to call # the ColorMapGUI apply_cb() method if hasattr(self.port.node, 'paramPanel'): self.port.node.paramPanel.applyFun = self.apply_cb ## def __init__(self, port=None, master=None, visibleInNodeByDefault=0, ## visibleInNode=0, value=None, callback=None, **kw): ## PortWidget.__init__(self, port, master, visibleInNodeByDefault, ## visibleInNode, callback) ## cmkw = {} # dict for ColorMap keywords ## cmkw['ramp'] = RGBRamp() #default ramp, can be overwritten below ## for k in kw.keys(): ## if k in ['ramp', 'geoms', 'filename', 'mini', 'maxi']: ## cmkw[k] = kw[k] ## del kw[k] ## # create an instance of the ColorMap which is required to instanciate ## # the ColorMapGUI ## cM = apply( ColorMap, ('cmap',), cmkw) ## # instanciate the ColorMapGUI ## kw['master'] = self.top ## self.cm = apply( ColorMapGUI, (cM,), kw) ## # and destroy the Apply and Dismiss buttons of the ColorMapGUI ## self.cm.dismiss.forget() ## self.cm.apply.forget() ## self.cm.frame2.forget() ## # add callback. Note, we do not call scheduleNode because this would ## # lead to recursion problem ## #self.cm.addCallback(self.port.node.schedule) ## # we call cmCallback because cm passed the color map as an argument ## # and node.schedule takes no argument ## self.cm.addCallback(self.cmCallback) ## if value is not None: ## self.set(value, run=0) ## # overwrite the paramPanel Appply button method to call ## # the ColorMapGUI apply_cb() method ## if hasattr(self.port.node, 'paramPanel'): ## self.port.node.paramPanel.applyFun = self.apply_cb def onUnbind(self): legend = self.widget.legend if legend is not None: viewer = legend.viewer if viewer is not None: legend.protected = False viewer.RemoveObject(legend) legend = None def onDelete(self): self.onUnbind() def cmCallback(self, cmap): self.port.node.schedule() def apply_cb(self, event=None): if self.widget is not None: self._setModified(True) # overwrite the paramPanel Appply button method to call # the ColorMapGUI apply_cb() method self.widget.apply_cb(event) self._newdata = 1 self.port.node.schedule() def set(self, value, run=1): #import pdb;pdb.set_trace() self._setModified(True) if isinstance(value, dict): apply(ColorMapGUI.configure,(self.widget,),value) else: self.widget.set(value) self._newdata = 1 if run: self.port.node.schedule() def get(self): return self.widget def getDataForSaving(self): # this method is called when a network is saved and the widget # value needs to be saved cfg = PortWidget.getDescr(self) cfg['name'] = self.widget.name cfg['ramp'] = self.widget.ramp cfg['mini'] = self.widget.mini cfg['maxi'] = self.widget.maxi return cfg def getDescr(self): cfg = PortWidget.getDescr(self) # the whole colormap is the widget value and # is returned by self.get() ! #cfg['name'] = self.widget.name #cfg['ramp'] = self.widget.ramp #cfg['mini'] = self.widget.mini #cfg['maxi'] = self.widget.maxi return cfg class NEColorWheel(PortWidget): # description of parameters that can only be used with the widget's # constructor configOpts = PortWidget.configOpts.copy() ownConfigOpts = { 'width':{'min':20, 'max':500, 'defaultValue':75, 'type':'int'}, 'height':{'min':20, 'max':500, 'defaultValue':75, 'type':'int'}, 'circles':{'min':2, 'max':20, 'defaultValue':5, 'type':'int'}, 'stripes':{'min':2, 'max':40, 'defaultValue':20, 'type':'int'}, } configOpts.update( ownConfigOpts ) def __init__(self, port, **kw): # create all attributes that will not be created by configure because # they do not appear on kw for key in self.ownConfigOpts.keys(): v = kw.get(key, None) if v is None: # self.configure will not do anyting for this key setattr(self, key, self.ownConfigOpts[key]['defaultValue']) # get all arguments handled by this widget and not by PortWidget widgetcfg = {} for k in self.ownConfigOpts.keys(): if k in kw: widgetcfg[k] = kw.pop(k) # call base class constructor apply( PortWidget.__init__, ( self, port), kw) # create the widget self.widget = apply( ColorWheel, (self.widgetFrame,), widgetcfg) self.widget.AddCallback(self.cwCallback) # configure without rebuilding to avoid enless loop #apply( self.configure, (False,), widgetcfg) if self.initialValue: self.set(self.initialValue, run=0) self.modified = False # will be set to True by configure method ## def __init__(self, port=None, master=None, visibleInNodeByDefault=0, ## visibleInNode=0, value=None, callback=None, **kw): ## PortWidget.__init__(self, port, master, visibleInNodeByDefault, ## visibleInNode, callback) ## self.cw = apply( ColorWheel, (self.top,), kw) ## if value is not None: ## self.set(value, run=0) ## self.cw.AddCallback(self.scheduleNode) def cwCallback(self, color): self._newdata = 1 self.scheduleNode() def set(self, value, run=1): self.widget.Set(value, mode='RGB') self._newdata = 1 if run: self.scheduleNode() #self.port.node.schedule() def get(self, mode='RGB'): value = self.widget.Get(mode) value = list( Numeric.array(value) ) return value def getDescr(self): cfg = PortWidget.getDescr(self) cfg['width'] = self.widget.width cfg['height'] = self.widget.height cfg['circles'] = self.widget.circles cfg['stripes'] = self.widget.stripes cfg['wheelPad'] = self.widget.wheelPad cfg['immediate'] = self.widget.immediate cfg['wysiwyg'] = self.widget.wysiwyg return cfg ## def configure(self, **kw): ## if len(kw)==0: ## cfg = PortWidget.configure(self) ## cfg['immediate'] = self.cw.immediate ## cfg['wysiwyg'] = self.cw.wysiwyg ## return cfg ## else: ## if kw.has_key('immediate'): ## self.cw.setImmediate(kw['immediate']) ## elif kw.has_key('wysiwyg'): ## self.cw.setWysiwyg(kw['wysiwyg']) class NEColorEditor(PortWidget): # description of parameters that can only be used with the widget's # constructor configOpts = PortWidget.configOpts.copy() ownConfigOpts = { 'mode':{'defaultValue':'RGB', 'type':'string', 'validValues':['RGB', 'HSV', 'HEX']}, 'immediate':{'defaultValue':True, 'type':'boolean'}, } configOpts.update( ownConfigOpts ) def __init__(self, port, **kw): # create all attributes that will not be created by configure because # they do not appear on kw for key in self.ownConfigOpts.keys(): v = kw.get(key, None) if v is None: # self.configure will not do anyting for this key setattr(self, key, self.ownConfigOpts[key]['defaultValue']) # get all arguments handled by this widget and not by PortWidget widgetcfg = {} for k in self.ownConfigOpts.keys(): if k in kw: widgetcfg[k] = kw.pop(k) # call base class constructor apply( PortWidget.__init__, ( self, port), kw) # create the widget self.widget = apply( ColorEditor, (self.widgetFrame,), widgetcfg) self.widget.cbManager.AddCallback(self.cwCallback) self.widget.pack() # configure without rebuilding to avoid enless loop #apply( self.configure, (False,), widgetcfg) if self.initialValue: self.set(self.initialValue, run=0) self.modified = False # will be set to True by configure method ## def __init__(self, port=None, master=None, visibleInNodeByDefault=0, ## visibleInNode=0, value=None, callback=None, **kw): ## PortWidget.__init__(self, port, master, visibleInNodeByDefault, ## visibleInNode, callback) ## self.cw = apply( ColorWheel, (self.top,), kw) ## if value is not None: ## self.set(value, run=0) ## self.cw.AddCallback(self.scheduleNode) def cwCallback(self, color): self._newdata = 1 self.scheduleNode() def set(self, value, run=1): if value is not None: self._setModified(True) self.widget.set(value, mode='RGB') self._newdata = 1 if run: self.port.node.schedule() def get(self, mode='RGB'): value = self.widget.get(mode='RGB') value = list( Numeric.array(value) ) return value def getDescr(self): cfg = PortWidget.getDescr(self) cfg['mode'] = self.widget.mode cfg['immediate'] = self.widget.immediate return cfg mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/DejaVuNodes.py0000644000175000017500000035706111354250007025507 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: July 2002 Authors: Daniel Stoffler, Michel Sanner # # stoffler@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/VisionInterface/DejaVuNodes.py,v 1.301 2010/03/30 01:12:39 sanner Exp $ # # $Id: DejaVuNodes.py,v 1.301 2010/03/30 01:12:39 sanner Exp $ # import types import warnings import string import numpy.oldnumeric as Numeric, sys, os from math import sqrt, atan, pi from NetworkEditor.items import NetworkNode from NetworkEditor.macros import MacroNode from NetworkEditor.macros import MacroOutputNode from Vision import UserLibBuild from DejaVu.VisionInterface.DejaVuWidgets import NEColorMap, NEColorWheel, NEColorEditor, NEDejaVuGeomOptions from DejaVu.Geom import Geom from DejaVu.Insert2d import Insert2d from DejaVu.colorMap import ColorMap def importSymLib(net): try: from symserv.VisionInterface.SymservNodes import symlib net.editor.addLibraryInstance( symlib, 'symserv.VisionInterface.SymservNodes', 'symlib') except: warnings.warn( 'Warning! Could not import symlib from symserv.VisionInterface.SymservNodes.py', stacklevel=2) def importImageLib(net): try: from Vision.PILNodes import imagelib net.editor.addLibraryInstance(imagelib, 'Vision.PILNodes', 'imagelib') except: warnings.warn( 'Warning! Could not import imagelib from Vision.PILNodes.py', stacklevel=2) def importVolLib(net): try: from Volume.VisionInterface.VolumeNodes import vollib net.editor.addLibraryInstance( vollib, 'Volume.VisionInterface.VolumeNodes', 'vollib') except: warnings.warn( 'Warning! Could not import vollib from Volume.VisionInterface.VolumeNodes.py') class GeomOptions(NetworkNode): def __init__(self, name='Set Geom Options', viewer=None, **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(name='geomOptions', datatype='dict') self.widgetDescr['geomOptions'] = { 'class':'NEDejaVuGeomOptions', 'lockedOnPort':True } op = self.outputPortsDescr op.append(datatype='dict', name='geomOptions') code = """def doit(self, geomOptions): self.outputData(geomOptions=geomOptions) """ self.setFunction(code) class RestoreState(NetworkNode): """Set a Viewer's state from a file Input Ports: Viewer: (required) the Viewer for which to restore the state filename: (required) the file containing the state mode: (optional) can be 'Viewer', 'objects' or 'both' defaults to 'both'. When this value is 'viewer', the state is restored only for objects always present in the viewer (i.e. root, lights, clipping planes, fog, etc). 'objects': means restoring the state of geometries in the viewer. 'both': does both. Output Ports: """ from DejaVu.Geom import Geom def __init__(self, name='RestoreState', viewer=None, **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(name='viewer', datatype='viewer') ip.append(name='filename', datatype='string') ip.append(name='mode', datatype='string', required=False, defaultValue='both') self.widgetDescr['filename'] = { 'class':'NEEntryWithFileBrowser', 'master':'node', 'width':10, 'initialValue':'', 'filetypes':[('state files','*_state.py'),('all','*')], 'labelCfg':{'text':'Filename: '} } self.widgetDescr['mode'] = { 'class':'NEComboBox', 'master':'node', 'choices':['viewer', 'objects', 'both'], 'initialValue': 'both', 'entryfield_entry_width':8, 'labelCfg':{'text':'mode:'}, } code = """def doit(self, viewer, filename, mode): execfile(filename, {'vi':viewer, 'mode':mode}) viewer.Redraw() """ self.setFunction(code) class CenterOnPickedVertex(NetworkNode): """Set the rotation center of for the scene to the picked vertex Input Ports: Viewer: (required) the Viewer for which to restore the state Output Ports: """ from DejaVu.Geom import Geom def __init__(self, name='CenterOnPick', viewer=None, **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(name='viewer', datatype='viewer') code = """def doit(self, viewer): if viewer.lastPick is None: return hits = viewer.lastPick.hits if len(hits)==1: g = hits.keys()[0] index = hits[g][0][0] point = g.vertexSet.vertices.array[index] viewer.rootObject.SetPivot(point)""" self.setFunction(code) class CenterOnVertex(NetworkNode): """Set the rotation center of for the scene to a vertex Input Ports: Viewer: (required) the Viewer for which to restore the state vertex: Output Ports: """ from DejaVu.Geom import Geom def __init__(self, name='CenterOnPick', viewer=None, **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(name='viewer', datatype='viewer') ip.append(name='point', datatype='coord3') code = """def doit(self, viewer, point): viewer.rootObject.SetPivot(point)""" self.setFunction(code) class Viewer(NetworkNode): """Create an instance of a DejaVu Viewer object. This object provides a full fledged 3D geometry viewer with support for the OpenGL material and lighting model with multiple light source, arbitrary clipping planes, a hierarchy of geometries with property inheritance, a material editor, etc... . Input Ports: Geometries: (required) Accepts any object that is a DejaVu.Geom instance or a list thereof from each parent port and adds the geometry objects to the viewer Output Ports: lastPick: outputs a DejaVu.Camera.PickObject DejaVu: outputs the DejaVu Viewer instance Redraw: fires at each redraw event """ from DejaVu.Geom import Geom def __init__(self, name='Viewer', viewer=None, **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 self.vi = viewer # code for input port callback "beforeDisconnect" # this will delete geometries added to the viewer codeBeforeDisconnect = """def beforeDisconnect(self, c): #print "Viewer Node beforeDisconnect" self.node.deleteGeometries(c) """ # add an entry so the show parma. panel will be enabled ip = self.inputPortsDescr ip.append(name='geometries', datatype='geom(0)', required=False, singleConnection=False, beforeDisconnect=codeBeforeDisconnect) op = self.outputPortsDescr op.append(datatype='None', name='lastPick') op.append(datatype='viewer', name='dejaVuViewer') op.append(datatype='None', name='redraw') code = """def doit(self, geometries): self.addGeometriesToViewer(geometries) self.outputData(lastPick=self.vi.lastPick) self.outputData(dejaVuViewer=self.vi) self.outputData(redraw=0) """ self.setFunction(code) def getStateDefinitionCode(self, nodeName, indent=''): #print "ViewerNode getStateDefinitionCode" return self.vi.getViewerStateDefinitionCode( viewerName=nodeName+'.vi', indent=indent, withMode=False) def addGeometriesToViewer(self, geometries): """ this geometries a list, but not a list from a geom node """ if self.vi is None: return if geometries: for g in geometries: self.addGeometryiesToViewer(g) def addGeometryiesToViewer(self, geometryies): """ we don't know if geometryies is a Geom or a list from a geom node """ if geometryies and geometryies != [None]: if isinstance(geometryies, Geom) or isinstance(geometryies, Insert2d): if hasattr(geometryies, 'node') and \ hasattr(geometryies.node(),'geoms'): self.addMultipleGeomsToViewer(geometryies.node().geoms) else: self.addSingleGeomToViewer(geometryies) self.addGeometryiesToViewer(geometryies.parent) elif isinstance(geometryies, list): self.addMultipleGeomsToViewer(geometryies) else: assert False self.vi.Redraw() def addMultipleGeomsToViewer(self, geometries ): """ geometries is a list from a geom node """ #print "addMultipleGeomsToViewer", geometries for g in geometries: if isinstance(g, Geom) or isinstance(g, Insert2d): self.addSingleGeomToViewer(g) if g.parent.viewer is None: self.addGeometryiesToViewer(g.parent) elif isinstance(g, list): self.addMultipleGeomsToViewer(g) def addSingleGeomToViewer(self, aGeom ): """ geometries is a Geom """ #print "addSingleGeomToViewer", aGeom.name #if aGeom is None or aGeom.viewer is not None: if aGeom.viewer is not None: return # add the geom to the viewer lHighestModifiedParent = \ self.vi.AddObjectAndParents(aGeom, parent=aGeom.parent, local=False) # rename node geometry in Vision and set input for name # FIXME this test has to go after all Vision geoms have .node() if hasattr(aGeom, 'node') : aGeom.node().ensureNameOfNodeAndDescendants(lHighestModifiedParent) def deleteGeometries(self, connection): """code for input port callback "beforeDisconnect" this will delete geometries added to the viewer """ #print "Viewer Node deleteGeometries" #import pdb;pdb.set_trace() if self.vi is not None: self.vi.SetCurrentObject(self.vi.rootObject) if connection.port1.data: geoms = connection.port1.data # geoms can be packed in a list or not import types from DejaVu.Geom import Geom if type(geoms) == types.ListType: for g in geoms: if self.vi is None: g.viewer = None else: if hasattr(g,'node'): g.node().removeViewerConnections(connection) g.node().removeAndCleanMultipleGeometryies(g) else: # not list if self.vi is None: geoms.viewer = None else: if hasattr(geoms,'node'): geoms.node().removeViewerConnections(connection) geoms.node().removeAndCleanMultipleGeometryies(geoms) def buildIcons(self, canvas, posx, posy): apply( NetworkNode.buildIcons, (self, canvas, posx, posy) ) self.paramPanel.applyButton.forget() from DejaVu import Viewer from DejaVu.Geom import Geom if self.vi is None: self.vi = Viewer(nogui=1, guiMaster=self.paramPanel.widgetFrame) # do not allow user to kill this window self.vi.master.protocol('WM_DELETE_WINDOW', self.doNothing) self.ownViewer = 1 else: #self.vi = viewer self.ownViewer = 0 camera = self.vi.currentCamera # add callback to output picking events self.vi.AddPickingCallback(self.handlePick) # add callback to output redraw event self.vi.afterRedraw = self.afterRedraw self.outputData(dejaVuViewer=self.vi) def doNothing(self): # used for overwriting WM_DELETE_WINDOW of Viewer window return def afterRedraw(self): if self.vi: apply( self.vi.__class__.afterRedraw, (self.vi,)) # trigger all children of the redraw outputPort if len(self.outputPorts): self.outputData(redraw=1) self.scheduleChildren(portList=[self.outputPorts[2]]) def handlePick(self, pick): if pick: if self.vi: self.outputData(lastPick=self.vi.lastPick) # schedule children of lastPick self.scheduleChildren(portList=[self.outputPorts[0]]) def beforeRemovingFromNetwork(self): NetworkNode.beforeRemovingFromNetwork(self) for g in self.vi.rootObject.AllObjects(): if hasattr(g,'node'): g.node().removeSingleGeom(g) if self.ownViewer: self.vi.Exit() self.vi = None def toggleNodeExpand_cb(self, event=None): # overwrite base class method, because this panel is special if self.paramPanel.visible: self.paramPanel.hide() else: self.paramPanel.show() class AccumPickedVertices(NetworkNode): """Class to accumulate picked vertices Input Ports: pick: DejaVu pick object instance viewer: DejaVu viewer object instance reset: resets the list of vertices to empty remove: check button to remove vertices form the list Output Ports: pickedVertices: list of 3D vertices """ def __init__(self, **kw): apply( NetworkNode.__init__, (self,), kw ) self.vertices = [] # add an entry so the show parma. panel will be enabled ip = self.inputPortsDescr ip.append(name='pick', datatype='None') ip.append(name='viewer', datatype='viewer') ip.append(name='reset', datatype='boolean') ip.append(name='remove', datatype='boolean') self.widgetDescr['reset'] = { 'class':'NEButton', 'master':'node', 'initialValue':False, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'empty list'}, } self.widgetDescr['remove'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':False, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'remove'}, } op = self.outputPortsDescr op.append(datatype='list', name='pickedVertices') code = """def doit(self, pick, viewer, reset, remove): if self.inputPortByName['reset'].hasNewValidData(): self.vertices = [] if self.inputPortByName['pick'].hasNewValidData(): vertices = viewer.transformedCoordinatesWithInstances(pick.hits) if remove: for v1 in vertices: vstr = '%.3f %.3f %.3f'%tuple(v1) for v2 in self.vertices: if '%.3f %.3f %.3f'%tuple(v2)==vstr: self.vertices.remove(v2) else: self.vertices.extend(vertices) self.outputData(pickedVertices=self.vertices) """ self.setFunction(code) class PolyhedronVolumeArea(NetworkNode): """compute the numerical volume and surface area of a polyhedron Input Ports: geometry: (required) Accepts any IndexedPolygon geometry from DejaVu Output Ports: volume: float area: float compactness: area/volume (float) .""" def triangleArea(self, p1, p2, p3): """Compute the surface area of a triangle. """ x1,y1,z1 = p1 x2,y2,z2 = p2 x3,y3,z3 = p3 dx, dy, dz = x1-x2, y1-y2, z1-z2 a = sqrt( dx*dx + dy*dy + dz*dz ) dx, dy, dz = x2-x3, y2-y3, z2-z3 b = sqrt( dx*dx + dy*dy + dz*dz ) dx, dy, dz = x1-x3, y1-y3, z1-z3 c = sqrt( dx*dx + dy*dy + dz*dz ) s = .5*(a+b+c) area = s*(s-a)*(s-b)*(s-c) if area <= 0.: return 0. return sqrt(area) def meshVolume(self, verts, tri, norm): """Compute the Volume and surface area of a mesh specified by vertices, indices of triangular faces and face normals """ assert len(tri)==len(norm) volSum = 0.0 areaSum = 0.0 oneThird = 1./3. for t,n in zip(tri, norm): s1 = verts[t[0]] s2 = verts[t[1]] s3 = verts[t[2]] area = self.triangleArea(s1,s2,s3) areaSum += area g = [ (s1[0]+s2[0]+s3[0])*oneThird, (s1[1]+s2[1]+s3[1])*oneThird, (s1[2]+s2[2]+s3[2])*oneThird ] volSum += (g[0]*n[0] + g[1]*n[1] + g[2]*n[2])*area return volSum*oneThird, areaSum def __init__(self, name='PolyhedronVolumeArea', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 ip = self.inputPortsDescr ip.append(datatype='geom', name='geometry') op = self.outputPortsDescr op.append(datatype='float', name='volume') op.append(datatype='float', name='area') op.append(datatype='float', name='compactness') code = """def doit(self, geometry): vert = geometry.getVertices() tri = geometry.getFaces() #from opengltk.extent.utillib import glTriangleNormals from geomutils.geomalgorithms import TriangleNormals norm = TriangleNormals( vert, tri, 'PER_FACE') # FIXME getFNormals() returns old set of normals after sendity has changed # on MSMS surface # norm = geometry.getFNormals() vol, area = self.meshVolume(vert, tri, norm) self.outputData(volume=vol, area=area, compactness=area/vol) """ self.setFunction(code) class writeIndexedPolygon(NetworkNode): """write the vertices, normals and faces of an IndexedPolygon to a file. Input Ports: geometry: (required) Accepts any IndexedPolgon geometry from DejaVu filename: (required) string, no extension. filename.vert and filename.face will be created Output Ports: .""" def __init__(self, name='writeIndexedPolygon', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 self.widgetDescr['filename'] = { 'class':'NEEntryWithFileSaver', 'master':'node', 'width':10, 'initialValue':'', 'labelCfg':{'text':'Filename: '} } ip = self.inputPortsDescr ip.append(datatype='geom', name='geometry') ip.append(datatype='string', name='filename') code = """def doit(self, geometry, filename): from DejaVu.IndexedPolygons import IndexedPolygons assert isinstance(geometry, IndexedPolygons) geometry.writeToFile(filename) """ self.setFunction(code) class writeCurvPly(NetworkNode): """write the vertices and triangles of an IndexedPolygon to a file in the format used by the setCurvature program (which ressembles ply2) Input Ports: geometry: (required) Accepts any IndexedPolgon geometry from DejaVu filename: (required) string, no extension. filename.vert and filename.face will be created Output Ports: filename: outputs the filename after it wrote the file """ def writeFile(self, filename, verts, faces, neighborhoodSize, crestLines): f = open(filename, 'w') # this assert just because the test bellow commented out was weird assert crestLines in [0, 1, True, False] f.write('%d\n%d\n%d\n%d\n'%( len(verts), len(faces), neighborhoodSize, crestLines )) # crestLines==True )) dum = map(lambda x, f=f: f.write('%f\n'%x), verts) dum = map(lambda x, f=f: f.write('%d\n'%x), faces) f.close() def __init__(self, name='writeCurvPly', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 self.widgetDescr['filename'] = { 'class':'NEEntryWithFileSaver', 'master':'node', 'width':10, 'initialValue':'', 'labelCfg':{'text':'Filename: '} } self.widgetDescr['neighborhoodSize'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':4, 'labelCfg':{'text':'neighborhoodSize:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':1, 'wheelPad':2 } self.widgetDescr['crestLines'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':False, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'crest Lines:'}, } ip = self.inputPortsDescr ip.append(datatype='geom', name='geometry') ip.append(datatype='string', name='filename') ip.append(datatype='int', name='neighborhoodSize') ip.append(datatype='boolean', name='crestLines') op = self.outputPortsDescr op.append(datatype='string', name='filename') code = """def doit(self, geometry, filename, neighborhoodSize, crestLines): from DejaVu.IndexedPolygons import IndexedPolygons assert isinstance(geometry, IndexedPolygons) verts = geometry.getVertices() faces = geometry.getFaces() self.writeFile(filename, verts, faces, neighborhoodSize, crestLines) geometry.writeToFile(filename) """ self.setFunction(code) class Curvature(NetworkNode): """run the setCurvature program Input Ports: geometry: (required) Accepts any IndexedPolgon geometry from DejaVu neighborhoodSize: size of the neighborhood use to fit quadric crestLines: when set to ture crest liens are traced Output Ports: maxCurv: max curvature for each vertex minCurv: min curvature for each vertex vmaxCurv: max curvature vector vminCurv: min curvature vector GaussianCurv: Gaussian curvature vector (Kmax*Kmin) meanCurv: mean curvature vector for (Kmax+Kmin) shapeIndex: shapeIndex -2/pi*arctan(Kmax+Kmin/Kmax-Kmin) curvedness: curvedness sqrt(Kmax**2 + Kmin**2)/2 normals: normals to the surface """ def writeFile(self, filename, verts, faces, neighborhoodSize, crestLines): f = open(filename, 'w') # this assert just because the test bellow commented out was weird assert crestLines is True or crestLines is False f.write('%d\n%d\n%d\n%d\n'%( len(verts)/3, len(faces)/3, neighborhoodSize, crestLines )) #crestLines==True )) dum = map(lambda x, f=f: f.write('%f\n'%x), verts) dum = map(lambda x, f=f: f.write('%d\n'%x), faces) f.close() def readCurvature(self, filename): f = open(filename) data = f.readlines() f.close() nbv = int(data[0]) nbt = int(data[1]) import string dataf = map(string.split, data[2:]) curvData = [] for l in dataf: curvData.append(map(float, l)) curvData = Numeric.array(curvData, 'f') return curvData def __init__(self, name='curvature', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.widgetDescr['neighborhoodSize'] = { 'class':'NEThumbWheel', 'master':'node', 'initialValue':4, 'labelCfg':{'text':'neighborhoodSize:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':1, 'wheelPad':2 } self.widgetDescr['crestLines'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':False, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'crest Lines:'}, } ip = self.inputPortsDescr ip.append(datatype='geom', name='geometry') ip.append(datatype='int', name='neighborhoodSize') ip.append(datatype='boolean', name='crestLines') op = self.outputPortsDescr op.append(datatype='list', name='maxCurv') op.append(datatype='list', name='minCurv') op.append(datatype='list', name='vmaxCurv') op.append(datatype='list', name='vminCurv') op.append(datatype='list', name='gaussian') op.append(datatype='list', name='mean') op.append(datatype='list', name='shapeIndex') op.append(datatype='list', name='curvedness') op.append(datatype='list', name='normals') code = """def doit(self, geometry, neighborhoodSize, crestLines): from DejaVu.IndexedPolygons import IndexedPolygons assert isinstance(geometry, IndexedPolygons) verts = Numeric.reshape(geometry.getVertices(), (-1,)) faces = Numeric.reshape(geometry.getFaces(), (-1,)) self.writeFile('curv.txt' , verts, faces, neighborhoodSize, crestLines) os.system('setCurvature curv.txt curv.out') curvData = self.readCurvature('curv.out') #os.system('rm curv.out curv.txt') Kmax = curvData[:,0] Kmin = curvData[:,1] gaussian = Kmax*Kmin mean = (Kmax+Kmin)*0.5 shapeIndex = (-2/pi)*Numeric.arctan((Kmax+Kmin)/(Kmax-Kmin)) curvedness = Numeric.sqrt(Kmax*Kmax+Kmin*Kmin)*0.5 self.outputData(maxCurv=Kmax, minCurv=Kmin, vmaxCurv=curvData[:,2:5].tolist(), vminCurv=curvData[:,5:8].tolist(), gaussian=gaussian, mean=mean, shapeIndex=shapeIndex, curvedness=curvedness, normals=curvData[:,8:].tolist() ) """ self.setFunction(code) class readIndexedPolygon(NetworkNode): """ ************* DEPRECATED, USE GeomsFromFile instead ************** read the vertices, normals and faces of an IndexedPolygon from a file. Input Ports: filename: (required) string, no extension. filename.vert and filename.face will be created name: (optional) name for the geoemtry. Defaults to filename Output Ports: geometry: DejaVu.IndexedPolgons geometry .""" def __init__(self, name='readIndexedPolygon', **kw): #warnings.warn("read Indexed Polygon is deprecated, use 'geoms from file' instead") kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 wdescr = self.widgetDescr wdescr['filename'] = { 'class':'NEEntryWithFileBrowser', 'master':'node', 'width':10, 'initialValue':'', 'labelCfg':{'text':'Filename: '}, 'filetypes': [('vert','*.vert'), ('all', '*')]} wdescr['name'] = { 'class':'NEEntry', 'master':'node', 'width':10, 'labelCfg':{'text':'name:'}, } ip = self.inputPortsDescr ip.append(datatype='string', name='filename') ip.append(datatype='string', required=False, name='name') op = self.outputPortsDescr op.append(datatype='geom', name='geom') code = """def doit(self, filename, name): if filename is None or filename == '': return from DejaVu.IndexedPolygons import IndexedPolygonFromFile from os.path import splitext if name == '': name=None filename = splitext(filename)[0] self.outputData(geom=IndexedPolygonFromFile(filename, name)) """ self.setFunction(code) from DejaVu.utils import RemoveDuplicatedVertices class RemoveDuplicatedVerticesNE(NetworkNode): """Remove duplicated vertices and re-index the polygonal faces such that they share vertices input: geom -- an IndexedGeom object in which vertices are suplicated newGeom -- when true a new geoemtry is created, else the incomming geometry is modified output: geom -- a new IndexedPolgons without duplicated vertices """ def __init__(self, name='removeDupVert', **kw): kw['name'] = name apply(NetworkNode.__init__, (self,), kw) ip = self.inputPortsDescr = [] ip.append({'datatype':'geom', 'name':'geom'}) ip.append({'datatype':'boolean', 'name':'newGeom'}) self.widgetDescr['newGeom'] = { 'class':'NECheckButton', 'initialValue':False, 'master':'node', 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'new geometry'}, } op = self.outputPortsDescr = [] op.append({'datatype':'geom', 'name':'geom'}) code = """def doit(self, geom, newGeom): from DejaVu.utils import RemoveDuplicatedVertices from DejaVu.IndexedPolygons import IndexedPolygons, Geom results = [] if isinstance(geom, Geom): geom = [geom] for g in geom: vertices = g.vertexSet.vertices.array faces = g.faceSet.faces.array vertList, faceList = RemoveDuplicatedVertices(vertices, faces) if newGeom: results.append( IndexedPolygons('%sMesh'%g.name, vertices=vertList, faces=faceList)) else: g.Set(vertices=vertList, faces=faceList) results.append(g) self.outputData(geom=results) """ self.configure(function=code) class removeDuplicatedVerticesC(NetworkNode): """Remove duplicated vertices and re-index the polygonal faces such that they share vertices (uses the C++ function from opengltk.extent.utillib) input: geom -- an IndexedGeom object in which vertices are suplicated newGeom -- when true a new geoemtry is created, else the incomming geometry is modified output: geom -- a new IndexedPolygons without duplicated vertices """ def __init__(self, name='removeDupVertC', **kw): kw['name'] = name apply(NetworkNode.__init__, (self,), kw) ip = self.inputPortsDescr = [] ip.append({'datatype':'geom', 'name':'geom'}) ip.append({'datatype':'boolean', 'name':'newGeom'}) self.widgetDescr['newGeom'] = { 'class':'NECheckButton', 'initialValue':False, 'master':'node', 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'new geometry'}, } op = self.outputPortsDescr = [] op.append({'datatype':'geom', 'name':'geom'}) code = """def doit(self, geom, newGeom): results = [] from DejaVu.IndexedPolygons import IndexedPolygons, Geom from geomutils.geomalgorithms import removeDuplicatedVertices if isinstance(geom, Geom): geom = [geom] for g in geom: vertices = g.vertexSet.vertices.array faces = g.faceSet.faces.array norms = g.getVNormals() if len(vertices) and len(faces): vertList, faceList, normList = removeDuplicatedVertices( vertices, faces, norms ) if newGeom: results.append( IndexedPolygons('%sMesh'%g.name, vertices=vertList, faces=faceList))#, vnormals=normList)) else: g.Set(vertices=vertList, faces=faceList)#, vnormals=normList) results.append(g) self.outputData(geom=results) """ self.configure(function=code) class QslimExt(NetworkNode): """Invoked the Qslim algorithm as an external process to decimate a surface. Input Ports geometry: Any DejaVu.IndexedPolgons geometry. (required) persent: percentage of faces to be retained in decimated model Output Ports: geom: decimated geometry .""" def __init__(self, name='write SMF', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.widgetDescr['percent'] = { 'class':'NEDial', 'size':50, 'oneTurn':100, 'min':0., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':50., 'labelCfg':{'text':'percent'}, } ip = self.inputPortsDescr ip.append(name='lines', datatype='list') ip.append(name='percent', datatype='float') ip.append(name='nbf', datatype='int', required=False) op = self.outputPortsDescr op.append({'name':'lines', 'datatype':'list'}) code = """def doit(self, lines, percent, nbf): if nbf is None: nbf = 0 for l in lines: if l[0]=='f': nbf+=1 targetFaces = int(nbf*percent/100.) from mglutil import process # start propslim process p = process.Popen('propslim %d'%targetFaces, stdin=process.PIPE, stdout=process.PIPE) inp, out, err = (p.stdin, p.stdout, p.stderr) # send input map( lambda x, f=inp: f.write('%s'%x), lines) inp.close() # FIXME we should select on out and err and handle errors # FIXME we should run popslim from the Binaries package # FIXME we should have a way to detect if the Binary package contains # popslim and if not not load the node # read results data = out.readlines() print 'propslim reduced from %d to %d faces'%(nbf,targetFaces) self.outputData(lines=data) """ self.setFunction(code) class GeomtoSMF(NetworkNode): """create the source of an SMF file from an DejaVu.IndexedPolygons geometry Input Ports: geometry: Any DejaVu.IndexedPolgons geometry. (required) filename: name of the SMF file to be created (required, string) Output Ports: lines: list of text lines in SMF format .""" def __init__(self, name='GeomToSMF', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(name='geometry', datatype='geom') self.outputPortsDescr.append(name='lines', datatype='list') code = """def doit(self, geometry): from DejaVu.IndexedPolygons import IndexedPolygons assert isinstance(geometry, IndexedPolygons) from DejaVu.DataOutput import IndexedPolgonsAsSMFString lines = IndexedPolgonsAsSMFString(geometry) self.outputData(lines = lines) """ self.setFunction(code) class SMFtoGeom(NetworkNode): """converts a list of strings describing an SMF file into a DejaVu.IndexedPolygons Input Ports: lines: list of lines geomname: name for the geoemtry parent: parent geometry Output Ports: geometry: DejaVu.IndexedPolgons geometry .""" def __init__(self, name='SMFtoGeom', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) from DejaVu.IndexedPolygons import IndexedPolygons self.geom = IndexedPolygons() self.widgetDescr['geomname'] = { 'class':'NEEntry', 'master':'node', 'width':10, 'labelCfg':{'text':'name:'}, 'initialValue':'smfModel', } ip = self.inputPortsDescr ip.append(name='lines', datatype='list') ip.append(name='geomname', datatype='string', required=False) ip.append(name='parent', datatype='geom', required=False) op = self.outputPortsDescr op.append(name='geom', datatype='geom') code = """def doit(self, lines, geomname, parent): if len(lines)==0: return if not geomname: # i.e. None or '' geomname = 'smfModel' from DejaVu.DataOutput import ParseSMFString v,f,n,c,r = ParseSMFString(lines) self.geom.Set(name=geomname, vertices=v, faces=f, redo=0) if len(n): if len(n)==len(v): self.geom.Set(vnormals=n, redo=0) elif len(n)==len(f): geom.Set(fnormals=n, redo=0) else: errstr = 'number of normals %d does not not match number of vertices (%d) or number of faces(%d)'%(len(v), len(f)) warnings.warn(errstr) if len(c): self.geom.Set(materials=c, inheritMaterial=False, redo=0) if parent is not None: self.geom.viewer.ReparentGeom(self.geom. parent) self.geom.Set(redo=1) self.outputData(geom=self.geom) """ self.setFunction(code) from DejaVu.IndexedPolygons import IndexedPolygons import numpy.oldnumeric as Numeric try: from QSlimLib import qlimlib except: pass class QSlimDecimate: def __init__(self): self.model = None self.newverts = None # Vertex array of new geometry self.newfaces = None # Face array of new geometry self.newcolors = None # Color array of new geometry self.newnorms = None self.numColors = 0 # Number of valid colors and self.colorBind = None self.maxFaces = 0 # number of faces in the geometry used to build the # QSlim model def build_model(self, geometry, t1=None, t2 = None): """Build new QSlim model.""" verts = geometry.getVertices() faces = geometry.getFaces() colors = None self.colorBind = None binding = geometry.materials[1028].binding[1] bind_to_face = False if binding==11: #per vertex color bind_to_face = False self.colorBind = 'vertex' elif binding==12: #per face color bind_to_face = True self.colorBind = 'face' if self.colorBind is not None: colors = geometry.materials[1028].prop[1][:,:3].astype('f') self.newcolors = Numeric.zeros(colors.shape, 'f') else: self.newcolors = None normals = geometry.getVNormals() #print "in build_model: faces %d, normals %d " % (len(faces), len(normals)) #texcoords texcoords = None self.newtexcoords = None #t1 = Numeric.arange(len(verts)).astype('f') if t1 is not None and t2 is not None: assert len(t1) == len(t2) texcoords = Numeric.zeros((len(t1),2), "f") texcoords[:,0] = t1[:] texcoords[:,1] = t2[:] elif t1 is not None: texcoords = Numeric.zeros((len(t1),2), "f") texcoords[:,0] = t1[:] elif t2 is not None: texcoords = Numeric.zeros((len(t2),2), "f") texcoords[:,0] = t2[:] else: if hasattr(geometry.vertexSet, 'texCoords'): texcoords = geometry.vertexSet.texCoords.array if texcoords is not None: #print "len(texcoords): ", len(texcoords) #print "len(verts): ", len(verts) assert len(texcoords) == len(verts) self.newtexcoords = Numeric.zeros(texcoords.shape, 'f') self.model = qslimlib.QSlimModel(verts, faces, bindtoface=bind_to_face, colors=colors, norms=normals, texcoords=texcoords) nverts = self.model.get_vert_count() self.maxFaces = nfaces = self.model.get_face_count() self.newverts = Numeric.zeros((nverts, 3)).astype('f') self.newfaces = Numeric.zeros((nfaces, 3)).astype('i') self.newnorms = Numeric.zeros((nverts, 3)).astype('f') def decimate(self, targetfaces): print 'DECIMATING TO', targetfaces self.model.slim_to_target(targetfaces) # the number of faces we get back can be slightly different # from the taget number of faces: numFaces = self.model.num_valid_faces() self.model.outmodel(self.newverts, self.newfaces, outcolors=self.newcolors, outnorms=self.newnorms,outtexcoords=self.newtexcoords ) numVertices = max(self.newfaces.ravel())+1 # build lookup table of vertices used in faces d = {} for t in self.newfaces[:numFaces]: d[t[0]] = 1 d[t[1]] = 1 d[t[2]] = 1 vl = {} decimVerts = Numeric.zeros((numVertices, 3)).astype('f') decimFaces = Numeric.zeros((numFaces, 3)).astype('i') decimNormals = Numeric.zeros((numVertices, 3)).astype('f') decimColors = None decimTex = None if self.newcolors is not None: decimColors = {'vertex': Numeric.zeros((numVertices, 3)).astype('f'), 'face':self.newcolors[:numFaces]}.get(self.colorBind) if self.newtexcoords is not None: decimTex = Numeric.zeros((numVertices, 2)).astype('f') nvert = 0 for j, t in enumerate(self.newfaces[:numFaces]): for i in (0,1,2): n = t[i] if not vl.has_key(n): vl[n] = nvert decimVerts[nvert] = self.newverts[n,:] decimNormals[nvert] = self.newnorms[n,:] if self.newcolors is not None: if self.colorBind == 'vertex': decimColors[nvert] = self.newcolors[n, :] if self.newtexcoords is not None: decimTex[nvert] = self.newtexcoords[n,:] nvert += 1 decimFaces[j] = (vl[t[0]], vl[t[1]], vl[t[2]]) return (decimVerts[:nvert], decimFaces, decimNormals[:nvert], decimColors, decimTex) class QSlim(NetworkNode): """Uses QSlim library to decimate a surface. Creates a QSlim model from the input geometry, decimates it and outputs a geometry with new number of faces, vertices, colors. Input Ports geometry: any DejaVu.IndexedPolgons geometry (required). percent: percentage of faces to be retained in decimated model (required). targetfaces: corresponding to persent number of faces. newgeom: (checkbutton) if checked - the node outputs a new IndexedPolygons geometry, if unchecked - modified input geometry is output. rebuild: (boolean), when true, rebuilds the QSlim model (takes current parameters of selected geometry). Output Ports: geom: decimated geometry .""" def __init__(self, name='QSlim', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.widgetDescr['percent'] = { 'class':'NEDial', 'master':'ParamPanel', 'size':50, 'oneTurn':100, 'min':0., 'max':100., 'type':'float', 'showLabel':1, 'continuous':0, 'initialValue':50., 'labelCfg':{'text':'percent'}, } self.widgetDescr['targetfaces'] = { 'class':'NEEntry', 'master':'ParamPanel', 'width':10, 'labelCfg':{'text':'num of faces:'}, } self.widgetDescr['newgeom'] = { 'class':'NECheckButton', 'initialValue':0, 'master':'ParamPanel', 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'create new geometry'}, } self.widgetDescr['rebuild'] = { #'class':'NECheckButton', 'class':'NEButton', 'master':'ParamPanel', 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'rebuild Qslim model'} } ip = self.inputPortsDescr ip.append(datatype='geom', name='geometry') ip.append(name='percent', datatype='float') ip.append(name='targetfaces', datatype = "int", required=False) ip.append (name='rebuild', datatype='boolean', required=False) ip.append(datatype='None', name='u', required=False) ip.append(datatype='None', name='v', required=False) op = self.outputPortsDescr op.append(datatype='geom', name='geometry') op.append(datatype='None', name='u') op.append(datatype='None', name='v') self.geometry = None # Current geometry self.model = QSlimDecimate() code = """def doit(self, geometry , percent, targetfaces, rebuild, u, v): #print 'QSlim Node Running QSlim', percent, targetfaces, rebuild, self.inputPortByName['rebuild'].hasNewValidData() # QSlim node can only handle 1 geom so far, so print out a message if there # are more comming in if type(geometry)==types.ListType: if len(geometry)>1: warnings.warn('Only first geometry is being processed by QSlim node') geometry = geometry[0] # check that the incomming geom can be represented as IndexedPolygons if not geometry.asIndexedPolygons(run=0): warnings.warn(geometry.name , 'QSlim Node: %s can not be represented as IndexedPolygons', geometry.name) return # if there is new data on the first input port (geom) rebuild the model #if self.inputPortByName['geometry'].hasNewValidData() or \ #(self.inputPortByName['rebuild'].hasNewValidData() and rebuild): if self.inputPortByName['geometry'].hasNewValidData() or \ self.inputPortByName['rebuild'].hasNewValidData(): if len(geometry.vertexSet.vertices): print 'QSlim Node BUILDING MODEL' self.model.build_model(geometry, u, v) else: return maxFaces = self.model.maxFaces # compute the number of triangles to be kept if self.inputPortByName['percent'].hasNewValidData(): #percent has changed targetfaces = int(maxFaces*percent/100.) elif self.inputPortByName['targetfaces'].hasNewValidData() and targetfaces: #targetfaces has changed targetfaces = int(targetfaces) else: # use the percentage targetfaces = int(maxFaces*percent/100.) print 'ELSE', maxFaces*percent, targetfaces # make sure targetfaces is OK if targetfaces > maxFaces: targetfaces = maxFaces if self.inputPortByName['percent'].widget: self.inputPortByName['percent'].widget.set(100, 0) if self.inputPortByName['targetfaces'].widget: self.inputPortByName['targetfaces'].widget.set(maxFaces, 0) # decimate if self.model: decimVerts, decimFaces, decimNormals, decimColors, decimTex = self.model.decimate(targetfaces) redo = self.model.newcolors is None geometry.Set(vertices=decimVerts, faces=decimFaces, vnormals=decimNormals, redo=redo) #print 'len decimated verts = %d, faces = %d, normals = %d' % (len(decimVerts), len(decimFaces), len(decimNormals)) geometry.vertexSet.vertices.array = decimVerts geometry.faceSet.faces.array = decimFaces #geometry.Set(faces=decimFaces, vertices=decimVerts, fnormals = decimNormals, redo=redo) numFaces = len(decimFaces) nvert = len(decimVerts) clen = len(decimFaces) if self.model.newcolors is not None: if self.model.colorBind == 'vertex': clen = nvert #print 'len colors:', clen if clen > 0: geometry.Set(materials=decimColors[:clen], inheritMaterial=False, redo=True) else: geometry.Set(inheritMaterial=False, redo=True) else: geometry.Set(faces=decimFaces, vertices=decimVerts, fnormals = decimNormals) # set the target face widget to the actual number of faces after # decimation if self.inputPortByName['targetfaces'].widget: self.inputPortByName['targetfaces'].widget.set(numFaces, run=0) realpercent = 100.*(float(numFaces)/maxFaces) if percent != realpercent and self.inputPortByName['percent'].widget: self.inputPortByName['percent'].widget.set(realpercent, run=0) if self.model.newtexcoords is not None: if hasattr(geometry.vertexSet, 'texCoords'): geometry.Set(textureCoords=decimTex[:nvert]) self.outputData(geometry=geometry, u=decimTex[:nvert,0], v = decimTex[:nvert,1] ) else: self.outputData(geometry=geometry) """ self.setFunction(code) try: bhtreelibFound = True from bhtree import bhtreelib class decimate3DPoints(NetworkNode): """loops over a list of 3D points and removes any point to close to an already seen one Input Ports: points: (required) 3D points to be decimated cutoff: distance below which a point in cut Output Ports: points: decimated set of points .""" def __init__(self, name='getSurfaceVFN', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 ip = self.inputPortsDescr ip.append(datatype='coordinates3D', name='point') ip.append(datatype='float', name='cutoff') op = self.outputPortsDescr op.append(datatype='coordinates3D', name='points') code = """def doit(self, points, cutoff): import numpy.oldnumeric as Numeric ids = Numeric.arange(len(points)).astype('i') bht = bhtreelib.TBHTree( points, ids, 10, 10, 9999.0 ) result = Numeric.zeros( (len(points),) ).astype('i') dist = Numeric.zeros( (len(points),) ).astype('f') pts = [] removed = {} for p in points: if removed.has_key('%9.6f,%9.6f,%9.6f'%tuple(p)): continue pts.append(p) nb = bht.ClosePointsDist2( tuple(p), cutoff, result, dist ) for close in result: removed['%9.6f,%9.6f,%9.6f'%tuple(points[close])] = True self.outputData(points=pts) """ self.setFunction(code) class DistFromSphereToGeom(NetworkNode): """assign to every sphere the distance to the closest surface vertex. Input ports: centers: a list of sphere centers radii: list of sphere radii geom: a polygonal geometry OutputPort: dist: list of distances """ def __init__(self, name='DistFromSphereToGeom', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='coordinates3D', name='centers') ip.append(datatype='None', name='radii') ip.append(datatype='geom', name='geom') op = self.outputPortsDescr op.append(datatype='list', name='distances') code = """def doit(self, centers, radii, geom): #build a BHtree for geometry's vertices vf = geom.getVertices() import numpy.oldnumeric as Numeric points = Numeric.array(vf, 'f') ids = Numeric.arange(len(points)).astype('i') result = Numeric.zeros( (len(points),) ).astype('i') dist = Numeric.zeros( (len(points),) ).astype('f') bht = bhtreelib.TBHTree( points, ids, 10, 10, 9999.0 ) distances = [] try: len(radii) except: radii = (radii,)*len(points) # compute distance from sphere to closest geometry vertex for c,r in zip(centers,radii): found = False cutoff=5.0 while not found: nb = bht.ClosePointsDist2( tuple(c), cutoff, result, dist) if nb: distances.append( sqrt(min(dist[:nb]))-r ) found = True else: cutoff += 5.0 self.outputData(distances=distances) """ self.setFunction(code) except: bhtreelibFound = False class getSurfaceVFN(NetworkNode): """extract vertices, faces and normals from a geometry. Input Ports: geometry: (required) Accepts any object that is a DejaVu.Geom instance and will add it to the viewer only once Output Ports: geom: either geom that is input or result of asIndexedPolygons vertices: faces: normals: .""" def __init__(self, name='getSurfaceVFN', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 ip = self.inputPortsDescr ip.append(datatype='geom', name='geometry') op = self.outputPortsDescr op.append(datatype='geom', name='geom') op.append(datatype='coordinates3D', name='vertices') op.append(datatype='faceIndices', name='faces') op.append(datatype='normals3D', name='normals') op.append(datatype='normals3D', name='facenormals') code = """def doit(self, geometry): if geometry: geom = geometry.asIndexedPolygons() v = geom.getVertices() vn = geom.getVNormals() fn = geom.getFNormals() f = geom.getFaces() self.outputData(geom=geom, vertices=v, faces=f, normals=vn, facenormals=fn) """ self.setFunction(code) try: from opengltk.extent import _gllib import Image import ImageChops class ImageViewerNode(NetworkNode): """create an instance of an OpenGL-based image viewer This object can compute the first and second derivative and the historgram of the image INPUT: image: image to be displayed operator: can be 'FirstDerivative', 'SecondDerivative' or 'Histogram' OUTPUT: imageViewer: the image viewer instance result: the processed image oir the histogram """ def beforeAddingToNetwork(self, net): # import imagelib importImageLib(net) def _init__(self, name='ImageViewer', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) from DejaVu.imageViewer import ImageViewer self.ivi = ImageViewer(name='image renderer') self.widgetDescr['operator'] = { 'class':'NEComboBox', 'master':'node', 'choices':['FirstDerivative', 'SecondDerivative', 'Histogram'], 'entryfield_entry_width':8, 'labelCfg':{'text':'operator:'}, } ip = self.inputPortsDescr ip.append(datatype='image', required=False, name='image') ip.append(datatype='string', required=False, name='operator') op = self.outputPortsDescr op.append(datatype='None', name='imageViewer') op.append(datatype='image', name='result') code = """def doit(self, image, operator): if image: self.ivi.setImage(image) if operator == 'FirstDerivative': outdata = self.ivi.firstDerivative() out = Image.fromstring('RGB', (self.ivi.width, self.ivi.height), outdata) self.outputPorts[1].setDataType('image', tagModified=False) elif operator == 'SecondDerivative': outata = self.ivi.secondDerivative() out = Image.fromstring('RGB', (self.ivi.width, self.ivi.height), outdata) self.outputPorts[1].setDataType('image', tagModified=False) elif operator == 'Histogram': out = self.ivi.getHistogram() self.outputPorts[1].setDataType('list', tagModified=False) else: out = None self.outputData(imageViewer=self.ivi, result=out ) """ self.setFunction(code) class NPR(NetworkNode): """make NPR rendering of the currentCamera of a viewer""" def beforeAddingToNetwork(self, net): # import imagelib importImageLib(net) from DejaVu.imageViewer import ImageViewer self.ivi = ImageViewer(name='image renderer') def afterRemovingFromNetwork(self): NetworkNode.afterRemovingFromNetwork(self) if self.ivi: self.ivi.master.destroy() del self.ivi def __init__(self, name='NPR', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.ivi = None # will be instanciated when node added to network self.widgetDescr['d1cut'] = { 'class':'NEThumbWheel', 'initialValue':0, 'labelCfg':{'text':'d1cut:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['d1scale'] = { 'class':'NEThumbWheel', 'initialValue':3, 'labelCfg':{'text':'d1scale:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['d1off'] = { 'class':'NEThumbWheel', 'initialValue':60, 'labelCfg':{'text':'d1off:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['d2cut'] = { 'class':'NEThumbWheel', 'initialValue':1, 'labelCfg':{'text':'d2cut:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['d2scale'] = { 'class':'NEThumbWheel', 'initialValue':8, 'labelCfg':{'text':'d2scale:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10., 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['d2off'] = { 'class':'NEThumbWheel', 'initialValue':10, 'labelCfg':{'text':'d2off:'}, 'width':80, 'height':20, 'type':'int', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['firstDerivative'] = { 'class':'NECheckButton', 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'first Derivative:'}, } self.widgetDescr['secondDerivative'] = { 'class':'NECheckButton', 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'secondtDerivative:'}, } self.widgetDescr['smooth'] = { 'class':'NECheckButton', 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'smooth:'}, } ip = self.inputPortsDescr ip.append(datatype='viewer', name='viewer') ip.append(datatype='int', required=False, name='d1cut', defaultValue=0) ip.append(datatype='float', required=False, name='d1scale', defaultValue=3.) ip.append(datatype='int', required=False, name='d1off', defaultValue=60) ip.append(datatype='int', required=False, name='d2cut', defaultValue=1) ip.append(datatype='float', required=False, name='d2scale', defaultValue=8.) ip.append(datatype='int', required=False, name='d2off', defaultValue=10) ip.append(datatype='boolean', required=False, name='firstDerivative', defaultValue=True) ip.append(datatype='boolean', required=False, name='secondDerivative', defaultValue=True) ip.append(datatype='boolean', required=False, name='smooth', defaultValue=True) op = self.outputPortsDescr op.append(datatype='image', name='image') op.append(datatype='image', name='outline') code = """def doit(self, viewer, d1cut, d1scale, d1off, d2cut, d2scale, d2off, firstDerivative, secondDerivative, smooth): camera = viewer.currentCamera viewer.stopAutoRedraw() camera.frame.master.lift() viewer.OneRedraw() image = camera.GrabFrontBuffer() zbuf = camera.GrabZBuffer() camera.viewer.startAutoRedraw() width = camera.width height = camera.height #self.ivi.master.lift() self.ivi.setImage(zbuf) if firstDerivative: deriv = self.ivi.firstDerivative() if deriv is None: return d1strong = Numeric.where(Numeric.greater(deriv,d1cut), d1scale*(deriv+d1off), 0) if secondDerivative: deriv2 = self.ivi.secondDerivative() d2strong = Numeric.where(Numeric.greater(deriv2,d2cut), d2scale*(deriv2+d2off), 0) if firstDerivative and secondDerivative: dstrong = Numeric.maximum(d1strong, d2strong) elif firstDerivative: dstrong = d1strong elif secondDerivative: dstrong = d2strong mini = min(dstrong) maxi = max(dstrong) if maxi!=mini: dstrong = ((dstrong-mini)/(maxi-mini))*255 derivcompb = Numeric.fabs(dstrong-255).astype('B') ## if smooth: ## from time import time ## t1 = time() ## self.ivi.setImage(derivcompb,width=width, height=height, mode='RGB') ## derivcompb = self.ivi.smooth() ## print time()-t1 outline = Image.fromstring('RGB', (width,height), derivcompb) if os.name != 'nt': #sys.platform!='win32': outline = outline.transpose(Image.FLIP_TOP_BOTTOM) if smooth: from time import time import ImageFilter, ImageChops t1 = time() outlinesmooth = outline.filter(ImageFilter.SMOOTH_MORE) #outline = ImageChops.multiply(outline, outlinesmooth) print time()-t1 import ImageChops contouredImage = ImageChops.multiply(image, outline) ## mask = dstrong ## mask.shape = ( width, height, -1) ## maskr = Numeric.array(mask[:,:,0]).astype('B') ## maskim = Image.fromstring('L', (width,height), maskr) ## maskim = maskim.transpose(Image.FLIP_TOP_BOTTOM) ## image.paste(outline, None, maskim) self.outputData(image=contouredImage, outline=outline) """ self.setFunction(code) except: pass class SelectMultipleGeometry(NetworkNode): """Choose one or more geometry using regular expression matching on the name Input: viewer: Viewer in which to search for geoemtry objects name: regular expression parent: (optional) if specified, only children geometry objects of 'parent' will be searched. Defaults to the root object. Output: geomList: list of geometry objects """ def __init__(self, name='Choose Geoms', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.widgetDescr['name'] = { 'class':'NEEntry', 'master':'node', 'labelCfg':{'text':'name pattern:'}, 'initialValue':'.*', } ip = self.inputPortsDescr ip.append(datatype='viewer', name='viewer') ip.append(datatype='string', name='name') ip.append(datatype='geom', required=False, name='searchedParent') op = self.outputPortsDescr op.append(datatype='geom', name='geomList') code = """def doit(self, viewer, name, searchedParent): result = viewer.findGeomsByName(name, searchedParent) self.outputData(geomList=result) """ self.setFunction(code) class SelectGeometry(NetworkNode): """Choose a geometry in the DejaVu Viewer.""" def __init__(self, name='Choose Geom', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.widgetDescr['geomName'] = { 'class':'NEComboBox', 'master':'node', 'choices':[''], 'autoList':True, 'entryfield_entry_width':16, 'labelCfg':{'text':'geom:'}, } ip = self.inputPortsDescr ip.append(datatype='viewer', name='viewer') ip.append(datatype='string', required=False, name='geomName') op = self.outputPortsDescr op.append(datatype='geom', name='geometry') code = """def doit(self, viewer, geomName): if viewer: allObjs = viewer.rootObject.AllObjects() allNames = map(lambda x: x.fullName, allObjs) w = self.inputPortByName['geomName'].widget if w: w.configure(choices=allNames) if geomName not in allNames: geomName = None w.widget.setentry('') if geomName: obj = allObjs[allNames.index(geomName)] if obj: self.outputData(geometry=obj ) """ self.setFunction(code) class Redraw(NetworkNode): """Create a DejaVu Redraw event. Trigger can be anything Input: Viewer: one or more viewer trigger: Output: """ def __init__(self, name='Redraw', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='viewer', singleConnection=False, name='viewer') ip.append(name='trigger') code = """def doit(self, viewer, trigger): for v in viewer: v.Redraw()\n""" self.setFunction(code) class StopAutoRedraw(NetworkNode): """Stop autoRedraw mode in the viewer Input: Viewer: one or more viewer trigger: Output: """ def __init__(self, name='Stop Auto Redraw', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='viewer', singleConnection=False, name='viewer') ip.append(name='trigger') code = """def doit(self, viewer, trigger): for v in viewer: v.stopAutoRedraw()\n""" self.setFunction(code) class StartAutoRedraw(NetworkNode): """Start autoRedraw mode in the viewer Input: Viewer: one or more viewer trigger: Output: """ def __init__(self, name='Start Auto Redraw', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='viewer', singleConnection=False, name='viewer') ip.append(name='trigger') code = """def doit(self, viewer, trigger): for v in viewer: v.startAutoRedraw()\n""" self.setFunction(code) class OneRedraw(NetworkNode): """Make one redraw in the viewer. This is used when auto redrwa is stopped Input: Viewer: one or more viewer trigger: Output: """ def __init__(self, name='One Redraw', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='viewer', singleConnection=False, name='viewer') ip.append(name='trigger') code = """def doit(self, viewer, trigger): for v in viewer: v.OneRedraw()\n""" self.setFunction(code) class SetInstances(NetworkNode): """Assign instance matrices to a geometry. """ def __init__(self, name='Set Instances', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='geom', singleConnection=False, name='geometry') ip.append(datatype='instancemat(0)', name='matrices') code = """def doit(self, geometry, matrices): if geometry and matrices: for g in geometry: g.Set(instanceMatrices=matrices) if g.viewer: g.viewer.Redraw()\n""" self.setFunction(code) def beforeAddingToNetwork(self, net): # import symlib importSymLib(net) class ReparentGeom(NetworkNode): """******************* DEPRECATED : USE geoms properties INSTEAD FOR THE GEOMETRY NODES OR THE IMPUT PORT "parent" assigns a geometry to a new parent. This node can handle a single geometry, list of geometry objects or a list containing both geoemtry objects and lists of them. Input Ports: geom: geometry to be assigned to a anew parent parent: parent geometry Output Ports: """ def __init__(self, name='Reparent Geom', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='geom(0)', singleConnection=False, name='geoms') ip.append(datatype='geom', required=False, name='parent') ip.append(datatype='boolean', required=False, name='retainPosition', defaultValue=False) self.widgetDescr['retainPosition'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'retain position:'}, } code = """def doit(self, geoms, parent, retainPosition): def getRidOfInnerLists(alist): returnedList = [] for element in alist: if isinstance(element, Geom) or isinstance(element, Insert2d): returnedList.append(element) elif isinstance(element, list): returnedList += getRidOfInnerLists(element) return returnedList try: if parent is not None: if len(parent)>1: raise TypeError('parent should be a geometry or a list of lenght 1') else: parent = parent[0] except AttributeError: pass geoms = getRidOfInnerLists(geoms) if len(geoms) > 0: viewer = geoms[0].viewer assert viewer is not None root = viewer.rootObject for geom in geoms: if parent is None: parent = root viewer.ReparentObject(geom, parent, objectRetainsCurrentPosition=retainPosition) """ if code: self.setFunction(code) class GeomsProperties(NetworkNode): """this node (should not be used with GeometryNode because it already manages all that) assigns a geometry to a new parent and set its properties. This node can handle a single geometry, list of geometry objects or a list containing both geoemtry objects and lists of them. Input Ports: geom: geometry to be assigned to a anew parent parent: parent geometry Output Ports: """ def __init__(self, name='geoms properties', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='geomOrInsert2d(0)', singleConnection=False, name='geoms') ip.append(datatype='int', required=True, name='noParentReparentToRoot') ip.append(datatype='colorfloat3or4(0)', required=False, name='colors') ip.append(datatype='instancemat(0)', required=False, name='instanceMatrices') ip.append(datatype='dict', required=False, name='geomOptions') ip.append(datatype='geomOrInsert2d', required=False, name='parent', singleConnection=True) ip.append(datatype='boolean', required=False, name='retainPosition', defaultValue=False) self.widgetDescr['retainPosition'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'retain position:'}, } self.widgetDescr['noParentReparentToRoot'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'no parent reparent to root:'}, } code = """def doit(self, geoms, noParentReparentToRoot, colors, instanceMatrices, geomOptions, parent, retainPosition): def getRidOfInnerLists(alist): returnedList = [] for element in alist: if isinstance(element, Geom) or isinstance(element, Insert2d): returnedList.append(element) elif isinstance(element, list): returnedList += getRidOfInnerLists(element) return returnedList try: if parent is not None: if len(parent)>1: raise TypeError('parent should be a geometry or a list of lenght 1') else: parent = parent[0] except AttributeError: pass if geomOptions is not None: insert2dOpts = geomOptions.copy() geomOpts = geomOptions.copy() else: insert2dOpt = {} geomOpts = {} if colors is not None: geomOpts['inheritMaterial'] = False geomOpts['materials'] = colors if instanceMatrices: geomOpts['instanceMatrices'] = Numeric.array(instanceMatrices) else: geomOpts['instanceMatrices'] = [Numeric.identity(4).astype('f')] geoms = getRidOfInnerLists(geoms) if len(geoms) > 0: viewer = geoms[0].viewer assert viewer is not None root = viewer.rootObject for geom in geoms: #opts['redo'] = 0 #opts['tagModified'] = False if isinstance(geom, Geom): apply( geom.Set, (), geomOpts ) else: apply( geom.Set, (), insert2dOpts ) if parent is None and noParentReparentToRoot == 1: parent = root if parent is not None: viewer.ReparentObject(geom, parent, objectRetainsCurrentPosition=retainPosition) """ if code: self.setFunction(code) class QConvexHull(NetworkNode): """Compute a convex hull using the external module QConvex. The convex hull of a set of points is the smallest convex set containing the points. Based on QHull http://www.qhull.org/ Input: coords: 3-D coordinates of vertices colors: list of colors. Length of list can be 1, nb. of vertex, nb. of faces name: name of the geometry parent: parent geometry instanceMatrices: list of 4x4 transformation matrices used to draw the object tmpDir: directory used for writing temporary files Output: geom: indexed polygones geometry object """ def __init__(self, name='Convex Hull', **kw): kw['name'] = name from mglutil.util.qhullUtils import QConvex self.QH = QConvex() apply( NetworkNode.__init__, (self,), kw ) self.widgetDescr['tmpdir'] = { 'class':'NEEntry', 'master':'node', 'labelCfg':{'text':'tmp dir:'}} ip = self.inputPortsDescr ip.append(datatype='coordinates3D', name='coords') ip.append(datatype='colorsRGB', required=False, name='colors') ip.append(datatype='string', required=False, name='name') ip.append(datatype='geom', required=False, name='parent') ip.append(datatype='instancemat(0)', required=False, name='instanceMatrices') ip.append(datatype='string', required=False, name='tmpdir') self.widgetDescr['name'] = { 'class':'NEEntry', 'master':'node', 'width':8, 'initialValue':'qhull', 'labelCfg':{'text':'name: '} } op = self.outputPortsDescr op.append(datatype='geom', name='geom') code = """def doit(self, coords, colors, name, parent, instanceMatrices, tmpdir): if tmpdir is None: tmpdir = './' self.QH.computeConvex(coords, tmpdir) geom = self.QH.getGeom() if name is not None and name!=geom.name[:len(name)]: geom.name = name if geom.viewer: vi = geom.viewer vi.stopAutoRedraw() vi.RemoveObject(geom) vi.AddObject(geom, parent=geom.parent) vi.startAutoRedraw() if parent is not None: if geom.viewer: vi = geom.viewer vi.stopAutoRedraw() vi.RemoveObject(geom) vi.AddObject(geom, parent=parent) vi.startAutoRedraw() else: geom.parent = parent if colors: geom.Set(materials=colors) if instanceMatrices: mat = Numeric.array(instanceMatrices) geom.Set(instanceMatrices=mat) self.outputData(geom=geom) """ self.setFunction(code) class EllipsoidFit(NetworkNode): """Fit an ellipsoid into a list of 3-D coordinates. DejaVu geometries can be generated using the Ellipsoid node Input: list of 3-D coordinates or list of lists of coordinates. In the latter case, multiple ellipsoids are generated, one for each list of coords Output: list of Ellipsoid Objects""" def __init__(self, name='EllipsoidFit', **kw): kw['name'] = name #from geomutils import geomutilslib from geomutils import efitlib apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='list', name='coords') ip.append(datatype='float', required=False, name='cov_scale') ip.append(datatype='float', required=False, name='ell_scale') op =self.outputPortsDescr op.append(datatype='list', name='ellipsoids') code = """def doit(self, coords, cov_scale, ell_scale): if not coords: return # we handle list of lists of coordinates and list of coordinates test = coords[0][0] if not type(test) == types.ListType: coords = [coords] if cov_scale is None: cov_scale = 1.75 if ell_scale is None: ell_scale = 1.0 out = [] for coordList in coords: # create an ellipsoid structure ellipse = efitlib.ellipsoid() # create an ellipsoidInfo structure ellipseInfo = efitlib.efit_info() # compute the ellipsoid status = efitlib.fitEllipse(coordList, ell_scale, cov_scale, ellipseInfo, ellipse) #ellipse = geomutilslib.ellipsoid() #ellipseInfo = geomutilslib.efit_info() #status = geomutilslib.fitEllipse(coordList, ell_scale, cov_scale, # ellipseInfo, ellipse) if status==0: # OK out.append(ellipse) if not len(out): return self.outputData(ellipsoids=out) """ self.setFunction(code) class GyrationSphere(NetworkNode): """Calculate the center and radius of the gyration Sphere Input: coords: 3-D coordinates of vertices Output: center: radius: """ def __init__(self, name='Gyration Sphere', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) from DejaVu.Spheres import Spheres self.geom = Spheres('gyration', quality=30) ip = self.inputPortsDescr ip.append(datatype='coordinates3D', name='coords') op =self.outputPortsDescr op.append(datatype='list', name='center') op.append(datatype='float', name='radius') code = """def doit(self, coords): def gyrationSphere(points): from numpy import sum if not isinstance(points, Numeric.ArrayType): points = Numeric.array(points) # compute centroid center = sum(points, 0)/len(points) # compute dist distances (vectorized) delta = points-center rg = sqrt( sum( sum( delta*delta, 1))/float(len(points)) ) return center, rg res, rg = gyrationSphere(coords) center = [ res[0], res[1], res[2] ] self.outputData(center=center, radius=rg) """ self.setFunction(code) class GroupGeomsNE(NetworkNode): """Group DejaVu geoms.""" def __init__(self, name='Group Geoms', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.g = None code = """def doit(self, geomsIn, instanceMatrices, parentName): from DejaVu.Geom import Geom if self.g is None: self.g = Geom(name=parentName) if geomsIn is None or len(geomsIn) == 0: for g in self.g.children: g.viewer = None g.parent = None self.g.children = [] return for c in geomsIn: if not c in self.g.children: c.parent = self.g self.g.children.append(c) if instanceMatrices: mat = Numeric.array(instanceMatrices) else: mat = None if self.g is not None and mat is not None: self.g.Set(instanceMatrices=mat) self.outputData(geomsOut=self.g)\n""" if code: self.setFunction(code) self.widgetDescr['parentName'] = { 'class':'NEEntry', 'master':'node', 'width':12, 'labelCfg':{'text':'name:'}, } ip = self.inputPortsDescr ip.append(datatype='geom', required=False, singleConnection=False, name='geomsIn') ip.append(datatype='instancemat(0)', required=False, name='instanceMatrices') ip.append(datatype='string', required=False, name='parentName', defaultValue='group') op = self.outputPortsDescr op.append(datatype='geom', name='geomsOut') class Decimate(NetworkNode): try: import multires except: pass def getTriangles(self): ntri = self.model.CountTriangles() fs = Numeric.zeros( (ntri, 3), 'i') self.model.GetCurrentTriangles(fs, ntri) return fs def __init__(self, name='Color By Ramp', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.model = None self.resolution = 0 self.widgetDescr['resolution'] = { 'class':'NEDial', 'size':50, 'oneTurn':10, 'min':-20, 'max':0, 'increment':0, 'type':'int', 'showLabel':1, 'initialValue':0, 'labelCfg':{'text':'resolution'}, } ip = self.inputPortsDescr ip.append(name='vertices', datatype='array(-1,3)') ip.append(name='indices', datatype='array(-1,3)') ip.append(datatype='float', name='resolution') op = self.outputPortsDescr op.append(datatype='array(-1,3', name='indices') code = """def doit(self, vertices, indices, resolution): if resolution == 0: # nothing to do, we keep highest resolution self.resolution = resolution self.outputData(indices=indices) return if self.model is None or len(vertices)!=self.nbVertices or \ len(indices)!=self.nbIndices: self.nbVertices = len(vertices) self.nbIndices = len(indices) self.model = self.multires.ModelT(vertices, indices) if resolution==self.resolution: print 'WARNING ', resolution, self.resolution if resolution > self.resolution: for i in range(resolution-self.resolution): self.model.GoFiner() else: for i in range(self.resolution-resolution): self.model.GoCoarser() self.resolution = resolution tri = self.getTriangles() print len(tri), 'triangles' if len(tri): self.outputData(indices=tri)\n""" self.setFunction(code) class Texture1DCoords(NetworkNode): """Compute 1D texture coordinates for a list of values InputPorts: data: list of values mini: start of value range maxi: end of value range OutputPorts: texCoords: list of texture coordinates """ def __init__(self, name='1D Texture Coordinates', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw) ip = self.inputPortsDescr ip.append(datatype='list', name='data') ip.append(datatype='float', required=False, name='mini') ip.append(datatype='float', required=False, name='maxi') op = self.outputPortsDescr op.append(datatype='list', name='texCoords') code = """def doit(self, data, mini, maxi): if data is None or len(data)==0: return if mini is None: mini = min(data) if maxi is None: maxi = max(data) delta = maxi-mini data = Numeric.array(data) texc = (data-mini)/delta self.outputData(texCoords=texc) """ if code: self.setFunction(code) class Texture1D(NetworkNode): """ This node maps a 1-dimensional texture to a geometry. InputPorts: geom: DejaVu Geometry texture: 1D texture texture (comming from color map node) property: list of texture indices OutputPorts: geom: DejaVu Geometry with texture # FIXME ! textture has to be a colormap with mini and maxi The texture can be of type image (RGB or RGBA, one pixel wide) or of type Numeric.array (shape (x,1) ). The property has to be of length coords of the geometry.""" def __init__(self, name='1D Texture Mapping', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw) code = """def doit(self, geom, texture, prop): # if we get a new texture, we have to set texture and textureCoords prop = Numeric.array(prop, 'f') prop.shape = (-1,1) if self.inputPortByName['texture'].hasNewValidData(): tex = Numeric.array(Numeric.array(texture)*255).astype('B') from DejaVu.Texture import Texture t = Texture() t.Set(enable=1, image=tex) geom.Set(texture=t, textureCoords=prop, transparent='implicit') # if we only get new property values, we only have to update the # texture coords elif self.inputPortByName['prop'].hasNewValidData(): geom.Set(textureCoords=prop) self.outputData(geom=geom)\n""" if code: self.setFunction(code) ip = self.inputPortsDescr ip.append(datatype='geom', name='geom') ip.append(datatype='texture', name='texture') ip.append(datatype='None', name='prop') op = self.outputPortsDescr op.append(datatype='geom', name='geom') class Texture2D(NetworkNode): """ This node maps a 2-dimensional texture to a geometry. InputPorts: geom: DejaVu Geometry texture: 2d texture (comming from color map node) OutputPorts: geom: DejaVu Geometry with texture """ def __init__(self, name='Texture2D', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw) ip = self.inputPortsDescr ip.append(datatype='geom', name='geom') ip.append(datatype='image', name='image') ip.append(datatype='coord2(0)', required=False, name='textureCoordinates') op = self.outputPortsDescr op.append(datatype='geom', name='geom') code = """def doit(self, geom, image, textureCoordinates): if self.inputPortByName['image'].hasNewValidData(): from DejaVu.Texture import Texture lTexture = Texture(enable=1, image=image) geom.Set(texture=lTexture) if self.inputPortByName['textureCoordinates'].hasNewValidData(): geom.Set(textureCoords=textureCoordinates) if self.inputPortByName['image'].hasNewValidData() or self.inputPortByName['textureCoordinates'].hasNewValidData(): if hasattr(geom.vertexSet, 'texCoords'): geom.vertexSet.texCoords.array = \ lTexture.getTextureCoordinatesAfterResizeRatio( geom.vertexSet.texCoords.array) self.outputData(geom=geom) """ if code: self.setFunction(code) class ColorChooser(NetworkNode): """********************* DEPRECATED : USE Color Editor INSTEAD *************************** Interactively choose a color from a color wheel. Double-click the node to expand the color wheel. Right-click to open the parameter panel. Here you can change the brightness of the color, turn the alpha value on/off and choose whether a list of lists or just a list of values is output. Input Ports color:\t\tbound to a color wheel brightness:\tbound to a thumbwheel alpha:\t\tbound to a checkbutton singleCol:\tbound to a checkbutton Output Ports colors: the resulting color""" def __init__(self, name='Choose Color', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 self.w_brightness = 255 # variable used to gain some speed in doit() self.w_singleCol = 0 # used to switch between datatypes of outp.Port self.widgetDescr['color'] = { 'class':'NEColorWheel', 'master':'node', 'width':75, 'height':75, 'circles':5, 'stripes':20, 'immediate':1, 'wysiwyg':0, 'wheelPad':0, 'widgetGridCfg':{'sticky':'we', 'labelSide':'top'}, 'labelCfg':{'text':''}, } self.widgetDescr['brightness'] = { 'class':'NEThumbWheel', 'master':'ParamPanel', 'width':80, 'height':15, 'type':'int', 'wheelPad':1, 'min':0, 'max':255, 'initialValue':255, 'labelGridCfg':{'sticky':'we'}, 'widgetGridCfg':{'sticky':'we', 'columnspan':2,'labelSide':'top'}, 'labelCfg':{'text':'brightness:'}, } self.widgetDescr['alpha'] = { 'class':'NECheckButton', 'master':'ParamPanel', 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'alpha val:'}, } self.widgetDescr['singleCol'] = { 'class':'NECheckButton', 'master':'ParamPanel', 'initialValue':0, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'single col:'}, } ip = self.inputPortsDescr ip.append(datatype='None', name='color') ip.append(datatype='int', name='brightness') ip.append(datatype='int', name='alpha') ip.append(datatype='int', name='singleCol') op = self.outputPortsDescr op.append(datatype='colorsRGB', name='colors') code = """def doit(self, color, brightness, alpha, \ singleCol): if brightness != self.w_brightness: self.w_brightness = brightness w = self.inputPorts[0].widget w.widget.BuildWheel(brightness/255.0) color = w.get() if alpha == 0: color = color[:-1] if singleCol != self.w_singleCol: #self.outputPorts[0]._modified = 1 self.w_singleCol = singleCol port = self.outputPorts[0] if singleCol == 1: port.setDataType('colorRGB') else: port.setDataType('colorsRGB') if self.w_singleCol == 0: self.outputData(colors=[color]) else: self.outputData(colors=color) """ self.setFunction(code) def afterAddingToNetwork(self): NetworkNode.afterAddingToNetwork(self) # run this node so the value is output self.run() class ColorEditor(NetworkNode): """Interactively choose a color from a sophisticated widget exposing a colorwheel, a value scale, HSV entries, RGB entries and HEX(HexTriplet) entries. The color is output as a list. The widget is bound to the parameter panel of this node. Input Ports color:\t\tbound to a color wheel Output Ports color: the resulting color""" def __init__(self, name='Choose Editor', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 self.w_brightness = 255 # variable used to gain some speed in doit() self.w_singleCol = 0 # used to switch between datatypes of outp.Port self.widgetDescr['color'] = { 'class':'NEColorEditor', 'master':'ParamPanel', 'mode':'RGB', 'immediate':True, 'widgetGridCfg':{'sticky':'we', 'labelSide':'top',}, 'labelCfg':{'text':''}, } ip = self.inputPortsDescr ip.append(datatype='None', name='color') op = self.outputPortsDescr op.append(datatype='colorsRGB', name='color') code = """def doit(self, color): w = self.inputPorts[0].widget color = w.get() self.outputData(color=color) """ self.setFunction(code) def afterAddingToNetwork(self): NetworkNode.afterAddingToNetwork(self) # run this node so the value is output self.schedule_cb() class ColorMapNE(NetworkNode): """Create a user editable color map Turn a list of values into a list of colors using a colormap. You can unbind the colormap in the parampanel to re-use an already existing colormap. Input: colorMap: a ramp of colors to be used for the color map object. If omitted a ramp of 256 colors ranging from blue to red will be used values: an optionnal list of values min: the floating point value to be mapped to the first color. If omitted it defaults to the minimum value in the list. max: the flaoting point value to be mapped to the last color. If omitted it defaults to the maximum value in the list. Output: colorMap legend: if connected to a viewer, a legend can be output """ def __init__(self, name='Color Map', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 ip = self.inputPortsDescr ip.append(datatype='ColorMapType', name='colorMap') ip.append(datatype='vector', required=False, name='values') ip.append(datatype='float', required=False, name='mini') ip.append(datatype='float', required=False, name='maxi') ip.append(datatype='string', name='filename') self.widgetDescr['colorMap'] = { 'class':'NEColorMap', 'master':'ParamPanel', 'mini':None, 'maxi':None, 'labelCfg':{'text':'colormap'}, 'widgetGridCfg':{'labelSide':'top'}, } self.widgetDescr['filename'] = { 'class':'NEEntryWithFileBrowser', 'master':'ParamPanel', 'width':10, 'initialValue':'', 'filetypes':[("ColorMap",'*_map.py'), ("any file",'*.*')], 'labelCfg':{'text':'filename: '}, 'widgetGridCfg':{'labelSide':'top'} } op = self.outputPortsDescr op.append(datatype='colorfloat3or4(0)', name='mappedColors') op.append(datatype='ColorMapType', name='colorMap') op.append(datatype='geom', name='legend') code = """def doit(self, colorMap, values, mini, maxi, filename): if self.inputPortByName['values'].hasNewValidData() or \ self.inputPortByName['mini'].hasNewValidData() or \ self.inputPortByName['maxi'].hasNewValidData(): if values is not None and len(values)>0: if mini is None: mini = min(values) if maxi is None: maxi = max(values) colorMap.configure(mini=mini, maxi=maxi) p = self.inputPortByName['filename'] if p.hasNewValidData() and filename: colorMap.read(filename=filename) for c in self.outputPortByName['legend'].connections: from DejaVu.VisionInterface.DejaVuNodes import Viewer if isinstance(c.port2.node, Viewer): if colorMap.viewer != c.port2.node.vi: colorMap.configure(viewer=c.port2.node.vi) colorMap.showLegend() self.outputData(colorMap=colorMap, legend=colorMap.legend) break elif isinstance(c.port2.node, MacroOutputNode): for macroOutputPort in c.port2.node.macroNode.outputPorts: for c2 in macroOutputPort.connections: if isinstance(c2.port2.node, Viewer): if colorMap.viewer != c2.port2.node.vi: colorMap.configure(viewer=c2.port2.node.vi) colorMap.showLegend() self.outputData(colorMap=colorMap, legend=colorMap.legend) break else: #we didn't break self.outputData(colorMap=colorMap) if (values is not None) and (len(values) > 0) : lCol = colorMap.Map(values) if lCol is not None: self.outputData(mappedColors=lCol.tolist()) elif len(colorMap.ramp) == 1: self.outputData(mappedColors=colorMap.ramp[0]) else: self.outputData(mappedColors=colorMap.ramp) """ self.setFunction(code) class ColorByRamp(NetworkNode): """ DEPRECATED : USE A COLORMAP INSTEAD (and unbind the colormap in the colormap parampanel) Turn a list of values into a list of colors using a colormap. This node allows you to re-use an already existing colormap. (To use/create a new colormap, use the node colormap instead) Input Ports values: a list of values colormap: a color map (array of rgba values), typically provided by a 'Color Map' node, Defaults to an RGB ramp. Output Ports colors: a list of colors. """ def __init__(self, name='Color By Ramp', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) #self.readOnly = 1 from DejaVu.colorTool import RGBARamp, Map self.defaultMap = ColorMap(name='default', ramp=RGBARamp()) ip = self.inputPortsDescr ip.append(datatype='vector', name='values') ip.append(datatype='ColorMapType', required=False, name='colormap') op = self.outputPortsDescr op.append(datatype='colorfloat3or4(0)', name='colors') code = """def doit(self, values, colormap): # self refers to the node if colormap is None: colormap = self.defaultMap if len(values): lCol = colormap.Map(values) if lCol: self.outputData(colors=lCol.tolist()) """ self.setFunction(code) class GeomsToVRML2(NetworkNode): """This node inputs a DejaVu viewer object and converts all visible geoms in vrml2 format. The output is a list of strings which can be saved using a save text node.""" def __init__(self, name='Get VRML2', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) from DejaVu.DataOutput import OutputVRML2 self.V = OutputVRML2() code ="""def doit(self, viewer): # FIXME: expose these fields either as input ports or as GUI co = 1 # 0 or 1 sn = 0 # 0 or 1 up = 0 # 0 or 1 sq = 2 # 0, 1, 2, 3, etc cq = 10 # 3, 4, 5, 6, etc vrml2 = self.V.getVRML2(viewer.rootObject, complete=co, normals=sn, usePROTO=up, sphereQuality=sq, cylinderQuality=cq) if vrml2 is not None and len(vrml2) != 0: self.outputData(vrml2=vrml2)\n""" if code: self.setFunction(code) self.inputPortsDescr.append(datatype='viewer', name='viewer') self.outputPortsDescr.append(datatype='list', name='vrml2') class TransferFuncEditor(NetworkNode): """ Transfer Function Editor widget used to edit color and opacity lookup tables of volumetric data. This node can be connected to UT-VolRen node from vollib library. Refer to 'Help' menu of the node for more info. """ def color_cb(self, values): if self.utvolGeom: self.utvolGeom.setVolRenColors(values) else: self.need_update = True def alpha_cb(self, values): if self.utvolGeom: self.utvolGeom.setVolRenAlpha(values) else: self.need_update = True def __init__(self, name='TransferFuncEditor', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.utvolGeom = None self.need_update = False self.tm = None # instanciated when node is added to a network self.isWithdrawn = 0 self.mouseAction[''] = self.show_hide ip = self.inputPortsDescr ip.append(datatype='geom', name='utvolGeom') op = self.outputPortsDescr op.append(datatype='None', name='cmap') code = """def doit(self, utvolGeom): self.utvolGeom = utvolGeom if self.need_update: self.tm.applylut_cb() self.need_update = False """ self.setFunction(code) def show_hide(self, event=None): if self.isWithdrawn: self.tm.master.deiconify() self.isWithdrawn = 0 else: self.tm.master.withdraw() self.isWithdrawn = 1 def beforeAddingToNetwork(self, net): import Tkinter root = Tkinter.Toplevel() from mglutil.gui.BasicWidgets.Tk.tablemaker import TableManager self.tm = TableManager(None, master=root, ymaxval=255, xminval = 0, alphaCallback=self.alpha_cb, colorCallback=self.color_cb, ) self.tm.master.protocol('WM_DELETE_WINDOW', self.show_hide) def afterRemovingFromNetwork(self): NetworkNode.afterRemovingFromNetwork(self) self.network.canvas.delete(self.iconTag) if self.tm: self.tm.master.destroy() del self.tm class ScaleLegend(NetworkNode): """This node creates a line geometry for displaying a scale in a DejaVu camera. ________________________________________ | 10.00 | Input: length -- the length of the scale line tickLength -- length of the vertical tick at the end of the scale labelOffsetx -- horizontal offset of the label from the center of the line labelOffsety -- vertical offset of the label from the the line labelFont -- font for the label Output: scaleLines -- line geometry scaleLabel -- text geometry """ def __init__(self, name='ScaleLegend', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) self.v = [[0.,0.,0.], [10.,0.,0.], [0.,-1.,0.], [10.,-1.,0.]] self.f = ( (0,1), (0,2), (1,3) ) #from DejaVu.Labels import Labels from DejaVu.glfLabels import GlfLabels vt = [[5., 0, 0]] self.textGeom = GlfLabels('ScaleLabel', vertices=vt, labels=['5.0']) from DejaVu.IndexedPolylines import IndexedPolylines self.lineGeom = IndexedPolylines( 'scaleLine', vertices=self.v, faces=self.f, lineWidth=2) ip = self.inputPortsDescr ip.append(datatype='float', name='length') ip.append(datatype='float', name='tickLength') ip.append(datatype='float', name='labelOffsetx') ip.append(datatype='float', name='labelOffsety') ip.append(datatype='float', name='labelFont') self.widgetDescr['length'] = { 'class':'NEThumbWheel', 'initialValue':10, 'labelCfg':{'text':'length:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['tickLength'] = { 'class':'NEThumbWheel', 'initialValue':1, 'labelCfg':{'text':'length:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10, 'lockBMin':1, 'min':0, 'wheelPad':2 } self.widgetDescr['labelOffsetx'] = { 'class':'NEThumbWheel', 'initialValue':0., 'labelCfg':{'text':'label Offset x:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10, 'wheelPad':2 } self.widgetDescr['labelOffsety'] = { 'class':'NEThumbWheel', 'initialValue':-2., 'labelCfg':{'text':'label Offset y:'}, 'width':80, 'height':20, 'type':'float', 'oneTurn':10, 'wheelPad':2 } self.widgetDescr['labelFont'] = { 'class':'NEComboBox', 'choices':GlfLabels.fontList, #self.textGeom.BMfonts, 'entryfield_entry_width':8, 'initialValue':GlfLabels.fontList[0], 'labelCfg':{'text':'label font:'}, } op = self.outputPortsDescr op.append(datatype='geom', name='scaleLines') op.append(datatype='geom', name='scaleLabel') code = """def doit(self, length, tickLength, labelOffsetx, labelOffsety, labelFont): self.v[1][0] = length self.v[2][1] = -tickLength self.v[3][0] = length self.v[3][1] = -tickLength self.lineGeom.Set(vertices = self.v) vt = [ [length*0.5+labelOffsetx, labelOffsety, 0.] ] lab = '%.2f'%length self.textGeom.Set(vertices=vt, labels=[lab], font=labelFont) self.outputData(scaleLines=self.lineGeom, scaleLabel=self.textGeom) """ self.setFunction(code) class ReadSTL(NetworkNode): """ ************* DEPRECATED, USE GeomsFromFile instead ************** Read ASCII STL Files, convert them to IndexedPolygon geometries. Input: filename Output: a list of geometries """ def __init__(self, name='Read STL ASCII', **kw): #warnings.warn("Read STL ASCII is deprecated, use 'geoms from file' instead") kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) from DejaVu.DataInput import ReadASCIISTL self.Parser = ReadASCIISTL() self.widgetDescr['filename'] = { 'class':'NEEntryWithFileBrowser', 'master':'node', 'width':10, 'initialValue':'', 'filetypes':[('stl','*.stl'),('all','*')], 'labelCfg':{'text':'Filename: '} } ip = self.inputPortsDescr ip.append(datatype='string', name='filename') op = self.outputPortsDescr op.append(datatype='list', name='geoms') code = """def doit(self, filename): if not filename: return lines = self.Parser.read(filename) geoms = self.Parser.doit(lines) if geoms and len(geoms): self.outputData(geoms=geoms)\n""" self.setFunction(code) class ReadSTL_B(NetworkNode): """ ************* DEPRECATED, USE GeomsFromFile instead ************** Read Binary STL File, convert to IndexedPolygon geometry. Input: filename Output: a DejaVu IndexedPolygon geometry object """ def __init__(self, name='Read STL Binary', **kw): #warnings.warn("Read STL Binary is deprecated, use 'geoms from file' instead") kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) from DejaVu.DataInput import ReadBinarySTL self.Parser = ReadBinarySTL() self.widgetDescr['filename'] = { 'class':'NEEntryWithFileBrowser', 'master':'node', 'width':10, 'initialValue':'', 'filetypes':[('stl','*.stl'),('all','*')], 'labelCfg':{'text':'Filename: '} } ip = self.inputPortsDescr ip.append(datatype='string', name='filename') op = self.outputPortsDescr op.append(datatype='geom', name='geom') code = """def doit(self, filename): if not filename: return geom = None geom = self.Parser.doit(filename) if geom and geom is not None: self.outputData(geom=geom)\n""" self.setFunction(code) class ComputeRMSD(NetworkNode): """Compute RMSD Input:\tcoords: 3-D coordinates \trefCoords: 3-D coordinates Output: rmsd (float)""" def __init__(self, name='Compute RMSD', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw ) from mglutil.math.rmsd import RMSDCalculator self.RMSD = RMSDCalculator() ip = self.inputPortsDescr ip.append(datatype='coordinates3D', name='coords') ip.append(datatype='coordinates3D', required=False, name='refCoords') op =self.outputPortsDescr op.append(datatype='float', name='rmsd') code = """def doit(self, coords, refCoords): rmsd = None if refCoords: self.RMSD.setRefCoords(refCoords) if coords and self.RMSD.refCoords: rmsd = self.RMSD.computeRMSD(coords) if rmsd is not None: self.outputData(rmsd=rmsd)\n""" self.setFunction(code) class SelectAxis(NetworkNode): def __init__(self, constrkw={}, name='SelectAxis', **kw): kw['name']=name apply( NetworkNode.__init__, (self,), kw ) ip = self.inputPortsDescr ip.append(datatype='boolean', name ='x-axis') ip.append(datatype='boolean', name ='y-axis') ip.append(datatype='boolean', name ='z-axis') wd = self.widgetDescr wd['x-axis'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'x-axis'}, } wd['y-axis'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':1, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'y-axis:'}, } wd['z-axis'] = { 'class':'NECheckButton', 'master':'node', 'initialValue':0, 'labelGridCfg':{'sticky':'we'}, 'labelCfg':{'text':'z-axis:'}, } self.outputPortsDescr.append(datatype='list',name='rotationAxis') code = """def doit(self,xaxis,yaxis,zaxis): if xaxis: x_rot=1 else: x_rot=0 if yaxis: y_rot=1 else: y_rot=0 if zaxis: z_rot=1 else: z_rot=0 if not xaxis and not yaxis and not zaxis: print"no axis select for rotation! Using y axis by default" y_rot=1 rotation=[x_rot,y_rot,z_rot] self.outputData(rotationAxis=rotation) """ self.setFunction(code) class DistanceMatrix(NetworkNode): """ Compute the NxN distance between 2 sets of 3D points Input: points: 3D coordinates Output: dm: 2D Numeric array of distances """ def __init__(self, name='DM', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw) code = """def doit(self, points): import numpy.oldnumeric as Numeric l = len(points) dm = Numeric.zeros( (l,l), 'd') points = Numeric.array(points).astype('d') for i in range(l): dist = points[i] - points dist = dist*dist dm[i] = Numeric.sqrt(Numeric.sum(dist, 1)) self.outputData(dm=dm) """ if code: self.setFunction(code) self.inputPortsDescr.append({'name': 'points', 'datatype': 'coordinates3D'}) self.outputPortsDescr.append({'name': 'dm', 'datatype': 'None'}) class DDM(NetworkNode): """ Compute the difference between two distance matrices Input: points1: sequence of 3D points points2: sequence of 3D points Output ddm: 2D Numeric array of differences between distances """ def __init__(self, name='DDM', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw) code = """def doit(self, points1, points2): import numpy.oldnumeric as Numeric result = points1-points2 self.outputData(ddm=result) """ if code: self.setFunction(code) self.inputPortsDescr.append({'name': 'points1', 'datatype': 'None'}) self.inputPortsDescr.append({'name':'points2', 'datatype': 'None'}) self.outputPortsDescr.append({'name':'ddm', 'datatype': 'None'}) class ConnectedComponents0(NetworkNode): """ Node to split connected surfaces. Input ports: -geometry or a list of geometries(the first object in the list will be used as input) -name of output geometries . Index (0-n) will be attached to the name Output: - list of Indexed Polygons """ def __init__(self, name='ConnectedComponents', **kw): kw['name'] = name apply( NetworkNode.__init__, (self,), kw) self.widgetDescr['outgeomname'] = { 'class':'NEEntry', 'master':'node', 'width':10, 'labelCfg':{'text':'name:'}, 'initialValue':'polygon', } ip = self.inputPortsDescr ip.append(name='ingeoms', datatype='geom', required=True) ip.append(name='outgeomname', datatype='str', required=False) op = self.outputPortsDescr op.append(name='outgeoms', datatype='geom') code = """def doit(self, ingeoms, outgeomname): try: len(ingeoms) geometry = ingeoms[0] except: geometry = ingeoms faces = geometry.getFaces() verts = geometry.getVertices() if not outgeomname: outgeomname = 'polygons' from time import time t1 = time() fdict = {} vdict = {} #dictionary with key - vertex index, #value - list of face indices in which the vertex is found flag1 = True; flag2 = True newfaces = []; newverts = [] while flag2: for i, fs in enumerate(faces): for v in fs: if not vdict.has_key(v): vdict[v] = [i] else: vdict[v].append(i) fdict[i] = fs Vco = faces[0][:] newfaces1 = []; newverts1 = [] vertinds = {} # keys - vertex indices from the input verts list # values - new vertex indices of current surface vcount = 0 # find a surface while flag1: _Vco = [] flag1 = False # find all vertices that share the same triangles with the vertices in Vco. for vert in Vco: vfs = vdict[vert] for i in vfs: if fdict.has_key(i): flag1 = True fs = fdict.pop(i) fsnew = [] # remapped face (with new vertex idices) for v in fs: if v not in Vco: if v not in _Vco: _Vco.append(v) if not vertinds.has_key(v): vertinds[v] = vcount newverts1.append(verts[v]) fsnew.append(vcount) vcount = vcount + 1 else: fsnew.append(vertinds[v]) newfaces1.append(fsnew) # add found triangle to the list of triangles of current surface Vco = _Vco newfaces.append(newfaces1) newverts.append(newverts1) if len(fdict): faces = fdict.values() fdict = {} vdict = {} flag1 = True else: flag2 = False t2 = time() print 'time to find %d connected components : %.2f'%(len(newfaces), t2-t1) from DejaVu.IndexedPolygons import IndexedPolygons outgeoms = [] for i, newfs in enumerate(newfaces): newname = outgeomname+str(i) print 'len faces of %s is %d'%(newname, len(newfs)) obj = IndexedPolygons(newname, vertices = newverts[i], faces = newfs) outgeoms.append(obj) self.outputData(outgeoms=outgeoms) """ self.setFunction(code) from Vision.VPE import NodeLibrary vizlib = NodeLibrary('3D Visualization', '#feec70') vizlib.addNode(ColorEditor, 'Color Editor', 'Input') vizlib.addNode(ColorMapNE, 'Color Map', 'Input') vizlib.addNode(TransferFuncEditor, 'TF Editor', 'Input') vizlib.addNode(ColorChooser, 'Color Chooser', 'deprecated') vizlib.addNode(ReadSTL, 'Read STL ASCII', 'deprecated') # deprecated vizlib.addNode(ReadSTL_B, 'Read STL Binary', 'deprecated') # deprecated vizlib.addNode(readIndexedPolygon, 'readIndexedPolygon', 'deprecated') # deprecated vizlib.addNode(ColorByRamp, 'Color', 'deprecated') vizlib.addNode(ReparentGeom, 'Reparent Geom', 'deprecated') vizlib.addNode(GeomsProperties, 'geoms properties', 'Mapper') vizlib.addNode(RestoreState, 'RestoreState', 'Input') vizlib.addNode(GeomOptions, 'Set Geom Options', 'Input') vizlib.addNode(Viewer, 'Viewer', 'Output') vizlib.addNode(Redraw, 'Redraw', 'Output') vizlib.addNode(StopAutoRedraw, 'Stop Auto Redraw', 'Output') vizlib.addNode(StartAutoRedraw, 'Start Auto Redraw', 'Output') vizlib.addNode(OneRedraw, 'One Redraw', 'Output') vizlib.addNode(writeIndexedPolygon, 'writeIndexedPolygon', 'Output') vizlib.addNode(writeCurvPly, 'writeCurvPly', 'Output') vizlib.addNode(ImageViewerNode, 'ImageViewer', 'Output') from DejaVu.VisionInterface.GeometryNodes import GeomsFromFile vizlib.addNode(GeomsFromFile, 'geoms from file', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import BoxNE vizlib.addNode(BoxNE, 'box', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import StickerTextNE vizlib.addNode(StickerTextNE, 'sticker text', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import StickerImageNE vizlib.addNode(StickerImageNE, 'sticker image', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import OneTexturedQuadNE vizlib.addNode(OneTexturedQuadNE, 'oneTexturedQuad', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE vizlib.addNode(IndexedPolygonsNE, 'IndPolygons', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import IndexedPolylinesNE vizlib.addNode(IndexedPolylinesNE, 'IndPolylines', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import Cylinders vizlib.addNode(Cylinders, 'Cylinders', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import AxisNE vizlib.addNode(AxisNE, 'axis', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import Spheres vizlib.addNode(Spheres, 'Spheres', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import Points vizlib.addNode(Points, 'points', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import CrossSet vizlib.addNode(CrossSet, 'CrossSet', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import GeomContainer vizlib.addNode(GeomContainer, 'GeomContainer', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import Ellipsoids vizlib.addNode(Ellipsoids, 'Ellipsoids', 'Geometry') from DejaVu.VisionInterface.GeometryNodes import Array2DToHeightFieldGeom from DejaVu.VisionInterface.GeometryNodes import GlfLabelsNE vizlib.addNode(GlfLabelsNE, 'GlfLabels', 'Geometry') #from DejaVu.VisionInterface.GeometryNodes import GlutLabelsNE #vizlib.addNode(GlutLabelsNE, 'GlutLabels', 'Geometry') vizlib.addNode(Array2DToHeightFieldGeom, 'HeightField', 'Mapper') vizlib.addNode(Curvature, 'Curvature', 'Mapper') vizlib.addNode(SetInstances, 'Set Instances', 'Mapper') vizlib.addNode(GroupGeomsNE, 'Group Geoms', 'Mapper') vizlib.addNode(Texture2D, 'Texture2D', 'Mapper') vizlib.addNode(Texture1D, '1D Texture Mapping', 'Mapper') vizlib.addNode(Texture1DCoords, '1D Texture Coordinates', 'Mapper') vizlib.addNode(GeomsToVRML2, 'Get VRML2', 'Mapper') vizlib.addNode(GyrationSphere, 'Gyration Sphere', 'Mapper') vizlib.addNode(ComputeRMSD, 'Compute RMSD', 'Mapper') vizlib.addNode(SMFtoGeom, 'SMF to Geom', 'Mapper') vizlib.addNode(GeomtoSMF, 'Geom to SMF', 'Mapper') vizlib.addNode(ScaleLegend, 'Scale', 'Mapper') vizlib.addNode(DistanceMatrix, 'DistanceMatrix', 'Mapper') vizlib.addNode(DDM, 'DDM', 'Mapper') vizlib.addNode(PolyhedronVolumeArea, 'PolyhedronVolumeArea', 'Mapper') #vizlib.addNode(AccumPickedVertices, 'AccumPickedVert', 'Mapper') from DejaVu.VisionInterface.RotateScene import RotateScene vizlib.addNode(RotateScene, 'RotateScene', 'Macro') from DejaVu.VisionInterface.StereoSep import StereoSep vizlib.addNode(StereoSep, 'StereoSep', 'Macro') from DejaVu.VisionInterface.MapPotOnGeom import MapPotOnGeom vizlib.addNode(MapPotOnGeom, 'Map Pot On Geom', 'Macro') vizlib.addNode(getSurfaceVFN, 'getSurfaceVFN', 'Filter') vizlib.addNode(SelectGeometry, 'Choose Geom', 'Filter') vizlib.addNode(SelectMultipleGeometry, 'Choose Geoms', 'Filter') vizlib.addNode(NPR, 'NPR', 'Filter') vizlib.addNode(QslimExt, 'QslimExt', 'Filter') vizlib.addNode(RemoveDuplicatedVerticesNE, 'RemoveDupVert','Filter') vizlib.addNode(CenterOnPickedVertex, 'CenterPick','Filter') vizlib.addNode(CenterOnVertex, 'CenterVertex','Filter') try: from geomutils.geomalgorithms import removeDuplicatedVertices vizlib.addNode(removeDuplicatedVerticesC, 'RemoveDupVert(C++)','Filter') except: pass try: from QSlimLib import qslimlib vizlib.addNode(QSlim, 'QSlim', 'Filter') except: pass try: from QSlimLib import qslimlib from DejaVu.VisionInterface.GeometryNodes import DecimateGeom vizlib.addNode(DecimateGeom, 'DecimateGeom', 'Filter') except: pass if bhtreelibFound: vizlib.addNode(decimate3DPoints, 'decimate3DPoints', 'Filter') vizlib.addNode(DistFromSphereToGeom, 'DistFromSphereToGeom', 'Filter') try: import multires vizlib.addNode(Decimate, 'Polygon Reduction', 'Filter') except: pass try: #from pyefit import efit #from geomutils import geomutilslib from geomutils import efitlib vizlib.addNode(EllipsoidFit, 'EllipsoidFit', 'Mapper') except: pass try: from mglutil.util.qhullUtils import findQhullModule pth = findQhullModule('qconvex') if pth: vizlib.addNode(QConvexHull, 'Convex Hull', 'Mapper') except: pass from DejaVu.VisionInterface.GeometryNodes import ConnectedComponents vizlib.addNode(ConnectedComponents, "ConnectedComponents", "Filter") vizlib.addWidget(NEColorMap) vizlib.addWidget(NEColorWheel) vizlib.addWidget(NEColorEditor) vizlib.addWidget(NEDejaVuGeomOptions) UserLibBuild.addTypes(vizlib, 'DejaVu.VisionInterface.DejaVuTypes') try: UserLibBuild.addTypes(vizlib, 'Vision.PILTypes') except: pass mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/StereoSep.py0000644000175000017500000001525010352605172025244 0ustar debiandebian######################################################################## # # Vision Macro - Python source code - file generated by vision # Thursday 22 December 2005 12:10:49 # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header$ # # $Id$ # from NetworkEditor.macros import MacroNode class StereoSep(MacroNode): def __init__(self, constrkw={}, name='StereoSep', **kw): kw['name'] = name apply( MacroNode.__init__, (self,), kw) def beforeAddingToNetwork(self, net): MacroNode.beforeAddingToNetwork(self, net) ## loading libraries ## from DejaVu.VisionInterface.DejaVuNodes import vizlib net.editor.addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") from Vision.StandardNodes import stdlib net.editor.addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") def afterAddingToNetwork(self): from NetworkEditor.macros import MacroNode MacroNode.afterAddingToNetwork(self) ## loading libraries ## from DejaVu.VisionInterface.DejaVuNodes import vizlib from Vision.StandardNodes import stdlib ## building macro network ## StereoSep_0 = self from traceback import print_exc ## loading libraries ## from DejaVu.VisionInterface.DejaVuNodes import vizlib self.macroNetwork.getEditor().addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") from Vision.StandardNodes import stdlib self.macroNetwork.getEditor().addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") try: ## saving node input Ports ## input_Ports_1 = self.macroNetwork.ipNode input_Ports_1.move(176, 6) except: print "WARNING: failed to restore MacroInputNode named input Ports in network self.macroNetwork" print_exc() input_Ports_1=None try: ## saving node output Ports ## output_Ports_2 = self.macroNetwork.opNode output_Ports_2.move(194, 314) except: print "WARNING: failed to restore MacroOutputNode named output Ports in network self.macroNetwork" print_exc() output_Ports_2=None try: ## saving node Get cameras ## from Vision.StandardNodes import GetAttr Get_cameras_3 = GetAttr(constrkw = {}, name='Get cameras', library=stdlib) self.macroNetwork.addNode(Get_cameras_3,275,67) apply(Get_cameras_3.getInputPortByName('objects').configure, (), {'datatype': 'viewer'}) apply(Get_cameras_3.getInputPortByName('attr').widget.configure, (), {'choices': ('cameras',)}) Get_cameras_3.getInputPortByName("attr").widget.set("cameras") except: print "WARNING: failed to restore GetAttr named Get cameras in network self.macroNetwork" print_exc() Get_cameras_3=None try: ## saving node Slice Data ## from Vision.StandardNodes import SliceData Slice_Data_4 = SliceData(constrkw = {}, name='Slice Data', library=stdlib) self.macroNetwork.addNode(Slice_Data_4,301,167) apply(Slice_Data_4.getInputPortByName('data').configure, (), {'datatype': 'list'}) Slice_Data_4.getInputPortByName("_slice").widget.set("[0]") except: print "WARNING: failed to restore SliceData named Slice Data in network self.macroNetwork" print_exc() Slice_Data_4=None try: ## saving node Dial ## from Vision.StandardNodes import DialNE Dial_5 = DialNE(constrkw = {}, name='Dial', library=stdlib) self.macroNetwork.addNode(Dial_5,497,16) Dial_5.getInputPortByName("dial").widget.set(0.159390991469) except: print "WARNING: failed to restore DialNE named Dial in network self.macroNetwork" print_exc() Dial_5=None try: ## saving node Redraw ## from DejaVu.VisionInterface.DejaVuNodes import Redraw Redraw_6 = Redraw(constrkw = {}, name='Redraw', library=vizlib) self.macroNetwork.addNode(Redraw_6,199,232) except: print "WARNING: failed to restore Redraw named Redraw in network self.macroNetwork" print_exc() Redraw_6=None try: ## saving node call method ## from Vision.StandardNodes import CallMethod call_method_7 = CallMethod(constrkw = {}, name='call method', library=stdlib) self.macroNetwork.addNode(call_method_7,353,228) apply(call_method_7.addInputPort, (), {'datatype': 'float', 'width': 12, 'required': False, 'name': 'sideBySideTranslation', 'height': 12}) call_method_7.getInputPortByName("signature").widget.set("Set sideBySideTranslation") except: print "WARNING: failed to restore CallMethod named call method in network self.macroNetwork" print_exc() call_method_7=None self.macroNetwork.freeze() ## saving connections for network StereoSep ## if Get_cameras_3 is not None and Slice_Data_4 is not None: self.macroNetwork.connectNodes( Get_cameras_3, Slice_Data_4, "attrs", "data", blocking=True) if Dial_5 is not None and call_method_7 is not None: self.macroNetwork.connectNodes( Dial_5, call_method_7, "value", "sideBySideTranslation", blocking=True) if Slice_Data_4 is not None and call_method_7 is not None: self.macroNetwork.connectNodes( Slice_Data_4, call_method_7, "data", "objects", blocking=True) if call_method_7 is not None and Redraw_6 is not None: self.macroNetwork.connectNodes( call_method_7, Redraw_6, "objects", "trigger", blocking=True) input_Ports_1 = self.macroNetwork.ipNode if input_Ports_1 is not None and Redraw_6 is not None: self.macroNetwork.connectNodes( input_Ports_1, Redraw_6, "new", "viewer", blocking=True) if input_Ports_1 is not None and Get_cameras_3 is not None: self.macroNetwork.connectNodes( input_Ports_1, Get_cameras_3, "Redraw_viewer", "objects", blocking=True) self.macroNetwork.unfreeze() StereoSep_0.shrink() ## reset modifications ## StereoSep_0.resetTags() StereoSep_0.buildOriginalList() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/regression/0000755000175000017500000000000012146207763025145 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/regression/testAll.py0000644000175000017500000000064107576540304027132 0ustar debiandebianimport sys from mglutil.regression import testplus import test_dejavu harness = testplus.TestHarness( "testAll_DejaVu_ViPEr", funs = [], dependents = [test_dejavu.harness, ], ) if __name__ == '__main__': testplus.chdir() print harness sys.exit( len( harness)) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/regression/test_dejavu.py0000644000175000017500000000567710055461161030042 0ustar debiandebianimport sys from mglutil.regression import testplus ed = None withThreads = 1 # default is: multi-threading on # allow for additional user input if len(sys.argv): for myArg in sys.argv[1:]: if myArg[:11] == 'withThreads': withThreads = int(string.strip(myArg)[-1]) def startEditor(): global ed from Vision.VPE import VisualProgramingEnvironment ed = VisualProgramingEnvironment(name='Vision') ed.root.update_idletasks() ed.configure(withThreads=withThreads) def quitEditor(): ed.master.after(1000, ed.exit ) ed.mainloop() def pause(sleepTime=0.4): from time import sleep ed.master.update() sleep(sleepTime) def test_loadDejaVuLib(): from DejaVu.VisionInterface.DejaVuNodes import vizlib ed.addLibrary(vizlib) def test_allDejaVuNodes(): # test the symserv nodes libs = ed.libraries posx = 150 posy = 150 for lib in libs.keys(): ed.ModulePages.selectpage(lib) ed.root.update_idletasks() for cat in libs[lib].libraryDescr.keys(): for node in libs[lib].libraryDescr[cat]['nodes']: klass = node.nodeClass kw = node.kw args = node.args netNode = apply( klass, args, kw ) print 'testing: '+node.name # begin node test #add node to canvas ed.currentNetwork.addNode(netNode,posx,posy) # show widget in node if available: widgetsInNode = netNode.getWidgetsForMaster('Node') if len(widgetsInNode.items()) is not None: for port,widget in widgetsInNode.items(): netNode.createOneWidget(port) ed.root.update_idletasks() # and then hide it for port,widget in widgetsInNode.items(): netNode.hideInNodeWidget(port.widget) ed.root.update_idletasks() # show widgets in param panel if available: widgetsInPanel = netNode.getWidgetsForMaster('ParamPanel') if len(widgetsInPanel.items()): netNode.paramPanel.show() ed.root.update_idletasks() #and then hide it netNode.paramPanel.hide() ed.root.update_idletasks() # and now delete the node ed.currentNetwork.deleteNodes([netNode]) ed.root.update_idletasks() print 'passed: '+node.name # end node test harness = testplus.TestHarness( "dejavu", connect = (startEditor, (), {}), funs = testplus.testcollect( globals()), disconnect = quitEditor ) if __name__ == '__main__': testplus.chdir() print harness sys.exit( len( harness)) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/0000755000175000017500000000000012146207763024067 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/Data/0000755000175000017500000000000012146207763024740 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/Data/parentsAndMacro_net.py0000644000175000017500000004206012102057401031223 0ustar debiandebian######################################################################## # # Vision Network - Python source code - file generated by vision # Wednesday 10 October 2007 14:20:02 # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header$ # # $Id$ # from traceback import print_exc ## loading libraries ## from DejaVu.VisionInterface.DejaVuNodes import vizlib masterNet.getEditor().addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") from Volume.VisionInterface.VolumeNodes import vollib masterNet.getEditor().addLibraryInstance(vollib,"Volume.VisionInterface.VolumeNodes", "vollib") try: ## saving node UT-Isocontour ## from Volume.VisionInterface.VolumeNodes import Isocontour UT_Isocontour_0 = Isocontour(constrkw = {}, name='UT-Isocontour', library=vollib) masterNet.addNode(UT_Isocontour_0,281,22) apply(UT_Isocontour_0.inputPortByName['isovalue'].widget.configure, (), {'max': 1.0, 'min': 0.0}) UT_Isocontour_0.inputPortByName['isovalue'].widget.set(1.0, run=False) except: print "WARNING: failed to restore Isocontour named UT-Isocontour in network masterNet" print_exc() UT_Isocontour_0=None try: ## saving node ReadBinaryRawiv ## from Volume.VisionInterface.VolumeNodes import ReadRawivfile ReadBinaryRawiv_1 = ReadRawivfile(constrkw = {}, name='ReadBinaryRawiv', library=vollib) masterNet.addNode(ReadBinaryRawiv_1,4,7) ReadBinaryRawiv_1.inputPortByName['filename'].widget.set("../../../Volume/Tests/Data/ct_head.rawiv", run=False) apply(ReadBinaryRawiv_1.configure, (), {'expanded': True}) except: print "WARNING: failed to restore ReadRawivfile named ReadBinaryRawiv in network masterNet" print_exc() ReadBinaryRawiv_1=None try: ## saving node indpol1 ## from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE indpol1_2 = IndexedPolygonsNE(constrkw = {}, name='indpol1') masterNet.addNode(indpol1_2,21,125) indpol1_2.inputPortByName['name'].widget.set("indpol1", run=False) apply(indpol1_2.configure, (), {'expanded': True}) except: print "WARNING: failed to restore IndexedPolygonsNE named indpol1 in network masterNet" print_exc() indpol1_2=None try: ## saving node indpol2 ## from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE indpol2_3 = IndexedPolygonsNE(constrkw = {}, name='indpol2') masterNet.addNode(indpol2_3,382,204) indpol2_3.inputPortByName['name'].widget.set("indpol2", run=False) apply(indpol2_3.configure, (), {'expanded': True}) except: print "WARNING: failed to restore IndexedPolygonsNE named indpol2 in network masterNet" print_exc() indpol2_3=None try: ## saving node Viewer ## from DejaVu.VisionInterface.DejaVuNodes import Viewer Viewer_4 = Viewer(constrkw = {}, name='Viewer') masterNet.addNode(Viewer_4,233,250) ## ## Saving State for Viewer Viewer_4.vi.TransformRootOnly(0) ## ## Light Model ## End Light Model ## Light sources ## End Light sources 7 ## Cameras ## Camera Number 0 state = {'color': (0.0, 0.0, 0.0, 1.0), 'd2off': 1, 'height': 400, 'lookAt': [0.0, 0.0, 0.0], 'rootx': 1291, 'pivot': [0.0, 0.0, 0.0], 'translation': [0.0, 0.0, 0.0], 'sideBySideTranslation': 0.0, 'fov': 40.0, 'scale': [1.0, 1.0, 1.0], 'stereoMode': 'MONO', 'width': 400, 'sideBySideRotAngle': 3.0, 'boundingbox': 0, 'projectionType': 0, 'contours': False, 'd2cutL': 150, 'direction': [0.0, 0.0, -30.0], 'd2cutH': 255, 'far': 50.0, 'd1off': 4, 'lookFrom': [0.0, 0.0, 30.0], 'd1cutH': 60, 'antialiased': 0, 'rotation': [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0], 'd1ramp': [0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 7.0, 9.0, 12.0, 14.0, 17.0, 19.0, 22.0, 24.0, 27.0, 29.0, 32.0, 34.0, 37.0, 44.0, 51.0, 57.0, 64.0, 71.0, 78.0, 84.0, 91.0, 98.0, 105.0, 111.0, 118.0, 125.0, 126.0, 128.0, 129.0, 130.0, 132.0, 133.0, 135.0, 136.0, 137.0, 139.0, 140.0, 141.0, 143.0, 144.0, 145.0, 147.0, 148.0, 149.0, 151.0, 152.0, 154.0, 155.0, 156.0, 158.0, 159.0, 160.0, 162.0, 163.0, 164.0, 166.0, 167.0, 168.0, 170.0, 171.0, 173.0, 174.0, 175.0, 177.0, 178.0, 179.0, 181.0, 182.0, 183.0, 185.0, 186.0, 187.0, 189.0, 190.0, 192.0, 193.0, 194.0, 196.0, 197.0, 197.0, 198.0, 198.0, 199.0, 199.0, 199.0, 200.0, 200.0, 200.0, 201.0, 201.0, 202.0, 202.0, 202.0, 203.0, 203.0, 204.0, 204.0, 204.0, 205.0, 205.0, 205.0, 206.0, 206.0, 207.0, 207.0, 207.0, 208.0, 208.0, 209.0, 209.0, 209.0, 210.0, 210.0, 210.0, 211.0, 211.0, 212.0, 212.0, 212.0, 213.0, 213.0, 214.0, 214.0, 214.0, 215.0, 215.0, 215.0, 216.0, 216.0, 217.0, 217.0, 217.0, 218.0, 218.0, 219.0, 219.0, 219.0, 220.0, 220.0, 220.0, 221.0, 221.0, 222.0, 222.0, 222.0, 223.0, 223.0, 224.0, 224.0, 224.0, 225.0, 225.0, 225.0, 226.0, 226.0, 227.0, 227.0, 227.0, 228.0, 228.0, 228.0, 229.0, 229.0, 230.0, 230.0, 230.0, 231.0, 231.0, 232.0, 232.0, 232.0, 233.0, 233.0, 233.0, 234.0, 234.0, 235.0, 235.0, 235.0, 236.0, 236.0, 237.0, 237.0, 237.0, 238.0, 238.0, 238.0, 239.0, 239.0, 240.0, 240.0, 240.0, 241.0, 241.0, 242.0, 242.0, 242.0, 243.0, 243.0, 243.0, 244.0, 244.0, 245.0, 245.0, 245.0, 246.0, 246.0, 247.0, 247.0, 247.0, 248.0, 248.0, 248.0, 249.0, 249.0, 250.0, 250.0, 250.0, 251.0, 251.0, 252.0, 252.0, 252.0, 253.0, 253.0, 253.0, 254.0, 254.0, 255.0, 255.0], 'suspendRedraw': False, 'd1cutL': 0, 'd2scale': 0.0, 'near': 0.10000000000000001, 'drawThumbnail': False, 'rooty': 68, 'd1scale': 0.012999999999999999} apply(Viewer_4.vi.cameras[0].Set, (), state) state = {'end': 40, 'density': 0.10000000000000001, 'color': (0.0, 0.0, 0.0, 1.0), 'enabled': False, 'start': 25, 'mode': 'GL_LINEAR'} apply(Viewer_4.vi.cameras[0].fog.Set, (), state) ## End Cameras ## Clipping planes ## End Clipping planes ## Root object ## End Root Object ## Material for root if Viewer_4.vi.rootObject: pass ## needed in case there no modif ## End Materials for root ## Clipping Planes for root if Viewer_4.vi.rootObject: Viewer_4.vi.rootObject.clipP = [] Viewer_4.vi.rootObject.clipPI = [] pass ## needed in case there no modif ## End Clipping Planes for root except: print "WARNING: failed to restore Viewer named Viewer in network masterNet" print_exc() Viewer_4=None try: ## saving node macro0 ## from NetworkEditor.macros import MacroNode macro0_5 = MacroNode(name='macro0') masterNet.addNode(macro0_5, 258, 162) from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE _2_8 = IndexedPolygonsNE(constrkw = {}, name='2', library=vizlib) macro0_5.macroNetwork.addNode(_2_8,212,133) _2_8.inputPortByName['name'].widget.set("2", run=False) apply(_2_8.configure, (), {'expanded': True}) ## saving connections for network macro0 ## macro0_5.macroNetwork.freeze() input_Ports_6 = macro0_5.macroNetwork.ipNode if input_Ports_6 is not None and _2_8 is not None: try: macro0_5.macroNetwork.connectNodes( input_Ports_6, _2_8, "new", "coords", blocking=True) except: print "WARNING: failed to restore connection between input_Ports_6 and _2_8 in network macro0_5.macroNetwork" if input_Ports_6 is not None and _2_8 is not None: try: macro0_5.macroNetwork.connectNodes( input_Ports_6, _2_8, "new", "indices", blocking=True) except: print "WARNING: failed to restore connection between input_Ports_6 and _2_8 in network macro0_5.macroNetwork" if input_Ports_6 is not None and _2_8 is not None: try: macro0_5.macroNetwork.connectNodes( input_Ports_6, _2_8, "new", "vnormals", blocking=True) except: print "WARNING: failed to restore connection between input_Ports_6 and _2_8 in network macro0_5.macroNetwork" if input_Ports_6 is not None and _2_8 is not None: try: macro0_5.macroNetwork.connectNodes( input_Ports_6, _2_8, "new", "parent", blocking=True) except: print "WARNING: failed to restore connection between input_Ports_6 and _2_8 in network macro0_5.macroNetwork" output_Ports_7 = macro0_5.macroNetwork.opNode if _2_8 is not None and output_Ports_7 is not None: try: macro0_5.macroNetwork.connectNodes( _2_8, output_Ports_7, "indexedPolygons", "new", blocking=True) except: print "WARNING: failed to restore connection between _2_8 and output_Ports_7 in network macro0_5.macroNetwork" macro0_5.macroNetwork.unfreeze() macro0_5.shrink() except: print "WARNING: failed to restore MacroNode named macro0 in network masterNet" print_exc() macro0_5=None masterNet.run() masterNet.freeze() ## saving connections for network parentsAndMacro ## if ReadBinaryRawiv_1 is not None and UT_Isocontour_0 is not None: try: masterNet.connectNodes( ReadBinaryRawiv_1, UT_Isocontour_0, "grid", "grid3D", blocking=True) except: print "WARNING: failed to restore connection between ReadBinaryRawiv_1 and UT_Isocontour_0 in network masterNet" if UT_Isocontour_0 is not None and indpol1_2 is not None: try: masterNet.connectNodes( UT_Isocontour_0, indpol1_2, "coords", "coords", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and indpol1_2 in network masterNet" if UT_Isocontour_0 is not None and indpol1_2 is not None: try: masterNet.connectNodes( UT_Isocontour_0, indpol1_2, "indices", "indices", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and indpol1_2 in network masterNet" if UT_Isocontour_0 is not None and indpol1_2 is not None: try: masterNet.connectNodes( UT_Isocontour_0, indpol1_2, "normals", "vnormals", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and indpol1_2 in network masterNet" if UT_Isocontour_0 is not None and indpol2_3 is not None: try: masterNet.connectNodes( UT_Isocontour_0, indpol2_3, "indices", "indices", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and indpol2_3 in network masterNet" if UT_Isocontour_0 is not None and indpol2_3 is not None: try: masterNet.connectNodes( UT_Isocontour_0, indpol2_3, "coords", "coords", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and indpol2_3 in network masterNet" if indpol2_3 is not None and Viewer_4 is not None: try: masterNet.connectNodes( indpol2_3, Viewer_4, "indexedPolygons", "geometries", blocking=True) except: print "WARNING: failed to restore connection between indpol2_3 and Viewer_4 in network masterNet" if UT_Isocontour_0 is not None and indpol2_3 is not None: try: masterNet.connectNodes( UT_Isocontour_0, indpol2_3, "normals", "vnormals", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and indpol2_3 in network masterNet" macro0_5 = masterNet.nodes[5] if UT_Isocontour_0 is not None and macro0_5 is not None: try: masterNet.connectNodes( UT_Isocontour_0, macro0_5, "coords", "2_coords", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and macro0_5 in network masterNet" if UT_Isocontour_0 is not None and macro0_5 is not None: try: masterNet.connectNodes( UT_Isocontour_0, macro0_5, "indices", "2_indices", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and macro0_5 in network masterNet" if UT_Isocontour_0 is not None and macro0_5 is not None: try: masterNet.connectNodes( UT_Isocontour_0, macro0_5, "normals", "2_vnormals", blocking=True) except: print "WARNING: failed to restore connection between UT_Isocontour_0 and macro0_5 in network masterNet" if macro0_5 is not None and Viewer_4 is not None: try: masterNet.connectNodes( macro0_5, Viewer_4, "2_indexedPolygons", "geometries", blocking=True) except: print "WARNING: failed to restore connection between macro0_5 and Viewer_4 in network masterNet" if indpol1_2 is not None and Viewer_4 is not None: try: masterNet.connectNodes( indpol1_2, Viewer_4, "indexedPolygons", "geometries", blocking=True) except: print "WARNING: failed to restore connection between indpol1_2 and Viewer_4 in network masterNet" if indpol1_2 is not None and macro0_5 is not None: try: masterNet.connectNodes( indpol1_2, macro0_5, "indexedPolygons", "2_parent", blocking=True) except: print "WARNING: failed to restore connection between indpol1_2 and macro0_5 in network masterNet" if macro0_5 is not None and indpol2_3 is not None: try: masterNet.connectNodes( macro0_5, indpol2_3, "2_indexedPolygons", "parent", blocking=True) except: print "WARNING: failed to restore connection between macro0_5 and indpol2_3 in network masterNet" masterNet.unfreeze() def loadSavedStates_Viewer_4(self=Viewer_4, event=None): ## ## Saving State for objects in Viewer ## ## End Object root ## ## Saving State for Viewer self.vi.TransformRootOnly(0) ## ## Light Model ## End Light Model ## Light sources ## End Light sources 7 ## Cameras ## Camera Number 0 state = {'color': (0.0, 0.0, 0.0, 1.0), 'd2off': 1, 'height': 400, 'lookAt': [0.0, 0.0, 0.0], 'pivot': [0.0, 0.0, 0.0], 'translation': [0.0, 0.0, 0.0], 'sideBySideTranslation': 0.0, 'fov': 40.0, 'scale': [1.0, 1.0, 1.0], 'stereoMode': 'MONO', 'width': 400, 'sideBySideRotAngle': 3.0, 'boundingbox': 0, 'projectionType': 0, 'contours': False, 'd2cutL': 150, 'direction': [0.0, 0.0, -30.0], 'd2cutH': 255, 'far': 50.0, 'd1off': 4, 'lookFrom': [0.0, 0.0, 30.0], 'd1cutH': 60, 'antialiased': 0, 'rotation': [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0], 'd1ramp': [0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 7.0, 9.0, 12.0, 14.0, 17.0, 19.0, 22.0, 24.0, 27.0, 29.0, 32.0, 34.0, 37.0, 44.0, 51.0, 57.0, 64.0, 71.0, 78.0, 84.0, 91.0, 98.0, 105.0, 111.0, 118.0, 125.0, 126.0, 128.0, 129.0, 130.0, 132.0, 133.0, 135.0, 136.0, 137.0, 139.0, 140.0, 141.0, 143.0, 144.0, 145.0, 147.0, 148.0, 149.0, 151.0, 152.0, 154.0, 155.0, 156.0, 158.0, 159.0, 160.0, 162.0, 163.0, 164.0, 166.0, 167.0, 168.0, 170.0, 171.0, 173.0, 174.0, 175.0, 177.0, 178.0, 179.0, 181.0, 182.0, 183.0, 185.0, 186.0, 187.0, 189.0, 190.0, 192.0, 193.0, 194.0, 196.0, 197.0, 197.0, 198.0, 198.0, 199.0, 199.0, 199.0, 200.0, 200.0, 200.0, 201.0, 201.0, 202.0, 202.0, 202.0, 203.0, 203.0, 204.0, 204.0, 204.0, 205.0, 205.0, 205.0, 206.0, 206.0, 207.0, 207.0, 207.0, 208.0, 208.0, 209.0, 209.0, 209.0, 210.0, 210.0, 210.0, 211.0, 211.0, 212.0, 212.0, 212.0, 213.0, 213.0, 214.0, 214.0, 214.0, 215.0, 215.0, 215.0, 216.0, 216.0, 217.0, 217.0, 217.0, 218.0, 218.0, 219.0, 219.0, 219.0, 220.0, 220.0, 220.0, 221.0, 221.0, 222.0, 222.0, 222.0, 223.0, 223.0, 224.0, 224.0, 224.0, 225.0, 225.0, 225.0, 226.0, 226.0, 227.0, 227.0, 227.0, 228.0, 228.0, 228.0, 229.0, 229.0, 230.0, 230.0, 230.0, 231.0, 231.0, 232.0, 232.0, 232.0, 233.0, 233.0, 233.0, 234.0, 234.0, 235.0, 235.0, 235.0, 236.0, 236.0, 237.0, 237.0, 237.0, 238.0, 238.0, 238.0, 239.0, 239.0, 240.0, 240.0, 240.0, 241.0, 241.0, 242.0, 242.0, 242.0, 243.0, 243.0, 243.0, 244.0, 244.0, 245.0, 245.0, 245.0, 246.0, 246.0, 247.0, 247.0, 247.0, 248.0, 248.0, 248.0, 249.0, 249.0, 250.0, 250.0, 250.0, 251.0, 251.0, 252.0, 252.0, 252.0, 253.0, 253.0, 253.0, 254.0, 254.0, 255.0, 255.0], 'suspendRedraw': False, 'd1cutL': 0, 'd2scale': 0.0, 'near': 0.10000000000000001, 'drawThumbnail': False, 'd1scale': 0.012999999999999999} apply(self.vi.cameras[0].Set, (), state) state = {'end': 40, 'density': 0.10000000000000001, 'color': (0.0, 0.0, 0.0, 1.0), 'enabled': False, 'start': 25, 'mode': 'GL_LINEAR'} apply(self.vi.cameras[0].fog.Set, (), state) ## End Cameras ## Clipping planes ## End Clipping planes ## Root object ## End Root Object ## Material for root if self.vi.rootObject: pass ## needed in case there no modif ## End Materials for root ## Clipping Planes for root if self.vi.rootObject: self.vi.rootObject.clipP = [] self.vi.rootObject.clipPI = [] pass ## needed in case there no modif ## End Clipping Planes for root Viewer_4.restoreStates_cb = Viewer_4.restoreStatesFirstRun = loadSavedStates_Viewer_4 Viewer_4.menu.add_separator() Viewer_4.menu.add_command(label='Restore states', command=Viewer_4.restoreStates_cb) #masterNet.run() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/Data/parenting1_net.py0000644000175000017500000001362510363552203030226 0ustar debiandebian######################################################################## # # Vision Network - Python source code - file generated by vision # Wednesday 14 December 2005 09:15:47 # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/VisionInterface/Tests/Data/parenting1_net.py,v 1.3 2006/01/18 23:51:31 vareille Exp $ # # $Id: parenting1_net.py,v 1.3 2006/01/18 23:51:31 vareille Exp $ # from traceback import print_exc ## loading libraries ## from Vision.StandardNodes import stdlib masterNet.getEditor().addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") from DejaVu.VisionInterface.DejaVuNodes import vizlib masterNet.getEditor().addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") try: ## saving node Viewer ## from DejaVu.VisionInterface.DejaVuNodes import Viewer Viewer_0 = Viewer(constrkw = {}, name='Viewer', library=vizlib) masterNet.addNode(Viewer_0,231,263) except: print "WARNING: failed to restore Viewer named Viewer in network masterNet" print_exc() node0=None try: ## saving node polygons2 ## from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE polygons2_1 = IndexedPolygonsNE(constrkw = {}, name='polygons2', library=vizlib) masterNet.addNode(polygons2_1,12,178) apply(polygons2_1.getInputPortByName('name').widget.configure, (), {'choices': ['polygons2']}) polygons2_1.getInputPortByName("name").widget.set("polygons2") apply(polygons2_1.configure, (), {'expanded': True}) except: print "WARNING: failed to restore IndexedPolygonsNE named polygons2 in network masterNet" print_exc() node1=None try: ## saving node polygons ## from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE polygons_2 = IndexedPolygonsNE(constrkw = {}, name='polygons', library=vizlib) masterNet.addNode(polygons_2,339,98) apply(polygons_2.getInputPortByName('name').widget.configure, (), {'choices': ['polygons']}) polygons_2.getInputPortByName("name").widget.set("polygons") apply(polygons_2.configure, (), {'expanded': True}) except: print "WARNING: failed to restore IndexedPolygonsNE named polygons in network masterNet" print_exc() node2=None try: ## saving node polygons1 ## from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE polygons1_3 = IndexedPolygonsNE(constrkw = {}, name='polygons1', library=vizlib) masterNet.addNode(polygons1_3,187,147) apply(polygons1_3.getInputPortByName('name').widget.configure, (), {'choices': ['polygons1']}) polygons1_3.getInputPortByName("name").widget.set("polygons1") apply(polygons1_3.configure, (), {'expanded': True}) except: print "WARNING: failed to restore IndexedPolygonsNE named polygons1 in network masterNet" print_exc() node3=None try: ## saving node polygons1 ## from DejaVu.VisionInterface.GeometryNodes import IndexedPolygonsNE polygons1_4 = IndexedPolygonsNE(constrkw = {}, name='polygons1', library=vizlib) masterNet.addNode(polygons1_4,429,213) apply(polygons1_4.getInputPortByName('name').widget.configure, (), {'choices': ['polygons1']}) polygons1_4.getInputPortByName("name").widget.set("polygons1") apply(polygons1_4.configure, (), {'expanded': True}) except: print "WARNING: failed to restore IndexedPolygonsNE named polygons1 in network masterNet" print_exc() node4=None try: ## saving node [[0,1,2]] ## from Vision.StandardNodes import Eval __0_1_2___5 = Eval(constrkw = {}, name='[[0,1,2]]', library=stdlib) masterNet.addNode(__0_1_2___5,263,10) __0_1_2___5.getInputPortByName("command").widget.set("[[0,1,2]]") apply(__0_1_2___5.configure, (), {'expanded': True}) except: print "WARNING: failed to restore Eval named [[0,1,2]] in network masterNet" print_exc() node5=None try: ## saving node [[0,0,0],[1,0,0... ## from Vision.StandardNodes import Eval __0_0_0___1_0_0____6 = Eval(constrkw = {}, name='[[0,0,0],[1,0,0...', library=stdlib) masterNet.addNode(__0_0_0___1_0_0____6,23,30) __0_0_0___1_0_0____6.getInputPortByName("command").widget.set("[[0,0,0],[1,0,0],[0,1,0.]]") apply(__0_0_0___1_0_0____6.configure, (), {'expanded': True}) except: print "WARNING: failed to restore Eval named [[0,0,0],[1,0,0... in network masterNet" print_exc() node6=None masterNet.freeze() ## saving connections for network parenting1 ## if __0_1_2___5 is not None and polygons2_1 is not None: masterNet.connectNodes( __0_1_2___5, polygons2_1, "result", "indices", blocking=True) if __0_1_2___5 is not None and polygons1_3 is not None: masterNet.connectNodes( __0_1_2___5, polygons1_3, "result", "indices", blocking=True) if __0_1_2___5 is not None and polygons_2 is not None: masterNet.connectNodes( __0_1_2___5, polygons_2, "result", "indices", blocking=True) if __0_1_2___5 is not None and polygons1_4 is not None: masterNet.connectNodes( __0_1_2___5, polygons1_4, "result", "indices", blocking=True) if __0_0_0___1_0_0____6 is not None and polygons2_1 is not None: masterNet.connectNodes( __0_0_0___1_0_0____6, polygons2_1, "result", "coords", blocking=True) if __0_0_0___1_0_0____6 is not None and polygons1_3 is not None: masterNet.connectNodes( __0_0_0___1_0_0____6, polygons1_3, "result", "coords", blocking=True) if __0_0_0___1_0_0____6 is not None and polygons_2 is not None: masterNet.connectNodes( __0_0_0___1_0_0____6, polygons_2, "result", "coords", blocking=True) if __0_0_0___1_0_0____6 is not None and polygons1_4 is not None: masterNet.connectNodes( __0_0_0___1_0_0____6, polygons1_4, "result", "coords", blocking=True) masterNet.unfreeze() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/Data/gyration_net.py0000644000175000017500000000714011011103002027761 0ustar debiandebian######################################################################## # # Vision Network - Python source code - file generated by vision # Tuesday 20 December 2005 14:00:56 # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header$ # # $Id$ # from traceback import print_exc ## loading libraries ## from Vision.StandardNodes import stdlib masterNet.getEditor().addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") from DejaVu.VisionInterface.DejaVuNodes import vizlib masterNet.getEditor().addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") try: ## saving node Viewer ## from DejaVu.VisionInterface.DejaVuNodes import Viewer Viewer_0 = Viewer(constrkw = {}, name='Viewer', library=vizlib) masterNet.addNode(Viewer_0,29,279) except: print "WARNING: failed to restore Viewer named Viewer in network masterNet" print_exc() node0=None try: ## saving node [[0,0,0],[1,0,0... ## from Vision.StandardNodes import Eval __0_0_0___1_0_0____1 = Eval(constrkw = {}, name='[[0,0,0],[3,0,0...', library=stdlib) masterNet.addNode(__0_0_0___1_0_0____1,15,8) __0_0_0___1_0_0____1.getInputPortByName("command").widget.set("[[0,0,0],[3,0,0],[0,3,0.]]") apply(__0_0_0___1_0_0____1.configure, (), {'expanded': True}) except: print "WARNING: failed to restore Eval named [[0,0,0],[3,0,0... in network masterNet" print_exc() node1=None try: ## saving node Spheres ## from DejaVu.VisionInterface.GeometryNodes import Spheres Spheres_2 = Spheres(constrkw = {}, name='spheres', library=vizlib) masterNet.addNode(Spheres_2,73,174) Spheres_2.getInputPortByName('radius').unbindWidget() apply(Spheres_2.configure, (), {'expanded': True}) except: print "WARNING: failed to restore Spheres named Spheres in network masterNet" print_exc() node2=None try: ## saving node Gyration Sphere ## from DejaVu.VisionInterface.DejaVuNodes import GyrationSphere Gyration_Sphere_3 = GyrationSphere(constrkw = {}, name='Gyration Sphere', library=vizlib) masterNet.addNode(Gyration_Sphere_3,91,84) except: print "WARNING: failed to restore GyrationSphere named Gyration Sphere in network masterNet" print_exc() node3=None try: ## saving node [[3,3,3]] ## from Vision.StandardNodes import Eval __3_3_3___4 = Eval(constrkw = {}, name='[[-3,-3,-3]]', library=stdlib) masterNet.addNode(__3_3_3___4,281,52) __3_3_3___4.getInputPortByName("command").widget.set("[[-3,-3,-3]]") apply(__3_3_3___4.configure, (), {'expanded': True}) except: print "WARNING: failed to restore Eval named [[-3,-3,-3]] in network masterNet" print_exc() node4=None masterNet.freeze() ## saving connections for network gyration ## if Gyration_Sphere_3 is not None and Spheres_2 is not None: masterNet.connectNodes( Gyration_Sphere_3, Spheres_2, "center", "coords", blocking=True) if Gyration_Sphere_3 is not None and Spheres_2 is not None: masterNet.connectNodes( Gyration_Sphere_3, Spheres_2, "radius", "radius", blocking=True) if __0_0_0___1_0_0____1 is not None and Gyration_Sphere_3 is not None: masterNet.connectNodes( __0_0_0___1_0_0____1, Gyration_Sphere_3, "result", "coords", blocking=True) if Spheres_2 is not None and Viewer_0 is not None: masterNet.connectNodes( Spheres_2, Viewer_0, "spheres", "geometries", blocking=True) masterNet.unfreeze() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/test_viznodes.py0000644000175000017500000000757011160007452027336 0ustar debiandebian######################################################################### # # Date: Aug 2004 Authors: Daniel Stoffler # # stoffler@scripps.edu # # Copyright: Daniel Stoffler, and TSRI # ######################################################################### import sys from time import sleep from Vision.VPE import VisualProgramingEnvironment from DejaVu.VisionInterface.DejaVuNodes import vizlib, Spheres, Viewer ed = None def setUp(): global ed ed = VisualProgramingEnvironment(name='test 3-D Visualization nodes', withShell=0, visibleWidth=400, visibleHeight=300) ed.root.update() ed.configure(withThreads=0) ed.addLibraryInstance( vizlib, "DejaVu.VisionInterface.DejaVuNodes", "vizlib") ed.root.update() def tearDown(): ed.exit_cb() import gc gc.collect() ########################## ## Helper methods ########################## def pause(sleepTime=0.1): from time import sleep ed.master.update() sleep(sleepTime) ########################## ## Tests ########################## def test_01_SphereNode(): """Test the Spheres node: create a sphere geom, add it to a viewer""" from Vision.StandardNodes import stdlib masterNet = ed.currentNetwork ed.addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") ed.root.update() ## adding node Eval to generate 1 center for a sphere from Vision.StandardNodes import Eval node1 = Eval(constrkw = {}, name='Sphere Center', library=stdlib) masterNet.addNode(node1,233,10) node1.inputPorts[0].widget.set("[(0.,0,0)]",0) apply(node1.configure, (), {'expanded': True}) ## adding node Sphere node2 = Spheres(constrkw = {}, name='Sphere', library=vizlib) masterNet.addNode(node2,29,100) node2.inputPortByName['radius'].widget.set(9.5, 0) # sphere radius node2.inputPortByName['quality'].widget.set(5, 0) # sphere quality node2.inputPortByName['name'].widget.set("testSphere") # sphere name apply(node2.configure, (), {'expanded': True}) ## adding a node Viewer node3 = Viewer(constrkw = {}, name='Viewer', library=vizlib) masterNet.addNode(node3,264,262) ## now connect the nodes masterNet.connectNodes( node1, node2, "result", "coords", blocking=True) masterNet.connectNodes( node2, node3, "spheres", "geometries", blocking=True) ## now run the network pause() masterNet.run() pause() ## finally, do some tests data = node2.outputPorts[0].data # the sphere geom # is this a Spheres geom? assert data is not None, "Expected data, got %s"%data from DejaVu.Geom import Geom assert isinstance(data, Geom), "Expected %s, got %s"%( Geom, data.__class__) # is its name 'testSphere'? assert data.name == "testSphere",\ "Expected 'testSphere', got '%s'"%data.name # is the radius set correctly? assert data.radius == 9.5, "Expected 9.5, got %s"%data.radius # does it have oneRadius set to True? assert data.oneRadius == True, "Expected True, got %s"%data.oneRadius # is the quality set correctly? assert data.quality == 5, "Expected 5, got %s"%data.quality # was the center set correctly? array = data.vertexSet.vertices.array[0] assert array[0] == array[1] == array[2] == 0.0,\ "Expected 0.0, arry0: %s, arry1: %s, arr2: %s"%( array[0], array[1], array[2]) # was it correctly added to the viewer? assert data in node3.vi.rootObject.children,\ "data is: %s\nchildren are: %s"%(data, node3.vi.rootObject.children) # does it have a parent? assert data.parent is not None, "data.parent is: %s"%data.parent # does it know about the viewer? assert data.viewer is not None, "data.viewer is: %s"%data.viewer # is it visible? assert data.visible == True, "Expected True, got %s"%data.visible mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/test_gyration.py0000644000175000017500000001347211355461516027342 0ustar debiandebian######################################################################### # # Date: DEc 2005 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # Copyright: Guillaume Vareille, Michel Sanner, and TSRI # ############################################################################# # # $Header$ # # $Id$ # import sys ed = None def setUp(): global ed from Vision.VPE import VisualProgramingEnvironment ed = VisualProgramingEnvironment(name='Vision', withShell=0,) from DejaVu.VisionInterface.DejaVuNodes import vizlib ed.addLibraryInstance(vizlib, 'DejaVu.VisionInterface.DejaVuNodes', 'vizlib') ed.root.update_idletasks() ed.configure(withThreads=0) def tearDown(): ed.exit_cb() import gc gc.collect() ########################## ## Helper methods ########################## def pause(sleepTime=0.4): from time import sleep ed.master.update() sleep(sleepTime) ########################## ## Tests ########################## #=============================================================================== #this concerns the rethinking of IndexedPolygonsNE #============================================================================= def test_01_different_input_for_sphere_center(): # test if Spheres accept: # - single point # - single point in list # - list of points # it is also a test for gyration sphere from DejaVu.Geom import Geom ed.loadNetwork('Data/gyration_net.py') net = ed.currentNetwork net.runOnNewData.value = True net.run() # the nodes PointsListNode = net.nodes[1] PointListNode = net.nodes[4] GyrationNode = net.getNodeByName('Gyration Sphere')[0] SphereNode = net.getNodeByName('spheres')[0] ViewerNode = net.getNodeByName('Viewer')[0] # the sphere geom data = SphereNode.outputPorts[0].data # is this a Spheres geom? assert data is not None, "Expected data, got %s"%data assert isinstance(data, Geom), "Expected %s, got %s"%( Geom, data.__class__) # is the radius set correctly? assert data.radius == 2.0 , \ "Expected 2.0, got %s"%data.radius # how many spheres ? assert len(data.vertexSet.vertices) == 1 , \ "expected %s got %s"%(1,len(data.vertexSet.vertices)) # is the center set correctly? array = data.vertexSet.vertices.array[0] assert array[0] == array[1] == 1 and array[2] == 0,\ "Expected 1 1 0 got array0: %s, array1: %s, array2: %s"%( array[0], array[1], array[2]) # was it correctly added to the viewer? assert data in ViewerNode.vi.rootObject.children,\ "data is: %s\nchildren are: %s"%(data, ViewerNode.vi.rootObject.children) # does it have a parent? assert data.parent is not None, "data.parent is: %s"%data.parent # does it know about the viewer? assert data.viewer is not None, "data.viewer is: %s"%data.viewer # is it visible? assert data.visible == True, "Expected True, got %s"%data.visible # delete connection from gyration: [3 3 0] net.deleteConnection(GyrationNode, 'center', SphereNode, 'coords') # connect to eval: [[-3 -3 -3]] net.connectNodes(PointListNode, SphereNode, portNode2 ='coords') data = SphereNode.outputPorts[0].data # is this a Spheres geom? assert data is not None, "Expected data, got %s"%data assert isinstance(data, Geom), "Expected %s, got %s"%( Geom, data.__class__) # is the radius set correctly? assert data.radius == 2.0 , \ "Expected 2.0, got %s"%data.radius # how many spheres ? assert len(data.vertexSet.vertices) == 1 , \ "expected %s got %s"%(1,len(data.vertexSet.vertices)) # is the center set correctly? array = data.vertexSet.vertices.array[0] assert array[0] == array[1] == array[2] == -3,\ "Expected -3 -3 -3 got array0: %s, array1: %s, array2: %s"%( array[0], array[1], array[2]) # was it correctly added to the viewer? assert data in ViewerNode.vi.rootObject.children,\ "data is: %s\nchildren are: %s"%(data, ViewerNode.vi.rootObject.children) # does it have a parent? assert data.parent is not None, "data.parent is: %s"%data.parent # does it know about the viewer? assert data.viewer is not None, "data.viewer is: %s"%data.viewer # is it visible? assert data.visible == True, "Expected True, got %s"%data.visible # delete connection from eval: [[-3 -3 -3]] net.deleteConnection(PointListNode, 'result', SphereNode, 'coords') # connect to eval: [[0,0,0],[3,0,0],[0,3,0.]] net.connectNodes(PointsListNode, SphereNode, portNode2 ='coords') data = SphereNode.outputPorts[0].data # is this a Spheres geom? assert data is not None, "Expected data, got %s"%data assert isinstance(data, Geom), "Expected %s, got %s"%( Geom, data.__class__) # how many spheres ? assert len(data.vertexSet.vertices) == 3 , \ "expected %s got %s"%(3,len(data.vertexSet.vertices)) # is the radius set correctly? assert data.radius == 2.0 , \ "Expected 2.0, got %s"%data.radius # is the center set correctly? array = data.vertexSet.vertices.array[0] assert array[0] == array[1] == array[2] == 0,\ "Expected 0 0 0 got array0: %s, array1: %s, array2: %s"%( array[0], array[1], array[2]) # was it correctly added to the viewer? assert data in ViewerNode.vi.rootObject.children,\ "data is: %s\nchildren are: %s"%(data, ViewerNode.vi.rootObject.children) # does it have a parent? assert data.parent is not None, "data.parent is: %s"%data.parent # does it know about the viewer? assert data.viewer is not None, "data.viewer is: %s"%data.viewer # is it visible? assert data.visible == True, "Expected True, got %s"%data.visible mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/__init__.py0000644000175000017500000000000007723713122026162 0ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/test_parentingGeom.py0000644000175000017500000001202211234154725030270 0ustar debiandebian######################################################################### # # Date: Dec 2005 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # Copyright: Guillaume Vareille, Michel Sanner, and TSRI # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/VisionInterface/Tests/test_parentingGeom.py,v 1.14 2009/07/29 23:23:01 vareille Exp $ # # $Id: test_parentingGeom.py,v 1.14 2009/07/29 23:23:01 vareille Exp $ # import sys ed = None def setUp(): global ed from Vision.VPE import VisualProgramingEnvironment ed = VisualProgramingEnvironment(name='Vision', withShell=0,) from DejaVu.VisionInterface.DejaVuNodes import vizlib ed.addLibraryInstance(vizlib, 'DejaVu.VisionInterface.DejaVuNodes', 'vizlib') ed.root.update_idletasks() ed.configure(withThreads=0) def tearDown(): ed.exit_cb() import gc gc.collect() ########################## ## Helper methods ########################## def pause(sleepTime=0.4): from time import sleep ed.master.update() sleep(sleepTime) ########################## ## Tests ########################## #=============================================================================== #this concerns the rethinking of IndexedPolygonsNE #============================================================================= def test_01_connect_one_geometry_node(): # creat a connection form polygon 1 to Viewer and maek sure geom is added ed.loadNetwork('Data/parenting1_net.py') net = ed.currentNetwork net.runOnNewData.value = True net.run() polNode = net.getNodeByName('polygons1')[0] viewer = net.getNodeByName('Viewer')[0] net.connectNodes(polNode, viewer) g = polNode.geom() assert g.parent == viewer.vi.rootObject assert viewer.vi.rootObject.children[-1] == g assert viewer.vi.GUI.tvolist.objToNode[g].parent.name == \ viewer.vi.rootObject.name assert viewer.vi.GUI.tvolist.objToNode[g].name == g.name assert g.node().getInputPortByName('geoms').widget.get() == g.name assert g.node().name == g.name ed.deleteNetwork(net) def test_02_addSecondGeomWithSameName(): # start from end of test_01 and connect polyg ed.loadNetwork('Data/parenting1_net.py') net = ed.currentNetwork net.runOnNewData.value = True net.run() polNode1, polNode2 = net.getNodeByName('polygons1') viewer = net.getNodeByName('Viewer')[0] net.connectNodes(polNode1, viewer) net.connectNodes(polNode2, viewer) g2 = polNode2.geom() assert g2.parent == viewer.vi.rootObject assert viewer.vi.rootObject.children[-1] == g2 assert viewer.vi.GUI.tvolist.objToNode[g2].parent.name == viewer.vi.rootObject.name assert viewer.vi.GUI.tvolist.objToNode[g2].name == g2.name assert g2.node().getInputPortByName('geoms').widget.get() == g2.name assert g2.node().name == g2.name assert polNode1.geom().name != g2.name ed.deleteNetwork(net) def test_03_parentPolygon(): # start from end of test_02 and parent polyg before running ed.loadNetwork('Data/parenting1_net.py') net = ed.currentNetwork polNode1, polNode2 = net.getNodeByName('polygons1') viewer = net.getNodeByName('Viewer')[0] net.connectNodes(polNode1, viewer) net.connectNodes(polNode2, viewer) net.connectNodes(polNode1, polNode2, portNode2 ='parent', doNotSchedule=True, doNotCb=True) #import pdb;pdb.set_trace() net.run() g1 = polNode1.geom() g2 = polNode2.geom() assert g2.parent == g1 assert g2 in g1.children assert viewer.vi.GUI.tvolist.objToNode[g1].parent.name == \ viewer.vi.rootObject.name assert viewer.vi.GUI.tvolist.objToNode[g2].parent.name == g1.name ed.deleteNetwork(net) def test_04_reparentPolygon(): # start from end of test_02 and reparent polyg after running ed.loadNetwork('Data/parenting1_net.py') net = ed.currentNetwork net.runOnNewData.value = True net.run() polNode1, polNode2 = net.getNodeByName('polygons1') viewer = net.getNodeByName('Viewer')[0] net.connectNodes(polNode1, viewer) net.connectNodes(polNode2, viewer) net.connectNodes(polNode1, polNode2, portNode2 ='parent') g1 = polNode1.geom() g2 = polNode2.geom() assert g2.parent == g1 assert g2 in g1.children assert viewer.vi.GUI.tvolist.objToNode[g1].parent.name == \ viewer.vi.rootObject.name assert viewer.vi.GUI.tvolist.objToNode[g2].parent.name == g1.name ed.deleteNetwork(net) def test_05_parentMacro(): # start from here ed.loadNetwork('Data/parentsAndMacro_net.py') net = ed.currentNetwork net.run() viewer = net.getNodeByName('Viewer')[0] indpol2 =viewer.vi.FindObjectByName('|indpol1|2|indpol2') assert indpol2 is not None ed.deleteNetwork(net) #============================================================================= mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/Tests/test_vizlib.py0000644000175000017500000000655710405665155027013 0ustar debiandebian######################################################################### # # Date: Aug 2003 Authors: Daniel Stoffler, Michel Sanner # # stoffler@scripps.edu # sanner@scripps.edu # # Copyright: Daniel Stoffler, Michel Sanner, and TSRI # ######################################################################### import sys ed = None def setUp(): global ed from Vision.VPE import VisualProgramingEnvironment ed = VisualProgramingEnvironment(name='Vision', withShell=0,) ed.root.update_idletasks() ed.configure(withThreads=0) def tearDown(): ed.exit_cb() import gc gc.collect() ########################## ## Helper methods ########################## def pause(sleepTime=0.4): from time import sleep ed.master.update() sleep(sleepTime) ########################## ## Tests ########################## def test_01_loadVizLib(): from DejaVu.VisionInterface.DejaVuNodes import vizlib ed.addLibraryInstance(vizlib, 'DejaVu.VisionInterface.DejaVuNodes', 'vizlib') ed.root.update_idletasks() pause() categories= ['Mapper', 'Geometry', 'Macro', 'Filter', 'Output', 'Input'] def categoryTest(cat): from DejaVu.VisionInterface.DejaVuNodes import vizlib ed.addLibraryInstance(vizlib, 'DejaVu.VisionInterface.DejaVuNodes', 'vizlib') ed.root.update_idletasks() pause() # test the vizlib nodes lib = '3D Visualization' libs = ed.libraries posx = 150 posy = 150 #ed.ModulePages.selectpage(lib) ed.root.update_idletasks() for node in libs[lib].libraryDescr[cat]['nodes']: klass = node.nodeClass kw = node.kw args = node.args netNode = apply( klass, args, kw ) print 'testing: '+node.name # begin node test #add node to canvas ed.currentNetwork.addNode(netNode,posx,posy) # show widget in node if available: widgetsInNode = netNode.getWidgetsForMaster('Node') if len( widgetsInNode.items() ): if not netNode.isExpanded(): netNode.toggleNodeExpand_cb() ed.root.update_idletasks() # and then hide it netNode.toggleNodeExpand_cb() ed.root.update_idletasks() # show widgets in param panel if available: widgetsInPanel = netNode.getWidgetsForMaster('ParamPanel') if len(widgetsInPanel.items()): netNode.paramPanel.show() ed.root.update_idletasks() #and then hide it netNode.paramPanel.hide() ed.root.update_idletasks() # and now delete the node ed.currentNetwork.deleteNodes([netNode]) ed.root.update_idletasks() print 'passed: '+node.name # end node test def test_02_MapperCategory(): """Testing Mapper category of nodudes.""" categoryTest("Mapper") def test_03_GeometryCategory(): """Testing Geometry category of nodudes.""" categoryTest("Geometry") def test_04_MacroCategory(): """Testing Macro category of nodudes.""" categoryTest("Macro") def test_05_FilterCategory(): """Testing Filter category of nodudes.""" categoryTest("Filter") def test_06_OutputCategory(): """Testing Output category of nodudes.""" categoryTest("Output") def test_07_InputCategory(): """Testing Input category of nodudes.""" categoryTest("Input") mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/__init__.py0000644000175000017500000000000007517111561025060 0ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/DejaVuTypes.py0000644000175000017500000001002510651502634025532 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: April 2006 Authors: Guillaume Vareille, Michel Sanner # # sanner@scripps.edu # vareille@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # # revision: # ######################################################################### # # $Header$ # # $Id$ # import Image import numpy.oldnumeric as Numeric from NetworkEditor.datatypes import AnyArrayType class ViewerType(AnyArrayType): from DejaVu.Viewer import Viewer def __init__(self, name='viewer', datashape=None, color='yellow', shape='rect', width=None, height=None, klass=Viewer): AnyArrayType.__init__(self, name=name, color=color, shape=shape, width=width, height=height, klass=klass, datashape=datashape) class ColorMapType(AnyArrayType): from DejaVu.colorMap import ColorMap def __init__(self, name='ColorMapType', datashape=None, color='magenta', shape='rect', width=None, height=None, klass=ColorMap): AnyArrayType.__init__(self, name=name, color=color, shape=shape, width=width, height=height, klass=klass, datashape=datashape) class TextureType(AnyArrayType): from Image import Image def __init__(self, name='texture', datashape=None, color='#995699', shape='rect', width=None, height=None, klass=None): AnyArrayType.__init__(self, name=name, color=color, shape=shape, width=width, height=height, klass=klass, datashape=datashape) def cast(self, data): """returns a success status (true, false) and the coerced data """ if self['datashape'] is None: from DejaVu.colorMap import ColorMap if isinstance(data, ColorMap): return True, data.ramp return False, None class Common2d3dObjectType(AnyArrayType): from DejaVu.Common2d3dObject import Common2d3dObject def __init__(self, name='geomOrInsert2d', datashape=None, color='red', shape='rect', width=None, height=None, klass=Common2d3dObject): AnyArrayType.__init__(self, name=name, color=color, shape=shape, width=width, height=height, klass=klass, datashape=datashape) class Insert2dType(AnyArrayType): from DejaVu.Insert2d import Insert2d def __init__(self, name='insert2d', datashape=None, color='red', shape='rect', width=None, height=None, klass=Insert2d): AnyArrayType.__init__(self, name=name, color=color, shape=shape, width=width, height=height, klass=klass, datashape=datashape) class GeomType(AnyArrayType): from DejaVu.Geom import Geom def __init__(self, name='geom', datashape=None, color='red', shape='rect', width=None, height=None, klass=Geom): AnyArrayType.__init__(self, name=name, color=color, shape=shape, width=width, height=height, klass=klass, datashape=datashape) def cast(self, data): """returns a success status (true, false) and the coerced data """ from DejaVu.Insert2d import Insert2d if self['datashape'] is None: if isinstance(data, Insert2d): return True, data else: lArray = Numeric.array(data) if lArray.size == 0: return False, None lArray0 = lArray.ravel()[0] while hasattr(lArray0,'shape'): lArray0 = lArray0.ravel()[0] if isinstance(lArray0, Insert2d): return True, lArray return False, None mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VisionInterface/RotateScene.py0000644000175000017500000004546710651433502025562 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Vision Macro - Python source code - file generated by vision # Tuesday 28 March 2006 11:26:49 # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler, Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header$ # # $Id$ # from NetworkEditor.macros import MacroNode class RotateScene(MacroNode): def __init__(self, constrkw={}, name='RotateScene', **kw): kw['name'] = name apply( MacroNode.__init__, (self,), kw) def beforeAddingToNetwork(self, net): MacroNode.beforeAddingToNetwork(self, net) ## loading libraries ## from symserv.VisionInterface.SymservNodes import symlib net.editor.addLibraryInstance(symlib,"symserv.VisionInterface.SymservNodes", "symlib") from Vision.StandardNodes import stdlib net.editor.addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") from DejaVu.VisionInterface.DejaVuNodes import vizlib net.editor.addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") def afterAddingToNetwork(self): from NetworkEditor.macros import MacroNode MacroNode.afterAddingToNetwork(self) ## loading libraries ## from symserv.VisionInterface.SymservNodes import symlib from Vision.StandardNodes import stdlib from DejaVu.VisionInterface.DejaVuNodes import vizlib ## building macro network ## RotateScene_0 = self from traceback import print_exc ## loading libraries ## from symserv.VisionInterface.SymservNodes import symlib self.macroNetwork.getEditor().addLibraryInstance(symlib,"symserv.VisionInterface.SymservNodes", "symlib") from Vision.StandardNodes import stdlib self.macroNetwork.getEditor().addLibraryInstance(stdlib,"Vision.StandardNodes", "stdlib") from DejaVu.VisionInterface.DejaVuNodes import vizlib self.macroNetwork.getEditor().addLibraryInstance(vizlib,"DejaVu.VisionInterface.DejaVuNodes", "vizlib") try: ## saving node input Ports ## input_Ports_1 = self.macroNetwork.ipNode input_Ports_1.move(45, 17) except: print "WARNING: failed to restore MacroInputNode named input Ports in network self.macroNetwork" print_exc() input_Ports_1=None try: ## saving node output Ports ## output_Ports_2 = self.macroNetwork.opNode output_Ports_2.move(228, 460) except: print "WARNING: failed to restore MacroOutputNode named output Ports in network self.macroNetwork" print_exc() output_Ports_2=None try: ## saving node Rotate ## from symserv.VisionInterface.SymservNodes import SymRotNE Rotate_3 = SymRotNE(constrkw = {}, name='Rotate', library=symlib) self.macroNetwork.addNode(Rotate_3,543,101) apply(Rotate_3.inputPortByName['matrices'].configure, (), {'color': 'cyan', 'cast': True, 'shape': 'rect'}) apply(Rotate_3.inputPortByName['vector'].configure, (), {'datatype': 'list', 'cast': True, 'shape': 'oval', 'color': 'cyan', 'height': 8}) apply(Rotate_3.inputPortByName['point'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(Rotate_3.inputPortByName['angle'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(Rotate_3.inputPortByName['identity'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(Rotate_3.outputPortByName['outMatrices'].configure, (), {'color': 'cyan', 'shape': 'rect'}) Rotate_3.inputPortByName['vector'].unbindWidget() Rotate_3.inputPortByName['angle'].widget.set(0.0, run=False) Rotate_3.inputPortByName['angle'].unbindWidget() except: print "WARNING: failed to restore SymRotNE named Rotate in network self.macroNetwork" print_exc() Rotate_3=None try: ## saving node One Redraw ## from DejaVu.VisionInterface.DejaVuNodes import OneRedraw One_Redraw_4 = OneRedraw(constrkw = {}, name='One Redraw', library=vizlib) self.macroNetwork.addNode(One_Redraw_4,22,452) apply(One_Redraw_4.inputPortByName['viewer'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'rect'}) apply(One_Redraw_4.inputPortByName['trigger'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) except: print "WARNING: failed to restore OneRedraw named One Redraw in network self.macroNetwork" print_exc() One_Redraw_4=None try: ## saving node Choose Geom ## from DejaVu.VisionInterface.DejaVuNodes import SelectGeometry Choose_Geom_5 = SelectGeometry(constrkw = {}, name='Choose Geom', library=vizlib) self.macroNetwork.addNode(Choose_Geom_5,412,220) apply(Choose_Geom_5.inputPortByName['viewer'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'rect'}) apply(Choose_Geom_5.inputPortByName['geomName'].configure, (), {'color': 'white', 'cast': True, 'shape': 'oval'}) apply(Choose_Geom_5.outputPortByName['geometry'].configure, (), {'color': 'red', 'shape': 'rect'}) apply(Choose_Geom_5.inputPortByName['geomName'].widget.configure, (), {'autoList': False, 'choices': ('root',)}) Choose_Geom_5.inputPortByName['geomName'].widget.set("root", run=False) except: print "WARNING: failed to restore SelectGeometry named Choose Geom in network self.macroNetwork" print_exc() Choose_Geom_5=None try: ## saving node range ## from Vision.StandardNodes import Range range_6 = Range(constrkw = {}, name='range', library=stdlib) self.macroNetwork.addNode(range_6,246,147) apply(range_6.inputPortByName['fromInd'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(range_6.inputPortByName['toInd'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(range_6.inputPortByName['step'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'circle'}) apply(range_6.outputPortByName['data'].configure, (), {'color': 'cyan', 'shape': 'oval'}) range_6.inputPortByName['toInd'].unbindWidget() except: print "WARNING: failed to restore Range named range in network self.macroNetwork" print_exc() range_6=None try: ## saving node iterate ## from Vision.StandardNodes import Iterate iterate_7 = Iterate(constrkw = {}, name='iterate', library=stdlib) self.macroNetwork.addNode(iterate_7,283,204) apply(iterate_7.inputPortByName['listToLoopOver'].configure, (), {'color': 'cyan', 'cast': True, 'shape': 'oval'}) apply(iterate_7.outputPortByName['oneItem'].configure, (), {'color': 'white', 'shape': 'diamond'}) apply(iterate_7.outputPortByName['iter'].configure, (), {'color': 'yellow', 'shape': 'circle'}) apply(iterate_7.outputPortByName['begin'].configure, (), {'color': 'yellow', 'shape': 'rect'}) apply(iterate_7.outputPortByName['end'].configure, (), {'color': 'yellow', 'shape': 'rect'}) apply(iterate_7.outputPortByName['maxIter'].configure, (), {'color': 'yellow', 'shape': 'circle'}) except: print "WARNING: failed to restore Iterate named iterate in network self.macroNetwork" print_exc() iterate_7=None try: ## saving node flattenRotation ## from Vision.StandardNodes import Generic flattenRotation_8 = Generic(constrkw = {}, name='flattenRotation', library=stdlib) self.macroNetwork.addNode(flattenRotation_8,560,200) apply(flattenRotation_8.addInputPort, (), {'name': 'in0', 'cast': True, 'datatype': 'instancemat(0)', 'height': 8, 'width': 12, 'shape': 'rect', 'color': 'cyan'}) apply(flattenRotation_8.addOutputPort, (), {'name': 'out0', 'datatype': 'float(16)', 'height': 10, 'width': 10, 'shape': 'rect', 'color': 'white'}) code = """def doit(self, in0): self.outputData(out0=in0[0].ravel()) """ flattenRotation_8.configure(function=code) except: print "WARNING: failed to restore Generic named flattenRotation in network self.macroNetwork" print_exc() flattenRotation_8=None try: ## saving node Pass ## from Vision.StandardNodes import Pass Pass_9 = Pass(constrkw = {}, name='Pass', library=stdlib) self.macroNetwork.addNode(Pass_9,333,339) apply(Pass_9.inputPortByName['in1'].configure, (), {'color': 'white', 'cast': True, 'shape': 'diamond'}) apply(Pass_9.outputPortByName['out1'].configure, (), {'color': 'white', 'shape': 'diamond'}) apply(Pass_9.configure, (), {'specialPortsVisible': True}) except: print "WARNING: failed to restore Pass named Pass in network self.macroNetwork" print_exc() Pass_9=None try: ## saving node angle ## from Vision.StandardNodes import DialNE angle_10 = DialNE(constrkw = {}, name='angle', library=stdlib) self.macroNetwork.addNode(angle_10,244,5) apply(angle_10.inputPortByName['dial'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(angle_10.inputPortByName['mini'].configure, (), {'datatype': 'int', 'cast': True, 'shape': 'circle', 'color': 'yellow'}) apply(angle_10.inputPortByName['maxi'].configure, (), {'datatype': 'int', 'cast': True, 'shape': 'circle', 'color': 'yellow'}) apply(angle_10.outputPortByName['value'].configure, (), {'datatype': 'int', 'color': 'yellow', 'shape': 'circle'}) apply(angle_10.inputPortByName['dial'].widget.configure, (), {'type': 'int', 'oneTurn': 100.0}) angle_10.inputPortByName['dial'].widget.set(360, run=False) except: print "WARNING: failed to restore DialNE named angle in network self.macroNetwork" print_exc() angle_10=None try: ## saving node nbSteps ## from Vision.StandardNodes import DialNE nbSteps_11 = DialNE(constrkw = {}, name='nbSteps', library=stdlib) self.macroNetwork.addNode(nbSteps_11,634,7) apply(nbSteps_11.inputPortByName['dial'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(nbSteps_11.inputPortByName['mini'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(nbSteps_11.inputPortByName['maxi'].configure, (), {'color': 'green', 'cast': True, 'shape': 'circle'}) apply(nbSteps_11.outputPortByName['value'].configure, (), {'color': 'green', 'shape': 'circle'}) apply(nbSteps_11.inputPortByName['dial'].widget.configure, (), {'oneTurn': 10.0}) nbSteps_11.inputPortByName['dial'].widget.set(1.0, run=False) except: print "WARNING: failed to restore DialNE named nbSteps in network self.macroNetwork" print_exc() nbSteps_11=None try: ## saving node select axis ## from DejaVu.VisionInterface.DejaVuNodes import SelectAxis select_axis_12 = SelectAxis(constrkw = {}, name='select axis', library=stdlib) self.macroNetwork.addNode(select_axis_12,528,40) apply(select_axis_12.inputPortByName['x-axis'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'rect'}) apply(select_axis_12.inputPortByName['y-axis'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'rect'}) apply(select_axis_12.inputPortByName['z-axis'].configure, (), {'color': 'yellow', 'cast': True, 'shape': 'rect'}) apply(select_axis_12.outputPortByName['rotationAxis'].configure, (), {'color': 'cyan', 'shape': 'oval'}) except: print "WARNING: failed to restore SelectAxis named select axis in network self.macroNetwork" print_exc() select_axis_12=None try: ## saving node call method ## from Vision.StandardNodes import CallMethod call_method_13 = CallMethod(constrkw = {}, name='call method', library=stdlib) self.macroNetwork.addNode(call_method_13,412,339) apply(call_method_13.inputPortByName['objects'].configure, (), {'datatype': 'geom', 'cast': True, 'shape': 'rect', 'color': 'red'}) apply(call_method_13.inputPortByName['signature'].configure, (), {'color': 'white', 'cast': True, 'shape': 'oval'}) apply(call_method_13.addInputPort, (), {'name': 'mat', 'cast': True, 'datatype': 'None', 'height': 8, 'width': 12, 'shape': 'diamond', 'color': 'white'}) apply(call_method_13.outputPortByName['objects'].configure, (), {'color': 'white', 'shape': 'diamond'}) apply(call_method_13.outputPortByName['results'].configure, (), {'color': 'white', 'shape': 'diamond'}) call_method_13.inputPortByName['signature'].widget.set("ConcatRotation %mat", run=False) apply(call_method_13.configure, (), {'specialPortsVisible': True}) except: print "WARNING: failed to restore CallMethod named call method in network self.macroNetwork" print_exc() call_method_13=None self.macroNetwork.freeze() ## saving connections for network RotateScene ## if range_6 is not None and iterate_7 is not None: try: self.macroNetwork.connectNodes( range_6, iterate_7, "data", "listToLoopOver", blocking=True) except: print "WARNING: failed to restore connection between range_6 and iterate_7 in network self.macroNetwork" if Rotate_3 is not None and flattenRotation_8 is not None: try: self.macroNetwork.connectNodes( Rotate_3, flattenRotation_8, "outMatrices", "in0", blocking=True) except: print "WARNING: failed to restore connection between Rotate_3 and flattenRotation_8 in network self.macroNetwork" if iterate_7 is not None and Pass_9 is not None: try: self.macroNetwork.connectNodes( iterate_7, Pass_9, "oneItem", "in1", blocking=True) except: print "WARNING: failed to restore connection between iterate_7 and Pass_9 in network self.macroNetwork" if angle_10 is not None and range_6 is not None: try: self.macroNetwork.connectNodes( angle_10, range_6, "value", "toInd", blocking=True) except: print "WARNING: failed to restore connection between angle_10 and range_6 in network self.macroNetwork" if nbSteps_11 is not None and Rotate_3 is not None: try: self.macroNetwork.connectNodes( nbSteps_11, Rotate_3, "value", "angle", blocking=True) except: print "WARNING: failed to restore connection between nbSteps_11 and Rotate_3 in network self.macroNetwork" if select_axis_12 is not None and Rotate_3 is not None: try: self.macroNetwork.connectNodes( select_axis_12, Rotate_3, "rotationAxis", "vector", blocking=True) except: print "WARNING: failed to restore connection between select_axis_12 and Rotate_3 in network self.macroNetwork" output_Ports_2 = self.macroNetwork.opNode if iterate_7 is not None and output_Ports_2 is not None: try: self.macroNetwork.connectNodes( iterate_7, output_Ports_2, "oneItem", "new", blocking=True) except: print "WARNING: failed to restore connection between iterate_7 and output_Ports_2 in network self.macroNetwork" if Choose_Geom_5 is not None and call_method_13 is not None: try: self.macroNetwork.connectNodes( Choose_Geom_5, call_method_13, "geometry", "objects", blocking=True) except: print "WARNING: failed to restore connection between Choose_Geom_5 and call_method_13 in network self.macroNetwork" if Pass_9 is not None and call_method_13 is not None: try: self.macroNetwork.specialConnectNodes( Pass_9, call_method_13, "trigger", "runNode", blocking=True) except: print "WARNING: failed to restore connection between Pass_9 and call_method_13 in network self.macroNetwork" if flattenRotation_8 is not None and call_method_13 is not None: try: self.macroNetwork.connectNodes( flattenRotation_8, call_method_13, "out0", "mat", blocking=True) except: print "WARNING: failed to restore connection between flattenRotation_8 and call_method_13 in network self.macroNetwork" if call_method_13 is not None and One_Redraw_4 is not None: try: self.macroNetwork.connectNodes( call_method_13, One_Redraw_4, "objects", "trigger", blocking=True) except: print "WARNING: failed to restore connection between call_method_13 and One_Redraw_4 in network self.macroNetwork" input_Ports_1 = self.macroNetwork.ipNode if input_Ports_1 is not None and One_Redraw_4 is not None: try: self.macroNetwork.connectNodes( input_Ports_1, One_Redraw_4, "new", "viewer", blocking=True) except: print "WARNING: failed to restore connection between input_Ports_1 and One_Redraw_4 in network self.macroNetwork" if input_Ports_1 is not None and Choose_Geom_5 is not None: try: self.macroNetwork.connectNodes( input_Ports_1, Choose_Geom_5, "One Redraw_viewer", "viewer", blocking=True) except: print "WARNING: failed to restore connection between input_Ports_1 and Choose_Geom_5 in network self.macroNetwork" self.macroNetwork.unfreeze() ## modifying MacroOutputNode dynamic ports output_Ports_2 = self.macroNetwork.opNode output_Ports_2.inputPorts[1].configure(singleConnection=True) RotateScene_0.shrink() ## reset modifications ## RotateScene_0.resetTags() RotateScene_0.buildOriginalList() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/NormalsViz.py0000644000175000017500000000151410651433502022343 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by from DejaVu.Polylines import Polylines import numpy.oldnumeric as Numeric class NormalsViewer: """Object that take a DejaVu geometry and a viewer and displays the geometry's normals in the viewer""" def __init__(self, geom, viewer): self.geom = geom self.normalsGeom = Polylines('normals_for_'+geom.name) self.viewer = viewer viewer.AddObject(self.normalsGeom, parent=geom) self.update() def update(self): vertices = self.geom.getVertices() normals = self.geom.getVNormals() pts = Numeric.concatenate( (vertices, vertices+normals), 1) pts = Numeric.reshape( pts, (len(vertices),2,-1) ).astype('f') self.normalsGeom.Set(vertices = pts) self.viewer.Redraw() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/colorMap.py0000644000175000017500000002765310651433501022026 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # # Revision: Guillaume Vareille # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/colorMap.py,v 1.98 2007/07/24 17:30:41 vareille Exp $ # # $Id: colorMap.py,v 1.98 2007/07/24 17:30:41 vareille Exp $ # import numpy.oldnumeric as Numeric import os import warnings import types from DejaVu import viewerConst from DejaVu.colorTool import RGBRamp, ToHSV, TkColor class ColorMap: """A Colormap is an object designed to provide a mapping from a property value to an entry in a 'ramp', which is a list of lists. Each entry defines a color for that value. The property range is set by the attributes 'mini' to 'maxi'. The corresponding colors are obtained from the Colormap's ramp, which is n by 4 matrix of floats: rgba or red, green, blue, alpha values. If it is initialized with only rgb, the alpha values are added. A Colormap has always a name and a ramp, if these values are not provided the creator will try to provide both if they are missing A Colormap may be created by reading a file and may saved in a file. A Colormap can return its ramp as hsva or as TkColors via its methods 'asHSV' and 'asTKCOL' A Colormap can be associated to a ColormapGUI object. """ def __init__(self, name=None, ramp=None, labels=None, mini='not passed', maxi='not passed', cmap=None, filename=None, **kw): self.name = None self.ramp = None self.labels = None self.mini = None self.maxi = None self.lastMini = None self.lastMaxi = None if cmap is not None: assert filename is None, \ "color map creation with both cmap and filename doesn't make sense" assert ramp is None, \ "color map creation with both cmap and ramp doesn't make sense" if name is not None: warnings.warn("color map creation with cmap and name: name won't be used") if mini is not None: warnings.warn("color map creation with cmap and mini: mini won't be used") if maxi is not None: warnings.warn("color map creation with cmap and maxi: maxi won't be used") name = cmap.name ramp = cmap.ramp labels = cmap.labels mini = cmap.mini maxi = cmap.maxi ColorMap.configure(self, name=name, ramp=ramp, labels=labels, mini=mini, maxi=maxi) elif filename is not None: assert ramp is None, \ "color map creation with both ramp and filename doesn't make sense" if ColorMap.read(self, filename) is False: # bad file, but now the colormap is instanced, # we configure it with good values #ColorMap.__init__(self, name=name, ramp=ramp, labels=labels, mini=mini, maxi=maxi) ColorMap.configure(self, name=name, ramp=ramp, labels=labels, mini=mini, maxi=maxi) #but we still raise an error raise RuntimeError('invalid Colormap file') #return else: if name is not None: self.name = name elif self.name is None: # filename without path and without extension self.name = filename.split(os.sep)[-1].split('.')[0] else: if ramp is None: ramp = RGBRamp(size=16) if name is None: name = 'RGBRamp_Colormap' if name is None: name = 'Untitled_Colormap' ColorMap.configure(self, name=name, ramp=ramp, labels=labels, mini=mini, maxi=maxi) def configure(self, name=None, ramp=None, labels=None, mini='not passed', maxi='not passed', **kw): """Configure the colormap with the given values. """ if name is None: assert self.name is not None, "colormap.configure() needs a name" else: self.name = name assert name != '' if ramp is None: assert self.ramp is not None, "colormap.configure() needs a ramp" else: assert len(ramp) > 0, \ "colormap.configure() needs a ramp with at least one element" self.ramp = self.checkRamp(ramp)[:] if hasattr(self.ramp, 'tolist'): self.ramp = self.ramp.tolist() assert type(self.ramp) is types.ListType, type(self.ramp) lenRamp = len(self.ramp) if labels is not None: if len(labels) == 0: # passing an empty list is a shortcut for a numeric list self.labels = range(lenRamp) else: assert len(labels) == lenRamp self.labels = labels elif self.labels is not None: lenLabels = len(self.labels) if lenLabels == 0: self.labels = range(lenRamp) elif lenLabels < lenRamp: lMissingLength = lenRamp - lenLabels lMissingLabels = range(lenLabels, lenRamp) #print "lMissingLabels", lMissingLabels self.labels += lMissingLabels else: while len(self.labels) > lenRamp: self.labels.pop() assert len(self.labels) == lenRamp if self.labels is not None: for i in range( len(self.labels) ): self.labels[i] = str(self.labels[i]) if mini != 'not passed': if mini is None: self.mini = None else: if maxi is not None and (maxi != 'not passed'): if mini >= maxi: mini = None elif self.maxi is not None: if mini >= self.maxi: mini = None self.mini = mini self.lastMini = self.mini if maxi != 'not passed': if maxi is None: self.maxi = None else: if mini is not None and (mini != 'not passed'): if mini >= maxi: maxi = None elif self.mini is not None: if self.mini >= maxi: maxi = None self.maxi = maxi self.lastMaxi = self.maxi def set(self, value): """set the colormap ramp with the given values. """ if isinstance(value, ColorMap): self.configure(name=value.name, ramp=value.ramp, labels=value.labels, mini=value.mini, maxi=value.maxi) else: self.configure(ramp=value) def get(self): """return the colormap ramp """ return self.ramp def getDescr(self): cfg = {} cfg['name'] = self.name cfg['ramp'] = self.ramp cfg['labels'] = self.labels cfg['mini'] = self.mini cfg['maxi'] = self.maxi return cfg def checkRamp(self, ramp): """Method to check the given ramp. If only rgb values given then 1 is added for the alpha values. """ #if no alpha values, add 1's if len(ramp[0]) == 4: return ramp if len(ramp[0]) == 3: lenRgb = len(ramp) _ones = Numeric.ones(lenRgb, 'f') _ones.shape = (lenRgb, 1) ramp = Numeric.concatenate((Numeric.array(ramp), _ones),1) return ramp.tolist() def read(self, fileName): """Reinitialize colormap with data from file """ l = {} g = {} try: execfile(fileName, g, l) except: return False cm = None for name, object in l.items(): if isinstance(object, ColorMap): cm = object break else: # we didn't break return False if cm.maxi > cm.mini: cfg = {'name':cm.name, 'ramp':cm.ramp, 'mini':cm.mini, 'maxi':cm.maxi} else: cfg = {'name':cm.name, 'ramp':cm.ramp} if hasattr(cm,'labels'): cfg['labels'] = cm.labels apply( ColorMap.configure, (self,), cfg) if self.ramp is None: return False else: return True def write(self, fileName): """Write the colormap's source code to a file """ code = self.sourceCode() f = open(fileName, 'w') f.write("%s"%code) f.close() def sourceCode(self): """returns python code that will recreate this object """ cm = self code = """from %s import %s\n"""%(ColorMap.__module__, 'ColorMap') code = code + """cm = %s(name='%s')\n"""%('ColorMap', cm.name) cfg = cm.getDescr() code = code + "cfg = "+str(cfg)+"""\n""" code = code + """apply( cm.configure, (), cfg)\n""" return code def Map(self, values, mini='not passed', maxi='not passed'): """Get colors corresponding to values in a colormap. if mini or maxi are provided, self.mini and self.maxi are not used and stay inchanged. if mini or maxi are not provided or set to None, self.mini and self.maxi are used instead. if mini or maxi are set to None, self.mini and self.maxi are ignored """ #print "Map", mini, maxi, self.mini, self.maxi, values values = Numeric.array(values) if len(values.shape)==2 and values.shape[1]==1: values.shape = ( values.shape[0], ) elif len(values.shape) > 1: raise ValueError('ERROR! values array has bad shape') ramp = Numeric.array(self.ramp) if len(ramp.shape) !=2 or ramp.shape[1] not in (3,4): raise ValueError('ERROR! colormap array has bad shape') if mini == 'not passed': mini = self.mini if maxi == 'not passed': maxi = self.maxi if mini is None: mini = min(values) else: # All the values < mini will be set to mini values = Numeric.maximum(values, mini) if maxi is None: maxi = max(values) else: values = Numeric.minimum(values, maxi) # mini and maxi are now set if mini >= maxi: txt = 'mini:%f must be < maxi:%f'%(mini, maxi) warnings.warn( txt ) valrange = maxi - mini if valrange < 0.0001: ind = Numeric.ones( values.shape ) else: colrange = ramp.shape[0] ind = (values - mini) * (colrange/float(valrange)) ind = ind.astype(viewerConst.IPRECISION) ind = Numeric.minimum(ind, colrange - 1) col = Numeric.take(self.ramp, ind ) self.lastMini = mini self.lastMaxi = maxi return col #alternative representations of the ramp def asHSV(self, redo=0): self.hsv = map(lambda x, conv=ToHSV: conv(x), self.ramp) #if redo or not hasattr(self, 'hsv'): # self.hsv = map(lambda x, conv=ToHSV: conv(x), self.ramp) return self.hsv def asHSL(self, redo=0): from mglutil.util.colorUtil import RGBA2HSLA_list return map(lambda x, conv=RGBA2HSLA_list: conv(x), self.ramp) def asTKCOL(self, redo=0): if redo or not hasattr(self, 'tkcol'): self.tkcol = map(lambda x, conv=TkColor: conv(x), self.ramp) return self.tkcol def _lookup(self, name): #name = str(name) if self.labels is None: for i in range( len(self.ramp) ): self.labels[i] = str(i) if type(name) != types.StringTypes: name = str(name) return self.ramp[self.labels.index(name)] def lookup(self, names): return map( self._lookup, names) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Transformable.py0000644000175000017500000006346411361700154023051 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Transformable.py,v 1.51 2010/04/15 21:09:00 autin Exp $ # # $Id: Transformable.py,v 1.51 2010/04/15 21:09:00 autin Exp $ # from opengltk.OpenGL import GL from opengltk.OpenGL.GLU import gluProject from opengltk.extent.utillib import glCleanRotMat from opengltk.extent import _gllib as gllib import numpy.oldnumeric as Numeric, math import DejaVu from mglutil.events import Event class translateEvent(Event): def __init__(self, arg=None, objects=[]): """ """ self.arg = arg self.objects = objects class Transformable: """Base Class inherited by objects which can be transformed using the mouse""" def multMat4pt(self, mat, pt): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ptx = mat[0][0]*pt[0]+mat[0][1]*pt[1]+mat[0][2]*pt[2]+mat[0][3] pty = mat[1][0]*pt[0]+mat[1][1]*pt[1]+mat[1][2]*pt[2]+mat[1][3] ptz = mat[2][0]*pt[0]+mat[2][1]*pt[1]+mat[2][2]*pt[2]+mat[2][3] return (ptx, pty, ptz) def ResetTransformation(self, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Reset the tranformations (Rotation, translation, pivot, scale)""" self.rotation = Numeric.identity(4).astype('f') self.rotation.shape = (16, ) self.translation = Numeric.zeros( (3,), 'f') self.pivot = Numeric.zeros( (3,), 'f') self.scale = Numeric.ones( (3,), 'f') if self.viewer: if self.viewer.currentObject != self.viewer.rootObject \ and redo: self.viewer.deleteOpenglList() def __init__(self, viewer=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Constructor""" self.inheritXform = 1 # set to 0 not to inherit self.redirectXform = None # object to which transf. # should be redirected self.propagateRedirection = 1 self.copyXform = [] # list of objects to be # transf. along with me # Object's original transf. # in OpenGL form (shape (16,)) self.Matrix = Numeric.identity(4).astype('f') self.Matrix.shape = (16, ) self.MatrixRot = self.Matrix self.MatrixRotInv = self.Matrix self.MatrixScale = Numeric.ones((3,), 'f') self.MatrixTransl = Numeric.zeros( (3,), 'f') self.viewer = viewer self.ResetTransformation(redo=0) # init object's transf. self.R = Numeric.identity(4).astype('f') # Object's frame rotation self.R.shape = (16, ) self.Ri = Numeric.identity(4) .astype('f') # Inverse of R self.Ri.shape = (16, ) self.Si = Numeric.ones( (3, ) ).astype('f') # Inverse of frame's scale self.isScalable = 1 self.immediateRendering = False #self.hasChildWithImmediateRendering = False # set to True if a child is not using dpyList self.needsRedoDpyListOnResize = False def Decompose4x4(self, matrix, cleanup=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ takes a matrix in shape (16,) in OpenGL form (sequential values go down columns) and decomposes it into its rotation (shape (16,)), translation (shape (3,)), and scale (shape (3,)) """ m = matrix transl = Numeric.array((m[12], m[13], m[14]), 'f') scale0 = Numeric.sqrt(m[0]*m[0]+m[4]*m[4]+m[8]*m[8]) scale1 = Numeric.sqrt(m[1]*m[1]+m[5]*m[5]+m[9]*m[9]) scale2 = Numeric.sqrt(m[2]*m[2]+m[6]*m[6]+m[10]*m[10]) scale = Numeric.array((scale0,scale1,scale2)).astype('f') mat = Numeric.reshape(m, (4,4)) rot = Numeric.identity(4).astype('f') rot[:3,:3] = mat[:3,:3].astype('f') rot[:,0] = (rot[:,0]/scale0).astype('f') rot[:,1] = (rot[:,1]/scale1).astype('f') rot[:,2] = (rot[:,2]/scale2).astype('f') if cleanup: rot = glCleanRotMat(rot.ravel()) rot.shape = (16,) #rot1 = rot.astype('f') return rot, transl, scale def setMatrixComponents(self, rot=None, trans=None, scale=None, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Define MatrixRot, MatrixTransl, MatrixScale and MatrixRotInv from a rotation, translation and scale. rot should be a 4x4 matrix defining a 3D 3x3 rotation trans should be a 3D translation vector scale should be 3-vector of positive number larger than 0.0 """ self._modified = True if rot is not None: assert rot.shape==(4,4) self.MatrixRot = rot.ravel() RotInv = Numeric.transpose(rot) self.MatrixRotInv = Numeric.reshape(RotInv, (16,)) if trans is not None: assert len(trans)==3 self.MatrixTransl = trans if scale is not None: assert len(scale)==3 and scale[0]>0. and scale[1]>0. and scale[2]>0. self.MatrixScale = scale if redo: self.RedoDisplayList() self.viewer.Redraw() def SetMatrix(self, matrix): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ takes a 4x4 matrix. If shape==(16,), it must be in OpenGL form. If shape==(4,4), then it is in standard form, with translation vector in right column, etc. calls Decompose4x4 to calculate equivalent rotation, translation, and scale matrix/vectors and sets the objects attributes, setting the object's original transformation to matrix """ assert matrix.shape==(16,) or matrix.shape==(4,4) self._modified = True if matrix.shape==(4,4): matrix = Numeric.reshape(Numeric.transpose(matrix), (16,)) self.Matrix = matrix self.MatrixRot, self.MatrixTransl, self.MatrixScale = self.Decompose4x4(matrix) RotInv = Numeric.transpose(Numeric.reshape(self.MatrixRot, (4,4))) self.MatrixRotInv = Numeric.reshape(RotInv, (16,)) # self.MatrixRot = self.MatrixRot.astype('f') self.MatrixRotInv = self.MatrixRot.astype('f') if self != self.viewer.rootObject: self.viewer.deleteOpenglList() self.viewer.Redraw() def RedirectTransformTo(self, object=None, propagate=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Apply transformations to object rather than to myself""" children = [] if object: assert isinstance(object, Transformable) if object: if hasattr(self, 'AllObjects'): children = self.AllObjects() else: if object in children: raise AttributeError("%s is a child of %s, therefore it \ already inherits the transformation" % (self.name, object.name) ) self.propagateRedirection = propagate while object and object.redirectXform and object.propagateRedirection: object = object.redirectXform self.redirectXform = object for o in children: if o.redirectXform: o.redirectXform=object def MoveWith(self, object=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add myself to the list of objects inheriting transf. from object""" if object: assert isinstance(object, Transformable) if object == self or object is None: objs = self.viewer.rootObject.AllObjects() for o in objs: if self in o.copyXform: o.copyXform.remove(self) return children = [] if hasattr(object, 'AllObjects'): children = object.AllObjects() if self in children: raise AttributeError("%s is a child of %s, therefore it already \ inherits the transformation" % (self.name, object.name) ) if self not in object.copyXform: object.copyXform.append(self) def _SetPivot(self, new_pivot): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the pivot vector directly""" pivot = Numeric.array ( new_pivot ) assert pivot.shape == (3,) self.pivot = pivot def SetPivot(self, new_pivot): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the center of rotation. the pivot point should be expressed in the coordinate system defined by all the transformations above this node including this node's transformation""" self._modified = True MatrixRotInv = Numeric.reshape(self.MatrixRotInv, (4,4)) pivotDiff = self.pivot-new_pivot pivotTrans = Numeric.dot(MatrixRotInv[:3,:3], pivotDiff) scal = self.scale scalTrans = -self.MatrixScale*pivotDiff newPivotTrans = Numeric.dot(MatrixRotInv[:3,:3], scalTrans) for j in (0,1,2): self.translation[j] = self.translation[j] + \ pivotTrans[j] for i in (0,1,2): self.translation[j] = self.translation[j] + \ scal[i] * (newPivotTrans[i]) * self.rotation[i*4+j] oldPivot = self.pivot self.pivot = Numeric.array ( new_pivot ) return oldPivot # Guillaume wonders if we could write MakeMat this way # ie get rid of the call with (self.MatrixRotInv) then (self.MatrixRot) # but I need an exemple where self.MatrixRot is not the identity # def MakeMat(self, scale=True): # """Build the matrix for this object in his parent's frame""" # gllib.glTranslatef(float(self.pivot[0]), # float(self.pivot[1]), # float(self.pivot[2])) # # gllib.glTranslatef(float(self.translation[0]), # float(self.translation[1]), # float(self.translation[2])) # gllib.glMultMatrixf(self.rotation) # if scale: # gllib.glScalef(float(self.scale[0]), # float(self.scale[1]), # float(self.scale[2])) # # gllib.glTranslatef(float(self.MatrixTransl[0]), # float(self.MatrixTransl[1]), # float(self.MatrixTransl[2])) # gllib.glMultMatrixf(self.MatrixRot) # gllib.glScalef(float(self.MatrixScale[0]), # float(self.MatrixScale[1]), # float(self.MatrixScale[2])) # # gllib.glTranslatef(float(-self.pivot[0]), # float(-self.pivot[1]), # float(-self.pivot[2])) def MakeMat(self, scale=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Build the matrix for this object in his parent's frame""" gllib.glTranslatef(float(self.translation[0]), float(self.translation[1]), float(self.translation[2])) gllib.glTranslatef(float(self.MatrixTransl[0]), float(self.MatrixTransl[1]), float(self.MatrixTransl[2])) #print "self.MatrixRot", self.MatrixRot gllib.glMultMatrixf(self.MatrixRot) gllib.glTranslatef(float(self.pivot[0]), float(self.pivot[1]), float(self.pivot[2])) gllib.glMultMatrixf(self.MatrixRotInv) gllib.glMultMatrixf(self.rotation) gllib.glMultMatrixf(self.MatrixRot) if scale: gllib.glScalef(float(self.scale[0]), float(self.scale[1]), float(self.scale[2])) gllib.glScalef(float(self.MatrixScale[0]), float(self.MatrixScale[1]), float(self.MatrixScale[2])) gllib.glTranslatef(float(-self.pivot[0]), float(-self.pivot[1]), float(-self.pivot[2])) def BuildMat(self, obj, root, scale, instance): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Build the matrix by which this object is transformed instance is a list of integer providing instance indices for all parents """ #print 'build Mat', obj.name, instance if obj.parent and obj!=root: parentInstance = instance[:-1] self.BuildMat(obj.parent, root, scale, parentInstance) obj.MakeMat(scale) #print 'build Mat end', obj.name, instance #print 'build multiply instance', instance[-1], 'for geom', obj instance = obj.instanceMatricesFortran[int(instance[-1])] gllib.glMultMatrixf(instance) ## FIXME does not work .. Project return weird stuff ## def Project(self, point): ## """Apply all transformations to point and return winx,winy,winz""" ## camera = self.viewer.currentCamera ## camera.SetupProjectionMatrix() ## GL.glViewport(0, 0, camera.width, camera.height) ## # mat = Numeric.reshape(Numeric.transpose(self.GetMatrix(self)), (16,)) ## mat = Numeric.reshape(self.GetMatrix(), (16,)) ## print self.name, mat ## GL.glPushMatrix() ## GL.glLoadIdentity() ## GL.glMultMatrix(mat) ## print 'MOD',GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX) ## print 'PROJ',GL.glGetDoublev(GL.GL_PROJECTION_MATRIX) ## projPoint = gluProject(point[0],point[1],point[2]) ## GL.glPopMatrix() ## return projPoint def GetMatrix(self, root=None, instance=None, scale=True, transpose=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Returns the matrix by which this object is transformed scale = False: returns the rotation and translation. no scaling info included Used to save the transformed geom --> coords --> new pdb file instance is a list of integer instance indices for all parents """ if root is None: root = self.viewer.rootObject if instance is None: instance = [0] p = self.parent while p: instance.append(0) p = p.parent GL.glPushMatrix() GL.glLoadIdentity() #print 'GetMatrix', instance self.BuildMat(self, root, scale, instance) #GL.glMultMatrixf(self.instanceMatricesFortran[instanceList[0]]]) m = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') GL.glPopMatrix() if Numeric.alltrue(m==Numeric.zeros(16).astype('f')): # this happens when Pmv has no GUI m = Numeric.identity(4) if transpose: return Numeric.transpose(Numeric.reshape(m, (4,4))) else: return Numeric.reshape(m, (4,4)) def GetMatrixInverse(self, root=None, instance=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Returns the inverse of the matrix used to transform this object""" if root is None: root = self.viewer.rootObject m = self.GetMatrix(root, instance) m = Numeric.reshape(Numeric.transpose(m), (16,)).astype('f') rot, transl, scale = self.Decompose4x4(m) sc = Numeric.concatenate((Numeric.reshape(scale,(3,1)), [[1]])) n = Numeric.reshape(rot, (4,4))/sc tr = Numeric.dot(n, (transl[0], transl[1], transl[2],1) ) n[:3,3] = -tr[:3].astype('f') return n ## m[:3,:3] = Numeric.transpose(m[:3,:3]) ## m[:3,3] = -m[:3,3] ## s = Numeric.identity(4) * 1.0/root.scale[0] ## s[3,3] = 1.0 ## m = Numeric.dot(s, m) def FrameTransform(self, camera=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Build the R an RI, the object's frame transformation and inverse""" GL.glPushMatrix() self.Si = Numeric.ones( (3, ) ) GL.glLoadIdentity() if hasattr(self, 'parent'): if self.inheritXform: parent = self.parent while (parent): m = Numeric.reshape( parent.rotation, (4,4) ) upd = Numeric.reshape( Numeric.transpose(m), (16, ) ) GL.glMultMatrixf(upd) GL.glMultMatrixf(parent.MatrixRotInv) self.Si = self.Si / parent.scale self.Si = self.Si / parent.MatrixScale # we have to test here because we need to take into # account the first parent that does not inherit while # building R and Ri if not parent.inheritXform: break parent = parent.parent if camera: m = Numeric.reshape( camera.rotation, (4,4) ) upd = Numeric.reshape( Numeric.transpose(m), (16, ) ) GL.glMultMatrixf(upd) self.Si = self.Si / camera.scale self.Ri = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') GL.glPopMatrix() self.Ri = glCleanRotMat(self.Ri).astype('f') self.Ri.shape = (4,4) self.R = Numeric.reshape( Numeric.transpose(self.Ri), (16, ) ).astype('f') self.Ri.shape = (16, ) if self.redirectXform: self.redirectXform.FrameTransform(camera) for o in self.copyXform: o.FrameTransform(camera) def SetTransformation(self, matrix, transpose=False, redo=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the transformation matrix, if transpose is False the rotation should be in FORTRAN style """ if transpose: matrix = Numeric.array(Numeric.transpose(matrix), 'f') if not matrix.flags.contiguous: matrix = Numeric.array(matrix) rot, transl, scale = self.Decompose4x4(matrix.ravel()) self.SetRotation(rot.astype('f'), redo=False) self.SetTranslation(transl, redo=False) self.SetScale(scale, redo=False) if redo and self != self.viewer.rootObject and \ not self.immediateRendering: self.viewer.deleteOpenglList() self.viewer.Redraw() def SetRotation(self, matrix, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the rotation matrix to the object [matrix.shape==(16,)]""" assert matrix.shape == (16,) self._modified = True ## if self.redirectXform: obj = self.redirectXform ## else: obj = self self.rotation = matrix ## for o in self.copyXform: o.SetRotation(camera) if redo and self.viewer and self != self.viewer.rootObject and \ not self.immediateRendering: self.viewer.deleteOpenglList() #self.viewer.Redraw() def ConcatRotationRelative(self, matrix): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Apply the rotation matrix to the object (matrix.shape ==(16,) Unlike ConcatRotation you just concatenate the rotation of the object without considering Ri and R """ self._modified = True obj = self GL.glPushMatrix() GL.glLoadIdentity() ## GL.glMultMatrixf(obj.rotation) GL.glMultMatrixf(matrix) GL.glMultMatrixf(obj.rotation) m = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') obj.rotation = m.astype('f') obj.rotation.shape = (16, ) GL.glPopMatrix() def ConcatRotation(self, matrix, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Apply the rotation matrix to the object [matrix.shape==(16,)]""" if self.redirectXform: obj = self.redirectXform else: obj = self obj._modified = True GL.glPushMatrix() GL.glLoadIdentity() GL.glMultMatrixf(obj.Ri)#.astype('f')) GL.glMultMatrixf(matrix) GL.glMultMatrixf(obj.R)#.astype('f')) GL.glMultMatrixf(obj.rotation) m = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') obj.rotation = glCleanRotMat(m).astype('f') obj.rotation.shape = (16, ) GL.glPopMatrix() for o in self.copyXform: o.ConcatRotation(matrix) ## This code made rotation very slow because it would rebuild the ## master dpyList in cases where it was not needed ## if redo and not self.immediateRendering: ## vi = self.viewer ## print 'faga' ## vi.deleteOpenglList() vi = self.viewer if vi.activeClippingPlanes > 0 or vi.activeScissor > 0 or \ (vi.currentObject!=vi.rootObject and not \ vi.redirectTransformToRoot) and redo and \ not self.immediateRendering: vi.deleteOpenglList() def SetTranslation(self, trans, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the translation trans to the object""" assert trans.shape == (3,) self._modified = True ## if self.redirectXform: obj = self.redirectXform ## else: obj = self self.translation = trans ## for o in self.copyXform: o.SetTranslation(camera) if self.viewer and self != self.viewer.rootObject and redo and \ not self.immediateRendering: self.viewer.deleteOpenglList() #self.viewer.Redraw() def getCumulatedTranslation(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """calculate the translation cumulated from root """ obj = self lCumulatedTranslation = (0.,0.,0.) while obj != self.viewer.rootObject: lCumulatedTranslation += obj.translation obj = obj.parent lCumulatedTranslation += obj.translation # to add rootObject translation return lCumulatedTranslation def ConcatTranslation(self, trans, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Apply the translation trans to the object""" if self.redirectXform: obj = self.redirectXform else: obj = self obj._modified = True # MS. Feb 22 '99 obj.R does not contain the scaling factor # d = obj.Si * Numeric.array( trans ) #d = Numeric.array( trans ) #d = Numeric.concatenate( (d, [1.0]) ) # go to homogenous coords d = list(trans)+[1.0] rot = Numeric.reshape( obj.R, (4,4) ) ## obj.translation = obj.translation + \ ## Numeric.dot( rot, d )[:3] obj.translation = obj.translation + self.multMat4pt(rot, d) for o in self.copyXform: o.ConcatTranslation(trans) vi = self.viewer if vi.activeClippingPlanes > 0 or vi.activeScissor > 0 or \ (vi.currentObject!=vi.rootObject and not \ vi.redirectTransformToRoot) and redo and \ not self.immediateRendering: vi.deleteOpenglList() vi.Redraw() event = translateEvent('translate',obj) vi.dispatchEvent(event) def SetScale(self, scale, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the scaling factor of the object""" #print "SetScale", redo ## if self.redirectXform: obj = self.redirectXform ## else: obj = self self._modified = True scale = Numeric.array(scale) if self.isScalable: assert scale.shape == (3,) if scale[0] > 0.00 and scale[1] > 0.00 and scale[2] > 0.00: self.scale = scale ## for o in self.copyXform: o.SetScale(camera) if self.viewer and (self != self.viewer.rootObject or \ self.viewer.activeClippingPlanes > 0) and redo and \ not self.immediateRendering: self.viewer.deleteOpenglList() #self.viewer.Redraw() def ConcatScale(self, scale, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Multiply the object's scale by scale""" if self.redirectXform: obj = self.redirectXform else: obj = self obj._modified = True scale = Numeric.array([scale]) if obj.isScalable: if scale[0] > 1.0 or (obj.scale[0] > 0.0 and obj.scale[1] > 0.0 and obj.scale[2] > 0.0): obj.scale = obj.scale * scale for o in self.copyXform: o.ConcatScale(scale) #was o.ConcatScale(camera) vi = self.viewer if vi.activeClippingPlanes > 0 or vi.activeScissor > 0 or \ (vi.currentObject!=vi.rootObject and not \ vi.redirectTransformToRoot) and redo and \ not self.immediateRendering: vi.deleteOpenglList() def transformIsIdentity(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """return true if this object has the identity matrix as transformation""" mat = self.GetMatrix() diff = Numeric.sum( (mat-Numeric.identity(4)).ravel() ) if math.fabs(diff) < 0.00001: return True else: return False def transformationSourceCode(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """generate the source code for setting the current transformation. the returned arryaays can be used to g.SetXXX where XXX is Rotation, Translation, Scale or Pivot""" mat = self.GetMatrix() rot, trans, scale = self.Decompose4x4(Numeric.transpose(mat).ravel()) src = [] src.append("from numpy.oldnumeric import array\n") src.append("rot = " + repr(rot) + ".astype('f')\n") src.append("trans = " + repr(trans) + "\n") src.append("scale = " + repr(scale) + "\n") src.append("pivot = " + repr(scale) + "\n") return src mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/utils.py0000644000175000017500000000206510757401130021400 0ustar debiandebiandef RemoveDuplicatedVertices(vertices, faces, vnorms = None): """Remove duplicated vertices and re-index the polygonal faces such that they share vertices """ vl = {} vrl = {} nvert = 0 vertList = [] normList = [] for i,v in enumerate(vertices): key = '%f%f%f'%tuple(v) if not vl.has_key(key): vl[key] = nvert vrl[i] = nvert nvert +=1 vertList.append(v) if vnorms is not None: normList.append(vnorms[i]) else: nind = vl[key] vrl[i] = nind if vnorms is not None: vn1 = normList[nind] vn2 = vnorms[i] normList[nind] = [(vn1[0] +vn2[0])/2, (vn1[1] +vn2[1])/2, (vn1[2] +vn2[2])/2 ] faceList = [] for f in faces: faceList.append( map( lambda x, l=vrl: vrl[x], f ) ) if vnorms is not None: return vertList, faceList, normList return vertList, faceList mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Clip.py0000644000175000017500000003420411576435366021151 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Clip.py,v 1.49 2011/06/16 17:18:46 sanner Exp $ # # $Id: Clip.py,v 1.49 2011/06/16 17:18:46 sanner Exp $ # from opengltk.OpenGL import GL from opengltk.extent.utillib import glCleanRotMat from mglutil.math.rotax import rotVectToVect import numpy import numpy.oldnumeric as Numeric from viewerFns import getkw from math import sqrt from Transformable import Transformable from colorTool import OneColor, glMaterialWithCheck, resetMaterialMemory from capGeom import capMesh class ClippingPlane(Transformable): clipPlaneNames = [ ] #GL.GL_CLIP_PLANE0, GL.GL_CLIP_PLANE1, #GL.GL_CLIP_PLANE2, GL.GL_CLIP_PLANE3, #GL.GL_CLIP_PLANE4, GL.GL_CLIP_PLANE5 ] clipPlaneColors = [ (.4,1.,1.,1), (1.,.6,1.,1), (1.,1,.5,1), (.4,1,.4,1), (.5,.7,1,1), (1,.5,.8,1) ] directions = [(1., 0., 0, 1.), (0., 1., 0, 1.), (0., 0., 1, 1.), (1., 1., 0, 1.), (1., 0., 1, 1.), (0., 1., 1, 1.) ] def __init__(self, object, num, viewer): """Create a arbitrary clipping plane. self.translation represents the point in the plane's parent's space about which the plane will rotate. self.eqn is a vector of the 4 coefficients for the equation of a plane.""" self.name = 'ClipPlane'+str(num) Transformable.__init__(self, viewer) self.num = num self.id = self.clipPlaneNames[num] self.object = object self.Reset() self.direction = self.directions[num] rot = rotVectToVect(self.direction[:3], (1,.0,0.)) self.planeRot = numpy.array(rot, 'f').flatten() self.ConcatRotation(numpy.identity(4,'f').flatten()) def Reset(self): # FIXME since clipping planes are added to objects as they are created # this seems superfluous # the consequence is that one cannot disable a clipping plane without # loosing it! so we should have an add clipping plane button which # is separated from enabling the clipping plane self.hasBeenCurrent = False self.color = self.clipPlaneColors[self.num] self.lineWidth = 2 #self.antiAliased = 0 self.visible = False self.enabled = False #self.antialiased = False self.eqn = Numeric.array( [1.0, 0.0, 0.0, 0.0], Numeric.Float ) # this is coefficient vector of the equation of a plane Ax+By+Cz+D = 0 self.n = 1.0 self.FrameTransform() self.polyMode = GL.GL_LINE_STRIP self._modified = False def ResetTransformation(self, redo=1): """Reset the clipping plane's transformation""" Transformable.ResetTransformation(self) self.eqn = Numeric.array( [1.0, 0.0, 0.0, 0.0] ) self.n = 1.0 def __repr__(self): return '' % (self.name,str(self.eqn) ) def FrameTransform(self, camera=None): """Build the R an RI, the object's frame transformation and inverse""" GL.glPushMatrix() self.Si = Numeric.ones( (3, ) ) GL.glLoadIdentity() m = Numeric.reshape( self.object.rotation, (4,4) ) upd = Numeric.reshape( Numeric.transpose(m), (16, ) ) GL.glMultMatrixf(self.object.Ri) GL.glMultMatrixf(upd) GL.glMultMatrixf(self.object.MatrixRotInv) self.Si = self.Si * self.object.Si / (self.object.scale * self.object.MatrixScale) self.Ri = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') GL.glPopMatrix() #self.Ri = Numeric.reshape(glCleanRotMat(self.Ri), (4,4) ) self.Ri = glCleanRotMat(self.Ri) self.R = Numeric.reshape( Numeric.transpose(self.Ri), (16, ) ).astype('f') self.Ri = Numeric.reshape(self.Ri, (16, )).astype('f') if self.redirectXform: self.redirectXform.FrameTransform(camera) for o in self.copyXform: o.FrameTransform(camera) def _NormalizeN(self): eqn = Numeric.zeros( (3,), Numeric.Float ) for i in (0,1,2): eqn[i] = self.rotation[i] n = Numeric.add.reduce(eqn*eqn) assert n > 0.0 if n > 0.00001: self.n = 1.0 / sqrt( n ) self.eqn[:3] = eqn else: self.n = 1.0 self.eqn[:3] = [1.0, 0.0, 0.0] def ConcatRotation(self, matrix): """Overwrite rotation methods""" self._modified = True Transformable.ConcatRotation(self, matrix) self.rotation.shape = (4,4) #eqn = Numeric.array(self.rotation[0,:3]) # because direction is (1.,0.,0.) eqn = numpy.dot(self.direction, self.rotation) #print '=================================================' #print 'eqn', eqn, eqn.shape #self.n = 1.0 / sqrt( Numeric.add.reduce(eqn*eqn) ) x,y,z = eqn[:3] self.n = 1.0 / sqrt( x*x + y*y +z*z) self.eqn[:3] = eqn[:3] #print 'self.eqn',self.eqn self.eqn[3] = -Numeric.dot(self.eqn[:3], self.translation) #print self.eqn #get the value so that the plane is equivalent to having the proper #normal vector and a translation from the origin along the vector for o in self.copyXform: o._NormalizeN() self.rotation.shape = (16, ) self.viewer.deleteOpenglList() def ConcatTranslation(self, trans): """ Overwrite translation methods """ #print "ConcatTranslation", trans self._modified = True self.rotation.shape = (4,4) lTransInLocalSystem = Numeric.dot( (trans[0], trans[1], trans[2], 1.), self.rotation, )[:3] #print "ConcatTranslation", lTransInLocalSystem self.rotation.shape = (16, ) self.translation = self.translation + lTransInLocalSystem self.eqn[3] = -Numeric.dot(self.eqn[:3], self.translation) for o in self.copyXform: o.ConcatTranslation(lTransInLocalSystem) self.viewer.deleteOpenglList() def screenConcatTranslation(self, trans): """ Overwrite translation methods """ #print "localConcatTranslation", trans self._modified = True self.viewer.rootObject.rotation.shape = (4,4) self.viewer.rootObject.rotation.transpose() lTransInScreenSystem = Numeric.dot( self.viewer.rootObject.rotation, (trans[0], trans[1], trans[2], 1.), )[:3] self.viewer.rootObject.rotation.transpose() self.viewer.rootObject.rotation.shape = (16, ) self.translation = self.translation + lTransInScreenSystem self.eqn[3] = -Numeric.dot(self.eqn[:3], self.translation) for o in self.copyXform: o.ConcatTranslation(lTransInScreenSystem) self.viewer.deleteOpenglList() def _Enable(self, side): """Activate the clipping plane""" eqnt = self.eqn * side #eqnt[3] = 0.0 - eqnt[3] GL.glClipPlane(self.clipPlaneNames[self.num], eqnt) GL.glEnable(self.clipPlaneNames[self.num]) def _Disable(self): """Deactivate the clipping plane""" GL.glDisable(self.clipPlaneNames[self.num]) def Set(self, **kw): """Set various clipping plane parameters""" self.hasBeenCurrent = True # remember the light has been changed tagModified = True val = getkw(kw, 'tagModified') if val is not None: tagModified = val assert tagModified in [True, False] self._modified = tagModified val = getkw(kw, 'enabled') if not val is None: if val is True: self._Enable(1) elif val is False: self._Disable() else: raise AttributeError('enable can only be True or False') self.enabled = val val = getkw(kw, 'name') if not val is None: self.name = val val = getkw(kw, 'visible') if not val is None: if val in [False,True]: self.visible = val else: raise AttributeError('visible can only be 0 or 1') val = getkw(kw, 'color') if not val is None: col = OneColor( val ) if col: self.color = col val = getkw(kw, 'lineWidth') if not val is None: try: int(val) except: raise ValueError ('lineWidth must be a positive int') if val>=1: self.lineWidth = int(val) else: raise ValueError ('lineWidth must be a positive int') # val = getkw(kw, 'antialiased') # if not val is None: # if val in (True, False) : # self.antialiased = val # else: raise ValueError ('antialiased can only be YES or NO') val = getkw(kw, 'rotation') if not val is None: self.rotation = Numeric.identity(4, 'f').ravel() mat = Numeric.reshape(Numeric.array(val), (16,)).astype('f') self.ConcatRotation(mat) val = getkw(kw, 'translation') if not val is None: self.translation = Numeric.zeros( (3,), 'f') mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') self.ConcatTranslation(mat) val = getkw(kw, 'scale') if not val is None: self.SetScale( val ) val = getkw(kw, 'pivot') if not val is None: self.SetPivot( val ) if len(kw): print 'WARNING1: Keyword(s) %s not used' % kw.keys() if self.object.viewer: self.object.viewer.objectsNeedingRedo[self.object] = None self.object.viewer.Redraw() def setColor(self, val): self.Set(color=val) def getState(self): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ return {'enabled':self.enabled, 'name':self.name, 'visible':self.visible, 'color':self.color, 'lineWidth':self.lineWidth, #'antialiased':self.antialiased, 'rotation':list(self.rotation), 'translation':list(self.translation), 'scale':list(self.scale), 'pivot':list(self.pivot) } def DisplayFunction(self): """Draw a square with diagonals to represent the clipping plane """ #print "ClippingPlane.DisplayFunction" #trans = self.eqn[3]*(self.eqn[:3]*self.n) resetMaterialMemory() trans = self.translation GL.glPushMatrix() #GL.glTranslatef(-trans[0],-trans[1],-trans[2]) GL.glTranslatef(float(trans[0]), float(trans[1]), float(trans[2])) GL.glMultMatrixf(self.rotation) GL.glScalef(float(self.scale[0]), float(self.scale[1]), float(self.scale[2])) if self.polyMode == GL.GL_QUADS: GL.glPushAttrib(GL.GL_CURRENT_BIT | GL.GL_LIGHTING_BIT | GL.GL_POLYGON_BIT) GL.glDisable(GL.GL_LIGHTING) GL.glMaterialWithCheck(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT, self.color) if self.viewer is not None: self.viewer.enableOpenglLighting() GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL) GL.glPushMatrix() GL.glMultMatrixf(self.planeRot) GL.glBegin (GL.GL_QUADS) GL.glVertex3f (0.0, -5.0, -5.0) GL.glVertex3f (0.0, -5.0, 5.0) GL.glVertex3f (0.0, 5.0, 5.0) GL.glVertex3f (0.0, 5.0, -5.0) GL.glVertex3f (0.0, -5.0, -5.0) GL.glEnd () GL.glPopMatrix() GL.glPopAttrib() else: # MS disabling GL.GL_BLEND breaks display of transparent surfaces ## if self.antialiased==True: ## GL.glEnable(GL.GL_LINE_SMOOTH) ## GL.glEnable(GL.GL_BLEND) ## else: ## GL.glDisable(GL.GL_LINE_SMOOTH) ## GL.glDisable(GL.GL_BLEND) GL.glColor4fv (self.color) GL.glLineWidth(self.lineWidth) GL.glPushMatrix() GL.glMultMatrixf(self.planeRot) # could and should be a display list made once for all planes GL.glBegin (GL.GL_LINE_STRIP) GL.glVertex3f (0.0, -5.0, -5.0) GL.glVertex3f (0.0, -5.0, 5.0) GL.glVertex3f (0.0, 5.0, 5.0) GL.glVertex3f (0.0, 5.0, -5.0) GL.glVertex3f (0.0, -5.0, -5.0) GL.glVertex3f (0.0, 5.0, 5.0) GL.glVertex3f (0.0, -5.0, 5.0) GL.glVertex3f (0.0, 5.0, -5.0) GL.glEnd () GL.glPopMatrix() GL.glPopMatrix() def getCapMesh(self, geom, delta=0.01): x,y,z,s = self.eqn planeNormal = (x,y,z) delta *= -geom.clipSide[self.num] planePoint = (-x*(s+delta), -y*(s+delta), -z*(s+delta)) edges, faceEdges = geom.buildEdgeList() vertsC, facesC = capMesh( geom.getVertices(), edges, geom.getFaces(), faceEdges, planePoint, planeNormal, 0.01) vc = [] fc = [] for v, f in zip(vertsC, facesC): l = len(vc) vc.extend(v) fc.extend( [ (t[0]+l, t[1]+l, t[2]+l) for t in f] ) return vc, fc def ClipCapMesh(self, obj, onOff): if not hasattr(obj, 'buildEdgeList'): return vi = obj.viewer if onOff: x,y,z,s = self.eqn vc, fc = self.getCapMesh(obj) from DejaVu.IndexedPolygons import IndexedPolygons capg = IndexedPolygons( 'cap%d'%self.num, vertices=vc, faces=fc, fnormals = ( (-x,-y,-z),), inheritFrontPolyMode=False, frontPolyMode='fill', inheritBackPolyMode=False, backPolyMode='fill', inheritCulling=0, culling='none', inheritShading=0, shading='flat' ) vi.AddObject(capg, parent=obj) obj.capMesh = 1 vi.cappedGeoms.append( (obj, self, capg) ) else: obj.capMesh = 0 for g,c,gc in obj.viewer.cappedGeoms: #print 'trying to remove', g, self if g==obj and c==self: #print 'removing' vi.cappedGeoms.remove( (g,c,gc) ) vi.RemoveObject(gc) break if obj != vi.rootObject: vi.objectsNeedingRedo[obj] = None vi.Redraw() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/IndexedPolygons.py0000644000175000017500000001560611456141347023370 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # $Header: /opt/cvs/python/packages/share1.5/DejaVu/IndexedPolygons.py,v 1.55 2010/10/15 21:08:55 sargis Exp $ # # $Id: IndexedPolygons.py,v 1.55 2010/10/15 21:08:55 sargis Exp $ # import os import numpy.oldnumeric as Numeric from opengltk.OpenGL import GL from opengltk.extent import _gllib import DejaVu from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.Geom import Geom from DejaVu.IndexedGeom import IndexedGeom import datamodel, viewerConst from viewerFns import checkKeywords if hasattr(DejaVu, 'enableVertexArray') is False: DejaVu.enableVertexArray = False def IndexedPolygonsFromFile(filename, name=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """IndexedPolygons <- indexedPolygonsFromFile(filename, name=None) Create an IndexedPolygons object from a file saved using the geom.saveIndexedPolygons method. The extension of filename (if any) will be remove. filename.vert and filename.face should be present. The name arguemnt will be the name of the Geom object. If omitted, filename will be used. """ filename = os.path.splitext(filename)[0] from string import split f = open(filename+'.indpolvert') data = map(split, f.readlines()) f.close() verts = map( lambda x: (float(x[0]), float(x[1]), float(x[2])), data ) norms = map( lambda x: (float(x[3]), float(x[4]), float(x[5])), data ) f = open(filename+'.indpolface') data = map(split, f.readlines()) f.close() faces = [] fnorms = [] for line in data: faces.append( map( int, line[:-3]) ) fnorms.append( map( float, line[-3:]) ) if name is None: name = filename import numpy.oldnumeric as Numeric faces = Numeric.array(faces) if min(faces.ravel())==1: faces = faces - 1 pol = IndexedPolygons(name, vertices=verts, vnormals=norms, faces=faces) # FIXME face normals have to be set after the constructor else they are # overwritten with computed ones pol.Set(fnormals=fnorms, shading=GL.GL_FLAT) return pol class IndexedPolygons(IndexedPolylines): """Set of polygons sharing vertices """ def __init__(self, name=None, check=1, redo=1, replace=True, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "IndexedPolygons.__init__", name kw['replace'] = replace #if DejaVu.enableVertexArray is True: # kw['vertexArrayFlag'] = True # kw['immediateRendering'] = True apply( IndexedPolylines.__init__, (self, name, check), kw) def Set(self, check=1, redo=1, updateOwnGui=True, setCurrent=True, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set data for this object: Set polygon's vertices, faces, normals or materials check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( IndexedPolylines.Set, (self, check, 0), kw ) if hasattr(self, 'faceSet') \ and len(self.faceSet.faces.array) > 0 \ and len(self.faceSet.faces.array[0]) > 2 : self._PrimitiveType() return self.redoNow(redo, updateOwnGui, redoFlags, setCurrent) def delete(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.vertexSet.normals.Compute = None self.faceSet.normals.Compute = None def sortPoly(self, order=-1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """None <- sortPoly(order=-1) Sorts the geometry polygons according to z values of polygon's geomtric centers. Order=-1 sorts by furthest z first, order=1 sorts by closest z first""" # FIXME will not work with instance matrices mat = self.GetMatrix() mat = Numeric.reshape(mat, (4,4)) vt = self.vertexSet.vertices*mat if vt is None: return triv = Numeric.take(vt, self.faceSet.faces.array) trig = Numeric.sum(triv,1)/3. trigz = trig[:,2] #triangle's center of gravity z value ind = Numeric.argsort(trigz) # sorted indices if len(self.faceSet.faces.array): faces = Numeric.take(self.faceSet.faces.array, ind[::order]) if self.shading==GL.GL_FLAT: # we also need to re-arrange the # face normals if self.normals is None: normals = None else: if len(self.normals)>1: normals = Numeric.take(self.normals, ind[::order]) else: normals = self.normals else: normals = None self.Set(faces=faces, fnormals=normals) def asIndexedPolygons(self, run=1, removeDupVerts=0, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Should return an IndexedPolygons object if this object can be represented using triangles, else return None. run=0 returns 1 if this geom can be represented as an IndexedPolygon and None if not run=1 returns the IndexedPolygon object.""" if run==0: return 1 # yes, I can be represented as IndexedPolygons if removeDupVerts==0: return self else: vu, fu = self.removeDuplicatedVertices() return IndexedPolygons('copy_'+self.name, vertices=vu, faces=fu, visible=1, invertNormals=self.invertNormals) def writeToFile(self, filename): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """swriteToFile(filename) Creates a .vert and a face file describing this indexed polygons geoemtry. only vertices, and noramsl are saved the the .vert file (x y z nx ny nz) and 0-based topoly in the .face file (i, j, k, ... ). """ verts = self.getVertices() vnorms = self.getVNormals() fnorms = self.getFNormals() faces = self.getFaces() file = open(filename+'.indpolvert', 'w') map( lambda v, n, f=file: \ f.write("%f %f %f %f %f %f\n"%tuple(tuple(v)+tuple(n))), verts, vnorms) file.close() file = open(filename+'.indpolface', 'w') for v, face in zip(fnorms, faces): map( lambda ind, f=file: f.write("%d "%ind ), face ) file.write("%f %f %f\n"%tuple(v)) file.close() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/triangle_strip.py0000644000175000017500000004737211532033273023301 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: 2000 Authors: Michel Sanner, Kevin Chan # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI 2000 # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/triangle_strip.py,v 1.34 2011/02/25 23:09:47 annao Exp $ # # $Id: triangle_strip.py,v 1.34 2011/02/25 23:09:47 annao Exp $ # from opengltk.OpenGL import GL from opengltk.extent import _gllib as gllib from DejaVu.Geom import Geom from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.viewerFns import checkKeywords import DejaVu.datamodel, DejaVu.viewerConst import numpy.oldnumeric as Numeric from DejaVu.colorTool import glMaterialWithCheck, resetMaterialMemory class Triangle_strip(IndexedPolygons): """ Class to draw a triangle strip or multiple triangle strip geometries. """ keywords = IndexedPolygons.keywords + [ 'stripBegin', 'stripEnd', 'fnormals', ] def __init__(self, name=None, check=1, **kw): """ Constructor: Takes an array of vertices and splits it into separate triangle strips at specific vertices specified by stripBegin, which is and array of indices. Generates faceSet. In this class, a face corresponds to a triangle strip. Calls IndexedPolygons constructor. Calls MatBindingMode() to set the correct mode specific to a triangle strip, overwriting the binding mode set by MaterialBindingMode in the Geom class. Initializes frontPolyMode to FILL. Initializes currentCol and currentMat.""" self.stripBegin = None self.stripEnd = None self.normals = None apply( IndexedPolygons.__init__, (self, name, 0), kw ) for face in self.materials.keys(): for j in range(5): self.MatBindingMode(j, face) self.frontPolyMode = GL.GL_FILL #self.inheritFrontPolyMode = 0 self.currentCol = [] for i in range(4): self.currentCol.append(-1.0) self.currentMat = [] for i in range(2): mat = [] for j in range(5): rgba = [] for k in range(4): rgba.append(-1.0) mat.append(rgba) self.currentMat.append(mat) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ sb = kw.get('stripBegin') se = kw.get('stripEnd') v = kw.get('vertices') if not sb is None or not v is None: # Modify self.stripBegin only if another set of vertices is # given or antother set of stripBegin. self.stripBegin = sb if sb is None: self.stripBegin = [0, len(v)] if (se and len(self.stripBegin) != len(se)) or se is None: self.stripEnd = map(lambda x,sB = self.stripBegin : sB[x+1], range(len(self.stripBegin[:-1]))) self.stripBegin = self.stripBegin[:-1] else: self.stripEnd = se faces = [] # only self.stripBegin no sef.stripEnd or # len(self.stripBeg)!= len(sel.stripBeg) if self.stripBegin and self.stripEnd: for i in range(len(self.stripBegin)): strip_ind = () begStrip = self.stripBegin[i] endStrip = self.stripEnd[i] for j in range(begStrip, endStrip): strip_ind = strip_ind + (j,) faces.extend([strip_ind]) ## else: ## for i in range(0, len(self.stripBegin)-1): ## strip_ind = () ## for j in range(self.stripBegin[i], self.stripBegin[i+1]): ## strip_ind = strip_ind + (j,) ## print 'strip_ind', strip_ind ## faces.extend([strip_ind]) ## if self.stripBegin: ## for i in range(0, len(self.stripBegin)-1): ## strip_ind = () ## for j in range(self.stripBegin[i], self.stripBegin[i+1]): ## strip_ind = strip_ind + (j,) ## print 'strip_ind', strip_ind ## faces.extend([strip_ind]) kw['faces'] = faces self.fnormals = kw.get( 'fnormals') redoFlags = apply( IndexedPolygons.Set, (self, check, 0), kw ) return self.redoNow(redo, updateOwnGui, redoFlags) def MatBindingMode(self, propNum, face=GL.GL_FRONT): """ For the given face and material property corresponding to propNum, the method sets the binding mode. If there is one value, the mode is OVERALL; if the number of values equals the number of vertices, strips, or faces(triangles), the mode is PER_VERTEX, PER_PART, or PER_FACE, respectively. Else, mode is none. """ #NONE, OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 OVERALL, PER_VERTEX, PER_PART, PER_FACE = 10, 11, 12, 13 num = propNum f = face nn = self.materials[f].prop[num].shape[0] self.inheritMaterial = 0 if nn == 1: self.materials[f].binding[num] = OVERALL elif nn == len(self.vertexSet.vertices): self.materials[f].binding[num] = PER_VERTEX elif hasattr(self, 'faceSet') and nn == len(self.faceSet): self.materials[f].binding[num] = PER_PART elif hasattr(self, 'IndexedFaceSet') and nn==len(self.IndexedFaceSet): self.materials[f].binding[num] = PER_FACE self.shading = GL.GL_FLAT self.GetNormals() else: self.materials[f].binding[num] = -1 self.inheritMaterial = 1 def buildIndexedFaceSet(self): """Build the set of indices describing the strips""" f = [] for stripNum in range(len(self.stripBegin)): start = self.stripBegin[stripNum] end = self.stripEnd[stripNum] for i in range(start, end-3,2): f.extend([(i, i+1, i+2), (i+2, i+1, i+3)]) if (end-start) % 2== 1: f.extend([(end-3, end-2, end-1)]) ## if not self.stripEnd is None: ## for stripNum in range(len(self.stripBegin)): ## print 'stripNum', stripNum ## start = self.stripBegin[stripNum] ## end = self.stripEnd[stripNum] ## for i in range(start, end-3,2): ## f.extend([(i, i+1, i+2), (i+2, i+1, i+3)]) ## if (end-start) % 2== 1: ## f.extend([(end-3, end-2, end-1)]) ## else: ## for stripNum in range(1,len(self.stripBegin)): ## print 'stripNum' ## for i in range(self.stripBegin[stripNum-1], ## self.stripBegin[stripNum]-3, 2): ## f.extend([(i, i+1, i+2), (i+2, i+1, i+3)]) ## if (self.stripBegin[stripNum]-self.stripBegin[stripNum-1]) % 2== 1: ## f.extend([(self.stripBegin[stripNum]-3, ## self.stripBegin[stripNum]-2, ## self.stripBegin[stripNum]-1)]) self.IndexedFaceSet = DejaVu.datamodel.FaceSet( f, (0,0) ) def GetNormals(self): """ Gets the proper normals for smooth or flat shading. Calls buildIndexedFaceSet(). Sets face normals or computes them if not given. Sets object normals to the vertex normals for smooth shading or to the face normals for flat shading. If shading none, normals are none.""" if not self.stripBegin: return if self.shading==GL.GL_NONE: self.normals = None else: if hasattr(self, 'faceSet'): self.StripFaceSet = self.faceSet self.buildIndexedFaceSet() self.faceSet = self.IndexedFaceSet if self.fnormals is not None: self.faceSet.normals.SetValues(self.fnormals) else: self.FaceNormalFunction( self.ComputeFaceNormals ) self.faceSet.normals.ComputeMode( DejaVu.viewerConst.AUTO ) if self.shading==GL.GL_FLAT: if hasattr(self, 'faceSet'): self.normals = self.faceSet.normals.GetProperty() else: self.normals = None elif self.shading==GL.GL_SMOOTH: self.normals = self.vertexSet.normals.GetProperty() self.faceSet = self.StripFaceSet else: self.normals = None def isNewColor(self, c=None): """ Compares new color c to the current color. If the same, method returns 0. If the new color is different, the current color gets the values of the new color, and the method returns 1. """ if c == None or not c.all(): for i in self.currentCol: i = -1.0 # set an impossible color return 0 elif abs(c[0]-self.currentCol[0]) < 0.0001 and \ abs(c[1]-self.currentCol[1]) < 0.0001 and \ abs(c[2]-self.currentCol[2]) < 0.0001 and \ abs(c[3]-self.currentCol[3]) < 0.0001: return 0 else: self.currentCol[0] = c[0] self.currentCol[1] = c[1] self.currentCol[2] = c[2] self.currentCol[3] = c[3] return 1 ## def isNewMaterial(self, face, prop, c): ## """ For the given face (face) and property number (prop), the method ## compares the new material value c to the current material. If ## the same, method returns 0. If different, the current material gets ## the new material value, and the method returns 1. """ ## f = not(face==GL.GL_FRONT) ## if not c: ## for i in range(2): ## for j in range(5): ## for k in self.currentMat[i][j]: ## k = -1.0 ## return 0 ## elif abs(c[0]-self.currentMat[f][prop][0]) < 0.0001 and \ ## abs(c[1]-self.currentMat[f][prop][1]) < 0.0001 and \ ## abs(c[2]-self.currentMat[f][prop][2]) < 0.0001 and \ ## abs(c[3]-self.currentMat[f][prop][3]) < 0.0001: ## return 0 ## else: ## self.currentMat[f][prop][0] = c[0] ## self.currentMat[f][prop][1] = c[1] ## self.currentMat[f][prop][2] = c[2] ## self.currentMat[f][prop][3] = c[3] ## return 1 def DisplayFunction(self): """ Either executes the present display list or creates a display list to display the triangle strip. """ # if in select mode, switches to IndexedPolygons if self.viewer.currentCamera.renderMode == GL.GL_SELECT: temp = self.primitiveType if self.frontPolyMode == GL.GL_FILL: self.primitiveType = GL.GL_POLYGON elif self.frontPolyMode == GL.GL_LINE: self.primitiveType = GL.GL_LINE_LOOP elif self.frontPolyMode == GL.GL_POINT: self.primitiveType = GL.GL_POINTS self.faceSet = self.IndexedFaceSet IndexedPolygons.DisplayFunction(self) self.faceSet = self.StripFaceSet self.primitiveType = temp return if self.dpyList: Geom.DisplayFunction(self) def Draw(self): OVERALL, PER_VERTEX, PER_PART, PER_FACE = 10, 11, 12, 13 #NONE, OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 propConst = DejaVu.viewerConst.propConst noCol = 1 vert = self.vertexSet.vertices.array if len(vert)==0: return if not self.stripBegin or len(self.stripBegin)==0: return if self.materials[GL.GL_FRONT] and not self.inheritMaterial: frontMat = fpProp = [] frontMatBind = fpBind = [] mat = self.materials[GL.GL_FRONT] for propInd in range(4): b, p = mat.GetProperty(propInd) fpProp.append(p) fpBind.append(b) fpProp.append(mat.prop[4]) fpBind.append(mat.binding[4]) else: frontMat = None frontMatBind = None if self.materials[GL.GL_BACK] and not self.inheritMaterial: backMat = bpProp = [] backMatBind = bpBind = [] mat = self.materials[GL.GL_BACK] for propInd in range(4): b, p = mat.GetProperty(propInd) bpProp.append(p) bpBind.append(b) bpProp.append(mat.prop[4]) bpBind.append(mat.binding[4]) else: backMat = None backMatBind = None if not self.frontAndBack is None: face = GL.GL_FRONT else: face = GL.GL_FRONT_AND_BACK n = self.normals if self.normals is None: # overall color for no normals or lighting if frontMat: if frontMatBind[noCol] == OVERALL: GL.glColor4fv( frontMat[noCol][0] ) else: if len(self.normals)==1: # overall normal GL.glNormal3dv(n[0]) if frontMat: for j in range(5): # overall materials if frontMatBind[j] == OVERALL: glMaterialWithCheck( face, propConst[j], frontMat[j][0] ) if backMat and not self.frontAndBack: for j in range(5): if backMatBind[j] == OVERALL: glMaterialWithCheck( GL.GL_BACK, propConst[j], backMat[j][0] ) self.isNewColor() #self.isNewMaterial(0,0,0) # loop over each strip sB = self.stripBegin sE = self.stripEnd self.sE = sE self.sB= sB for stripNum in range(len(sB)): #print 'stripNum',stripNum GL.glPushName(stripNum) GL.glBegin(GL.GL_TRIANGLE_STRIP) # per part material properties if frontMat: if frontMatBind[noCol] == PER_PART: if self.isNewColor(c=frontMat[noCol][stripNum]): GL.glColor4fv(frontMat[noCol][stripNum]) if n is not None: if frontMat: for j in range(5): if frontMatBind[j]==PER_PART: glMaterialWithCheck( face, propConst[j], frontMat[j][stripNum] ) if backMat and not self.frontAndBack: for j in range(5): if backMatBind[j] == PER_PART: glMaterialWithCheck( GL.GL_BACK, propConst[j], backMat[j][stripNum] ) # loop over each vertex in a strip i = 0 for ind in range(sB[stripNum],sE[stripNum]): if ind >= len(vert): print 'ERROR',ind v = vert[ind] # normals for flat or smooth shading if n is not None: if self.shading==GL.GL_FLAT: if i > 1: GL.glNormal3dv(n[sB[stripNum]+i-(2*(stripNum+1))]) elif self.shading==GL.GL_SMOOTH: GL.glNormal3fv(n[ind]) else: pass # per face (per triangle) material properties if n is None: if frontMat: if frontMatBind[noCol] == PER_FACE: if i > 1: if self.isNewColor(c=frontMat[noCol][sB[stripNum]+i-(2*(stripNum+1))]): GL.glColor4fv(frontMat[noCol][sB[stripNum]+i-(2*(stripNum+1))]) else: if frontMat: for k in range(5): if frontMatBind[k] == PER_FACE: if i > 1: glMaterialWithCheck( face, propConst[k], frontMat[k][sB[stripNum]+i-(2*(stripNum+1))] ) if backMat and not self.frontAndBack: for k in range(5): if backMatBind[k] == PER_FACE: if i > 1 and i%2==0: glMaterialWithCheck( GL.GL_BACK, propConst[k], backMat[k][sB[stripNum]+i-(2*(stripNum+1))] ) # per vertex material properties if n is None: if frontMat: if frontMatBind[noCol] == PER_VERTEX: if self.isNewColor(c=frontMat[noCol][sB[stripNum]+i]): GL.glColor4fv(frontMat[noCol][sB[stripNum]+i]) else: if frontMat: for k in range(5): if frontMatBind[k] == PER_VERTEX: glMaterialWithCheck( face, propConst[k], frontMat[k][sB[stripNum]+i] ) if backMat and not self.frontAndBack: for k in range(5): if backMatBind[k] == PER_VERTEX: glMaterialWithCheck( GL.GL_BACK, propConst[k], backMat[k][sB[stripNum]+i] ) # draw vertex #GL.glVertex3dv(v) gllib.glVertex3fv(v) i = i + 1 GL.glEnd() GL.glPopName() return 1 if __name__=='__main__': import pdb, numpy.oldnumeric as Numeric from DejaVu import Viewer vi = Viewer() vert = [(0, 1, 0), (1, 0, 1), (1, 1, 0), (2, 0, -1), (2, 1, 0), (3, 0, 1), (3, 1, 0), (4, 0, -1), (4, 1, 0), (5, 0, 1), (5, 3, 0), (6, -2, 1)] v1 = Numeric.array(vert) v2 = v1 + 3.0 v3 = Numeric.concatenate( (v1,v2) ) colors = [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0)] v4 = v2 + 3.0 v5 = Numeric.concatenate( (v3,v4) ) strip3 = Triangle_strip(vertices = v5, stripBegin=[0,12], materials = [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0)]) #strip.Set(materials = [(1, 0, 0)]) vi.AddObject(strip3) strip2 = Triangle_strip(vertices = v3, stripBegin=[0,12,24], materials = colors+colors[0:8]) #strip2.Set(materials = [(0, 1, 0), (0, 0, 1)]) vi.AddObject(strip2) strip = Triangle_strip(vertices = vert, materials = colors[2:12]) #strip.Set(materials = [(1, 0, 0)]) vi.AddObject(strip) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/colors.py0000644000175000017500000002220411351726516021547 0ustar debiandebian## from matplotlib.colors import cnames, hex2color ## for name, hex in cnames.items(): ## r,g,b = hex2color(hex) ## print "%-25s = (%5.3f,%5.3f, %5.3f)"%(name, r, g, b) ## names = cnames.keys() ## names.sort() ## print 'cnames = ', names cnames = [ 'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dimgrey', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey', 'honeydew', 'hotpink', 'indianred', 'indigo', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen'] indigo = (0.294,0.000, 0.510) gold = (1.000,0.843, 0.000) firebrick = (0.698,0.133, 0.133) indianred = (0.804,0.361, 0.361) yellow = (1.000,1.000, 0.000) darkolivegreen = (0.333,0.420, 0.184) darkseagreen = (0.561,0.737, 0.561) slategrey = (0.439,0.502, 0.565) darkslategrey = (0.184,0.310, 0.310) mediumvioletred = (0.780,0.082, 0.522) mediumorchid = (0.729,0.333, 0.827) chartreuse = (0.498,1.000, 0.000) mediumslateblue = (0.482,0.408, 0.933) black = (0.000,0.000, 0.000) springgreen = (0.000,1.000, 0.498) crimson = (0.863,0.078, 0.235) lightsalmon = (1.000,0.627, 0.478) brown = (0.647,0.165, 0.165) turquoise = (0.251,0.878, 0.816) olivedrab = (0.420,0.557, 0.137) cyan = (0.000,1.000, 1.000) silver = (0.753,0.753, 0.753) skyblue = (0.529,0.808, 0.922) gray = (0.502,0.502, 0.502) darkturquoise = (0.000,0.808, 0.820) goldenrod = (0.855,0.647, 0.125) darkgreen = (0.000,0.392, 0.000) darkviolet = (0.580,0.000, 0.827) darkgray = (0.663,0.663, 0.663) lightpink = (1.000,0.714, 0.757) teal = (0.000,0.502, 0.502) darkmagenta = (0.545,0.000, 0.545) lightgoldenrodyellow = (0.980,0.980, 0.824) lavender = (0.902,0.902, 0.980) yellowgreen = (0.604,0.804, 0.196) thistle = (0.847,0.749, 0.847) violet = (0.933,0.510, 0.933) navy = (0.000,0.000, 0.502) dimgrey = (0.412,0.412, 0.412) orchid = (0.855,0.439, 0.839) blue = (0.000,0.000, 1.000) ghostwhite = (0.973,0.973, 1.000) honeydew = (0.941,1.000, 0.941) cornflowerblue = (0.392,0.584, 0.929) darkblue = (0.000,0.000, 0.545) darkkhaki = (0.741,0.718, 0.420) mediumpurple = (0.576,0.439, 0.859) cornsilk = (1.000,0.973, 0.863) red = (1.000,0.000, 0.000) bisque = (1.000,0.894, 0.769) slategray = (0.439,0.502, 0.565) darkcyan = (0.000,0.545, 0.545) khaki = (0.941,0.902, 0.549) wheat = (0.961,0.871, 0.702) deepskyblue = (0.000,0.749, 1.000) darkred = (0.545,0.000, 0.000) steelblue = (0.275,0.510, 0.706) aliceblue = (0.941,0.973, 1.000) lightslategrey = (0.467,0.533, 0.600) gainsboro = (0.863,0.863, 0.863) mediumturquoise = (0.282,0.820, 0.800) floralwhite = (1.000,0.980, 0.941) coral = (1.000,0.498, 0.314) purple = (0.502,0.000, 0.502) lightgrey = (0.827,0.827, 0.827) lightcyan = (0.878,1.000, 1.000) darksalmon = (0.914,0.588, 0.478) beige = (0.961,0.961, 0.863) azure = (0.941,1.000, 1.000) lightsteelblue = (0.690,0.769, 0.871) oldlace = (0.992,0.961, 0.902) greenyellow = (0.678,1.000, 0.184) royalblue = (0.255,0.412, 0.882) lightseagreen = (0.125,0.698, 0.667) mistyrose = (1.000,0.894, 0.882) sienna = (0.627,0.322, 0.176) lightcoral = (0.941,0.502, 0.502) orangered = (1.000,0.271, 0.000) navajowhite = (1.000,0.871, 0.678) lime = (0.000,1.000, 0.000) palegreen = (0.596,0.984, 0.596) burlywood = (0.871,0.722, 0.529) seashell = (1.000,0.961, 0.933) mediumspringgreen = (0.000,0.980, 0.604) fuchsia = (1.000,0.000, 1.000) papayawhip = (1.000,0.937, 0.835) blanchedalmond = (1.000,0.922, 0.804) peru = (0.804,0.522, 0.247) aquamarine = (0.498,1.000, 0.831) white = (1.000,1.000, 1.000) darkslategray = (0.184,0.310, 0.310) ivory = (1.000,1.000, 0.941) dodgerblue = (0.118,0.565, 1.000) lemonchiffon = (1.000,0.980, 0.804) chocolate = (0.824,0.412, 0.118) orange = (1.000,0.647, 0.000) forestgreen = (0.133,0.545, 0.133) slateblue = (0.416,0.353, 0.804) olive = (0.502,0.502, 0.000) mintcream = (0.961,1.000, 0.980) antiquewhite = (0.980,0.922, 0.843) darkorange = (1.000,0.549, 0.000) cadetblue = (0.373,0.620, 0.627) moccasin = (1.000,0.894, 0.710) limegreen = (0.196,0.804, 0.196) saddlebrown = (0.545,0.271, 0.075) grey = (0.502,0.502, 0.502) darkslateblue = (0.282,0.239, 0.545) lightskyblue = (0.529,0.808, 0.980) deeppink = (1.000,0.078, 0.576) plum = (0.867,0.627, 0.867) aqua = (0.000,1.000, 1.000) darkgoldenrod = (0.722,0.525, 0.043) maroon = (0.502,0.000, 0.000) sandybrown = (0.980,0.643, 0.376) magenta = (1.000,0.000, 1.000) tan = (0.824,0.706, 0.549) rosybrown = (0.737,0.561, 0.561) pink = (1.000,0.753, 0.796) lightblue = (0.678,0.847, 0.902) palevioletred = (0.686,0.933, 0.933) mediumseagreen = (0.235,0.702, 0.443) dimgray = (0.412,0.412, 0.412) powderblue = (0.690,0.878, 0.902) seagreen = (0.180,0.545, 0.341) snow = (1.000,0.980, 0.980) mediumblue = (0.000,0.000, 0.804) midnightblue = (0.098,0.098, 0.439) palegoldenrod = (0.933,0.910, 0.667) whitesmoke = (0.961,0.961, 0.961) darkorchid = (0.600,0.196, 0.800) salmon = (0.980,0.502, 0.447) lightslategray = (0.467,0.533, 0.600) lawngreen = (0.486,0.988, 0.000) lightgreen = (0.565,0.933, 0.565) tomato = (1.000,0.388, 0.278) hotpink = (1.000,0.412, 0.706) lightyellow = (1.000,1.000, 0.878) lavenderblush = (1.000,0.941, 0.961) linen = (0.980,0.941, 0.902) mediumaquamarine = (0.400,0.804, 0.667) green = (0.000,0.502, 0.000) blueviolet = (0.541,0.169, 0.886) peachpuff = (1.000,0.855, 0.725) darkgrey = (0.663,0.663, 0.663) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/blenderScene.py0000644000175000017500000007441611247327435022654 0ustar debiandebianfrom opengltk.OpenGL import GL #from opengltk.extent.utillib import glTriangleNormals from geomutils.geomalgorithms import TriangleNormals import numpy.oldnumeric as Numeric, math, string, warnings from mglutil.math import rotax from mglutil.util.misc import ensureFontCase from DejaVu.Geom import Geom from DejaVu.IndexedGeom import IndexedGeom from DejaVu.Transformable import Transformable from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.Spheres import Spheres from DejaVu.Cylinders import Cylinders from DejaVu import viewerConst from DejaVu.colorTool import glMaterialWithCheck from DejaVu.GleObjects import GleExtrude from DejaVu.glfLabels import GlfLabels from DejaVu.DataOutput import * from DejaVu import colorTool import Tkinter, Pmw from mglutil.gui.InputForm.Tk.gui import InputFormDescr, InputForm class OutputBlender(OutputNode): def __init__(self): OutputNode.__init__(self) self.geomName = None self.Transformable = Transformable() self.completeFlag = 1 # is set in getBlender() self.saveNormalsFlag = 0 # is set in getBlender() self.colorPerVertexFlag = True # set in getBlender() self.usePROTOFlag = 0 # if set, instanceMatrice geoms are not # saved as geoms, but re-used with PROTO self.sphereQuality = 2 # default quality for sphere subsampling self.cylinderQuality = 10 # default quality for cyl. subsampling def getBlender(self, root, complete=1, normals=0, colorPerVertex=True, usePROTO=0, sphereQuality=2, cylinderQuality=10): """ this method returns a list of strings describing DejaVu Geoms in blender python API format """ # this is the method the user should call self.completeFlag = complete # if 1, header and footer will be added self.saveNormalsFlag = normals # if 1, normals are added self.colorPerVertexFlag = colorPerVertex # if False, color per face self.usePROTOFlag = usePROTO # if set to 1, instance geoms are saved # with one PROTO. Else: data for these # geoms will be prepared which blows up # the file size self.sphereQuality = sphereQuality # default is 2 self.cylinderQuality = cylinderQuality # default is 10 self.output = [] if self.completeFlag: self.output.extend(self.getCopyright()) self.output.extend(self.getFileHeader1()) self.loopGeoms(root) return self.output def NodeRepr(self, geom, matrix): # called recursively from loopGeom() if not self.checkGeom(geom): return # call the progress bar update self.configureProgressBar(labeltext='parse '+geom.name) self.updateProgressBar() # IndexedGeoms, Spheres and Cylinders have to be treated differently if isinstance(geom, IndexedPolygons) or \ isinstance(geom, IndexedPolylines): self.output.extend( self.doit(geom, matrix) ) elif isinstance(geom, Spheres): # convert Spheres geom into IndexedPolygons sphGeom = geom.asIndexedPolygons(quality=self.sphereQuality) sphGeom.viewer = geom.viewer sphGeom.parent = geom.parent sphGeom.name = geom.name sphGeom.fullName = geom.fullName sphGeom.instanceMatrices = geom.instanceMatrices sphGeom.instanceMatricesIndex = geom.instanceMatricesIndex sphGeom.VRML2CreatedPROTOForThisGeom = 0 self.output.extend( self.doit(sphGeom, matrix) ) elif isinstance(geom, Cylinders): # convert Cylinders geom into IndexedPolygons cylGeom = geom.asIndexedPolygons(quality=self.cylinderQuality) cylGeom.viewer = geom.viewer cylGeom.parent = geom.parent cylGeom.name = geom.name cylGeom.fullName = geom.fullName cylGeom.instanceMatrices = geom.instanceMatrices cylGeom.instanceMatricesIndex = geom.instanceMatricesIndex cylGeom.VRML2CreatedPROTOForThisGeom = 0 self.output.extend( self.doit(cylGeom, matrix) ) elif isinstance(geom, GlfLabels): # convert Cylinders geom into IndexedPolygons glfGeom = geom.asIndexedPolygons() glfGeom.viewer = geom.viewer glfGeom.parent = geom.parent glfGeom.name = geom.name glfGeom.fullName = geom.fullName glfGeom.instanceMatrices = geom.instanceMatrices glfGeom.instanceMatricesIndex = geom.instanceMatricesIndex glfGeom.VRML2CreatedPROTOForThisGeom = 0 self.output.extend( self.doit(glfGeom, matrix) ) def doit(self, geom, matrix): # gets called from NodeRepr() blender = [] # if self.usePROTO is set to 1: don't convert instance matrices # geoms into geoms, but use the vrml2 USE if self.usePROTOFlag: # create all the necessary data to be put in the PROTO which goes # in the header of the vrml2 file if geom.VRML2CreatedPROTOForThisGeom == 0: name = self.getGeomName(geom) blender.append("PROTO "+name+" [ ] {\n") identityMatrix = Numeric.identity(4).astype('f') blender.extend( self.doitReally(geom, identityMatrix) ) blender.append("}\n") # now insert this into the header of self.output for i in range(len(vrml2)): self.output.insert(i+1,blender[i]) geom.VRML2CreatedPROTOForThisGeom = 1 # don't add this geom # to the header next time # this PROTO flag will be deleted when we leave the recursive # and add it as USE to the body blender = [] # clear the list because this data has been added blender.extend( self.doitUsePROTO(geom, matrix) ) return blender else: # here we save all the data for all geoms return self.doitReally(geom, matrix) def doitReally(self, geom, matrix): # add header for geom blender = [] blender.extend(self.getGeomHeader(geom)) mat, colors = self.getMaterial(geom) # add texture if applicable: #if geom.texture: # blender.extend( self.getTexture(geom) ) # add coords, faces, etc blender.extend( self.getGeomDescr(geom) ) # add texCoord Coordinates is applicable #if geom.texture: # blender.extend( self.getTexCoords(geom) ) # add texCoordsIndex if applicable #if hasattr(geom.vertexSet,'texCoordsIndex'): # blender.extend( self.getTexCoordsIndex(geom)) # add normals if applicable #if self.saveNormalsFlag and isinstance(geom, IndexedPolygons): # blender.extend( self.getNormals(geom) ) # add colors per vertex if applicable if colors is not None and len(colors): blender.extend( self.getColors(geom, colors) ) # add transformations for geom #blender.extend( self.getTransforms(matrix) ) # add closing bracket for Transform{} #blender.append(" }\n") return blender def doitUsePROTO(self, geom, matrix): # FIXME: this works currently only with geoms that are not grouped # i.e. it doesnt work with secondary structures, they will be saved # as PROTO too, but also for each instanceMatrix (->redundant) vrml2 = [] geom.instanceMatricesIndex = 0 name = string.split(self.getGeomHeader(geom)[0])[1] vrml2.append(" Transform {\n") vrml2.append(" children "+name+" { }\n") # add transformations for geom vrml2.extend( self.getTransforms(matrix) ) # add closing bracket for Transform{} vrml2.append(" }\n") return vrml2 def getFileHeader1(self): blender=[] blender.append("#!BPY\n") blender.append("""import sys, os, os.path, struct, math, string import Blender import bpy from Blender import * from Blender.Mathutils import * from Blender import Object from Blender import Material from Blender import Window, Scene, Draw import BPyMesh def createsNmesh(name,vertices,vnormals,faces,mat=None): vlist = [] me=bpy.data.meshes.new(name) me.verts.extend(vertices) # add vertices to mesh me.faces.extend(faces) # add faces to the mesh (also adds edges) #smooth face : the vertex normals are averaged to make this face look smooth for face in me.faces: face.smooth=1 me.calcNormals() if mat == None : mat = Material.New('test') mat.R = 0.8 mat.G = 1.0 mat.B = 1.0 me.materials=[mat] ob = Blender.Object.New("Mesh") ob.link(me) return ob,me sc=Blender.Scene.GetCurrent() """) blender.append("\n") return blender def getCopyright(self): blender=[] blender.append(""" ############################################################################# #Blender Scene Export v1.1 by Ludovic Autin # Date: August 2009 Author: Ludovic Autin # # autin@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Ludovic Autin and TSRI # # ############################################################################# """) blender.append("\n") return blender def getGeomName(self, geom): g = geom name = "Pmv_" while g != geom.viewer.rootObject: # g.name can contain whitespaces which we have to get rid of gname = string.split(g.name) ggname = "" for i in gname: ggname = ggname + i name = name + string.strip(ggname)+"AT"+\ string.strip(str(g.instanceMatricesIndex))+ '_' g = g.parent name=string.replace(name,"-","_") return name def getGeomHeader(self, geom): # generates geom name blender=[] g = geom name = self.getGeomName(geom) blender.append("#Geom "+name+"\nname=\""+name+"\"\n") blender.append("mat=None\n") return blender def getMaterial(self, geom): blender=[] name = self.getGeomName(geom) mat = geom.materials[GL.GL_FRONT].prop[:] geom.materials[GL.GL_FRONT].colorIndex = None # will be used later on colors = None # if only 1 color present, skip this all and use the ambient definition # below if len(mat[1])> 1: colors = mat[1] # The ZCorp printer software doesn't support color_per_face, # but Pmv does. So, we create a colorIndex list for special cases # However, the user can still choose between coloring # per face and per vertex # FIXME: test for primitive type, i.e. tri_strip or quad_strip # currently this works only for tri_strips if isinstance(geom, GleExtrude): # special case! faces = geom.faceSet.faces.array # triangle_strips ifaces = geom.getFaces() # indexed geom # if the user forces to save color per vertex: if self.colorPerVertexFlag is True: colorIndex = Numeric.zeros( (ifaces.shape[0], \ ifaces.shape[1]) ) c = 0 cc = 0 for face in faces: for j in range(len(face)-2): # -2 because of tri_strip colorIndex[cc] = c cc = cc + 1 c = c + 1 geom.materials[GL.GL_FRONT].colorIndex = colorIndex elif isinstance(geom, IndexedPolygons): mat[1]=[mat[1][0]] vertices = geom.getVertices() faces = geom.getFaces() # if current colors are per face: if len(colors) != len(vertices) and len(colors) == len(faces): # if the user forces colors per vertices: if self.colorPerVertexFlag is True: colorIndex = Numeric.zeros( (faces.shape[0], \ faces.shape[1]) ) c = 0 for face in faces: for f in face: colorIndex[c] = c c = c + 1 geom.materials[GL.GL_FRONT].colorIndex = colorIndex # if current colors are per vertex else: # if the user forces colors per face: if self.colorPerVertexFlag is False: # code from Michel Sanner follows (thanks Michel!): vcol = geom.materials[1028].prop[1] tri = geom.faceSet.faces.array verts= geom.vertexSet.vertices.array colors = [] for t in tri: s1,s2,s3 = t col = ( (vcol[s1][0]+vcol[s2][0]+vcol[s3][0])/3., (vcol[s1][1]+vcol[s2][1]+vcol[s3][1])/3., (vcol[s1][2]+vcol[s2][2]+vcol[s3][2])/3. ) colors.append( col) ambInt = '%.5f'%mat[0][0][0] difCol = '%.5f'%mat[1][0][0]+" "+'%.5f'%mat[1][0][1]+" "+\ '%.5f'%mat[1][0][2] emCol = '%.5f'%mat[2][0][0]+" "+'%.5f'%mat[2][0][1]+" "+\ '%.5f'%mat[2][0][2] specCol = '%.5f'%mat[3][0][0]+" "+'%.5f'%mat[3][0][1]+" "+\ '%.5f'%mat[3][0][2] shin = '%.5f'%mat[4][0] trans = `1-mat[5][0]` blender.append("mat = Material.New('mat"+name+"')") blender.append("mat.R = '%.5f'n" %mat[1][0][0]) blender.append("mat.G = '%.5f'n" %mat[1][0][1]) blender.append("mat.B = '%.5f'n" %mat[1][0][2]) #vrml2.append(" material Material {\n") #vrml2.append(" ambientIntensity "+ambInt+"\n") #vrml2.append(" diffuseColor "+difCol+"\n") #vrml2.append(" emissiveColor "+emCol+"\n") #vrml2.append(" specularColor "+specCol+"\n") #vrml2.append(" shininess "+shin+"\n") #vrml2.append(" transparency "+trans+"\n") #vrml2.append(" }\n") return blender, colors def getGeomDescr(self, geom): blender = [] name = self.getGeomName(geom) if isinstance(geom, IndexedPolygons): #blender.append("vertices=\n") # add vertices blender.extend( self.getCoords(geom) ) # add face indices blender.extend( self.getFaces(geom) ) blender.extend( self.getNormals(geom) ) # add color indices if applicable #if geom.materials[GL.GL_FRONT].colorIndex is not None and len(geom.materials[GL.GL_FRONT].colorIndex): # vrml2.extend( self.getColorIndex(geom) ) blender.append(""+name+",mesh"+name+"=createsNmesh(name,vertices,vnormals,faces,mat=mat)\n") blender.append("sc.link("+name+")\n") #elif isinstance(geom, IndexedPolylines): # vrml2.append(" geometry IndexedLineSet {\n") # # add vertices # vrml2.extend( self.getCoords(geom) ) # # add face indices # vrml2.extend( self.getFaces(geom) ) return blender ## added by A Gillet 04/13/2006 def getTexture(self,geom): """ return PixelTexture Node PixelTexture { image 0 0 0 # exposedField SFImage repeatS True # field SFBool repeatT True # field SFBool } the value of the image field specifies image size and pixel values for a texture image width (in pixel) height (in pixel) number of 8-bit bytes for each pixel recognize values are: 0 disable texturing for shape 1 Grayscale 2 Grayscale with alpha 3 RGB 4 RGB with alpha (Info taken from Book " VRML 2.0 source book by Andrea L. Ames, David R. Nadeau and John L. Moreland ") """ vrml2=[] tex = geom.texture dims = tex.image.shape vrml2.append("\n") vrml2.append(" texture PixelTexture {\n") width = dims[0] if len(dims) == 3: height = dims[1] num_byte = dims[2] elif len(dims)==1: height = 1 num_byte = len(tex.image[0]) elif len(dims)==2: height = 1 num_byte = dims[1] vrml2.append(" image "+`width`+" "+`height`+" "+`num_byte`+"\n") if len(dims) == 3: # we have a 2D texture (image) countW =0 for r in tex.image: # row for c in r: # column istring = "0x" for i in range(3): hexa = "%X"%c[i] if len(hexa)==1: hexa = "0"+hexa istring = istring+ hexa istring = istring + " " vrml2.append(istring) vrml2.append("\n") vrml2.append(" }\n") else: # we have a 1-dimensional array for line in tex.image: istring = "0x" for i in range(len(line)): hexa = "%X"%line[i] if len(hexa)==1: hexa = "0"+hexa istring = istring+ hexa istring = istring + "\n" vrml2.append(istring) vrml2.append(" }\n") return vrml2 ## Daniel Stoffler code ## def getTexture(self, geom): ## vrml2=[] ## dims = geom.texture.image.shape ## vrml2.append("\n") ## vrml2.append(" texture PixelTexture {\n") ## # FIXME : what are real dimensions of image? ## # I never tested this for images larger than one-dimensional array ## vrml2.append(" image "+`dims[0]`+" "+`1`+" "+\ ## `len(geom.texture.image[0])`+"\n") ## for line in geom.texture.image: ## istring = "0x" ## for i in range(len(line)): ## hexa = "%X"%line[i] ## if len(hexa)==1: hexa = "0"+hexa ## istring = istring+ hexa ## istring = istring + "\n" ## vrml2.append(istring) ## vrml2.append(" }\n") ## return vrml2 def getCoords(self, geom): blender=[] vertices = geom.getVertices() blender.append("vertices=[") for vert in vertices: vstring = "[%.5f,%.5f,%.5f]," % (vert[0],vert[1],vert[2]) blender.append(vstring) blender[-1][-1].replace(",","") blender.append("]\n") return blender def getFaces(self, geom): #print "getFaces" blender=[] faces = geom.getFaces() blender.append("faces=[") for face in faces: facestring = "[%d,%d,%d]," % (face[0],face[1],face[2]) blender.append(facestring) #for face in faces: # facestring = " " # if geom.invertNormals: # reverse faces # facestring = facestring + `face[0]` + ", " # for i in range(len(face)-1,0,-1): # facestring = facestring + `face[i]` + ", " # else: # for f in face: # facestring = facestring + `f` + ", "# # # facestring = facestring + "-1,\n" # blender.append(facestring) blender[-1][-1].replace(",","") blender.append("]\n") return blender def getColorIndex(self, geom): # only called if len(colors) != len(faces) vrml2 = [] colorIndex = geom.materials[GL.GL_FRONT].colorIndex vrml2.append(" colorIndex [\n") for cI in colorIndex: cIstring = " " for c in cI: cIstring = cIstring + `c` +", " cIstring = cIstring + "-1,\n" vrml2.append(cIstring) vrml2.append(" ]\n") # clean up the geom object del geom.materials[GL.GL_FRONT].colorIndex return vrml2 def getNormals(self, geom): if geom.invertNormals: fn = -1.0 * geom.normals vn = -1.0 * geom.getVNormals() else: fn = geom.normals vn = geom.getVNormals() blender=[] blender.append("vnormals=[") for n in vn: blender.append("[%d,%d,%d]," % (n[0],n[1],n[2])) blender[-1][-1].replace(",","") blender.append("]\n") return blender def getTexCoords(self, geom): vrml2=[] vrml2.append("\n") vrml2.append(" texCoord TextureCoordinate {\n") vrml2.append(" point [\n") for p in geom.vertexSet.texCoords.array: if len(p) == 1: # one dimension array vrml2.append(" "+`p[0]`+" 0,\n") else: vrml2.append(" "+`p[0]`+" "+`p[1]`+",\n") vrml2.append(" ]\n") vrml2.append(" }\n") return vrml2 def getTexCoordsIndex(self, geom): vrml2=[] texCoordsIndex = geom.vertexSet.texCoordsIndex.array vrml2.append(" texCoordIndex [\n") for face in texCoordsIndex: indexstring = " " for i in face: indexstring = indexstring + `i` + ", " indexstring = indexstring + "-1,\n" vrml2.append(indexstring) vrml2.append(" ]\n") return vrml2 def blenderColor(self,col): if max(col)<=1.0: col = map( lambda x: x*255, col) return col def getColors(self, geom, colors): name = self.getGeomName(geom) blender=[] blender.append("\n") blender.append("colors=[") #color foreach vertices for c in colors: c=self.blenderColor(c) cstring = "[%d,%d,%d]," % (c[0],c[1],c[2]) blender.append(cstring) blender[-1][-1].replace(",","") blender.append("]\n\n") blender.append("mesh"+name+".vertexColors = 1 # enable vertex colors \n") blender.append("for f in mesh"+name+".faces:\n") blender.append(" for i, v in enumerate(f):\n") blender.append(" col= f.col[i]\n") blender.append(" col.r= colors[v.index][0]\n") blender.append(" col.g= colors[v.index][1]\n") blender.append(" col.b= colors[v.index][2]\n") blender.append("mesh"+name+".materials[0].setMode(\"VColPaint\")\n") return blender def getTransforms(self, matrix): vrml2=[] #mymatrix = matrix.__copy__() #mymatrix = Numeric.reshape(mymatrix, (16,)) mymatrix = Numeric.reshape(matrix, (16,)) rot,trans,scale=self.Transformable.Decompose4x4(mymatrix) r = rotax.mat_to_quat(rot) r[3]=r[3]*math.pi/180.0 #convert to rad r[0] = round(r[0],6) r[1] = round(r[1],6) r[2] = round(r[2],6) r[3] = round(r[3],6) vrml2.append(" translation "+`trans[0]`+" "+`trans[1]`+" "+\ `trans[2]`+"\n") vrml2.append(" rotation "+`r[0]`+" "+`r[1]`+" "+\ `r[2]`+" "+`r[3]`+"\n") vrml2.append(" scale "+`scale[0]`+" "+`scale[1]`+" "+\ `scale[2]`+"\n") return vrml2 def write(self,entries, filename): """void <- write(filename) dumps gelato scene description""" self.filename = filename f = open(filename, 'w') for entry in entries: f.write(entry) f.close() #from DejaVu import blenderScene #outB=blenderScene.OutputBlender() #m=self.getMolFromName('1crn') #g=m.geomContainer.geoms['MSMS-MOL'] #g=m.geomContainer.masterGeom #test=outB.getBlender(g,complete=1) #outB.write(test,"test_blender.py") class BlenderGUI(DatGUI): """This is the gui for OutputBlender: - Save normals adds normals to all geoms to be saved as vrml2 - Invert normals inverts the normals for all geoms to be saved as vrml2 - colorPerVertex: True by default. If set to False, color per face is used - Using PROTO will define a prototype geom which can be reused. This is usefull to lower the file size when instanceMatrices are applied. - Sphere quality is the subsampling of the spheres. Default value is 2 lowest allowed value is 0. Higher values increase the file size significantly. - Cylinder quality is the subsampling of cylinders. Default value is 10 lowest allowed value is 3. """ def __init__(self, master=None, title=None): DatGUI.__init__(self, master, title) self.saveNormals = Tkinter.IntVar() self.colorPerVertex = Tkinter.IntVar() self.colorPerVertex.set(1) # on by default self.usePROTO = Tkinter.IntVar() self.createForm() def createForm(self): row = 0 self.idf.append({'name':'savNormals', 'widgetType':Tkinter.Checkbutton, 'wcfg':{'text':'Save Normals ', 'variable':self.saveNormals, 'command':self.saveNormals_cb}, 'gridcfg':{'sticky':'w', 'columnspan':2, 'row':row, 'column':0} }) row+= 1 self.idf.append({'widgetType':Tkinter.Frame, 'wcfg':{'relief':'sunken','borderwidth':2,'height':2}, 'gridcfg':{'columnspan':2, 'row':row, 'column':0}, }) row += 1 self.idf.append({'name':'colorPerVertex', 'widgetType':Tkinter.Checkbutton, 'wcfg':{'text':'color per vertex', 'variable':self.colorPerVertex, 'command':self.colorPerVertex_cb}, 'gridcfg':{'sticky':'w', 'columnspan':2, 'row':row, 'column':0} }) row+= 1 self.idf.append({'widgetType':Tkinter.Frame, 'wcfg':{'relief':'sunken','borderwidth':2,'height':2}, 'gridcfg':{'columnspan':2, 'row':row, 'column':0}, }) row+= 1 self.idf.append({'name':'usePROTO', 'widgetType':Tkinter.Checkbutton, 'wcfg':{'text':'Use PROTO for instance\n'+\ 'matrices to lower file size', 'variable':self.usePROTO, 'command':self.usePROTO_cb}, 'gridcfg':{'sticky':'w', 'columnspan':2, 'row':row, 'column':0} }) row+= 1 self.idf.append({'widgetType':Tkinter.Frame, 'wcfg':{'relief':'sunken','borderwidth':2,'height':2}, 'gridcfg':{'columnspan':2, 'row':row, 'column':0}, }) row+= 1 self.idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Sphere quality'}, 'gridcfg':{'sticky':'w','columnspan':2, 'row':row, 'column':0}, }) self.idf.append({'name':'inpSphQual', 'widgetType':Tkinter.Entry, 'defaultValue':'2', 'wcfg':{'font':(ensureFontCase('Courier'),10), 'width':5,'textvariable':self.sphInput, 'command':self.sphereQuality_cb, }, 'gridcfg':{'sticky':'e', 'columnspan':2, 'row':row, 'column':1 } }) row+= 1 self.idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Cylinder quality'}, 'gridcfg':{'sticky':'w','columnspan':2, 'row':row, 'column':0}, }) self.idf.append({'name':'inpCylQual', 'widgetType':Tkinter.Entry, 'defaultValue':'10', 'wcfg':{'font':(ensureFontCase('Courier'),10), 'width':5,'textvariable':self.cylInput, 'command':self.cylinderQuality_cb, }, 'gridcfg':{'sticky':'e', 'columnspan':2, 'row':row, 'column':1 } }) row+= 1 self.idf.append({'widgetType':Tkinter.Button, 'text':'OK', 'wcfg':{}, 'gridcfg':{'sticky':'wens', 'columnspan':1, 'row':row, 'column':0}, 'command': self.OK_cb}) self.idf.append({'widgetType':Tkinter.Button, 'text':'Cancel', 'wcfg':{}, 'gridcfg':{'sticky':'wens', 'columnspan':1, 'row':row, 'column':1}, 'command': self.Cancel_cb}) def saveNormals_cb(self): pass def colorPerVertex_cb(self): pass def usePROTO_cb(self): pass def getValues(self): vals = {} vals['saveNormals'] = self.saveNormals.get() co = self.colorPerVertex.get() if co == 1: co = True else: co = False vals['colorPerVertex'] = co vals['usePROTO'] = self.usePROTO.get() vals['sphereQuality'] = self.sphereQuality vals['cylinderQuality'] = self.cylinderQuality return vals mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Slider.py0000644000175000017500000002023610614466344021474 0ustar debiandebian############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# """ Slider Module This module implements a class for Sliders. constructor: def __init__(self, master=None, label=None, minval=0.0, maxval=100.0, incr=None, init=None, width=150, height=20, withValue=1, immediate=1, left=10, right=10 ): Usage: After instanciating a Slider 's' one needs to pack() it s.frame.pack(). This is not done automatically in order to provide the user with some flexibility with respect to the slider's placement. One or more callback function(s) also need to be registered. A callback function takes one argument that will hold the slider's value. Methods: slider.Set(value): set the slider programatically to a value slider.Get(): get the current value slider.AddCallback(func): register a callback function Examples: def MyCallback1(color): print 'in MyCallback1: ',color def MyCallback2(color): print 'in MyCallback1: ',color sl1 = Slider(None, label='Continuous slider', height=40, minval=0.1, maxval = 10.0, init=5.0) sl1.frame.pack() sl1.AddCallback(MyCallback1) sl2 = Slider(None, label='multiple of 1.5 slider', minval=0.0, maxval = 10.0, incr=1.5) sl2.frame.pack() sl2.AddCallback(MyCallback2) sl3 = Slider(None, label='No value slider', minval=0.1, maxval = 1.0, init=1.0, withValue=0) sl3.frame.pack() sl4 = Slider(None, label='Non immediate slider', minval=5., maxval = 25.0, init=10.0, immediate=0, left=50, right=5) sl4.frame.pack() sl4.AddCallback(MyCallback1) sl4.AddCallback(MyCallback2) sl1.Set(1.0) sl2.Set(5.2) sl3.Set(100.0) """ # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Slider.py,v 1.8 2007/04/27 21:36:36 vareille Exp $ # # $Id: Slider.py,v 1.8 2007/04/27 21:36:36 vareille Exp $ # #from Tkinter import * import Tkinter from EventHandler import CallbackFunctions import types class Slider(CallbackFunctions): """Class for a simple slider""" def Callbacks(self): """Implement call to all callbacks""" for f in self.callbacks: if self.lookup: f(self.lookup[int(round(self.val))]) else: f(self.val) def MoveCursor(self, event): """Callback function for left mouse button""" x = event.x - self.left self._MoveCursor(x) def DrawCursor(self): """Update graphics representatin of the cursor""" # compute position x = (self.val-self.min)*self.cst deltax = x - self.lastx if self.withValue: #self.draw.itemconfig(self.valueLabel, text = str(self.val) ) if self.lookup: val = self.lookup[int(round(self.val))] else: val = self.val self.draw.itemconfig(self.valueLabel, text = (self.labelformat)%val ) self.draw.move('cursor', deltax, 0 ) self.lastx = self.lastx + deltax def _MoveCursor(self, x): """Compute value and move the cursor to the new position""" # compute the new value #minType = type(self.min) val = self.min+self.cst1 * x if self.incrCanvas: #valType = type(val) val = round(val/self.incr)*self.incr val = eval(self.cursortype+'('+str(val)+')') #if minType is types.IntType: #val = int(val) if valself.max: val = self.max # check if redraw and callback are needed if self.val != val: self.val = val self.DrawCursor() if self.immediate: self.Callbacks() def Set(self, val, update=1): """Set the cursor""" if valself.max: val = self.max if self.incrCanvas: #valType = type(val) val = round(val/self.incr)*self.incr val = eval(self.cursortype+'('+str(val)+')') #if valType is types.IntType: #val = int(val) self.val = val self.DrawCursor() if update: self.Callbacks() return self.val def SetMin(self, val): """Set the minimum value of the slider""" if val>self.max: return self.min = val self._ComputeCst() self.DrawCursor() def SetMax(self, val): """Set the maximum value of the slider""" if val", self.MoveCursor) Tkinter.Widget.bind(self.draw, "", self.MoveCursor) if not immediate: Tkinter.Widget.bind(self.draw, "", self.MouseUp) if __name__ == '__main__': def MyCallback(color): print color def MyCallback2(color): print 'hello' sl1 = Slider(None, label='Continuous slider', height=40, minval=0.1, maxval = 10.0, init=5.0) sl1.frame.pack() sl1.AddCallback(MyCallback) sl2 = Slider(None, label='multiple of 1.5 slider', minval=0.0, maxval = 10.0, incr=1.5) sl2.frame.pack() sl2.AddCallback(MyCallback2) sl3 = Slider(None, label='No value slider', minval=0.1, maxval = 1.0, init=1.0, withValue=0) sl3.frame.pack() sl4 = Slider(None, label='Non immediate slider', minval=5., maxval = 25.0, init=10.0, immediate=0, left=50, right=5) sl4.frame.pack() sl4.AddCallback(MyCallback) sl4.AddCallback(MyCallback2) #sl1.Set(1.0) sl2.Set(5.2) #sl3.Set(100.0) #slider for discrete values sl5 = Slider(None, label='discrete slider', labelformat='%4d', immediate=0, lookup=[10, 15, 25, 46, 78, 99] ) sl5.frame.pack() # slider for non numeric values sl6 = Slider(None, label='string slider', labelformat='%s', immediate=0, lookup=['Pierre', 'Paul', 'Jean', 'Jessica']) sl6.frame.pack() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/GeomChooser.py0000644000175000017500000001240112064444316022453 0ustar debiandebian""" This module provides a Geoemtry picker for DejaVu Geometry objects """ from DejaVu import Viewer from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ObjectChooser import Tkinter class GeomChooser: """ The GeomChooser object display a list of geometry object present in a given DejaVu.Viewer object. """ def __init__(self, viewer, showAll=True, filterFunction=None, root=None, command=None, refreshButton=False, showAllButton=False): """ GeomChooser constructor GeomChooserObject <- GeomChooser(viewer) - viewer is an instance of a DejaVu.Viewer object - showAll is a boolean. When True all objects are shown - filterFunction is an optional function that will be called when showAll is False. I takes one argument (the viewer) and returns a list of (name, [geoms]) pairs. The names will be displayed in the GUI for representing the corresponding list of geometry objects. - root is the master in which the chooser will be created. - command is the fucntion call upon selection in the list """ assert isinstance(viewer, Viewer) self.root = root self.viewer = viewer self.frame = Tkinter.Frame(root) self.frame1 = None if refreshButton or showAllButton: f1 = self.frame1 = Tkinter.Frame(root) if refreshButton: self.refresh = Tkinter.Button(f1, text='Refresh Lists', command=self.updateList) #self.refresh.pack(side='left', fill="x", expand=1) self.refresh.pack(side='top', fill="x", expand=1,pady=3) if showAllButton: self.showAllVar = Tkinter.IntVar() self.showAllVar.set(0) self.show = Tkinter.Checkbutton( f1, text='Show all objects', variable=self.showAllVar, command=self.showAll_cb) #self.show.pack(side='left', fill="x", expand=1) self.show.pack(side='top', fill="x", expand=1, pady=3) self.frame1.pack(side = 'top', fill='x', expand=1) assert isinstance(showAll, bool) self.showAll = showAll if filterFunction is not None: assert callable(filterFunction) self.filterFunction = filterFunction self.geomList = [] self.root = root self.chooserW = ObjectChooser( self.frame, mode='single', title='Choose Object', command=command, lbpackcfg={'fill':'both', 'expand':1} ) #self.chooserW.pack(side='left', fill='both', expand=1) self.chooserW.pack(side='top', fill='both', expand=1) self.buildListOfGeoms() self.setList() self.chooserW.widget.configure(exportselection = False) # this is done to prevent disappearing #of the ListBox selection when a text is selected in another widget or window. def onSelect(self, event): pass def buildListOfGeoms(self): self.geomList = [] if self.showAll or self.filterFunction is None: for g in self.viewer.rootObject.AllObjects(): self.geomList.append( (g.fullName, [g]) ) else: self.geomList = self.filterFunction(self.viewer) #for n, g in self.geomList: # print n def setList(self): self.chooserW.clear() self.chooserW.setObjects(self.geomList) def updateList(self): lb = self.chooserW.lb selection = lb.curselection() self.buildListOfGeoms() self.setList() for i in selection: lb.selection_set(i) #def get(self): # return self.chooserW.get() def get(self, event = None): res = [] sel = self.chooserW.lb.curselection() if not sel: return res for ent in map( int, sel ): obj= self.geomList[ent][1] res.append(obj) if self.chooserW.mode=='single' and res: res = res[0] return res def showAll_cb(self, even=None): val = self.showAllVar.get() self.showAll = val self.updateList() def grid(self,**kw): """Applies the specified keywords (kw) to the grid method of the frame containing geometry chooser""" self.frame.grid(kw) if not kw.has_key('row'): row = 0 else: row = kw['row'] if not kw.has_key('column'): column=0 else: column=kw['column'] if kw.has_key('weight'): weight = kw['weight'] else: weight = 1 self.frame.rowconfigure(row, weight=weight) self.frame.columnconfigure(column, weight=weight) def grid_forget(self): """Calls grid_forget() method of the frame containing geometry chooser""" self.frame.grid_forget() def pack(self, **kw): """Applies the specified keywords (kw) to the pack method of the frame containing geometry chooser""" self.frame.pack(kw) def pack_forget(self): """Calls pack_forget() method of the frame containing geometry chooser""" self.frame.pack_forget() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Arcs3D.py0000644000175000017500000002756411111132470021323 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Arcs3D.py,v 1.29 2008/11/20 00:54:16 vareille Exp $ # # $Id: Arcs3D.py,v 1.29 2008/11/20 00:54:16 vareille Exp $ # from opengltk.OpenGL import GL import math, numpy.oldnumeric as Numeric, types from math import sqrt, fabs, pi, cos, sin, acos, atan2 from Geom import Geom from Polylines import Polylines import datamodel, viewerConst from viewerFns import checkKeywords, getkw from DejaVu.colorTool import resetMaterialMemory def valideFloat(values, length): """This function takes a single float, or int or a list of them and a requested length and returns a list of float of length 1 or length. """ if type(values)==types.FloatType: return [values] elif type(values)==types.IntType: return [float(values)] else: if len(values)==1: return [float(values[0])] else: assert len(values)==length return [float(v) for v in values] class Fan3D(Geom): keywords = Geom.keywords + [ 'radii', """either single float or list of same length as vertices""", 'angles', """either single float or list of same length as vertices""", 'vectors', """normalized vector where fan starts, either single 3D vector or list of same length as vertices""", ] def __init__(self, name=None, check=1, **kw): if not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set self.radii = (0.2,) self.angles = (360.0,) self.vectors = None self.degreesPerSegment = 10. self.frontPolyMode = self.backPolyMode = GL.GL_FILL self.inheritFrontPolyMode = self.inheritBackPolyMode = 0 apply( Geom.__init__, (self, name, check), kw) assert len(self.vertexSet.vertices.ashape)==2 self._modified = False def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: add faces (polygon or lines) to this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( Geom.Set, (self, check, 0), kw) c = self.vertexSet.vertices rad = kw.get('radii') if rad is not None: values = valideFloat(rad, len(c)) if values is not None: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.radii = values ang = getkw(kw, 'angles') if ang is not None: values = valideFloat(ang, len(c)) if values is not None: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.angles = values vec = getkw(kw, 'vectors') if vec is not None: if len(vec)==3: self.vectors = [vec] else: assert len(vec)==len(c) for v in vec: assert len(v)==3 self.vectors = vec redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): for i in xrange(len(self.vertexSet)): if len(self.radii)==1: rad = self.radii[0] else: rad = self.radii[i] if len(self.angles)==1: ang = self.angles[0] else: ang = self.angles[i] vx, vy, vz = norm = self.vertexSet.normals.array[i] if self.vectors is None: # get orthogonal vector dx, dy, dz = fabs(vx), fabs(vy), fabs(vz) mini= min( [dx, dy, dz] ) if mini==dx: nov = 1./sqrt( vz*vz+ vy*vy ) ovx = 0. ovy = -vz*nov ovz = vy*nov elif mini==dy: nov = 1./sqrt( vz*vz+ vx*vx ) ovx = -vz*nov ovy = 0. ovz = vx*nov else: nov = 1./sqrt( vy*vy+ vx*vx ) ovx = -vy*nov ovy = vx*nov ovz = 0. vec = [ovx, ovy, ovz] elif len(self.vectors)==1: vec = self.vectors[0] else: vec = self.vectors[i] angRad = ang*pi*0.00555555555556 nsegments = int(ang/self.degreesPerSegment) + 1 d = angRad / nsegments # increment a = 0 # starting angle GL.glNormal3fv(norm.astype('f')) GL.glPushName(i) GL.glBegin(GL.GL_TRIANGLE_FAN) if self.materials[GL.GL_FRONT].binding[0]==viewerConst.PER_VERTEX: col = self.materials[GL.GL_FRONT].prop[0] GL.glColor4fv(col[i]) center = Numeric.array(self.vertexSet.vertices.array[i]) vec = Numeric.array(vec).astype('f') #vec = vec/sqrt(Numeric.sum(vec*vec)) vec2 = Numeric.zeros(3, 'f') vec2[0] = vec[1]*norm[2] - vec[2]*norm[1] vec2[1] = vec[2]*norm[0] - vec[0]*norm[2] vec2[2] = vec[0]*norm[1] - vec[1]*norm[0] GL.glVertex3fv(center) for j in range(nsegments+1): p = center + cos(a)*vec*rad + sin(a)*vec2*rad GL.glVertex3fv(p.astype('f')) a = a+d GL.glEnd() GL.glPopName() return 1 class Arcs3D(Geom): """Class for sets of cylinders""" keywords = Geom.keywords + [ 'radii', 'angles', 'quality', ] def __init__(self, name=None, check=1, **kw): if not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set self.radii = (0.2,) self.angles = (360.0,) self.lighting = False self.nsegments = 10 apply( Geom.__init__, (self, name, check), kw) assert len(self.vertexSet.vertices.ashape)==2 def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: Set polylines's vertices check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( Geom.Set, (self, check, 0), kw ) c = self.vertexSet.vertices rad = kw.get('radii') if rad is not None: values = valideFloat(rad, len(c)) if values is not None: self.radii = values redoFlags |= self._redoFlags['redoDisplayListFlag'] ang = getkw(kw, 'angles') if ang is not None: values = valideFloat(ang, len(c)) if values is not None: self.angles = values redoFlags |= self._redoFlags['redoDisplayListFlag'] quality = getkw(kw, 'quality') if quality is not None: assert type(quality)==types.IntType and quality > 1 self.nsegments = quality redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): n = self.vertexSet.normals.array c = self.vertexSet.vertices.array ang = self.angles if len(self.angles)==1: self._arcTemplate(self.anges[0]) if self.materials[GL.GL_FRONT].binding[1]==viewerConst.PER_VERTEX: col = self.materials[GL.GL_FRONT].prop[1] for i in xrange(len(self.vertexSet)): if len(self.radii)==1: rad = self.radii[0] else: rad = self.radii[i] GL.glPushName(i) self.arcdraw( c[i], n[i], rad, col[i] ) GL.glPopName() else: col = self.materials[GL.GL_FRONT].prop[1][0] for i in xrange(len(self.vertexSet)): if len(self.radii)==1: rad = self.radii[0] else: rad = self.radii[i] GL.glPushName(i) self.arcdraw( c[i], n[i], rad, col ) GL.glPopName() else: if self.materials[GL.GL_FRONT].binding[1]==viewerConst.PER_VERTEX: col = self.materials[GL.GL_FRONT].prop[1] for i in xrange(len(self.vertexSet)): if i==0 or ang[i]!=ang[i-1]: self._arcTemplate(ang[i]) if len(self.radii)==1: rad = self.radii[0] else: rad = self.radii[i] GL.glPushName(i) self.arcdraw( c[i], n[i], rad, col[i] ) GL.glPopName() else: col = self.materials[GL.GL_FRONT].prop[1][0] for i in xrange(len(self.vertexSet)): if i==0 or ang[i]!=ang[i-1]: self._arcTemplate(ang[i]) if len(self.radii)==1: rad = self.radii[0] else: rad = self.radii[i] GL.glPushName(i) self.arcdraw( c[i], n[i], rad, col ) GL.glPopName() def _arcTemplate(self, angle): nsegments = self.nsegments assert (nsegments>1) import numpy.oldnumeric as Numeric, math self.v = Numeric.zeros( ((nsegments+1),3), 'f') self.n = Numeric.zeros( ((nsegments+1),3), 'f') self.nsegments = nsegments angRad = angle*pi*0.00555555555556 a = -pi # starting angle d = angRad / nsegments # increment for i in range(nsegments+1): self.n[i][0] = self.v[i][0] = cos(a) self.n[i][1] = self.v[i][1] = sin(a) self.n[i][2] = 1.0 self.v[i][2] = 0.0 a=a+d def arcdraw(self, x, n, radius, colxf=None): # determine scale and rotation of template import math sz=0.0 y = [0, 0, 0] for i in (0,1,2): y[i] = x[i]+n[i] for i in (0,1,2): sz=sz+(x[i]-y[i])*(x[i]-y[i]) sz = sqrt(sz) if sz==0.0: return rx = -180.0*acos((y[2]-x[2])/sz)/pi rz = -180.0*atan2(y[0]-x[0],y[1]-x[1])/pi GL.glPushMatrix() GL.glTranslatef(float(x[0]),float(x[1]),float(x[2])) if rz<=180.0 and rz >=-180.0: GL.glRotatef(float(rz), 0., 0., 1.) GL.glRotatef(float(rx), 1., 0., 0.) GL.glScalef(float(radius),float(radius),float(sz)) # draw circle GL.glColor4fv(colxf) GL.glBegin(GL.GL_LINE_STRIP) for i in range(self.nsegments+1): GL.glVertex3fv(self.v[i]) GL.glEnd() GL.glPopMatrix() if __name__ == '__main__': from DejaVu.Arcs3D import Arcs3D, Fan3D c = Arcs3D('arc3d', vertices = ((0,0,0), (5.,0.,0.)), vnormals = ((1.0,0,0), (0, 1.,0)), materials = ( (1,0,0), (0,0,1)), radii = (1.0, 2.0), angles = ( 360., 180. )) f = Fan3D('fan3d', vertices = ((0,0,0), (5.,0.,0.)), vnormals = ((0,0,1), (0, 1.,0)), materials = ( (1,0,0), (0,0,1)), radii = (1.0, 2.0), angles = ( 60., 170. ), vectors = ((1,1,0), (1,0,0))) from DejaVu import Viewer vi = Viewer() vi.AddObject(c) vi.AddObject(f) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/.packager.py0000644000175000017500000000564407770420343022111 0ustar debiandebian# The .packager.py is used by the DistTools package to get the files to be # included in a distribution. def getFiles(root, what = 'all', plat=None): """ files <- getFiles(root, what='all', plat=None) files -- list of the files to be included in the download arguments: root -- path to the package. This is used by glob to get all the python modules. what -- string that can be 'all' and 'supported' to specified what files to include in the distribution. By default 'all' the files are added. plat -- platform ('linux2', 'irix646', 'sunos5' etc...) """ import os from glob import glob # 1- Specify the list of all the Python module allPyModule = ["*.py", "ViPEr/*.py", "materialsDef/*.py", 'gui/*.py'] # 2- Specify the list of the non supported Python module. These files # will be removed from the release of the supported python modules. pynotsupported = [] # 3- Specify the documentation files and directories to be included in the # release docFiles = ["Tutorial"] # 4-Specify the extraFiles to be included in the release. extraFiles = ["*.ppm", 'CVS', "ViPEr/CVS", "materialsDef/CVS", 'gui/CVS', "RELNOTES"] # 5-Specify the testFiles to be included in the release. testFiles = ["Tests","ViPEr/Tests"] ######################################################### ## Where things are done for you . ######################################################### # if some files need to be removed, we need the exact list of the pymodule. if len(pynotsupported): # store the path of the current directory olddir = os.getcwd() os.chdir(root) files = [] # we use glob to get the exact list of files. for p in allPyModule: files = files + glob(p) allPyModule = files files = [] # need to get the list of the files ... no wild card possible. for p in pynotsupported: files = files + glob(p) pynotsupported = files os.chdir(olddir) # Creation of the proper list of files depending on the value of what if what == 'supported' and len(pynotsupported): # need to remove the non supported python files from all the python # files # These are the keys used for to make the releases... supportedFiles = filter(lambda x, l = pynotsupported: not x in l, allPyModule) return supportedFiles + testFiles + extraFiles elif what == 'all' or ( what == 'supported' and not len(pynotsupported)): # Other wise just add the documentation, test and extra files to all # the python modules. allFiles= allPyModule + docFiles + testFiles + extraFiles return allFiles elif what == 'documentation': return docFiles else: return [] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Textured2DArray.py0000644000175000017500000001046211220747343023236 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import numpy.oldnumeric as Numeric from DejaVu.colorTool import RGBARamp from DejaVu.Texture import Texture from DejaVu.viewerFns import checkKeywords from DejaVu.colorMap import ColorMap from DejaVu.IndexedPolygons import IndexedPolygons class textured2DArray(IndexedPolygons): """Draw a quad with a 2D array textured mapped on it using a colormap""" keywords = IndexedPolygons.keywords + [ 'array', # 2D array of data to be turned into texture 'colormap', # colormap used for mapping data inot colors 'min', # min value used for mapping data inot colors 'max', # max value used for mapping data inot colors ] def __init__(self, name='textured2DArray', check=1, redo=1, **kw): # default colormap self.colormap = ColorMap('default', RGBARamp()) # 2d array self.array = None if not kw.has_key('inheritMaterial'): kw['inheritMaterial'] = 0 if not kw.has_key('culling'): kw['culling'] = 'none' if not kw.has_key('blendFunctions'): kw['blendFunctions'] = ('GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA') if not kw.has_key('frontPolyMode'): kw['frontPolyMode'] = 'fill' if not kw.has_key('backPolyMode'): kw['backPolyMode'] = 'fill' if not kw.has_key('shading'): kw['shading'] = 'flat' if not kw.has_key('vertices'): kw['vertices'] = ((0.,0,0), (1,0,0), (1,1,0), (0,1,0)) kw['faces'] = ((0,1,2,3),) #kw['faces'] = ( (0, 1, 2), (0, 2, 3) ) apply( IndexedPolygons.__init__, (self, name, check), kw) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: Set polylines's vertices check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( IndexedPolygons.Set, (self, check, 0), kw ) redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] rebuildTexture=False val = kw.get( 'array') if val is not None: array = Numeric.array(val) assert len(array.shape)==2 self.array = val rebuildTexture=True val = kw.get( 'colormap') if val is not None: assert isinstance(val, ColorMap) self.colormap = val rebuildTexture=True setMinMax = False val = kw.get( 'max') if val: maxi = float(val) setMinMax = True else: maxi = self.colormap.maxi val = kw.get( 'min') if val: mini = float(val) setMinMax = True else: mini = self.colormap.mini if mini<= maxi and setMinMax: self.colormap.configure(mini=mini, maxi=maxi, updateGui=True) if rebuildTexture and self.array is not None: tex, texCoords = self.buildTexture() self.Set(texture=tex, textureCoords=texCoords) return self.redoNow(redo, updateOwnGui, redoFlags) def buildTexture(self): """Build a 2D Texture object and compute texture coordinates for self.array, using self.colormap to colorize the texture. """ width, height = self.array.shape # find smallest power of 2 larger than shape dim1=dim2=1 while dim1= 0) assert(self.Rows >= 0) def tileSize(self, width, height, border): assert(border >= 0) assert(width >= 1) assert(height >= 1) assert(width >= 2*border) assert(height >= 2*border) self.TileBorder = border self.TileWidth = width self.TileHeight = height self.TileWidthNB = width - 2 * border self.TileHeightNB = height - 2 * border self.setup() def tileBuffer(self, format, type, image): self.TileFormat = format self.TileType = type self.TileBuffer = image def imageSize(self, width, height): self.ImageWidth = width self.ImageHeight = height self.setup() def imageBuffer(self, format, type, image): self.ImageFormat = format self.ImageType = type self.ImageBuffer = image def get(self, param): if param==TR_TILE_WIDTH: return self.TileWidth elif param==TR_TILE_HEIGHT: return self.TileHeight elif param==TR_TILE_BORDER: return self.TileBorder elif param==TR_IMAGE_WIDTH: return self.ImageWidth elif param==TR_IMAGE_HEIGHT: return self.ImageHeight elif param==TR_ROWS: return self.Rows elif param==TR_COLUMNS: return self.Columns elif param==TR_CURRENT_ROW: if (self.CurrentTile<0): return -1 else: return self.CurrentRow elif param==TR_CURRENT_COLUMN: if (self.CurrentTile<0): return -1 else: return self.CurrentColumn elif param==TR_CURRENT_TILE_WIDTH: return self.CurrentTileWidth elif param==TR_CURRENT_TILE_HEIGHT: return self.CurrentTileHeight elif param==TR_ROW_ORDER: return int(self.RowOrder) else: return 0 def rowOrder(self, order): if order==TR_TOP_TO_BOTTOM or order==TR_BOTTOM_TO_TOP: self.RowOrder = order def ortho(self, left, right, bottom, top, zNear, zFar): self.Perspective = False self.Left = left self.Right = right self.Bottom = bottom self.Top = top self.Near = zNear self.Far = zFar def frustum(self, left, right, bottom, top, zNear, zFar): self.Perspective = True self.Left = left self.Right = right self.Bottom = bottom self.Top = top self.Near = zNear self.Far = zFar def perspective(self, fovy, aspect, zNear, zFar): from math import tan ymax = zNear * tan(fovy * 3.14159265 / 360.0) ymin = -ymax xmin = ymin * aspect xmax = ymax * aspect self.frustum(xmin, xmax, ymin, ymax, zNear, zFar) def beginTile(self): if self.CurrentTile <= 0: self.setup() # Save user's viewport, will be restored after last tile rendered self.ViewportSave = GL.glGetIntegerv(GL.GL_VIEWPORT) # which tile (by row and column) we're about to render if self.RowOrder==TR_BOTTOM_TO_TOP: self.CurrentRow = self.CurrentTile / self.Columns self.CurrentColumn = self.CurrentTile % self.Columns elif self.RowOrder==TR_TOP_TO_BOTTOM: self.CurrentRow = self.Rows - (self.CurrentTile / self.Columns) - 1 self.CurrentColumn = self.CurrentTile % self.Columns else: raise RuntimeError assert(self.CurrentRow < self.Rows) assert(self.CurrentColumn < self.Columns) border = self.TileBorder # Compute actual size of this tile with border if self.CurrentRow < self.Rows-1: tileHeight = self.TileHeight else: tileHeight = self.ImageHeight - (self.Rows-1) * \ (self.TileHeightNB) + 2 * border if self.CurrentColumn < self.Columns-1: tileWidth = self.TileWidth else: tileWidth = self.ImageWidth - (self.Columns-1) * \ (self.TileWidthNB) + 2 * border # Save tile size, with border self.CurrentTileWidth = tileWidth self.CurrentTileHeight = tileHeight GL.glViewport(0, 0, tileWidth, tileHeight) #tile size including border # save current matrix mode matrixMode = GL.glGetIntegerv(GL.GL_MATRIX_MODE)[0] GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() # compute projection parameters self.tileleft = left = self.Left + (self.Right - self.Left) \ * (self.CurrentColumn * self.TileWidthNB - border) \ / self.ImageWidth self.tileright = right = left + (self.Right - self.Left) * \ self.TileWidth / self.ImageWidth self.tilebottom = bottom = self.Bottom + (self.Top - self.Bottom) \ * (self.CurrentRow * self.TileHeightNB - border) / \ self.ImageHeight self.tiletop = top = bottom + (self.Top - self.Bottom) * self.TileHeight / \ self.ImageHeight if self.Perspective: GL.glFrustum(float(left), float(right), float(bottom), float(top), float(self.Near), float(self.Far)) else: GL.glOrtho(float(left), float(right), float(bottom), float(top), float(self.Near), float(self.Far)) # restore user's matrix mode GL.glMatrixMode(int(matrixMode)) def endTile(self): assert(self.CurrentTile>=0) # be sure OpenGL rendering is finished GL.glFinish() #was glFlush() # save current glPixelStore values prevRowLength = GL.glGetIntegerv(GL.GL_PACK_ROW_LENGTH)[0] prevSkipRows = GL.glGetIntegerv(GL.GL_PACK_SKIP_ROWS)[0] prevSkipPixels = GL.glGetIntegerv(GL.GL_PACK_SKIP_PIXELS)[0] #prevAlignment = GL.glGetIntegerv(GL_PACK_ALIGNMENT)[0] if self.TileBuffer is not None: srcX = self.TileBorder srcY = self.TileBorder srcWidth = self.TileWidthNB srcHeight = self.TileHeightNB GL.glReadPixels(srcX, srcY, srcWidth, srcHeight, self.TileFormat, self.TileType, self.TileBuffer) if self.ImageBuffer is not None: srcX = self.TileBorder srcY = self.TileBorder srcWidth = self.CurrentTileWidth - 2 * self.TileBorder srcHeight = self.CurrentTileHeight - 2 * self.TileBorder destX = self.TileWidthNB * self.CurrentColumn destY = self.TileHeightNB * self.CurrentRow ## #save single tile ## # setup pixel store for glReadPixels ## GL.glPixelStorei(GL.GL_PACK_ROW_LENGTH, self.CurrentTileWidth) ## GL.glPixelStorei(GL.GL_PACK_SKIP_ROWS, 0) ## GL.glPixelStorei(GL.GL_PACK_SKIP_PIXELS, 0) ## #GL.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1) ## # read the tile into buffer ## gllib.glReadPixels(srcX, srcY, srcWidth, srcHeight, ## self.ImageFormat, self.ImageType, self.oneTileRenderBuffer) ## import Image, sys ## im = Image.fromstring('RGB', (srcWidth, srcHeight), ## self.oneTileRenderBuffer) ## if sys.platform!='win32': ## im = im.transpose(Image.FLIP_TOP_BOTTOM) ## im.save('tile%d_%d.tif'%(self.CurrentRow, self.CurrentColumn)) # setup pixel store for glReadPixels GL.glPixelStorei(GL.GL_PACK_ROW_LENGTH, self.ImageWidth) GL.glPixelStorei(GL.GL_PACK_SKIP_ROWS, destY) GL.glPixelStorei(GL.GL_PACK_SKIP_PIXELS, destX) #GL.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1) # read the tile into the final image #print 'DEBUG Tile renderer' #print 'column, row:', self.CurrentColumn, self.CurrentRow #print 'srcWidth,srcHeight,destX, destY',srcWidth,srcHeight,destX, destY gllib.glReadPixels(srcX, srcY, srcWidth, srcHeight, self.ImageFormat, self.ImageType, self.ImageBuffer) # restore previous glPixelStore values GL.glPixelStorei(GL.GL_PACK_ROW_LENGTH, int(prevRowLength)) GL.glPixelStorei(GL.GL_PACK_SKIP_ROWS, int(prevSkipRows)) GL.glPixelStorei(GL.GL_PACK_SKIP_PIXELS, int(prevSkipPixels)) #GL.glPixelStorei(GL.GL_PACK_ALIGNMENT, prevAlignment) # increment tile counter, return 1 if more tiles left to render self.CurrentTile+=1 if self.CurrentTile >= self.Rows * self.Columns: # restore user's viewport GL.glViewport(int(self.ViewportSave[0]), int(self.ViewportSave[1]), int(self.ViewportSave[2]), int(self.ViewportSave[3])) self.CurrentTile = -1 # all done return 0 else: return 1 def trRasterPos3f(self, x, y, z): """ Replacement for glRastePos3f() which avoids the problem with invalid raster pos. """ if self.CurrentTile<0: # not doing tile rendering right now. Let OpenGL do this. GL.glRasterPos3f(float(x), float(y), float(z)) else: # Get modelview, projection and viewport modelview = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX) proj = GL.glGetDoublev(GL.GL_PROJECTION_MATRIX) viewport = [0, 0, self.CurrentTileWidth, self.CurrentTileHeight] ## FIXME, need to finish this # Project object coord to window coordinate ## projpoint = gluProject(x, y, z, modelview, proj, viewport) ## if gluProject(x, y, z, modelview, proj, viewport, &winX, &winY, &winZ)){ ## /* set raster pos to window coord (0,0) */ ## glMatrixMode(GL_MODELVIEW) ## glPushMatrix() ## glLoadIdentity() ## glMatrixMode(GL_PROJECTION) ## glPushMatrix() ## glLoadIdentity() ## glOrtho(0.0, self.CurrentTileWidth, ## 0.0, self.CurrentTileHeight, 0.0, 1.0) ## glRasterPos3f(0.0, 0.0, -winZ) ## /* Now use empty bitmap to adjust raster position to (winX,winY) */ ## { ## GLubyte bitmap[1] = {0} ## glBitmap(1, 1, 0.0, 0.0, winX, winY, bitmap) ## } ## /* restore original matrices */ ## glPopMatrix() /*proj*/ ## glMatrixMode(GL_MODELVIEW) ## glPopMatrix() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/imageViewer.py0000644000175000017500000002472411175667604022531 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import Tkinter, os import numpy.oldnumeric as Numeric import Image from opengltk.OpenGL import GL from opengltk.extent import _gllib from DejaVu.EventHandler import EventManager from DejaVu.MaterialEditor import OGLWidget import warnings from warnings import warn ## TODO ## ## try using glPixelMap to clip and change the outlines ## try using FL_FLOAT format for images to have more resolution in Z ## try glPicelTransfer to scale bias contour ## try a bluring filter to antialias outline ## detect imaging subset presence ## class ImageViewer(OGLWidget): def __init__(self, master=None, image=None, name='ImageViewer', cnf = {}, **kw): if not kw.has_key('double'): kw['double'] = 1 if not kw.has_key('depth'): kw['depth'] = 0 if not kw.has_key('accum'): kw['accum'] = 0 if master is None: master = Tkinter.Toplevel() master.title(name) self.width = 100 self.height = 100 self.imarray = None ## self.scale= 1.0 ## self.bias = 0.0 apply( OGLWidget.__init__, (self, master, cnf), kw) self.initGL() self.setImage(image) def Exit(self): self.master.destroy() def Configure(self, event=None): """Cause the opengl widget to redraw itself.""" #print 'Configure 0' if self.imarray is None: return if isinstance(self.master, Tkinter.Tk) or \ isinstance(self.master, Tkinter.Toplevel): geom = '%dx%d' % (self.width, self.height) self.master.geometry(geom) self.unbind('') self.configure(width=self.width, height=self.height) self.bind('', self.Configure) self.initProjection() def initProjection(self): if self.imarray is None: return self.tk.call(self._w, 'makecurrent') GL.glViewport(0, 0, self.width, self.height) GL.glMatrixMode(GL.GL_PROJECTION) GL.glLoadIdentity() GL.glOrtho(0, float(self.width), 0, float(self.height), -1.0, 1.0) GL.glMatrixMode(GL.GL_MODELVIEW) def setImage(self, image, width=None, height=None, mode=None): self.width = None self.height = None self.imarray = None if image is None: return elif isinstance(image, Image.Image): self.width = image.size[0] self.height = image.size[1] im = image.transpose(Image.FLIP_TOP_BOTTOM) self.imarray = Numeric.fromstring(im.tostring(), 'B') self.mode = image.mode elif isinstance(image,Numeric.ArrayType): if mode == 'RGB': lenmode = 3 elif mode in ['L','P']: lenmode = 1 assert image.dtype.char=='b' if len(image.shape)==3: self.width = image.shape[0] self.height = image.shape[1] self.imarray = Numeric.reshape( image, (-1,)) elif len(image.shape)==1: self.width = width self.height = height self.imarray = image self.imarray.shape = (self.width, self,height) self.numimarray = numarray.array(self.imarray) self.imarray = Numeric.reshape( image, (-1,)) else: raise RuntimeError, "bad shape for image array" assert len(self.imarray)==self.width*self.height*lenmode self.mode = mode else: print 'Not surported yet' self.Configure() self.tkRedraw() def initGL(self): GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) GL.glClearColor(0.4, 0.4, 0.4, 0.0) def redraw(self, event=None, filter=None): if self.imarray is None: return if filter: self.master.lift() GL.glConvolutionFilter2D(GL.GL_CONVOLUTION_2D, GL.GL_LUMINANCE, 3, 3, GL.GL_LUMINANCE, GL.GL_FLOAT, filter) ## GL.glConvolutionParameterfv(GL.GL_CONVOLUTION_2D, ## GL.GL_CONVOLUTION_FILTER_SCALE, ## (3., 3.,3.,3.)) ## s= self.scale ## GL.glPixelTransferf(GL.GL_POST_CONVOLUTION_RED_SCALE, s) ## GL.glPixelTransferf(GL.GL_POST_CONVOLUTION_BLUE_SCALE, s) ## GL.glPixelTransferf(GL.GL_POST_CONVOLUTION_GREEN_SCALE, s) ## s = self.bias ## GL.glPixelTransferf(GL.GL_POST_CONVOLUTION_RED_BIAS, s) ## GL.glPixelTransferf(GL.GL_POST_CONVOLUTION_BLUE_BIAS, s) ## GL.glPixelTransferf(GL.GL_POST_CONVOLUTION_GREEN_BIAS, s) ## GL.GL_CONVOLUTION_FILTER_SCALE, ## (3., 3.,3.,3.)) ## GL.glConvolutionParameteriv(GL.GL_CONVOLUTION_2D, ## GL.GL_CONVOLUTION_FILTER_BIAS, ## (1500, 1500, 1500, 1500)) GL.glEnable(GL.GL_CONVOLUTION_2D) self.tk.call(self._w, 'makecurrent') GL.glClearColor(0.0, 0.0, 0.0, 0.0) GL.glClear(GL.GL_COLOR_BUFFER_BIT) GL.glRasterPos2i( 0, 0) GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) if self.mode=='RGB': _gllib.glDrawPixels( self.width, self.height, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, self.imarray) elif self.mode in ['L','P']: _gllib.glDrawPixels( self.width, self.height, GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, self.imarray) GL.glDisable(GL.GL_CONVOLUTION_2D) def smooth(self): average = (Numeric.ones( (3,3) , 'f')/9.).astype('f') # average[1][1] = .0 print average self.redraw(filter=average) image = (self.imageAsArray()).astype('B') return image def secondDerivativeNum(self): sndDeriv = numarray.array([ [-0.125, -0.125, -0.125,], [-0.125, 1.0, -0.125,], [-0.125, -0.125, -0.125,] ], 'f') a = self.numimarray c = a.copy() Numeric.convolve.Convolve2d(sndDeriv, a, c) return c def firstDerivative(self): if self.imarray is None: return fstDeriveV = numarray.array([ [-0.125, -0.25, -0.125], [ 0.0 , 0.0, 0.0 ], [ 0.125, 0.25, 0.125] ], 'f') a = numarray.array(self.imarray) c = a.copy() Numeric.convolve.Convolve2d(fstDeriveV, a, c) fstDeriveV = numarray.array([ [ 0.125, 0.25, 0.125], [ 0.0 , 0.0, 0.0 ], [-0.125, -0.25, -0.125] ], 'f') d = a.copy() Numeric.convolve.Convolve2d(fstDeriveV, a, d) fstDeriveH = numarray.array([ [-0.125, 0.0, 0.125], [-0.25 , 0.0, 0.25 ], [-0.125, 0.0, 0.125] ], 'f') e = a.copy() Numeric.convolve.Convolve2d(fstDeriveH, a, e) fstDeriveH = numarray.array([ [ 0.125, 0.0, -0.125], [ 0.25 , 0.0, -0.25 ], [ 0.125, 0.0, -0.125] ], 'f') f = a.copy() Numeric.convolve.Convolve2d(fstDeriveH, a, f) deriv = numarray.fabs(c+d*0.5)+numarray.fabs(e+f*0.5) return deriv.astype('B') def secondDerivative(self): sndDeriv = Numeric.array([ [-0.125, -0.125, -0.125,], [-0.125, 1.0, -0.125,], [-0.125, -0.125, -0.125,] ], 'f') self.redraw(filter=sndDeriv) deriv = Numeric.fabs(self.imageAsArray()).astype('B') return deriv def firstDerivative(self): fstDeriveV = Numeric.array([ [-0.125, -0.25, -0.125], [ 0.0 , 0.0, 0.0 ], [ 0.125, 0.25, 0.125] ], 'f') self.redraw(filter=fstDeriveV) derivV = self.imageAsArray() if derivV is None: return None fstDeriveV = Numeric.array([ [ 0.125, 0.25, 0.125], [ 0.0 , 0.0, 0.0 ], [-0.125, -0.25, -0.125] ], 'f') self.redraw(filter=fstDeriveV) derivV += self.imageAsArray() fstDeriveH = Numeric.array([ [-0.125, 0.0, 0.125], [-0.25 , 0.0, 0.25 ], [-0.125, 0.0, 0.125] ], 'f') self.redraw(filter=fstDeriveH) derivH = self.imageAsArray() fstDeriveH = Numeric.array([ [ 0.125, 0.0, -0.125], [ 0.25 , 0.0, -0.25 ], [ 0.125, 0.0, -0.125] ], 'f') self.redraw(filter=fstDeriveH) derivH += self.imageAsArray() deriv = Numeric.fabs(derivH*0.5)+Numeric.fabs(derivV*0.5) return deriv.astype('B') def getHistogram(self): GL.glHistogram(GL.GL_HISTOGRAM, 256, GL.GL_RGB, GL.GL_FALSE) GL.glEnable(GL.GL_HISTOGRAM) self.redraw() values = Numeric.zeros( (256,3), Numeric.UInt16) #seg faults GL.glGetHistogram(GL.GL_HISTOGRAM, GL.GL_TRUE, GL.GL_RGB, GL.GL_UNSIGNED_SHORT, values) return values def imageAsArray(self): width = self.width height = self.height if width is None or height is None: return None nar = Numeric.zeros(3*width*height, Numeric.UnsignedInt8) self.tk.call(self._w, 'makecurrent') GL.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1) # self.tk.call(self._w, 'swapbuffers') GL.glReadBuffer(GL.GL_BACK) _gllib.glReadPixels( 0, 0, width, height, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, nar) # self.tk.call(self._w, 'swapbuffers') return nar if __name__=='__main__': im = Image.open('lena.jpg') vi = ImageViewer(image=im, name='lena.jpg') vi.redraw() im2 = Image.open('cAMP_mac.jpg') im3 = Image.open('spectrum.jpg') vi.setImage(im3) #vi.setImage(im2) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Displayable.py0000644000175000017500000005215111473263120022473 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Displayable.py,v 1.57 2010/11/24 19:24:00 sanner Exp $ # # $Id: Displayable.py,v 1.57 2010/11/24 19:24:00 sanner Exp $ # from math import pi, exp, sin from time import time from opengltk.OpenGL import GL import types import numpy import numpy.oldnumeric as Numeric import Materials, viewerConst from viewerFns import getkw from colorTool import OneColor, glMaterialWithCheck, resetMaterialMemory from mglutil.util.callback import CallbackFunction import DejaVu class OutLine: """Base class for wire frame used for outlined polygons""" def Reset(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Reset members to default values""" self.factor = 1.5 self.unit = 0.000001 self.lineWidth = 1 self.color = [0., 0., 0., .3] self.colorAsMaterial = False # set to True to use Object's material # to color lines self.dpyList = None self.lighting = False def Set(self, redo=0,**kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set members""" val = getkw(kw, 'factor') if val is not None: assert type(val).__name__ == 'float' self.factor = val val = getkw(kw, 'unit') if val is not None: assert type(val).__name__ == 'float' self.unit = val val = getkw(kw, 'lineWidth') if val is not None: assert val >= 1 self.lineWidth = int(val) val = getkw(kw, 'color') if val is not None: color = OneColor( val ) if color: self.color = color val = getkw(kw, 'lighting') if val is not None: assert val in [False, True] self.lighting = val val = getkw(kw, 'colorAsMaterial') if val is not None: assert val in [False,True] self.colorAsMaterial = val if self.geom.viewer is not None: #self.geom.RedoDisplayList() self.geom.viewer.deleteOpenglList() if len(kw): print 'WARNING2: Keyword(s) %s not used' % kw.keys() def __init__(self, geom, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.geom = geom self.Reset() self.Set( factor = getkw(kw, 'factor'), unit = getkw(kw, 'unit'), lineWidth = getkw(kw, 'lineWidth'), color = getkw(kw, 'color') ) if len(kw): print 'WARNING3: Keyword(s) %s not used' % kw.keys() def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return '<%s> factor=%5.2f unit=%5.2f lineWidth=%5.2f color=%s' % \ (self.__class__, self.factor, self.unit, self.lineWidth, str(self.color) ) class LineStipple: """Base class for line stippling information""" def Reset(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Reset members to default values""" self.factor = 1 self.pattern = 0x7878 def Set(self, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set members""" val = getkw(kw, 'factor') if val: assert type(val).__name__ == 'int' and val > 0 self.factor = val val = getkw(kw, 'pattern') if val: assert val > 0x0000 and val < 0xFFFF self.pattern = val if len(kw): print 'WARNING4: Keyword(s) %s not used' % kw.keys() def __init__(self, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.Reset() self.Set( factor = getkw(kw, 'factor'), pattern = getkw(kw, 'pattern')) if len(kw): print 'WARNING5: Keyword(s) %s not used' % kw.keys() def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return '<%s> factor=%f pattern=%s' % ( self.__class__, self.factor, hex(self.pattern) ) class PolygonStipple: """Base class for polygon stippling information""" def Reset(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Reset members to default values""" self.pattern = Numeric.ones( (128,)) * 0xFF self.pattern = self.pattern.astype('B') def Set(self, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set members""" val = getkw(kw, 'pattern') if val is not None: assert type(val).__name__ == 'ndarray' assert val.shape[0] == 128 assert val.dtype.char == 'B' self.pattern = val if len(kw): print 'WARNING6: Keyword(s) %s not used' % kw.keys() def __init__(self, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.Reset() self.Set( pattern = getkw(kw, 'pattern')) if len(kw): print 'WARNING7: Keyword(s) %s not used' % kw.keys() def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return '<%s>\n pattern=%s' % ( self.__class__, map(hex,self.pattern) ) class Displayable: """Base class for all object that can be viewed""" def Set(self, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set data for this object""" # currently all these attributs are in GEOM # they should move here pass def __init__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.materials = { GL.GL_FRONT:Materials.Materials(), GL.GL_BACK:Materials.Materials() } self.texture = None self.frontPolyMode = GL.GL_FILL self.backPolyMode = GL.GL_FILL self.frontAndBack = viewerConst.NO self.shading = GL.GL_SMOOTH self.lighting = viewerConst.NO self.culling = GL.GL_BACK #self.antiAliased = 0 #self.antialiased = viewerConst.NO self.primitiveType = None self.inheritMaterial = viewerConst.YES self.inheritFrontPolyMode = viewerConst.YES self.inheritBackPolyMode = viewerConst.YES self.inheritShading = viewerConst.YES self.inheritLighting = viewerConst.YES self.inheritCulling = viewerConst.YES self.inheritPointWidth = viewerConst.YES self.inheritLineWidth = viewerConst.YES self.inheritStippleLines = viewerConst.YES self.inheritStipplePolygons = viewerConst.YES self.dpyList = None # OpenGL display list used to draw this object self.lineWidth = 2 self.pointWidth = 2 from DejaVu.Transformable import Transformable if isinstance(self, Transformable): self.drawOutline = (False, False) self.outline = OutLine(self) self.linestipple = LineStipple() self.stippleLines = viewerConst.NO self.polygonstipple = PolygonStipple() self.stipplePolygons = viewerConst.NO self.transparent = viewerConst.NO self.depthMask = 1 # 0: zbuffer is readOnly for transparent objects # 1: zbuffer is read write for transparent objects self.srcBlendFunc = GL.GL_SRC_ALPHA #self.dstBlendFunc = GL.GL_ONE #GL.GL_ONE_MINUS_SRC_COLOR # ONE_MINUS_SRC_ALPHA works for colorMapEditor self.dstBlendFunc = GL.GL_ONE_MINUS_SRC_ALPHA # attribute used for flashing geometry self.flashInDuration = .5 # length of flash in seconds self.flashSolidDuration = .2 # length of flash in seconds self.flashOutDuration = .8 # length of flash in seconds self.flashIntervalTime = 10 # in ms self.flashStartTime = None # will be set when flash start ## version of flashing using after(ms, func) def _fadeOutT(self): dtime = time() - self.flashStartTime fraction = min(1.0, dtime/self.flashOutDuration) val = exp(1.)/exp(1.+2*fraction) print fraction, val self.Set(opacity=val) self._setTransparent('implicit') vi = self.viewer vi.OneRedraw() if fraction<1.0: vi.master.after(self.flashIntervalTime, self._fadeOutT) else: self.Set(visible=0) def fadeOutT(self, duration=1.5, interval=10): self.flashOutDuration = duration self.flashIntervalTime = interval self.Set(visible=1) self.flashStartTime = time() self._fadeOutT() def _fadeInT(self): dtime = time() - self.flashStartTime fraction = min(1.0, dtime/self.flashInDuration) val = fraction*pi*.5 vi = self.viewer #print fraction, val self.Set(opacity=val) self._setTransparent('implicit') vi.OneRedraw() if fraction<1.0: vi.master.after(self.flashIntervalTime, self._fadeInT) def fadeInT(self, duration=.5, interval=10): self.flashInDuration = duration self.flashIntervalTime = interval self.Set(visible=1, opacity=0.01, transparent=1, inheritMaterial=0) self._setTransparent('implicit') vi = self.viewer vi.OneRedraw() self.flashStartTime = time() self._fadeInT() def _flashT(self): dtime = time() - self.flashStartTime fraction = dtime/self.flashInDuration if fraction < 1.0: # we are in fade in mode val = fraction*pi*.5 else: # We are in fade out mode dtime -= self.flashInDuration fraction = dtime/self.flashSolidDuration if fraction < 1.0: # we are in solid mode val = 1.0 else: # we are in fade out mode dtime -= self.flashSolidDuration fraction = min(1., dtime/self.flashOutDuration) val = exp(1.)/exp(1.+2*fraction) vi = self.viewer #print fraction, val self.Set(opacity=val) self._setTransparent('implicit') vi.OneRedraw() if fraction<1.0: vi.master.after(self.flashIntervalTime, self._flashT) else: self.Set(visible=0) vi.OneRedraw() if self.after_cb: self.after_cb() def flashT(self, durationIn=.5, duration=.2, durationOut=.8, interval=10, after_cb=None): self.flashInDuration = durationIn self.flashOutDuration = durationOut self.flashSolidDuration = duration self.flashIntervalTime = interval self.after_cb = after_cb self.flashStartTime = time() self.Set(visible=1, opacity=0.01, transparent=1, inheritMaterial=0) self._flashT() ## version of flashing without using after(ms, func) def fadeOut(self, nbf=25): vi = self.viewer for i in numpy.arange(1., 3., 2./nbf): val = exp(1.)/exp(i) self.Set(opacity=val) self._setTransparent('implicit') vi.OneRedraw() self.Set(visible=0) vi.OneRedraw() def fadeIn(self, nbf=15): self.Set(visible=1, opacity=0.01, transparent=1, inheritMaterial=0) self._setTransparent('implicit') self.viewer.OneRedraw() vi = self.viewer for i in numpy.arange(0, pi*.5, (pi*.5)/nbf): val = sin(i) self.Set(opacity=val) self._setTransparent('implicit') vi.OneRedraw() def flash(self, nbfIn=5, nbfOut=25, fullPause=200): self.fadeIn(nbf=nbfIn) cb = CallbackFunction(self.fadeOut, nbf=nbfOut) self.viewer.master.after(fullPause, self.fadeOut) def InitMaterial(self, num=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Setup GL material only sets the material if binding mode is OVERALL or PER_INSTANCE (i.e. per instance matrix) which are the 2 only material bindngs for which the material is not set in the display list""" #import traceback #traceback.print_stack() #print 'InitMaterial', self.name prop = self.materials[GL.GL_FRONT] if self.frontAndBack: f = GL.GL_FRONT_AND_BACK else: f = GL.GL_FRONT resetMaterialMemory() b, p = prop.GetProperty(0) if prop.binding[0] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_AMBIENT, p[0]) elif prop.binding[0] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_AMBIENT, p[num]) b, p = prop.GetProperty(1) if prop.binding[1] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_DIFFUSE, p[0]) elif prop.binding[1] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_DIFFUSE, p[num]) b, p = prop.GetProperty(2) if prop.binding[2] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_EMISSION, p[0]) elif prop.binding[3] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_EMISSION, p[num]) b, p = prop.GetProperty(3) if prop.binding[2] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_SPECULAR, p[0]) elif prop.binding[2] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_SPECULAR, p[num]) if prop.binding[4] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_SHININESS, float(prop.prop[4][0])) #GL.glMaterialf(f, GL.GL_SHININESS, float(prop.prop[4][0])) elif prop.binding[4] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_SHININESS, float(prop.prop[4][num])) #GL.glMaterialf(f, GL.GL_SHININESS, float(prop.prop[4][num])) if not self.frontAndBack: prop = self.materials[GL.GL_BACK] f = GL.GL_BACK if prop.binding[0] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_AMBIENT, prop.prop[0][0]) elif prop.binding[0] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_AMBIENT, prop.prop[0][num]) if prop.binding[1] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_DIFFUSE, prop.prop[1][0]) elif prop.binding[1] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_DIFFUSE, prop.prop[1][num]) if prop.binding[2] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_SPECULAR, prop.prop[3][0]) elif prop.binding[2] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_SPECULAR, prop.prop[3][num]) if prop.binding[3] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_EMISSION, prop.prop[2][0]) elif prop.binding[3] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_EMISSION, prop.prop[2][num]) if prop.binding[4] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_SHININESS, float(prop.prop[4][0])) #GL.glMaterialf(f, GL.GL_SHININESS, float(prop.prop[4][0])) elif prop.binding[4] == viewerConst.PER_INSTANCE: glMaterialWithCheck(f, GL.GL_SHININESS, float(prop.prop[4][num])) #GL.glMaterialf(f, GL.GL_SHININESS, float(prop.prop[4][num])) def InitColor(self, num=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Setup GL color (used when lighting is turned off) only sets the color if binding mode is OVERALL or PER_INSTANCE (i.e. per instance matrix) which are the 2 only colors which are not set in the display list""" prop = self.materials[GL.GL_FRONT] if prop.binding[1] == viewerConst.OVERALL: material = prop.prop[prop.diff][0] if not material.flags.contiguous: material = Numeric.array(material,copy=1) GL.glColor4fv ( material.tolist() ) elif prop.binding[1] == viewerConst.PER_INSTANCE: material = prop.prop[prop.diff][num] if not material.flags.contiguous: material = Numeric.array(material,copy=1) GL.glColor4fv ( material.tolist() ) ## ======= ## mat = self.materials[GL.GL_FRONT] ## # without tolist() we hang if array is not contiguous ! ## GL.glColor4fv ( mat.prop[mat.diff][0].tolist() ) ## >>>>>>> 1.8.2.1 def _WidthAndStipple(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the line or points width """ #print "_WidthAndStipple", self.stippleLines , self.inheritStippleLines , self GL.glPointSize(self.getPointWidth()) GL.glLineWidth(self.getLineWidth()) if self.getStippleLines() in (True, 1): GL.glEnable(GL.GL_LINE_STIPPLE) ls = self.linestipple GL.glLineStipple(ls.factor, ls.pattern) else: GL.glDisable(GL.GL_LINE_STIPPLE) if self.getStipplePolygons() in (True, 1): GL.glEnable(GL.GL_POLYGON_STIPPLE) ps = self.polygonstipple GL.glPolygonStipple(self.polygonstipple.pattern) else: GL.glDisable(GL.GL_POLYGON_STIPPLE) def getPointWidth(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "getPointWidth", self.name obj = self while obj.inheritPointWidth: if obj.parent: obj = obj.parent else: break return obj.pointWidth def getLineWidth(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "getLineWidth", self.name obj = self while obj.inheritLineWidth: if obj.parent: obj = obj.parent else: break return obj.lineWidth def getStippleLines(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "getStippleLines", self.name obj = self while obj.inheritStippleLines: if obj.parent: obj = obj.parent else: break return obj.stippleLines def getStipplePolygons(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "getStipplePolygons", self.name obj = self while obj.inheritStipplePolygons: if obj.parent: obj = obj.parent else: break return obj.stipplePolygons # def _AntiAliasing(self): # """Turn line or points antialiasing on or of""" # # if self.antialiased==viewerConst.YES: # if self.primitiveType == GL.GL_POINTS or \ # self.frontPolyMode == GL.GL_POINT or \ # self.backPolyMode == GL.GL_POINT: # GL.glEnable(GL.GL_POINT_SMOOTH) # # elif self.primitiveType in viewerConst.LINES_PRIMITIVES or \ # self.frontPolyMode == GL.GL_LINE or \ # self.backPolyMode == GL.GL_LINE: # GL.glEnable(GL.GL_LINE_SMOOTH) # # GL.glEnable(GL.GL_BLEND) # else: # GL.glDisable(GL.GL_LINE_SMOOTH) # GL.glDisable(GL.GL_BLEND) def SetupGL(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Setup OpenGL rendering state for this object """ #print "SetupGL", self if not self.inheritMaterial: self.InitMaterial() self.InitColor() if self.GetLighting(): #glEnable(GL_LIGHTING) if self.viewer is not None: self.viewer.enableOpenglLighting() shading = self.GetShading() if shading != GL.GL_NONE: if self.normals is not None: if (shading==GL.GL_SMOOTH and \ len(self.normals)!=len(self.vertexSet)) or \ (shading==GL.GL_FLAT and \ len(self.normals)!=len(self.faceSet)): self.GetNormals() self.viewer.objectsNeedingRedo[self] = None GL.glShadeModel(shading) else: # no lighting GL.glDisable(GL.GL_LIGHTING) if not self.inheritCulling: if self.culling in (GL.GL_BACK, GL.GL_FRONT, GL.GL_FRONT_AND_BACK): GL.glCullFace(self.culling) GL.glEnable(GL.GL_CULL_FACE) else: GL.glDisable(GL.GL_CULL_FACE) if not self.inheritFrontPolyMode: mode =self.frontPolyMode if self.frontPolyMode==viewerConst.OUTLINED: mode = GL.GL_FILL if self.frontAndBack: GL.glPolygonMode(GL.GL_FRONT_AND_BACK, mode) else: GL.glPolygonMode(GL.GL_FRONT, mode) if not self.inheritBackPolyMode: mode = self.backPolyMode if self.backPolyMode==viewerConst.OUTLINED: mode = GL.GL_FILL GL.glPolygonMode(GL.GL_BACK, mode) #self._AntiAliasing() self._WidthAndStipple() def showOwnGui(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "showOwnGui", self if self.ownGui is None: self.createOwnGui() if self.ownGui.winfo_ismapped() == 0: self.ownGui.deiconify() self.ownGui.lift() def hideOwnGui(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "hideOwnGui", self if (self.ownGui is not None) and (self.ownGui.winfo_ismapped() == 0): self.ownGui.withdraw() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/shaders/0000755000175000017500000000000012146210044021310 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/shaders/fragSSAO0000644000175000017500000002514311650117503022652 0ustar debiandebianuniform sampler2D DepthTexture; uniform sampler2D RenderedTexture;//RGB...Should try RGBA ie fog, transparancy uniform sampler2D LuminanceTexture; uniform sampler2D RandomTexture; // for method 2 uniform sampler2D DepthMaskTexture; // for method 2 uniform float RenderedTextureWidth; uniform float RenderedTextureHeight; uniform float near; uniform float far; uniform float realfar; //uniform float fogE; //uniform float fogS; uniform int method; //OPTIONS TO EXPLORE uniform int do_noise; uniform int only_ssao; uniform int only_depth; uniform int mix_depth; uniform int use_mask_depth; uniform int show_mask_depth; uniform int negative; uniform float scale; uniform int samples;// = 3; //samples on the each ring (3-7) uniform int rings;// = 3; //ring count (2-8) uniform float aoCap;// = 1.0; uniform float aoMultiplier;// = 100.0; uniform float depthTolerance;// = 0.0000; uniform float aorange;// = 160.0;//60 units in space the AO effect extends to (this gets divided by the camera far range //FOG options uniform int fog; uniform int use_fog; uniform float correction; //need to handle transparancy and depthcuing/fog #define PI 3.14159265 //method2 TO BE DONE //uniform float zFar; //uniform float SampleRad; //uniform float Intensity; //uniform float Scale; //uniform float Bias; float SampleRad=3.0; float Intensity=1.0; float Scale=1.0; float Bias=0.1; //varying var for method 1 varying vec2 texCoords; varying vec3 vCoords; varying vec2 vTexCoord; varying vec4 test; //varying var for method 2 varying vec3 normal; //varying vec4 pos; float textureSize =RenderedTextureWidth; //size of the texture float texelSize = 1.0 / textureSize; //size of one texel float width = RenderedTextureWidth; //texture width float height = RenderedTextureHeight; //texture height //int samples = 3; //samples on the each ring (3-7) //int rings = 3; //ring count (2-8) float random_size = 64.0; // size of random texture //vec2 texCoord = gl_TexCoord[0].xy;//st; vec2 getRandom(in vec2 uv){ float u = (fract(uv.x * (width/2.0))*0.25); float v = (fract(uv.y * (height/2.0))*0.75); return vec2(u,v); } vec2 rand(in vec2 coord) { //generating random noise float noiseX = (fract(sin(dot(coord ,vec2(12.9898,78.233))) * 43758.5453)); float noiseY = (fract(sin(dot(coord ,vec2(12.9898,78.233)*2.0)) * 43758.5453)); return vec2(noiseX,noiseY)*0.004; } vec4 texture2DBilinear(in sampler2D textureSampler, in vec2 uv ){ // in vertex shaders you should use texture2DLod instead of texture2D vec4 tl = texture2D(textureSampler, uv); vec4 tr = texture2D(textureSampler, uv + vec2(texelSize, 0)); vec4 bl = texture2D(textureSampler, uv + vec2(0, texelSize)); vec4 br = texture2D(textureSampler, uv + vec2(texelSize , texelSize)); vec2 f = fract( uv.xy * textureSize ); // get the decimal part vec4 tA = mix( tl, tr, f.x ); // will interpolate the red dot in the image vec4 tB = mix( bl, br, f.x ); // will interpolate the blue dot in the image return mix( tA, tB, f.y ); // will interpolate the green dot in the image } float scaleNearFar(in float val, in float near, in float far){ float res = 0.0; //res = 1.0 / (far + near -val*(far-near)); //if (val > 1.0){return 1.0;} //if (val < 0.0){return 0.0;} res = (2.0*near) / (far + near - val* (far-near)); return res; } float readDepth(in vec2 coord){ //linearisation of depth but already done vec4 val = texture2D(DepthTexture, coord ); return scaleNearFar(val.x,near,far);//(2.0*near) / (far + near - val.x* (far-near)); } float readMaskDepth(in vec2 coord){ //linearisation of depth but already done vec4 val = texture2D(DepthMaskTexture, coord ); return scaleNearFar(val.x,near,far); } float compareDepths( in float depth1, in float depth2 ){ float diff = sqrt(clamp(1.0-(depth1-depth2) / (aorange/(far-near)),0.0,1.0)); float ao = min(aoCap,max(0.0,depth1-depth2-depthTolerance) * aoMultiplier) * diff; return ao; } float computeAO(in vec2 scrCoord){ float depth = readDepth(scrCoord); float d; float aspect = RenderedTextureWidth/RenderedTextureHeight; vec2 noise = rand(scrCoord);//getRandom(srcCoord);// float w; float h; if (do_noise == 1) { w = (1.0 / RenderedTextureWidth)/clamp(depth,0.05,1.0)+(noise.x*(1.0-noise.x))*scale; h = (1.0 / RenderedTextureHeight)/clamp(depth,0.05,1.0)+(noise.y*(1.0-noise.y))*scale; } else { w = (1.0 / RenderedTextureWidth)/clamp(depth,0.05,1.0)+0.001*scale;//+(noise.x*(1.0-noise.x)); h = (1.0 / RenderedTextureHeight)/clamp(depth,0.05,1.0)+0.001*scale;//+(noise.y*(1.0-noise.y)); } float pw; float ph; float ao; float s; int ringsamples; for (int i = 1; i <= rings; i += 1){ ringsamples = i * samples; for (int j = 0 ; j < ringsamples ; j += 1) { float step = PI*2.0 / float(ringsamples); pw = (cos(float(j)*step)*float(i)); ph = (sin(float(j)*step)*float(i))*aspect; d = readDepth( vec2(scrCoord.s+pw*w,scrCoord.t+ph*h)); ao += compareDepths(depth,d); s += 1.0; } } ao /= s; ao = 1.0-ao; return ao; } float compareFog( in float depth1, in float depth2 ){ float diff = sqrt(clamp(1.0-(depth1-depth2) / (1.0/(far-near)),0.0,1.0)); //float ao = min(aoCap,max(0.0,depth1-depth2-depthTolerance) * aoMultiplier) * diff; return diff; } float getfog(in vec2 scrCoord) { vec4 val = texture2D(DepthTexture, scrCoord ); float fogFactor = 1.0; float f; const float LOG2 = 1.442695; float d0 = scaleNearFar(0.,near,realfar);//(2.0 * near) / (realfar + near); float d1 = scaleNearFar(1.,near,realfar);//(2.0 * near) / (realfar + near - (realfar-near)); float d = scaleNearFar(val.x,near,realfar);//(2.0 * near) / (realfar + near - val.x* (realfar-near));//readDepth(scrCoord);//val.x;//need real far vec3 coord = vec3(scrCoord.x,scrCoord.y,val.x); float fogc = length(coord); //val.x;//val.x;//length(coord); //distance from the camera ? //GL_LINEAR //float correction = 6.0;//scaleNearFar(60.0,near,realfar); float st = d0 + ((gl_Fog.start + correction) / (realfar-near))*(d1-d0); float en = d0 + ((gl_Fog.end + correction) / (realfar-near))*(d1-d0); if (den) { f = 0.0;//was 0.0, avoid overlay of bg color } else { f = (en-d) /(en-st); } if (val.x >= 1.0) {f = 1.0;} fogFactor = clamp(f, 0.0, 1.0); return fogFactor; } vec4 combineAO(in float ao,in vec2 scrCoord){ vec4 result = vec4(1.0,1.0,1.0,1.0); vec3 white = vec3(1.0,1.0,1.0); vec3 black = vec3(0.0,0.0,0.0); vec3 treshold = vec3(0.2,0.2,0.2); float d = 0.; float md = 0.; float fogf = 0.; vec3 luminance = texture2D(LuminanceTexture, scrCoord).rgb; luminance = clamp(max(black,luminance-treshold)+max(black,luminance-treshold)+max(black,luminance-treshold),0.0,1.0); /*if (fog == 1) { if (use_fog == 1) { fogf = getfog(scrCoord);//0 no fog, 1 fog ao = 1. - ((1. - ao) * fogf); ao = fogf;//clamp(ao, 0.0, 1.0); } } */ if (use_mask_depth == 1){ md = texture2D(DepthMaskTexture, scrCoord ).x;//readMaskDepth(scrCoord); if (d < 1.0) { d = texture2D(DepthTexture, scrCoord ).x; if (d == md ){ ao = 1.0;//no ao white } } } result = vec4(mix(vec3(ao,ao,ao),luminance,black),1.0); if (fog == 1) { if (use_fog == 1) { fogf = getfog(scrCoord); // 1 no fog, 0 fog //result = mix(gl_Fog.color, result, fogf ); // we use sin(fogf*PI*.5)) to attenuate the AO slower when we are close to fog start // and faster toward fog end result = vec4(mix(gl_Fog.color.rgb,result.rgb,sin(fogf*PI*.5)),1.0); } } return result; } float calcAO(in vec2 uv, in vec2 coord, in float depth, in vec3 norm){ //vec3 diff = texture2D(DepthTexture, uv + coord).xyz - pos; float diff = readDepth(uv + coord) - depth; //vec3 v = normalize(diff); vec3 v = normalize(vec3(diff,diff,diff)); //float d = diff * Scale; float d = length(vec3(diff,diff,diff)) * Scale; //return max(0.0, dot(norm, v) - Bias) * (1.0 / (1.0 + d)) * Intensity; return max(0.0, dot(norm, v) - Bias) * (1.0 / (1.0 + d)) * Intensity; } /*float computeAONormal(in vec2 uv){ vec2 rand; vec3 n; vec2 vec[4]; vec[0] = vec2(1, 0); vec[1] = vec2(-1, 0); vec[2] = vec2(0, 1); vec[3] = vec2(0, -1); vec2 randomMap = texture2D(RandomTexture, vec2(64,64) * uv / random_size).xy; vec3 normalMap = normal.xyz; //vec3 pos = texture2D(DepthTexture, uv).xyz;//depth float depth = readDepth(uv); n = normalize(normalMap * 2.0 - 1.0); rand = normalize(randomMap * 2.0 - 1.0); float ao = 0.0; float rad = SampleRad / depth; int iterations = int(mix(4.0, 1.0, - depth/far)); for (int i = 0; i < iterations; ++i) { vec2 coord1 = reflect(vec[i], rand) * rad; vec2 coord2 = vec2(coord1.x * 0.707 - coord1.y * 0.707, coord1.x * 0.707 + coord1.y * 0.707); ao += calcAO(uv, coord1 * 0.25, depth, n); ao += calcAO(uv, coord2 * 0.5,depth, n); ao += calcAO(uv, coord1 * 0.75, depth, n); ao += calcAO(uv, coord2, depth, n); } ao /= float(iterations) * 4.0; return ao; } */ vec4 Posterization(in vec3 color){ float gamma = 0.5; float numColors = 10.0; vec3 c = pow(color, vec3(gamma, gamma, gamma)); c = c * numColors; c = floor(c); c = c / numColors; c = pow(c, vec3(1.0/gamma)); return vec4(c, 1.0); } void main() { vec4 result = vec4(0.0); //vec2 coord=(test.xy/test.w+1.0)*0.5; vec2 scrCoord = vec2 (1.0 / width, 1.0 / height) * gl_FragCoord.xy; vec4 color = texture2D(RenderedTexture, scrCoord); float d = readDepth(scrCoord); float ao; float fogf = 0.; result = color ; if (method == 0){ ao = computeAO(scrCoord); ao = clamp(ao,0.0,1.0); if ( ao > 1.0 ) {ao = 1.0 ;} if ( ao < 0.0 ) {ao = 0.0 ;} if (d > 1.0 ) {ao = 1.0 ;} if (d < 0.0 ) {ao = 0.0 ;} } vec4 mixed = combineAO(ao,scrCoord); if (only_ssao == 1) { result = mixed; } else { result = vec4(color.rgb*mixed.rgb,1.0);//color.a } if (show_mask_depth == 1){ float d = readMaskDepth(scrCoord);//texture2D(DepthMaskTexture, scrCoord ).x;//readMaskDepth(scrCoord); result = vec4(d,d,d,1.0);//texture2D(DepthMaskTexture, scrCoord ); } else if ( (only_depth == 1) || (mix_depth == 1) ){ float d = readDepth(scrCoord); if (negative == 1) {d = 1.0 - d;} result = vec4(d,d,d,1.0); if (mix_depth == 1) { result = vec4(color.rgb*result.rgb,1.0); } } gl_FragColor = result;//result;//result; } mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/shaders/vertSSAO0000644000175000017500000000150311650117503022705 0ustar debiandebianvarying vec2 texCoords; varying vec3 vCoords; //varying vec4 test; varying vec2 vTexCoord; varying vec3 normal; //varying vec4 pos; void main (void) { gl_FrontColor = gl_Color;//gl_Normal for normal map gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; //gl_TexCoord[0] = gl_MultiTexCoord0; //vTexCoord = (gl_ModelViewProjectionMatrix * gl_Vertex).xy;//(gl_TextureMatrix[0] * gl_Vertex).xy; //vCoords = (gl_ModelViewProjectionMatrix * gl_Vertex).xyz; //vec4 t = gl ModelViewMatrix * gl_Vertex; //test = gl_ModelViewProjectionMatrix * gl_Vertex;// gl_Position.w; //test = test / test.w; //test = test / test.w ; //viweport transformation ? //normal = normalize(gl_NormalMatrix * gl_Normal.xyz); normal = vec3(gl_ModelViewMatrix * vec4(gl_Normal,0.0)); //pos = gl_Vertex; } mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/shaders/fragNormal0000644000175000017500000000020611644665024023337 0ustar debiandebianvarying vec3 vertex_color; void main (void) { gl_FragColor = vec4(vertex_color,1.0); //gl_FragColor = vec4(1.0,0.0,0.0,1.0); }mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/shaders/vertNormal0000644000175000017500000000043111644665024023400 0ustar debiandebian//varying vec2 texCoord; varying vec3 vertex_color; void main (void) { //TexCoord = gl_MultiTexCoord0; //texCoord = gl_MultiTexCoord0; //gl_Position = ftransform(); gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; vertex_color = gl_Normal.xyz; }mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/PropertyEditor.py0000644000175000017500000001663610651433501023244 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # $Header: /opt/cvs/python/packages/share1.5/DejaVu/PropertyEditor.py,v 1.5 2007/07/24 17:30:41 vareille Exp $ # # $Id: PropertyEditor.py,v 1.5 2007/07/24 17:30:41 vareille Exp $ # import Tkinter, numpy.oldnumeric as Numeric import Slider, ColorWheel, ColorChooser, colorTool from EventHandler import CallbackFunctions class MaterialEditor(CallbackFunctions): """Class for a material editor""" property = [ 'ambient', 'diffuse', 'specular', 'emission' ] def Callbacks(self, event=None): """Implement callback functions""" if type(event) == type(0.0): for f in self.callbacks: f('shininess', event) else: tkrgb = self.colorChooser.hsWheel.Get(mode='TkRGB') c = self.currentComponent.get() self.mat[c] = self.colorChooser.hsWheel.Get(mode='RGB')[:3] self.colw[c].config( background = tkrgb ) for f in self.callbacks: f(self.property[c], self.mat[c]) def RestoreColor(self): """Set the wheel cursor to the color of the current component""" c = self.currentComponent.get() self.colorChooser.Set(self.mat[c], 'RGB') def Set(self, ambi=None, diff=None, spec=None, emis=None, shini=None, mode = 'RGB'): """Set the material Editor to a given material""" assert mode in ('HSV', 'RGB') c = self.currentComponent.get() if ambi: ambi = colorTool.OneColor(ambi) tkrgb = colorTool.TkColor(ambi[:3]) self.colw[0].config( background = tkrgb ) self.mat[0][:3] = ambi[:3] if c==0: self.colorChooser.Set( ambi, 'RGB' ) if diff: diff = colorTool.OneColor(diff) tkrgb = colorTool.TkColor(diff[:3]) self.colw[1].config( background = tkrgb ) self.mat[1][:3] = diff[:3] if c==1: self.colorChooser.Set( diff, 'RGB' ) if spec: spec = colorTool.OneColor(spec) tkrgb = colorTool.TkColor(spec[:3]) self.colw[2].config( background = tkrgb ) self.mat[2][:3] = spec[:3] if c==2: self.colorChooser.Set( spec, 'RGB' ) if emis: emis = colorTool.OneColor(emis) tkrgb = colorTool.TkColor(emis[:3]) self.colw[3].config( background = tkrgb ) self.mat[3][:3] = emis[:3] if c==3: self.colorChooser.Set( emis, 'RGB' ) if shini: self.shini.Set(shini) def __init__(self, root=None, colorChooser=None): CallbackFunctions.__init__(self) self.frame = Tkinter.Frame(root, relief=Tkinter.RIDGE, borderwidth=3) self.mat = Numeric.ones( (4,3), 'f') self.currentComponent = Tkinter.IntVar() self.currentComponent.set(0) self.colw = [0,]*4 width = 9 self.colw[0] = Tkinter.Radiobutton(self.frame, text='Ambient', variable = self.currentComponent, value=0, command=self.RestoreColor, relief = Tkinter.SUNKEN, width=width, borderwidth=3, background = '#FFFFFF', foreground = '#000000', ) self.colw[0].grid(row=0,column=0) self.colw[1] = Tkinter.Radiobutton(self.frame, text='Diffuse', value=1, variable = self.currentComponent, command=self.RestoreColor, borderwidth=3, width=width, relief = Tkinter.SUNKEN, background = '#FFFFFF', foreground = '#000000' ) self.colw[1].grid(row=1,column=0) self.colw[2] = Tkinter.Radiobutton(self.frame, text='Specular', value=2, variable = self.currentComponent, command=self.RestoreColor, relief = Tkinter.SUNKEN, width=width, borderwidth=3, background = '#FFFFFF', foreground = '#000000' ) self.colw[2].grid(row=0,column=1) self.colw[3] = Tkinter.Radiobutton(self.frame, text='Emissive', value=3, variable = self.currentComponent, command=self.RestoreColor, relief = Tkinter.SUNKEN, width=width, borderwidth=3, background = '#FFFFFF', foreground = '#000000') self.colw[3].grid(row=1,column=1) self.shini = Slider.Slider(self.frame, label='Shininess', immediate=0, minval=0.0, maxval = 128.0, init=30.0) self.shini.frame.grid(row=2,column=0,columnspan=2) self.shini.AddCallback(self.Callbacks) if not colorChooser: self.colorChooser = ColorChooser.ColorChooser(self.frame) self.colorChooser.frame.grid(row=3, column=0, columnspan=2) else: self.colorChooser = colorChooser self.colorChooser.AddCallback(self.Callbacks) class LightColorEditor(CallbackFunctions): """Class for a light source color editor""" property = [ 'ambient', 'diffuse', 'specular' ] def Callbacks(self, event=None): """Implement callback functions""" tkrgb = self.colorChooser.hsWheel.Get(mode='TkRGB') c = self.currentComponent.get() self.mat[c] = self.colorChooser.hsWheel.Get(mode='RGB')[:3] self.colw[c].config( background = tkrgb ) for f in self.callbacks: f(self.property[c], self.mat[c]) def RestoreColor(self): """Set the wheel cursor to the color of the current component""" c = self.currentComponent.get() self.colorChooser.Set(self.mat[c], 'RGB') def Set(self, ambi=None, diff=None, spec=None, mode = 'RGB'): """Set the material Editor to a given material""" assert mode in ('HSV', 'RGB') c = self.currentComponent.get() if ambi: ambi = colorTool.OneColor(ambi) tkrgb = colorTool.TkColor(ambi[:3]) self.colw[0].config( background = tkrgb ) self.mat[0][:3] = ambi[:3] if c==0: self.colorChooser.Set( ambi, 'RGB' ) if diff: diff = colorTool.OneColor(diff) tkrgb = colorTool.TkColor(diff[:3]) self.colw[1].config( background = tkrgb ) self.mat[1][:3] = diff[:3] if c==1: self.colorChooser.Set( diff, 'RGB' ) if spec: spec = colorTool.OneColor(spec) tkrgb = colorTool.TkColor(spec[:3]) self.colw[2].config( background = tkrgb ) self.mat[2][:3] = spec[:3] if c==2: self.colorChooser.Set( spec, 'RGB' ) def __init__(self, root=None, colorChooser=None): CallbackFunctions.__init__(self) self.frame = Tkinter.Frame(root, relief=Tkinter.RIDGE, borderwidth=3) self.mat = Numeric.ones( (3,3), 'f') self.currentComponent = Tkinter.IntVar() self.currentComponent.set(0) self.colw = [0,]*4 width = 9 self.colw[0] = Tkinter.Radiobutton(self.frame, text='Ambient', value=0, variable = self.currentComponent, command=self.RestoreColor, relief = Tkinter.SUNKEN, width=width, borderwidth=3, background = '#FFFFFF', foreground = '#000000', ) self.colw[0].grid(row=0,column=0) self.colw[1] = Tkinter.Radiobutton(self.frame, text='Diffuse', value=1, variable = self.currentComponent, command=self.RestoreColor, borderwidth=3, width=width, relief = Tkinter.SUNKEN, background = '#FFFFFF', foreground = '#000000' ) self.colw[1].grid(row=1,column=0) self.colw[2] = Tkinter.Radiobutton(self.frame, text='Specular', value=2, variable = self.currentComponent, command=self.RestoreColor, relief = Tkinter.SUNKEN, width=width, borderwidth=3, background = '#FFFFFF', foreground = '#000000' ) self.colw[2].grid(row=0,column=1) if not colorChooser: self.colorChooser = ColorChooser.ColorChooser(self.frame) self.colorChooser.frame.grid(row=3, column=0, columnspan=2) else: self.colorChooser = colorChooser self.colorChooser.AddCallback(self.Callbacks) if __name__ == '__main__': root = Tkinter.Tk() root.title( 'Material Editor' ) me = MaterialEditor(root) me.frame.pack() lce = LightColorEditor(root) lce.frame.pack() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/ColormapGui.py0000644000175000017500000022574111216031313022462 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # # Revision: Guillaume Vareille # ############################################################################# # # $Header$ # # $Id$ # import types, numpy.oldnumeric as Numeric, os, sys import Tkinter, Pmw import tkFileDialog from string import strip, split, find from opengltk.OpenGL import GL from opengltk.extent import _gllib as gllib from mglutil.util.misc import deepCopySeq from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from mglutil.util.colorUtil import HSL2RGB, RGB2HSL, \ RGBA2HSLA_list, HSLA2RGBA_list, ToHSV, ToHEX from mglutil.gui import widgetsOnBackWindowsCanGrabFocus from DejaVu import viewerConst from DejaVu.colorMap import ColorMap from DejaVu.MaterialEditor import OGLWidget from DejaVu.colorMapLegend import ColorMapLegend from DejaVu.Geom import Geom from DejaVu.colorTool import RGBARamp, RedWhiteBlueRamp, RedWhiteRamp, \ WhiteBlueRamp, TkColor from DejaVu.Legend import drawLegendOnly class ComboBoxRename(Pmw.ComboBox): def setExternalList(self, externalList, reverse=False, numOfBlockedLabels=0): self.externalList = externalList self.reverse = reverse self.numOfBlockedLabels = numOfBlockedLabels def _addHistory(self): #print "_addHistory" lCurSelection = self.curselection() if len(lCurSelection) > 0: lCurSelection0 = int(lCurSelection[0]) if self.reverse is True: lBoolTest = (len(self.externalList)-1-lCurSelection0) >= self.numOfBlockedLabels else: lBoolTest = lCurSelection0 >= self.numOfBlockedLabels if lBoolTest: input = self._entryWidget.get() if (input != '') and (input not in self._list.get(0, 'end') ): self.delete(lCurSelection0) self.insert(lCurSelection0, input) if self.reverse is True: self.externalList[len(self.externalList)-1-lCurSelection0] = input else: self.externalList[lCurSelection0] = input self.selectitem(lCurSelection0) else: self.selectitem(0) class DummyEvent: """dummy Tkinter event """ def __init__(self, x=0, y=0): self.x = x self.y = y COLORMAPGUI_MAXIMAL_HEIGHT = 1024 class ColorMapGUI(Tkinter.Frame, ColorMap): """The ColorMapGUI is an object providing an interface to expose and to modify a ColorMap object. The ColorMapGUI has a local copy of the colormap.ramp, colormap.mini and colormap.maxi which will be modified through the GUI. The associated colormap object will only be updated when by the apply_cb which is called whenever a mouseUp event or update is called if the gui is in continuous mode or when the Aplly button is pressed when the gui is not in a continuous mode. The GUI allows the user to edit each of 4 different color properties: 'Hue','Sat' or saturation, 'Val' or value and 'Opa' or opacity for each entry in the ramp of the ColorMap. This is implemented via 4 Canvases, one for each color property. (Drawing on a canvas is done by pressing the left mouse button over the canvas and holding it down while moving the mouse.) Drawing at a point 'x','y', on one of the canvases changes the value of the corresponding color property in this way: 'y' specifies the entry in the ColorMap.ramp to be changed. 'x' is first normalized to give a value between 0 and 1.0. (by dividing it by the effective canvas width). A new rgba value is built from the hsva list comprised of 3 previous values and this new normalized 'x' in the appropriate position. (that is, if the user is drawing on the 'Hue' canvas, the normalized 'x' value replaces the 'h', or zeroth entry,etc). If the GUI has a viewer, an OpenGLColorMapWidget is constructed which displays the GUI's current rgbMap. Also, the user can choose to add a ColorMapLegend to the viewer which displays the current ColorMap.ramp and which can be labeled. """ staticRamp = RGBARamp(size=128, upperValue=.85).tolist() def __init__(self, cmap=None, master=None, continuous=0, allowRename=True, modifyMinMax=False, viewer=None, xoffset=25, width=200, height=256, geoms=None, name=None, ramp=None, labels=None, mini=None, maxi=None, filename=None, show=True, numOfBlockedLabels=0, **kw): #this is the active colormap if cmap is None: ColorMap.__init__(self, name=name, ramp=ramp, labels=labels, filename=filename, mini=mini, maxi=maxi) else: ColorMap.__init__(self, name=cmap.name, ramp=cmap.ramp, labels=cmap.labels, mini=cmap.mini, maxi=cmap.maxi) self.history = [] self.legend = None if geoms is None: geoms = {} self.geoms = geoms self.viewer = None self.currentOnStack = False self.numOfBlockedLabels = numOfBlockedLabels # initialize a bunch of flags. self.cmapCurrent = True self.cmapCompToReset = None self.cmapResetAll = False self.nbStepBack = 0 # Initialize the local guiRamp, guiMini and guiMaxi values # which will be modified self.guiRamp = [] self.guiMini = None self.guiMaxi = None if self.labels is not None: self.guiLabels = deepCopySeq(self.labels) self.colorbin = [] self.labelbin = [] self.lengthRamp = len(self.ramp) if height < self.lengthRamp: height = self.lengthRamp self.height = height self.linesPerRampValue = self.height / float(self.lengthRamp) self.currentHue = [] self.currentSat = [] # Create parts of the GUI if master is None: if viewer: theMaster = Tkinter.Toplevel(viewer.master) else: theMaster = Tkinter.Toplevel() else: theMaster = master if hasattr(theMaster, 'protocol'): theMaster.protocol('WM_DELETE_WINDOW', self.dismiss) # we hide it if it was asked if show is False: master2 = theMaster while hasattr(master2, 'withdraw') is False and hasattr(master2, 'master') is True: master2 = master2.master master2.withdraw() Tkinter.Frame.__init__(self, theMaster) Tkinter.Pack.config(self, expand=1, fill='both') if hasattr(theMaster, 'title'): theMaster.title(self.name) # Canvas width (default=200) self.width = width self.canvasStart = 4 # left border width (default=25) self.xoffset = xoffset # Available drawing width default=width-xoffset self.xrange = float(width - xoffset) # DejaVu viewer to which colorMapLegend is added self.viewer = None self.continuousUpdate = Tkinter.IntVar() self.continuousUpdate.set(continuous) #if allowRename is False, name entry is disabled. self.allowRename = allowRename self.modifyMinMax = modifyMinMax self.idList = ['Hue','Sat','Val','Opa'] self.getColorFunc = { 'Hue':self.hueColor, 'Sat':self.satColor, 'Val':self.valColor, 'Opa':self.opaColor } #initialize dictionaries #NB all the lines end at xpoints corresponding to the #the colorproperty value at that point... (except #'Hue' is backwards, width-property+xoffset instead of #property+xoffset) self.rightXVals = {} self.lines = {} for idStr in self.idList: self.rightXVals[idStr] = [] self.lines[idStr] = [] self.current = 'Hue' # name of the currently visible prop. canvas self.callbacks = [] # list of functions to be called when apply # button is pressed or ramp is modified and # mode is continuous update # Calls the createWidgets method to create the 4 canvases # and the buttons. self.createWidgets(theMaster) self.configureGui(ramp=self.ramp, geoms=self.geoms, legend=self.legend, labels=self.labels, mini=self.mini, maxi=self.maxi, **kw) # Call the update to initialize the gui with the given cmap values, # without configuring the cmap self.update( mini=self.mini, maxi=self.maxi, ramp=deepCopySeq(self.ramp), cfgCmap=False) self.cmapCurrent = True #set current colorFunc, lines and values to 'Hue' self.getColor = self.getColorFunc['Hue'] self.currentLines = self.lines['Hue'] self.currentValues = self.rightXVals['Hue'] Tkinter.Widget.bind(self, "", self.enter_cb) Tkinter.Widget.bind(self, "", self.leave_cb) #set-up canvas mouse bindings: for idStr in ['Hue', 'Sat', 'Val', 'Opa']: Tkinter.Widget.bind(self.canvas[idStr], "", self.mouseDown) Tkinter.Widget.bind(self.canvas[idStr], "", self.mouseMotion) Tkinter.Widget.bind(self.canvas[idStr], "", self.mouseUp) Tkinter.Widget.bind(self.canvas[idStr], "", self.updateCurTk) Tkinter.Widget.bind(self.canvas[idStr], "", self.mouseDownRight) Tkinter.Widget.bind(self.canvas[idStr], "", self.mouseMotionRight) Tkinter.Widget.bind(self.canvas[idStr], "", self.mouseUpRight) self.canvas[idStr].configure(cursor='cross') self.straightLine = None # create the cml if self.legend is None: self.createCML() self.SetViewer(viewer) # # fields created by the CMLwidget # self.legend.createOwnGui() # self.legend.hideOwnGui() if master is not None: master2 = theMaster if hasattr(master2, 'master') is True and isinstance(master2.master,Tkinter.Widget): master2 = master2.master if hasattr(master2, 'master') is True and isinstance(master2.master,Tkinter.Widget): master2 = master2.master #Tkinter.Widget.bind(master2, '', self.configure_cb) self.inVision = True else: Tkinter.Widget.bind(self.fullWidgetFrame, '', self.configure_cb) self.inVision = False def configure_cb(self, event=None): #print "configure_cb", event, dir (event) #print "configure_cb event.height", event.height # self.width = event.width # self.xrange = float(self.width - self.xoffset) if self.inVision is True: height = event.height - 2*self.canvasStart \ - self.menuFrame1.winfo_reqheight() \ - self.buttonFrame.winfo_reqheight() \ - 73 elif os.name == 'nt': #sys.platform == 'win32': height = event.height - 2*self.canvasStart \ - self.menuFrame1.winfo_reqheight() \ - self.buttonFrame.winfo_reqheight() \ - self.frame2.winfo_reqheight() \ - 2 else: height = event.height - 2*self.canvasStart \ - self.menuFrame1.winfo_reqheight() \ - self.buttonFrame.winfo_reqheight() \ - self.frame2.winfo_reqheight() #print "configure_cb height", height if height >= self.lengthRamp and height > 0: self.height = height #print "self.height 1", self.height self.linesPerRampValue = self.height / float(self.lengthRamp) self.resizeCanvases(self.height) self.drawRampCanvases(drawRamp=True) def changeRampLength_cb(self, numOfRampValue): #print "changeRampLength_cb", numOfRampValue, len(self.guiRamp), len(self.ramp) #import traceback;traceback.print_stack() lenguiramp = len(self.guiRamp) if numOfRampValue < self.numOfBlockedLabels: self.numOfRampValues.set(lenguiramp) return elif numOfRampValue == lenguiramp: return elif numOfRampValue < lenguiramp: for i in range(numOfRampValue, lenguiramp): self.colorbin.append(self.guiRamp.pop()) else: # numOfRampValue > lenguiramp: lNumOfColorsToAdd = numOfRampValue - lenguiramp lNumOfColorsToCreate = lNumOfColorsToAdd - len(self.colorbin) if lNumOfColorsToCreate > 0: for i in range(len(self.colorbin)): self.guiRamp.append(self.colorbin.pop()) for i in range(lNumOfColorsToCreate): lIndex = len(self.guiRamp) % len(self.staticRamp) self.guiRamp.append( self.staticRamp[ lIndex ] ) else: for i in range(lNumOfColorsToAdd): self.guiRamp.append(self.colorbin.pop()) self.configureGui( ramp=self.guiRamp, mini=self.mini, maxi=self.maxi, updateGui=True, theGivenRampIsTheGuiRamp=True, #guiRamp=self.guiRamp ) self.cmapCurrent=False def adjustGuiLabels(self, newNumOfGuiLabels): #print "adjustGuiLabels", newNumOfGuiLabels lenguiLabels = len(self.guiLabels) if newNumOfGuiLabels == lenguiLabels: return elif newNumOfGuiLabels < lenguiLabels: for i in range(newNumOfGuiLabels, lenguiLabels): self.labelbin.append(self.guiLabels.pop()) else: lNumOfLabelsToAdd = newNumOfGuiLabels - lenguiLabels lNumOfLabelsToCreate = lNumOfLabelsToAdd - len(self.labelbin) if lNumOfLabelsToCreate > 0: for i in range(len(self.labelbin)): self.guiLabels.append(self.labelbin.pop()) for i in range(lNumOfLabelsToCreate): self.guiLabels.append( str(len(self.guiLabels) ) ) else: for i in range(lNumOfLabelsToAdd): self.guiLabels.append(self.labelbin.pop()) self.configureGui(labels=self.guiLabels) def createCML(self): """create the ColorMap Legend """ if self.legend: return #width defaults to len(ramp); height defaults to 1 #mini, maxi and interp set from self cmlOptions = {'width':10, 'height':1, 'name':self.name, 'ramp':self.ramp} if self.mini is not None: cmlOptions['mini'] = self.mini if self.maxi is not None: cmlOptions['maxi'] = self.maxi self.legend = apply(ColorMapLegend, (self,), cmlOptions) # def resetComp(self, comp): # """resets on component to first entry in history list""" # compNum = ['Hue','Sat','Val','Opa'].index(comp) # # Get the first entry in the history list # hist = self.history[0] # # Remove all the entries in the history list # self.history = self.history[:1] # # # Transform the history RGBramp into a HSL ramp # histHSL = map(lambda x: list(RGBA2HSLA_list(x)), hist) # # Transform the current ramp in a HSL ramp # hsl = map(lambda x: list(x), self.asHSL()) # for i in range(len(hsl)): # hsl[i][compNum] = histHSL[i][compNum] # ramp = map(lambda x: list(HSLA2RGBA_list(x)), hsl) # self.configure(ramp=ramp, updateGui=False) def reset(self): """return to first entry in history list""" ramp = self.history[0] self.history = [] self.configure(ramp=deepCopySeq(ramp), updateGui=False) def pushRamp(self): """ The pushRamp method appends the current ramp stored in cmap.ramp at the end of the history list. The attribute self.currentOnStack is set to True. """ # append the current ramp to the history if the ramp is not None and # if the ramp has not been pushed onto the history stack yet. if self.ramp is None or self.currentOnStack: return self.history.append(deepCopySeq(self.ramp)) self.currentOnStack = True def popRamp(self, index=-1): """ optional arguments index -- default -1, specifies the index of the ramp to pop. It is a negative index as we are popping ramps from the end of the history list. The popRamp method will save the ramp stored at the given index in cmap.ramp then remove all the entry from the ramp (included) till the end of the history list. After a popRamp the attribute self.currentOnStack is False. """ # Need at least one entry in the history if not len(self.history): return # Always keep the first entry of the history if len(self.history)==1: if not self.currentOnStack: self.ramp = self.history[0] self.currentOnStack = True return # PopRamp removes entry from the end of the history list # which is why the index has to be negative. assert (index < 0) # 1- set the actual ramp to be the entry of history # corresponding to the given index # 2- history = history[:index] # the popped history is not on the stack any longer except # when it is the first entry # Get the index from the beginning of the history list newind = len(self.history)+index pushRamp = False if newind <= 0: newind = 0 # Always keep the first entry in the history list pushRamp = True elif newind >= len(self.history): newind = -1 pushRamp = False ramp = self.history[newind] self.history = self.history[:newind] # We do not want to push the ramp we are popping onto the history stack # the current ramp will not be on the history stack any longer. self.configure(ramp=deepCopySeq(ramp), updateGui=False, pushRamp=pushRamp) def SetViewer(self, viewer): """to give a viewer reference to the ColorMapGUI even after it's creation """ if viewer : if self.viewer is not None: self.viewer.RemoveObject(self.legend) self.viewer = viewer self.createCML() self.legend.name = self.viewer.ensureUniqueName(self.legend.name) self.update(cmapName=self.legend.name) self.legend.replace = False #self.legend.protected = True self.viewer.AddObject(self.legend, redo=0) self.showLegendVar = Tkinter.IntVar() self.showLegendButton = Tkinter.Checkbutton( self.buttonFrame, text='show legend', variable=self.showLegendVar, command=self.showLegendButton_cb) self.showLegendButton.grid(row=5, column=0, columnspan=2, sticky='w') def createWidgets(self, master): """create Tkinter widgets: 4 canvas and buttons in 2 frames """ #print "createWidgets" self.fullWidgetFrame = Tkinter.Frame(master) self.fullWidgetFrame.pack(side='top', expand=1, fill='both') # create menu frame self.menuFrame1 = Tkinter.Frame(self.fullWidgetFrame, relief='raised', borderwidth=3) self.menuFrame1.pack(side='top', expand=1, fill='x') filebutton = Tkinter.Menubutton(self.menuFrame1, text='File') filebutton.pack(side='left') filemenu = Tkinter.Menu(filebutton, {}) filemenu.add_command(label='Read', command=self.read_cb) filemenu.add_command(label='Write', command=self.write_cb) filebutton['menu'] = filemenu editbutton = Tkinter.Menubutton(self.menuFrame1, text='Edit') editbutton.pack(side='left', anchor='w') editmenu = Tkinter.Menu(editbutton, {}) editmenu.add_command(label='Reset to first in history', command=self.resetAll_cb) editmenu.add_command(label='Step back in history loop', command=self.stepBack_cb) ## editmenu.add_checkbutton(label='Preview', variable=self.preview) editmenu.add_checkbutton(label='Continuous', variable=self.continuousUpdate) editmenu.add_command(label='Edit Legend', command=self.editLegend_cb) editbutton['menu'] = editmenu self.numOfRampValues = ThumbWheel( self.menuFrame1, labCfg={'text':'Num of colors:', 'side':'left'}, showLabel=1, width=80, height=16, min=1, max=COLORMAPGUI_MAXIMAL_HEIGHT, type=int, value=self.lengthRamp, callback=self.changeRampLength_cb, continuous=True, oneTurn=60, wheelPad=2 ) self.numOfRampValues.pack(side='right', anchor='e') # create canvas frames self.canvasesFrame = Tkinter.Frame(self.fullWidgetFrame) # create a frame for rproperties canvases self.propCanvasFrame = Tkinter.Frame(self.canvasesFrame) # create 4 canvases self.canvas = {} for idStr in self.idList: self.canvas[idStr] = Tkinter.Canvas( self.propCanvasFrame, relief='sunken', borderwidth=3, width=self.width, height=self.height) #pack Hue to start with self.canvas['Hue'].pack(side='left', expand=1, fill='both') self.propCanvasFrame.pack(side='left', expand=1, fill='both') self.ogl_cmw = OGLColorMapWidget( self.canvasesFrame, self, width=19, height=self.height, ) self.canvasesFrame.pack(side = 'top', expand=1, fill='both') # create a frame for buttons self.buttonFrame = Tkinter.Frame(self.fullWidgetFrame, relief='ridge', borderwidth=3) # create radio buttons to switch between canvas self.currentCanvasVar = Tkinter.StringVar() self.buttonHue = Tkinter.Radiobutton( self.buttonFrame, text='Hue', value = 'Hue', width=8, indicatoron = 0, variable = self.currentCanvasVar, command=self.button_cb) self.buttonHue.grid(row=0, column=0, sticky='we')#pack(side='left') self.buttonSat = Tkinter.Radiobutton( self.buttonFrame, text='Sat.', value = 'Sat', width=8, indicatoron = 0, variable = self.currentCanvasVar, command=self.button_cb) self.buttonSat.grid(row=0, column=1, sticky='we')#pack(side='left') self.buttonVal = Tkinter.Radiobutton( self.buttonFrame, text='Lum.', value = 'Val', width=8, indicatoron = 0, variable = self.currentCanvasVar, command=self.button_cb) self.buttonVal.grid(row=0, column=2, sticky='we')#pack(side='left') self.buttonOpa = Tkinter.Radiobutton( self.buttonFrame, text='Opa.', value = 'Opa', width=8, indicatoron = 0, variable = self.currentCanvasVar, command=self.button_cb) self.buttonOpa.grid(row=0, column=3, sticky='we')#pack(side='left') self.currentCanvas = self.canvas['Hue'] self.currentCanvasVar.set('Hue') # name self.nameVar = Tkinter.StringVar() if self.name is not None: self.nameVar.set(self.name) a = Tkinter.Label(self.buttonFrame, text='name') a.grid(row=2, column=0, sticky='e') if self.allowRename is True: self.nameEntry = Tkinter.Entry( self.buttonFrame, textvariable=self.nameVar, width=18) self.nameEntry.bind('', self.rename_cb) self.nameEntry.bind('', self.rename_cb) else: self.nameEntry = Tkinter.Label( self.buttonFrame, textvariable=self.nameVar, width=18, relief='groove', padx=2, pady=1) self.nameEntry.grid(row=2, column=1, columnspan=3, sticky='w') # min max self.maxTk = Tkinter.StringVar() if self.guiMaxi is not None: self.maxTk.set(('%8.2f'%self.guiMaxi)) a = Tkinter.Label(self.buttonFrame, text='max') a.grid(row=3, column=2, sticky='e') if self.modifyMinMax: self.maxEntry = Tkinter.Entry( self.buttonFrame, textvariable=self.maxTk, width=8) self.maxEntry.bind('', self.max_cb) self.maxEntry.bind('', self.max_cb) else: self.maxEntry = Tkinter.Label( self.buttonFrame, textvariable=self.maxTk, width=8, relief='groove', justify='left', padx=2, pady=1) self.maxEntry.grid(row=3, column=3,sticky='w') self.curyTk = Tkinter.StringVar() a = Tkinter.Label(self.buttonFrame, text='y ') a.grid(row=4, column=2, sticky='e') self.curYLabel = Tkinter.Label( self.buttonFrame, textvariable=self.curyTk, width=8, relief='groove', justify='left', padx=2, pady=1) self.curYLabel.grid(row=4, column=3, sticky='w') self.minTk = Tkinter.StringVar() if self.guiMini is not None: self.minTk.set(('%8.2f'%self.guiMini)) a = Tkinter.Label(self.buttonFrame, text='min') a.grid(row=5, column=2, sticky='e') if self.modifyMinMax: self.minEntry = Tkinter.Entry( self.buttonFrame, textvariable=self.minTk, width=8) self.minEntry.bind('', self.min_cb) self.minEntry.bind('', self.min_cb) else: self.minEntry = Tkinter.Label( self.buttonFrame, textvariable=self.minTk, width=8, relief='groove', justify='right', padx=2, pady=1) self.minEntry.grid(row=5, column=3, sticky='w') self.curxTk = Tkinter.StringVar() a = Tkinter.Label(self.buttonFrame, text='x') a.grid(row=4, column=1, sticky='w') self.curXLabel = Tkinter.Label( self.buttonFrame, textvariable=self.curxTk, width=8, relief='groove', justify='left', padx=2, pady=1) self.curXLabel.grid(row=4, column=0, sticky='w') if self.labels is not None: #self.labelsInComboBox = Tkinter.StringVar() self.labelsComboBox = ComboBoxRename( self.buttonFrame, label_text='label', labelpos='w', history=1) self.labelsComboBox.setExternalList( self.guiLabels, reverse=True, numOfBlockedLabels=self.numOfBlockedLabels) self.labelsComboBox.grid(row=6, column=0, columnspan=4, sticky='w') #Apply and Dismiss go here self.frame2 = Tkinter.Frame(self.fullWidgetFrame, relief='raise', borderwidth=3) f2 = self.frame2 self.apply = Tkinter.Button(f2, text='Apply', command=self.apply_cb) self.apply.pack(side='left', expand=1, fill='x') self.dismiss = Tkinter.Button(f2, text='Dismiss', command=self.dismiss) self.dismiss.pack(side='left', expand=1, fill='x') f2.pack(side='bottom', expand=1, fill='x') self.frame2.pack(side='bottom', expand=1, fill=Tkinter.X) self.buttonFrame.pack(side='bottom', expand=1, fill='x') def update(self, ramp=None, mini=None, maxi=None, cmapName=None, drawRamp=True, cfgCmap=True, theGivenRampIsTheGuiRamp=False, #guiRamp=None ): # Update the name of cmg if relevant if hasattr(self.master, 'title'): self.master.title(cmapName) # Update the maxi and mini values of cmg if maxi is not None and mini is not None: if mini <= maxi: self.guiMaxi = maxi self.guiMini = mini self.minTk.set(('%8.2f'%self.guiMini)) self.maxTk.set(('%8.2f'%self.guiMaxi)) else: self.guiMaxi = None self.guiMini = None self.minTk.set('') self.maxTk.set('') elif maxi is not None and mini is None: if self.guiMini <= maxi: self.guiMaxi = maxi self.maxTk.set(('%8.2f'%self.guiMaxi)) else: self.guiMaxi = None self.maxTk.set('') elif mini is not None and maxi is None: if mini <= self.guiMaxi: self.guiMini = mini self.minTk.set(('%8.2f'%self.guiMini)) else: self.guiMini = None self.minTk.set('') # Update the cmg ramp with the one given if not ramp is None: if theGivenRampIsTheGuiRamp is False: self.cmapCurrent = False ramp = deepCopySeq(self.checkRamp(ramp)) self.lengthRamp = len(ramp) if self.lengthRamp > self.height : self.height = self.lengthRamp #print "self.height 2", self.height self.numOfRampValues.set(self.lengthRamp) self.linesPerRampValue = self.height / float(self.lengthRamp) self.resizeCanvases(self.height) self.guiRamp = ramp if self.labels is not None: self.adjustGuiLabels(self.lengthRamp) self.drawRampCanvases(drawRamp=drawRamp) else: #print "guiRamp" self.lengthRamp = len(ramp) if self.lengthRamp > self.height : self.height = self.lengthRamp #print "self.height 3", self.height #self.numOfRampValues.set(self.lengthRamp) self.linesPerRampValue = self.height / float(self.lengthRamp) self.resizeCanvases(self.height) #self.guiRamp = guiRamp if self.labels is not None: self.adjustGuiLabels(self.lengthRamp) self.drawRampCanvases(drawRamp=drawRamp) # Update the OpenGL ramp self.ogl_cmw.ramp = deepCopySeq(self.guiRamp) self.ogl_cmw.tkRedraw() if self.continuousUpdate.get(): self.configureCmap(cfgCmap=cfgCmap) def configure(self, name=None, ramp=None, geoms=None, legend=None, labels=None, mini='not passed', maxi='not passed', viewer=None, updateGui=True, pushRamp=True, **kw): #print "ColorMapGUI.configure", mini, maxi ColorMap.configure(self, name=name, ramp=ramp, labels=labels, mini=mini, maxi=maxi) if ramp is not None: ramp = self.ramp if labels is not None: labels = self.labels # because it was just set in the configure self.configureGui(ramp=ramp, labels=labels, geoms=geoms, legend=legend, viewer=viewer, updateGui=updateGui, pushRamp=pushRamp, **kw) def configureGui(self, name=None, ramp=None, labels=None, geoms=None, legend=None, viewer=None, updateGui=True, pushRamp=True, #guiRamp=None, theGivenRampIsTheGuiRamp=False, **kw): """Configure the colormapGui with the given values. """ if (ramp is not None) and (theGivenRampIsTheGuiRamp is False): # The ramp is new put has not been pushed onto the history # stack yet self.currentOnStack = False # When pushRamp is True this new ramp is pushed on the stack if pushRamp: self.pushRamp() if labels is not None and self.labels is not None: #print "labels", labels #import traceback;traceback.print_stack() self.labelsComboBox.delete(0,'end') for label in labels: self.labelsComboBox.insert(0, str(label) ) if geoms is not None and len(geoms): self.geoms.update(geoms) if viewer is not None and viewer != self.viewer: self.SetViewer(viewer) if self.name != self.legend.name: self.nameVar.set(self.legend.name) self.rename_cb() # if a legend is specified then set self.legend if legend is not None: self.legend = legend # Then update the legend with the given values if self.legend is not None: cmlOptions = {'ramp':self.ramp} # Need to update the legendValues as well cmlOptions['mini'] = self.mini cmlOptions['maxi'] = self.maxi if hasattr(self, 'showLegendVar'): cmlOptions['visible'] = self.showLegendVar.get() apply(self.legend.Set, (), cmlOptions) if updateGui: self.update(ramp=ramp, mini=self.mini, maxi=self.maxi, cfgCmap=False, theGivenRampIsTheGuiRamp=theGivenRampIsTheGuiRamp, ) def Map(self, values, mini='not passed', maxi='not passed'): col = ColorMap.Map(self, values, mini=mini, maxi=maxi) if self.legend is not None: cmlOptions = {'ramp':self.ramp} # Need to update the legendValues with the value that where just used cmlOptions['mini'] = self.lastMini cmlOptions['maxi'] = self.lastMaxi if hasattr(self, 'showLegendVar'): cmlOptions['visible'] = self.showLegendVar.get() apply(self.legend.Set, (), cmlOptions) return col def configureCmap(self, cfgCmap=True): """ This method configures the associated cmap with the GUI new values. """ if self.cmapCompToReset is not None: self.resetComp(self.cmapCompToReset) self.cmapCompToReset = None cfgCmap = False self.cmapCurrent = True if self.cmapResetAll is True: self.reset() self.cmapResetAll = False cfgCmap = False self.cmapCurrent = True if self.nbStepBack != 0: if self.nbStepBack == len(self.history): cfgCmap = False self.cmapCurrent = True self.popRamp(-self.nbStepBack) self.nbStepBack = 0 if cfgCmap: # if self.allowRename: # name = self.nametk.get() # else: # name=None # donnot update the cmap if already current... if self.cmapCurrent: ramp=None else: ramp = deepCopySeq(self.guiRamp) self.configure(ramp=ramp, mini=self.guiMini, maxi=self.guiMaxi) if self.legend is not None: if self.legend.viewer: self.tk.call(self.legend.viewer.currentCamera._w, 'makecurrent') self.legend.RedoDisplayList() self.legend.viewer.Redraw() self.cmapCurrent = True if self.labels is not None: self.labels = deepCopySeq(self.guiLabels) #print "self.labels", self.labels # Then will call the callbacks with the new cmap values. self.callCallbacks() def drawRampCanvases(self, event=None, drawRamp=True): """draw all ramp canvases """ #print "drawRampCanvases" # update Ramp self.currentHue = range(self.lengthRamp) self.currentSat = range(self.lengthRamp) if drawRamp: for v in self.idList: self.deleteCanvasLines(v) self.setRightXVals(v) var = self.currentCanvasVar.get() self.currentValues = self.rightXVals[var] self.drawHue() self.drawSaturation() self.drawValue() self.drawOpacity() ################################################################# ### MOUSE CALLBACKS ################################################################# def mouseUp(self, event=None): self.cmapCurrent=False self.update(drawRamp=False) def mouseDown(self, event): j = self.canvasStart # canvas x and y take the screen coords from the event and translate # them into the coordinate system of the canvas object Y = min(j+self.height-1, event.y) x = min(self.width, event.x) x = max(self.xoffset, x) if Y < j: Y = j y = int ( (Y-j) / self.linesPerRampValue) if y < 0: y = 0 self.startx = x self.startY = Y self.starty = y self.updateCurTk(event) c = self.currentCanvas lineIndex = self.lengthRamp-1-y line = self.currentLines[lineIndex] col, graybitmap = self.getColor(x, lineIndex) #y newline = c.create_rectangle( j, y*self.linesPerRampValue+j, 1+x,#+j, (1+y)*self.linesPerRampValue+j, outline='', fill=col, stipple=graybitmap) self.currentLines[lineIndex] = newline #update self.guiRamp self.updateRGBMap(x, lineIndex) #update rightXVals self.currentValues[lineIndex] = x c.delete(line) def mouseMotion(self, event): j = self.canvasStart # canvas x and y take the screen coords from the event and translate # them into the coordinate system of the canvas object # x,y are float #x = self.canvasHue.canvasx(event.x) #y = self.canvasHue.canvasy(event.y) # event.x, event.y are same as x,y but int Y = min(j+self.height-1, event.y) x = min(self.width, event.x) x = max(self.xoffset, x) if Y < j: Y = j y = int ( (Y-j) / self.linesPerRampValue) if y < 0: y = 0 elif self.startx is None: self.mouseDown(event) c = self.currentCanvas if self.startY == Y: lineIndex = self.lengthRamp-1-y #print "lineIndex 0 ...", lineIndex line = self.currentLines[lineIndex] col, graybitmap = self.getColor(x, lineIndex) newline = c.create_rectangle( j, y*self.linesPerRampValue+j, 1+x,#+j, (1+y)*self.linesPerRampValue+j, outline='', fill=col, stipple=graybitmap) self.currentLines[lineIndex] = newline c.delete(line) self.currentValues[lineIndex] = x self.updateRGBMap(x, lineIndex) else: # we need to interpolate for all y's between self.starty and y dx = x-self.startx dy = Y-self.startY rat = float(dx)/float(dy) if Y > self.startY: for Yl in range(self.startY, Y+1): yl = int ( (Yl-j) / self.linesPerRampValue) ddx = int(rat*(Yl-self.startY)) + self.startx lineIndex = self.lengthRamp-1-yl #print "lineIndex 1 ...", lineIndex line = self.currentLines[lineIndex] col, graybitmap = self.getColor(ddx, lineIndex) newline = c.create_rectangle( j, yl*self.linesPerRampValue+j, 1+ddx,#+j, (yl+1)*self.linesPerRampValue+j, outline='', fill=col, stipple=graybitmap) self.currentLines[lineIndex] = newline c.delete(line) self.currentValues[lineIndex] = ddx self.updateRGBMap(ddx, lineIndex) else: for Yl in range(self.startY, Y-1, -1): yl = int ( (Yl-j) / self.linesPerRampValue) ddx = int(rat*(Yl-self.startY)) + self.startx lineIndex = self.lengthRamp-1-yl #print "lineIndex 2 ...", lineIndex line = self.currentLines[lineIndex] col, graybitmap = self.getColor(ddx, lineIndex) newline = c.create_rectangle( j, yl*self.linesPerRampValue+j, 1+ddx,#+j, (1+yl)*self.linesPerRampValue+j, outline='', fill=col, stipple=graybitmap) self.currentLines[lineIndex] = newline c.delete(line) self.currentValues[lineIndex] = ddx self.updateRGBMap(ddx, lineIndex) self.startY = Y self.startx = x # this flushes the output, making sure that # the rectangle makes it to the screen # before the next event is handled self.update_idletasks() self.updateCurTk(event) def mouseDownRight(self, event): j = self.canvasStart Y = min(j+self.height-1, event.y) x = min(self.width, event.x) x = max(self.xoffset, x) if Y < j: Y = j y = int ( (Y-j) / self.linesPerRampValue) if y < 0: y = 0 self.startx = x self.startY = Y self.starty = y def mouseMotionRight(self, event): j = self.canvasStart Y = min(j+self.height-1, event.y) x = min(self.width, event.x) x = max(self.xoffset, x) if Y < j: Y = j y = int ( (Y-j) / self.linesPerRampValue) if y < 0: y = 0 elif self.startx is None: self.mouseDown(event) c = self.currentCanvas if self.straightLine is not None: c.delete(self.straightLine[0]) c.delete(self.straightLine[1]) dy = Y-self.startY if abs(dy) < (self.linesPerRampValue/2): return straightLineBlack = c.create_line( self.startx,#+j, (self.starty+.5)*self.linesPerRampValue+j, x,#+j, (y+.5)*self.linesPerRampValue+j, fill='black', width=3) straightLineWhite = c.create_line( self.startx,#+j, (self.starty+.5)*self.linesPerRampValue+j, x,#+j, (y+.5)*self.linesPerRampValue+j, fill='white', width=1) self.straightLine = [straightLineBlack, straightLineWhite] self.update_idletasks() self.updateCurTk(event) def mouseUpRight(self, event=None): j = self.canvasStart c = self.currentCanvas if self.straightLine is not None: c.delete(self.straightLine[0]) c.delete(self.straightLine[1]) Y = min(j+self.height-1, event.y) x = min(self.width, event.x) x = max(self.xoffset, x) if Y < j: Y = j y = int ( (Y-j) / self.linesPerRampValue) if y < 0: y = 0 elif self.startx is None: self.mouseDown(event) dx = x-self.startx dY = Y-self.startY dy = y-self.starty if abs(dY) < (self.linesPerRampValue/2): return rat = float(dx)/float(dy) if y > self.starty: for yl in range(self.starty, y+1): ddx = int(rat*(yl-self.starty)) + self.startx lineIndex = self.lengthRamp-1-yl line = self.currentLines[lineIndex] col, graybitmap = self.getColor(ddx, lineIndex) newline = c.create_rectangle( j, yl*self.linesPerRampValue+j, 1+ddx,#+j, (yl+1)*self.linesPerRampValue+j, outline='', fill=col, stipple=graybitmap) self.currentLines[lineIndex] = newline c.delete(line) self.currentValues[lineIndex] = ddx self.updateRGBMap(ddx, lineIndex) else: for yl in range(self.starty, y-1, -1): ddx = int(rat*(yl-self.starty)) + self.startx lineIndex = self.lengthRamp-1-yl line = self.currentLines[lineIndex] col, graybitmap = self.getColor(ddx, lineIndex) newline = c.create_rectangle( j, yl*self.linesPerRampValue+j, 1+ddx,#+j, (yl+1)*self.linesPerRampValue+j, outline='', fill=col, stipple=graybitmap) self.currentLines[lineIndex] = newline c.delete(line) self.currentValues[lineIndex] = ddx self.updateRGBMap(ddx, lineIndex) self.starty = y self.startY = Y self.startx = x # this flushes the output, making sure that # the rectangle makes it to the screen # before the next event is handled self.update_idletasks() self.updateCurTk(event) self.cmapCurrent=False self.update(drawRamp=False) ########################################################################### ## CALLBACK FUNCTIONS ########################################################################### def apply_cb(self, event=None, cfgCmap=True): """ """ #print "ColorMapGUI apply_cb" # Need to set self.guiMini, self.guiMaxi,from, to, from fill and to fill # to be set to the proper values. # Method which reconfigures the colormap associated to the gui self.configureCmap() def fileOpenAsk(self, idir=None, ifile=None, types=None, title='Open'): if types==None: types = [ ('All files', '*') ] file = tkFileDialog.askopenfilename( filetypes=types, initialdir=idir, initialfile=ifile, title=title) if file=='': file = None return file def fileSaveAsk(self, idir=None, ifile=None, types = None, title='Save'): if types==None: types = [ ('All files', '*') ] file = tkFileDialog.asksaveasfilename( filetypes=types, initialdir=idir, initialfile=ifile, title=title) if file=='': file = None return file def button_cb(self, event=None): """call back function for the buttons allowing to toggle between different canvases. This function hides the currentCanvas and shows the canvas corresponding to the active radio button. In addition it sets self.currentCanvas : used to hide it next time we come in self.currentLines : list of Canvas Line objects (one per canvas) self.currentValues : list of numerical rightXVals (one per canvas) self.getColor = function to be called to represent a color as a Tk string """ var = self.currentCanvasVar.get() if var == 'Hue': self.drawHue() elif var == 'Sat': self.drawSaturation() elif var == 'Val': self.drawValue() elif var == 'Opa': self.drawOpacity() newCanvas = self.canvas[var] self.currentCanvas.forget() newCanvas.pack(side='top') self.currentCanvas = newCanvas self.currentLines = self.lines[var] self.currentValues = self.rightXVals[var] self.getColor = self.getColorFunc[var] self.current = var def min_cb(self, event=None): minVal = self.minTk.get() try: minVal = float(minVal) if self.guiMaxi is not None and minVal >= self.guiMaxi: raise ValueError self.update(mini=minVal) except: self.minTk.set('') self.guiMini = None return def max_cb(self, event=None): maxVal = self.maxTk.get() try: maxVal = float(maxVal) if self.guiMini is not None and maxVal <= self.guiMini: raise ValueError self.update(maxi=maxVal) except: self.maxTk.set('') self.guiMaxi = None return def rename_cb(self, event=None): self.name = self.nameVar.get() self.update(cmapName=self.name) self.legend.Set(name=self.name) if self.legend.ownGui is not None: self.legend.ownGui.title(self.legend.name) if self.viewer is not None: self.viewer.Redraw() def quit(self): #print "quit" self.master.destroy() def dismiss(self): #print "dismiss" if self.master.winfo_ismapped(): self.master.withdraw() def resetAll_cb(self, event=None): self.cmapResetAll = True self.update(ramp = deepCopySeq(self.history[0]), cfgCmap=False) # def reset_cb(self, event=None): # """reset only the currently visible property canvas""" # var = self.currentCanvasVar.get() # self.deleteCanvasLines(var) # ramp = deepCopySeq(self.history[0]) # # self.lengthRamp = len(ramp) # if self.lengthRamp > self.height : # self.height = self.lengthRamp # self.numOfRampValues.set( self.lengthRamp ) # # hsva = map(lambda x, conv=RGBA2HSLA_list: conv(x), ramp) # ind = self.idList.index(var) # #format?...list?....array?? # newVals = Numeric.array(hsva)[:,ind] # self.guiRamp = self.buildRGBMap(ind, newVals) # # self.cmapCompToReset = var # if var == 'Hue': # self.setRightXVals('Hue') # self.drawHue() # elif var == 'Sat': # self.setRightXVals('Sat') # self.drawSaturation() # elif var == 'Val': # self.setRightXVals('Val') # self.drawValue() # elif var == 'Opa': # self.setRightXVals('Opa') # self.drawOpacity() # if self.continuousUpdate.get(): # self.configureCmap() # #self.mouseUp(None) # to call callbacks # self.currentValues = self.rightXVals[var] # self.ogl_cmw.ramp = self.guiRamp[:] # self.ogl_cmw.tkRedraw() def stepBack_cb(self): #update self.ramp to last ramp on history list if len(self.history)==1 and self.cmapCurrent is True: return if self.cmapCurrent and self.nbStepBack == 0: index = self.nbStepBack + 2 else: index = self.nbStepBack + 1 self.nbStepBack = index newind = len(self.history)-index cfgCmap = True if newind < 0: # tried to go back too far newind = 0 self.nbStepBack = 0 if newind == 0: # only valid for continuous mode. # want to go back to the first entry of the history which # stays so we don't need to update the cmap cfgCmap=False self.update(ramp=self.history[newind], cfgCmap=cfgCmap) def read_cb(self): fileTypes = [("ColorMap",'*_map.py'), ("any file",'*.*')] fileBrowserTitle = "Read Color Map" fileName = self.fileOpenAsk(types=fileTypes, title=fileBrowserTitle) if not fileName: return self.read(fileName) def read(self, filename): ColorMap.read(self, filename) self.configureGui(ramp=self.ramp, mini=self.mini, maxi=self.maxi) if self.legend.viewer: #self.legend.RedoDisplayList() self.legend.viewer.Redraw() #self.configureCmap() def enter_cb(self, event=None): if widgetsOnBackWindowsCanGrabFocus is False: lActiveWindow = self.focus_get() if lActiveWindow is not None \ and ( lActiveWindow.winfo_toplevel() != self.winfo_toplevel() ): return self.focus_set() def leave_cb(self, event=None): pass ############################################################ ### UTILITY FUNCTIONS ############################################################ def makeEvent(self, x, y): xval = x*self.xrange + self.xoffset return DummyEvent( xval, y) def hueColor(self, val, rampIndex): """ TkColorString <- hueColor(val) val is an integer between self.xoffset and self.width. (default:val is an integer between 25 and 200.) returns color to be use to draw hue lines in hue canvas """ #print "hueColor", h if val > self.width: h = 1 else: h = (float(self.width-val)/self.xrange) #* .999 #*.6666666667 # if h == 0: # h = 1 self.currentHue[rampIndex] = h rgb = HSL2RGB(h, 1., .5) graybitmap = '' return TkColor(rgb), graybitmap def satColor(self, val, rampIndex): """ TkColorString <- satColor(val) val is an integer between self.xoffset and self.width. (default:val is an integer between 25 and 200.) returns color to be use to draw saturation lines in saturation canvas """ #print "satColor", val, rampIndex if val < self.xoffset: x = 0 else: x = float(val-self.xoffset)/self.xrange self.currentSat[rampIndex] = x rgb = HSL2RGB(self.currentHue[rampIndex], x, .5) rgb.append(1.) graybitmap = '' return TkColor(rgb), graybitmap def valColor(self, val, rampIndex): """ TkColorString <- valColor(val) val is an integer between 25 and 200 returns color to be used to draw value and opacity lines in canvas """ #print "valColor", val, rampIndex if val < self.xoffset: x = 0 else: x = float(val-self.xoffset)/self.xrange rgb = HSL2RGB(self.currentHue[rampIndex], self.currentSat[rampIndex], x) rgb.append(1.) graybitmap = '' return TkColor(rgb), graybitmap def opaColor(self, val, rampIndex=None): #print "opaColor" if val < self.xoffset: x = 0 else: x = float(val-self.xoffset)/self.xrange if x >= 1: graybitmap = '' col = 'black' elif x > .75: graybitmap = 'gray75' col = 'black' elif x > .50: graybitmap = 'gray50' col = 'black' elif x > .25: graybitmap = 'gray25' col = 'black' elif x > 0: graybitmap = 'gray12' col = 'black' else: graybitmap = '' col='' return col, graybitmap def opaColor_Unused(self, val, rampIndex=None): # the color of the dot changes # we don't use it because the limit line drawn is less visible x = float(val- self.xoffset)/self.xrange background = self.canvas['Opa'].configure()['background'] backgroundHSV = ToHSV(background[4], mode='HEX', flag255=0) bgHSV = [backgroundHSV[0], backgroundHSV[1], backgroundHSV[2] * (1-x)] col = ToHEX(bgHSV, mode='HSV') if x >= 1: graybitmap = '' elif x > .75: graybitmap = 'gray75' elif x > .50: graybitmap = 'gray50' elif x > .25: graybitmap = 'gray25' elif x > 0: graybitmap = 'gray12' else: graybitmap = '' return col, graybitmap # def createCMLWidget(self): # self.legend_gui = Tkinter.Toplevel() # self.legend_gui.title(self.legend.name) # self.legend_gui.protocol('WM_DELETE_WINDOW', self.legend_gui.withdraw ) # # frame1 = Tkinter.Frame(self.legend_gui) # frame1.pack(side='top') # # #unit # self.unitsEnt = Pmw.EntryField(frame1, # label_text='Units ', # labelpos='w', # command=self.updateCML_cb) # self.unitsEnt.pack(side='top', fill='x') # # #glf vector font # self.glfFont = Tkinter.StringVar() # self.glfFont.set('chicago1.glf') # self.glfFontCB = Pmw.ComboBox(frame1, label_text='Font ', # labelpos='w', # entryfield_value=self.glfFont.get(), # scrolledlist_items=ColorMapLegend.glfVectorFontList, # selectioncommand=self.updateCML_cb) # self.glfFontCB.pack(side='top', fill='x') # # #fontScale # self.fontScale = ThumbWheel(frame1, # labCfg={'text':'font scale ', 'side':'left'}, # showLabel=1, # width=90, # height=14, # min=0, # max=200, # type=int, # value=self.legend.fontScale, # callback=self.updateCML_cb, # continuous=True, # oneTurn=10, # wheelPad=0) # self.fontScale.pack(side='top') # # #label # self.labelValsEnt = Pmw.EntryField( # frame1, # label_text='Numeric labels ', # labelpos='w', # command=self.updateCML_cb) # self.labelValsEnt.component('entry').config(width=6) # self.labelValsEnt.pack(side='top', fill='x') # # #numOfLabel # self.numOfLabelsCtr = ThumbWheel(frame1, # labCfg={'text':'Automatic labels', 'side':'left'}, # showLabel=1, # width=90, # height=14, # min=0, # max=200, # type=int, # value=5, # callback=self.updateCML_cb, # continuous=True, # oneTurn=20, # wheelPad=0) # self.numOfLabelsCtr.pack(side='top') # # # Interpolate # self.interpVar = Tkinter.IntVar() # self.interpVar.set(0) # self.checkBoxFrame = Tkinter.Checkbutton( # frame1, # text='Interpolate', # variable=self.interpVar, # command=self.updateCML_cb) # self.checkBoxFrame.pack(side='top') # # # frame # self.frameVar = Tkinter.IntVar() # self.frameVar.set(1) # self.checkBoxFrame = Tkinter.Checkbutton( # frame1, # text='Frame', # variable=self.frameVar, # command=self.updateCML_cb) # self.checkBoxFrame.pack(side='top') # # # invert labels color # self.invertLabelsColorVar = Tkinter.IntVar() # self.invertLabelsColorVar.set(0) # self.checkBoxinvertLabelsColor = Tkinter.Checkbutton( # frame1, # text='Invert labels color', # variable=self.invertLabelsColorVar, # command=self.updateCML_cb) # #self.checkBoxFrame.pack(side='top') # self.checkBoxinvertLabelsColor.pack(side='top') # # # colormapguiwidget: # self.launchColormapWidget = Tkinter.Button( # frame1, # text="Show colormap settings", # command=self.showColormapSettings_cb ) # self.launchColormapWidget.pack(side='top', fill='x') def showColormapSettings_cb(self, event=None): #print "showColormapSettings_cb" master = self.master while hasattr(master, 'deiconify') is False and hasattr(master, 'master') is True: master = master.master if hasattr(master, 'deiconify'): if master.winfo_ismapped() == 0: master.deiconify() master.lift() #else: master.withdraw() def showLegendButton_cb(self, event=None): #print "showLegendButton_cb" if not self.viewer: return if not self.legend: self.createCML() visible = self.showLegendVar.get() self.legend.Set(visible=visible) #self.legend.setWithOwnGui() if visible == 0: if self.legend.viewer.currentObject is self.legend: self.legend.viewer.SetCurrentObject(self.legend.viewer.rootObject) #do you have to do a redraw to see it? self.viewer.Redraw() def showLegend(self): self.showLegendVar.set(1) self.showLegendButton_cb() def hideLegend(self): self.showLegendVar.set(0) self.showLegendButton_cb() def editLegend_cb(self, event=None): #print "editLegend_cb" if not self.legend: self.createCML() self.legend.showOwnGui() def resizeCanvases(self, height=None, width=None): #print "resizeCanvases" if height is not None: for c in self.canvas.values(): c.configure(height=height) self.ogl_cmw.configure(height=height) self.ogl_cmw.height = height if width is not None: for c in self.canvas.values(): c.configure(width=width) self.ogl_cmw.configure(width=width) self.ogl_cmw.width = width def buildRGBMap(self, ind, newVals): """ ind is 0 for Hue, 1 for Sat etc newVals is list of new rightXValues for that column """ #print "buildRGBMap" rgbs = [] hsva = map(list, map(RGBA2HSLA_list, self.guiRamp)) for i in range(len(self.guiRamp)): hsva[i][ind] = newVals[i] rgbs.append(list(HSLA2RGBA_list(hsva[i]))) return rgbs def buildRightXVals(self): """ idList = ['Hue','Sat','Opa','Val'] """ for id in self.idList: self.setRightXVals(id) def setRightXVals(self, idStr): #each canvas line is drawn at constant y value #between x1=0 on the left and x2 which is current #ramp at y (which ranges between 0. and 1.) times 175 #NB: 175 is the effective width of the canvas #idList = ['Hue','Sat','Opa','Val'] #print "setRightXVals" if idStr not in self.idList: return ind = self.idList.index(idStr) #apparently these are 200-this value and #for entire Hue ramp delta x = .66401 hsvaRamp = map(list, map(RGBA2HSLA_list, self.guiRamp)) ramp_vals = Numeric.array(hsvaRamp)[:,ind] norm_n = ramp_vals if idStr=='Hue': # self.width is 200 which is 25 border + 175 map # 25 and 175 are the default values but can be changed val = self.width - (norm_n * self.xrange) else: val = norm_n * self.xrange + self.xoffset #self.rightXVals[idStr] = map(int, val.tolist()) self.rightXVals[idStr] = val.tolist() def write_cb(self): fileTypes = [("ColorMap",'*_map.py'), ("any file",'*.*')] fileBrowserTitle = "Write Color Map" fileName = self.fileSaveAsk(types=fileTypes, title=fileBrowserTitle) if not fileName: return self.write(fileName) def deleteCanvasLines(self, name): """delete all lines in ramp canvas""" assert name in self.idList #assert name in ['Hue', 'Sat', 'Val', 'Opa' ] l = self.lines[name] c = self.canvas[name] for i in range(len(l)): c.delete(l[i]) self.lines[name] = [] self.rightXVals[name] = [] self.curxTk.set("0.0") self.curyTk.set("0.0") if self.current==name: self.currentValues = self.rightXVals[name] self.currentLines = self.lines[name] def drawHue(self): j = self.canvasStart #print "drawHue" #this is for initializing and resets l = self.lines['Hue'] c = self.canvas['Hue'] v = self.rightXVals['Hue'] for i in range(len(l)): c.delete(l[i]) self.lines['Hue'] = [] l = self.lines['Hue'] for i in range(self.lengthRamp): #nb val is the LENGTH of the line to draw val = v[i] col, graybitmap = self.hueColor(val, i) l.append( c.create_rectangle( j, (self.lengthRamp-1-i)*self.linesPerRampValue+j, 1+val, ((self.lengthRamp-1-i)+1)*self.linesPerRampValue+j, fill=col, outline='') ) if self.current=='Hue': self.currentLines = l def drawSaturation(self): #print "drawSaturation" c = self.canvas['Sat'] l = self.lines['Sat'] v = self.rightXVals['Sat'] j = self.canvasStart for i in range(len(l)): c.delete(l[i]) self.lines['Sat'] = [] l = self.lines['Sat'] for i in range(self.lengthRamp): val = v[i] col, graybitmap = self.satColor(val, i) l.append( c.create_rectangle( j, (self.lengthRamp-1-i)*self.linesPerRampValue+j, 1+val, ((self.lengthRamp-1-i)+1)*self.linesPerRampValue+j, fill=col, outline='') ) if self.current=='Sat': self.currentLines = l def drawValue(self): c = self.canvas['Val'] l = self.lines['Val'] v = self.rightXVals['Val'] j = self.canvasStart for i in range(len(l)): c.delete(l[i]) self.lines['Val'] = [] l = self.lines['Val'] for i in range(self.lengthRamp): val = v[i] col, graybitmap = self.valColor(val, i) #print "val i col", val, i, col l.append( c.create_rectangle( j, (self.lengthRamp-1-i)*self.linesPerRampValue+j, 1+val, ((self.lengthRamp-1-i)+1)*self.linesPerRampValue+j, fill=col, outline='') ) if self.current=='Val': self.currentLines = l def drawOpacity(self): c = self.canvas['Opa'] l = self.lines['Opa'] v = self.rightXVals['Opa'] j = self.canvasStart for i in range(len(l)): c.delete(l[i]) self.lines['Opa'] = [] l = self.lines['Opa'] for i in range(self.lengthRamp): val = v[i] col, graybitmap = self.opaColor(val) l.append( c.create_rectangle( j, (self.lengthRamp-1-i)*self.linesPerRampValue+j, 1+val, ((self.lengthRamp-1-i)+1)*self.linesPerRampValue+j, outline='', fill=col, stipple=graybitmap) ) if self.current=='Opa': self.currentLines = l def addCallback(self, function): assert callable(function) self.callbacks.append( function ) def callCallbacks(self): for f in self.callbacks: f( self ) def valueAtY(self, y): # compute the value for q given line in canvas y = y - self.canvasStart y = max(y, 0) y = min(y, self.height-1) if self.guiMini is not None and self.guiMaxi is not None: range = self.guiMaxi-self.guiMini return (float(self.height-y)/(self.height-1))*range + self.guiMini else: return int((self.height-y)/self.linesPerRampValue) def indexAtY(self, y): # compute the value for q given line in canvas j = self.canvasStart Y = min(j+self.height-1, y) if Y < j: Y = j y = int ( (Y-j) / self.linesPerRampValue) return y def updateCurTk(self, event): x = event.x# - self.canvasStart x = max(x, self.xoffset) x = min(x, self.width) val = (x-self.xoffset)/self.xrange self.curxTk.set("%4.2f"%val) lVal = self.valueAtY(event.y) if lVal is not None: self.curyTk.set("%4.2f"%lVal) else: self.curyTk.set('') if self.labels is not None: self.labelsComboBox.selectitem(self.indexAtY(event.y)) def updateOGLwidget(self): self.ogl_cmw.tkRedraw() def updateRGBMap(self, x, y): cur_val = list(RGBA2HSLA_list(self.guiRamp[y])) cur_val[0] = self.currentHue[y] cur_val[1] = self.currentSat[y] if self.current=='Hue': h = ((self.width-x)/self.xrange) * .999 #*.6666666667 cur_val[0] = round(h, 3) else: #use keyList = ['Sat', 'Val', 'Opa'] keyList = self.idList[1:] ind = keyList.index(self.current) + 1 h = (x-self.xoffset)/self.xrange cur_val[ind] = round(h, 3) self.guiRamp[y] = list(HSLA2RGBA_list(cur_val)) class OGLColorMapWidget(OGLWidget): """This object provides a OpenGL window that displays an RGBA color map""" def __init__(self, master, cmap, title='OGLColorMapWidget', width=None, height=None, cnf=None, **kw): if width is None: kw['width'] = 19 else: kw['width'] = width if height is None: kw['height'] = 180 else: kw['height'] = height self.callback = None assert isinstance(cmap, ColorMap) self.ramp = deepCopySeq(cmap.ramp) self.step = 1 # set to larger values to accelerate redraw tf = self.topFrame = Tkinter.Frame(master, borderwidth=1) self.frame = Tkinter.Frame(tf, borderwidth=3, relief='sunken') if cnf is None: cnf = {} apply( OGLWidget.__init__, (self, self.frame, title, cnf, 0), kw ) self.frame.pack(expand=1,fill='both') self.topFrame.pack(expand=1,fill='both') self.pack(side='left',expand=1,fill='both') #self.initTexture() def tkRedraw(self, *dummy): """guillaume: probably useless, the code is almost identical in the overriden function OGLWidget.tkRedraw """ self.update_idletasks() self.tk.call(self._w, 'makecurrent') self.initProjection() GL.glPushMatrix() apply( self.redraw, dummy ) #guillaume: self.redraw() in OGLWidget.tkRedraw GL.glFlush() GL.glPopMatrix() self.tk.call(self._w, 'swapbuffers') def redraw(self, line=None): #print "redraw" drawLegendOnly( fullWidth=self.width, fullHeight=self.height, ramp=self.ramp, verticalLegend=True, roomLeftToLegend=0, roomBelowLegend=0, legendShortSide=self.width, legendLongSide=self.height, interpolate=False, selected=False, ) return if __name__ == '__main__': #import pdb #test = ColorMapGUI() #def cb(ramp, min, max): #print len(ramp), min, max #test.addCallback(cb) ##cm = ColorMap('cmap', filename='/home/rhuey/python/dev/rgb.map') #cmg = ColorMapGUI(cm, allowRename=1) l = {} g = {} execfile('Tests/rgb256_map.py', g,l) cm = None #for name, object in l.items(): # if isinstance(object, ColorMap): # cm = object # break cm = l['cm'] from DejaVu import Viewer vi = Viewer() cmg = ColorMapGUI(cm, allowRename=1, viewer=vi ) #test.mainloop() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/0000755000175000017500000000000012146210041022254 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/summer.py0000644000175000017500000002457307354231036024165 0ustar debiandebian# material definition table: summer # summer = [\ [ # 0 [[0.712006, 0.702151, 0.643298, 1.0]], # ambient [[0.982993, 0.969388, 0.888136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0, 0.0, 1.0]], # specular [0.0], # shininess [ 1.0], # opacity ], [ # 1 [[0.194631, 0.146621, 0.135912, 1.0]], # ambient [[0.766102, 0.577127, 0.534973, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0, 0.0, 1.0]], # specular [0.027027], # shininess [ 1.0], # opacity ], [ # 2 [[0.105523, 0.169052, 0.191584, 1.0]], # ambient [[0.406702, 0.651555, 0.738397, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 0.131592, 0.218563, 1.0]], # specular [0.848649], # shininess [ 1.0], # opacity ], [ # 3 [[0.0135021, 0.0582278, 0.097479, 1.0]], # ambient [[0.0540084, 0.232911, 0.389916, 1.0]], # diffuse [[0.00540541, 0.00540541, 0.00540541, 1.0]], # emission [[0.0963412, 0.0794815, 0.379258, 1.0]], # specular [0.994595], # shininess [ 1.0], # opacity ], [ # 4 [[0.0135021, 0.0582278, 0.097479, 1.0]], # ambient [[0.0540084, 0.232911, 0.389916, 1.0]], # diffuse [[0.00540541, 0.00540541, 0.00540541, 1.0]], # emission [[0.0510891, 0.220322, 0.368839, 1.0]], # specular [0.0648649], # shininess [ 1.0], # opacity ], [ # 5 [[0.0877551, 0.0639456, 0.183051, 1.0]], # ambient [[0.35102, 0.255782, 0.732203, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0801129, 0.345487, 0.578378, 1.0]], # specular [0.0918919], # shininess [ 1.0], # opacity ], [ # 6 [[0.0492359, 0.0358774, 0.102703, 1.0]], # ambient [[0.191761, 0.139733, 0.4, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0381847, 0.164671, 0.275676, 1.0]], # specular [0.0216216], # shininess [ 1.0], # opacity ], [ # 7 [[0.0492359, 0.0358774, 0.102703, 1.0]], # ambient [[0.191761, 0.139733, 0.4, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0898463, 0.387462, 0.648649, 1.0]], # specular [0.924324], # shininess [ 1.0], # opacity ], [ # 8 [[0.0711713, 0.144409, 0.12303, 1.0]], # ambient [[0.371245, 0.753268, 0.641749, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0956359, 0.280612, 0.16999, 1.0]], # specular [0.403061], # shininess [ 1.0], # opacity ], [ # 9 [[0.0, 0.435006, 0.141651, 1.0]], # ambient [[0.0, 0.619048, 0.20158, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0714408, 0.20962, 0.126984, 1.0]], # specular [0.0108108], # shininess [ 1.0], # opacity ], [ # 10 [[0.0, 0.153925, 0.0501226, 1.0]], # ambient [[0.0, 0.538739, 0.175429, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.280892, 0.824187, 0.499277, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 11 [[0.0511345, 0.153925, 0.0846063, 1.0]], # ambient [[0.178971, 0.538739, 0.296122, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.086242, 0.259606, 0.142694, 1.0]], # specular [0.0648649], # shininess [ 1.0], # opacity ], [ # 12 [[0.098983, 0.0565609, 0.0320604, 1.0]], # ambient [[0.395932, 0.226244, 0.128242, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.192616, 0.110064, 0.0623879, 1.0]], # specular [0.027027], # shininess [ 1.0], # opacity ], [ # 13 [[0.0, 0.153925, 0.0892738, 1.0]], # ambient [[0.0, 0.619048, 0.359036, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.259785, 0.762254, 0.461759, 1.0]], # specular [0.827027], # shininess [ 1.0], # opacity ], [ # 14 [[0.259459, 0.251553, 0.0800367, 1.0]], # ambient [[1.0, 0.969526, 0.308475, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.728905, 0.691826, 0.153194, 1.0]], # specular [0.891892], # shininess [ 1.0], # opacity ], [ # 15 [[0.259459, 0.248397, 0.008424, 1.0]], # ambient [[1.0, 0.957367, 0.0324675, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.990909, 0.940502, 0.208259, 1.0]], # specular [0.363636], # shininess [ 1.0], # opacity ], [ # 16 [[0.20255, 0.148406, 0.00214757, 1.0]], # ambient [[0.792195, 0.580431, 0.0083994, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.25, 0.237283, 0.0525425, 1.0]], # specular [0.177273], # shininess [ 1.0], # opacity ], [ # 17 [[0.248649, 0.14376, 0.151864, 1.0]], # ambient [[1.0, 0.578166, 0.610756, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0, 0.0, 1.0]], # specular [0.513514], # shininess [ 1.0], # opacity ], [ # 18 [[0.248649, 0.087328, 0.130646, 1.0]], # ambient [[0.994595, 0.349312, 0.522584, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.718919, 0.23964, 0.370426, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 19 [[0.172973, 0.0607498, 0.0908841, 1.0]], # ambient [[0.697297, 0.244898, 0.366377, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.335135, 0.0306779, 0.0, 1.0]], # specular [0.0594595], # shininess [ 1.0], # opacity ], [ # 20 [[0.936975, 0.0923259, 0.42843, 1.0]], # ambient [[0.536861, 0.0529003, 0.245479, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.805292, 0.765198, 0.747416, 1.0]], # specular [0.832432], # shininess [ 1.0], # opacity ], [ # 21 [[0.102703, 0.0174664, 0.0348145, 1.0]], # ambient [[0.416216, 0.0707851, 0.14109, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.372973, 0.00253723, 0.00126432, 1.0]], # specular [0.0108108], # shininess [ 1.0], # opacity ], [ # 22 [[0.0831403, 0.0, 0.0275034, 1.0]], # ambient [[0.336937, 0.0, 0.111461, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.341055, 0.20592, 0.0, 1.0]], # specular [0.0648649], # shininess [ 1.0], # opacity ], [ # 23 [[0.0544218, 0.0285714, 0.0176271, 1.0]], # ambient [[0.217687, 0.114286, 0.0705085, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.254054, 0.117984, 0.120752, 1.0]], # specular [0.135135], # shininess [ 1.0], # opacity ], [ # 24 [[0.123037, 0.0675867, 0.094362, 1.0]], # ambient [[0.465784, 0.255864, 0.357227, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.178011, 0.093326, 0.161906, 1.0]], # specular [0.0540541], # shininess [ 1.0], # opacity ], [ # 25 [[0.123037, 0.0675867, 0.094362, 1.0]], # ambient [[0.465784, 0.255864, 0.357227, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.805405, 0.805405, 0.805405, 1.0]], # specular [0.751351], # shininess [ 1.0], # opacity ], [ # 26 [[0.0608964, 0.0023948, 0.00238474, 1.0]], # ambient [[0.228214, 0.00897471, 0.008937, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.237838, 0.0, 0.101038, 1.0]], # specular [0.113514], # shininess [ 1.0], # opacity ], [ # 27 [[0.0810811, 0.0, 0.0354558, 1.0]], # ambient [[0.303858, 0.0, 0.132874, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.340541, 0.0, 0.144668, 1.0]], # specular [0.0486486], # shininess [ 1.0], # opacity ], [ # 28 [[0.0301158, 0.000642761, 0.0290243, 1.0]], # ambient [[0.12381, 0.00264246, 0.119322, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.151866, 0.0223515, 0.156482, 1.0]], # specular [0.0648649], # shininess [ 1.0], # opacity ], [ # 29 [[0.0544218, 0.0285714, 0.0176271, 1.0]], # ambient [[0.217687, 0.114286, 0.0705085, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 0.464407, 0.4753, 1.0]], # specular [0.994595], # shininess [ 1.0], # opacity ], [ # 30 [[0.0171929, 0.0239493, 0.0293175, 1.0]], # ambient [[0.0808068, 0.112562, 0.137792, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.127228, 0.177225, 0.216949, 1.0]], # specular [0.0486486], # shininess [ 1.0], # opacity ], [ # 31 [[0.0055341, 0.0040326, 0.0115437, 1.0]], # ambient [[0.0227513, 0.0165785, 0.0474576, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.271499, 0.302282, 0.351351, 1.0]], # specular [0.135135], # shininess [ 1.0], # opacity ], [ # 32 [[0.000256616, 0.00161334, 0.00586349, 1.0]], # ambient [[0.00128308, 0.00806671, 0.0293175, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.135714, 0.151102, 0.17563, 1.0]], # specular [0.027027], # shininess [ 1.0], # opacity ], [ # 33 [[0.0790876, 0.110167, 0.13486, 1.0]], # ambient [[0.288842, 0.402349, 0.492533, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.288842, 0.402349, 0.492533, 1.0]], # specular [0.962162], # shininess [ 1.0], # opacity ], [ # 34 [[0.105523, 0.169052, 0.191584, 1.0]], # ambient [[0.406702, 0.651555, 0.738397, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0650855, 0.0810811, 0.0810811, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/silky.py0000644000175000017500000002475607354231036024013 0ustar debiandebian# material definition table: silky # silky = [\ [ # 0 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0347538, 0.0335554, 0.693878, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 1 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.425195, 0.0335554, 0.693878, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 2 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.964441, 0.641609, 0.979592, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 3 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.979592, 0.641609, 0.798946, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 4 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.979592, 0.641609, 0.641609, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 5 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.979592, 0.805939, 0.641609, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 6 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.946959, 0.979592, 0.641609, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 7 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.641609, 0.979592, 0.657925, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 8 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.641609, 0.976208, 0.979592, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 9 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.641609, 0.748831, 0.979592, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 10 [[0.0329288, 0.0335907, 0.0445259, 1.0]], # ambient [[0.135374, 0.138095, 0.183051, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.362217, 0.369498, 0.489785, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 11 [[0.0697433, 0.0215254, 0.070936, 1.0]], # ambient [[0.280113, 0.0864535, 0.284904, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.588517, 0.248038, 0.596939, 1.0]], # specular [0.0204082], # shininess [ 1.0], # opacity ], [ # 12 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.693878, 0.0335554, 0.313623, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 13 [[0.070936, 0.0215254, 0.0470826, 1.0]], # ambient [[0.284904, 0.0864535, 0.1891, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.765306, 0.33779, 0.572187, 1.0]], # specular [0.0408163], # shininess [ 1.0], # opacity ], [ # 14 [[0.070936, 0.0, 0.0, 1.0]], # ambient [[0.284904, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.831633, 0.403851, 0.367065, 1.0]], # specular [0.0408163], # shininess [ 1.0], # opacity ], [ # 15 [[0.0714286, 0.0301012, 0.0, 1.0]], # ambient [[0.286882, 0.120897, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.831633, 0.482277, 0.317353, 1.0]], # specular [0.0408163], # shininess [ 1.0], # opacity ], [ # 16 [[0.0714286, 0.0682211, 0.0, 1.0]], # ambient [[0.286882, 0.274, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.631735, 0.600752, 0.241071, 1.0]], # specular [0.0408163], # shininess [ 1.0], # opacity ], [ # 17 [[0.0, 0.0714286, 0.0150246, 1.0]], # ambient [[0.0, 0.286882, 0.0603441, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.428943, 0.632653, 0.241422, 1.0]], # specular [0.0255102], # shininess [ 1.0], # opacity ], [ # 18 [[0.0, 0.0714286, 0.0652005, 1.0]], # ambient [[0.0, 0.286882, 0.261868, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.243549, 0.556863, 0.607143, 1.0]], # specular [0.0663265], # shininess [ 1.0], # opacity ], [ # 19 [[0.00176873, 0.0335907, 0.0445259, 1.0]], # ambient [[0.00727146, 0.138095, 0.183051, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.362217, 0.369498, 0.489785, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 20 [[0.0519579, 0.0631746, 0.081228, 1.0]], # ambient [[0.211415, 0.257055, 0.330514, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.183673, 0.165545, 0.163419, 1.0]], # specular [0.0255102], # shininess [ 1.0], # opacity ], [ # 21 [[0.0826531, 0.0609662, 0.0681122, 1.0]], # ambient [[0.336312, 0.24807, 0.277146, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.221121, 0.199297, 0.196736, 1.0]], # specular [0.0357143], # shininess [ 1.0], # opacity ], [ # 22 [[0.081228, 0.0634641, 0.0519579, 1.0]], # ambient [[0.330514, 0.258233, 0.211415, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.183673, 0.165545, 0.163419, 1.0]], # specular [0.0255102], # shininess [ 1.0], # opacity ], [ # 23 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.693878, 0.0335554, 0.0335554, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 24 [[0.0826531, 0.0609662, 0.04943, 1.0]], # ambient [[0.336312, 0.24807, 0.201129, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.108805, 0.0980667, 0.0968068, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 25 [[0.0656656, 0.0518188, 0.0228008, 1.0]], # ambient [[0.267191, 0.210849, 0.0927759, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.183673, 0.165545, 0.163419, 1.0]], # specular [0.0255102], # shininess [ 1.0], # opacity ], [ # 26 [[0.144808, 0.142894, 0.120918, 1.0]], # ambient [[0.589217, 0.581431, 0.492013, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0, 0.0, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 27 [[0.0699071, 0.0689834, 0.0583744, 1.0]], # ambient [[0.280771, 0.277061, 0.234452, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.22814, 0.205624, 0.202982, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 28 [[0.071021, 0.0811225, 0.0424735, 1.0]], # ambient [[0.288982, 0.330084, 0.172823, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.108805, 0.0980667, 0.0968068, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 29 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.693878, 0.29313, 0.0335554, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 30 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.535714, 0.500555, 0.0259067, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 31 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.182327, 0.540816, 0.0261535, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 32 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0261535, 0.540816, 0.439658, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 33 [[0.171143, 0.170799, 0.171534, 1.0]], # ambient [[0.684572, 0.683198, 0.686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0261535, 0.242667, 0.540816, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 34 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.670745, 0.641609, 0.979592, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/metal.py0000644000175000017500000002406507354231036023753 0ustar debiandebian# material definition table: metal # metal = [\ [ # 0 [[0.00714286, 0.00495707, 0.0, 1.0]], # ambient [[0.314286, 0.218111, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 0.887979, 0.0, 1.0]], # specular [0.660606], # shininess [ 1.0], # opacity ], [ # 1 [[0.00714286, 0.00495707, 0.0, 1.0]], # ambient [[0.314286, 0.218111, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.729592, 0.647862, 0.0, 1.0]], # specular [0.132653], # shininess [ 1.0], # opacity ], [ # 2 [[0.00714286, 0.00169011, 0.0, 1.0]], # ambient [[0.314286, 0.0743647, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.760204, 0.582954, 0.0, 1.0]], # specular [0.0408163], # shininess [ 1.0], # opacity ], [ # 3 [[0.00714286, 0.00169011, 0.0, 1.0]], # ambient [[0.314286, 0.0743647, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.780612, 0.691177, 0.397036, 1.0]], # specular [0.107143], # shininess [ 1.0], # opacity ], [ # 4 [[0.0570021, 0.0395589, 0.0, 1.0]], # ambient [[0.222308, 0.15428, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.714286, 0.696627, 0.55665, 1.0]], # specular [0.163265], # shininess [ 1.0], # opacity ], [ # 5 [[0.0570021, 0.0395589, 0.0, 1.0]], # ambient [[0.222308, 0.15428, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.882653, 0.860832, 0.687861, 1.0]], # specular [0.204082], # shininess [ 1.0], # opacity ], [ # 6 [[0.0787879, 0.0186424, 0.0, 1.0]], # ambient [[0.315152, 0.0745695, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.508861, 0.684007, 0.326263, 1.0]], # specular [0.0363636], # shininess [ 1.0], # opacity ], [ # 7 [[0.0961806, 0.0667484, 0.0, 1.0]], # ambient [[0.384722, 0.266993, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.757576, 0.738847, 0.590386, 1.0]], # specular [0.0666667], # shininess [ 1.0], # opacity ], [ # 8 [[0.0570021, 0.0395589, 0.0, 1.0]], # ambient [[0.222308, 0.15428, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.678571, 0.661796, 0.528818, 1.0]], # specular [0.0204082], # shininess [ 1.0], # opacity ], [ # 9 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.641609, 0.651044, 0.979592, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 10 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 0.991559, 0.963793, 1.0]], # specular [0.557576], # shininess [ 1.0], # opacity ], [ # 11 [[0.020276, 0.0, 0.019898, 1.0]], # ambient [[0.0811039, 0.0, 0.0795918, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.963636, 0.955501, 0.928746, 1.0]], # specular [0.654545], # shininess [ 1.0], # opacity ], [ # 12 [[0.133333, 0.0925319, 0.0, 1.0]], # ambient [[0.49697, 0.344891, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 0.887978, 0.0, 1.0]], # specular [0.927273], # shininess [ 1.0], # opacity ], [ # 13 [[0.0, 0.0, 0.0106351, 1.0]], # ambient [[0.0, 0.0, 0.0425405, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.632653, 0.627312, 0.609747, 1.0]], # specular [0.102041], # shininess [ 1.0], # opacity ], [ # 14 [[0.0, 0.0, 0.0106351, 1.0]], # ambient [[0.0, 0.0, 0.0425405, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.632653, 0.627312, 0.609747, 1.0]], # specular [0.0561224], # shininess [ 1.0], # opacity ], [ # 15 [[0.0, 0.0, 0.0106351, 1.0]], # ambient [[0.0, 0.0, 0.0425405, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.821429, 0.814494, 0.791687, 1.0]], # specular [0.0561224], # shininess [ 1.0], # opacity ], [ # 16 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.918367, 0.910614, 0.885116, 1.0]], # specular [0.0561224], # shininess [ 1.0], # opacity ], [ # 17 [[0.0397589, 0.038631, 0.0388459, 1.0]], # ambient [[0.155308, 0.150902, 0.151742, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.528268, 0.524391, 0.524455, 1.0]], # specular [0.102041], # shininess [ 1.0], # opacity ], [ # 18 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.44898, 0.445189, 0.432723, 1.0]], # specular [0.0561224], # shininess [ 1.0], # opacity ], [ # 19 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.780612, 0.774022, 0.752349, 1.0]], # specular [0.102041], # shininess [ 1.0], # opacity ], [ # 20 [[0.703925, 0.721552, 0.721554, 1.0]], # ambient [[0.557827, 0.571796, 0.571797, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.708205, 0.480594, 0.458724, 1.0]], # specular [0.236364], # shininess [ 1.0], # opacity ], [ # 21 [[0.860488, 0.860488, 0.9, 1.0]], # ambient [[0.412673, 0.455048, 0.472727, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.420602, 0.431402, 0.454545, 1.0]], # specular [0.127273], # shininess [ 1.0], # opacity ], [ # 22 [[0.132816, 0.136142, 0.136142, 1.0]], # ambient [[0.566681, 0.580872, 0.580874, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.673937, 0.45734, 0.436528, 1.0]], # specular [0.168182], # shininess [ 1.0], # opacity ], [ # 23 [[0.00714286, 0.00495707, 0.0, 1.0]], # ambient [[0.314286, 0.218111, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.540816, 0.480233, 0.0, 1.0]], # specular [0.0306122], # shininess [ 1.0], # opacity ], [ # 24 [[0.0953144, 0.095123, 0.0955322, 1.0]], # ambient [[0.372322, 0.371574, 0.373173, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.890909, 0.887832, 0.890909, 1.0]], # specular [0.127551], # shininess [ 1.0], # opacity ], [ # 25 [[0.0953144, 0.095123, 0.0955322, 1.0]], # ambient [[0.372322, 0.371574, 0.373173, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.556122, 0.554201, 0.556122, 1.0]], # specular [0.127551], # shininess [ 1.0], # opacity ], [ # 26 [[0.0789891, 0.0788305, 0.0791696, 1.0]], # ambient [[0.697737, 0.696336, 0.699331, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.227785, 0.227345, 0.227393, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 27 [[0.25, 0.25, 0.25, 1.0]], # ambient [[0.4, 0.4, 0.4, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.774597, 0.774597, 0.774597, 1.0]], # specular [0.6], # shininess [ 1.0], # opacity ], [ # 28 [[0.23125, 0.23125, 0.23125, 1.0]], # ambient [[0.2775, 0.2775, 0.2775, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.773911, 0.773911, 0.773911, 1.0]], # specular [0.7], # shininess [ 1.0], # opacity ], [ # 29 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.938776, 0.0550317, 0.0550317, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 30 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.641609, 0.976208, 0.979592, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 31 [[0.00714286, 0.00169011, 0.0, 1.0]], # ambient [[0.314286, 0.0743647, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.780612, 0.691177, 0.397036, 1.0]], # specular [0.357143], # shininess [ 1.0], # opacity ], [ # 32 [[0.109091, 0.0258126, 0.0, 1.0]], # ambient [[0.454545, 0.107552, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.951515, 0.729659, 0.0, 1.0]], # specular [0.927273], # shininess [ 1.0], # opacity ], [ # 33 [[0.00714286, 0.00169011, 0.0, 1.0]], # ambient [[0.314286, 0.0743647, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.780612, 0.598604, 0.0, 1.0]], # specular [0.107143], # shininess [ 1.0], # opacity ], [ # 34 [[0.00714286, 0.00169011, 0.0, 1.0]], # ambient [[0.314286, 0.0743647, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 0.766841, 0.0, 1.0]], # specular [0.0484848], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/glass.py0000644000175000017500000002573007354231035023761 0ustar debiandebian# material definition table: glass # glass = [\ [ # 0 [[0.187004, 0.155212, 0.0, 0.65251]], # ambient [[0.748014, 0.62085, 0.0, 0.65251]], # diffuse [[0.0, 0.0, 0.0, 0.65251]], # emission [[0.860606, 0.860606, 0.860599, 0.65251]], # specular [0.939394], # shininess [ 0.65251], # opacity ], [ # 1 [[0.187004, 0.13893, 0.0, 0.648649]], # ambient [[0.748016, 0.555721, 0.0, 0.648649]], # diffuse [[0.0, 0.0, 0.0, 0.648649]], # emission [[0.836364, 0.836364, 0.836364, 0.648649]], # specular [0.606061], # shininess [ 0.648649], # opacity ], [ # 2 [[0.00746438, 0.00673081, 0.00690282, 0.594595]], # ambient [[0.0291577, 0.0262922, 0.0269642, 0.594595]], # diffuse [[0.0, 0.0, 0.0, 0.594595]], # emission [[0.641609, 0.0, 0.979592, 0.594595]], # specular [0.0612245], # shininess [ 0.594595], # opacity ], [ # 3 [[0.000579251, 0.0, 0.187004, 0.65251]], # ambient [[0.002317, 0.0, 0.748016, 0.65251]], # diffuse [[0.0, 0.0, 0.0, 0.65251]], # emission [[0.884848, 0.884848, 0.884848, 0.65251]], # specular [0.830303], # shininess [ 0.65251], # opacity ], [ # 4 [[0.00518309, 0.0849113, 0.187004, 0.637066]], # ambient [[0.0207323, 0.339645, 0.748016, 0.637066]], # diffuse [[0.0, 0.0, 0.0, 0.637066]], # emission [[0.90303, 0.90303, 0.90303, 0.637066]], # specular [0.927273], # shininess [ 0.637066], # opacity ], [ # 5 [[0.0, 0.157811, 0.187004, 0.610039]], # ambient [[0.0, 0.631244, 0.748016, 0.610039]], # diffuse [[0.0, 0.0, 0.0, 0.610039]], # emission [[0.915152, 0.915152, 0.915152, 0.610039]], # specular [0.642424], # shininess [ 0.610039], # opacity ], [ # 6 [[0.0, 0.0714286, 0.0652005, 0.706564]], # ambient [[0.0, 0.286882, 0.261868, 0.706564]], # diffuse [[0.0, 0.0, 0.0, 0.706564]], # emission [[0.243549, 0.556863, 0.607143, 0.706564]], # specular [0.0663265], # shininess [ 0.706564], # opacity ], [ # 7 [[0.0, 0.187004, 0.117351, 0.598456]], # ambient [[0.0, 0.748016, 0.469403, 0.598456]], # diffuse [[0.0, 0.0, 0.0, 0.598456]], # emission [[1.0, 1.0, 1.0, 0.598456]], # specular [0.818182], # shininess [ 0.598456], # opacity ], [ # 8 [[0.0, 0.187004, 0.0440039, 0.644788]], # ambient [[0.0, 0.748016, 0.176015, 0.644788]], # diffuse [[0.0, 0.0, 0.0, 0.644788]], # emission [[0.981818, 0.981818, 0.981818, 0.644788]], # specular [0.721212], # shininess [ 0.644788], # opacity ], [ # 9 [[0.0954861, 0.187004, 0.0, 0.629344]], # ambient [[0.381944, 0.748016, 0.0, 0.629344]], # diffuse [[0.0, 0.0, 0.0, 0.629344]], # emission [[0.963636, 0.963636, 0.963636, 0.629344]], # specular [0.981818], # shininess [ 0.629344], # opacity ], [ # 10 [[0.860488, 0.860488, 0.9, 0.756757]], # ambient [[0.400769, 0.441922, 0.459091, 0.756757]], # diffuse [[0.0, 0.0, 0.0, 0.756757]], # emission [[0.814672, 0.354965, 0.310792, 0.756757]], # specular [0.127273], # shininess [ 0.756757], # opacity ], [ # 11 [[0.860488, 0.860488, 0.9, 0.810811]], # ambient [[0.400769, 0.441922, 0.459091, 0.810811]], # diffuse [[0.0, 0.0, 0.0, 0.810811]], # emission [[0.573887, 0.649271, 0.810811, 0.810811]], # specular [0.127273], # shininess [ 0.810811], # opacity ], [ # 12 [[0.187004, 0.0748842, 0.0, 0.65251]], # ambient [[0.748016, 0.299537, 0.0, 0.65251]], # diffuse [[0.0, 0.0, 0.0, 0.65251]], # emission [[0.836364, 0.836364, 0.836364, 0.65251]], # specular [0.921212], # shininess [ 0.65251], # opacity ], [ # 13 [[0.703925, 0.721552, 0.721554, 0.783784]], # ambient [[0.481983, 0.481084, 0.552124, 0.783784]], # diffuse [[0.0, 0.0, 0.0, 0.783784]], # emission [[0.833977, 0.565944, 0.54019, 0.783784]], # specular [0.236364], # shininess [ 0.783784], # opacity ], [ # 14 [[0.567604, 0.581818, 0.581818, 0.648649]], # ambient [[0.566681, 0.580872, 0.580874, 0.648649]], # diffuse [[0.0, 0.0, 0.0, 0.648649]], # emission [[0.673937, 0.45734, 0.436528, 0.648649]], # specular [0.168182], # shininess [ 0.648649], # opacity ], [ # 15 [[0.812683, 0.812683, 0.85, 0.783784]], # ambient [[0.2606, 0.28736, 0.298524, 0.783784]], # diffuse [[0.0, 0.0, 0.0, 0.783784]], # emission [[0.420602, 0.431402, 0.454545, 0.783784]], # specular [0.0454545], # shininess [ 0.783784], # opacity ], [ # 16 [[0.860488, 0.860488, 0.9, 0.791506]], # ambient [[0.400769, 0.441922, 0.459091, 0.791506]], # diffuse [[0.0, 0.0, 0.0, 0.791506]], # emission [[0.420602, 0.431402, 0.454545, 0.791506]], # specular [0.127273], # shininess [ 0.791506], # opacity ], [ # 17 [[0.123725, 0.123947, 0.129723, 0.714286]], # ambient [[0.527894, 0.52884, 0.553483, 0.714286]], # diffuse [[0.0, 0.0, 0.0, 0.714286]], # emission [[0.757704, 0.527183, 0.490785, 0.714286]], # specular [0.854545], # shininess [ 0.714286], # opacity ], [ # 18 [[0.0953144, 0.095123, 0.0955322, 0.69112]], # ambient [[0.372322, 0.371574, 0.373173, 0.69112]], # diffuse [[0.0, 0.0, 0.0, 0.69112]], # emission [[0.890909, 0.887832, 0.890909, 0.69112]], # specular [0.127551], # shininess [ 0.69112], # opacity ], [ # 19 [[0.12677, 0.126534, 0.145218, 0.714286]], # ambient [[0.526888, 0.525905, 0.603564, 0.714286]], # diffuse [[0.0, 0.0, 0.0, 0.714286]], # emission [[0.651092, 0.441837, 0.42173, 0.714286]], # specular [0.636364], # shininess [ 0.714286], # opacity ], [ # 20 [[0.812683, 0.812683, 0.85, 0.72973]], # ambient [[0.2606, 0.28736, 0.298524, 0.72973]], # diffuse [[0.0, 0.0, 0.0, 0.72973]], # emission [[0.671665, 0.688911, 0.725869, 0.72973]], # specular [0.127273], # shininess [ 0.72973], # opacity ], [ # 21 [[0.132816, 0.136142, 0.136142, 0.803089]], # ambient [[0.566681, 0.580872, 0.580874, 0.803089]], # diffuse [[0.0, 0.0, 0.0, 0.803089]], # emission [[0.610215, 0.7546, 0.942085, 0.803089]], # specular [0.168182], # shininess [ 0.803089], # opacity ], [ # 22 [[0.132816, 0.136142, 0.136142, 0.764479]], # ambient [[0.566681, 0.580872, 0.580874, 0.764479]], # diffuse [[0.0, 0.0, 0.0, 0.764479]], # emission [[0.617761, 0.429816, 0.40014, 0.764479]], # specular [0.0727273], # shininess [ 0.764479], # opacity ], [ # 23 [[0.187004, 0.0348922, 0.0, 0.41]], # ambient [[0.748016, 0.139569, 0.0, 0.41]], # diffuse [[0.0, 0.0, 0.0, 0.41]], # emission [[0.709091, 0.709091, 0.709091, 0.41]], # specular [0.478788], # shininess [ 0.41], # opacity ], [ # 24 [[0.106059, 0.106059, 0.106059, 0.745174]], # ambient [[0.424238, 0.424238, 0.424238, 0.745174]], # diffuse [[0.0, 0.0, 0.0, 0.745174]], # emission [[0.168, 0.168, 0.168, 0.745174]], # specular [0.153696], # shininess [ 0.745174], # opacity ], [ # 25 [[0.0380952, 0.0362853, 0.0382051, 0.745174]], # ambient [[0.152381, 0.145141, 0.15282, 0.745174]], # diffuse [[0.0, 0.0, 0.0, 0.745174]], # emission [[0.745455, 0.745455, 0.745455, 0.745174]], # specular [0.957576], # shininess [ 0.745174], # opacity ], [ # 26 [[0.0346667, 0.0346667, 0.0346667, 0.648649]], # ambient [[0.138667, 0.138667, 0.138667, 0.648649]], # diffuse [[0.0, 0.0, 0.0, 0.648649]], # emission [[0.168, 0.168, 0.168, 0.648649]], # specular [0.153696], # shininess [ 0.648649], # opacity ], [ # 27 [[0.0, 0.0, 0.0, 0.764479]], # ambient [[0.0, 0.0, 0.0, 0.764479]], # diffuse [[0.0, 0.0, 0.0, 0.764479]], # emission [[0.918367, 0.910614, 0.885116, 0.764479]], # specular [0.0561224], # shininess [ 0.764479], # opacity ], [ # 28 [[0.0, 0.0, 0.0, 0.745174]], # ambient [[0.0, 0.0, 0.0, 0.745174]], # diffuse [[0.0, 0.0, 0.0, 0.745174]], # emission [[1.0, 0.991559, 0.963793, 0.745174]], # specular [0.557576], # shininess [ 0.745174], # opacity ], [ # 29 [[0.187004, 0.0, 0.0100218, 0.640927]], # ambient [[0.748016, 0.0, 0.0400871, 0.640927]], # diffuse [[0.0, 0.0, 0.0, 0.640927]], # emission [[0.89697, 0.89697, 0.89697, 0.640927]], # specular [1.0], # shininess [ 0.640927], # opacity ], [ # 30 [[0.00746438, 0.00673081, 0.00690282, 0.610039]], # ambient [[0.0291577, 0.0262922, 0.0269642, 0.610039]], # diffuse [[0.0, 0.0, 0.0, 0.610039]], # emission [[0.981818, 0.0, 0.0, 0.610039]], # specular [0.030303], # shininess [ 0.610039], # opacity ], [ # 31 [[0.187004, 0.00156472, 0.0629827, 0.644788]], # ambient [[0.748016, 0.00625887, 0.251931, 0.644788]], # diffuse [[0.0, 0.0, 0.0, 0.644788]], # emission [[0.684848, 0.684848, 0.684848, 0.644788]], # specular [0.933333], # shininess [ 0.644788], # opacity ], [ # 32 [[0.187004, 0.0, 0.137588, 0.648649]], # ambient [[0.748016, 0.0, 0.550351, 0.648649]], # diffuse [[0.0, 0.0, 0.0, 0.648649]], # emission [[0.672727, 0.672727, 0.672727, 0.648649]], # specular [0.230303], # shininess [ 0.648649], # opacity ], [ # 33 [[0.156092, 0.0, 0.187004, 0.644788]], # ambient [[0.624368, 0.0, 0.748016, 0.644788]], # diffuse [[0.0, 0.0, 0.0, 0.644788]], # emission [[0.951515, 0.951515, 0.951515, 0.644788]], # specular [0.557576], # shininess [ 0.644788], # opacity ], [ # 34 [[0.093502, 0.0, 0.187004, 0.644788]], # ambient [[0.374008, 0.0, 0.748016, 0.644788]], # diffuse [[0.0, 0.0, 0.0, 0.644788]], # emission [[0.909091, 0.909091, 0.909091, 0.644788]], # specular [0.406061], # shininess [ 0.644788], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/winter.py0000644000175000017500000002414707354231037024163 0ustar debiandebian# material definition table: winter # winter = [\ [ # 0 [[0.245289, 0.248649, 0.248649, 1.0]], # ambient [[0.986486, 1.0, 1.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.405259, 0.410811, 0.410811, 1.0]], # specular [0.524324], # shininess [ 1.0], # opacity ], [ # 1 [[0.140541, 0.140541, 0.140541, 1.0]], # ambient [[0.610811, 0.610811, 0.610811, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.767568, 0.756757, 0.764964, 1.0]], # specular [0.897297], # shininess [ 1.0], # opacity ], [ # 2 [[0.0, 0.0786092, 0.0, 1.0]], # ambient [[0.0, 0.309524, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.071925, 0.677294, 0.0, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 3 [[0.14724, 0.253968, 0.120473, 1.0]], # ambient [[0.0, 0.488636, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0, 0.0, 1.0]], # specular [0.0], # shininess [ 1.0], # opacity ], [ # 4 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.071925, 0.356628, 0.0, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 5 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0816327, 0.404762, 0.0, 1.0]], # specular [0.789189], # shininess [ 1.0], # opacity ], [ # 6 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.356628, 0.356628, 0.356628, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 7 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.87027, 0.458816, 0.87027, 1.0]], # specular [0.724324], # shininess [ 1.0], # opacity ], [ # 8 [[0.0144823, 0.0170597, 0.0514007, 1.0]], # ambient [[0.0595385, 0.0701343, 0.211314, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0845487, 0.0995954, 0.111647, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 9 [[0.0205217, 0.0168695, 0.0864583, 1.0]], # ambient [[0.0827088, 0.0679893, 0.348453, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.656314, 0.773115, 0.866667, 1.0]], # specular [0.684848], # shininess [ 1.0], # opacity ], [ # 10 [[0.11141, 0.127535, 0.212121, 1.0]], # ambient [[0.442456, 0.506497, 0.842424, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.405259, 0.410811, 0.410811, 1.0]], # specular [0.524324], # shininess [ 1.0], # opacity ], [ # 11 [[0.0601497, 0.105048, 0.212121, 1.0]], # ambient [[0.23888, 0.41719, 0.842424, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.405259, 0.410811, 0.410811, 1.0]], # specular [0.524324], # shininess [ 1.0], # opacity ], [ # 12 [[0.0486486, 0.0486486, 0.0486486, 1.0]], # ambient [[0.205405, 0.205405, 0.205405, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.686486, 0.676818, 0.684159, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 13 [[0.108581, 0.173951, 0.197136, 1.0]], # ambient [[0.434323, 0.695804, 0.788544, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0616885, 0.0988278, 0.112, 1.0]], # specular [0.094483], # shininess [ 1.0], # opacity ], [ # 14 [[0.00377976, 0.0829494, 0.0997833, 1.0]], # ambient [[0.015119, 0.331798, 0.399133, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0170845, 0.374932, 0.451021, 1.0]], # specular [0.772973], # shininess [ 1.0], # opacity ], [ # 15 [[0.00377976, 0.0829494, 0.0997833, 1.0]], # ambient [[0.015119, 0.331798, 0.399133, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.00438452, 0.0962214, 0.115749, 1.0]], # specular [0.0972973], # shininess [ 1.0], # opacity ], [ # 16 [[0.0074806, 0.0954792, 0.126768, 1.0]], # ambient [[0.0308575, 0.393852, 0.522917, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0137744, 0.302289, 0.363636, 1.0]], # specular [0.0972973], # shininess [ 1.0], # opacity ], [ # 17 [[0.241883, 0.153925, 0.175318, 1.0]], # ambient [[0.972789, 0.619048, 0.705085, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.610811, 0.35315, 0.373056, 1.0]], # specular [0.832432], # shininess [ 1.0], # opacity ], [ # 18 [[0.232978, 0.0229567, 0.106528, 1.0]], # ambient [[0.936975, 0.0923259, 0.42843, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.805292, 0.216986, 0.36733, 1.0]], # specular [0.832432], # shininess [ 1.0], # opacity ], [ # 19 [[0.187593, 0.0234558, 0.091801, 1.0]], # ambient [[0.738397, 0.0923259, 0.361345, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.526732, 0.141928, 0.240266, 1.0]], # specular [0.151351], # shininess [ 1.0], # opacity ], [ # 20 [[0.0615003, 0.0284765, 0.0761043, 1.0]], # ambient [[0.230477, 0.106718, 0.285207, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.551351, 0.0, 0.234225, 1.0]], # specular [0.0540541], # shininess [ 1.0], # opacity ], [ # 21 [[0.0615003, 0.0284765, 0.0761043, 1.0]], # ambient [[0.230477, 0.106718, 0.285207, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.848649, 0.0, 0.360523, 1.0]], # specular [0.740541], # shininess [ 1.0], # opacity ], [ # 22 [[0.0655221, 0.0303387, 0.0810811, 1.0]], # ambient [[0.244615, 0.113264, 0.302703, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.690166, 0.319568, 0.854054, 1.0]], # specular [0.659459], # shininess [ 1.0], # opacity ], [ # 23 [[0.0610795, 0.066508, 0.0909091, 1.0]], # ambient [[0.240246, 0.261598, 0.357576, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.220301, 0.259507, 0.290909, 1.0]], # specular [0.0727273], # shininess [ 1.0], # opacity ], [ # 24 [[0.0655221, 0.0303387, 0.0810811, 1.0]], # ambient [[0.244615, 0.113264, 0.302703, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.253352, 0.11731, 0.313514, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 25 [[0.0761043, 0.0, 0.0, 1.0]], # ambient [[0.285207, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.110903, 0.0, 0.337957, 1.0]], # specular [0.0972973], # shininess [ 1.0], # opacity ], [ # 26 [[0.0761043, 0.0, 0.0, 1.0]], # ambient [[0.285207, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.150101, 0.0, 0.457407, 1.0]], # specular [0.740541], # shininess [ 1.0], # opacity ], [ # 27 [[0.135135, 0.0, 0.0, 1.0]], # ambient [[0.540541, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0920022, 0.0, 0.0201191, 1.0]], # specular [0.0648649], # shininess [ 1.0], # opacity ], [ # 28 [[0.135135, 0.0, 0.0, 1.0]], # ambient [[0.540541, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.577569, 0.0, 0.126303, 1.0]], # specular [0.772973], # shininess [ 1.0], # opacity ], [ # 29 [[0.0359235, 0.0369933, 0.0418019, 1.0]], # ambient [[0.141299, 0.145507, 0.164421, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.394707, 0.464951, 0.521212, 1.0]], # specular [0.0727273], # shininess [ 1.0], # opacity ], [ # 30 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.293243, 0.297387, 0.290421, 1.0]], # specular [0.0816327], # shininess [ 1.0], # opacity ], [ # 31 [[0.897959, 0.830331, 0.326872, 1.0]], # ambient [[0.331633, 0.296582, 0.279057, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.311224, 0.25183, 0.133042, 1.0]], # specular [0.0969388], # shininess [ 1.0], # opacity ], [ # 32 [[0.253968, 0.253968, 0.120473, 1.0]], # ambient [[1.0, 1.0, 0.474361, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0, 0.0, 1.0]], # specular [0.0378378], # shininess [ 1.0], # opacity ], [ # 33 [[0.253968, 0.253968, 0.0, 1.0]], # ambient [[1.0, 1.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.899871, 0.893105, 0.896821, 1.0]], # specular [0.681081], # shininess [ 1.0], # opacity ], [ # 34 [[0.14724, 0.253968, 0.120473, 1.0]], # ambient [[0.579759, 1.0, 0.474361, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.809524, 0.0, 1.0, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/artdeco.py0000644000175000017500000002447007354231035024271 0ustar debiandebian# material definition table: artdeco # artdeco = [\ [ # 0 [[0.0706087, 0.0212897, 0.0336154, 1.0]], # ambient [[0.282435, 0.0851587, 0.134462, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.276305, 0.11431, 0.139857, 1.0]], # specular [0.127273], # shininess [ 1.0], # opacity ], [ # 1 [[0.174575, 0.0343131, 0.084684, 1.0]], # ambient [[0.685208, 0.134679, 0.332385, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.122449, 0.0500352, 0.0500352, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 2 [[0.073697, 0.0218788, 0.0502702, 1.0]], # ambient [[0.304, 0.09025, 0.207364, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.6665, 0.579046, 0.830303, 1.0]], # specular [0.0727273], # shininess [ 1.0], # opacity ], [ # 3 [[0.0869044, 0.0537721, 0.0617037, 1.0]], # ambient [[0.335631, 0.207672, 0.238304, 1.0]], # diffuse [[0.0106383, 0.0106383, 0.0106383, 1.0]], # emission [[0.198631, 0.0754031, 0.138803, 1.0]], # specular [0.0212766], # shininess [ 1.0], # opacity ], [ # 4 [[0.211184, 0.0354392, 0.00206169, 1.0]], # ambient [[0.876873, 0.14715, 0.00856049, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.193878, 0.0294159, 0.0294159, 1.0]], # specular [0.0765306], # shininess [ 1.0], # opacity ], [ # 5 [[0.198611, 0.0623562, 0.0, 1.0]], # ambient [[0.794445, 0.249425, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.62904, 0.194211, 0.0336632, 1.0]], # specular [0.551515], # shininess [ 1.0], # opacity ], [ # 6 [[0.127652, 0.0431599, 0.0149679, 1.0]], # ambient [[0.510609, 0.17264, 0.0598717, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.533333, 0.533333, 0.533333, 1.0]], # specular [0.933333], # shininess [ 1.0], # opacity ], [ # 7 [[0.234043, 0.113685, 0.089257, 1.0]], # ambient [[0.914894, 0.444404, 0.348914, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.345745, 0.143066, 0.0, 1.0]], # specular [0.12766], # shininess [ 1.0], # opacity ], [ # 8 [[0.211184, 0.0778259, 0.0480626, 1.0]], # ambient [[0.876873, 0.323147, 0.199564, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.816327, 0.278677, 0.278677, 1.0]], # specular [0.80102], # shininess [ 1.0], # opacity ], [ # 9 [[0.125, 0.0764838, 0.0611979, 1.0]], # ambient [[0.515625, 0.315496, 0.252441, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.533333, 0.533333, 0.533333, 1.0]], # specular [0.933333], # shininess [ 1.0], # opacity ], [ # 10 [[0.0, 0.0918367, 0.0671358, 1.0]], # ambient [[0.0, 0.346939, 0.253624, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.311074, 0.357143, 1.0]], # specular [0.316327], # shininess [ 1.0], # opacity ], [ # 11 [[0.0, 0.0650751, 0.0620272, 1.0]], # ambient [[0.0, 0.251004, 0.239248, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.177935, 0.249369, 0.229278, 1.0]], # specular [0.0606061], # shininess [ 1.0], # opacity ], [ # 12 [[0.936975, 0.0923259, 0.42843, 1.0]], # ambient [[0.536861, 0.0529003, 0.245479, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.805292, 0.765198, 0.747416, 1.0]], # specular [0.832432], # shininess [ 1.0], # opacity ], [ # 13 [[0.0547916, 0.092585, 0.0448306, 1.0]], # ambient [[0.228298, 0.385771, 0.186794, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.200464, 0.300145, 0.293518, 1.0]], # specular [0.393939], # shininess [ 1.0], # opacity ], [ # 14 [[0.0788472, 0.136, 0.0645131, 1.0]], # ambient [[0.315389, 0.544, 0.258052, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.456, 0.456, 0.456, 1.0]], # specular [0.509389], # shininess [ 1.0], # opacity ], [ # 15 [[0.0617796, 0.0769001, 0.0496305, 1.0]], # ambient [[0.251104, 0.312562, 0.201724, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.209184, 0.113842, 0.111328, 1.0]], # specular [0.0867347], # shininess [ 1.0], # opacity ], [ # 16 [[0.0951146, 0.110545, 0.101263, 1.0]], # ambient [[0.392348, 0.456, 0.417708, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.533333, 0.533333, 0.533333, 1.0]], # specular [0.933333], # shininess [ 1.0], # opacity ], [ # 17 [[0.253968, 0.217123, 0.0, 1.0]], # ambient [[1.0, 0.854922, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.872449, 0.247119, 0.254214, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 18 [[0.204082, 0.12971, 0.0239268, 1.0]], # ambient [[0.795918, 0.505869, 0.0933146, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.923469, 0.428866, 0.00636875, 1.0]], # specular [0.397959], # shininess [ 1.0], # opacity ], [ # 19 [[0.897959, 0.830331, 0.326872, 1.0]], # ambient [[0.331633, 0.296582, 0.279057, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.311224, 0.25183, 0.133042, 1.0]], # specular [0.0969388], # shininess [ 1.0], # opacity ], [ # 20 [[0.0909091, 0.0429638, 0.0322688, 1.0]], # ambient [[0.345455, 0.163262, 0.122622, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.212121, 0.107475, 0.0, 1.0]], # specular [0.0486486], # shininess [ 1.0], # opacity ], [ # 21 [[0.0666877, 0.0250935, 0.0192164, 1.0]], # ambient [[0.277281, 0.104336, 0.0798996, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.305587, 0.141916, 0.270572, 1.0]], # specular [0.0969697], # shininess [ 1.0], # opacity ], [ # 22 [[0.018772, 0.00558358, 0.0, 1.0]], # ambient [[0.0870338, 0.0258875, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.224138, 0.104091, 0.104091, 1.0]], # specular [0.0459184], # shininess [ 1.0], # opacity ], [ # 23 [[0.248649, 0.112484, 0.100302, 1.0]], # ambient [[1.0, 0.452381, 0.40339, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.686486, 0.396903, 0.419275, 1.0]], # specular [0.902703], # shininess [ 1.0], # opacity ], [ # 24 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.293243, 0.297387, 0.290421, 1.0]], # specular [0.0816327], # shininess [ 1.0], # opacity ], [ # 25 [[0.0606061, 0.0606061, 0.0606061, 1.0]], # ambient [[0.236364, 0.236364, 0.236364, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.29697, 0.245839, 0.295962, 1.0]], # specular [0.0545455], # shininess [ 1.0], # opacity ], [ # 26 [[0.092332, 0.0928379, 0.101263, 1.0]], # ambient [[0.38087, 0.382957, 0.417708, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.533333, 0.533333, 0.533333, 1.0]], # specular [0.933333], # shininess [ 1.0], # opacity ], [ # 27 [[0.140541, 0.140541, 0.140541, 1.0]], # ambient [[0.610811, 0.610811, 0.610811, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.767568, 0.756757, 0.764964, 1.0]], # specular [0.897297], # shininess [ 1.0], # opacity ], [ # 28 [[0.2, 0.2, 0.2, 1.0]], # ambient [[0.8, 0.8, 0.8, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.2, 0.2, 0.2, 1.0]], # specular [0.0], # shininess [ 1.0], # opacity ], [ # 29 [[0.187004, 0.0745904, 0.0856559, 1.0]], # ambient [[0.748016, 0.298362, 0.342624, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.345455, 0.345455, 0.345455, 1.0]], # specular [0.69697], # shininess [ 1.0], # opacity ], [ # 30 [[0.230303, 0.0777022, 0.078367, 1.0]], # ambient [[0.945455, 0.318988, 0.321717, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0727273, 0.0217051, 0.0107323, 1.0]], # specular [0.0181818], # shininess [ 1.0], # opacity ], [ # 31 [[0.0593267, 0.0507277, 0.110396, 1.0]], # ambient [[0.228655, 0.195513, 0.425484, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.324504, 0.404255, 0.404255, 1.0]], # specular [0.542553], # shininess [ 1.0], # opacity ], [ # 32 [[0.0667826, 0.0336191, 0.106944, 1.0]], # ambient [[0.200348, 0.100857, 0.320833, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.311358, 0.387879, 0.387879, 1.0]], # specular [0.133333], # shininess [ 1.0], # opacity ], [ # 33 [[0.0801258, 0.0821575, 0.145455, 1.0]], # ambient [[0.330519, 0.3389, 0.6, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.290909, 0.290909, 0.290909, 1.0]], # specular [0.787879], # shininess [ 1.0], # opacity ], [ # 34 [[0.0790198, 0.0320909, 0.071875, 1.0]], # ambient [[0.237059, 0.0962728, 0.215625, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.311358, 0.387879, 0.387879, 1.0]], # specular [0.133333], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/santafe.py0000644000175000017500000002500107354231036024261 0ustar debiandebian# material definition table: santafe # santafe = [\ [ # 0 [[0.234043, 0.113685, 0.089257, 1.0]], # ambient [[0.914894, 0.444404, 0.348914, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.345745, 0.143066, 0.0, 1.0]], # specular [0.12766], # shininess [ 1.0], # opacity ], [ # 1 [[0.196809, 0.113788, 0.120202, 1.0]], # ambient [[0.803191, 0.464378, 0.490554, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.319149, 0.0813297, 0.0813297, 1.0]], # specular [0.0265957], # shininess [ 1.0], # opacity ], [ # 2 [[0.0593267, 0.0507277, 0.110396, 1.0]], # ambient [[0.228655, 0.195513, 0.425484, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.324504, 0.404255, 0.404255, 1.0]], # specular [0.542553], # shininess [ 1.0], # opacity ], [ # 3 [[0.0132503, 0.0625526, 0.0797636, 1.0]], # ambient [[0.0510601, 0.241047, 0.30737, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0551487, 0.0810796, 0.207447, 1.0]], # specular [0.0319149], # shininess [ 1.0], # opacity ], [ # 4 [[0.0323647, 0.124352, 0.118739, 1.0]], # ambient [[0.130807, 0.502591, 0.479904, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.330429, 0.336788, 0.23505, 1.0]], # specular [0.0569948], # shininess [ 1.0], # opacity ], [ # 5 [[0.0304568, 0.117021, 0.111739, 1.0]], # ambient [[0.130133, 0.5, 0.47743, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.360091, 0.367021, 0.25615, 1.0]], # specular [0.308511], # shininess [ 1.0], # opacity ], [ # 6 [[0.0929826, 0.126603, 0.0845505, 1.0]], # ambient [[0.359105, 0.48895, 0.32654, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.218085, 0.218085, 0.218085, 1.0]], # specular [0.0585106], # shininess [ 1.0], # opacity ], [ # 7 [[0.0, 0.101269, 0.068588, 1.0]], # ambient [[0.0, 0.413884, 0.280316, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.112376, 0.390598, 0.205359, 1.0]], # specular [0.191489], # shininess [ 1.0], # opacity ], [ # 8 [[0.00401819, 0.0732565, 0.0689279, 1.0]], # ambient [[0.0164076, 0.299131, 0.281455, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.479592, 0.428903, 0.403559, 1.0]], # specular [0.25], # shininess [ 1.0], # opacity ], [ # 9 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.356628, 0.356628, 0.356628, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 10 [[0.188697, 0.151351, 0.116214, 1.0]], # ambient [[0.749548, 0.601201, 0.461629, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0786239, 0.0803968, 0.0484226, 1.0]], # specular [0.167568], # shininess [ 1.0], # opacity ], [ # 11 [[0.113875, 0.0786447, 0.0529297, 1.0]], # ambient [[0.449506, 0.31044, 0.208933, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.180851, 0.068473, 0.0473582, 1.0]], # specular [0.0106383], # shininess [ 1.0], # opacity ], [ # 12 [[0.20373, 0.0832482, 0.0832482, 1.0]], # ambient [[0.799639, 0.326749, 0.326749, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.327377, 0.135466, 0.0, 1.0]], # specular [0.0765306], # shininess [ 1.0], # opacity ], [ # 13 [[0.117021, 0.0569453, 0.0298209, 1.0]], # ambient [[0.5, 0.243312, 0.127417, 1.0]], # diffuse [[0.0159574, 0.0159574, 0.0159574, 1.0]], # emission [[0.276596, 0.0550859, 0.0152398, 1.0]], # specular [0.0319149], # shininess [ 1.0], # opacity ], [ # 14 [[0.0791511, 0.0385168, 0.0201703, 1.0]], # ambient [[0.322063, 0.156723, 0.0820722, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.296891, 0.0591278, 0.016358, 1.0]], # specular [0.0319149], # shininess [ 1.0], # opacity ], [ # 15 [[0.0791511, 0.0385168, 0.0201703, 1.0]], # ambient [[0.322063, 0.156723, 0.0820722, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.122719, 0.0363652, 0.0100606, 1.0]], # specular [0.0319149], # shininess [ 1.0], # opacity ], [ # 16 [[0.0854592, 0.0223421, 0.00129976, 1.0]], # ambient [[0.34773, 0.0909093, 0.00528868, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.336735, 0.0510908, 0.0510908, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 17 [[0.081228, 0.0634641, 0.0519579, 1.0]], # ambient [[0.330514, 0.258233, 0.211415, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.183673, 0.165545, 0.163419, 1.0]], # specular [0.0255102], # shininess [ 1.0], # opacity ], [ # 18 [[0.0774408, 0.0508492, 0.0391968, 1.0]], # ambient [[0.311801, 0.204735, 0.157819, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.204427, 0.102753, 0.114546, 1.0]], # specular [0.0957447], # shininess [ 1.0], # opacity ], [ # 19 [[0.149109, 0.0954788, 0.0403047, 1.0]], # ambient [[0.501339, 0.321021, 0.135513, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0794227, 0.0300707, 0.0207978, 1.0]], # specular [0.0212766], # shininess [ 1.0], # opacity ], [ # 20 [[0.116413, 0.0814615, 0.00859288, 1.0]], # ambient [[0.484043, 0.338715, 0.035729, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.223676, 0.109052, 0.0333732, 1.0]], # specular [0.0851064], # shininess [ 1.0], # opacity ], [ # 21 [[0.204082, 0.12971, 0.0239268, 1.0]], # ambient [[0.795918, 0.505869, 0.0933146, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.923469, 0.428866, 0.00636875, 1.0]], # specular [0.397959], # shininess [ 1.0], # opacity ], [ # 22 [[0.0611001, 0.0254494, 0.0254494, 1.0]], # ambient [[0.241185, 0.100458, 0.100458, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.00916127, 0.0158039, 0.108627, 1.0]], # specular [0.037234], # shininess [ 1.0], # opacity ], [ # 23 [[0.154255, 0.0441891, 0.0546348, 1.0]], # ambient [[0.601064, 0.172185, 0.212887, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.824468, 0.227489, 0.227489, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 24 [[0.113875, 0.0947862, 0.0808531, 1.0]], # ambient [[0.449506, 0.374156, 0.319157, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.198631, 0.0321162, 0.160295, 1.0]], # specular [0.0106383], # shininess [ 1.0], # opacity ], [ # 25 [[0.0869044, 0.0537721, 0.0617037, 1.0]], # ambient [[0.335631, 0.207672, 0.238304, 1.0]], # diffuse [[0.0106383, 0.0106383, 0.0106383, 1.0]], # emission [[0.198631, 0.0754031, 0.138803, 1.0]], # specular [0.0212766], # shininess [ 1.0], # opacity ], [ # 26 [[0.0978699, 0.0978699, 0.0978699, 1.0]], # ambient [[0.381693, 0.381693, 0.381693, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0397459, 0.0341806, 0.100964, 1.0]], # specular [0.0362694], # shininess [ 1.0], # opacity ], [ # 27 [[0.0518135, 0.0518135, 0.0518135, 1.0]], # ambient [[0.248705, 0.248705, 0.248705, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0530324, 0.0456067, 0.134715, 1.0]], # specular [0.0984456], # shininess [ 1.0], # opacity ], [ # 28 [[0.00892394, 0.00892394, 0.00892394, 1.0]], # ambient [[0.042835, 0.042835, 0.042835, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.113468, 0.109578, 0.156265, 1.0]], # specular [0.0638298], # shininess [ 1.0], # opacity ], [ # 29 [[0.154255, 0.0189769, 0.0294289, 1.0]], # ambient [[0.601064, 0.0739446, 0.114671, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.425532, 0.032158, 0.032158, 1.0]], # specular [0.0851064], # shininess [ 1.0], # opacity ], [ # 30 [[0.0450585, 0.00625593, 0.0156668, 1.0]], # ambient [[0.191499, 0.0265877, 0.0665837, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.367348, 0.0557356, 0.0557356, 1.0]], # specular [0.0585106], # shininess [ 1.0], # opacity ], [ # 31 [[0.119867, 0.12566, 0.177947, 1.0]], # ambient [[0.461987, 0.484316, 0.685837, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.2038, 0.253886, 0.253886, 1.0]], # specular [0.0569948], # shininess [ 1.0], # opacity ], [ # 32 [[0.0632039, 0.101255, 0.114751, 1.0]], # ambient [[0.243598, 0.390254, 0.442269, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.257869, 0.321244, 0.321244, 1.0]], # specular [0.0310881], # shininess [ 1.0], # opacity ], [ # 33 [[0.0883556, 0.0972922, 0.177947, 1.0]], # ambient [[0.340537, 0.37498, 0.685837, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.237073, 0.295337, 0.295337, 1.0]], # specular [0.466321], # shininess [ 1.0], # opacity ], [ # 34 [[0.0415096, 0.124737, 0.154255, 1.0]], # ambient [[0.160312, 0.481742, 0.595745, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.19214, 0.239362, 0.239362, 1.0]], # specular [0.0691489], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/rococo.py0000644000175000017500000002470407354231036024135 0ustar debiandebian# material definition table: rococo # rococo = [\ [ # 0 [[0.159053, 0.187004, 0.075237, 1.0]], # ambient [[0.636212, 0.748016, 0.300948, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.412121, 0.412121, 0.412121, 1.0]], # specular [0.8], # shininess [ 1.0], # opacity ], [ # 1 [[0.216064, 0.208447, 0.0826205, 1.0]], # ambient [[0.864256, 0.833788, 0.330482, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0940254, 0.0681705, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 2 [[0.187004, 0.0745904, 0.0856559, 1.0]], # ambient [[0.748016, 0.298362, 0.342624, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.345455, 0.345455, 0.345455, 1.0]], # specular [0.69697], # shininess [ 1.0], # opacity ], [ # 3 [[0.226102, 0.0365915, 0.052192, 1.0]], # ambient [[0.904409, 0.146366, 0.208768, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 4 [[0.187004, 0.0680835, 0.101711, 1.0]], # ambient [[0.748016, 0.272334, 0.406842, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.251984, 0.251984, 0.251984, 1.0]], # specular [0.6], # shininess [ 1.0], # opacity ], [ # 5 [[0.226102, 0.0788828, 0.136097, 1.0]], # ambient [[0.904409, 0.315531, 0.544386, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 6 [[0.187004, 0.117467, 0.168318, 1.0]], # ambient [[0.748016, 0.469867, 0.673271, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.251984, 0.251984, 0.251984, 1.0]], # specular [0.593939], # shininess [ 1.0], # opacity ], [ # 7 [[0.223615, 0.095694, 0.226102, 1.0]], # ambient [[0.894461, 0.382776, 0.904409, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 8 [[0.160247, 0.115024, 0.187004, 1.0]], # ambient [[0.640987, 0.460097, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.251984, 0.251984, 0.251984, 1.0]], # specular [0.612121], # shininess [ 1.0], # opacity ], [ # 9 [[0.153893, 0.0899144, 0.181818, 1.0]], # ambient [[0.630959, 0.368649, 0.745454, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.278788, 0.278788, 0.278788, 1.0]], # specular [0.0909091], # shininess [ 1.0], # opacity ], [ # 10 [[0.103014, 0.105626, 0.187004, 1.0]], # ambient [[0.412056, 0.422504, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.290909, 0.290909, 0.290909, 1.0]], # specular [0.787879], # shininess [ 1.0], # opacity ], [ # 11 [[0.131363, 0.113974, 0.226102, 1.0]], # ambient [[0.52545, 0.455896, 0.904409, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 12 [[0.187004, 0.180659, 0.0672271, 1.0]], # ambient [[0.748016, 0.722635, 0.268909, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.412121, 0.412121, 0.412121, 1.0]], # specular [0.806061], # shininess [ 1.0], # opacity ], [ # 13 [[0.126039, 0.151751, 0.187004, 1.0]], # ambient [[0.504157, 0.607004, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.309091, 0.309091, 0.309091, 1.0]], # specular [0.8], # shininess [ 1.0], # opacity ], [ # 14 [[0.113974, 0.187427, 0.226102, 1.0]], # ambient [[0.455896, 0.749706, 0.904409, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 15 [[0.0645725, 0.133621, 0.187004, 1.0]], # ambient [[0.25829, 0.534482, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.251984, 0.251984, 0.251984, 1.0]], # specular [0.25], # shininess [ 1.0], # opacity ], [ # 16 [[0.0715899, 0.138726, 0.226102, 1.0]], # ambient [[0.28636, 0.554905, 0.904409, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 17 [[0.0654101, 0.187004, 0.181479, 1.0]], # ambient [[0.261641, 0.748016, 0.725916, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.490909, 0.490909, 0.490909, 1.0]], # specular [0.593939], # shininess [ 1.0], # opacity ], [ # 18 [[0.115585, 0.226102, 0.17518, 1.0]], # ambient [[0.462339, 0.904409, 0.700718, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 19 [[0.076592, 0.187004, 0.141413, 1.0]], # ambient [[0.306368, 0.748016, 0.565651, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.569697, 0.569697, 0.569697, 1.0]], # specular [0.636364], # shininess [ 1.0], # opacity ], [ # 20 [[0.0699112, 0.226102, 0.127897, 1.0]], # ambient [[0.279645, 0.904409, 0.511589, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 21 [[0.090187, 0.187004, 0.0986946, 1.0]], # ambient [[0.360748, 0.748016, 0.394778, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.345455, 0.345455, 0.345455, 1.0]], # specular [0.612121], # shininess [ 1.0], # opacity ], [ # 22 [[0.137804, 0.226102, 0.0673236, 1.0]], # ambient [[0.551217, 0.904409, 0.269294, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 23 [[0.226102, 0.189684, 0.0678377, 1.0]], # ambient [[0.904409, 0.758737, 0.271351, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 24 [[0.182693, 0.185095, 0.187004, 1.0]], # ambient [[0.730772, 0.740381, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.251984, 0.251984, 0.251984, 1.0]], # specular [0.25], # shininess [ 1.0], # opacity ], [ # 25 [[0.193939, 0.193232, 0.191111, 1.0]], # ambient [[0.581818, 0.579698, 0.573336, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 26 [[0.107626, 0.109041, 0.110166, 1.0]], # ambient [[0.430504, 0.436165, 0.440663, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.251984, 0.251984, 0.251984, 1.0]], # specular [0.684848], # shininess [ 1.0], # opacity ], [ # 27 [[0.0548466, 0.0546467, 0.054047, 1.0]], # ambient [[0.219386, 0.218587, 0.216188, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 28 [[0.0488387, 0.0494809, 0.0499912, 1.0]], # ambient [[0.195355, 0.197924, 0.199965, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.430303, 0.430303, 0.430303, 1.0]], # specular [0.406061], # shininess [ 1.0], # opacity ], [ # 29 [[0.187004, 0.148447, 0.0640423, 1.0]], # ambient [[0.748016, 0.593789, 0.256169, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.375758, 0.375758, 0.375758, 1.0]], # specular [0.781818], # shininess [ 1.0], # opacity ], [ # 30 [[0.226102, 0.137326, 0.0560706, 1.0]], # ambient [[0.904409, 0.549305, 0.224283, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 31 [[0.187004, 0.116776, 0.0654101, 1.0]], # ambient [[0.748016, 0.467103, 0.261641, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.251984, 0.251984, 0.251984, 1.0]], # specular [0.872727], # shininess [ 1.0], # opacity ], [ # 32 [[0.226102, 0.114442, 0.0852773, 1.0]], # ambient [[0.904409, 0.457768, 0.341109, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 33 [[0.187004, 0.0988488, 0.076592, 1.0]], # ambient [[0.748016, 0.395395, 0.306368, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.30303, 0.30303, 0.30303, 1.0]], # specular [0.69697], # shininess [ 1.0], # opacity ], [ # 34 [[0.226102, 0.0730882, 0.0574825, 1.0]], # ambient [[0.904409, 0.292353, 0.22993, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/sheen.py0000644000175000017500000002430307354231036023746 0ustar debiandebian# material definition table: sheen # sheen = [\ [ # 0 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.641609, 0.0, 0.979592, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 1 [[0.0, 0.0, 0.0768587, 1.0]], # ambient [[0.0, 0.125353, 0.262167, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.383952, 0.0, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 2 [[0.00634796, 0.047354, 0.000659749, 1.0]], # ambient [[0.024884, 0.185628, 0.00258622, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.505305, 0.463899, 0.0, 1.0]], # specular [0.127551], # shininess [ 1.0], # opacity ], [ # 3 [[0.00634796, 0.107945, 0.000659749, 1.0]], # ambient [[0.024884, 0.423143, 0.00258622, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.505305, 0.463899, 0.0, 1.0]], # specular [0.127551], # shininess [ 1.0], # opacity ], [ # 4 [[0.0785714, 0.0785714, 0.0, 1.0]], # ambient [[0.314286, 0.314286, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.367996, 0.439089, 0.957576, 1.0]], # specular [0.345455], # shininess [ 1.0], # opacity ], [ # 5 [[0.0684189, 0.0714286, 0.00140067, 1.0]], # ambient [[0.287218, 0.299852, 0.00587991, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.15182, 0.607143, 0.173867, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 6 [[0.127551, 0.121662, 0.0479476, 1.0]], # ambient [[0.5, 0.476914, 0.187954, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.035776, 0.591837, 0.0, 1.0]], # specular [0.0816327], # shininess [ 1.0], # opacity ], [ # 7 [[0.125023, 0.127551, 0.0554187, 1.0]], # ambient [[0.490091, 0.5, 0.217241, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.565306, 0.591837, 0.0, 1.0]], # specular [0.107143], # shininess [ 1.0], # opacity ], [ # 8 [[0.102041, 0.100102, 0.0, 1.0]], # ambient [[0.403061, 0.395404, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.683673, 0.0990148, 0.0, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 9 [[0.00714286, 0.00495707, 0.0, 1.0]], # ambient [[0.314286, 0.218111, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.607143, 0.53913, 0.0, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 10 [[0.00714286, 0.00318111, 0.0, 1.0]], # ambient [[0.314286, 0.139969, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.607143, 0.53913, 0.0, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 11 [[0.0831403, 0.0, 0.0275034, 1.0]], # ambient [[0.336937, 0.0, 0.111461, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.336183, 0.372973, 0.00126432, 1.0]], # specular [0.0648649], # shininess [ 1.0], # opacity ], [ # 12 [[0.0, 0.00107338, 0.0785714, 1.0]], # ambient [[0.0, 0.00429352, 0.314286, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.364672, 0.833805, 0.909091, 1.0]], # specular [0.636364], # shininess [ 1.0], # opacity ], [ # 13 [[0.105867, 0.0485445, 0.00230774, 1.0]], # ambient [[0.42712, 0.195852, 0.00931052, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.233325, 0.607143, 0.572339, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 14 [[0.0785714, 0.0360282, 0.00171273, 1.0]], # ambient [[0.314286, 0.144113, 0.00685092, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.233325, 0.278401, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 15 [[0.0785714, 0.00279079, 0.00171273, 1.0]], # ambient [[0.314286, 0.0111632, 0.00685092, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.381971, 0.455764, 0.993939, 1.0]], # specular [0.8], # shininess [ 1.0], # opacity ], [ # 16 [[0.0785714, 0.0, 0.0, 1.0]], # ambient [[0.26801, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.607143, 0.132784, 0.175795, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 17 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.938776, 0.0550317, 0.0550317, 1.0]], # specular [0.0612245], # shininess [ 1.0], # opacity ], [ # 18 [[0.00746438, 0.00673081, 0.00690282, 1.0]], # ambient [[0.0291577, 0.0262922, 0.0269642, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.981818, 0.0, 0.0, 1.0]], # specular [0.030303], # shininess [ 1.0], # opacity ], [ # 19 [[0.0, 0.0, 0.0768587, 1.0]], # ambient [[0.262167, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.383952, 0.0, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 20 [[0.0712302, 0.0, 0.0714286, 1.0]], # ambient [[0.265081, 0.0, 0.265819, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.607143, 0.607143, 0.00496302, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 21 [[0.0714286, 0.0, 0.0696466, 1.0]], # ambient [[0.308275, 0.0, 0.300584, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.236417, 0.945455, 0.270749, 1.0]], # specular [0.369697], # shininess [ 1.0], # opacity ], [ # 22 [[0.068267, 0.0360282, 0.0785714, 1.0]], # ambient [[0.273068, 0.144113, 0.314286, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.233325, 0.278401, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 23 [[0.0301951, 0.0360283, 0.0785714, 1.0]], # ambient [[0.12078, 0.144113, 0.314286, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.233325, 0.278401, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 24 [[0.0, 0.0, 0.0768587, 1.0]], # ambient [[0.262167, 0.0, 0.262167, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.383952, 0.0, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 25 [[0.0, 0.0, 0.19898, 1.0]], # ambient [[0.348557, 0.0, 0.795918, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.448482, 0.0, 0.709184, 1.0]], # specular [0.433673], # shininess [ 1.0], # opacity ], [ # 26 [[0.0437648, 0.0, 0.0840517, 1.0]], # ambient [[0.187413, 0.121184, 0.25936, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.625, 0.892857, 1.0]], # specular [0.122449], # shininess [ 1.0], # opacity ], [ # 27 [[0.029171, 0.0147651, 0.0445259, 1.0]], # ambient [[0.119925, 0.0607008, 0.183051, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.356263, 0.383104, 0.826531, 1.0]], # specular [0.0867347], # shininess [ 1.0], # opacity ], [ # 28 [[0.0329288, 0.0335907, 0.0445259, 1.0]], # ambient [[0.135374, 0.138095, 0.183051, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.362217, 0.369498, 0.489785, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 29 [[0.000457702, 0.0, 0.0714286, 1.0]], # ambient [[0.00183081, 0.0, 0.285714, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.15182, 0.607143, 0.173867, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 30 [[0.0, 0.0, 0.0768587, 1.0]], # ambient [[0.0, 0.262167, 0.262167, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.383952, 0.0, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 31 [[0.0, 0.0785714, 0.0777151, 1.0]], # ambient [[0.0, 0.26801, 0.265089, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.607143, 0.132784, 0.175795, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 32 [[0.0, 0.0706284, 0.0785714, 1.0]], # ambient [[0.0, 0.282514, 0.314286, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.233325, 0.278401, 0.607143, 1.0]], # specular [0.157143], # shininess [ 1.0], # opacity ], [ # 33 [[0.0, 0.0714286, 0.0652005, 1.0]], # ambient [[0.0, 0.286882, 0.261868, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.243549, 0.556863, 0.607143, 1.0]], # specular [0.0663265], # shininess [ 1.0], # opacity ], [ # 34 [[0.0, 0.0714286, 0.0652005, 1.0]], # ambient [[0.0, 0.286882, 0.261868, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.243549, 0.556863, 0.607143, 1.0]], # specular [0.15], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/tropical.py0000644000175000017500000002430207354231037024461 0ustar debiandebian# material definition table: tropical # tropical = [\ [ # 0 [[0.219385, 0.226102, 0.0, 1.0]], # ambient [[0.877539, 0.904409, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 1 [[0.187004, 0.155212, 0.0, 1.0]], # ambient [[0.748014, 0.62085, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.860606, 0.860606, 0.860599, 1.0]], # specular [0.939394], # shininess [ 1.0], # opacity ], [ # 2 [[0.226102, 0.0, 0.0774629, 1.0]], # ambient [[0.904409, 0.0, 0.309851, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 3 [[0.187004, 0.00156472, 0.0629827, 1.0]], # ambient [[0.748016, 0.00625887, 0.251931, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.684848, 0.684848, 0.684848, 1.0]], # specular [0.933333], # shininess [ 1.0], # opacity ], [ # 4 [[0.226102, 0.0117368, 0.124027, 1.0]], # ambient [[0.904409, 0.0469471, 0.496108, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 5 [[0.187004, 0.0, 0.137588, 1.0]], # ambient [[0.748016, 0.0, 0.550351, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.672727, 0.672727, 0.672727, 1.0]], # specular [0.230303], # shininess [ 1.0], # opacity ], [ # 6 [[0.223992, 0.0, 0.172818, 1.0]], # ambient [[0.895967, 0.0, 0.691271, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0862563, 0.093458, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 7 [[0.156092, 0.0, 0.187004, 1.0]], # ambient [[0.624368, 0.0, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.951515, 0.951515, 0.951515, 1.0]], # specular [0.557576], # shininess [ 1.0], # opacity ], [ # 8 [[0.155445, 0.00522921, 0.220045, 1.0]], # ambient [[0.62178, 0.0209168, 0.880181, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0877258, 0.0694377, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 9 [[0.093502, 0.0, 0.187004, 1.0]], # ambient [[0.374008, 0.0, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.909091, 0.909091, 0.909091, 1.0]], # specular [0.406061], # shininess [ 1.0], # opacity ], [ # 10 [[0.0698754, 0.00128542, 0.211477, 1.0]], # ambient [[0.279501, 0.00514168, 0.845907, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0522777, 0.0312975, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 11 [[0.000579251, 0.0, 0.187004, 1.0]], # ambient [[0.002317, 0.0, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.884848, 0.884848, 0.884848, 1.0]], # specular [0.830303], # shininess [ 1.0], # opacity ], [ # 12 [[0.226102, 0.193685, 0.0207668, 1.0]], # ambient [[0.904409, 0.774741, 0.0830671, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 13 [[0.0, 0.0512388, 0.211311, 1.0]], # ambient [[0.0, 0.204955, 0.845242, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.03017, 0.0460332, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 14 [[0.00518309, 0.0849113, 0.187004, 1.0]], # ambient [[0.0207323, 0.339645, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.90303, 0.90303, 0.90303, 1.0]], # specular [0.927273], # shininess [ 1.0], # opacity ], [ # 15 [[0.0, 0.149246, 0.204489, 1.0]], # ambient [[0.0, 0.596985, 0.817956, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0697667, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 16 [[0.0, 0.157811, 0.187004, 1.0]], # ambient [[0.0, 0.631244, 0.748016, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.915152, 0.915152, 0.915152, 1.0]], # specular [0.642424], # shininess [ 1.0], # opacity ], [ # 17 [[0.0, 0.204489, 0.138459, 1.0]], # ambient [[0.0, 0.817956, 0.553836, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0955906, 0.0647242, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 18 [[0.0, 0.187004, 0.117351, 1.0]], # ambient [[0.0, 0.748016, 0.469403, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 1.0, 1.0, 1.0]], # specular [0.818182], # shininess [ 1.0], # opacity ], [ # 19 [[0.0132882, 0.204489, 0.0220044, 1.0]], # ambient [[0.0531526, 0.817956, 0.0880178, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.00621169, 0.0955906, 0.0102862, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 20 [[0.0, 0.187004, 0.0440039, 1.0]], # ambient [[0.0, 0.748016, 0.176015, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.981818, 0.981818, 0.981818, 1.0]], # specular [0.721212], # shininess [ 1.0], # opacity ], [ # 21 [[0.0888441, 0.204489, 0.00394926, 1.0]], # ambient [[0.355377, 0.817956, 0.015797, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0415311, 0.0955906, 0.00184612, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 22 [[0.0954861, 0.187004, 0.0, 1.0]], # ambient [[0.381944, 0.748016, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.963636, 0.963636, 0.963636, 1.0]], # specular [0.981818], # shininess [ 1.0], # opacity ], [ # 23 [[0.187004, 0.13893, 0.0, 1.0]], # ambient [[0.748016, 0.555721, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.836364, 0.836364, 0.836364, 1.0]], # specular [0.606061], # shininess [ 1.0], # opacity ], [ # 24 [[0.247933, 0.234873, 0.25, 1.0]], # ambient [[0.991732, 0.939493, 1.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.0, 0.0, 1.0]], # specular [0.0], # shininess [ 1.0], # opacity ], [ # 25 [[0.106266, 0.101217, 0.106572, 1.0]], # ambient [[0.425062, 0.404868, 0.426289, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.860606, 0.860606, 0.860606, 1.0]], # specular [0.90303], # shininess [ 1.0], # opacity ], [ # 26 [[0.106059, 0.106059, 0.106059, 1.0]], # ambient [[0.424238, 0.424238, 0.424238, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.168, 0.168, 0.168, 1.0]], # specular [0.153696], # shininess [ 1.0], # opacity ], [ # 27 [[0.0380952, 0.0362853, 0.0382051, 1.0]], # ambient [[0.152381, 0.145141, 0.15282, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.745455, 0.745455, 0.745455, 1.0]], # specular [0.957576], # shininess [ 1.0], # opacity ], [ # 28 [[0.0346667, 0.0346667, 0.0346667, 1.0]], # ambient [[0.138667, 0.138667, 0.138667, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.168, 0.168, 0.168, 1.0]], # specular [0.153696], # shininess [ 1.0], # opacity ], [ # 29 [[0.226102, 0.103065, 0.0, 1.0]], # ambient [[0.904409, 0.412258, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 30 [[0.187004, 0.0748842, 0.0, 1.0]], # ambient [[0.748016, 0.299537, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.836364, 0.836364, 0.836364, 1.0]], # specular [0.921212], # shininess [ 1.0], # opacity ], [ # 31 [[0.226102, 0.0709385, 0.0, 1.0]], # ambient [[0.904409, 0.283754, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 32 [[0.187004, 0.0348922, 0.0, 1.0]], # ambient [[0.748016, 0.139569, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.709091, 0.709091, 0.709091, 1.0]], # specular [0.478788], # shininess [ 1.0], # opacity ], [ # 33 [[0.226102, 0.0375784, 0.0, 1.0]], # ambient [[0.904409, 0.150314, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 34 [[0.187004, 0.0, 0.0100218, 1.0]], # ambient [[0.748016, 0.0, 0.0400871, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.89697, 0.89697, 0.89697, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/neon.py0000644000175000017500000002322007354231036023600 0ustar debiandebian# material definition table: neon # neon = [\ [ # 0 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.398733, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 1 [[0.0972973, 0.0972973, 0.0972973, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.628573, 1.0, 1.0]], # emission [[0.47027, 0.47027, 0.47027, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 2 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.871763, 0.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 3 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.7155, 0.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 4 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.577069, 0.0, 1.0]], # emission [[0.383784, 0.383784, 0.383784, 1.0]], # specular [0.0540541], # shininess [ 1.0], # opacity ], [ # 5 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.442751, 0.0, 1.0]], # emission [[0.475676, 0.475676, 0.475676, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 6 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.318894, 0.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0864865], # shininess [ 1.0], # opacity ], [ # 7 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.151505, 0.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 8 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.0, 0.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 9 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.0, 0.0807333, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 10 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.0, 0.265757, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 11 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.0, 0.34678, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 12 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0188407, 0.940276, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 13 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.0790818, 0.656922, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 14 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.934028, 0.00304288, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 15 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.755836, 0.0, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 16 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.58832, 0.0172936, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 17 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.460235, 0.0, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 18 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.17496, 0.0, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 19 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.135953, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 20 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.277276, 1.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 21 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.2805, 0.39661, 1.0]], # emission [[0.616216, 0.616216, 0.616216, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 22 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.2805, 0.040678, 1.0]], # emission [[0.616216, 0.616216, 0.616216, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 23 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 1.0, 0.734243, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 24 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.921769, 0.544218, 0.0, 1.0]], # emission [[0.637764, 0.37654, 0.0, 1.0]], # specular [0.0540541], # shininess [ 1.0], # opacity ], [ # 25 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[1.0, 0.286509, 0.159322, 1.0]], # emission [[0.535135, 0.535135, 0.535135, 1.0]], # specular [0.0540541], # shininess [ 1.0], # opacity ], [ # 26 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.667797, 0.0769664, 0.171099, 1.0]], # emission [[0.497297, 0.497297, 0.497297, 1.0]], # specular [0.0540541], # shininess [ 1.0], # opacity ], [ # 27 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.59083, 0.0582792, 0.307405, 1.0]], # emission [[0.6, 0.6, 0.6, 1.0]], # specular [0.0756757], # shininess [ 1.0], # opacity ], [ # 28 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.595346, 0.187689, 0.595358, 1.0]], # emission [[0.47027, 0.47027, 0.47027, 1.0]], # specular [0.0540541], # shininess [ 1.0], # opacity ], [ # 29 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 1.0, 0.456346, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 30 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0, 1.0, 0.168349, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 31 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.0239058, 1.0, 0.00238997, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 32 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.363921, 1.0, 0.0478005, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 33 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.559606, 1.0, 0.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], [ # 34 [[0.0, 0.0, 0.0, 1.0]], # ambient [[0.0, 0.0, 0.0, 1.0]], # diffuse [[0.757687, 1.0, 0.0, 1.0]], # emission [[0.622449, 0.622449, 0.622449, 1.0]], # specular [0.0510204], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/__init__.py0000644000175000017500000000053307352707246024413 0ustar debiandebianfrom artdeco import artdeco from autumn import autumn from glass import glass from metal import metal from neon import neon from rococo import rococo from santafe import santafe from sheen import sheen from silky import silky from spring import spring from summer import summer from tropical import tropical from winter import winter mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/autumn.py0000644000175000017500000002457607354231035024170 0ustar debiandebian# material definition table: autumn # autumn = [\ [ # 0 [[0.937255, 0.866667, 0.341176, 1.0]], # ambient [[0.964706, 0.862745, 0.811765, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.513726, 0.415686, 0.219608, 1.0]], # specular [11.4872], # shininess [ 1.0], # opacity ], [ # 1 [[0.188697, 0.151351, 0.116214, 1.0]], # ambient [[0.749548, 0.601201, 0.461629, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0786239, 0.0803968, 0.0484226, 1.0]], # specular [0.167568], # shininess [ 1.0], # opacity ], [ # 2 [[0.149894, 0.070142, 0.00175932, 1.0]], # ambient [[0.584588, 0.273554, 0.00686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.428571, 0.199032, 0.00295567, 1.0]], # specular [0.0663265], # shininess [ 1.0], # opacity ], [ # 3 [[0.204082, 0.070142, 0.00175932, 1.0]], # ambient [[0.795918, 0.273554, 0.00686136, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.48655, 0.319155, 0.444036, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 4 [[0.110873, 0.0340652, 0.00930366, 1.0]], # ambient [[0.460362, 0.141445, 0.0386304, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.193005, 0.159326, 0.125431, 1.0]], # specular [0.178571], # shininess [ 1.0], # opacity ], [ # 5 [[0.0854592, 0.0223421, 0.00129976, 1.0]], # ambient [[0.34773, 0.0909093, 0.00528868, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.336735, 0.0510908, 0.0510908, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 6 [[0.211184, 0.0522992, 0.0480626, 1.0]], # ambient [[0.876873, 0.217155, 0.199564, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.928571, 0.140887, 0.140887, 1.0]], # specular [0.984694], # shininess [ 1.0], # opacity ], [ # 7 [[0.211184, 0.0778259, 0.0480626, 1.0]], # ambient [[0.876873, 0.323147, 0.199564, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.816327, 0.278677, 0.278677, 1.0]], # specular [0.80102], # shininess [ 1.0], # opacity ], [ # 8 [[0.135556, 0.0354392, 0.00206169, 1.0]], # ambient [[0.562852, 0.14715, 0.00856049, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.107143, 0.0162562, 0.0162562, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 9 [[0.211184, 0.0354392, 0.00206169, 1.0]], # ambient [[0.876873, 0.14715, 0.00856049, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.193878, 0.0294159, 0.0294159, 1.0]], # specular [0.0765306], # shininess [ 1.0], # opacity ], [ # 10 [[0.135135, 0.0, 0.0, 1.0]], # ambient [[0.540541, 0.0, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.592903, 0.0, 0.129656, 1.0]], # specular [0.0648649], # shininess [ 1.0], # opacity ], [ # 11 [[0.113362, 0.0340517, 0.0240963, 1.0]], # ambient [[0.453448, 0.136207, 0.0963852, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0874736, 0.207208, 0.576531, 1.0]], # specular [0.892857], # shininess [ 1.0], # opacity ], [ # 12 [[0.098983, 0.0565609, 0.0320604, 1.0]], # ambient [[0.395932, 0.226244, 0.128242, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[1.0, 0.464407, 0.4753, 1.0]], # specular [0.994595], # shininess [ 1.0], # opacity ], [ # 13 [[0.0670918, 0.0201531, 0.0142611, 1.0]], # ambient [[0.272994, 0.0820021, 0.0580278, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.27551, 0.0418016, 0.0418016, 1.0]], # specular [0.127551], # shininess [ 1.0], # opacity ], [ # 14 [[0.0927533, 0.161054, 0.0241379, 1.0]], # ambient [[0.371013, 0.644214, 0.0965517, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0874736, 0.207208, 0.576531, 1.0]], # specular [0.892857], # shininess [ 1.0], # opacity ], [ # 15 [[0.0285238, 0.135746, 0.0212702, 1.0]], # ambient [[0.114827, 0.546465, 0.0856263, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.117347, 0.0638623, 0.0624524, 1.0]], # specular [0.0918367], # shininess [ 1.0], # opacity ], [ # 16 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.071925, 0.356628, 0.0, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 17 [[0.0617796, 0.0769001, 0.0496305, 1.0]], # ambient [[0.251104, 0.312562, 0.201724, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.494898, 0.269332, 0.263386, 1.0]], # specular [0.790816], # shininess [ 1.0], # opacity ], [ # 18 [[0.0617796, 0.0769001, 0.0496305, 1.0]], # ambient [[0.251104, 0.312562, 0.201724, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.209184, 0.113842, 0.111328, 1.0]], # specular [0.0867347], # shininess [ 1.0], # opacity ], [ # 19 [[0.0479792, 0.0624384, 0.0443528, 1.0]], # ambient [[0.193147, 0.251355, 0.178548, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.418367, 0.227683, 0.222656, 1.0]], # specular [0.0918367], # shininess [ 1.0], # opacity ], [ # 20 [[0.0337695, 0.0473434, 0.0303651, 1.0]], # ambient [[0.135944, 0.190588, 0.122239, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.209184, 0.113842, 0.111328, 1.0]], # specular [0.0867347], # shininess [ 1.0], # opacity ], [ # 21 [[0.0788472, 0.136, 0.0645131, 1.0]], # ambient [[0.315389, 0.544, 0.258052, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.456, 0.456, 0.456, 1.0]], # specular [0.509389], # shininess [ 1.0], # opacity ], [ # 22 [[0.0915613, 0.15793, 0.0749157, 1.0]], # ambient [[0.176164, 0.303858, 0.144138, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.465986, 0.253598, 0.247999, 1.0]], # specular [0.448649], # shininess [ 1.0], # opacity ], [ # 23 [[0.018772, 0.00558358, 0.0, 1.0]], # ambient [[0.0870338, 0.0258875, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.224138, 0.104091, 0.104091, 1.0]], # specular [0.0459184], # shininess [ 1.0], # opacity ], [ # 24 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.356628, 0.356628, 0.356628, 1.0]], # specular [0.0810811], # shininess [ 1.0], # opacity ], [ # 25 [[0.0, 0.0310982, 0.0, 1.0]], # ambient [[0.0, 0.122449, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.303255, 0.348166, 1.0]], # specular [0.194595], # shininess [ 1.0], # opacity ], [ # 26 [[0.0, 0.0918367, 0.0671358, 1.0]], # ambient [[0.0, 0.346939, 0.253624, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.311074, 0.357143, 1.0]], # specular [0.316327], # shininess [ 1.0], # opacity ], [ # 27 [[0.0213458, 0.0155543, 0.0445259, 1.0]], # ambient [[0.0877551, 0.0639456, 0.183051, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.234804, 0.171098, 0.489785, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 28 [[0.0640375, 0.046663, 0.133578, 1.0]], # ambient [[0.263265, 0.191837, 0.549153, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.374738, 0.273065, 0.781677, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 29 [[0.0635508, 0.0273503, 0.0177271, 1.0]], # ambient [[0.252438, 0.108642, 0.0704161, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.300449, 0.142972, 0.142972, 1.0]], # specular [0.0663265], # shininess [ 1.0], # opacity ], [ # 30 [[0.126557, 0.0744004, 0.0482226, 1.0]], # ambient [[0.502714, 0.295535, 0.191551, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.265851, 0.126509, 0.126509, 1.0]], # specular [0.928571], # shininess [ 1.0], # opacity ], [ # 31 [[0.126557, 0.0744004, 0.0482226, 1.0]], # ambient [[0.502714, 0.295535, 0.191551, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0786239, 0.0803968, 0.0484226, 1.0]], # specular [0.167568], # shininess [ 1.0], # opacity ], [ # 32 [[0.204082, 0.12971, 0.0422238, 1.0]], # ambient [[0.795918, 0.505869, 0.164673, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.295918, 0.096084, 0.00204082, 1.0]], # specular [0.831633], # shininess [ 1.0], # opacity ], [ # 33 [[0.0724766, 0.0342526, 0.0257261, 1.0]], # ambient [[0.297959, 0.140816, 0.105763, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.176503, 0.0894282, 0.0, 1.0]], # specular [0.0486486], # shininess [ 1.0], # opacity ], [ # 34 [[0.204082, 0.12971, 0.0239268, 1.0]], # ambient [[0.795918, 0.505869, 0.0933146, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.923469, 0.428866, 0.00636875, 1.0]], # specular [0.397959], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/materialsDef/spring.py0000644000175000017500000002461707354231036024156 0ustar debiandebian# material definition table: spring # spring = [\ [ # 0 [[0.897959, 0.830331, 0.326872, 1.0]], # ambient [[0.331633, 0.296582, 0.279057, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.489796, 0.396323, 0.209378, 1.0]], # specular [0.979592], # shininess [ 1.0], # opacity ], [ # 1 [[0.216064, 0.208447, 0.0826205, 1.0]], # ambient [[0.864256, 0.833788, 0.330482, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0940254, 0.0681705, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 2 [[0.20373, 0.0207242, 0.0320616, 1.0]], # ambient [[0.799639, 0.0813426, 0.125842, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.913265, 0.373179, 0.373179, 1.0]], # specular [0.959184], # shininess [ 1.0], # opacity ], [ # 3 [[0.174575, 0.0227552, 0.00692281, 1.0]], # ambient [[0.685208, 0.0893143, 0.027172, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.913265, 0.373179, 0.373179, 1.0]], # specular [0.959184], # shininess [ 1.0], # opacity ], [ # 4 [[0.174575, 0.0343131, 0.084684, 1.0]], # ambient [[0.685208, 0.134679, 0.332385, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.122449, 0.0500352, 0.0500352, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 5 [[0.226102, 0.0788828, 0.136097, 1.0]], # ambient [[0.904409, 0.315531, 0.544386, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 6 [[0.115152, 0.0895623, 0.102867, 1.0]], # ambient [[0.484848, 0.377104, 0.433123, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.436364, 0.243939, 0.298678, 1.0]], # specular [0.0242424], # shininess [ 1.0], # opacity ], [ # 7 [[0.223615, 0.095694, 0.226102, 1.0]], # ambient [[0.894461, 0.382776, 0.904409, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 8 [[0.153893, 0.0899144, 0.181818, 1.0]], # ambient [[0.630959, 0.368649, 0.745454, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.278788, 0.278788, 0.278788, 1.0]], # specular [0.0909091], # shininess [ 1.0], # opacity ], [ # 9 [[0.0901801, 0.033855, 0.0888283, 1.0]], # ambient [[0.355416, 0.133428, 0.350088, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.680294, 0.314997, 0.841837, 1.0]], # specular [0.107143], # shininess [ 1.0], # opacity ], [ # 10 [[0.109203, 0.0505645, 0.135135, 1.0]], # ambient [[0.432445, 0.200235, 0.535135, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.30577, 0.141581, 0.378378, 1.0]], # specular [0.567568], # shininess [ 1.0], # opacity ], [ # 11 [[0.0899574, 0.0891371, 0.158314, 1.0]], # ambient [[0.348585, 0.345407, 0.613468, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.380859, 0.353232, 0.890218, 1.0]], # specular [0.612245], # shininess [ 1.0], # opacity ], [ # 12 [[0.253968, 0.228701, 0.0798059, 1.0]], # ambient [[1.0, 0.900511, 0.314236, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.872449, 0.247119, 0.254214, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 13 [[0.11708, 0.119434, 0.158314, 1.0]], # ambient [[0.453686, 0.462806, 0.613468, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.101243, 0.093899, 0.0914149, 1.0]], # specular [0.0432432], # shininess [ 1.0], # opacity ], [ # 14 [[0.0695165, 0.0709138, 0.0939991, 1.0]], # ambient [[0.278066, 0.283655, 0.375996, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.248796, 0.253797, 0.336418, 1.0]], # specular [0.0432432], # shininess [ 1.0], # opacity ], [ # 15 [[0.0877551, 0.0639456, 0.183051, 1.0]], # ambient [[0.35102, 0.255782, 0.732203, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.374738, 0.273065, 0.781677, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 16 [[0.0877551, 0.0639456, 0.183051, 1.0]], # ambient [[0.35102, 0.255782, 0.732203, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.101986, 0.0743151, 0.212735, 1.0]], # specular [0.0702703], # shininess [ 1.0], # opacity ], [ # 17 [[0.113974, 0.187427, 0.226102, 1.0]], # ambient [[0.455896, 0.749706, 0.904409, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 18 [[0.0654101, 0.187004, 0.181479, 1.0]], # ambient [[0.261641, 0.748016, 0.725916, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.490909, 0.490909, 0.490909, 1.0]], # specular [0.593939], # shininess [ 1.0], # opacity ], [ # 19 [[0.0323647, 0.124352, 0.118739, 1.0]], # ambient [[0.130807, 0.502591, 0.479904, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.330429, 0.336788, 0.23505, 1.0]], # specular [0.0569948], # shininess [ 1.0], # opacity ], [ # 20 [[0.0323647, 0.124352, 0.118739, 1.0]], # ambient [[0.130807, 0.502591, 0.479904, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.330429, 0.336788, 0.23505, 1.0]], # specular [0.585492], # shininess [ 1.0], # opacity ], [ # 21 [[0.00401819, 0.0732565, 0.0689279, 1.0]], # ambient [[0.0164076, 0.299131, 0.281455, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.479592, 0.428903, 0.403559, 1.0]], # specular [0.25], # shininess [ 1.0], # opacity ], [ # 22 [[0.00401819, 0.0732565, 0.0689279, 1.0]], # ambient [[0.0164076, 0.299131, 0.281455, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.168367, 0.150572, 0.141675, 1.0]], # specular [0.0867347], # shininess [ 1.0], # opacity ], [ # 23 [[0.253968, 0.217123, 0.0, 1.0]], # ambient [[1.0, 0.854922, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.872449, 0.247119, 0.254214, 1.0]], # specular [1.0], # shininess [ 1.0], # opacity ], [ # 24 [[0.00979482, 0.144029, 0.0741995, 1.0]], # ambient [[0.0402987, 0.592577, 0.305278, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0447285, 0.612254, 0.0843031, 1.0]], # specular [0.678571], # shininess [ 1.0], # opacity ], [ # 25 [[0.0901605, 0.163636, 0.0897727, 1.0]], # ambient [[0.37066, 0.672727, 0.369066, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.355787, 0.642424, 0.355787, 1.0]], # specular [0.909091], # shininess [ 1.0], # opacity ], [ # 26 [[0.0548827, 0.13582, 0.0451952, 1.0]], # ambient [[0.215415, 0.533093, 0.177391, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.272814, 0.0, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 27 [[0.0548827, 0.13582, 0.0451952, 1.0]], # ambient [[0.215415, 0.533093, 0.177391, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0, 0.591097, 0.0, 1.0]], # specular [0.0765306], # shininess [ 1.0], # opacity ], [ # 28 [[0.0, 0.139394, 0.0, 1.0]], # ambient [[0.0, 0.49697, 0.0, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.585714, 0.6, 0.0, 1.0]], # specular [0.109091], # shininess [ 1.0], # opacity ], [ # 29 [[0.226102, 0.137326, 0.0560706, 1.0]], # ambient [[0.904409, 0.549305, 0.224283, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 30 [[0.204082, 0.12971, 0.0239268, 1.0]], # ambient [[0.795918, 0.505869, 0.0933146, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.304961, 0.131827, 0.00788694, 1.0]], # specular [0.97449], # shininess [ 1.0], # opacity ], [ # 31 [[0.226102, 0.114442, 0.0852773, 1.0]], # ambient [[0.904409, 0.457768, 0.341109, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.0955906, 0.0955906, 0.0955906, 1.0]], # specular [0.078125], # shininess [ 1.0], # opacity ], [ # 32 [[0.20373, 0.0652958, 0.0403947, 1.0]], # ambient [[0.799639, 0.256286, 0.158549, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.20373, 0.0832482, 0.0832482, 1.0]], # specular [0.0714286], # shininess [ 1.0], # opacity ], [ # 33 [[0.20373, 0.0832482, 0.0615764, 1.0]], # ambient [[0.799639, 0.326749, 0.241687, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.891318, 0.364211, 0.364211, 1.0]], # specular [0.928571], # shininess [ 1.0], # opacity ], [ # 34 [[0.248649, 0.112484, 0.100302, 1.0]], # ambient [[1.0, 0.452381, 0.40339, 1.0]], # diffuse [[0.0, 0.0, 0.0, 1.0]], # emission [[0.686486, 0.396903, 0.419275, 1.0]], # specular [0.902703], # shininess [ 1.0], # opacity ], ] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Viewer.py0000644000175000017500000034315212105304612021502 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: 2000 Authors: Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI 2000 # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Viewer.py,v 1.378 2013/02/08 23:26:02 annao Exp $ # # $Id: Viewer.py,v 1.378 2013/02/08 23:26:02 annao Exp $ # import warnings import thread, threading import os import numpy import numpy.oldnumeric as Numeric import math import string import types import sys from time import time, sleep import re try: import Image except: pass import Tkinter import tkMessageBox from opengltk.OpenGL import GL from mglutil.events import Event, EventHandler from mglutil.util.callback import CallbackFunction import DejaVu from DejaVu import loadTogl from DejaVu import viewerConst from DejaVu.MaterialEditor import MaterialEditor from DejaVu.Geom import Geom from DejaVu.Camera import Camera from DejaVu.ViewerGUI import ViewerGUI from DejaVu.Clip import ClippingPlane from DejaVu.Light import Light, LightModel from DejaVu.colorTool import OneColor from DejaVu.tileRenderer import TRctx from DejaVu.Transformable import Transformable from DejaVu.Insert2d import Insert2d from DejaVu.Common2d3dObject import Common2d3dObject from DejaVu.cursors import cursorsDict # count clipping planes if hasattr( DejaVu, 'enableStereo') is False: DejaVu.enableStereo = False class SetCurrentObjectEvent(Event): def __init__(self, object): Event.__init__(self) self.object = object class SetCurrentCameraEvent(SetCurrentObjectEvent): pass class SetCurrentLightEvent(SetCurrentObjectEvent): pass class SetCurrentClipEvent(SetCurrentObjectEvent): pass class AddObjectEvent(Event): def __init__(self, object): Event.__init__(self) self.object = object class RemoveObjectEvent(AddObjectEvent): pass class ReparentObjectEvent(Event): def __init__(self, object, oldparent): Event.__init__(self) self.object = object self.oldparent = oldparent class Viewer(Tkinter.Widget, Tkinter.Misc, EventHandler): """A viewer holds a bunch of object that inherit from Geom and displays them in cameras""" def getViewerStateDefinitionCode(self, viewerName, indent='', withMode=True, rootxy=True): """Returns a list of strings containing Python code to restore the state of the viewer. The returned code will restore the state of all non- transient objects, i.e. light models, light sources, clipping planes, cameras, fog and root object. indent is the level of indentation that is desired. viewerName is the name of the Viewer object in the source code generated. """ lines = [] if withMode is True: lines.append(indent+"if mode=='viewer' or mode=='both':\n") indent += ' ' lines.append(indent+"##\n") lines.append(indent+" ## Saving State for Viewer\n") lines.append(indent+"%s.TransformRootOnly(%d)\n"%(viewerName, self.redirectTransformToRoot)) lines.append(indent+"##\n\n") lines.append(indent+"## Light Model\n") lm = self.lightModel if lm._modified: lines.append(indent+"state = %s\n"%str(lm.getState())) lines.append(indent+"%s.lightModel.Set(**state)\n\n"%( viewerName)) lines.append(indent+"## End Light Model\n\n") lines.append(indent+"## Light sources\n") for i,l in enumerate(self.lights): if not l._modified: continue lines.append(indent+"## Light Number %d\n"%i) lines.append(indent+"state = %s\n"%str(self.lights[i].getState())) lines.append(indent+"%s.lights[%d].Set(**state)\n\n"%( viewerName, i)) lines.append(indent+"## End Light sources %d\n\n"%i) lines.append(indent+"## Cameras\n") for i,c in enumerate(self.cameras): if not c._modified: continue lines.append(indent+"## Camera Number %d\n"%i) lCamState = self.cameras[i].getState() if rootxy is False: lCamState.pop('rootx') lCamState.pop('rooty') lines.append(indent+"state = %s\n"%str(lCamState)) lines.append(indent+"%s.cameras[%d].Set(**state)\n\n"%( viewerName, i)) lines.append(indent+"state = %s\n"%str( self.cameras[i].fog.getState())) lines.append(indent+"%s.cameras[%d].fog.Set(**state)\n\n"%( viewerName, i)) lines.append(indent+"## End Cameras\n\n") lines.append(indent+"## Clipping planes\n") for i,c in enumerate(self.clipP): if not c._modified: continue lines.append(indent+"state = %s\n"%str(c.getState())) lines.append(indent+"%s.clipP[%d].Set(**state)\n\n"%( viewerName, i)) lines.append(indent+"## End Clipping planes\n\n") lines.append(indent+"## Root object\n") if self.rootObject._modified: lState = self.rootObject.getState() lState.pop('protected') lines.append(indent+"state = %s\n"%str(lState)) lines.append(indent+"%s.rootObject.Set(**state)\n\n"%( viewerName)) lines.append(indent+"## End Root Object\n\n") # get material definition of root object lines.extend(self.rootObject.getGeomMaterialCode( '%s.rootObject'%viewerName, indent)) # rootObject's clipping planes lines.extend(self.rootObject.getGeomClipPlanesCode( '%s.rootObject'%viewerName, indent)) return lines def getObjectsStateDefinitionCode(self, viewerName, indent='', withMode=True, includeBinding=True): """Returns a list of strings containing Python code to restore the state of the geometry objects in the viewer. indent is the level of indentation that is desired. viewerName is the name of the Viewer object in the source code generated. """ lines = [] if withMode is True: lines.append(indent+"if mode=='objects' or mode=='both':\n") indent += ' ' lines.append(indent+"pass #needed in case there no modif\n") lines.append(indent+"##\n") lines.append(indent+"## Saving State for objects in Viewer\n") lines.append(indent+"##\n\n") for obj in self.rootObject.AllObjects(): if obj == self.rootObject: continue lines.append(indent+"## Object %s\n"%obj.fullName) if obj._modified: lines.append(indent+"state = %s\n"%str(obj.getState())) lines.append(indent+"obj = %s.FindObjectByName('%s')\n"%( viewerName, obj.fullName)) lines.append(indent+"if obj:\n") lines.append(indent+" obj.Set(**state)\n\n") if isinstance(obj, Geom): # get material definition of obj lines.extend(obj.getGeomMaterialCode('obj', indent, includeBinding=includeBinding)) # clipping planes for obj lines.extend(obj.getGeomClipPlanesCode('obj', indent)) lines.append(indent+"## End Object %s\n\n"%obj.fullName) return lines def AddCamera(self, master=None, screenName=None, classCamera=None, stereo='none', num=None, cnf={}, **kw): """Add one more camera to this viewer""" if num is None: num = len(self.cameras) if classCamera is None: classCamera = Camera name = 'camera '+str(num) else: name = classCamera.__name__+str(num) cameraOwnsMaster = False if not master: ## if screenName is None: ## if os.environ.has_key("DISPLAY"): ## screenName = os.environ["DISPLAY"] ## if screenName is not None: ## master = Tk(screenName=screenName) ## else: ## master = Tk() master = Tkinter.Toplevel(self.master) master.title(name) cameraOwnsMaster = True #else: # assert isinstance(master, Widget) # simulate the setting of TCLLIPATH # we shoudl really check is the directory where we know togl is # isn't already in that path # path = master.tk.globalgetvar('auto_path') # master.tk.globalsetvar('auto_path', os.path.join(sys.exec_prefix, # 'lib')+ ' '+ path ) # master.tk.call('package', 'require', 'Togl') #else: # assert isinstance(master, Widget) ## # simulate the setting of TCLLIPATH ## # we should really check is the directory where we know togl is ## # isn't already in that path ## path = master.tk.globalgetvar('auto_path') ## # master.tk.globalsetvar('auto_path', os.path.join(sys.exec_prefix, ## # 'lib')+ ' '+ path ) ## import opengltk ## toglpath = os.path.join(opengltk.__path__[0], 'OpenGL/Tk/ ') ## master.tk.globalsetvar('auto_path', (toglpath,) + path ) ## #master.tk.globalsetvar('auto_path', toglpath) ## #print master.tk.globalgetvar('auto_path') ## master.tk.call('package', 'require', 'Togl') #kw['takefocus'] = 1 kw['stereo'] = stereo c = classCamera(master, screenName, self, num, cnf=cnf, **kw) if hasattr(c.frame.master,"protocol"): c.frame.master.protocol("WM_DELETE_WINDOW",self.dialog) c.eventManager.AddCallback('', self.modifierDown) c.eventManager.AddCallback('', self.modifierUp) c.eventManager.AddCallback('R', self.Reset_cb_arg) c.eventManager.AddCallback('r', self.Reset_cb_arg) c.eventManager.AddCallback('A', self.AutoDepthCue) c.eventManager.AddCallback('a', self.AutoDepthCue) c.eventManager.AddCallback('N', self.Normalize_cb_arg) c.eventManager.AddCallback('n', self.Normalize_cb_arg) c.eventManager.AddCallback('C', self.Center_cb_arg) c.eventManager.AddCallback('c', self.Center_cb_arg) c.eventManager.AddCallback('D', self.Depth_cb_arg) c.eventManager.AddCallback('d', self.Depth_cb_arg) c.eventManager.AddCallback('T', self.toggleTransformRootOnly) c.eventManager.AddCallback('t', self.toggleTransformRootOnly) c.eventManager.AddCallback('L', self.toggleOpenglLighting) c.eventManager.AddCallback('l', self.toggleOpenglLighting) c.eventManager.AddCallback('O', self.SSAO_cb_arg) c.eventManager.AddCallback('o', self.SSAO_cb_arg) c.ownMaster = cameraOwnsMaster if self.GUI is not None: self.GUI.bindModifersToTransformInfo(master) self.cameras.append( c ) if len(self.cameras)==1: self.currentCamera = c c.hasBeenCurrent = 1 #self.trackball = c.trackball c.frame.config( background = "#900000" ) # make the trackball transform the current object if self.rootObject: self.BindTrackballToObject(self.rootObject) c.firstRedraw = True c.Activate() return c def dialog(self): # t="Do you Wish to Quit?" # from SimpleDialog import SimpleDialog # d = SimpleDialog(self.currentCamera, text=t, # buttons=["Quit","Cancel"], # default=0, title="Quit?") # # ok=d.go() ok = tkMessageBox.askokcancel("Quit?","Do you Wish to Quit?") if ok: self.quit_cb() else: return def quit_cb(self): self.currentCamera.frame.master.destroy() def _DeleteCamera(self, camera): """Remove the given camera in the right order """ #print 'Viewer._DeleteCamera ', camera # Check if this camera shareCTX with other camera. if hasattr(camera, 'shareCTXWith'): while len(camera.shareCTXWith): cam = camera.shareCTXWith[0] self._DeleteCamera(cam) camera.destroy() if camera.ownMaster: camera.frame.master.destroy() else: camera.frame.destroy() self.cameras.remove(camera) for c in self.cameras: if hasattr(c, 'shareCTXWith'): c.shareCTXWith.remove(camera) def DeleteCamera(self, camera): """ Remove the given camera from the viewer and takes care of the dpyList if camera is cameras[0] """ # #delete NPR rendering toplevel # if camera.imCanvastop: # camera.imCanvastop.destroy() # camera.imCanvas = None # camera.imCanvas1 = None # camera.imCanvas2 = None # camera.imCanvas3 = None # Remove the camera from the list of cameras associated to # the viewer. camIndex = self.cameras.index(camera) # the current openGL context has been destroyed so # the dpyList need to be destroyed only if the CTX is not # shared by any other camera. if camIndex == 0: self.objectsNeedingRedo = {} for g in self.rootObject.AllObjects(): g.deleteOpenglList() self.objectsNeedingRedo[g] = None self._DeleteCamera(camera) # If this camera is the current camera if self.currentCamera == camera: if len(self.cameras) == 0: # There is no more cameras then set currentCamera to None self.currentCamera = None else: # Set the current Camera to be the first camera of the list. self.currentCamera = self.cameras[0] def InitLighting(self, camera): """Set up some basic lighting (single infinite light source) """ #print "InitLighting" camera.Activate() self.lightModel = LightModel(self, twoSide=True) # Graham light model # 'key light': front, top left (80%) self.lights[0].Set( enabled=viewerConst.YES, direction=(-0.7, 0.8, 1.4, 1.), diffuse = [0.75, 0.75, 0.75, 1.], specular=(.8, .8, .65, 1.), ambient=(.12, .12, .12, 1.), tagModified=False) # 'fill light': front, top right, warmer (15-30%) self.lights[1].Set( enabled=viewerConst.YES, direction=(9., .5, 3., 1.), diffuse=(.35,.25,.175,1.), specular=(.0,.0,.0,1.), ambient=(.12, .12, .12, 1.), tagModified=False ) # 'reflective or back': back, bottom center, cooler (10-30%) self.lights[2].Set( enabled=viewerConst.YES, direction=(0., -.45, -.35, 1.), diffuse=(.4,.5,.75,1.), specular=(.0,.0,.0,1.), ambient=(.12, .12, .12, 1.), tagModified=False ) self.currentLight = self.lights[0] self.currentLight.hasBeenCurrent = 1 #for l in self.lights: # activate is needed else lights other than 0 seem to tbe lost # self.cameras[0].Activate() # l.apply() def findGeomsByName(self, pat, parent=None): """find geoms whose name matches the string pat, a list of matches is returned, option parent: if parent, search only children of parent. see also: FindObjectByName""" # here 'root|mol|MSMS-MOL' is interepreter as either of the strings # (in FindObjectByName | is interpreted as a parent child separator) if parent is None: allObjs = self.rootObject.AllObjects() else: allObjs = parent.AllObjects() match = re.compile(pat) result = {} for object in allObjs: if match.search(object.name): result[object] = 1 for c in object.children: if match.search(c.name): result[c] = 1 return result.keys() def __init__(self, master=None, nogui=0, screenName=None, guiMaster=None, classCamera=None, showViewerGUI=True, autoRedraw=True, verbose=True, cnf={}, **kw): """Viewer's constructor """ EventHandler.__init__(self) #print "Viewer.__init__" self.isInitialized=0 self.suspendRedraw = True # set to True to Prevent redrawing name = 'camera0' self.ownMaster = False # is set to True if this Viewer creates its own Tk if guiMaster is not None and master is None: master = guiMaster #while not isinstance(master, Tk) or isinstance(master, Toplevel): # master = master.master master = master.winfo_toplevel() master = Tkinter.Toplevel(master) self.ownMaster = True withdrawDefaultRoot = Tkinter._default_root is None if not master: # DISABLE DISPLAY handling as it would require creating a new # Tk, and this creates many problems, including that Pmw uses # Tkinter._default_root in many places #if screenName is None: # screenName = os.environ.get("DISPLAY", None) #if screenName is not None: # master = Tk(screenName=screenName) # self.ownMaster = True # #print 'new Tk', repr(master) #else: # master = Toplevel() # self.ownMaster = True #print 'new Tk', repr(master) master = Tkinter.Toplevel() self.ownMaster = True if guiMaster is None and self.ownMaster: guiMaster = Tkinter.Toplevel(master) master.title(name) else: assert isinstance(master, Tkinter.BaseWidget) or isinstance(master, Tkinter.Tk) if withdrawDefaultRoot: Tkinter._default_root.withdraw() # string var used to decide what the trackball is moving self.Xform = Tkinter.StringVar(value="Object") self.contourTk = Tkinter.BooleanVar() #print 'master', repr(master) #print 'guiMaster', repr(guiMaster) self.master = master loadTogl(master) self.redoDspLst = 0 # set to 1 to for Display List re-calculation if sys.platform == 'osf1V4': # for some reason using nested display lists on DecAlpha OpenGL # freezes the viewer self.useMasterDpyList = 0 else: self.useMasterDpyList = 1 self.oldUseMasterDpyList = self.useMasterDpyList self.singleDpyList = False # when false, any object can have a dpyList # which is called from the master # when True, only the master list is built self.uniqID = '_'+str(time()) # timing self.numberOfRedraws = 0 self.timeButonDown = 0 self.timeButonUp = 0 self.lastFrameTime = 0 self.avgFrameRate = 0. # average frame rate between button down and # button up. Compute in tackball self.autoRedraw = autoRedraw # identifier returned by last called to after_idle in autoRedraw mode # it is set to None of no autoredraw has been posted self.pendingAutoRedrawID = None self.rootObject = None self.currentObject = self.rootObject self.lastObjectNumber = 1 self.lastPick = None self.lastPickedCamera = None self.currentLight = None self.lights = [] self.GUI = None self.redirectTransformToRoot = 0 self.Reset_cb = self.ResetCurrentObject self.Normalize_cb = self.NormalizeCurrentObject self.Center_cb = self.CenterCurrentObject self.Delete_cb = self.DeleteCurrentObject self.redrawLock = thread.allocate_lock() self.objectsNeedingRedo = {} self.materialEditor = None self.spinVar = Tkinter.IntVar() self.spinVar.set(DejaVu.defaultSpinningMode) self.spinCallBack = None # create a first camera self.cameras = [ ] c = Viewer.AddCamera(self, master, screenName, classCamera, num=0, cnf=cnf, **kw) #self.GLextensions = string.split(GL.glGetString(GL.GL_EXTENSIONS)) #self.GLversion = GL.glGetString(GL.GL_VERSION) #self.GLvendor = GL.glGetString(GL.GL_VENDOR) if verbose: print 'OpenGL-based graphics' print ' GL_VENDOR', GL.glGetString(GL.GL_VENDOR) print ' GL_RENDERER', GL.glGetString(GL.GL_RENDERER) print ' GL_VERSION', GL.glGetString(GL.GL_VERSION) #self.hasOffsetExt = "GL_EXT_polygon_offset" in self.GLextensions # Find out how many clipping planes OpenGL defines maxClipP = 0 for i in range(6): try: cpn = getattr(GL, "GL_CLIP_PLANE%d"%i) ClippingPlane.clipPlaneNames.append(cpn) maxClipP +=1 except AttributeError: break # Find out how many clipping planes OpenGL "thinks" it supports #maxClipP = min(int(GL.glGetDoublev(GL.GL_MAX_CLIP_PLANES)[0]), 6) # Find out how many light sources maxLights = int(GL.glGetDoublev(GL.GL_MAX_LIGHTS)[0]) if maxLights > 8: print 'WARNING: Reducing number of light sources from %d to 8' % \ maxLights maxLights = 8 # Decides if the call to enable GL_LIGHTNING will be considered self.OverAllLightingIsOn = Tkinter.IntVar() self.OverAllLightingIsOn.set(1) # create the array of clipping plane objects # these objects can be added to the list of active clippign planes # for each geometry on a given side self.maxClipP = maxClipP self.clipP = [] self.activeClippingPlanes = 0 # number of active clipping planes self.cappedGeoms = [] # will hold a list of (geom, clipp) pairs self.activeScissor = 0 # number of active scissors # create the light sources self.maxLights = maxLights self.lights = [] for i in range(self.maxLights): l = Light(i, self) self.lights.append( l ) l.viewer = self self.currentLight = None self.InitLighting(c) # create the material editor self.materialEditor = MaterialEditor(None, self) self.materialEditor.dismissTk.grid_forget() self.materialEditor.dismiss() # register Object that have their own OpenGL context but need to have # the same lighting model and lights for l in self.lights: l.applyTo = [self.materialEditor] self.lightModel.applyTo = [self.materialEditor] # lists of object not using a dispalylist (managed in ReallyRedraw) self.noDpyListOpaque = [] self.noDpyListTransp = [] # create the root objects root = Geom('root', protected=True, shape=(0,0), inheritPointWidth=0, inheritLighting=0, inheritLineWidth=0, inheritStippleLines=0, inheritStipplePolygons=0, inheritFrontPolyMode=0, inheritBackPolyMode=0, inheritShading=0, inheritSharpColorBoundaries=0, inheritCulling=0, inheritXform=0) self.rootObject = root self.rootObject.viewer = self root.materials[GL.GL_FRONT].InitDefault() root.materials[GL.GL_BACK].InitDefault() root.inheritMaterial = viewerConst.NO root.inheritFrontPolyMode = viewerConst.NO root.inheritBackPolyMode = viewerConst.NO root.inheritShading = viewerConst.NO root.inheritLighting = viewerConst.NO root.inheritSharpColorBoundaries = viewerConst.NO root.inheritCulling = viewerConst.NO self.rootObject = root self.currentObject = root root.clipSide = [1]*self.maxClipP root.hasBeenCurrent = 1 for i in range(self.maxClipP): #from DejaVu.csgClip import CsgClippingPlane #cp = CsgClippingPlane(self.rootObject, i, self) cp = ClippingPlane(self.rootObject, i, self) self.clipP.append(cp) if self.maxClipP: self.currentClip = self.clipP[0] else: self.currentClip = None # # add geometry for picking visual feedback # from DejaVu.Spheres import Spheres self.showPickedVertex = 1 # self.pickVerticesSpheres = Spheres('pickSpheres', quality=10, # radii = 0.2, # materials = ((0,1,0),), protected=True) # self.pickVerticesSpheres.listed = 0 # self.pickVerticesSpheres.visible = 1 # self.pickVerticesSpheres.pickable = 0 # self.pickReminiscence = 10 # in 10th of seconds # self.AddObject(self.pickVerticesSpheres) # find out if PolygonOffset is supported self.hasOffsetExt = True self.polyOffset = None # OpenGL function to call for PolygonOffset try: self.polyOffset = GL.glPolygonOffset except AttributeError: try: self.polyOffset = GL.glPolygonOffsetEXT except AttributeError: self.hasOffsetExt = False # see if it is actually implemented if self.hasOffsetExt: try: self.polyOffset(1.0, 1.0) except ValueError: self.viewer.hasOffsetExt = False ## if cnf.has_key("addScenarioButton"): ## self.addScenarioButton = cnf["addScenarioButton"] ## else: ## self.addScenarioButton = True # create the ViewerGui if showViewerGUI: self.GUI = ViewerGUI(self, maxLights, maxClipP, nogui=nogui, master=guiMaster) #self.GUI.CameraBackgroundColor = self.CurrentCameraBackgroundColor #self.GUI.LightColor = self.CurrentLightColor #self.GUI.ClipColor = self.CurrentClipColor #self.GUI.ObjectFrontColor = self.CurrentObjectFrontColor #self.GUI.ObjectBackColor = self.CurrentObjectBackColor #self.GUI.LightModelColor = self.LMColor self.GUI.addObject(self.rootObject, None) self.GUI.bindResetButton( self.Reset_cb) self.GUI.bindNormalizeButton( self.Normalize_cb) self.GUI.bindCenterButton( self.Center_cb) self.GUI.bindDeleteButton( self.Delete_cb) ## self.GUI.Exit = self.__del__ if nogui and isinstance(self.GUI.root, Tkinter.Toplevel): self.GUI.withdraw() #self.GUI.addObject(self.pickVerticesSpheres, None) #self.GUI.showPickedVertex.set(self.showPickedVertex) # this line causes networks wih viewers not to appear completely # (missing connections, which appear only after a window takes focus # MS march 26, 03 #self.master.wait_visibility() # flags to track modifier positions self.kbdModifier = { 'Shift_L':0, 'Shift_R':0, 'Control_L':0, 'Control_R':0, 'Alt_L':0, 'Alt_R':0, 'Meta_L':0, 'Meta_R':0 } # list of functions to be called when picking occurs self.pickingFunctions = [] self.AddPickingCallback(self.unsolicitedPick) self.pickLevel = 'vertices' #can also be 'parts' self.isInitialized=1 self.needsRedraw = True self.hasRedrawn = False # tiled rendering self.tileRender = False self.tileRenderCtx = None self.tileRenderFinalWidth = 0 self.tileRenderFinalHeight = 0 self.tileRenderBorder = 0 self.tileRenderOutput = None self.tileRenderBuffer = None self.tileCount = None self.SetCurrentObject(self.rootObject) self.BindTrackballToObject(self.rootObject) if self.autoRedraw: self.pendingAutoRedrawID = self.master.after_idle(self.ReallyRedraw) self.rootObject._modified = False #print "DejaVu.enableStereo", DejaVu.enableStereo if DejaVu.enableStereo is True: self.activeStereoSupport = self.currentCamera.activeStereoSupport() else: self.activeStereoSupport = False #print "self.activeStereoSupport", self.activeStereoSupport #make sure that at the end of the init the current context is the one of the current camera self.currentCamera.tk.call(self.currentCamera._w, 'makecurrent') # create fake geometry to find out if VBO are supported from DejaVu.IndexedPolygons import IndexedPolygons fake = IndexedPolygons('test', vertexArrayFlag=True, vertices=((0,0,0),)) if verbose: print 'Enable VBO:', DejaVu.enableVBO self.suspendRedraw = False # set to True to Prevent redrawing def update(self): self.master.update() def saveViewerState(self, filename): """Save the source code to restore the state of all the Viewer, i.e. Cameras, Fog, LightModel, Lights, Clipping Planes and rootObject """ code = self.getViewerStateDefinitionCode('vi') f = open(filename, 'w') dum = map(lambda x, f=f: f.write("%s"%x), code) f.close() def saveObjectsStates(self, filename): """Save the source code to restore the state of all objects in the viewer except for rootObject. """ code = self.getObjectsStateDefinitionCode('vi') f = open(filename, 'w') dum = map(lambda x, f=f: f.write("%s"%x), code) f.close() def saveViewerAndObjectsStates(self, filename): """Save the source code to restore the state of all objects in the Viewer's""" f = open(filename, 'w') code = self.getViewerStateDefinitionCode('vi') dum = map(lambda x, f=f: f.write("%s"%x), code) code = self.getObjectsStateDefinitionCode('vi') dum = map(lambda x, f=f: f.write("%s"%x), code) f.close() def startTileRendering(self, border=0, outputFile='test.jpg', width=None, height=None, backBuffer=True, checkeredBackground=False): self.stopAutoRedraw() lDepthArray = self.currentCamera.GrabZBufferAsArray() lDepthArray = lDepthArray.ravel() zmin = min(lDepthArray) zmax = max(lDepthArray) self.tileRender = True self.tileRenderCtx = TRctx(zmin, zmax) self.tileRenderCtx.checkeredBackground = checkeredBackground # set to true to see tiles rendered in foreground self.tileRenderCtx.backBuffer = backBuffer # set to true to create colors tiles background from black to white self.tileRenderOutput = outputFile if width is not None: self.tileRenderFinalWidth = width # self.tileRenderFinalHeight=None if height is not None: self.tileRenderFinalHeight = height # self.tileRenderFinalWidth = None if height is None and width is None: self.tileRender = False def stopTileRendering(self): self.tileRender = False self.startAutoRedraw() def unsolicitedPick(self, pick): """treat and unsollicited picking event""" ## if self.isShift(): ## self.centerCurrentObject(pick) ## elif self.isControl(): ## self.selectGeom(pick) ## else: ## for object, items in pick.hits.items(): ## print "Object", object.name, pick.type, items for object, items in pick.hits.items(): print "Object", object.name, pick.type, items def isShift(self): return self.kbdModifier['Shift_L'] or self.kbdModifier['Shift_R'] def isControl(self): return self.kbdModifier['Control_L'] or self.kbdModifier['Control_R'] def isAlt(self): return self.kbdModifier['Alt_L'] or self.kbdModifier['Alt_R'] def getModifier(self): if self.kbdModifier['Shift_L']: return 'Shift_L' elif self.kbdModifier['Control_L']: return 'Control_L' elif self.kbdModifier['Alt_L']: return 'Alt_L' elif self.kbdModifier['Shift_R']: return 'Shift_R' elif self.kbdModifier['Control_R']: return 'Control_R' elif self.kbdModifier['Alt_R']: return 'Alt_R' else: return 'None' def modifierDown(self, event): """track changes in SHIFT, CONTROL, ALT kyes positions""" #print "event.keysym", event.keysym if event.keysym in ['Shift_L', 'Shift_R', 'Control_L', 'Control_R', 'Alt_L', 'Alt_R']: self.kbdModifier[event.keysym] = 1 # grab all event to make sure get the key release event even # if the mouse is outside the application #self.currentCamera.master.grab_set_global() #self.master.grab_set_global() def modifierUp(self, event): """track changes in SHIFT, CONTROL, ALT keys positions""" #print 'modifier up', event.keysym if event.keysym in ['Shift_L', 'Shift_R', 'Control_L', 'Control_R', 'Alt_L', 'Alt_R']: self.currentCamera.configure(cursor=cursorsDict['default']) self.kbdModifier[event.keysym] = 0 # release the grab self.currentCamera.master.grab_release() #self.master.grab_release() ## def __del__(self): ## """Viewer's destructor""" ## self.GUI.root.destroy() ## for c in self.cameras: ## c.frame.master.destroy() def Exit(self): #if sys.platform != "win32": # FIX this: the following line causes # "PyEval_Restore_Thread: Null tstate" error on Windows # when Python interpreter quits. # Python2.6.5 , numpy 1.4.1, Togl 1.7 #if self.GUI: #self.GUI.occlusionCamera.destroy() self.materialEditor._destroy() if self.GUI: # When "occlusionCamera" class was commented out # "PyEval_Restore_Thread: Null tstate" error on Windows returned # ( happens when Python interpreter quits). # The following line seems to fix this problem. self.GUI.GraphToolpanel.destroy() # self.GUI.root.destroy() if self.autoRedraw: self.stopAutoRedraw() sleep(0.1) self.master.update() if len(self.cameras) > 1: lReversedListOfCameras = self.cameras[:] lReversedListOfCameras.reverse() else: lReversedListOfCameras = self.cameras[:] for c in lReversedListOfCameras: self._DeleteCamera(c) if self.ownMaster: self.master.destroy() def processPicking(self, pick): """call all functions that need to be called after something has been picked""" for func in self.pickingFunctions: func(pick) def AddPickingCallback(self, func): """Add function func to the list of picking callback fucntions""" if func not in self.pickingFunctions: self.pickingFunctions.append(func) def RemovePickingCallback(self, func, modifier=None): """Delete function func from the list of picking callbacks""" if type(func)==types.StringType: findFunc = self.currentCamera.eventManager.FindFunctionByName func = findFunc(func, self.pickingFunctions) if not func: return self.pickingFunctions.remove(func) def SetPickingCallback(self, func): """Replace the functions to be called after a picking event. Return the list of functions that got replaced""" save = self.pickingFunctions # used to restore save callbacks sent back earlier if type(func)==types.ListType: self.pickingFunctions = func else: self.pickingFunctions = [func] return save ## def selectGeom(self, pick): ## """Picking call back""" ## l = len(pick.hits.keys()) ## if l == 0: ## if pick.camera.currentTransfMode == 'Object': ## self.BindTrackballToObject(self.rootObject) ## else: ## self.BindTrackballToObject(self.currentObject) ## return ## if l > 1: ## print "WARNING selectPick does not work for multiple objects""" ## return ## object = pick.hits.keys()[0] ## if isinstance(object, Geom): ## self.BindTrackballToObject(object) ## elif isinstance(object, ClippingPlane): ## self.BindTrackballToClip( object ) ## elif isinstance(object, Light): ## self.BindTrackballToLight( object ) ## def centerCurrentObject(self, pick): ## """Center the world on the picked vertex""" ## if pick.type=='parts': ## self.vf.message("WARNING: centering for picking done on parts is not implmented.") ## return ## g = Numeric.zeros( (3), 'f' ) ## object = self.rootObject ## inv = object.GetMatrixInverse() ## for obj, vertInd in pick.hits.items(): ## if len(vertInd)==0: ## print 'WARNING: object',o.name,' is not vertex pickable' ## else: ## m = Numeric.dot( inv, obj.GetMatrix() ) ## vert = obj.vertexSet.vertices * m ## vertsel = Numeric.take( vert, vertInd ) ## g = g + Numeric.sum(vertsel)/len(vertsel) ## object.SetPivot( g ) def toggleTransformRootOnly(self, event=None): self.TransformRootOnly(not self.redirectTransformToRoot) def TransformRootOnly(self, value): """if value is true, all 3D transformations are redirected to the root object, and all objects added subsequently are have their transformation redirected automatically""" root = self.rootObject objs = root.AllObjects() objs.remove(root) objsTransformableOnly = [] for o in objs: if isinstance(o, Transformable) is True: objsTransformableOnly.append(o) if value: for o in objsTransformableOnly: o.RedirectTransformTo(root) self.redirectTransformToRoot = 1 else: for o in objsTransformableOnly: o.RedirectTransformTo(None) self.redirectTransformToRoot = 0 # since the root transormation might have changed we need to # recompute R and Ri for the current Object if self.currentObject is not self.rootObject: if isinstance(self.currentObject, Transformable): self.currentObject.FrameTransform(self.currentCamera) if self.GUI: self.GUI.moveRootOnly.set(value) def ResetCurrentObject(self): """Reset the current's object transformation """ #self.trackball.autospin = 0 if self.redirectTransformToRoot: self.rootObject.ResetTransformation() else: self.currentObject.ResetTransformation() self.Redraw() def Reset_cb_arg(self, event): """Function to be bound to the GUI's reset widget""" self.Reset_cb() def AutoDepthCue(self, nearOffset=0.0, farOffset=0.0): """ """ self.currentCamera.AutoDepthCue() self.Redraw() def NormalizeCurrentObject(self): """Normalize the current object or RootObject """ ## ## MS Jan 31 2013 I was unable to get the normalize center to work properly on ## object when the current object was not the root. The workaround is to ## set the root to be the current onject and hide all but current objects to perform ## normalize then restore current object lObject = self.rootObject if self.redirectTransformToRoot or self.currentObject==self.rootObject: hidden = None else: hidden = [] for g in self.rootObject.VisibleObjects(): #print g.name , g.visible if g is not self.currentObject and g.visible and not self.AreYouMyDescendant(self.currentObject, g): g.visible = False hidden.append(g) current = self.currentObject self.SetCurrentObject(self.rootObject) #print "CURRENT ROOT", self.currentObject #print self.rootObject.VisibleObjects() if isinstance(lObject, Transformable): self.rootObject.Set(scale=(1.,1.,1.)) mini, maxi = lObject.ComputeBB(self.currentCamera) g = Numeric.add.reduce( (mini, maxi) ) * .5 # center of BoundingBox if lObject == self.rootObject: self.rootObject.ConcatTranslation( -g[:3] ) #* lObject.Si ) else: self.rootObject.SetTranslation( -g[:3] ) #* lObject.Si ) lBox = maxi - mini lHalfObject = max(lBox)/2. if lHalfObject == 0.: lHalfObject = 1. c = self.currentCamera c.Set(fov=c.fovyNeutral) lNewDist = lHalfObject / math.tan(c.fovy/2*math.pi/180.0) c.lookFrom = Numeric.array( ( 0., 0., c.nearDefault+lNewDist+lHalfObject ) ) c.lookAt = Numeric.array((0.,0.,0.)) c.direction = c.lookAt - c.lookFrom c.AutoDepthCue(object=lObject) else: # Insert2d self.lObject.ResetSize() if hidden: self.SetCurrentObject(current) for g in hidden: g.visible = True self.Redraw() def Normalize_cb_arg(self, event): """Function to be bound to the GUI's normalize widget """ self.Normalize_cb() def CenterCurrentObject(self): """Center the current object on the center of gravity of its subtree in "redirect transform to root" mode, root is recentered on the selected geometry """ #print "self.currentObject", self.currentObject if isinstance(self.currentObject, Transformable): #mini, maxi = self.currentObject.BoundingBoxSubtree() mini, maxi = self.currentObject.ComputeBB(self.currentCamera) #g = Numeric.add.reduce( (mini, maxi) ) / 2.0 # center of BoundingBox g = mini + ( (maxi-mini) *0.5 ) # center of BoundingBox g = Numeric.concatenate( (g, [1.0]) ) # FIXME won't work with instance matrices m = self.currentObject.GetMatrixInverse(root=self.currentObject) g = Numeric.dot(m, g)[:3] if self.redirectTransformToRoot and self.currentObject != self.rootObject: self.rootObject.SetPivot( self.currentObject.translation + g ) else: self.currentObject.SetPivot( g ) else: # Insert2d self.currentObject.ResetPosition() #self.Redraw() def get3DPointFromPick(self,event): """Compute 3D point from pick event. point, background <- get3DPointFromPick(event) Returns a 3D point and a boolean which is True if picking occured on background """ if isinstance(self.currentObject, Transformable): winx = event.x winy = self.currentCamera.height - event.y g, background = self.currentCamera.xyzFromPixel(winx, winy) g = Numeric.concatenate( (g, [1.0]) ) # FIXME won't work with instance matrices if self.redirectTransformToRoot or \ self.currentObject==self.rootObject: m = self.rootObject.GetMatrixInverse(root=self.rootObject) g = Numeric.dot(m, g)[:3] else: m = self.currentObject.GetMatrixInverse( root=self.rootObject) g = Numeric.dot(m, g)[:3] return g, background def pivotOnPixel(self, event): #print "pivotOnPixel" g, background = self.get3DPointFromPick(event) #print 'pivotOnPixel setting pivot', background, g if not background: # not background pick if self.redirectTransformToRoot or \ self.currentObject == self.rootObject: self.rootObject.SetPivot( g ) else: self.currentObject.SetPivot( g ) def Center_cb_arg(self, event): """Function to be bound to the GUI's center widget""" self.Center_cb() def _FocusCameraBB(self): cam = self.currentCamera dtime = time() - self.focusTimeStart steps = self.steps i = (dtime/self.focusDuration)*steps cam.Set(fov=cam.fovy + self.diff_fovy/float(steps)) self.rootObject.ConcatTranslation( self.diffVect[:3]/float(steps)) lNewDist = self.lHalfObject / math.tan(cam.fovy/2*math.pi/180.0) newDist = cam.nearDefault+lNewDist+self.lHalfObject dist = self.oldLookFrom*(steps-i-1.)/steps + newDist*(i+1.)/steps cam.lookFrom = Numeric.array( ( 0., 0., dist ) ) cam.direction = cam.lookAt - cam.lookFrom self.OneRedraw() if i 1: lFovyFactor = math.pow(lFovyFactor, 1.5) #lDistanceFactor = (c.far - c.near) * .001 # FIXME this will not work if we rotate the camera # using c.lookFrom[2] - c.lookAt[2] so taht translation is the same # regardless of distance of camera to scene lDistanceFactor = (c.lookFrom[2] - 0.0) * .001 lDistanceFactor = math.exp(lDistanceFactor) - 1 lFactor = lDistanceFactor * lFovyFactor t = (transXY[0] * lFactor, transXY[1]*lFactor, 0.0 ) if c.currentTransfMode == 'Clip': self.currentClip.ConcatTranslation( t ) else: self.currentObject.ConcatTranslation( t ) self.Redraw() def screenTranslateCurrentObjectXY(self, event, matrix, transXY, transZ): """Add the translation trans to the current object """ c = self.currentCamera lFovyFactor = c.fovy / c.fovyNeutral if lFovyFactor > 1: lFovyFactor = math.pow(lFovyFactor, 1.5) lDistanceFactor = (c.far - c.near) * .001 lDistanceFactor = math.exp(lDistanceFactor) - 1 lFactor = lDistanceFactor * lFovyFactor t = (transXY[0] * lFactor, transXY[1]*lFactor, 0.0 ) if c.currentTransfMode == 'Clip': self.currentClip.screenConcatTranslation( t ) else: # not implemented yet self.currentObject.ConcatTranslation( t ) self.Redraw() def TranslateCurrentObjectZ(self, event, matrix, transXY, transZ): """Add the translation trans to the current object """ if isinstance(self.currentObject, Transformable): c = self.currentCamera lFovyFactor = c.fovy / c.fovyNeutral if lFovyFactor > 1: lFovyFactor = math.pow(lFovyFactor, 1.5) lDistanceFactor = (c.far - c.near) * .001 lDistanceFactor = math.exp(lDistanceFactor) - 1 lFactor = lDistanceFactor * lFovyFactor * .5 t = (0.0, 0.0, transZ*lFactor) if c.currentTransfMode == 'Clip': self.currentClip.ConcatTranslation( (transZ*lFactor, 0., 0.) ) else: self.currentObject.ConcatTranslation( t ) self.Redraw() def screenTranslateCurrentObjectZ(self, event, matrix, transXY, transZ): """Add the translation trans to the current object """ if isinstance(self.currentObject, Transformable): c = self.currentCamera lFovyFactor = c.fovy / c.fovyNeutral if lFovyFactor > 1: lFovyFactor = math.pow(lFovyFactor, 1.5) lDistanceFactor = (c.far - c.near) * .001 lDistanceFactor = math.exp(lDistanceFactor) - 1 lFactor = lDistanceFactor * lFovyFactor * .5 t = (0.0, 0.0, transZ*lFactor) if c.currentTransfMode == 'Clip': self.currentClip.screenConcatTranslation( t ) else: # not implemented yet self.currentObject.ConcatTranslation( t ) self.Redraw() def ScaleCurrentObject(self, event, matrix, transXY, transZ): """Scale the current object""" scaleFactor = max(0.001, 1.0 + transZ*0.01) if scaleFactor < 0.001: scaleFactor = 0.001 self.currentObject.ConcatScale(scaleFactor) self.Redraw() def CurrentObjectFrontColor(self, prop, value): """Method to be bound to a GUI widget""" if value: self.currentObject.Set( materials = (value,), propName=prop ) def CurrentObjectBackColor(self, prop, value): """Method to be bound to a GUI widget""" if value: self.currentObject.Set( materials = (value,), propName=prop, polyFace=GL.GL_BACK) def CurrentObjectOpacity(self, val): """Method to be bound to a GUI widget""" if val: self.currentObject.Set( opacity = val ) def BindTrackballToClip(self, c, allCameras=None): """Bind trackball to the current clipping plane""" self.useMasterDpyList = self.oldUseMasterDpyList if c is None: return if not isinstance(c, ClippingPlane): raise AttributeError ('first parameter has to be an instance\ of ClippingPlane') self.SetCurrentClip(c) if allCameras: for c in self.cameras: c.bindAllActions('Clip') ## c.trackball.B2motion = self.RotateCurrentClipPlane ## c.trackball.B3motion = self.TranslateCurrentClipPlane ## c.trackball.ShiftB3motion = c.trackball.NoFunc ## c.trackball.ShiftB2motion = self.ScaleCurrentClipPlane self.Reset_cb = self.ResetCurrentClipPlane if self.GUI: self.GUI.bindResetButton( self.Reset_cb) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Clip' else: c = self.currentCamera c.bindAllActions('Clip') ## c.trackball.B2motion = self.RotateCurrentClipPlane ## c.trackball.B3motion = self.TranslateCurrentClipPlane ## c.trackball.ShiftB3motion = c.trackball.NoFunc ## c.trackball.ShiftB2motion = self.ScaleCurrentClipPlane self.Reset_cb = self.ResetCurrentClipPlane if self.GUI: self.GUI.bindResetButton( self.Reset_cb) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Clip' self.Xform.set(c.currentTransfMode) if self.GUI: self.GUI.fillTransformInfo_cb() def ResetCurrentClipPlane(self): """Reset the current clipping plane's transformation""" self.currentClip.ResetTransformation() self.Redraw() def RotateCurrentClipPlane(self, event, matrix, transXY, transZ): """Apply rotation matrix to the current clipping plane""" c = self.currentClip c.ConcatRotation(matrix) self.Redraw() # def TranslateCurrentClipPlane(self, event, matrix, transXY, transZ): # """Apply translation trans to the current clipping plane""" # ## clip = self.currentClip ## t = (transXY[0]*0.05, transXY[1]*0.05, 0.0 ) ## clip.ConcatTranslation( t ) ## self.Redraw() # # c = self.currentCamera # lFovyFactor = c.fovy / c.fovyNeutral # if lFovyFactor > 1: # lFovyFactor = math.pow(lFovyFactor, 1.5) # lDistanceFactor = (c.far - c.near) * .001 # lDistanceFactor = math.exp(lDistanceFactor) - 1 # lFactor = lDistanceFactor * lFovyFactor # t = (transXY[0] * lFactor, transXY[1]*lFactor, 0.0 ) # self.currentClip.ConcatTranslation( t ) # self.Redraw() def ScaleCurrentClipPlane(self, event, matrix, transXY, transZ): """Scale clipping plane representation""" scaleFactor = max(0.001, 1.0 + transZ*0.01) if scaleFactor < 0.001: scaleFactor = 0.001 self.currentClip.ConcatScale(scaleFactor) self.Redraw() def CurrentClipColor(self, col): """Method to be bound to a GUI widget""" if col: self.currentClip.Set( color = col ) self.currentCamera.Redraw() def BindTrackballToCamera(self, c, allCameras=None): """Bind the trackball to the current camera""" self.useMasterDpyList = self.oldUseMasterDpyList if not isinstance(c, Camera): raise AttributeError('first parameter has to be an instance of \ Camera') self.SetCurrentCamera(c) if allCameras: for c in self.cameras: c.bindAllActions('Camera') ## c.trackball.B2motion = self.RotateCurrentCamera ## c.trackball.B3motion = self.TranslateCurrentCamera ## c.trackball.ShiftB3motion = c.trackball.NoFunc ## c.trackball.ShiftB2motion = self.ScaleCurrentCamera self.Reset_cb = self.ResetCurrentCamera if self.GUI: self.GUI.bindResetButton( self.Reset_cb ) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Camera' else: c.bindAllActions('Camera') ## c.trackball.B2motion = self.RotateCurrentCamera ## c.trackball.B3motion = self.TranslateCurrentCamera ## c.trackball.ShiftB3motion = c.trackball.NoFunc ## c.trackball.ShiftB2motion = self.ScaleCurrentCamera self.Reset_cb = self.ResetCurrentCamera if self.GUI: self.GUI.bindResetButton( self.Reset_cb ) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Camera' self.Xform.set(c.currentTransfMode) if self.GUI: self.GUI.fillTransformInfo_cb() ## def RotateCameraLookAt(self, event, matrix): ## self.currentCamera.ConcatLookAtRot(matrix) ## for l in self.lights: ## if self.currentCamera.renderMode == GL.GL_SELECT: ## continue ## if l.positional==viewerConst.YES: ## l.posFlag = 1 ## l.spotFlag = 1 ## else: ## l.dirFlag = 1 ## self.Redraw() ## # not implemented now; will need to fix light if it is used (see fn above) ## def TranslateCameraLookAt(self, event, trans): ## self.currentCamera.ConcatLookAtTrans(trans) ## self.Redraw() def RotateCurrentCamera(self, event, matrix, transXY, transZ): """Apply the rotation matrix to camera. If lights, the flag is set to redraw the lights in a new position.""" #self.currentCamera.ConcatLookFromRot(matrix) #rot = Numeric.transpose(Numeric.reshape(matrix, (4,4))) #rot = Numeric.reshape(rot, (16,)) self.currentCamera.ConcatRotation(matrix) for l in self.lights: if self.currentCamera.renderMode == GL.GL_SELECT: continue if l.positional==viewerConst.YES: l.posFlag = 1 l.spotFlag = 1 else: l.dirFlag = 1 #l.ConcatRotationDir(matrix) #l.ConcatRotationDir(rot) ## for type in ('dir', 'pos', 'spot'): ## setattr(l, '%sFlag'%type, 1) self.Redraw() def TranslateCurrentCamera(self, event, matrix, transXY, transZ): """Add the translation trans to the current object """ #t = (- transXY[0]*0.05, - transXY[1]*0.05, -transZ ) t = (0, 0, -transZ ) self.currentCamera.ConcatTranslation( t ) self.Redraw() def TranslateXYCurrentCamera(self, event, matrix, transXY, transZ): """Add the translation trans to the current object """ t = (transXY[0]*0.05, transXY[1]*0.05, 0. ) self.currentCamera.ConcatTranslation( t ) self.Redraw() def translateCurrentCameraMouseWheel(self, event): """translate the current camera via the mouse wheel """ #print "translateCurrentCameraMouseWheel", event.num if event.num == 4: t = (0, 0, -10 ) else: t = (0, 0, 10 ) self.currentCamera.ConcatTranslation( t ) self.Redraw() def ScaleCurrentCamera(self, event, matrix, transXY, transZ): """Scale the current object """ #print "ScaleCurrentCamera", event, matrix, transXY, transZ c = self.currentCamera value = c.fovy * .01 * transZ fovy = c.fovy - value if (fovy < 180.) and (fovy > 0.): c.Set(fov=fovy) self.Redraw() def scaleCurrentCameraMouseWheel(self, event): """Scale the current object """ #print "scaleCurrentCameraUp", event.num if os.name == 'nt': #sys.platform == 'win32': if event.delta > 0: lEventNum = 4 else: lEventNum = 5 else: lEventNum = event.num c = self.currentCamera value = c.fovy * .1 if lEventNum == 4: fovy = c.fovy - value c.Set(fov=fovy) else: fovy = c.fovy + value if fovy < 180.: c.Set(fov=fovy) self.Redraw() def ResetCurrentCamera(self): """Reset the current camera's transformation""" self.currentCamera.ResetTransformation() for l in self.lights: if self.currentCamera.renderMode == GL.GL_SELECT: continue if l.positional==viewerConst.YES: l.posFlag = 1 l.spotFlag = 1 else: l.dirFlag = 1 self.Redraw() def BindTrackballToLight(self, light, allCameras=None): """Bind the trackball to the current ligth source""" self.useMasterDpyList = self.oldUseMasterDpyList if not isinstance(light, Light): raise AttributeError('first parameter has to be an instance of \ Light') self.SetCurrentLight(light) if light.positional==viewerConst.NO: # directional light if allCameras: for c in self.cameras: c.bindAllActions('Light') ## c.trackball.B2motion = self.RotateCurrentDLight ## c.trackball.B3motion = c.trackball.NoFunc ## c.trackball.ShiftB3motion = c.trackball.NoFunc ## c.trackball.ShiftB2motion = c.trackball.NoFunc self.Reset_cb = self.ResetCurrentDLight if self.GUI: self.GUI.bindResetButton( self.Reset_cb) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Light' else: c = self.currentCamera c.bindAllActions('Light') ## c.trackball.B2motion = self.RotateCurrentDLight ## c.trackball.B3motion = c.trackball.NoFunc ## c.trackball.ShiftB3motion = c.trackball.NoFunc ## c.trackball.ShiftB2motion = c.trackball.NoFunc self.Reset_cb = self.ResetCurrentDLight if self.GUI: self.GUI.bindResetButton( self.Reset_cb) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Light' else: # positional light light.FrameTransform(self.currentCamera) self.Xform.set(c.currentTransfMode) if self.GUI: self.GUI.fillTransformInfo_cb() def RotateCurrentDLight(self, event, matrix, transXY, transZ): self.currentLight.ConcatRotationDir(matrix) self.Redraw() def ResetCurrentDLight(self): self.currentLight.Set(direction = (1,1,1,1)) self.Redraw() def CurrentLightColor(self, prop, value): """Method to be bound to a GUI widget""" if value: if prop=='ambient': self.currentLight.Set( ambient = value ) elif prop=='diffuse': self.currentLight.Set( diffuse = value ) elif prop=='specular': self.currentLight.Set( specular = value ) self.currentCamera.Redraw() def LMColor(self, col): """Method to be bound to a GUI widget""" if col: self.lightModel.Set( ambient=col, tagModified=False ) self.currentCamera.Redraw() def BindTrackballToTexture(self, o, allCameras=None): """Bind trackball to the texture of the current object """ # we cannot use masterDpyList else Xform matrix for texture does not # get updated in DrawOneObject (since it is embbeded in masterDpyList self.oldUseMasterDpyList = self.useMasterDpyList self.useMasterDpyList = 0 if o is None: self.Xform.set(self.currentCamera.currentTransfMode) return if not isinstance(o, Geom): raise AttributeError ('first parameter has to be an instance of Geom') if not o.texture: self.Xform.set(self.currentCamera.currentTransfMode) return self.SetCurrentTexture(o.texture) if allCameras: for c in self.cameras: c.bindAllActions('Texture') #c.trackball.B2motion = self.RotateCurrentTexture #c.trackball.B3motion = self.TranslateCurrentTextureXY #c.trackball.ShiftB3motion = self.TranslateCurrentTextureZ #c.trackball.ShiftB2motion = self.ScaleCurrentTexture self.Reset_cb = self.ResetCurrentTexture if self.GUI: self.GUI.bindResetButton( self.Reset_cb) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Texture' else: c = self.currentCamera c.bindAllActions('Texture') #c.trackball.B2motion = self.RotateCurrentTexture #c.trackball.B3motion = self.TranslateCurrentTextureXY #c.trackball.ShiftB3motion = self.TranslateCurrentTextureZ #c.trackball.ShiftB2motion = self.ScaleCurrentTexture self.Reset_cb = self.ResetCurrentTexture if self.GUI: self.GUI.bindResetButton( self.Reset_cb) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Texture' self.Xform.set(c.currentTransfMode) if self.GUI: self.GUI.fillTransformInfo_cb() def ResetCurrentTexture(self): """Reset the current tesxture's transformation""" self.currentTexture.ResetTransformation() self.Redraw() def ScaleCurrentTexture(self, event, matrix, transXY, transZ): """Scale the current object""" scaleFactor = max(0.001, 1.0 + transZ*0.01) if scaleFactor < 0.001: scaleFactor = 0.001 self.currentTexture.ConcatScale(1.0/scaleFactor) self.Redraw() def RotateCurrentTexture(self, event, matrix, transXY, transZ): """Apply the rotation matrix""" self.currentTexture.ConcatRotation(matrix) self.Redraw() def TranslateCurrentTextureXY(self, event, matrix, transXY, transZ): """Add the translation trans to the current Texture""" t = (-transXY[0]*0.05, -transXY[1]*0.05, 0.0 ) self.currentTexture.ConcatTranslation(t) self.Redraw() def TranslateCurrentTextureZ(self, event, matrix, transXY, transZ): """Add the translation trans to the current Texture""" t = (0.0, 0.0, -transZ*0.05) self.currentTexture.ConcatTranslation(t) self.Redraw() def BindTrackballToScissor(self, o, allCameras=None): """Bind trackball to the scissor of the current object """ if o is None: self.Xform.set(self.currentCamera.currentTransfMode) return if not isinstance(o, Geom): raise AttributeError('first parameter has to be an instance of Geom') if not o.scissor: self.Xform.set(self.currentCamera.currentTransfMode) return self.useMasterDpyList = self.oldUseMasterDpyList self.currentScissor = o if allCameras: for c in self.cameras: c.bindAllActions('Scissor') #c.trackball.B2motion = c.trackball.NoFunc #c.trackball.B3motion = self.TranslateCurrentScissor #c.trackball.ShiftB3motion = self.AspectRatioScissor #c.trackball.ShiftB2motion = self.ScaleCurrentScissor self.Reset_cb = self.ResetCurrentScissor if self.GUI: self.GUI.bindResetButton( self.Reset_cb ) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Scissor' else: c = self.currentCamera c.bindAllActions('Scissor') #c.trackball.B2motion = c.trackball.NoFunc #c.trackball.B3motion = self.TranslateCurrentScissor #c.trackball.ShiftB3motion = self.AspectRatioScissor #c.trackball.ShiftB2motion = self.ScaleCurrentScissor self.Reset_cb = self.ResetCurrentScissor if self.GUI: self.GUI.bindResetButton( self.Reset_cb ) self.GUI.enableNormalizeButton(Tkinter.DISABLED) self.GUI.enableCenterButton(Tkinter.DISABLED) c.currentTransfMode = 'Scissor' self.Xform.set(c.currentTransfMode) if self.GUI: self.GUI.fillTransformInfo_cb() def ResetCurrentScissor(self): """Reset the current tesxture's transformation""" self.currentScissor.Set( scissorX=0, scissorY=0, scissorW=200, scissorH=200 ) self.Redraw() def AspectRatioScissor(self, event, matrix, transXY, transZ): """modify scissor aspect ratio""" scale = max(0.001, 1.0 + transZ*0.01) sc = self.currentScissor sc.Set(scissorAspectRatio = sc.scissorAspectRatio*scale) self.Redraw() def ScaleCurrentScissor(self, event, matrix, transXY, transZ): """Scale the current object""" scaleFactor = max(0.001, 1.0 + transZ*0.01) if scaleFactor < 0.001: scaleFactor = 0.001 sc = self.currentScissor sc.Set( scissorW=int(sc.scissorW*scaleFactor), scissorH=int(sc.scissorH*scaleFactor) ) self.Redraw() def TranslateCurrentScissor(self, event, matrix, transXY, transZ): """Add the translation trans to the current Scissor""" sc = self.currentScissor sc.Set( scissorX=int(sc.scissorX+transXY[0]), scissorY=int(sc.scissorY+transXY[1]) ) self.Redraw() def deleteOpenglList(self): #import traceback;traceback.print_stack() #print "Viewer.deleteOpenglList" self.redoDspLst = 0 for c in self.cameras: if c is not None and c.dpyList is not None: c.tk.call(c._w, 'makecurrent') currentcontext = self.currentCamera.tk.call(self.currentCamera._w, 'contexttag') if currentcontext != c.dpyList[1]: warnings.warn("""deleteOpenglList failed because the current context is the wrong one""") #print "currentcontext != self.dpyList[1]", currentcontext, self.dpyList[1] else: #print '-%d'%c.dpyList[0], currentcontext, "glDeleteLists Viewer" GL.glDeleteLists(c.dpyList[0], 1) c.dpyList = None def deleteOpenglListAndCallRedraw(self): self.deleteOpenglList() self.Redraw() # def deleteAllTheDisplayListAndCallRedraw(self): # # except the templates # for o in self.rootObject.AllObjects(): # if o.dpyList is not None: # o.RedoDisplayList() # self.deleteOpenglList() # self.Redraw() def removeAllTheDisplayListsExceptTemplatesAndVBO(self): self.objectsNeedingRedo = {} for g in self.rootObject.AllObjects(): if not (hasattr(g, 'vertexArrayFlag') and \ g.vertexArrayFlag is True and \ hasattr(g, 'vertexSet') is True and \ DejaVu.enableVBO is True): g.deleteOpenglList() self.objectsNeedingRedo[g] = None self.deleteOpenglList() def deleteOpenglListAndCallRedrawAndCallDisableGlLighting(self): #print "deleteOpenglListAndCallRedrawAndCallDisableGlLighting" GL.glDisable(GL.GL_LIGHTING) self.deleteOpenglListAndCallRedraw() def transformedCoordinatesWithInstances(self, hits): """ hist is pick.hits = {geom: [(vertexInd, intance),...]} This function will use the instance information to return a list of transformed coordinates """ vt = [] for geom, values in hits.items(): coords = geom.vertexSet.vertices.array for vert, instance in values: M = geom.GetMatrix(geom.LastParentBeforeRoot(), instance[1:]) pt = coords[vert] ptx = M[0][0]*pt[0]+M[0][1]*pt[1]+M[0][2]*pt[2]+M[0][3] pty = M[1][0]*pt[0]+M[1][1]*pt[1]+M[1][2]*pt[2]+M[1][3] ptz = M[2][0]*pt[0]+M[2][1]*pt[1]+M[2][2]*pt[2]+M[2][3] vt.append( (ptx, pty, ptz) ) return vt def enableOpenglLighting(self): #print "enableOpenglLighting", self.OverAllLightingIsOn.get() if self.OverAllLightingIsOn.get() == 1: #print "Opengl lighting enabled" GL.glEnable(GL.GL_LIGHTING) def toggleOpenglLighting(self, event=None): #print "toggleOpenglLighting" self.OverAllLightingIsOn.set( not self.OverAllLightingIsOn.get() ) self.deleteOpenglListAndCallRedrawAndCallDisableGlLighting() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/RELNOTES0000755000175000017500000025223111102416534021050 0ustar debiandebianDejaVu Release Notes ==================== Release 1.5.4 (November 2008) ------------------------------ Arcs3D.py - renamed geometry in examples - modified Fan object to compute vector orthogonal to disc normal when it is not provided Points.py -adjusted selection lines not to interfer with selection -adjusted selection crosset not to interfer with selection SelectionGUI.py - now contour selection has a settings panel Spheres.py; -radii can be int and not just float Trackball.py -repaired: now button 1 stop the spin -now spinning can be managed by any button Viewer.py -adjusted clip translation - adjusted far and near for TranslateCurrentObjectZ - adjusted far and near for AutoDepthCue and TranslateCurrentObjectXY - added self.OneRedraw() in FocusCameraBB - replace 0,001 by 0.01 in setting lastFrameTime - added def getVisibleGeoms(self, geom=None) method - limited self.lastFrameTime to more than 0.01 - added if self.lastFrameTime == 0: in FocusCameraBB - added FocusOnObject and FocusCameraBB methods ViewerGUI.py - corrected geom properties propagation - now Ambient Occlusion Gui has a Button, not a checkbutton VisionInterface/ DejaVuNodes.py - added missing default values for not required paremeters GeometryNodes.py - spheres node has default values - cylinder node has default values - repaired instanceMatrices in geometryNode Releases 1.4.6 - 1.5.2 (July 2008) ------------------------------ - moved fron Numeric to numpy Camera.py - corrected behaviour when changing selectedgeom in geometryNode and corrected sticker text - introduced pivotOnPixel - adjusted mouse transform info in viewergui - allow mac intel GMA to run without preventing intel bugs -added geomReparented() method to OcclusionCamera class to update the name of a reparented geometry in the GUI. - moved compute button away from apply button - re-organized GUI a bit - Geometry objects for which we compute occlusion do no longer automatically occlude. However, adding a geom to the list for computation adds it by to the list of occluders (but it can be removed). addded a test for at least 1 occluder. Currently it prints a message to the shell and returns if no occluders are present. - more checks in normal calculation code for ambient occlusion - added percentage counter for completiom of occlusion calculation - created DynamicComboBox class to subclass Pmv.Combobox and allow to fill the pulldown menu as it gets posted - added OcclusionCamera class to compute occlusion using OpenGL - corrected numpy arrray test for antialiasing - fixed Bug 895 - corrected cartoon bug due to PIL imports - now widgetsOnBackWindowsCanGrabFocus is in mglutil.gui -fixed a small bug in Set() method ( pivot attribute). - adjusted mousewheel on win32 - protect from bug in mac intel when zomming on molecule 1BX4 - replaced l.visible is False with l.visible in (False,0) to fix light visibility problem ColorChooser.py, ColorWheel.py - repaired test for 4 channels colorchooser - allowed managment of alpha channel - a better colorChooser Cylinders.py - added highlight to cylinders DataInput.py - repaired read obj - corrected pb in readobj Geom.py - added def getOcclusionPointsDir(self) method to Geom - repaired tests for numpy IndexedPolygons.py - indexedPolygons can be exported as indpolvert not vert Insert2d.py - retrieved lost function getTile - solved small bug, plus corrections for vista - bad cast introduced when preparing move to numpy, tuple not float LICENSE - -added TSRI to the copyright part. - -added LICENSE file MaterialEditor.py - moving to numpy Materials.py - - modified .GetProperty() method to handle a vector as second argument of getFrom and an (r,g,b) tuple as the first getFrom argument. - fixed len(values.shape) problem in SetMaterial Spheres.py - -in Set(radii) added a check if type of radii is 'ndarray'. - UTSpheres can be used in pmv - - added def makeTemplate(self): pass to UTSphere to avoid building - template - -updated utimposter-releted code in UTSpheres - in Set() replaced the statement : "if rad or v:" by if rad != None or v != None:" - caused an error if rad is numpy array. StickImage.py - renamed stickimage into stickerimage StickerImage.py - renamed stickimage into stickerimage Textured2DArray.py - replaced "if foo" with "if foo is not None" Trackball.py - now spin launch with the mouse is working Viewer.py - objects can retain their current position when reparenting - fixed ALT-TAB problem reported by Oleg on 06/27/2008 - adjusted pivotOnPixel - introduced pivotOnPixel - repaired center when root only and current object is root - repaired center when object has been translated - adjusted mouse transform info in viewergui - added mouse transformInfo in viewerGUI - repaired Normalize and CenterCurrentObject - repaired CenterCurrentObject - -added ReparentObjectEvent class and a call to dispatchEvent() in ReparentObject() method. - - Added RemoveObjectEvent class to Viewer and dispatch call for these events - -added addScenarioButton attribute to the Viewer( if set to False the Scenario button is not added to the Viewer's GUI even if Scenario is enabled in _dejavurc). This is to allow VF scenarioCammand add this button to the button bar of the Molecular Viewer. - -added class AddObjectEvent(Event). ViewerGUI.py - introduced pivotOnPixel - adjusted mouse transform info in viewergui - introduced NoteBook tabs for property gui - added mouse transformInfo in viewerGUI - - added Ambient Occlusion GUI - -added addScenarioButton attribute to the Viewer( if set to False the Scenario button is not added to the Viewer's GUI even if Scenario is enabled in _dejavurc). This is to allow VF scenarioCammand add this button to the button bar of the Molecular Viewer. - added enabled Scenario - -modified startScenario() method. - now networks runs in saved directory - now networks run into the saved network directory __init__.py - now vision runs even without a directory to write to - added 'pytz' to the list of NONCRITICAL_DEPENDENCIES. glfSticker.py - now glfSticker has its own gui opengltkCanvas.py - file opengltkCanvas.py was initially added on branch wx. - work in progress with wxpython run.py - file run.py was initially added on branch wx. - attempt to wx utils.py -the function returns also vertex normals (it averages duplicated normals). videoRecorder.py -added code to display the folder that contains saved mpg file in the file browser. VisionInterface/DejaVuNodes.py - objects can retain their current position when reparenting in vision - -in the QSlim node replaced all occurrences of 'if ###:' statement by 'if ### is not None:' - -QSlim node: moved build_model() and decimate() methods (that are also used by GeometryNodes.DecimateGeom node) to a new class QSlimDecimate; renamed ConnectedComponents to ConnectedComponents0. - added GeometryNodes.ConnectedComponents node to vizlib. - in RemoveDupVertices nodes(Python and C++ versions) removed setting of vnormals of the resulting geometry. - -in RemoveDuplicatedVerticesNE , added vnormals parameter to IndexedPolygons() - renamed stickimage into stickerimage - changed func name: doit instead of computefunction VisionInterface/DejaVuWidgets.py - repaired configure of initialValue VisionInterface/GeometryNodes.py - when nodes rerun the recreated geoms keep their state and position - objects can retain their current position when reparenting in vision - corrected sticker text to keep user's modifications on rerun - corrected behaviour when changing selectedgeom in geometryNode and corrected sticker text - -modified class DecimateGeom: it is no longer derived from QSlim class - it creates an instance of DejaVuNodes.QSlimDecimate() instead. - now erasing a geom in vision erases it in pmv also - -ConnectedComponents node: removed 'outgeoms' output port, added some comments, removed 'print' statements - repaired GeometryNode to recreate the currents geometries on each run - corrected datatype of output of geometry node - added .vert/.face reader scenarioInterface/__init__.py - expand viewergui to accomodate Animate buttons - fixed creating clipping plane actor in autotrack mode. - in getActorScript() replaced 'print warning' lines by 'tkMessageBox.showwarning' . - -modified getActorScript() to add linkedKeyFrames anf kfSetId to the actor's script. - added a redraw actor. - added autotrack feature. -replaced saveAnimation() by getActorScript(). Moved part of the code for saving current animation to scenario/gui.py - added code for saving/restoring current scenario in/from a script. scenarioInterface/actor.py -added methods to RedrawActor for recording movies. - added a redraw actor. -modified setValue() and getValue() methods of DejaVuRotationActor to use quatToMatrix() and matToQuaternion() from scenario.interpolators . -modified setValue() and getValue() of DejaVuRotationActor to use UnitQuaternion. -added a check for white spaces in the actor's name. scenarioInterface/actorsDescr.py -added description of Light.direction actor. -worked on autotrack feature. -added fieldOfView actor. -added DejaVuRotationActor class. Updated the description of this actor. scenarioInterface/interpolators.py -added a keyword 'active' to the parameter list of the interpolators constructors. -added LightColorInterpolator. Release 1.4.5 (May 2007) ------------------------------ New features and bug fixes Camera.py - repaired fuzzy AA with Thumbnail. move thumbnail just before swapBuffers. - improved auto depthcueing and fog; - new keyboard bindings: Shift - to scale the camera; Alt - to translate the camera. Also, mouse wheel is now used to scale the camera; - introduced allowedAntialiasInMotion; - now camera z translation updates fog sliders - fixed redrawing of the clipping plane frame - improved hightlight - introduced widgetsOnBackWindowsCanGrabFocus - imporoved selection texture - corrected camera light in stereo ColorChooser.py - adjusted target for colorchooser - imporoved gui buttons - introduced new background-clipplane-light color chooser ColormapGui.py - introduced widgetsOnBackWindowsCanGrabFocus now, on windows, the widget grab the focus only if the window is already activated. Common2d3dObject.py - introduced deleteOpenglTemplateList Geom.py - corrected inheritLineWidth missing redoDisplayList - now pointwidth is an int - now linewidth is an int, corrected list bug - added propagate property to children - modified cull into culling - modified shademodel into shading Light.py - corrected light broadcast in material editor sphere - introduced new background-clipplane-light color chooser - corrected Set() MaterialEditor.py - introduced spinOptionMenu Trackball.py - introduced spinOption Menu, can be accessed trough Pmv or Viewer GUI Transformable.py - added transpose=True argument to def GetMatrix(), Should be backward compat. Viewer.py - added EventHandler mix in class to Viewer class and created events for setting current object, camera, light and clipping plane - added callback mechanism when currentObject is set - corrected scale on Normalize - corrected near and far, Normalize and AutoDepthCue now NormalizeCurrentObject translates the rootObject and the camera - introduced graham light model - added spinning in _dejavurc ViewerGUI.py - improved propagate property to children - added pointwidth to geom properties menu - added linewidth to geom properties menu - now inherit options are disabled for root - rearranged object gui - made sure depthcue check button is updated - introduced new background-clipplane-light color chooser - now camera z translation update fog sliders - introduced RelabelingCascadeMenu - added spinning checkbox - improved the appearance of the gui - added to display histogram in graphtool.added showHistogram to support that VolumeGeom.py - the following lines of VolumeGeom.__init__(): self.immediateRendering = 1 self.transparent = 1 are moved below the "apply(Geom.__init__ ...)" statement to prevent setting of these attributes to False (in the Geom.__init__()). colorMap.py -repaired color map output glfLabels.py - fix bug where you could not set to False the keyword billboard or includeCameraRotationInBillboard at the initialisation of geom. - introduced includeCameraRotationInBillboard videoRecorder.py - added a GUI for recording movies in DejaVu Viewer. This GUI can be accessed through the Viewer's gui or from Pmv '3d Grafics' menu. Release 1.4.4 (December 2006) ------------------------------ New features and bug fixes - introduced current context verification - introduced viewer.enableOpenglLighting() - introduced Camera.lastBackgroundColorInPhotoMode - got rid of the camera scale, as it seems to block the viewer when overused - replaced some glFlush() with glFinish() - renamed Camera StandardCamera added class RecordableCamera which can create mpg movies. Camera is set to the latter if pymedia.video.vcodec can be imported else it is set to StandardCamera - added glFinish to grab buffer - repaired stereo_buffers (was not working with the new docking) - introduced 'cameraScale' - root color is set to gray during motion with NPR - introduced Common2d3dObject; now Geom inherit Common2d3dObject - make sure togl is properly loaded - better managment of CCW - now we redo all the display list when global lighting changes - now objectsNeedingRedo is a dict - docking and floating adjustments without calling deleteOpenglList - introduced sharpColorBoundaries for lines, cylinders and surfaces - introduced ownGui for ColorMapLegend - implemented invert normal per geometry (and it is exportable) - corrected bug in normals calculation in Set method of Geom objacts - corrected Normal calculation when set vertices and faces at the same time - changed to create the light model first, then the material editor. - repaired lighting on sphere in Material editor - now material editor works also without lighting - now we activate the camera when it is added - added hasRedrawn attribute to viewer (used by recordable camera to save only unique frames) - we erase the last camera first on exit - repaired stereo_buffers (was not working with the new docking) - implemented GraphTool Widget for adjusting non photo rendering parameters. DejaVu/VisionInterface - added DecimateGeom node that inherits from QSlim node and GeometryNode. - QSlim node: fixed decimation of colors. - introduced node sticker - introduced node StickImageNE - removed glutLabels node - corrected output port names in GeometryNodes - repaired bug when deleting connections, the callback can destroy some connections in the list - introduced texture in GeometryNode; now most of the GeometryNodes can receive texture - adjusted GeometryNode following inheritance of Common2d3dObject - added node OneTexturedPolygonNE - introduced type 'geomOrInsert2d' Release 1.4.3 (September 2006) ------------------------------- New features - introduced legend with glf font; - introduced glfLabels, renamed node LabelsNE into GlutLabelsNE; - introduced VRML for glf labels; - added showLegend and hideLegend to colormapgui; - added NucleicBases.py for displaying Nucleic Bases; - added Ribbon representation for DNA/RNA; - added option for coloring DNA/RNA ribbons; - added customization options for Nucleic_Acids_properties; - made NPR rendering work for docked and undocked cameras and global anti aliasing; - made NPR drawing independent of Numarray; - added all NPR attributes to Set method and getState; - now geoms have attr 'invertNormals' for stl and vrml saving; - added texCoordsIndex ( we use it for the ARPlatform geometries) if geometry vertexSet as texCoordsIndex attribute then added to vrml2 output file - now in the networks, we save only the part of the material that is not PER_VERTEX or PER_PART (it was too big); - implemented tside by side stereo of ilerenderer; - the colormap can handle labels and the colorpalette is modifiable; - modified getTexture for VRML2 output to support 2D texture. Bug fixes - corrected scissor on resize and inheritance; - fixed NPR skewed and set lighting; - fixed a bug when switching to stereo buffer withoou pmv; - corrected colormapgui expanding by itself in pmv on win32; - corected bug when the viewer modifies the name of the colormap; - corrected right button straight ramp generation; - corrected bug (lights > #2 in pmv were not working); Release 1.4.2. (May 2006 ) ------------------------ Bug fixes and modifications: Camera.py -implemented stereo color separation, added red-green stereo color separation; - added drawThumbnail to the list of options that can be set for a Camera; - added support for point rendering in thumbnail; ColormapGui.py -introduced editable color palette via colorPaletteCommands, made it resizable; -added ability to handle a list of labels; -left click on the colormap allows to draw straight ramp. It is previewed with a black and white line. Legend.py -fixed bug: under Mesa in vision depth buffering wasn't working -simplified and cleaned colormap legend -corrected vertical/horizontal positionning in some corner -the legend in the colormap and in the camera is drawn using the same function Viewer.py -replaced SimpleDialog with tkMessageBox.askokcanel -saved networks now restore the viewer state - made twoSide light model default - made light model panel in gui initialize checkbuttons with current values - corrections in saving macros - corrections in loading mydefaultlib ViewerGUI.py - made backPolyMode and FrontPolyMode GL_FILL by default - added code to disable culling when a clipping plane is enabled - added drawThumbnail to list of options that can be set for a Camera - added a checkbutton under Camera Panel in GUI to toggle this values - made twoSide light model default - made light model panel in gui initialize checkbuttons with current values colorTool.py -adjusted HSVRamp to allow size =1 VisionInterface/DejaVuNodes.py -moved filename in colormap node to the parampanel -made Box a GeometryNode -implemented node Labels - added CenterOnPickedVertex node allowing to turn mouse picking into scene centering opeartion using lastPicked vertex - added CenterOnVertex node to allow to center on a 3D point -added support for colorMap with only one color -introduced Types files per library -suppressed annoying deprecation warnings -corrected bug when saving colormap node source code, -reduced default colormap node to 16 values -saved networks now restore the viewer state -corrected bug in SetInstances -corrected TextureType -corrected bug related to "show legend" and apply. -corrected bug when closing colormap settings -corrected bug when saving colormap node source code -corrected bug when apply colormap settings with 'show legend' off -corrected TextureType to accept Colormap VisionInterface/DejaVuTypes.py -now all the libraries are using UserLibBuild.addTypes() to load types VisionInterface/DejaVuWidgets.py -corrected bug in colorEditor callback -corrected bug when saving colormap node source code, -reduced default colormap node to 16 values VisionInterface/GeometryNodes.py -corrected bug in geom's deletion -now geometryNode renames and doesn't duplicate -changed minimum sphere radius from 0.1 to 0.0000001 -now geometries are set with tagModified=False -now parenting geometry nodes can be done througth macros Release 1.4.1. March 2006 ---------------------------- What's new since 1.3alpha2: --------------------------- *Added support for saving 'png' files with transparent background in Camera *Added assertion that width and height of camera are int. When passing a float the camera.width and .height could become float which cause some OpenGL functions not to execute (for instance glViewport) ultimately leading to segfault on some other OpenGL calls *added an option to save a VRML2 file with colors per vertex or color per face. Added a checkbutton to the VRML2 save panel to toggle this. If colors are currently per vertex and the user chooses per face, the colors are interpolated to give a reasonable result (code by Michel). Vice versa was already implemented and applied by default. Note: the materials of the geometry are not modified by this operation in DataOutput. *Added tests foe colorChooser,Ellipsoids *The OGLWidget in Material Editor now has a width and height attribute which are used to set the width and the height of the widget instead of using the current height and width. *Added dialogbox such that when camera x button is clicked asks whether to quit or not? *Added Viewer.stopTileRendering method *Modified Viewer.OneRedraw() to check is autoRedraw is on and in this case switch it off for the duration of this redraw and restore its previous value.This way it is OK to call OneRedraw when autoRedraw is on.Also the rotateScene macro no longer has to stop and start autoRedraw at the beginning and the end of the iteration. The nice thing about this is that interrupting the rotateScene macro no longer leaves the viewer in autoRedraw off mode, and it is possible to interact with the rotating scene with the mouse. *Added a dialog box such that when x button of ViewerGUI is clicked asks whether to quit or not. *Added Viewer.GUI renameObject method, to change the name of an object in the widget tree *Added a checkbutton to allow the user to set the thumbwheels to the given colorMap values. *Added SelectMultipleGeometry node to select geometry object using regex on name in ImageViewer. *Added new check button to IndexedPolygons node to create new geometry when name changes in ImageViewer. *Added utils for algorithms operating on geometries *Added ConnectedComponents,DistanceSet(width=, height=) to make sure the windows does resize before we return from the call - added swap attribute to camera (to avoid swapping after redraw in some cases) - made the camera only swap if c.swap is true - modified Expose method to not do anything if in the viewer is in autoRedraw mode. This was creating a racing condition when the tile renderer lifted the camera - fixed Camera.lift method to work for docked and floating camera - added camera.frameBorderWidth attribute to camera - fixed camera.Geometry method to add 2*frameBorderWidth to width and height - added camera.getGeometry method - added assertion that width and height of camera are int. When passing a float the camera.width and .height could become float which cause some OpenGL functions not to execute (for instance glViewport) ultimately leading to segfault on some other OpenGL calls - commented out picked code in ActivateClipPlanes - commented out loading a name for clipping plane as it changed the length of the picking names vectors .. now clipping planes cannot be picked. - fixed some bugs in handlePick (p was not incremented properly and mini was never set) - removed some extr space characters - modified pickObject to store instance info together with vertex in hits dictionary rather than in separate instance dictionary - reverted to previous PickObject with seprated lit of hits and instances - modified PickObject.hits to provide a list of (vertex, instance) tuples for each geometry - deprecated DrawPickingSphere, CenterPick_cb - modified set to clamp rootx and rooty at 0 DejaVu/Cylinders.py: - removed self.radius from Cylinders and CylinderArrows - added first pass of CylinderArrows object, need to add Set method for headLength and headRadius attributes, and may be caps. -Fixed a bug in asIndexedPolygons method when radii specified for each vertex. DejaVu/DataOutput.py: - added an option to save a VRML2 file with colors per vertex or color per face. Added a checkbutton to the VRML2 save panel to toggle this. If colors are currently per vertex and the user chooses per face, the colors are interpolated to give a reasonable result (code by Michel). Vice versa was already implemented and applied by default. Note: the materials of the geometry are not modified by this operation. DejaVu/Displayable.py: - modified initColor and InitMaterial to check for OVERALL binding and else use propr[num] DejaVu/Ellipsoids.py: - fixed a bug in Draw which caused only one ellipsoid to be drawn - added self.redoDspLst=1 in .Set method - removed obsolete PickedVertex method DejaVu/Geom.py: - added attribute instance to calls to ApplyParentsTransform and TransformedCoords - removed obsolete PickedVertex method - worked on incorporating instances into ApplyParentsTransform, TransformedCoords and GravityCenterSubtree - added SetForChildren(self, recursive=False, **kw): method to Geom - in .Set(name=...) do not rise an exception if the name matches the name of of the object itself - added .replace attribute to Geom. This attribute is used in AddObject to decide if a geoemtry should be renamed or replace an existing geometry if they have the same name (among children of the same parent) - added check for name unicity in Set(name=...) method - fixed ObjSubTreeBB to compute the bounding box with instance matrices. The problem was that geoemtries with no vertices where skipped before the instance matrices where considered DejaVu/MaterialEditor.py: - added ownsMaster attribute - added _destroy method to force deleting opengl contexts in this editor - The OGLWidget now has a width and height attribute which are used to set the width and the height of the widget instead of using the current height and width.This was causing the OGLWidget to get bigger and bigger with each step back in the colorMapGUI. DejaVu/Points.py: - removed obsolete PickedVertex method DejaVu/Polylines.py: - removed obsolete PickedVertex method DejaVu/Spheres.py: -fixed an 'import' statement and the names of UTImposter Spheres methods - added skeleton of imposterRenderer-based spheres - removed obsolete PickedVertex method DejaVu/Transformable.py: - modified logic for re-building the viewer's display list after in ConcatRotation - added optional instance attribute to BuildMat, GetMatrix and GetMatrixInverse - worked in adding support for instance in BuildMat, GetMatrix and GetMatrixInverse - added SetTransformation(self, matrix, transpose=False, redo=True) to the Transformable class to set an object's transformation from a 4x4 DejaVu/Viewer.py: -added dialogbox such that when camera x button is clicked asks whether to quit or not? - renamed Viewer.enableTileRendering Viewer.startTileRendering - added Viewer.stopTileRendering method - tile rendering now switched to not autoRedraw mode - worked on tilerendering, works better now - added print statment for each tile rendered - replaced while loop to find toplevel by winfo_toplevel() - added destroying the MaterialEditor in the Exit moethd if the Viewer This forces the opengl contexts created for this editor to be deleted - uncommented some functions - fixed a bug that crated a problem when replacing a geometry - added redo=False argument to RemoveObject - fixed bug in RemoveObject, no object could be removed because of a logic error - removed the topObjects list, There can only be one root object now - modified the Viewer's contructor to create root (rather than using AddObject - replace unique=1 argument to AddObject by replace=True - removed 'top' as a legal parent object in AddObject - rewrote most of AddObject - made reparenting work - added emopty lines for demo od cvs - replaced all after_idle() by after(10) for autoRedraw - added self.pendingAutoRedrawID attribute to Viewer to same the ID of the after() call used by autoRedraw - modified viewer.stopAutoRedraw() to kill the last after() call and made sure ReallyRedraw will not be called for the pending after call - modified OneRedraw() to check is autoRedraw is on and in this case switch it off for the duration of this redraw and restore its previous value. This way it is OK to call OneRedraw when autoRedraw is on. Also the rotateScene macro no longer has to stop and start autoRedraw at the beginning and the end of the iteration. The nice thing about this is that interrupting the rotateScene macro no longer leaves the viewer in autoRedraw off mode, and it is possible to interact with the rotating scene with the mouse. DejaVu/ViewerGUI.py: -self.root is checked whether instance of Toplevel before self.root.protocol('WM_DELETE_WINDOW', f).If its a frame it doesn't have protocol attr -added a dialog box such that when x button is clicked asks whether to quit or not -fixed a bug in ClipVisible method with cause only clipping plane 1 to be made visible - added support for quick transform key panel - replaced children property by a new panel that pops up and provides 2 radio buttons to turn a given property on or off for all direct children (i.e. not recursively) of an object. The panel is initialized and shows the radio button selected if all children have the property set to True, deselected if all children have the property set to False. If there is a mix of values neither the on nor the off button is set. - Fixed typo i nPreference menu "Transf. Root Only" The R was missing - added renameObject method, to change the name of an object in the widget tree - modified the addObject method which adds DejaVu geoemtry objects to the widget tree to automatically add the children of the object recursively - added a FIXME comment about calling GetMatrixInverse DejaVu/colorMap.py: - fixed a bug in setRightXVals and commented what is computed - In setRightXVals sometimes the ramp_range is equal to 0.0 which then causes a problem when normalizing the color values. - Using the value .666667 instead of the ramp_range until understanding why the ramp_range can be 0.0. - In setRightVals if idStr is 'Hue' need to normalize the ramp values by dividing the values by (max(ramp) - min(ramp) instead of using the arbitrary values of .66666667 - In OGLColorMapWidget the width attribute is now set in the constructor of the base class OGLWidget. - Cleaned up the code by removing some the commented section. - Modified the behavior of the Interval. - Added a button to set the interval to the given value - Added a checkbutton to allow the user to set the thumbwheels to the given colorMap values. - Changed the widgets to specify the intervals from Tkinter.Entry to Thumbwheel. - added glAllMaterialWithCheck function, but not used yet DejaVu/imageViewer.py: - added SelectMultipleGeometry node to select geometry object using regex on name - added new check button to IndexedPolygons node to create new geometry when name changes - fixed bug in Viewer node that created endless recursion when adding a geom container to the viewer when the parent already belonged to the viewer DejaVu/utils.py: - added utils for algorithms operating on geometries DejaVu/Tests/test_Arcs3D.py: -added new tests for radii and angles - added function validateFloat to check values used to set floarVectors of scalars. -changed comparison of R values to comparison of B values for viewer test which hinges on toggling inheritMaterial... -restructured tests into 3 classes: Arcs3D_init_Tests, Arcs3D_Set_Tests and Arcs3D_Viewer_Tests. removed tests already covered by Geom class.. NOTE: Fan3D class has no tests at all, currently. DejaVu/Tests/test_Arrows.py: -removed empty comment from beginning of file -removed unnecessary imports. -restructured tests into 3 classes: Arrows_init_Tests, Arrows_Set_Tests and Arrows_Viewer_Tests. removed tests already covered by Geom class.. . -vi.stopAutoRedraw() is removed,vi.update() is added to make the image visible while running tests -OneRedraw is now raising an exception when viewer in autoRedraw mode ,fixed by calling stopautoRedraw before OneRedraw -updated the tests by rearranging creation of self.geom... also: added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -restructured tests into 3 classes: Box_init_Tests, Box_Set_Tests and Box_Viewer_Tests. removed tests already covered by Geom class.. . DejaVu/Tests/test_Camera.py: - modified some tests in camera to properly set the width and height - modified test in Cylinders to not use radius at all anymore - fixed tests for setting camera width and height to rally check that the window size actually changed - added tests to check that setting camera.with or .height with floats raises an exception -removed testing whether setting contours to an invalid value raised a ValueError because the test depended on the "hasNumarry", a global variable in Camera which varies between platforms. -modified tests to verify that rootx and rooty are set to 0 if negative values are provided DejaVu/Tests/test_Clip.py: -removed Image because it broke things on the apple platform. -apparently can get these tests to pass if make sure that the camera is on top of all the other widgets: added camera.master.master.lift before each Redraw. -fixed rotating_clip_removes_top_half,setup_spheres_clips_right_sphere tests -corrected translating clip removes half left_sphere test DejaVu/Tests/test_ColorChooser.py: -added tests DejaVu/Tests/test_ColorMap.py: -Updated the test_ColorMap to reflect the changes made to the default values of mini and maxi DejaVu/Tests/test_ColorWheel.py: -added some more tests DejaVu/Tests/test_CrossSet.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -restructured tests into 3 classes: CrossSet_init_Tests, CrossSet_Set_Tests and CrossSet_Viewer_Tests. removed tests already covered by Geom class -vi.stopAutoRedraw() is removed,vi.update() is added to make the image visible while running tests -OneRedraw is now raising an exception when viewer in autoRedraw mode ,fixed by calling stopautoRedraw before OneRedraw DejaVu/Tests/test_Cylinders.py: -added "self.geom.Set(radii=5.0)" to Cylinders_Viewer_Tests setup method...Otherwise, the test hangs because the geometry cannot be redrawn... - modified some tests in camera to properly set the width and height - modified test in Cylinders to not use radius at all anymore -forced redraw in setUp by calling currentCamera.DoPick... -restructured tests into 3 classes: Cylinders_init_Tests, Cylinders_Set_Tests and Cylinders_Viewer_Tests. removed tests already covered by Geom class.. . DejaVu/Tests/test_Ellipsoids.py: -added tests DejaVu/Tests/test_Fan3D.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -changed def xtest to def test -added comment strings -added new tests for keywords radii,angles,vectors - Added Set method to Fan3D and Arc3D, fixed the existing tests -restructured tests into 3 classes: Fan3D_init_Tests, Fan3D_Set_Tests and Fan3D_Viewer_Tests. removed tests already covered by Geom class. DejaVu/Tests/test_Geom.py: -changed name of IndexedGeom_BaseTests to IndexedGeom_Set_Tests. -restructured previous tests to focus on testing specifics of the Geom class and those of the IndexedGeom class. now this module contains 4 test classes: Geom_init_Tests which test the possible combinations of parameters to Geom.__init__, Geom_Set_Tests which is designed to test setting each keyword which is specific to the Geom class [16 are not yet tested because i don't know valid input for them], Geom_Viewer_Tests which test adding an instance of the class to the viewer AND IndexedGeom_BaseTests which tests setting the keywords specific to the indexed geom class...[this should be called IndexedGeom_Set_Tests...]... DejaVu/Tests/test_GridBox.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -restructured tests into 3 classes: GridBox_init_Tests, GridBox_Set_Tests and GridBox_Viewer_Tests. removed tests already covered by Geom class.. DejaVu/Tests/test_IndexedPolygons.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry PLUS renamed duplicate class to IndexedPolygon_Viewer_Tests2, added it to list of classes to test, removed its duplicate tearDown method. -modified IndexedPolygons_Viewer_Tests setup to draw a polygon with 5 faces DejaVu/Tests/test_IndexedPolylines.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -restructured tests into 3 classes: IndexedPolylines_init_Tests, IndexedPolylines_Set_Tests and IndexedPolylines_Viewer_Tests. removed tests already covered by Geom class. DejaVu/Tests/test_Labels.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -modified position of labels to cope with subtle change in camera dimension. -size of camera has changed slightly so adjusted location of pixel to check so that it is in the Label geometry.... -added "camera.DoPick" to tests for Label image: this was necessary otherwise the geometry was not drawn when the tests were run [it was drawn when the tests were tested interactively]. -restructured tests into 3 classes: Labels_init_Tests, Labels_Set_Tests and Labels_Viewer_Tests. removed tests already covered by Geom class. DejaVu/Tests/test_Points.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -restructured tests into 3 classes: Points_init_Tests, Points_Set_Tests and Points_Viewer_Tests. removed tests already covered by Geom class.. NOTE: CrossSet class has no tests at all, currently. -OneRedraw is now raising an exception when viewer in autoRedraw mode ,fixed by calling stopautoRedraw before OneRedraw DejaVu/Tests/test_Spheres.py: -added lines: self.vi.update() and self.vi.currentCamera.DoPick(0.,0.) to setUp to force drawing geometry -restructured tests into 3 classes: Spheres_init_Tests, Spheres_Set_Tests and Spheres_Viewer_Tests. removed tests already covered by Geom class.. NOTE: TriangulateIcos andTriangulateIcoByFaceCenterPoint classes have no tests DejaVu/Tests/test_Viewer.py: - replaced unique=0 by repalce=True in Viewer.AddObject DejaVu/Tests/test_basics.py: -restored multiple viewer tests;fixed apparent bug in "create a viewer with a frame to pack the GUI and destroy it" -updated these tests to inherit from unittest.... DejaVu/Tests/test_memory.py: -restored commented-out test which created and destroyed a bunch of viewers... NOTE: I commented out these tests because they crash the xserver on my computer EVERY TIME! so the nightly tests can't finish... - replaced while loop to find toplevel by winfo_toplevel() -changed tests to inherit from unittest; commented out vi1.Exit in test_creating Viewers100TimeWIthViewer because this line [apparently] crashed the xserver on my linux box. DejaVu/Tests/test_triangleStrip.py: -added: self.vi.update() and self.vi.currentCamera.DoPick(0,0) to force a redraw in tests... -restructured tests into 3 classes: Triangle_strip_init_Tests, Triangle_strip_Set_Tests and Triangle_strip_Viewer_Tests. DejaVu/VisionInterface/DejaVuNodes.py: -added ConnectedComponents node -replaced PyQslim by QSlimLib, and 'class Qslim' by 'class QSlim' . - moved the type InstanceMatricesType from NetworkEditor to DejaVuNodes -added removeDuplicatedVerticesC class that uses C++ function from opengltk.extent.utillib. - added Distance handlePick, output lastpick only when self.vi is set - added RemoveDuplicatedVerticesNE node. This nodes removed vertices that appear multiple times in the vertexSet of a geometry and re-indexed the faceSet accordingly. This is useful for geoemtries comming from the isocontours or readSTL nodes. Shoudl be used before decimating a surface. - removed comment - added a node called ScaleLegend to display a size scale in a DejaVu Camera -bugfix: ColorsRGBType was moved to NetworkEditor/datatypes.py -> which means we now need to import it from there. Added this to the import statements. Before this fix, DejaVuNodes could not be loaded. -moved colorRGB and colorsRGB types to NetworkEditor.datatypes - added code Qslim node to output only used vertices for decimated geometry - added Axis node to create 3D arrows geometry - modified Viewer node's handlePick method to only schedule node children of lastPick port - modified mapPotOnGeom macro to use mean value insteead of absmax - a character had been deleted in the stereoSeparation node causing the node not to call the Set method anymore - modifed vViewer node (can stil be simplified now that the parent is set after adding to the viewer) - added output port to Viewer node to output the added geoemtries - modified IndexedPolygons to create new geoms when name changes, added replace check button and removed parent input port - added ReparentGeom - added SelectMultipleGeometry node to select geometry object using regex on name - added new check button to IndexedPolygons node to create new geometry when name changes - fixed bug in Viewer node that created endless recursion when adding a geom container to the viewer when the parent already belonged to the viewer -modified Qslim node. Added ability to rebuild the model and a choice to either output a new geometry or to modify the input geometry. -added an Entry widget to ParamPanel of Qslim node to display/set current number of faces. -added Qslim node exposing the functionality of the Qslim Surface Simplification library by Michael Garland (University of Illinois). - added node0.macroNetwork.runOnConnect = False before restoring connections in rotatScene macro and restor it's state after to avoid running the macro upon instanciation. FIXME this code shoudl be generated automatically. - added by hand node.autoRun=False and resore it for the flattenRotation node. This node is a Generic node and and its input and output ports can only be added after the node is added to the network. This was causing the execution of this node when the macro is instanciated. - removed stop and start auto redraw nodes from rotateScene macro Release October 2004 -------------------- #cvs log -d ">2003-12-17" DejaVu What's New (compared to release December 17, 2003): High level modifications: - We switched to a new version of the OpenGL wrapper called opengltk. As a consequence the following functions in opengltk are replace by: glIndexedGeomDSPL -> glDrawIndexedGeom glSphereSetDSPL -> glDrawSphereSet - for each geometry a new method has been added self.Draw() we took the call to the opengl function of self.RedoDisplayList and move them in self.Draw(). The code in Draw() is what should be between: GL.glNewList GL.glEndList that allows use to draw a geometry in another opengl context without having to share the display list. The geometry display list need to be recreated in the new context. - we added support for saving the viewer's and geometry objects' state - the _modified attribute was introduced to monitor state changes - fixed Camera destruction code to not destroy OpenGL context when it is shared - added gneric mechanism for callbacks on button up and down - added experimental Non Photo Realistic (NPR) rendering mode called silhouette. Requires Numarray to be present. Currently only works on square cameras. - added method to camera to automatically adjust depth cueing - added support for tile rendering. - fixed cliping planes - added stopAutoRedraw and startAutoRedraw methods to the Viewer - added oneRedraw method to Viewer to get a guaranteed redraw programmatically - allow to turn lighting on and off on each geometry - added new nodes to the Vision interface - fixed many bugs - added many tests Detailed lof entries per file: DejaVu/Arcs3D.py - turned lighting on for Arc3D objects by defaults else they appear VERY dim - replaced calls to GL.glColor3fv by GL.glColor4fv - change made to use new opengltk (build with distutil) - added _modifed = False at the end of the constructor DejaVu/Arrows.py - added _modifed = False at the end of the constructor - change made to use new opengltk (build with distutil) - following function in opengltk are replace by: DejaVu/Box.py - changed GridBox keywords nxpts, nypts and nzpts to xnpts, ynpts, znpts... - made the box geometry render as a default IndexedPolygons when mode is not GL_LINES - change made to use new opengltk (build with distutil) - following function in opengltk are replace by: DejaVu/Camera.py - replaced glPushName(-1) by glPushName(0) becaues under MacOSX this is not allowed (correctly so) - added self.ownMaster to Camera to decide if camera.frame.master has to be destroyed or not when camera is deleted - fixed typos in comments about shared context - fixed Camera.addButtonDown method to check if function not already in list - fixed Camera.addButtonUpCB to only add the function if it is not already in the list else we added the z-sorting functions for every opacity slider motion event - added imCanvastop attribute to prevent exception when docking camera - If a camera share context then the camera which owns the OpenGL context has an attribute shareCTXWith which contains the list of camera sharing its context.This is used when deleting a camera - added anode about sharecontext and sharelist - replaced print message by warning if numarray is not found - added support for numarray-based 2D convolution for silhouette rendering mode - added contours key word to Camera.Set, can be True or False - commented out flipping of image under windows - made GrabZBuffer return an array of floats rather than bytes - added d1cut, d1scale, d1off and d2cut, d2scale, d2off attributes to camera for controlling silhoueete rendering - added firstDerivative and secondDerivative methods to conpute this for images - added code in RedrawAASwitch for drawing contours. The contoured image is stored in camera.contouredImage - return on new lines in Camera.Redraw - removed glFlush and swapbuffer from Redraw because it was already done in .RedrawAASwitch - added check for GL_CONVOLUTION_2D in set(contours) - fixed capitalization of depthImage - modified GrabZBuffer to return more meaningful; values when zmin==zmax when nothing is draw zmin==zmax = 1.0 and it will return 255 when a single polygon, orthogonal to the viewing direction is draw it would return a constant values corresponding to zmax*255 where zmax is between 0.0 and 1.0 - modifed handling of contour keyword in Set in order to destroy iamgeviewer if present, regardless of value of to be set - added contour capability in on AntiAliased mode - speed up constour calculation by moving normalization out of the loop - made AA accumulation hapen in back buffer - Grab Z and Front buffer no longer swap buffers - GrabFrontBuffer now has a buffer argument allowing to also grab back buffer - added attributes for drawing contours # attributes used to draw black outlines self.contouredImage = None # will hole the final PIL image self.outlineim = None # will hole the final contour self.outline = None # accumulation buffer used for AA contour self.contours = False # set to True to enalbe contouring self.d1cut = 0 self.d1scale = 3.0 self.d1off = 60 self.d2cut = 1 self.d2scale = 8.0 self.d2off = 10 - added code to antialias contours - split GrabFront and ZBuffer method into on to get a Numeric array and one to get a PIL image - fixed set(end, start) for bad input - enabled unit tests - Changes GrabZbuffer to make an 'L' image instaed of 'P' - added pushAttrib=True argument to Camera's Draw method. This is used by tests to retain the OpenGL state after drawing an object - indentation change in Enter_c - added _modifed=True to Setxxxx and Concatxxxx method - save rootObject's state only if _modofed is True - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. - added _modifed flag to camera. It can be set using the Set method. if not specified as False, calling Set will set it to True - added getState method to Camera and Fog - removed viewerConst.FPRECISION argument from colorTool.OneColor calls - fixed bug that caused expose events to freeze camera - added silent optional attribute to delButtonDownCB and delButtonUpCB methods - recompute camera.direction qhen lookfrom or lookat is modified - added 2 functions to remove button up and down callbacks - generalized mechanism to specify call back on button down and up Camera has 2 new lists onButtonUpCBlist and onButtonDownCBlist and 2 methods to add callback to these list addButtonDownCB, addButtonUpCB. I also added 2 methods for manging anti aliasing suspendAA and restoreAA - added AutoDepthCue(self, nearOffset=0.0, farOffset=0.0) method to camera It sets fog start and end automatically using the bounding box of the scene. if delta is the depth of the bounding box, start will be set to near+(nearOffset*delta) end will be set to farn+(farOffset*delta) - added backBuffer option to enableTileRendering - made image buffer 3byte per pixel - known problems: text might fail, need to implement trRasterPos3f stereo does not work for some sizes of windows, top tile is distorted - added support for tile rendering. to use it call vi.enableTileRendering() with an outputFile, a desired width or a height and an optional border vi.enableTileRendering(width=2000, outputFile='testpmv.jpg') - changed signature of Expose function from def Expose(self, *dummy): to def Expose(self, event=None): DejaVu/Clip.py - removed side attribute as this is defined by each clipped object - fixed calculation of eqn[3] when rotating the clipping plane, has to add - self.eqn[3] = -Numeric.matrixmultiply(self.eqn[:3], self.translation) - added checks for valid input to setting lineWidth... now raises ValueError if new value can't be converted to a float OR if new value is not greater than 0. - inverted order of treating translation and rotation in Set method - added _modifed=True to Setxxxx and Concatxxxx method - save rootObject's state only if _modofed is True - made clipping plane color a list rather than an array - visible is now True or False rather than 0/1 - fixed a bug in Set method for keyword 'side' - reshape rotation to (16,) because that is what ConcatRotation wants - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. - added _modified flag - change Set method for translation, rotation scale and pivot - added a comment about clipping planes - added getSate method to clipping plane object - modified Set method for rotation, translation, scale and pivot DejaVu/ColorChooser.py - Using copy.deepcopy() instead of the __copy__() in swap. DejaVu/Cylinders.py - Fixed a bug in asIndexedPolygons method when radii specified for each vertex. - added a checkMat attribute that is set to True for MacOSX to force sending the color of each cylinder regarless of the color sent previously - fixed the bug that the radii of cylindar was not assigned in the proper order. - added lighting=True in constructor - added _modifed = False at the end of the constructor - change made to use new opengltk (build with distutil) DejaVu/DataInput.py - added this file - added class ReadASCIISTL that allows to parse ASCII STL files and convert them to DejaVu IndexedPolygons DejaVu/DataOutput.py - added various function for supporting the SMF format http://www.csit.fsu.edu/~burkardt/data/smf/smf.html listOfStrings <-- IndexedPolgonsAsSMFString(geometry) writePolygonsAsSMF(geometry, filename) v,f,n,c,r <-- ParseSMFString(stringList) readSMF(filename) - Fixed a bug in output STL: IndexedPolygons with more than 4 faces would fail, also fixed case when face is -1 (padding to make array uniform): this happens for example in BSP Tree objects DejaVu/Displayable.py - added colorAsMaterial attribute to Outline to have the outline colored same as the surface - changes lighting from 0,1 to False, True - replaced test self.frontPolyMode=='outline' by self.frontPolyMode==viewerConst.OUTLINED - moved self.immediateRendering and self.hasChildWithImmediateRendering from Displayable constructor to Transformable because immediateRendering is used in Transformable but not in Displayble - removed viewerConst.FPRECISION argument from colorTool.OneColor calls - fixed bugs in setting materials. Opacity would be ignored and required calling Set(opacity=vals). Now it is used to set the opacity is it is specified as the 4th column of the diffuse property DejaVu/Ellipsoids.py - made Draw return true, else the dpyList is always deleted - added _modifed = False at the end of the constructor - change made to use new opengltk (build with distutil) - Added initial Ellipsoid object - added setMatrixComponents method to set the rotation, translation and/or scale of object.matrix DejaVu/Geom.py - added deprecation warning for RenderMode - fixed Geom.Set(instanceMatrices=...) - fixed Set(instanceMtrices=...) - added 'lighting' parameter to Set method - modifed Draw method to not use normals is lighting is False - added tests to only call GetNormals if lighting is True - GetNormals sets lighting to True - fixed a typo bug in getState method - commented out extraneous viewer.objectsNeedingRedo.append(o) in setViewer - added test of object existence in code generated by getGeomMaterialCode and getGeomClipPlanesCode - fixed Set(instanceMatrices=). It was appending matrices instead of setting them - added _modifed = False at the end of constructor - added support for drawing outline with asme colors as material - added all argumenst to glDrawIndexedGeom for outline else it segfaults - added tagModified to calls to mat.SetMaterial in Geom .Set method to avoid taggind material _modified if tagModified is False - change made to use new opengltk (build with distutil) - added _modified attribute and tagModified keyword for Set method - added 'frontPolyMode', 'backPolyMode', 'shading', 'rotation', 'translation', 'scale', 'pivot', 'protected' and 'listed' keywords to Set method - added getState method (ahndles everything except for textures now) - added getGeomMaterialCode method - added getGeomClipPlanesCode method - replaced viewerConst.YES and NO by True and False - allow using strings for GL constants such a "front", "back", "front_and_back" - added a comment about side of clippign plane which shoudl be sored in clipping plane - removed viewerConst.FPRECISION argument from colorTool.OneColor calls - removed code to build display list for outline in DisplayFunction. THis was causing color legend to freeze viewer when outline was turned on since we tried to build a display list while building the viewer's display list - fixed bug in RedoDisplay list. repalced GL.glPolygonOffsetEXT by self.viewer.polyOffset - fixed several typo bugs in updateParentsForImmediateRendering - added support for automatically sorting polygons on button release for transparent objects - fixed bug that required Set(opacity=val) to be called twice - fixed bugs in setting materials. Opacity would be ignored and required calling Set(opacity=vals). Now it is used to set the opacity is it is specified as the 4th column of the diffuse property - fixed the IndexedGeom.Set method to reset the faces if faces are specified. This avoid the exception about faces indexing bad vertices when normals are recomputed DejaVu/GleObjects.py - In extrude() of GleExtrude class replaced: gle.gleExtrusion(contourPoints, contourNormals, self.contourUp, self.trace3D, self.materials[1028].prop[0] ) by: gle.gleExtrusion(contourPoints, contourNormals, self.contourUp, self.trace3D, self.materials[1028].prop[0][:,:3] ) DejaVu/IndexedPolygons.py - added lighting=True in constructor - added _modifed = False at the end of the constructor - fixed some bugs in saving/restoring the state - removed RenderMode from IndexedPolygons - set self.dpyList to None rather than 0 when it gets deleted DejaVu/Labels.py - added _modifed = False at the end of the constructor - change made to use new opengltk (build with distutil) DejaVu/Light.py - fixed Light.Set to check for positive values for attenuation factors - fixed unit test to check for ValueError when trying to set to negative values - changes which raise ValueError when new colorvalue for call to OneColor is not 3 or 4 long. - added _modifed=True to Setxxxx and Concatxxxx method - save rootObject's state only if _modofed is True - made all 4-tuples in Light object lists rather than 4-tuples else light's color cannot be edited - made LightModel be not modified when first constructed - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. - added _modifed to Light and LightModel - renamed enable option for light to enabled - replaced viewerConst.YES and NO by True and False - added getState() methods to LightModel and Light objects - set hasBeenCurrent flag for lights to True in Set method and False in Reset - use lists for direction, position and spotDirection DejaVu/MaterialEditor.py - renamed self.master self.root in MaterialEditor - added master for colorWheel PhotoImage - made the MaterialEditor use viewer.master as a master for its Toplevel to make sure it is in the right Tk - modifed configure method of OGLWidget to resize OGL widget - tests for default height and width had been comment out in OGLWidget's constructor had been commented out, put them back. - Also added test in MaterialEditor's contructor to set height and width to 200 by default DejaVu/Materials.py - added tagModified to SetMaterial - added getState method and Set method - added _modified attribute - fixed bugs in setting materials. Opacity would be ignored and required calling Set(opacity=vals). Now it is used to set the opacity is it is specified as the 4th column of the diffuse property DejaVu/Texture.py - fixed 1DTexture to work with latest changes in opengltk: we now call glTexImage1D directly from _gllib rather than the Python wrapper - fixed the DejaVu Vision node 1DTexture to work with the latest changes - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. DejaVu/Trackball.py - generalized mechanism to specify call back on button down and up Camera has 2 new lists onButtonUpCBlist and onButtonDownCBlist and 2 methods to add callback to these list addButtonDownCB, addButtonUpCB. I also added 2 methods for manging anti aliasing suspendAA and restoreAA DejaVu/Transformable.py - added scale=False to GetMatrix(), returns the matrix with rotation and translation. no scaling info included Used to save the transformed geom --> coords --> new pdb file - added _modifed=True to Setxxxx and Concatxxxx method - save rootObject's state only if _modofed is True - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. - moved self.immediateRendering and self.hasChildWithImmediateRendering from Displayable constructor to Transformable because immediateRendering is used in Transformable but not in Displayble - added cleanup argument to Decompose4x4 method - worked some on ConcatTranslation - change scaling factor ato allow to get very small rther than limiting to 0.001 - Added initial Ellipsoid object - added setMatrixComponents method to set the rotation, translation and/or scale of object.matrix DejaVu/Viewer.py - replaced all after_idle() by after(10) for autoRedraw - added self.pendingAutoRedrawID attribute to Viewer to same the ID of the after() call used by autoRedraw - modified viewer.stopAutoRedraw() to kill the last after() call and made sure ReallyRedraw will not be called for the pending after call - modified OneRedraw() to check is autoRedraw is on and in this case switch it off for the duration of this redraw and restore its previous value. This way it is OK to call OneRedraw when autoRedraw is on. Also the rotateScene macro no longer has to stop and start autoRedraw at the beginning and the end of the iteration. The nice thing about this is that interrupting the rotateScene macro no longer leaves the viewer in autoRedraw off mode, and it is possible to interact with the rotating scene with the mouse. - fixed Viewer's ReparentObject method which was completely broken - OneRedraw now raises an exception if it is called while the Viewer is in autoRedraw mode, since this can lead to blocking the application - commented out the old body of the ReparentGeom method and created new one - replaced all cameras[0].update and .after by viewer.master.update or after - AddCamera now sets the camera's ownMaster flag and _DeleteCamera uses it to destroy the toplevel ofthe camera is needed - fixed logic of deleting cameras sharing context - changed polycy for amster to only generate Toplevels (never Tk) because Pmw is unable to handle multiple TCL interpreters - renamed ownTk ownMaster - removed self.master = master in AddCAmera as it was overwritting the Viewer's master with th emaster for the Camera - added test to make sure guiMaster and Master are in the same TCL interpreter - fixed creation of Viewer's master for windows - added Viewer.ownTk attribute to know if we created a new Tk instance - destroy Viewer.master only if it ownTk is true - fixed bug in __DeleteCamera(), the camera was removed twice from the viewer's list of cameras - ficxed guiMaster to be a Toplevel(master) in the case that a new Tk is created, else when 2 viewers are created the root of their GUI is the same and deleting a viewer desctroys it - replaced except by finally in AddObject and RemoveObject so that exceptions are still thrown and seen by the tester but the lock is always released - modified deleteCamera to destroy camera after deleteing all dpyLists - called activate befor applying each light in InitLighting to avoid loosing lights - Delete the dpyList in DeleteCamera before setting it to None. - Modified Exit to: - destroy the GUI - destroy the Camera.master.master - Implemented a _DeleteCamera and a DeleteCamera methods. - Modified the Exit method to call _DeleteCamera. - FIXME: If cameras share context Exit will segmentation fault. - added a check for no camera in ReallyRedraw - commented out creation of toplevel if screen is provided - destroy explicitly camera its frame and the frame's master - added test about existence of justGotRedone attribute before deleting - added self.redrawLock.acquire(0) before relasing it in final: because if an exception has occured I can get there while the lock is unlocked - removed white space - added a verbose option to Viewer's constructor to suppress printing OpenGL version - Added an Exit methof to the Viewer object that properly stops the viewer avoiding "after callit" error message - updated test_Fog.py to use verbose=False and exit properly - set parent of removed object to None (else causes enless recursive loop when addign geom back to viewer) - commented out loading of togl in AddCamera - added _modifed=True to Setxxxx and Concatxxxx method - save rootObject's state only if _modofed is True - fixed a typo bug in saving inherited clipping planes - moved state saving methods from ViewerGUI to Viewer - check id LightModel is modified before saving - initLighting uses tagModfied=False to avoid saving 2 default lights - rootObject is now not _modified after Viewer is built - fixed some bugs in saving/restoring the state - removed RenderMode from IndexedPolygons - added getViewerStateDefinitionCode method - added getObjectsStateDefinitionCode method - renamed "enable" option for Set method of lights and camera "enabled" - added a comment about clipping planes - fixed bug in Viewer._RemoveObjectRec - print out OpenGL variables - determine availability of glPolygonOffset - added silent=True when removinf transparent geom to avoid warning message when removing utvolgeom - removed _RemoveObject which was obsolete - added parts of _RemoveObject to _RemoveObjectRec - removed transparent objects from c.onButtonUpCBlist list of callbacks when object is removed from viewer - add transparent objects to c.onButtonUpCBlist list of callbacks when object is added to viewer - added startAutoRedraw and stopAutoRedraw method to Viewer - added autoRedraw attribute to Viewer and constructor - viewer.currentScissor was not set when the current object was changed in the tree widget or when scissors were enabled/disabled - added method OneRedraw to guarantee a single redraw. ReallyRedraw now return true if it actually does redraw - RemoveObject method also removes object from list objectsNeedingRedo - added traceback.print_exc after traceback.print_stack - added checkered background capability to tile renderer - added backBuffer option to enableTileRendering - made image buffer 3byte per pixel - known problems: text might fail, need to implement trRasterPos3f stereo does not work for some sizes of windows, top tile is distorted - added support for tile rendering. to use it call vi.enableTileRendering() with an outputFile, a desired width or a height and an optional border vi.enableTileRendering(width=2000, outputFile='testpmv.jpg') - add the possibility to specify a different Camera instance to be created by the viewer. The new camerainstance to be add is specify using classCamera. By default we use the DejaVu Camera. DejaVu/ViewerGUI.py - added "Display Object Value in the Tree" checkbutton to "Preference" menu - added checkbutton for silhouette drawing - added a checkbutton to camera panel for enabling/disabling contouring - added a verbose option to Viewer's constructor to suppress printing OpenGL version - Added an Exit methof to the Viewer object that properly stops the viewer avoiding "after callit" error message - updated test_Fog.py to use verbose=False and exit properly - added lighting to check button list for objects properties and property inheritence - made buttons for clipping plane visibility use Set method so that the state will be saved - fixed SetPolyMode to maked back face mode = front face mode work again - moved state saving methods from ViewerGUI to Viewer - separated state saving methods into _cb and actual method - fixed some bugs in saving/restoring the state - removed RenderMode from IndexedPolygons - added restoreState, saveObjectsStates, saveViewerState and saveViewerAndObjectsStates methods - added entries under File menu to call these methods - replaced calling RenderMode by calling Set - modified menu construction to use POLYGON_MODES and SHADINGS - rplaced enable by enabled - made clipping plane buttons cause redraw - removed code of glPolygonOffset checking - viewer.currentScissor was not set when the current object was changed in the tree widget or when scissors were enabled/disabled - added auto depth cue button to Camera panel DejaVu/VolumeGeom.py - added _modifed = False at the end of the constructor - add draw method to volume geometry DejaVu/__init__.py - added New Release version - set __MGLTOOLSVersion__ - Replace RELEASE-VERSION by __MGLTOOLSVersion__ - set RELEASE_VERSION - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. DejaVu/colorMap.py - made ColorMapGUI use the same amster as the viewer - changed code in if __main__ section at the end to import a updated file from Tests...breaks when trying to create ColorMapGUI because of assert isinstance on line 392. - fix bug,so the oglwidget on the colorMapGUI is resize correctly. - the oglColorMapGuiwidget should be set to doube buffer. - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. - In fill_cb calls the mouseUp method instead of update. - Fixed a bug in the read method of colorMap. When reading a file, the current colorMap is reinitialized with the new data so the history stack needs to be reset to an empty list. - Fixed the write method of the colormap. - replaced the self.gui.rgbMap by self.gui.guiRamp and a typo - Fixed problem occuring when updating the GUI with a ramp longer or shorter than the current one. - Fixed problems of popRamp stepBack_cb, reset and resetAll. - Add an argument to popRamp to be able to specify the index (negative) of the ramp to pop. - When a ramp is popped from the history list it is not pushed back on. - Fixed the reset/resetAll and stepBack mechanism in the colorMapGui. - Fixed problems in ColorMap and ColorMapGUI. DejaVu/colorMapLegend.py - added _modifed = False at the end of the constructor - change made to use new opengltk (build with distutil) DejaVu/colorTool.py - added a check argument to glMaterialWithCheck to allow to force sending the color to GL even if it is the same as the previous one. Under MacOSX not sending the color results in wrong colors for cylinders :( - switch to new opengltk (build with distutil) - change import of module name - remove reference to bufarray, opengltk us Numeric now. - removed viewerConst.FPRECISION argument from colorTool.OneColor calls - modifed OneColor function to return lists or tupels instead of Numeric array DejaVu/tileRenderer.py - change to use new opengltk (build with distutil) - added backBuffer option to enableTileRendering - made image buffer 3byte per pixel - known problems: text might fail, need to implement trRasterPos3f stereo does not work for some sizes of windows, top tile is distorted - added support for tile rendering. to use it call vi.enableTileRendering() with an outputFile, a desired width or a height and an optional border vi.enableTileRendering(width=2000, outputFile='testpmv.jpg') DejaVu/viewerConst.py - added inherit and outlined to POLYGON_MODES - added inherit to SHADINGS - NO is now False and YES is true DejaVu/Tests/__init__.py - replaced all vi.GUI.Exit() by vi.Exit() - replaced all del vi bi vi.exit DejaVu/VisionInterface/DejaVuNodes.py - added node0.macroNetwork.runOnConnect = False before restoring connections in rotatScene macro and restor it's state after to avoid running the macro upon instanciation. FIXME this code shoudl be generated automatically. - added by hand node.autoRun=False and resore it for the flattenRotation node. This node is a Generic node and and its input and output ports can only be added after the node is added to the network. This was causing the execution of this node when the macro is instanciated. - removed stop and start auto redraw nodes from rotateScene macro - created a small class "SelectAxis", which is used in the RotateScene macro. - the user now selects the axis of rotation by 3 checkbox widgets - if no boxes are checked, then the scene is rotated around the y axis. - modified RotateScene macro to use custome node to flatten rotation matrix. The previous macro used getattr('flat') wich could not be restored from file - removed some spurious lines accidentally left in while testing NEBox class: - converted the origin and length of side inputs into individual thumbwheel widgits - added a "constrain scale" option, which maintains the proportions of the sides of the box as you increase or decrease the length of any of the sides - added some documentation for the class NE - fixed rotate scene macro: the inputPort trigger of the StopAutoRedraw node in the macro had been changed from type None to List. The output port begin of the iterate sent a boolean which caused the StopAutoRedraw node to fail to execute, then the loop was carried out while we were in AutoRedraw=True thus leading to the problem of slwoing down and blocking. - added SMFtoGeom, GeomtoSMF and QslimExt nodes - updated the portsDescr in all nodes: our new append method now understands passing values as keywords, i.e. instead of append({'name':'foo'}) we can now say append(name='foo') - removed all keys labelSide='left' from widgetDescr, since this is the default value. Moved all other labelSide keys into widgetGridCfg - in some of the macros that output data we needed to set singleConnection=True in the dynamically created ports of the MacroOutputNode - deleted the line kw['originalClass'] = MacroNode in all macro nodes since this is wrong. - fix bug: Geom instance was not known in the compute function of the node. - updated validate method of Geom type to accept list containing either geometry objects or lists of geoemtry objects (or any combination thereof) - Replaced the 3 DejaVu macros with the new macro code - renamed keyword autoSave to autoList in node Choose Geom NEComboBox widget descriptor - moved instanciation of ImageViewer in node NPR to beforeAddingToNetwork() - deleting node NPR now deletes the ImageViewer window - moved instanciation of TableMaker in node TransferFuncEditor to beforeAddingToNetwork() - replaced pyefit by geomutils package - added a new keyword autoSave, this allows to save just the current selection in "choices" - running the choose geom node now again sets the _modified flag in the NEComboBox widget which allows for proper saving/restoring - fixed 1DTexture to work with latest changes in opengltk: we now call glTexImage1D directly from _gllib rather than the Python wrapper - fixed the DejaVu Vision node 1DTexture to work with the latest changes - added stacklevel=2 to warnings.warn - import of stdlib and symlib is now done inside the macro code - removes setting DejaVu camera to ORTHOGRAPHIC mode when instantiating PmvVIewer - moved all the import library statements in beforeAddingToNetwork() methods to new helper functions importSymLib(), importImageLib(), and importVolLib() - added StopAutoRedraw, StartAutoRedraw, OneRedraw nodes - added RotateScene macro - replaced in all geometry nodes the test if name is not None by if name is not None and name!=self.geom.name[:len(name)]: to avoid renaming the geometry over and over which was causing huge slow down - made Viewer node destroy the Viewer instance in beforeRemovingFromNetwork and protected BeforeDisconnect against node' viewer being None - use ImageChops.multiply - fixed indentation bug in computational method of new ImageViewerNode - added ImageViewerNode - added NPR node to compute outlnes and composite with orginal image - Using the Browse Libraries GUI, the module DejaVuNodes displayed not only the vizlib but also stdlib and vollib. Fixed the import of these 2 libraries in the two newly added macro nodes. Final stage of renaming the ViPEr package: - replaced "ViPEr" with "Vision" - repaced /ViPEr with /VisionInterface - replaced "viper" with "vision" - removed double decalration of same output port. This causes an endless loop - worked on the documentation of colorMap node - fixed bug in Viewer - added node GeomContainer to create parent node to group geometries - added name and parent input ports to geometry nodes: GeomContainer IndexedPolylinesNE IndexedPolygonsNE Cylinders Spheres QConvexHull Ellipsoids GyrationSphere - added standard documentation to all these nodes - modified viewer to add the chain of parents of a node if they are not already in the viewer - added quality dial to cylinder node - changed the way the Viewer nodes adds the geoemtries - added self.resetModifiedTag() at the end of afterAddingToNetwork of all macro nodes to prevent macro from being save explicitely - added MapPotOnGeom macro node - fixed stereo translation setting macro - added macro node to set stereo separation - added import types in codeBeforeDisconnectof Viewer - Fixed a bug in TransferFuncEditor node: loading LUT from a file before running a network(meaning - loading a volume) would cause an error. - fixed nodes that used a method 'afterDisconnect', replaced that with the new mechanism (pass code to the respective port) - update the NEBox class. drawing docking box - added DistFromSphereToGeom node - shifted node source code to the left where appropriate, to make code editing in GUI more comfortable - fixed signature of all nodes with inputports that are not required (setting =None or =defaultvalue where applicable) this was changed in the following nodes: Viewer, SelectGeometry, IndexedPolylinesNE, IndexedPolygonsNE, GroupGeomsNE, ColorMap, ColorByRamp, NEBox, Cylinders, Spheres, QConvexHull, Ellipsoids, GyrationSphere, ComputeRMSD - made ports required in: SetInstances (port matrices),TTexture1D (port prop) - added decimate3DPoints node - made the radii port of sphere type None since it can handle list or float - updated datatypes to use width, height - small bugfix in RMSD node compute function - added node Compute RMSD to vizlib - fixed beforeDisconnect in Viewer node: in very rare cases, a geometry does yet not belong to a viewer so disconnecting would fail. Added test if g.viewer is not None - added new widget ColorEditor which is a rather sophisticated color editor - added a new node ColorEditor that exposes this widget in its param panel - QConvex nodes uses new method QH.getGeom() to get geom - added new node GyrationSphere - added color and instanceMatrices input ports for QConvex, Ellipsoid, GyrationSphere nodes - cleaned up code of all nodes (inputPortDescr and outputPortDescr in particular) - QConvexHull node is now only added to library if the module qconvex can be imported for a given platform - added support to input lists of lists of coords or just a single list of coords into the EllipsoidFit node - added entry to QConvexHull node to specify a directory to save the temp. files - fixed ConvexHull & both Ellipsoid nodes to use proper keywords in _init_ - added a test from None in list of geoemtries of viewer node - added cov_scale and ell_scale ports to fitEllipsoids node - added new nodes EllipsoidFit and Ellipsoids - fixed bug in GetVRML node that prevented it from running - changed Viewer node to open viewer GUI by double-clicking on node (and hide if double-clicked again) - added new node QConvexHull that computes convex hulls calling the external module QHULL. - added new node "Read STL" that allows to read a ASCII STL file and convert it into DejaVu IndexedPolygon(s) - removed UTVolRen node from this package and moved this to the new Volume package DejaVu/VisionInterface/DejaVuWidgets.py - widget set() method now also sets widget._modified=True - removed the key "ramp" from ColorMap getDescr() method. This is the actual widget value which should be accessed using the get() method - added new widget ColorEditor which is a rather sophisticated color editor - added a new node ColorEditor that exposes this widget in its param panel Release December 17, 2003 ------------------------ What's New (compared to release Sep 18 2003): - added self.inheritMaterial=0 in constructor sor box shows color by default - added quality kw word to Cylinders geometry constructor and Set metod - Geom's maxBB and minBB are set to None by default now. These can be used to specify a bounding box for objects that do not have vertices such as the volume renderer - ObjSubTreeBB was fixed to take into account maxBB and minBB values of None - added sortPoly method to Geom to recursively sort polygons in children - added self.redoDspLst = 1 for cull option, to force rebuilding dispaly list - added writeToFile method to IndexedPolygons object and function IndexedPolygonFromFile - added writeIndexedPolygon and readIndexedPolygon nodes to ViPEr library - removed import of GLUT which were not needed anymore - Use new TreeWidget to display object hierarchy (see mglutil/gui/BasicWidgets) - added a comamnd to apply transformation to a geoemtry's vertices (Edit->Apply Transformation) - Added support to be able to close the GUI using the [x] icon. Implemented a withdraw and deiconify method and added a new attribute shown which is set to True when the ViewerGUI is displayed and to False when not. - Implemented a dismiss and quit method for the colorMap gui. One withdraw the gui the other destroys it. - Modified the ColorMap so it can be created with a colormap legend object which will be added to a viewer is specified when a colormapgui is created for that colormap. - A colorMap is now associated with one gui which is withdrawn instead of destroyed. - The colorMap is updated the same way than the geometry. So if the colorMap is in continuous mode the colormap legend will be in continuous mode as well. Fixed some problems with the ColorMapLegend. - added afterConnect method to UTVolumeRender node for the geometries to be aware of the viewer as soon as it gets connected - added AddGrid3D method to UTVolRenGeom and made UtVolRen node use this method - also protected UTVolRenGeom against initializing VolumeRenderer if not OpenGL context is available. This was causing segmentattion faults - added a new datatype RGBColorType (one color, versus RGBColorsType) - updated the ColorChooser Node: it got a param. panel with a thumbwheel for color brightness, a checkbutton for alpha value yes/no and a checkbutton for output the color encapsulated in another list or not - added quality and radii thumbwheels in Spheres node Backwards imcompatible modifications: - moved Isocontour node to Volume library - modified UTVolRen node to accept Grid3D object Bug Fixes - in orthographic projection mode the configure event were not handled properly fixed that - added self.redoDspLst for Set(radii) - fixed bug that caused container objects to use -1. 1. as their bounding box when they had no vertices, this caused the obejcts not to center properly - fixed reset normalize center to be applied to root object is transform root only is on - fixed deadlock issue in AddObject and RemoveObject methods when an exception is raised - added support in ReallyRedraw to handle camera.exposeEvent - made lineWidth and PointWidth slide force inherit flag to 0 - made the Viewer port of the Redraw multiConnections - Set the inheritXform argument to 0 when creating the ColorMapLegend object so that the legend is not transformed. - Fixed a bunch of problems in colorMapGui: -1 When changing the mini and maxi value of the gui and Apply the mini and maxi value of the cmap were not updated. -2 When using intervals the redraw of the ogl widget was all screwed up now the fill_cb just calls the mouseDown, mouseMotion and mouseUp method of the colorMapGui class with the proper event. - Removed the deepCopyRamp from the ColorMap class and moved it to the mglutil.util.misc module under the name of deepCopySeq and used this new function to deep copy the various sequence. - rewrote doit method of Viewer node (greatly simplified) - Fixed bug in Spheres node - made NEColorMap widget use configure and return lists rather than arrays for getDataForSaving - fixed a bug in SetInstances node, which was not working at all because singleValue was set to 1 for port geometries. Also added a beforeAdding() method to load symlib for this node - replaced widget.setlist by configure(choices=list) - bugfix in Viewer node: users can no longer kill the Camera window - made lineWidth and PointWidth slide force inherit flag to 0 - fixed ColorChooser widget so that it can be saved again. - fixed addLibrary statement (being addLibraryInstance now) - fixed getDpyList updated to handle transparent object. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Release September 18, 2003 ------------------------ What's New (compared to release Feb 26 2003): ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Release February 26, 2003 ------------------------- mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/viewerConst.py0000644000175000017500000000700611240611606022547 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/viewerConst.py,v 1.18 2009/08/12 19:09:58 vareille Exp $ # # $Id: viewerConst.py,v 1.18 2009/08/12 19:09:58 vareille Exp $ # import numpy.oldnumeric as Numeric from opengltk.OpenGL import GL FPRECISION = Numeric.Float32 IPRECISION = Numeric.Int32 INHERIT = -1 NO = False YES = True # binding modes for normals and colors OVERALL = 10 PER_VERTEX = 11 PER_PART = 12 PER_INSTANCE = 13 ## FIXME these constances are defined here AND in Materials.py ! propConst = ( GL.GL_AMBIENT, GL.GL_DIFFUSE, GL.GL_EMISSION, GL.GL_SPECULAR, GL.GL_SHININESS ) propNum = { GL.GL_AMBIENT:0, GL.GL_DIFFUSE:1, GL.GL_EMISSION:2, GL.GL_SPECULAR:3, GL.GL_SHININESS:4 } # constants for properties status and computation NONE = 20 UNKNOWN = 21 TOO_MANY = 22 TOO_FEW = 23 COMPUTED = 24 SET = 25 # constants for properties computation NO_COMPUTATION = 30 AUTO = 31 #drawBB values NO = NO ONLY = 41 # BB only WITHOBJECT = 42 # BB and object BB_MODES = (NO, ONLY, WITHOBJECT) OUTLINED = 50 Front_POLYGON_MODES_keys = ('point', 'line', 'fill', 'outlined', 'inherit') Front_POLYGON_MODES_values = (GL.GL_POINT, GL.GL_LINE, GL.GL_FILL, OUTLINED, INHERIT) Back_POLYGON_MODES_keys = ('point', 'line', 'fill', 'outlined', 'inherit', 'as front') Back_POLYGON_MODES_values = (GL.GL_POINT, GL.GL_LINE, GL.GL_FILL, OUTLINED, INHERIT, GL.GL_FRONT_AND_BACK) POLYGON_MODES = dict(zip(Back_POLYGON_MODES_keys, Back_POLYGON_MODES_values)) POLYGON_MODES_REV = dict(zip(Back_POLYGON_MODES_values, Back_POLYGON_MODES_keys)) #POLYGON_MODES['as front'] = GL.GL_FRONT_AND_BACK #POLYGON_MODES[GL.GL_FRONT_AND_BACK] = 'as front' POINTS_PRIMITIVES = (GL.GL_POINTS, ) LINES_PRIMITIVES = (GL.GL_LINES, GL.GL_LINE_LOOP, GL.GL_LINE_STRIP ) POLYGON_PRIMITIVES = (GL.GL_TRIANGLES, GL.GL_TRIANGLE_STRIP, GL.GL_TRIANGLE_FAN, GL.GL_QUADS, GL.GL_QUAD_STRIP, GL.GL_POLYGON) PRIMITIVES = POINTS_PRIMITIVES + LINES_PRIMITIVES + POLYGON_PRIMITIVES MINIMUM_LENGTH = { GL.GL_POINTS:1, GL.GL_LINES:2, GL.GL_LINE_LOOP:3, GL.GL_LINE_STRIP:3, GL.GL_TRIANGLES:3, GL.GL_TRIANGLE_STRIP:4, GL.GL_TRIANGLE_FAN:4, GL.GL_QUADS:4, GL.GL_QUAD_STRIP:5, GL.GL_POLYGON:3 } SHADINGS = {'flat':GL.GL_FLAT, 'smooth':GL.GL_SMOOTH, 'inherit':INHERIT} SHADINGS_REV = {GL.GL_FLAT:'flat', GL.GL_SMOOTH:'smooth', INHERIT:'inherit'} CULLINGS_keys = ('none', 'back', 'front', 'front_and_back', 'inherit') CULLINGS_values = (GL.GL_NONE, GL.GL_BACK, GL.GL_FRONT, GL.GL_FRONT_AND_BACK, INHERIT) CULLINGS = dict(zip(CULLINGS_keys, CULLINGS_values)) CULLINGS_REV = dict(zip(CULLINGS_values, CULLINGS_keys)) srcBFnames_keys = ( 'GL_ZERO', 'GL_ONE', 'GL_DST_COLOR', 'GL_ONE_MINUS_DST_COLOR', 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA', 'GL_DST_ALPHA', 'GL_ONE_MINUS_DST_ALPHA', 'GL_SRC_ALPHA_SATURATE' ) srcBFnames_values = ( GL.GL_ZERO, GL.GL_ONE, GL.GL_DST_COLOR, GL.GL_ONE_MINUS_DST_COLOR, GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_DST_ALPHA, GL.GL_ONE_MINUS_DST_ALPHA, GL.GL_SRC_ALPHA_SATURATE ) srcBFnames = dict(zip(srcBFnames_keys, srcBFnames_values)) srcBFnames_REV = dict(zip(srcBFnames_values, srcBFnames_keys)) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/glfLabels.py0000644000175000017500000011156012032615115022132 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: May 2006 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # ######################################################################### # # $Header$ # # $Id$ # import os import numpy.oldnumeric as Numeric import types import math import warnings import Tkinter import Pmw from opengltk.OpenGL import GL from opengltk.extent.utillib import glCleanRotMat from mglutil.math import rotax from mglutil.math.VectorModule import Vector from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from DejaVu.Geom import Geom from DejaVu.viewerFns import checkKeywords from DejaVu import viewerConst from DejaVu.colorTool import glMaterialWithCheck, resetMaterialMemory from DejaVu.IndexedPolygons import IndexedPolygons from pyglf import glf class GlfLabels(Geom): """Class for sets of 3d labels """ keywords = Geom.keywords + [ 'billboard', 'font', 'fontRotateAngles', 'fontScales', 'fontSpacing', 'fontStyle', 'fontTranslation', 'labelTranslation', 'includeCameraRotationInBillboard', 'labels', ] bitmapFont3dList = [ # 'arbat.bmf', # 'arial.bmf', # 'brushtype.bmf', # 'chicago.bmf', # 'courier.bmf', # 'cricket.bmf', # 'crystal.bmf', # 'fixedsys.bmf', # 'gals.bmf', # 'greek.bmf', # 'impact.bmf', # 'proun.bmf', # 'techno.bmf', # 'times_new.bmf' ] vectorFont3dList = [ 'arial1.glf', 'courier1.glf', 'crystal1.glf', 'techno0.glf', 'techno1.glf', 'times_new1.glf', 'aksent1.glf', 'alpine1.glf', 'broadway1.glf', 'chicago1.glf', 'compact1.glf', 'cricket1.glf', 'garamond1.glf', 'gothic1.glf', 'penta1.glf', 'present_script1.glf'] fontList = vectorFont3dList + bitmapFont3dList fontStyleDict = { 'solid': glf.glfDrawSolidString, 'solid3d': glf.glfDraw3DSolidString, 'wire': glf.glfDrawWiredString, 'wire3d': glf.glfDraw3DWiredString, } fontStyleList = fontStyleDict.keys() def __init__(self, name=None, check=1, **kw): #print "GlfLabels::__init__" if not kw.get('shape'): kw['shape'] = (0,3) if not kw.get('labels'): kw['labels'] = ['Aa'] if kw.get('billboard') is None: kw['billboard'] = True if kw.get('includeCameraRotationInBillboard') is None: kw['includeCameraRotationInBillboard'] = False if not kw.get('font'): kw['font'] = self.fontList[0] if not kw.get('fontStyle'): kw['fontStyle'] = 'solid' if not kw.get('fontSpacing'): kw['fontSpacing'] = .2 if not kw.get('fontScales'): kw['fontScales'] = (1, 1, 1) if not kw.get('fontRotateAngles'): kw['fontRotateAngles'] = (0, 0, 0) if not kw.get('fontTranslation'): kw['fontTranslation'] = (0, 0, 0) if not kw.get('labelTranslation'): kw['labelTranslation'] = None # Glf initialisations glf.glfInit() # usefull glf messages (like "font not found") glf.glfEnable(glf.GLF_CONSOLE_MESSAGES) # we manage this through the opengl Z scale. (we have to make a call to glScale anyway) glf.glfSetSymbolDepth(.8) # .2 is C code default value (it is not deep enough) #contouring is far from being nice in the glf 1.4 C code! So we don't use it. #glf.glfDisable(glf.GLF_CONTOURING) # C code default value #glf.glfDisable(glf.GLF_TEXTURING) # C code default value # loading BMF fonts has to be done after the context exists # otherwise nothing appears self.vectorFonts = {} self.bitmapFonts = {} apply( Geom.__init__, (self, name, check), kw) # make ambient to be same as diffuse mat = self.materials[GL.GL_FRONT] mat.getFrom[mat.ambient] = [mat.diffuse, 1.] self.labelTranslation = None def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ #print "Set glfLabels" redoFlags = apply( Geom.Set, (self, check, 0), kw ) labels = kw.get('labels') if labels: kw.pop('labels') self.labels = list(labels) redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] billboard = kw.get('billboard') if billboard is not None: kw.pop('billboard') self.billboard = billboard self.immediateRendering = billboard redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] includeCameraRotationInBillboard = kw.get('includeCameraRotationInBillboard') if includeCameraRotationInBillboard is not None: kw.pop('includeCameraRotationInBillboard') self.includeCameraRotationInBillboard = includeCameraRotationInBillboard redoFlags |= self._redoFlags['updateOwnGuiFlag'] font = kw.get('font') if not font is None: # loading BMF fonts has to be done after the context exists # otherwise nothing appears kw.pop('font') lGlfModulePath = os.path.split(glf.__file__)[-2] lPathToFonts = lGlfModulePath+os.sep+'fonts'+os.sep if font in self.vectorFont3dList: self.fontTypeIsVector = True if font not in self.vectorFonts: self.vectorFonts[font] = glf.glfLoadFont(lPathToFonts+font) self.font = font redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] elif font in self.bitmapFont3dList: self.fontTypeIsVector = False if font not in self.bitmapFonts: self.bitmapFonts[font] = glf.glfLoadBMFFont(lPathToFonts+font) self.font = font redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] else: warnings.warn('not a glf font %s'%font) fontStyle = kw.get('fontStyle') if fontStyle is not None: kw.pop('fontStyle') assert fontStyle in self.fontStyleList self.fontStyle = fontStyle redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] fontSpacing = kw.get('fontSpacing') if fontSpacing is not None: # this set the space between letters #glf.glfSetSymbolSpace(.2) # C code default value kw.pop('fontSpacing') self.fontSpacing = fontSpacing redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] fontScales = kw.get('fontScales') if fontScales is not None: kw.pop('fontScales') self.fontScales = fontScales redoFlags |= self._redoFlags['redoDisplayListFlag'] fontRotateAngles = kw.get('fontRotateAngles') if fontRotateAngles is not None: kw.pop('fontRotateAngles') self.fontRotateAngles = fontRotateAngles redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] fontTranslation = kw.get('fontTranslation') if fontTranslation is not None: kw.pop('fontTranslation') self.fontTranslation = fontTranslation redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] labelTranslation = kw.get('labelTranslation') if labelTranslation is not None: kw.pop('labelTranslation') assert labelTranslation.shape == self.vertexSet.vertices.array.shape self.labelTranslation = labelTranslation redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['updateOwnGuiFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def getState(self, full=False): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ state = Geom.getState(self, full).copy() state.update( self.getSubClassState() ) return state def getSubClassState(self): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ state = { 'billboard': self.billboard, 'font': self.font, 'fontRotateAngles': self.fontRotateAngles, 'fontScales': self.fontScales, 'fontSpacing': self.fontSpacing, 'fontStyle': self.fontStyle, 'fontTranslation': self.fontTranslation, 'labelTranslation': self.labelTranslation, 'includeCameraRotationInBillboard': self.includeCameraRotationInBillboard, 'labels': self.labels, } return state def Add(self, check=1, redo=1, **kw): """Add glfLabels """ #print "Add glfLabels" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) v = kw.get('vertices') if v: self.redoDspLst = 1 labels = kw.get( 'labels') if labels: #labels is apparently a tuple self.labels = self.labels + labels self.redoDspLst = 1 Geom.Add( self, check=0, redo=0, vertices = kw.get( 'vertices'), materials = kw.get( 'materials') ) if self.viewer and redo: if self.redoDspLst: self.viewer.objectsNeedingRedo[self] = None def drawOne3dTextLine(self, textLine, index): c = self.vertexSet.vertices.array n = self.vertexSet.normals.array if self.labelTranslation is not None: labelTrans =self.labelTranslation[index] else: labelTrans = (0,0,0) lenn = len(n) try: GL.glPushMatrix() GL.glTranslatef( float(c[index][0]), float(c[index][1]), float(c[index][2]), ) if self.billboard: GL.glMultMatrixf(self.billboardRotation) elif lenn == len(c): lMat = rotax.rotVectToVect(n[index] , (0,0,1) ) lMat = [ lMat[0][0], lMat[0][1], lMat[0][2], lMat[0][3], lMat[1][0], lMat[1][1], lMat[1][2], lMat[1][3], lMat[2][0], lMat[2][1], lMat[2][2], lMat[2][3], lMat[3][0], lMat[3][1], lMat[3][2], lMat[3][3] ] GL.glMultMatrixf(lMat) elif lenn > 0: GL.glMultMatrixf(self.orientation) GL.glTranslatef( float(labelTrans[0]), float(labelTrans[1]), float(labelTrans[2]), ) GL.glTranslatef( float(self.fontTranslation[0]), float(self.fontTranslation[1]), float(self.fontTranslation[2]), ) GL.glRotatef(float(self.fontRotateAngles[2]), 0., 0., 1., ) GL.glRotatef(float(self.fontRotateAngles[1]), 0., 1., 0., ) GL.glRotatef(float(self.fontRotateAngles[0]), 1., 0., 0., ) if self.fontTypeIsVector: GL.glScalef(float(self.fontScales[0]), float(self.fontScales[1]), float(self.fontScales[2])) if textLine is not None: self.fontStyleDict[self.fontStyle](textLine) else: GL.glScalef(float(self.fontScales[0])*40, float(self.fontScales[1])*40, 0) # to be the same size as vector fonts if textLine is not None: glf.glfDrawBString(textLine) finally: if textLine is None: lMatrix = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX) GL.glPopMatrix() return lMatrix else: GL.glPopMatrix() def prepareBillboardAndNormalForAllTextLines(self): if self.billboard: m = self.GetMatrix() m = Numeric.reshape(m, (16,)) rot = glCleanRotMat(m) #much faster than self.Decompose4x4(m) if self.includeCameraRotationInBillboard: # this permit billboarding even if the camera is not in the Z axis lCameraTransformation = self.viewer.currentCamera.GetMatrix() lCameraTransformation = Numeric.reshape(lCameraTransformation, (16,)) lCameraRotation = glCleanRotMat(lCameraTransformation) #much faster than self.Decompose4x4(m) lCameraRotation = Numeric.transpose(lCameraRotation) rot = Numeric.dot(lCameraRotation, rot) rot = Numeric.reshape(rot, (16,)) self.billboardRotation = rot.astype('f') else: c = self.vertexSet.vertices.array n = self.vertexSet.normals.array lenn = len(n) if lenn > 0 and lenn != len(c): lMat = rotax.rotVectToVect(n[0] , (0,0,1) ) self.orientation = [ lMat[0][0], lMat[0][1], lMat[0][2], lMat[0][3], lMat[1][0], lMat[1][1], lMat[1][2], lMat[1][3], lMat[2][0], lMat[2][1], lMat[2][2], lMat[2][3], lMat[3][0], lMat[3][1], lMat[3][2], lMat[3][3] ] def Draw(self): #print "GlfLabels.Draw", self centers = self.vertexSet.vertices.array if len(centers)==0: return labels = self.labels if labels is None or len(labels) == 0: return elif len(labels) == centers.shape[0]: txt = None else: txt = labels[0] if type(txt) != types.StringType: txt= str(txt) self.prepareBillboardAndNormalForAllTextLines() glf.glfSetSymbolSpace(self.fontSpacing) if self.fontTypeIsVector: font = self.vectorFonts[self.font] glf.glfSetCurrentFont(font) else: font = self.bitmapFonts[self.font] glf.glfSetCurrentBMFFont(font) glf.glfStartBitmapDrawing() resetMaterialMemory() if self.inheritMaterial: fp = None bp = None else: self.InitMaterial() colorFront = Numeric.array(self.materials[GL.GL_FRONT].prop[1], copy=1) fp = self.materials[GL.GL_FRONT] if fp.binding[1] == viewerConst.OVERALL: GL.glColor4fv(colorFront[0]) bp = None face = GL.GL_FRONT_AND_BACK else: bp = self.materials[GL.GL_BACK] face = GL.GL_FRONT ## if fp: ## for m in (0,1,2,3,4): ## if fp.binding[m] == viewerConst.OVERALL: ## glMaterialWithCheck( face, ## viewerConst.propConst[m], ## fp.prop[m][0]) ## if fp.binding[1] == viewerConst.OVERALL: ## GL.glColor4fv(colorFront[0]) for i in xrange(centers.shape[0]): if fp: for m in (0,1,2,3,4): if fp.binding[m] == viewerConst.PER_VERTEX: b, p = fp.GetProperty(m) glMaterialWithCheck( face, viewerConst.propConst[m], p[i] ) if fp.binding[1] != viewerConst.OVERALL: GL.glColor4fv(colorFront[i]) if bp: for m in (0,1,2,3,4): if bp.binding[m] == viewerConst.PER_VERTEX: b, p = bp.GetProperty(m) glMaterialWithCheck( face, viewerConst.propConst[m], p[i] ) #GL.glPushName(i) if txt is None: txt2 = self.labels[i] if type(txt2) != types.StringType: txt2 = str(txt2) self.drawOne3dTextLine(txt2, i) else: self.drawOne3dTextLine(txt, i) #GL.glPopName() if self.fontTypeIsVector is False: glf.glfStopBitmapDrawing() return 1 def asIndexedPolygons(self, run=1, removeDupVerts=0, **kw): """Should return an IndexedPolygons object if this object can be represented using triangles, else return None. run=0 returns 1 if this geom can be represented as an IndexedPolygon and None if not run=1 returns the IndexedPolygon object. """ #print "GlfLabels::asIndexedPolygons" #import pdb;pdb.set_trace() if run == 0: return 1 # yes, I can be represented as IndexedPolygons self.prepareBillboardAndNormalForAllTextLines() lLenLabelsVertices = len(self.vertexSet.vertices.array) if lLenLabelsVertices != len(self.labels): lSameText = True assert len(self.labels) > 0 if type(self.labels[0]) == types.StringType: output = glf.glfGet3DSolidStringTriangles(self.labels[0]) else: output = glf.glfGet3DSolidStringTriangles( str(self.labels[0]) ) lNumOfTriangleVertices = len(output[0]) assert lNumOfTriangleVertices == len(output[1]) #assert is a multiple of 3 else: lSameText = False if lLenLabelsVertices != len(self.vertexSet.normals.array): if len(self.vertexSet.normals.array) > 0: lSameOrientation = True lLocalNormal = self.normals[0] else: lLocalNormal = None self.prepareBillboardAndNormalForAllTextLines() lOverallTriangles = [] lOverallVertices = [] lOverallTrianglesColors = [] for i in range(lLenLabelsVertices): #print "i", i if lSameText is False: if type(self.labels[0]) == types.StringType: output = glf.glfGet3DSolidStringTriangles(self.labels[i]) else: output = glf.glfGet3DSolidStringTriangles( str(self.labels[i]) ) lNumOfTriangleVertices = len(output[0]) assert lNumOfTriangleVertices == len(output[1]) #assert is a multiple of 3 colorFront = Numeric.array(self.materials[GL.GL_FRONT].prop[1], copy=1) lNumOfOverallVertices = len(lOverallVertices) for j in range( lNumOfOverallVertices, lNumOfOverallVertices+lNumOfTriangleVertices, 3): lOverallTriangles.append( ( j, j+1, j+2 ) ) lOverallTrianglesColors.append(colorFront[i]) lMatrix = self.drawOne3dTextLine(None, i) lMatrix.shape = (4, 4) for j in range(lNumOfTriangleVertices): lVertexBeforeTransform = output[0][j] lVertex = [] lVertex.append( lMatrix[0][0] * lVertexBeforeTransform[0] \ + lMatrix[1][0] * lVertexBeforeTransform[1] \ + lMatrix[2][0] * lVertexBeforeTransform[2] \ + lMatrix[3][0] ) lVertex.append( lMatrix[0][1] * lVertexBeforeTransform[0] \ + lMatrix[1][1] * lVertexBeforeTransform[1] \ + lMatrix[2][1] * lVertexBeforeTransform[2] \ + lMatrix[3][1] ) lVertex.append( lMatrix[0][2] * lVertexBeforeTransform[0] \ + lMatrix[1][2] * lVertexBeforeTransform[1] \ + lMatrix[2][2] * lVertexBeforeTransform[2] \ + lMatrix[3][2] ) lOverallVertices.append(lVertex) lIndexedPolygons = IndexedPolygons( self.name+'_glfTriangles', vertices=lOverallVertices, faces=lOverallTriangles, materials=lOverallTrianglesColors, visible=1, invertNormals=self.invertNormals, ) return lIndexedPolygons def createOwnGui(self): #print "GlfLabels.createOwnGui", self self.ownGui = Tkinter.Toplevel() self.ownGui.title(self.name) self.ownGui.protocol('WM_DELETE_WINDOW', self.ownGui.withdraw ) frame1 = Tkinter.Frame(self.ownGui) frame1.pack(side='top') # labels self.ownGui.labelsEnt = Pmw.EntryField( frame1, label_text='list of labels', labelpos='w', value=str(self.labels), command=self.setWithOwnGui) self.ownGui.labelsEnt.pack(side='top', fill='x') # billboard self.ownGui.billboardVar = Tkinter.IntVar() self.ownGui.billboardVar.set(self.billboard) self.ownGui.guiBillboard = Tkinter.Checkbutton( frame1, text='billboard', variable=self.ownGui.billboardVar, command=self.setWithOwnGui) self.ownGui.guiBillboard.pack(side='top', fill='x') # includeCameraRotationInBillboard self.ownGui.includeCameraRotationInBillboardVar = Tkinter.IntVar() self.ownGui.includeCameraRotationInBillboardVar.set(self.includeCameraRotationInBillboard) self.ownGui.guiIncludeCameraRotationInBillboard = Tkinter.Checkbutton( frame1, text='includeCameraRotationInBillboard', variable=self.ownGui.includeCameraRotationInBillboardVar, command=self.setWithOwnGui) self.ownGui.guiIncludeCameraRotationInBillboard.pack(side='top', fill='x') # # lighting # self.ownGui.lightingVar = Tkinter.IntVar() # self.ownGui.lightingVar.set(self.lighting) # self.ownGui.guiLighting = Tkinter.Checkbutton( # frame1, # text='lighting', # variable=self.ownGui.lightingVar, # command=self.setWithOwnGui) # self.ownGui.guiLighting.pack(side='top', fill='x') # font self.ownGui.guiFontComboBox = Pmw.ComboBox( frame1, label_text='font', labelpos='w', entryfield_value=self.font, scrolledlist_items=self.fontList, selectioncommand=self.setWithOwnGui ) self.ownGui.guiFontComboBox.pack(side='top', fill='x') # font style self.ownGui.guiFontStyleComboBox = Pmw.ComboBox( frame1, label_text='font style', labelpos='w', entryfield_value=self.fontStyle, scrolledlist_items=self.fontStyleList, selectioncommand=self.setWithOwnGui ) self.ownGui.guiFontStyleComboBox.pack(side='top', fill='x') # font spacing self.ownGui.guiSpacing = ThumbWheel( frame1, labCfg={'text':'font spacing', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=self.fontSpacing, callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiSpacing.pack(side='top', fill='x') # font global scale self.ownGui.guiGlobalScale = ThumbWheel( frame1, labCfg={'text':'global scale', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=1., callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiGlobalScale.pack(side='top', fill='x') # font scale X self.ownGui.guiScaleX = ThumbWheel( frame1, labCfg={'text':'scale X', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=self.fontScales[0], callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiScaleX.pack(side='top', fill='x') # font scale Y self.ownGui.guiScaleY = ThumbWheel( frame1, labCfg={'text':'scale Y', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=self.fontScales[1], callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiScaleY.pack(side='top', fill='x') # font scale Z self.ownGui.guiScaleZ = ThumbWheel( frame1, labCfg={'text':'scale Z', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=self.fontScales[2], callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiScaleZ.pack(side='top', fill='x') # font Translate X self.ownGui.guiTranslateX = ThumbWheel( frame1, labCfg={'text':'translate X', 'side':'left'}, showLabel=1, width=80, height=16, #min=0, #max=100, type=float, value=self.fontTranslation[0], callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiTranslateX.pack(side='top', fill='x') # font Translate Y self.ownGui.guiTranslateY = ThumbWheel( frame1, labCfg={'text':'translate Y', 'side':'left'}, showLabel=1, width=80, height=16, #min=0, #max=100, type=float, value=self.fontTranslation[1], callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiTranslateY.pack(side='top', fill='x') # font Translate Z self.ownGui.guiTranslateZ = ThumbWheel( frame1, labCfg={'text':'translate Z', 'side':'left'}, showLabel=1, width=80, height=16, #min=0, #max=100, type=float, value=self.fontTranslation[2], callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiTranslateZ.pack(side='top', fill='x') # font Rotate X self.ownGui.guiRotateX = ThumbWheel( frame1, labCfg={'text':'Rotate X', 'side':'left'}, showLabel=1, width=80, height=16, min=-180, max=180, type=float, value=self.fontRotateAngles[0], callback=self.setWithOwnGui, continuous=True, oneTurn=90, wheelPad=2 ) self.ownGui.guiRotateX.pack(side='top', fill='x') # font Rotate Y self.ownGui.guiRotateY = ThumbWheel( frame1, labCfg={'text':'Rotate Y', 'side':'left'}, showLabel=1, width=80, height=16, min=-180, max=180, type=float, value=self.fontRotateAngles[1], callback=self.setWithOwnGui, continuous=True, oneTurn=90, wheelPad=2 ) self.ownGui.guiRotateY.pack(side='top', fill='x') # font Rotate Z self.ownGui.guiRotateZ = ThumbWheel( frame1, labCfg={'text':'Rotate Z', 'side':'left'}, showLabel=1, width=80, height=16, min=-180, max=180, type=float, value=self.fontRotateAngles[2], callback=self.setWithOwnGui, continuous=True, oneTurn=90, wheelPad=2 ) self.ownGui.guiRotateZ.pack(side='top', fill='x') def setWithOwnGui(self, event=None): """ """ #print "setWithOwnGui", event lGlobalScale = self.ownGui.guiGlobalScale.get() self.Set(labels=eval(self.ownGui.labelsEnt.get()), billboard=self.ownGui.billboardVar.get(), includeCameraRotationInBillboard=self.ownGui.includeCameraRotationInBillboardVar.get(), #lighting=self.ownGui.lightingVar.get(), font=self.ownGui.guiFontComboBox.get(), fontStyle=self.ownGui.guiFontStyleComboBox.get(), fontSpacing=self.ownGui.guiSpacing.get(), fontScales = ( lGlobalScale*self.ownGui.guiScaleX.get(), lGlobalScale*self.ownGui.guiScaleY.get(), lGlobalScale*self.ownGui.guiScaleZ.get() ), fontTranslation = ( self.ownGui.guiTranslateX.get(), self.ownGui.guiTranslateY.get(), self.ownGui.guiTranslateZ.get() ), fontRotateAngles = ( self.ownGui.guiRotateX.get(), self.ownGui.guiRotateY.get(), self.ownGui.guiRotateZ.get() ), updateOwnGui=False) def updateOwnGui(self): self.ownGui.title(self.name) self.ownGui.labelsEnt.setvalue(str(self.labels)) self.ownGui.billboardVar.set(self.billboard) self.ownGui.includeCameraRotationInBillboardVar.set(self.includeCameraRotationInBillboard) #self.ownGui.lightingVar.set(self.lighting) self.ownGui.guiFontComboBox.selectitem(self.font) self.ownGui.guiFontStyleComboBox.selectitem(self.fontStyle) self.ownGui.guiSpacing.set(self.fontSpacing, update=0) self.ownGui.guiGlobalScale.set(1., update=0) self.ownGui.guiScaleX.set(self.fontScales[0], update=0) self.ownGui.guiScaleY.set(self.fontScales[1], update=0) self.ownGui.guiScaleZ.set(self.fontScales[2], update=0) self.ownGui.guiTranslateX.set(self.fontTranslation[0], update=0) self.ownGui.guiTranslateY.set(self.fontTranslation[1], update=0) self.ownGui.guiTranslateZ.set(self.fontTranslation[2], update=0) self.ownGui.guiRotateX.set(self.fontRotateAngles[0], update=0) self.ownGui.guiRotateY.set(self.fontRotateAngles[1], update=0) self.ownGui.guiRotateZ.set(self.fontRotateAngles[2], update=0) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/gelato.py0000644000175000017500000007427311245060670021530 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # adapted From povray3.py ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/gelato.py,v 1.2 2009/08/25 22:12:08 autin Exp $ # # $Id: gelato.py,v 1.2 2009/08/25 22:12:08 autin Exp $ # """ Povray module: driver to generate PovRay scenes form a DejaVu scene The driver currently handles: camera parameters (background color, perpective parameters, position), light sources, and Spheres, IndexedPolygons and IndexedPolylines geometries. The projection is still somewhat approximative ! still a 10 translation that is not explained :(. """ #from ARViewer import util from opengltk.OpenGL import GL #from opengltk.extent.utillib import glTriangleNormals from geomutils.geomalgorithms import TriangleNormals from DejaVu import viewerConst from mglutil.math import rotax from numpy import matrix import numpy.oldnumeric as Numeric import numpy.oldnumeric as N PROJ={ 1:"orthographic", 0:"perspective" } class Shader: ShaderDic={"plastic" : [ "\"float Ka\", 0", "\"float Kd\", 1", "\"float Ks\", 0.75", "\"float roughness\", 0.05"], "glass" : [ "\"float Ka\", 0.2", "\"float Kd\", 0.25", "\"float Ks\", 0.4", "\"float roughness\", 0.1", "\"string envname\",\"reflection\"", "\"float Kr\", 0.5", "\"float samples\", 4"], "clay" : [ "\"float Ka\", 0.9", "\"float Kd\", 1", "\"float roughness\", 0.2"], "shinyplastic" : [ "\"float Ks\", 0.9", "\"float Kd\", 1", "\"float eta\", 1.5", "\"string envname\", \"reflection\""], "plasticss" : [ "\"float Ks\", 0.9", "\"float Kd\", 1", "\"float Kss\", 1"], "metal" : [ "\"float Ka\", 1.0", "\"float Kd\", 0.5", "\"float Ks\", 0.8", "\"float roughness\", 0.2", "\"string envname\",\"reflection\"", "\"float Kr\", 0.5", "\"float samples\", 4"], "ambocclude" : [ "\"string occlusionname\",\"localocclusion\"", "\"float samples\", 256", "\"float bias\", 0.01"], "greenmarble" : [ "\"float Ka\", 0.1", "\"float Kd\", 0.6", "\"float Ks\", 0.4", "\"float roughness\", 0.1", "\"float veinfreq\", 1", "\"float sharpness\", 25", "\"float shadingfreq\", 1"], "oak" : [ "\"float Ka\", 1", "\"float Kd\", 1", "\"float Ks\", 0.25", "\"float roughness\", 0.25", "\"float divotdepth\", 0.5", "\"float ringy\", 1", "\"float ringfreq\", 8", "\"float ringunevenness\", 0.3", "\"float ringnoise\", 0.02", "\"float ringnoisefreq\", 1", "\"float trunkwobble\", 0.15", "\"float trunkwobblefreq\", 0.025", "\"float angularwobble\", 0.15", "\"float angularwobblefreq\", 0.025", "\"float grainy\", 1", "\"float grainfreq\", 8", "\"float shadingfreq\", 1"], "screen" : [ "\"float Ka\", 1.0", "\"float Kd\", 0.75", "\"float Ks\", 0.4", "\"float roughness\", 0.1", "\"float sfreq\", 10", "\"float tfreq\", 10", "\"float sdensity\", 10", "\"float tdensity\", 10"], "soapbubble" : [ "\"float Ka\", 0.2", "\"float Kd\", 0.25", "\"float Ks\", 0.4", "\"float roughness\", 0.1", "\"string envname\", \"reflection\"", "\"float Kr\", 0.5", "\"float samples\", 4", "\"float fakerefract\", 1"], "shownormals" : [ "\"float bias\", 1"], "showfacing" : [ "\"float Ka\", 0.25", "\"float Kd\", 0.75"] } def __init__(self): self.name="" self.Type="surface" self.parameters=[] def vec3(self, x, y=None, z=None): """string <- vec3(x, y=None, z=None) returns a povray vector string this function does not invert the z coordinates. It can be called with a sequence of 3 or with 3 values. """ if y is None: return ' (%.2f, %.2f, %.2f) '% (x[0],x[1],x[2]) else: return ' (%.2f, %.2f, %.2f) '% (x, y, z) def addParameters(typ,name,value): if typ == "float" : self.parameters.append('"float %s", %f' % (typ,name,value)) elif typ == "string" : self.parameters.append('"string %s", %s' % (typ,name,value)) elif typ == "color" : self.parameters.append('"color %s", %s' % (typ,name,self.vec3(value))) class Gelato: """Driver for Povray v3.x """ def __init__(self, shaderD=None,includes = []): """Create a PovRay file generator class for a given camera""" self.camera = None self.PRECISION = 6 if shaderD== None : self.shaderDic=Shader.ShaderDic else : self.shaderDic=shaderD self.entries = [""" # # Molecular graphics export from PMV 1.5.4 # Requires NVIDIA Gelato 2.1, PYG format # ###Some usefull Function###### ####nurbscyl comes from the Technical REference guide of gelato ####create a cylinder def nurbscyl(): uknot = (0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4) vknot = (0, 0, 1, 1) Pw = ( 1, 0, 0, 1, 1, 1, 0, 1, 0, 2, 0, 2, -1, 1, 0, 1, -1, 0, 0, 1, -1, -1, 0, 1, 0, -2, 0, 2, 1, -1, 0, 1, 1, 0, 0, 1, 1, 0, -3, 1, 1, 1, -3, 1, 0, 2, -6, 2, -1, 1, -3, 1, -1, 0, -3, 1, -1, -1, -3, 1, 0, -2, -6, 2, 1, -1, -3, 1, 1, 0, -3, 1 ) Scale(0.2,0.2,0.3) Patch (9, 3, uknot, 0, 4, 2, 2, vknot, 0, 1, "vertex hpoint Pw", Pw) def vmd_cylinder(): uknot = (0,0,0,0.25,0.25,0.5,0.5,0.75,0.75,1,1,1,) vknot = (0, 0, 1, 1) Pw = (0.0429226,0,0,1,0.0303509,0.0303509,0,0.707107, -1.87621e-09,0.0429226,0,1,-0.0303509,0.0303509, 0,0.707107,-0.0429226,-3.75241e-09,0,1,-0.0303509,-0.0303509, 0,0.707107,5.62862e-09,-0.0429226,0,1,0.0303509,-0.0303509, 0,0.707107,0.0429226,2.38805e-09,0,1,0.0429226,0,0.110961,1, 0.0303509,0.0303509,0.0784616,0.707107,-1.87621e-09,0.0429226, 0.110961,1,-0.0303509,0.0303509,0.0784616,0.707107,-0.0429226, -3.75241e-09,0.110961,1,-0.0303509,-0.0303509,0.0784616,0.707107, 5.62862e-09,-0.0429226,0.110961,1,0.0303509,-0.0303509,0.0784616, 0.707107,0.0429226,2.38805e-09,0.110961,1,) Patch (9, 3, uknot, 0, 1, 2, 2, vknot, 0, 1, "vertex hpoint Pw", Pw) """] def write(self, filename): """void <- write(filename) dumps gelato scene description""" self.filename = filename f = open(filename, 'w') for entry in self.entries: f.write(entry) f.close() def clear(self): """void <- clear() empties povray scene description""" self.entries = [] def coord3(self, x, y=None, z=None): """string <- coord3(x, y=None, z=None) returns a povray vector string this function inverts the z coordinates. It can be called with a sequence of 3 or with 3 values. """ if y is None: return ' (%f, %f, %f) '% (x[0],x[1],(-x[2])) else: return ' (%f, %f, %f) '% (x, y, (-z)) def vec2(self, x, y=None): """string <- vec3(x, y=None, z=None) returns a povray vector string this function does not invert the z coordinates. It can be called with a sequence of 3 or with 3 values. """ if y is None: return ' (%.2f, %.2f) '% (x[0],x[1]) else: return ' (%.2f, %.2f) '% (x, y) def vec3(self, x, y=None, z=None): """string <- vec3(x, y=None, z=None) returns a povray vector string this function does not invert the z coordinates. It can be called with a sequence of 3 or with 3 values. """ if y is None: return ' (%.2f, %.2f, %.2f) '% (x[0],x[1],x[2]) else: return ' (%.2f, %.2f, %.2f) '% (x, y, z) def vec4(self, x, y=None, z=None, t=None): """string <- vec4(x, y=None, z=None, t=None) returns a povray 4-vector this function does not invert the z coordinates. It can be called with a sequence of 3 and a y-value or with 4 values. """ if z is None: return ' (%.2f, %.2f, %.2f, %.2f) '% (x[0],x[1],x[2],y) else: return ' (%.2f, %.2f, %.2f, %.2f) '% (x, y, z, t) def matrix16(self, mat): """string <- matrix(mat) returns a 16, matrix""" str = '( %f, %f, %f,%f, %f, %f, %f,%f, %f, %f, %f,%f, %f, %f, %f ,%f)' % ( mat[0], mat[1], mat[2],mat[3], mat[4], mat[5], mat[6],mat[7], mat[8], mat[9], mat[10],mat[11], mat[12], mat[13], mat[14]*-1.,mat[15]) return str def set_transform(self, matrix): return ('SetTransform %s\n' % self.matrix16(matrix)) def append_transform(self, matrix): return ('AppendTransform %s\n' % self.matrix16(matrix)) def addRender(self): self.entries.append("Render()") def addCamera(self, camera, scaleLight=2.0): """void <- addCamera(camera) adds the given camera to the povray scene handles: camera background color projection matrix (only perspective currently light sources """ # doesn't handle camera transformation yet r,t,s=camera.viewer.rootObject.Decompose4x4(camera.GetMatrix()) astr='' astr = astr + '\nAttribute(\"int[2] resolution\", ('+str(int(camera.width))+','+str(int(camera.height))+'))' #astr = astr + '\nAttribute (\"int[2] spatialquality\", (4, 4))' proj= PROJ[camera.projectionType] astr = astr + '\nAttribute(\"string projection\", \"'+proj+'\")' if (camera.projectionType == 1):#ORTHO astr = astr + '\nAttribute ("float[4] screen",'+self.vec4(camera.left,camera.right,camera.bottom,camera.top)+')' #astr = astr + ('\nAttribute("float[4] screen", (%f, %f, %f, %f))'%(camera.left,camera.right,camera.bottom,camera.top)) #have to be adjust astr = astr + '\nAttribute ("float far", '+str(camera.far)+')' astr = astr + '\nAttribute ("float near", '+str(camera.near)+')' #astr = astr + '\nTranslate'+self.vec3(camera.translation) else : #astr = astr + '\nAttribute ( "float shadingquality", 0.25 )' #astr = astr + '\nAttribute ( "int[2] spatialquality", (1, 1) )' astr = astr + '\nAttribute ("float fov", '+str(camera.fovy)+')' #str = str + '\nCamera(\"'+camera.name+'\")' astr = astr + '\nTranslate '+self.coord3(t) self.entries.append( astr ) self.entries.append("\nWorld()\n") #self.addBackground(camera) #self.entries.append("Shader (\"surface\", \"plastic\", \"float Ks\", 0.9, \"float Kd\", 1)\n") for l in camera.viewer.lights: if l.enabled: self.addLight(l, scaleLight) def addBackground(self,camera): astr="#####Background#######\n" astr = astr + "PushAttributes()\n" astr = astr + "Shader(\"surface\", \"constant\")\n" astr = astr + ("Attribute(\"color C\", %s)\n"%self.vec3(camera.backgroundColor)) astr = astr + "Input(\"backplane.pyg\")\n" astr = astr + "PopAttributes()\n" self.entries.append( astr ) def addLight1(self): self.entries.append("""Light ("amb1", "ambientlight", "float intensity", 0.1) #Light ("spt1", "spotlight", "float intensity", 10.0,"point from",(0,0,20),"point to",(-0.628775, 10.648891, 26.800826)) Light ("dpt1", "distantlight", "float intensity",0.8,"color lightcolor" , (1,1,1)) #PushTransform () #Translate (-0.628775, -2.648891, 20.800826) #Light ("pt2", "pointlight", "float intensity", 10.0) #PopTransform () #PushTransform () #Translate (0, 1, 20) #Light ("pt1", "pointlight", "float intensity", 1.0) #PopTransform () """) def addLight(self, light, scale=2.0): """void <- addLight(light) add a light source to the povray scene """ gv=[0.,0.,1] v=light.direction[0:3] mat=N.array(rotax.rotVectToVect(gv,v)) astr="PushTransform ()\n" astr= astr + ("AppendTransform %s\n"%self.matrix16(mat.reshape(16,))) astr= astr + "Light (\""+light.name.replace(" ","")+"\", \"distantlight\",\"float intensity\",0.5," astr= astr + "\"float __nonspecular\","+str(1-light.specular[0])+"," astr= astr + ("\"color lightcolor\" , %s)\n" % self.vec3(scale*light.diffuse[0],scale*light.diffuse[1], scale*light.diffuse[2])) astr= astr + "PopTransform()\n" self.entries.append( astr ) def addShader(self,shader): if shader == "soapbubble" : astr='Shader("surface","glass"' else : astr='Shader("surface","%s"' % shader for i in self.shaderDic[shader]: astr = astr +","+ i astr = astr + ")\n" self.entries.append(astr) if shader == 'shinyplastic' or shader == 'metal' or shader == 'soapbubble' or shader == 'glass' : self.entries.append("Attribute (\"string geometryset\", \"+reflection\")\n") if shader == 'ambocclude' : self.entries.append("""Attribute ("string geometryset", "+localocclusion") Attribute ("float occlusion:maxpixeldist", 20) Attribute ("float occlusion:maxerror", 0.25) """) def addShader_old(self,shader): if shader == '' : self.entries.append("") if shader == 'clay' : self.entries.append("Shader (\"surface\", \"clay\", \"float Ka\", 0.9, \"float Kd\", 1,\"float roughness\", 0.2)\n") if shader == 'plastic' : #self.entries.append("Shader (\"surface\", \"plastic\", \"float Ks\", 0.9, \"float Kd\", 1)\n") self.entries.append("Shader(\"surface\", \"plastic\", \"float Ka\", 0, \"float Kd\", 1, \"float Ks\", 0.75, \"float roughness\", 0.05)\n") elif shader == 'shinyplastic' : self.entries.append("Attribute (\"string geometryset\", \"+reflection\")\n") self.entries.append("Shader (\"surface\", \"shinyplastic\", \"float Ks\", 0.9, \"float Kd\", 1,\"float eta\", 1.5,\"string envname\", \"reflection\")\n") elif shader == 'plasticss': self.entries.append("Shader (\"surface\", \"plasticss\", \"float Ks\", 0.9, \"float Kd\", 1,\"float Kss\", 1)\n") elif shader == 'metal' : self.entries.append("Attribute (\"string geometryset\", \"+reflection\")\n") self.entries.append("Shader (\"surface\", \"metal\", \"float Ka\", 1.0, \"float Kd\", 0.5,\"float Ks\", 0.8,\"float roughness\", 0.2,\"string envname\", \"reflection\",\"float Kr\", 0.5,\"float samples\", 4)\n") elif shader == 'occlusion' : self.entries.append("""Shader ("surface", "ambocclude", "string occlusionname", "localocclusion", "float samples", 256, "float bias", 0.01) Attribute ("string geometryset", "+localocclusion") Attribute ("float occlusion:maxpixeldist", 20) Attribute ("float occlusion:maxerror", 0.25) """) elif shader == 'screen' : self.entries.append("Shader (\"surface\", \"screen\", \"float Ka\", 1.0, \"float Kd\", 0.75,\"float Ks\", 0.4,\"float roughness\", 0.1, \"float sfreq\", 10, \"float tfreq\", 10, \"float sdensity\", 10, \"float tdensity\", 10)\n") elif shader == 'glass' : self.entries.append("Attribute (\"string geometryset\", \"+reflection\")\n") self.entries.append("Shader (\"surface\", \"glass\", \"float Ka\", 0.2, \"float Kd\", 0.25,\"float Ks\", 0.4,\"float roughness\", 0.1,\"string envname\", \"reflection\",\"float Kr\", 0.5,\"float samples\", 4)\n") elif shader == 'soapbubble' : self.entries.append("Attribute (\"string geometryset\", \"+reflection\")\n") self.entries.append("Shader (\"surface\", \"glass\", \"float Ka\", 0.2, \"float Kd\", 0.25,\"float Ks\", 0.4,\"float roughness\", 0.1,\"string envname\", \"reflection\",\"float Kr\", 0.5,\"float samples\", 4,\"float fakerefract\", 1)\n") elif shader == 'shownormals' : self.entries.append("Shader (\"surface\", \"shownormals\", \"float bias\", 1)\n") elif shader == 'showfacing' : self.entries.append("Shader (\"surface\", \"showfacing\", \"float Ka\", 0.25, \"float Kd\", 0.75)\n") def addColor(self, col): """ Attribute ( "color C", (0.75, 0.75, 0.75) ) """ astr=("Attribute ( \"color C\", %s )\n"%self.vec3( col )) self.entries.append( astr ) # str = ' texture {\n' # if not 'pigment' in texture.keys(): # str = str + ' pigment { color rgb %s }\n' %self.vec3( col ) # elif texture['pigment']=='': # str = str + ' pigment { color rgb %s }\n' %self.vec3( col ) # else: # str = str + ' pigment { %s }\n' % texture['pigment'] # for k,v in texture.items(): # if k=='pigment': continue # if v is None: # str = str + ' %s\n' % (k,) # else: # str = str + ' %s { %s }\n' % (k,v) # str = str + ' }\n' def endShape(self): self.entries.append( '}\n' ); def addGeoms(self, geometries, texture = {'finish':'specular 1 roughness 0.001 ambient 0.3'}, bondRad = 0.15): """void <- addGeoms(geometries, texture) adds a list of geometries to the povray scene only visible geometries are added """ for g in geometries: if g.visible and len(g.vertexSet): self.entries.append('// geometry %s\n//\n'%g.name) self.addGeom(g, texture, bondRad) def addGeom(self, geom, texture = {'finish':'specular 1 roughness 0.001 ambient 0.3'}, bondRad = 0.15, interpolation='linear'): """void <- addGeom(geometry, texture) adds a geometries to the povray scene Spheres, IndexedPolygons and IndexedPolylines are handled """ from DejaVu.Spheres import Spheres from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.Cylinders import Cylinders print texture if isinstance(geom, Spheres): self.entries.append('#####Object %s#######\n' % geom.name) self.addSpheres(geom, texture) elif isinstance(geom, IndexedPolygons) and len(geom.faceSet): self.entries.append('#####Object %s#######\n\n' % geom.name) self.addIndexedPolgygons(geom, texture,interpolation) # elif isinstance(geom, IndexedPolylines) and len(geom.faceSet): # self.entries.append('// Object %s\n//\n' % geom.name) # self.addIndexedPolylines(geom, texture, bondRad) elif isinstance(geom, Cylinders) and len(geom.faceSet): self.entries.append('#####Object %s#######\n' % geom.name) self.addCylinders(geom, texture) # else: # print 'WARNING: %s the geometry is not yet supported'%geom.__class__ def addIndexedPolylines(self, geom, texture, bondRad): """void <- addIndexedPolylines(geom, texture) """ mat = geom.GetMatrix() v = geom.vertexSet.vertices*mat c = geom.materials[GL.GL_FRONT].prop[1] lines = geom.faceSet.faces.array for i in xrange(len(v)): if len(c)==len(v): col = c[i] else: col = c[0] self.entries.append('sphere{%s,%f\n' % (self.coord3(v[i]), bondRad) ) self.addTexture( texture, col ) self.endShape() for j in xrange(len(lines)): l = lines[j] if len(c) == len(v): col1 = c[l[0]] col2 = c[l[1]] else: col1 = col2 = c[0] if Numeric.sum(col1-col2) < 0.0001: p2 = v[l[1]] oneCyl = 1 else: p2 = (v[l[1]]+v[l[0]])/2. oneCyl = 0 self.entries.append('cylinder{%s,%s, %f open\n' % \ (self.coord3(v[l[0]]), self.coord3(p2), bondRad) ) self.addTexture( texture, col1 ) self.endShape() if not oneCyl: self.entries.append('cylinder{%s, %s, %f open\n' % \ (self.coord3(p2), self.coord3(v[l[1]]), bondRad)) self.addTexture( texture, col2 ) self.endShape() def join_list(self, l): return ', '.join([str(i) for i in l]) def mesh_geometry(self, name, single_sided, interpolation, nverts,\ verts, points, normals = None, vertexcolor = None, holes = None,transform = None): #""" #interp parameter may be "linear" or "catmull-clark" to indicate Catmull-Clark subdivision #nverts[0..n f aces - 1] contains the number of vertices in each face. #array verts, whose length is the sum of all the entries in nverts, contains the vertex indices of all faces. #""" points*=N.array((1.,1.,-1.),'f') astr="" if (transform != None ) : astr=astr + self.append_transform(transform) #astr=astr + 'Scale (1.,1.,-1)\n' if (single_sided): astr= astr +'Attribute ("int twosided", 0)\n' astr= astr + ('Mesh ("%s", (%s), (%s), "vertex point P", (%s)' % (interpolation, self.join_list(nverts), self.join_list(verts), self.join_list(points.flatten()))) if (normals != None): normals*=N.array((1.,1.,-1.),'f') astr = astr +(', "vertex normal N", (%s)' % self.join_list(normals.flatten())) #else : # astr = astr +(', "vertex normal N", (') # for i in points : # astr = astr +('surfacenormal %s,'%self.vec3(i)) # astr = astr + ')' if (vertexcolor != None): astr= astr +(', "vertex color C", (%s)' % self.join_list(vertexcolor)) if (holes != None): astr= astr +(', "int[%d] holes", (%s)' % (len(holes), self.join_list(holes))) astr= astr +')\n' return astr def sortPoly(self, geom,vt, order=-1): """None <- sortPoly(order=-1) Sorts the geometry polygons according to z values of polygon's geomtric centers. Order=-1 sorts by furthest z first, order=1 sorts by closest z first""" # FIXME will not work with instance matrices #mat = geom.GetMatrix() #mat = Numeric.reshape(mat, (4,4)) #vt = geom.vertexSet.vertices*mat if vt is None: return triv = Numeric.take(vt, geom.faceSet.faces.array) trig = Numeric.sum(triv,1)/3. trigz = trig[:,2] #triangle's center of gravity z value ind = Numeric.argsort(trigz) # sorted indices if len(geom.faceSet.faces.array): faces = Numeric.take(geom.faceSet.faces.array, ind[::order]) n = geom.getFNormals() n = geom.faceSet.normals * geom.GetMatrix() normals = Numeric.take(n, ind[::order]) # #if geom.shading==GL.GL_FLAT: # we also need to re-arrange the # # face normals # if geom.normals is None: # normals = None # else: # if len(geom.normals)>1: #normals = Numeric.take(geom.normals, ind[::order]) # else: # normals = geom.normals # else: # normals = None #normals = None #geom.Set(faces=faces, fnormals=normals) return faces.copy(),normals.copy() def addIndexedPolgygons(self, geom, texture, interpolation='linear'): """void <- addIndexedPolgygons(geom, texture) self.mesh_geometry(name, transform, single_sided, interpolation, nverts, verts, points, normals) """ smooth=True #interpolation = 'catmull-clark'#'linear' - need correct normal to use linear interpolation single_sided = False name=geom.name #mat=matrix(geom.GetMatrix()) #transform = N.array(mat.T).reshape(16,) transform = mat = geom.GetMatrix() transform = N.array(transform.transpose()).reshape(16,) transform = None #vertices point vt = geom.vertexSet.vertices*mat #vt = geom.getVertices()#geom.vertexSet.vertices*mat #> use set transform of gelato : maybe compare performance points = vt#*N.array((1.,1.,-1.),'f') #vertex indice corrrespond to faces in Pmv #before getting the face aneed to sort them according the orientation in the viewer #f = geom.getFaces().copy() #normals = geom.getFNormals() faces,normals = self.sortPoly(geom,vt,order=1) faces,normals = self.sortPoly(geom,vt,order=1) #geom.sortPoly() #faces = geom.getFaces().copy() #print (f == geom.getFaces()).all() verts = faces #number of vertices for each faces nverts = [] for i in faces : nverts.append(len(i)) #lines = ["mesh2 {\n\tvertex_vectors {\n\t\t%d,\n"%len(vt)] #for v in vt: # lines.append("\t\t%s,\n"%self.coord3(v)) #lines.append("\t}\n") # add normals normals = geom.getVNormals() mat=geom.GetMatrix()[:3,:3] normals = N.dot(normals,mat.transpose()) # handle colors colors = geom.materials[GL.GL_FRONT].prop[1] vtcolor = False vertexcolor = [] colBinding = 'Overall' if len(colors)==len(points): colBinding = 'Per Vertex' vtcolor = True for i in colors : vertexcolor.append(i[0:3]) vertexcolor = N.array(vertexcolor).flatten() elif len(colors)==len(faces): colBinding = 'Per Face' vtcolor = True for i in colors : vertexcolor.append(i[0:3]) vertexcolor = N.array(vertexcolor).flatten() else : vertexcolor = None # color self.entries.append('PushAttributes ()\n') if texture['pigment'] == "occlusion" or texture['pigment'] == "glass" : vertexcolor = None if texture['pigment'] != "" : self.addShader(texture['pigment']) if not vtcolor : self.addColor(colors[0][0:3]) # alpha alpha = colors[0][3] if (alpha < 1.0): alpha = round(alpha, self.PRECISION) self.entries.append('Attribute (\"color opacity\", %s)\n' % self.vec3(alpha, alpha, alpha)) mgeom=self.mesh_geometry(name, single_sided, interpolation, nverts, verts.flatten(), points,normals=normals, vertexcolor =vertexcolor,transform=transform) self.entries.append(mgeom) self.entries.append('PopAttributes ()\n') def addSpheres(self, geom, texture): """void <- addSpheres(geom, texture) r.PushAttributes() r.Scale(1.7,1.7,1.7) r.Attribute ( "color C", (0., 0., 0.1) ) r.Translate ( 0, 0, 30.) r.Sphere(1.0,-1.0,1.0,360.0) r.PopAttributes() """ mat = geom.GetMatrix() v = geom.vertexSet.vertices*mat #v = geom.vertexSet.vertices.array c = geom.materials[1028].prop[1] if geom.oneRadius == viewerConst.NO: radii = geom.vertexSet.radii.array if geom.inheritMaterial: fp = None # FIXME bp = None else: fp = geom.materials[GL.GL_FRONT] if not geom.frontAndBack: bp = geom.materials[GL.GL_BACK] face = GL.GL_FRONT else: bp = None face = GL.GL_FRONT_AND_BACK if texture['pigment'] != '' : self.addShader(texture['pigment']) for i in range(len(geom.vertexSet)): self.entries.append('PushAttributes()\n') if fp: col = fp.prop[1][i][:3] alpha = fp.prop[1][i][3] else: col = (1.,1.,1.) alpha = 1.0 self.addColor( col ) # alpha if (alpha < 1.0): alpha = round(alpha, self.PRECISION) self.entries.append('Attribute (\"color opacity\", %s)\n' % self.vec3(alpha, alpha, alpha)) self.entries.append('Translate %s\n'%self.coord3(v[i]) ) if not geom.oneRadius: self.entries.append('Scale(%f,%f,%f)\n'%((radii[i][0]),(radii[i][0]),(radii[i][0])) ) else: self.entries.append('Scale(%f,%f,%f)\n'%(geom.radius,geom.radius,geom.radius) ) self.entries.append("Sphere (1.0,-1.0,1.0,360.0)\n") self.entries.append("PopAttributes()\n") #self.endShape() def addOneCylinder(self,v1,v2,color,alpha = 1.0): gv=[0.,0.,1] v=v2-v1 mat=N.array(rotax.rotVectToVect(gv,v)) # first translate on v1 #then rotate astr="PushTransform ()\n" astr = astr + "Attribute (\"color C\", %s)\n"% self.vec3(color) if (alpha < 1.0): alpha = round(alpha, self.PRECISION) self.entries.append('Attribute (\"color opacity\", %s)\n' % self.vec3(alpha, alpha, alpha)) astr = astr + "Translate %s\n" % self.coord3(v1) astr = astr + ("AppendTransform %s\n"%self.matrix16(mat.reshape(16,))) astr = astr + "nurbscyl ()\n" astr = astr + "PopTransform ()\n" return astr def addCylinders(self, geom, texture): """void <- addSpheres(geom, texture) PushTransform () Attribute ("color C", %s) Translate (x, y, z) Rotate (a, x, y, z) OR AppendTransform (m16); nurbscyl () PopTransform () """ mat = geom.GetMatrix() v = geom.vertexSet.vertices*mat #v = geom.vertexSet.vertices.array c = geom.materials[1028].prop[1] radii = geom.vertexSet.radii.array if geom.inheritMaterial: fp = None # FIXME bp = None else: fp = geom.materials[GL.GL_FRONT] if not geom.frontAndBack: bp = geom.materials[GL.GL_BACK] face = GL.GL_FRONT else: bp = None face = GL.GL_FRONT_AND_BACK if texture['pigment'] != '' : self.addShader(texture['pigment']) f = geom.getFaces() for i in range(len(geom.faceSet)): for j in range(len(f[i])-1): # self.entries.append('cone { \n') if not geom.oneRadius: r1 = radii[f[i][j]]/2. r2 = radii[f[i][j+1]]/2. else: r1 = r2 = radii[0]/2. #self.entries.append('\t%s, %f, %s, %f\n'%( # self.coord3(v[f[i][j]]), r1, # self.coord3(v[f[i][j+1]]), r2)) if fp: col = c[f[i][j]][:3] alpha=c[f[i][j]][3] else: col = (1.,1.,1.) alpha = 1.0 self.entries.append(self.addOneCylinder(v[f[i][j]],v[f[i][j+1]],col)) self.entries.append(self.addOneCylinder(v[f[i][j+1]],v[f[i][j]],col)) #self.entries.append("\tpigment { color rgb<%6.3f, %6.3f, %6.3f> }\n"% tuple(col)) #self.entries.append("\tfinish { specular 1 roughness 0.001 ambient 0.3 }\n") #self.endShape() #########From blendergelato.py############################# if __name__ == '__main__': from DejaVu import Viewer vi = Viewer() from DejaVu.Spheres import Spheres s = Spheres('test', centers = ( (0.0, 0., 0.), (3.,0.,0.) ) ) s.Set(quality = 15) vi .AddObject(s) from DejaVu.povray3 import PovRay p = PovRay() p.addCamera(vi.cameras[0]) p.addLight(vi.lights[0]) p.addGeom(s) p.write('test.pov') mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/csgClip.py0000644000175000017500000001357311111132470021623 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import numpy.oldnumeric as Numeric from opengltk.OpenGL import GL from OpenCSG import opencsglib as OpenCSG from DejaVu.Clip import ClippingPlane from DejaVu.Geom import Geom from DejaVu.IndexedPolygons import IndexedPolygons class DejaVuPrimitive(OpenCSG.PythonPrimitive): def __init__(self, geom): apply( OpenCSG.PythonPrimitive.__init__, (self, self.render, OpenCSG.Intersection, 0)) # does not work for some reason #OpenCSG.PythonPrimitive(self.render, OpenCSG.Intersection, 1) self.geom = geom self.dpyListCSG = None def redoDisplayListCSG(self): if self.dpyListCSG is not None: GL.glDeleteLists(1, self.dpyListCSG) g = self.geom self.dpyListCSG = GL.glGenLists(1) GL.glNewList(self.dpyListCSG, GL.GL_COMPILE) ## if isinstance(g, Spheres): ## g.DisplayFunction() ## else: self.drawpolygons() GL.glEndList() def drawpolygons(self): g = self.geom vertices = g.getVertices() faces = g.getFaces() normals = g.getFNormals() GL.glDisable(GL.GL_CULL_FACE) for i,f in enumerate(faces): GL.glBegin(GL.GL_POLYGON) GL.glNormal3fv(normals[i]) for vi in f: GL.glVertex3fv(vertices[vi]) GL.glEnd() i+=1 def render(self, mode='render'): # call with mode='csg' to render simple shape to setup Zbuffer for CSG # call with mode='render' to render by calling geom's draw function if self.geom: #import traceback #print traceback.print_stack() #print self.geom #print "=========================================================" root = self.geom.viewer.rootObject instance = [0] p = self.geom.parent while p: instance.append(0) p = p.parent #mat = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') #print 'mat OK', mat GL.glPushMatrix() GL.glLoadIdentity() self.geom.viewer.currentCamera.BuildTransformation() self.geom.BuildMat(self.geom, root, True, instance) #mat = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') #print 'mat PB', mat #print 'render ', mode, self.geom if mode=='csg': if self.dpyListCSG is None: self.redoDisplayListCSG() GL.glCallList(self.dpyListCSG) elif mode=='render': obj = self.geom if not obj.inheritMaterial: obj.InitMaterial(0) obj.InitColor(0) obj.DisplayFunction() GL.glPopMatrix() class CsgGeom(Geom): keywords = Geom.keywords + [ 'primitives', 'algo', 'depthalgo', ] def __init__(self, name=None, check=1, **kw): # C++ primitives self.primitives = OpenCSG.PrimitiveVector() # python subclasses used to call python implementation or render self.pyprimitives = [] algo = kw.get('algo') if algo is None: kw['algo'] = OpenCSG.Goldfeather depthalgo = kw.get('depthalgo') if depthalgo is None: kw['depthalgo'] = OpenCSG.DepthComplexitySampling apply( Geom.__init__, (self, name, check), kw) def clearPrimitives(self): self.primitives.clear() self.pyprimitives = [] def setPrimitives(self, *args): self.clearPrimitives() for g in args: assert isinstance(g, Geom) prim = DejaVuPrimitive(g) #self.primitives.append(prim) OpenCSG.PrimitiveVector_add(self.primitives, prim) self.pyprimitives.append(prim) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: primitives check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ #print "CsgGeom.Set" redoFlags = apply( Geom.Set, (self, check, 0), kw) p = kw.get( 'primitives') if p: assert isinstance(p, OpenCSG.PythonPrimitiveVector) self.primitives = p a = kw.get( 'algo') if a: if a =='automatic': a = OpenCSG.Automatic elif a== 'goldfeather': a = OpenCSG.Goldfeather elif a == 'scs': a = OpenCSG.SCS assert a in (OpenCSG.Automatic, OpenCSG.Goldfeather, OpenCSG.SCS) self.algo = a d = kw.get( 'depthalgo') if d: if d =='DepthComplexitySampling': d = OpenCSG.DepthComplexitySampling elif d== 'NoDepthComplexitySampling': d = OpenCSG.NoDepthComplexitySampling elif d == 'OcclusionQuery': d = OpenCSG.OcclusionQuery assert d in (OpenCSG.DepthComplexitySampling, OpenCSG.NoDepthComplexitySampling, OpenCSG.OcclusionQuery) self.depthalgo = d return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): GL.glEnable(GL.GL_DEPTH_TEST); GL.glClear( GL.GL_STENCIL_BUFFER_BIT) GL.glDisable(GL.GL_FOG) GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL) OpenCSG.render(self.primitives, self.algo, self.depthalgo) GL.glDepthFunc(GL.GL_EQUAL) # FIXME should only enable fog if it is on in camera GL.glEnable(GL.GL_FOG) self.SetupGL() for p in self.pyprimitives: p.render() GL.glDepthFunc(GL.GL_LESS); mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Camera.py0000644000175000017500000074273012104003322021427 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: 2000 Author: Michel F. SANNER # # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Camera.py,v 1.456 2013/02/04 19:06:58 sanner Exp $ # # $Id: Camera.py,v 1.456 2013/02/04 19:06:58 sanner Exp $ # """Camera Module: This Module implements the Camera class and the Fog class. """ ## NOTE about share context and sharelist keyword arguments to Camera ## By default ane new Camera will share its context with camaera 0 ## which creates the OpenGL context ## Passing an argument sharecontext=None will make the new camera not share ## the context but still the display lists will be shared. ## Passing sharelist=None in addition to sharecontext=None will create a ## camera with a completely separate OpenGL context. ## All display list are created in the context of the Camera 0 which is the ## one activated in ReallyRedraw when display list are created. import os, sys, warnings import Image import ImageFilter import ImageChops import tkMessageBox from opengltk.OpenGL.GLU import gluPerspective, gluPickMatrix, gluUnProject, gluErrorString, gluLookAt from opengltk.extent import _gllib from opengltk.OpenGL.GL import * from opengltk.extent.utillib import glCleanRotMat from opengltk.OpenGL import GL from mglutil.gui import widgetsOnBackWindowsCanGrabFocus import DejaVu from DejaVu import loadTogl from DejaVu.Insert2d import Insert2d from DejaVu.Spheres import Spheres from DejaVu.Ellipsoids import Ellipsoids from DejaVu.Cylinders import Cylinders from DejaVu import bitPatterns from DejaVu.cursors import cursorsDict from DejaVu.Texture import Texture if hasattr(DejaVu, 'enableVertexArray') is False: DejaVu.enableVertexArray = False if hasattr( DejaVu, 'allowedAntiAliasInMotion') is False: DejaVu.allowedAntiAliasInMotion = 0 if hasattr( DejaVu, 'enableSelectionContour') is False: DejaVu.enableSelectionContour = False if hasattr( DejaVu, 'selectionContourSize') is False: DejaVu.selectionContourSize = 0 if hasattr( DejaVu, 'selectionContourColor') is False: DejaVu.selectionContourColor = (1., 0., 1., .7) if hasattr( DejaVu, 'selectionPatternSize') is False: DejaVu.selectionPatternSize = 6 if hasattr( DejaVu, 'enableSSAO') is False: DejaVu.enableSSAO = True sndDeriv = [ -0.125, -0.125, -0.125, -0.125, 1.0, -0.125, -0.125, -0.125, -0.125] fstDeriveV1 = [-0.125, -0.25, -0.125, 0.0 , 0.0, 0.0, 0.125, 0.25, 0.125] fstDeriveV2 = [ 0.125, 0.25, 0.125, 0.0 , 0.0, 0.0, -0.125, -0.25, -0.125] fstDeriveH1 = [-0.125, 0.0, 0.125, -0.25 , 0.0, 0.25, -0.125, 0.0, 0.125] fstDeriveH2 = [ 0.125, 0.0, -0.125, 0.25 , 0.0, -0.25, 0.125, 0.0, -0.125] from time import time try: from opengltk.extent.utillib import namedPoints except ImportError: def namedPoints(v): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() i = 0 for p in v: glPushName(i) glBegin(GL_POINTS) glVertex3f(float(p[0]), float(p[1]), float(p[2])) glEnd() glPopName() i = i + 1 import Tkinter, os import numpy.oldnumeric as Numeric import math import types import weakref import viewerConst, ViewerGUI, jitter from Geom import Geom from Transformable import Transformable import colorTool import viewerFns from Trackball import Trackball from EventHandler import EventManager from IndexedPolygons import IndexedPolygons from viewerFns import checkKeywords import array matf = array.array('f', [0]*16) try: from opengltk.extent._glextlib import * except Exception, e: print 'ERROR: failed to import opengltk.extent._glextlib' print e #print "no glActiveTextue" DejaVu.enableSSAO = False class Fog: keywords = [ 'tagModified', 'enabled', 'start', 'end', 'density', 'mode', 'color' ] def Reset(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.color = (0.0, 0.0, 0.0, 1.0) self.enabled = False self.start = 25 self.end = 40 self.mode = GL_LINEAR self.density = 0.1 self._modified = False def __init__(self, camera): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.Reset() self.camera = weakref.ref(camera) # used to activate right context # the alternative would be to have the Set of # fog values be done trough Camera.Set self.name = 'Fog'+camera.name def getState(self): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() state = {'enabled':self.enabled, 'start':self.start, 'end':self.end, 'density':self.density, 'color':self.color } mode='GL_LINEAR' if self.mode==GL_EXP: mode='GL_EXP' elif self.mode==GL_EXP2: mode='GL_EXP2' state['mode'] = mode return state def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return '' % \ (self.enabled, self.start, self.end, self.mode, self.density, repr(self.color) ) def Set(self, check=1, **kw): """Set various fog parameters""" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if __debug__: if check: apply( checkKeywords, ("Fog",self.keywords), kw) val = kw.get( 'tagModified', True ) assert val in [True, False] self._modified = val self.camera().tk.call(self.camera()._w, 'makecurrent') val = kw.get( 'enabled') if val is not None: if val in [False, 0]: glDisable(GL_FOG) elif val in [True, 1]: glFogi(GL_FOG_MODE, self.mode) if self.mode == GL_LINEAR: glFogf(GL_FOG_START, float(self.start) ) glFogf(GL_FOG_END, float(self.end) ) else: glFogf(GL_FOG_DENSITY, float(self.density)) glFogfv(GL_FOG_COLOR, self.color) glEnable(GL_FOG) else: raise ValueError('Bad argument, Only True ot False are possible %s'%val) self.enabled = val val = kw.get( 'start') if not val is None: if kw.has_key('end'): end = kw.get('end') else: end = self.end if val < end: glFogf(GL_FOG_START, float(val) ) self.start = val else: raise AttributeError('start has to be smaller than end=', self.start, self.end) val = kw.get( 'end') if not val is None: if val > self.start: glFogf(GL_FOG_END, float(val) ) self.end = val else: raise AttributeError('end has to be larger than start=', self.start, self.end) val = kw.get( 'density') if not val is None: if val <= 1.0 and val >= 0.0: glFogf(GL_FOG_DENSITY, float(val)) self.density = val else: raise AttributeError('density has to be <=1.0 and >= 0.0') val = kw.get( 'mode') if not val is None: if val=='GL_LINEAR': val=GL_LINEAR elif val=='GL_EXP': val=GL_EXP elif val=='GL_EXP2': val=GL_EXP2 if val in (GL_LINEAR, GL_EXP, GL_EXP2): glFogi(GL_FOG_MODE, int(val)) self.mode = val else: raise AttributeError('mode has to be GL_LINEAR,GL_EXP or\ GL_EXP2') val = kw.get( 'color') if not val is None: self.color = colorTool.OneColor( val ) glFogfv(GL_FOG_COLOR, self.color) class PickObject: """Class to represent the result of picking or drag selection the keys of hits dictionary are geometries, the values are lists of 2-tuples (vertexIndexe, instance), where vertexInd is the index of the a vertex of a face of the geometry and instance is a list of integer providing the instance matrix index for the geometry and all its parents. """ def __init__(self, mode, camera, type='vertices'): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() assert mode in ['pick', 'drag select'] assert type in ['vertices', 'parts'] self.type = type self.mode = mode self.hits = {} self.camera = weakref.ref(camera) self.p1 = None # intersection of pick ray with front clip plane self.p2 = None # intersection of pick ray with back clip plane self.event = None # event that triggered picking self.box = (0,0,0,0) # screen coordinates of selection box def add(self, object=None, vertex=None, instance=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.hits.has_key(object): self.hits[object].append( (vertex, instance) ) else: self.hits[object] = [ (vertex, instance) ] from math import sqrt, fabs import Pmw from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser import numpy from IndexedPolygons import IndexedPolygons from Spheres import Spheres from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel # sub class combobox to intercept _postList and populate list when the pull # down is posted class DynamicComboBox(Pmw.ComboBox): def __init__(self, viewer, parent = None, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.viewer = viewer Pmw.ComboBox.__init__(self, parent, **kw) def _postList(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() geomNames = [] for g in self.viewer.rootObject.AllObjects(): if isinstance(g, IndexedPolygons): geomNames.append(g.fullName) self.component('scrolledlist').setlist(geomNames) Pmw.ComboBox._postList(self, event) ## class OcclusionCamera(Tkinter.Widget, Tkinter.Misc): ## def orient(self, eyex, eyey, eyez, nx, ny, nz): ## """Place camera at x,y,z and look along vector nx, ny, nz""" ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## glPushMatrix() ## glLoadIdentity() ## # compute normal vector ## if nx==0.0 and ny==0.0: ## x2=1. ## y2=0. ## z2=0. ## else: ## z2 = nz ## if ny==0.0 and nz==0.0: ## x2 = 0.0 ## y2 = 1.0 ## elif nx==0 and nz==0: ## x2 = 1.0 ## y2 = 0.0 ## else: ## if fabs(nx)>fabs(ny): ## x2 = 0.0 ## y2 = ny ## else: ## x2 = nx ## y2 = 0.0 ## upx = ny*z2 - nz*y2 ## upy = nz*x2 - nx*z2 ## upz = nx*y2 - ny*x2 ## n = 1. / sqrt(upx*upx + upy*upy + upz*upz) ## upx *=n ## upy *=n ## upz *=n ## gluLookAt( eyex, eyey, eyez, eyex+nx, eyey+ny, eyez+nz, upx, upy, upz) ## m = Numeric.array(glGetDoublev(GL_MODELVIEW_MATRIX)).astype('f') ## glPopMatrix() ## # compute gluLookAt( x, y, z, x+nx, y+ny, z+nz, x3, y3, z3) matrix ## # http://www.opengl.org/documentation/specs/man_pages/hardcopy/GL/html/glu/lookat.html ## ## # nx, ny, nz is the vector F (eye->center) (normalized) ## ## # x, y, z is the eye position ## ## # s = f x up ## ## sx = ny*upz - nz*upy ## ## sy = nz*upx - nx*upz ## ## sz = nx*upy - ny*upx ## ## # u = s x f ## ## ux = sy*nz - sz*ny ## ## uy = sz*nx - sx*nz ## ## uz = sx*ny - sy*nx ## ## M = ( sx, ux, -nx, 0, sy, uy, -ny, 0, sz, uz, -nz, 0, -eyex, -eyey, -eyez, 1.) ## ## diff = Numeric.sum(m-M) ## ## if diff > 0.1: ## ## raise ValueError ## self.matrix = m ## self.Redraw() ## def computeOcclusion(self, positions, directions): ## """For a list of pocitions and directions, render the geometry and ## compute occlusion by summing Zbuffer. Direction have to be normalized""" ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## from time import time ## t1 = time() ## occlusionValues = [] ## self.tk.call(self._w, 'makecurrent') ## OnePercent = len(positions)/100 ## percent = 0 ## counter = 0 ## for pos, dir in zip(positions,directions): ## if OnePercent>0 and counter % OnePercent == 0: ## self.counterText.configure(text=str(percent)+'%') ## self.update_idletasks() ## percent += 1 ## counter += 1 ## x, y, z = pos ## nx, ny, nz = dir ## self.orient(float(x), float(y), float(z), ## float(nx), float(ny), float(nz) ) ## zbuf = self.GrabZBufferAsArray() ## sum = Numeric.sum(zbuf) ## occlusionValues.append(sum) ## #print time()-t1 ## return occlusionValues ## def computeOcclusion_cb(self): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## self.removeOcclusion() ## occluderGeoms = self.occluders.getAll(index=2) ## computeOccluGeoms = self.compOcclusion.getAll(index=2) ## #print occluderGeoms ## #print '-------------' ## #print computeOccluGeoms ## if len(occluderGeoms)==0: ## print "WARNING: no occluders" ## return ## # allocate new dispaly lists ## # build display lists for all geoms ## self.tk.call(self._w, 'makecurrent') ## for i,g in enumerate(occluderGeoms): ## if hasattr(g, 'Draw'): ## g.oldinheritmaterial = g.inheritMaterial ## g.inheritMaterial = True ## if isinstance(g, Spheres): ## g.oldquality = g.quality ## self.tk.call(self.viewer.currentCamera._w, 'makecurrent') ## g.deleteTemplate() ## #self.tk.call(self._w, 'makecurrent') ## g.Set(quality=1) ## self.tk.call(self._w, 'makecurrent') ## g.makeTemplate() ## l = glGenLists(1) ## GL.glNewList(l, GL.GL_COMPILE) ## status = g.Draw() ## #print 'status', status ## GL.glEndList() ## self.dpyList.append(l) ## # compute occlusion for each geom ## #self.tk.call(self._w, 'makecurrent') ## for g in computeOccluGeoms: ## if isinstance(g, Spheres): ## self.near = 3.0 ## self.setFovy(135.0) ## v = g.getVertices() ## from math import sqrt ## n = sqrt(3,) ## occRight = self.computeOcclusion(v, ( (-n,-n,n), )*len(v) ) ## occLeft = self.computeOcclusion(v, ( (n,n,n), )*len(v) ) ## occTop = self.computeOcclusion(v, ( (-n,n,-n), )*len(v) ) ## occBottom = self.computeOcclusion(v, ( (n,-n,-n), )*len(v) ) ## #occRight = self.computeOcclusion(v, ( (1.,0.,0.), )*len(v) ) ## #occLeft = self.computeOcclusion(v, ( (-1.,0.,0.), )*len(v) ) ## #occTop = self.computeOcclusion(v, ( (0.,1.,0.), )*len(v) ) ## #occBottom = self.computeOcclusion(v, ( (0.,-1.,0.), )*len(v) ) ## #occFront = self.computeOcclusion(v, ( (0.,0.,1.), )*len(v) ) ## #occBack = self.computeOcclusion(v, ( (0.,0.,-1.), )*len(v) ) ## occlusionValues = [] ## for i in xrange(len(v)): ## occlusionValues.append( occRight[i] + occLeft[i] + ## occTop[i] + occBottom[i])# + ## #occFront[i] + occBack[i]) ## g.occlusionValues = occlusionValues ## #g.occlusionValues = occRight ## else: ## self.near = self.near ## self.setFovy(self.fovyTW.get()) ## v, n = g.getOcclusionPointsDir() ## #print 'computing for:', g, len(v) ## g.occlusionValues = self.computeOcclusion(v, n) ## # delete display lists ## for l in self.dpyList: ## glDeleteLists(l, 1) ## self.dpyList = [] ## # restore Sphere templates and display list ## self.tk.call(self.viewer.currentCamera._w, 'makecurrent') ## #for i,g in enumerate(set.union(set(occluderGeoms), set(computeOccluGeoms))): ## for i,g in enumerate(occluderGeoms): ## if hasattr(g, 'Draw'): ## g.inheritMaterial = g.oldinheritmaterial ## if isinstance(g, Spheres): ## self.tk.call(self._w, 'makecurrent') ## g.deleteTemplate() ## #GL.glDeleteLists(g.templateDSPL[0], 3) ## #g.templateDSPL = None ## #self.tk.call(self.viewer.currentCamera._w, 'makecurrent') ## g.Set(quality=g.oldquality) ## self.tk.call(self.viewer.currentCamera._w, 'makecurrent') ## g.makeTemplate() ## del g.oldquality ## self.applyOcclusion() ## def normalize(self, values): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## mini = min(values) ## delta = max(values)-mini ## off = self.off*delta ## delta = delta + off ## nvalues = [] ## for v in values: ## nv = ((v-mini+off)/delta) ## #nv = ((v-mini)/delta) ## nvalues.append(nv) ## #print 'normalize off:', self.off, 'delta:',delta, min(nvalues), max(nvalues) ## return nvalues ## def applyOcclusion(self):#, *dummy): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## #print "applyOcclusion" ## lGeoms = self.compOcclusion.getAll(index=2) ## if len(lGeoms) == 0: ## tkMessageBox.showwarning('ambient occlusion','add geometry to apply occlusion') ## elif hasattr(lGeoms[0], 'occlusionValues') is False: ## tkMessageBox.showwarning('ambient occlusion','compute occlusion first') ## for g in self.compOcclusion.getAll(index=2): ## # max value is 2500 becauseocculsion rendering is 50x50 pixels ## # set values below 2400 to 2400. If we do not do this ## # we sometiems get very small values that kill the range ## # for instance gpcr ## #print "g.occlusionValues", g.occlusionValues ## if isinstance(g, Spheres): ## values = numpy.clip(g.occlusionValues, 5000., 7500.0) ## else: ## values = numpy.clip(g.occlusionValues, 2400., 2500.0) ## if values is None: return ## ambiScale = self.ambiScale ## diffScale = self.diffScale ## #print 'ambiScale:', ambiScale ## #print 'diffScale:', diffScale ## #print "values", values ## nvalues = self.normalize(values) ## nvalues = numpy.array(nvalues) ## nvalues.shape = (-1, 1) ## #print 'nvalues:', g.name, min(nvalues), max(nvalues) ## # modulate ambient ## from DejaVu import preventIntelBug_WhiteTriangles ## if preventIntelBug_WhiteTriangles is False: ## prop = numpy.ones( (len(values), 4) )*nvalues ## p = prop*ambiScale ## p[:,3] = 1 ## g.materials[1028].getFrom[0][1] = p ## # modulate specular ## prop = numpy.ones( (len(values), 4) )*nvalues ## p = prop*ambiScale ## p[:,3] = 1 ## g.materials[1028].getFrom[0][1] = p ## # modulate diffuse ## prop = numpy.ones( (len(values), 4) )*nvalues ## origProp = g.materials[1028].prop[1].copy() ## p = prop*diffScale ## g.materials[1028].getFrom[1] = [1, p] ## else: ## # modulate diffuse ## prop = numpy.ones( (len(values), 4) )*nvalues ## origProp = g.materials[1028].prop[1].copy() ## g.materials[1028].getFrom[1] = [1, prop] ## g.Set(inheritMaterial=False) ## g.RedoDisplayList() ## g.viewer.Redraw() ## def removeOcclusion(self):#, *dummy): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## # reset ## for g in self.compOcclusion.getAll(index=2): ## from DejaVu import preventIntelBug_WhiteTriangles ## if preventIntelBug_WhiteTriangles: ## g.materials[1028].getFrom[0] = None # same as Materials.py line 107 ## g.materials[1028].getFrom[1] = None # same as Materials.py line 107 ## else: ## g.materials[1028].getFrom[0][1] = 0.6 # same as Materials.py line 107 ## # g.materials[1028].getFrom[1][1] = 0.6 # same as Materials.py line 107 ## g.Set(inheritMaterial=False) ## g.RedoDisplayList() ## g.viewer.Redraw() ## def setOffAndApplyOcclusion(self, val): ## self.setOff(val) ## self.applyOcclusion() ## def __init__(self, master, viewer, cnf={}, **kw): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## self.fovy = 90.0 ## self.near = 0.1 ## self.far = 100. ## self.matrix = None ## self.dpyList = [] ## self.ambiScale = 0.6 # same as Materials.py line 107 ## self.diffScale = 0.6 # same as Materials.py line 107 ## self.off = 0.4 ## self.ownMaster = False # set tot tru is the master of self.Frame ## # has to be destroyed when Camera is deleted ## self.exposeEvent = False # set to true on expose events and reset in ## # Viewer.ReallyRedraw ## self.frameBorderWidth = 3 ## self.frame = Tkinter.Frame(master, bd=self.frameBorderWidth) ## cfg = 0 ## self.counterText = Tkinter.Label(self.frame, text='0%') ## self.fovyTW = ThumbWheel( ## self.frame, width=70, height=16, type=float, value=self.fovy, ## callback=self.setFovy_cb, continuous=False, oneTurn=180, ## wheelPad=2, min=1.0, max=179.99, ## labCfg = {'text':'cavity darkness:', 'side':'top'} ## ) ## #self.fovyTW.grid(column=3, row=0) ## self.fovyTW.pack(side='left') ## self.compute = Tkinter.Button(self.frame, text='compute', ## command = self.computeOcclusion_cb) ## self.guiFrame = Tkinter.Frame(master, bd=self.frameBorderWidth) ## frame = self.guiFrame ## # build geometry chooser ## #objects = [] ## #for g in viewer.rootObject.AllObjects(): ## # if g.visible and len(g.getVertices())>0: ## # objects.append( (g.fullName, 'no comment available', g) ) ## b = Tkinter.Button(frame, text='Update Geom list', ## command=self.listGeoms) ## b.grid(column=0, row=0) ## self.chooser = ListChooser( ## frame, mode='extended', title='Geometry list', #entries=objects, ## lbwcfg={'height':12} ## ) ## self.chooser.grid(column=0, row=1, rowspan=5) ## b = Tkinter.Button(frame, text='Add', command=self.addGeoms) ## b.grid(column=1, row=1) ## b = Tkinter.Button(frame, text='Remove', command=self.removeGeoms) ## b.grid(column=1, row=2) ## self.compOcclusion = ListChooser( ## frame, lbwcfg={'height':5}, mode='extended', title='Compute Occlusion', ## ) ## self.compOcclusion.grid(column=2, row=0, rowspan=3) ## b = Tkinter.Button(frame, text='Add', command=self.addOccluders) ## b.grid(column=1, row=4) ## b = Tkinter.Button(frame, text='Remove', command=self.removeOccluders) ## b.grid(column=1, row=5) ## self.occluders = ListChooser( ## frame, lbwcfg={'height':5}, mode='extended', title='Occluders', ## ) ## self.occluders.grid(column=2, row=3, rowspan=3) ## # self.ambiScaleTW = ThumbWheel( ## # frame, width=70, height=16, type=float, value=self.ambiScale, ## # callback=self.setambiScale, continuous=True, oneTurn=1., ## # wheelPad=2, min=0.0001, max=1., ## # labCfg = {'text':'ambi. sca.:', 'side':'top'}) ## # self.ambiScaleTW.grid(column=3, row=1) ## # ## # self.diffScaleTW = ThumbWheel( ## # frame, width=70, height=16, type=float, value=self.diffScale, ## # callback=self.setdiffScale, continuous=True, oneTurn=1., ## # wheelPad=2, min=0.0001, max=1., ## # labCfg = {'text':'diff. sca.:', 'side':'top'}) ## # self.diffScaleTW.grid(column=3, row=2) ## self.offTW = ThumbWheel( ## frame, width=70, height=16, type=float, value=self.off, ## callback=self.setOffAndApplyOcclusion, ## continuous=False, oneTurn=1., ## wheelPad=2, min=0.0001, max=1., ## labCfg = {'text':'overall brightness:', 'side':'top'}) ## self.offTW.grid(column=3, row=3) ## self.apply = Tkinter.Button(frame, text='apply occ.', ## command = self.applyOcclusion) ## self.apply.grid(column=3, row=4) ## self.remove = Tkinter.Button(frame, text='remove occ.', ## command = self.removeOcclusion) ## self.remove.grid(column=3, row=5) ## self.viewer = viewer ## from DejaVu.Viewer import AddObjectEvent, RemoveObjectEvent, ReparentObjectEvent ## viewer.registerListener(AddObjectEvent, self.geomAddedToViewer) ## viewer.registerListener(RemoveObjectEvent, self.geomRemovedFromViewer) ## viewer.registerListener(ReparentObjectEvent, self.geomReparented) ## if not kw.has_key('double'): kw['double'] = 1 ## if not kw.has_key('depth'): kw['depth'] = 1 ## #kw['rgba'] = False ## #kw['depthsize'] = 20 ## if not kw.has_key('sharecontext') and len(viewer.cameras): ## # share context with the default camera. ## cam = viewer.cameras[0] ## kw['sharecontext'] = cam.uniqID ## self.width = 50 ## if 'width' in cnf.keys(): ## self.width = cnf['width'] ## cfg = 1 ## self.height = 50 ## if 'height' in cnf.keys(): ## self.height = cnf['height'] ## cfg = 1 ## self.rootx = 320 ## if 'rootx' in cnf.keys(): ## self.rootx = cnf['rootx'] ## del cnf['rootx'] ## cfg = 1 ## self.rooty = 180 ## if 'rooty' in cnf.keys(): ## self.rooty = cnf['rooty'] ## del cnf['rooty'] ## cfg = 1 ## if cfg: self.Geometry() ## if 'side' in cnf.keys(): ## side = cnf['side'] ## del cnf['side'] ## else: side = 'top' ## self.frame.pack(side=side) ## self.compute.pack(side='left') ## self.counterText.pack(side='left') ## self.defFrameBack = self.frame.config()['background'][3] ## loadTogl(self.frame) ## try : ## # after this line self.master will be set to self frame ## Tkinter.Widget.__init__(self, self.frame, 'togl', cnf, kw) ## #currentcontext = self.tk.call(self._w, 'contexttag') ## #print "StandardCamera.__init__ currentcontext", currentcontext ## self.tk.call(self._w, 'makecurrent') ## glDepthFunc(GL_LESS) ## except: ## kw.pop('sharecontext') ## # after this line self.master will be set to self frame ## Tkinter.Widget.__init__(self, self.frame, 'togl', cnf, kw) ## #currentcontext = self.tk.call(self._w, 'contexttag') ## #print "StandardCamera.__init__ currentcontext", currentcontext ## self.tk.call(self._w, 'makecurrent') ## glDepthFunc(GL_LESS) ## glEnable(GL_DEPTH_TEST) ## glDisable(GL_LIGHTING) ## glEnable(GL_CULL_FACE) ## # create a TK-event manager for this camera ## self.eventManager = EventManager(self) ## self.eventManager.AddCallback('', self.Map) ## self.eventManager.AddCallback('', self.Expose) ## self.eventManager.AddCallback('', self.Expose) ## self.pack(side=side) ## frame.pack() ## self.matrix = (1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) ## master.update_idletasks() ## self.tk.call(viewer.currentCamera._w, 'makecurrent') ## def listGeoms(self, event=None): ## self.chooser.clear() ## objects = [] ## for g in self.viewer.rootObject.AllObjects(): ## if g.visible and len(g.getVertices())>0: ## objects.append( (g.fullName, 'no comment available', g) ) ## self.chooser.setlist(objects) ## def geomAddedToViewer(self, event): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## geom = event.object ## if not hasattr(geom, "getVertices"): return ## if geom.visible and len(geom.getVertices())>0: ## self.chooser.add( (geom.fullName, 'no comment available', geom) ) ## def geomRemovedFromViewer(self, event): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## #print "geomRemovedFromViewer", event.object.name ## geom = event.object ## self.chooser.remove( geom.fullName ) ## # MS not sure we need this function ... viewer.ReparentObject shoudl be used ## def geomReparented(self, event): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## geom = event.object ## oldparent = event.oldparent ## # the listchooser needs to be updated when a geometry gets reparented. ## # replace old geometry name in the listchooser with the new one: ## oldname = oldparent.fullName + "|" + geom.name ## allentries = map(lambda x: x[0],self.chooser.entries) ## if oldname in allentries: ## ind = allentries.index(oldname) ## oldentry = self.chooser.entries[ind] ## self.chooser.remove(ind) ## self.chooser.insert(ind, (geom.fullName, 'no comment available', geom)) ## if len(oldentry)> 1: ## self.chooser.entries[ind] = (geom.fullName, 'no comment available', geom) + oldentry[1:] ## def setambiScale(self, val): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## self.ambiScale = val ## def setdiffScale(self, val): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## self.diffScale = val ## def setOff(self, val): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## self.off = val ## def addGeoms(self): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## for g in self.chooser.get(index=2): ## self.compOcclusion.add( (g.fullName, 'no comment available', g)) ## self.occluders.add( (g.fullName, 'no comment available', g)) ## self.chooser.remove( g.fullName ) ## return ## def removeGeoms(self): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## for g in self.compOcclusion.get(index=2): ## if g.fullName not in self.chooser.lb.get(0, 'end'): ## self.chooser.add( (g.fullName, 'no comment available', g) ) ## self.compOcclusion.remove( g.fullName ) ## return ## def addOccluders(self): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## for g in self.chooser.get(index=2): ## self.occluders.add( (g.fullName, 'no comment available', g)) ## self.chooser.remove( g.fullName ) ## return ## def removeOccluders(self): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## for g in self.occluders.get(index=2): ## if g.fullName not in self.chooser.lb.get(0, 'end'): ## self.chooser.add( (g.fullName, 'no comment available', g) ) ## self.occluders.remove( g.fullName ) ## return ## def setFovy_cb(self, *dummy): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## val = self.fovyTW.get() ## self.setFovy(val) ## def setFovy(self, fovy): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## #print 'fovy:', fovy, self.near, self.far ## self.fovy = fovy ## self.tk.call(self._w, 'makecurrent') ## glMatrixMode(GL_PROJECTION); ## glLoadIdentity() ## gluPerspective(float(fovy), ## float(self.width)/float(self.height), ## float(self.near), float(self.far)) ## glMatrixMode(GL_MODELVIEW) ## def GrabZBufferAsArray(self): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## """Grabs the detph buffer and returns it as a Numeric array""" ## from opengltk.extent import _gllib as gllib ## width = self.width ## height = self.height ## nar = Numeric.zeros(width*height, 'f') ## glFinish() #was glFlush() ## gllib.glReadPixels( 0, 0, width, height, GL.GL_DEPTH_COMPONENT, ## GL.GL_FLOAT, nar) ## glFinish() ## return nar ## def GrabZBuffer(self, zmin=None, zmax=None): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## """Grabs the detph buffer and returns it as PIL P image""" ## deptharray = self.GrabZBufferAsArray() ## # map z values to unsigned byte ## if zmin is None: ## zmin = min(deptharray) ## if zmax is None: ## zmax = max(deptharray) ## if (zmax!=zmin): ## zval1 = 255 * ((deptharray-zmin) / (zmax-zmin)) ## else: ## zval1 = Numeric.ones(self.width*self.height, 'f')*zmax*255 ## import Image ## depthImage = Image.fromstring('L', (self.width, self.height), ## zval1.astype('B').tostring()) ## return depthImage ## def Map(self, *dummy): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## """Cause the opengl widget to redraw itself.""" ## self.tk.call(self._w, 'makecurrent') ## self.Redraw() ## def Expose(self, event=None): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## """set the camera's exposeEvent so that at the next redraw ## the camera width and height are updated ## """ ## self.tk.call(self._w, 'makecurrent') ## self.Redraw() ## def setGeom(self, geom): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## self.tk.call(self._w, 'makecurrent') ## self.dpyList = GL.glGenLists(1) ## GL.glNewList(self.dpyList, GL.GL_COMPILE) ## if hasattr(geom, 'Draw'): ## status = geom.Draw() ## else: ## status = 0 ## GL.glEndList() ## self.geom = geom ## def Redraw(self, *dummy): ## if __debug__: ## if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ## #if self.dpyList is None: ## # return ## if self.matrix is None: ## return ## if self.dpyList is None: ## return ## glClearColor(0, 0, 0, 1 ) ## glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ## glViewport(0, 0, self.width, self.height) ## glPushMatrix() ## glLoadIdentity() ## glMultMatrixf(self.matrix) ## for l in self.dpyList: ## glCallList(l) ## glPopMatrix() ## if self.swap: ## self.tk.call(self._w, 'swapbuffers') ## ## if not self.viewer.isInitialized: ## ## self.after(100, self.Expose) ## ## else: ## ## # if viewer is in autoRedraw mode the next redraw will handle it ## ## if not self.exposeEvent and self.viewer.autoRedraw: ## ## self.viewer.Redraw() ## ## self.exposeEvent = True ## ## for o in self.viewer.rootObject.AllObjects(): ## ## if o.needsRedoDpyListOnResize or o.scissor: ## ## self.viewer.objectsNeedingRedo[o] = None ## ## class StandardCamera(Transformable, Tkinter.Widget, Tkinter.Misc): """Class for Opengl 3D drawing window""" initKeywords = [ 'height', 'width', 'rgba' 'redsize', 'greensize', 'bluesize', 'double', 'depth', 'depthsize', 'accum', 'accumredsize', 'accumgreensize', 'accumbluesize', 'accumalphasize', 'alpha', 'alphasize', 'stencil', 'stencilsize', 'auxbuffers', 'privatecmap', 'overlay', 'stereo', 'time', 'sharelist', 'sharecontext', 'ident', 'rootx', 'rooty', 'side', 'stereoflag', 'ssao', 'SSAO_OPTIONS' ] setKeywords = [ 'tagModified', 'height', 'width', 'fov', 'near', 'far', 'color', 'antialiased', 'contours', 'd1ramp', 'd1scale', 'd1off', 'd1cutL', 'd1cutH', 'd2scale', 'd2off', 'd2cutL', 'd2cutH', 'boundingbox', 'rotation', 'translation', 'scale', 'pivot', 'direction', 'lookAt', 'lookFrom', 'projectionType', 'rootx', 'rooty', 'stereoMode', 'sideBySideRotAngle', 'sideBySideTranslation', 'TV3DTranslation', 'TV3DRotAngle', 'TV3DScaling', 'suspendRedraw', 'drawThumbnail', 'ssao', 'SSAO_OPTIONS' ] PERSPECTIVE = 0 ORTHOGRAPHIC = 1 stereoModesList = ['MONO', 'SIDE_BY_SIDE_CROSS', 'SIDE_BY_SIDE_STRAIGHT', '3DTV', 'STEREO_BUFFERS', 'COLOR_SEPARATION_RED_BLUE', 'COLOR_SEPARATION_BLUE_RED', 'COLOR_SEPARATION_RED_GREEN', 'COLOR_SEPARATION_GREEN_RED', 'COLOR_SEPARATION_RED_GREENBLUE', 'COLOR_SEPARATION_GREENBLUE_RED', 'COLOR_SEPARATION_REDGREEN_BLUE', 'COLOR_SEPARATION_BLUE_REDGREEN' ] def getState(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ states = { 'height':self.height, 'width':self.width, 'rootx':self.rootx, 'rooty':self.rooty, 'fov':self.fovy, 'near':self.near, 'far':self.far, 'color':self.backgroundColor, 'antialiased':self.antiAliased, 'boundingbox':self.drawBB, 'rotation':list(self.rotation), 'translation':list(self.translation), 'scale':list(self.scale), 'pivot':list(self.pivot), 'direction':list(self.direction), 'lookAt':list(self.lookAt), 'lookFrom':list(self.lookFrom), 'projectionType':self.projectionType, 'stereoMode':self.stereoMode, 'sideBySideRotAngle':self.sideBySideRotAngle, 'sideBySideTranslation':self.sideBySideTranslation, 'TV3DTranslation': self.TV3DTranslation, 'TV3DRotAngle': self.TV3DRotAngle, 'TV3DScaling': self.TV3DScaling, 'suspendRedraw':self.suspendRedraw, 'drawThumbnail':self.drawThumbnailFlag, 'contours': self.contours, 'd1ramp':list(self.d1ramp), 'd1scale': self.d1scale, 'd1off': self.d1off, 'd1cutL': self.d1cutL, 'd1cutH': self.d1cutH, 'd2scale': self.d2scale, 'd2off': self.d2off, 'd2cutL': self.d2cutL, 'd2cutH': self.d2cutH, 'ssao':self.ssao, } if self.ssao: d = {} # for k in self.SSAO_OPTIONS: # d[k] = self.SSAO_OPTIONS[k][0] states['SSAO_OPTIONS'] = self.SSAO_OPTIONS return states def lift(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """brings the window containing the camera in front of others""" window = self.frame.master if isinstance(window, Tkinter.Tk) or \ isinstance(window, Tkinter.Toplevel): self.frame.master.lift() else: m = self.master while m.master: m = m.master m.lift() def AutoDepthCue(self, nearOffset=0.0, farOffset=0.0, object=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ AutoDepthCue(nearOffset=0.0, farOffset=0.0) set fog start and end automatically using the bounding box of the specified object. if delta is the depth of the bounding box, start will be set to near+(nearOffset*delta) end will be set to farn+(farOffset*delta) """ #print "StandardCamera.AutoDepthCue" #print 'BEFORE', self.near, self.far, self.fog.start, self.fog.end, self.nearDefault, self.farDefault if object is None: object = self.viewer.rootObject bb = object.ComputeBB(camera=self) lf = self.lookFrom la = self.lookAt v = lf-la from math import sqrt fl = frustrumlength = sqrt( v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) # compute unit vector in viewing direction viewDir1 = v/fl # project center of bb to view direction # and measure length from lookfrom to projected point bbCenter = (bb[1]+bb[0])*.5 u = bbCenter-lf u1 = u/sqrt(numpy.sum(u*u)) cosAlpha = numpy.dot(viewDir1, u1) v = u*cosAlpha l = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) # length from lookFrom # subtract from this distance halfDiag = bbCenter-bb[1] rad = sqrt(numpy.sum(halfDiag*halfDiag)) d = rad#/sqrt(3) v = (l-d)*viewDir1 start = sqrt(numpy.sum(v*v)) v = (l+d)*viewDir1 end = sqrt(numpy.sum(v*v)) #print 'AAAA1', l, d, start, end #print 'fog', self.fog.start, self.fog.end #print 'clip', self.near, self.far #far = -min(bb[0])+frustrumlength #near= -max(bb[1])+frustrumlength #delta = far-near #start = near+delta*nearOffset #end = far+delta*farOffset if start < end: self.fog.Set(start=start, end=end) # update camera near and far #self.Set(near=self.nearDefault, far=self.farDefault) #self.Set(near=self.fog.start*.9, far=self.fog.end*1.1) #print 'AAAA1', self.fog.start, self.fog.end, self.near, self.far #self.Set(near=self.fog.start*0.9) #self.Set(far=self.fog.end*1.1) self.Set(near=self.fog.start*0.9, far=self.fog.end*1.1) self.viewer.GUI.NearFarFog.Set(self.near, self.far, self.fog.start, self.fog.end) #print 'AFTER', self.nearDefault, self.farDefault #print 'fog', self.fog.start, self.fog.end #print 'clip', self.near, self.far def GrabFrontBufferAsArray(self, lock=True, buffer=GL.GL_FRONT): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Grabs the front buffer and returns it as Numeric array of size camera.width*camera.height*3""" from opengltk.extent import _gllib as gllib width = self.width height = self.height nar = Numeric.zeros(3*width*height, Numeric.UnsignedInt8) # get the redraw lock to prevent viewer from swapping buffers if lock: self.viewer.redrawLock.acquire() self.tk.call(self._w, 'makecurrent') glPixelStorei(GL.GL_PACK_ALIGNMENT, 1) current_buffer = int(GL.glGetIntegerv(GL.GL_DRAW_BUFFER)[0]) # tell OpenGL we want to read pixels from front buffer glReadBuffer(buffer) glFinish() #was glFlush() gllib.glReadPixels( 0, 0, width, height, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, nar) glFinish() # restore buffer from on which we operate glReadBuffer(current_buffer) if lock: self.viewer.redrawLock.release() return nar def GrabFrontBuffer(self, lock=True, buffer=GL.GL_FRONT): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Grabs the detph buffer and returns it as PIL P image""" nar = self.GrabFrontBufferAsArray(lock, buffer) import Image image = Image.fromstring('RGB', (self.width, self.height), nar.tostring()) #if sys.platform!='win32': image = image.transpose(Image.FLIP_TOP_BOTTOM) return image def GrabZBufferAsArray(self, lock=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Grabs the detph buffer and returns it as a Numeric array""" from opengltk.extent import _gllib as gllib width = self.width height = self.height nar = Numeric.zeros(width*height, 'f') if lock: # get the redraw lock to prevent viewer from swapping buffers self.viewer.redrawLock.acquire() glFinish() #was glFlush() gllib.glReadPixels( 0, 0, width, height, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, nar) glFinish() if lock: self.viewer.redrawLock.release() return nar def GrabZBuffer(self, lock=True, flipTopBottom=True, zmin=None, zmax=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Grabs the detph buffer and returns it as PIL P image""" deptharray = self.GrabZBufferAsArray(lock) # map z values to unsigned byte if zmin is None: zmin = min(deptharray) if zmax is None: zmax = max(deptharray) if (zmax!=zmin): zval1 = 255 * ((deptharray-zmin) / (zmax-zmin)) else: zval1 = Numeric.ones(self.width*self.height, 'f')*zmax*255 import Image depthImage = Image.fromstring('L', (self.width, self.height), zval1.astype('B').tostring()) #if sys.platform!='win32': if flipTopBottom is True: depthImage = depthImage.transpose(Image.FLIP_TOP_BOTTOM) return depthImage def SaveImage(self, filename, transparentBackground=False): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """None <- cam.SaveImage(filename, transparentBackground=False) The file format is defined by the filename extension. Transparent background is only supported in 'png' format. """ im = self.GrabFrontBuffer() if transparentBackground: errmsg = 'WARNING: transparent background is only supported with the png file format' name, ext = os.path.splitext(filename) if ext.lower != '.png': print errmsg filename += '.png' def BinaryImage(x): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if x==255: return 0 else: return 255 # grab z buffer z = self.GrabZBuffer() # turn 255 (i.e. bg into 0 opacity and everything else into 255) alpha = Image.eval(z, BinaryImage) im = Image.merge('RGBA', im.split()+(alpha,)) extension = os.path.splitext(filename)[1] kw = {} if not extension: filename += '.png' elif extension in ['.jpg', '.jpeg', '.JPG', '.JPEG']: kw = {'quality':95} im.save(filename, **kw) def ResetTransformation(self, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() Transformable.ResetTransformation(self, redo=redo) # Point at which we are looking self.lookAt = Numeric.array([0.0, 0.0, 0.0]) # Point at which the camera is self.lookFrom = Numeric.array([0.0, 0.0, 30.0]) # Vector from lookFrom to lookAt self.direction = self.lookAt - self.lookFrom # Field of view in y direction self.fovyNeutral = 40. self.fovy = self.fovyNeutral self.projectionType = self.PERSPECTIVE self.left = 0. self.right = 0. self.top = 0. self.bottom = 0. # Position of clipping planes. self.nearDefault = .1 self.near = self.nearDefault self.near_real = self.near self.farDefault = 50. self.far = self.farDefault self.zclipWidth = self.far - self.near self.SetupProjectionMatrix() def ResetDepthcueing(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.fog.Set(start = 25, end = 40) def BuildTransformation(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Creates the camera's transformation""" fx, fy, fz = self.lookFrom ax, ay, az = self.lookAt #ux, uy, uz = self.up gluLookAt( float(fx), float(fy), float(fz), float(ax), float(ay), float(az), float(0), float(1), float(0)) #lMatrix = Numeric.array(glGetDoublev(GL_MODELVIEW_MATRIX)).astype('f') #print 'Before', lMatrix #lRotation, lTranslation, lScale = self.Decompose4x4(lMatrix, cleanup=False) #print lRotation #print lTranslation #glLoadIdentity() #glTranslatef(float(lTranslation[0]), float(lTranslation[1]), float(lTranslation[2])) #glMultMatrixf(lRotation) #lMatrix = Numeric.array(glGetDoublev(GL_PROJECTION_MATRIX)).astype('f') #print 'After', lMatrix #float(ux), float(uy), float(uz) ) ## ## eye = self.lookFrom ## ## center = self.lookAt ## ## gluLookAt( eye[0], eye[1], eye[2], center[0], center[1], center[2], ## ## 0, 1, 0) ## ## return ## ## rot = Numeric.reshape(self.rotation, (4,4)) ## ## dir = Numeric.dot(self.direction, rot[:3,:3]) ## ## glTranslatef(dir[0], dir[1], dir[2]) ## glTranslatef(float(self.direction[0]),float(self.direction[1]),float(self.direction[2])) ## glMultMatrixf(self.rotation) ## glTranslatef(float(-self.lookAt[0]),float(-self.lookAt[1]),float(-self.lookAt[2])) ## ## glTranslatef(self.pivot[0],self.pivot[1],self.pivot[2]) ## ## glMultMatrixf(self.rotation) ## ## glTranslatef(-self.pivot[0],-self.pivot[1],-self.pivot[2]) def GetMatrix(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Returns the matrix that is used to transform the whole scene to the proper camera view""" glPushMatrix() glLoadIdentity() self.BuildTransformation() m = Numeric.array(glGetDoublev(GL_MODELVIEW_MATRIX)).astype('f') glPopMatrix() return Numeric.transpose(m) def GetMatrixInverse(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Returns the inverse of the matrix used to transform the whole scene to the proper camera view""" m = self.GetMatrix() m = Numeric.reshape(Numeric.transpose(m), (16,)).astype('f') rot, transl, scale = self.Decompose4x4(m) sc = Numeric.concatenate((Numeric.reshape(scale,(3,1)), [[1]])) n = Numeric.reshape(rot, (4,4))/sc tr = Numeric.dot(n, (transl[0], transl[1], transl[2],1) ) n[:3,3] = -tr[:3] return n ## def ConcatLookAtRot(self, matrix): ## """Rotates the lookAt point around the lookFrom point.""" ## matrix = Numeric.transpose(Numeric.reshape( matrix, (4,4) )) ## rot = Numeric.reshape( self.rotation, (4,4)) ## m = Numeric.dot(rot, matrix) ## m = Numeric.dot(m, Numeric.transpose(rot)) ## dir = Numeric.dot(self.direction, m[:3,:3]) ## self.lookAt = self.lookFrom + dir ## self.ConcatRotation(Numeric.reshape(matrix, (16,))) ## self.pivot = self.lookFrom ## def ConcatLookAtRot(self, matrix): ## """Rotates the lookAt point around the lookFrom point.""" ## self.SetPivot(self.lookFrom) ## #print "ConcatLookAtRot", self.pivot ## self.ConcatRotation(matrix) ## def ConcatLookFromRot(self, matrix): ## """Rotates the lookFrom point around the lookAt point.""" ## self.SetPivot(self.lookAt) ## #print "ConcatLookFromRot", self.pivot ## self.ConcatRotation(matrix) ## # not implemented ## def ConcatLookAtTrans(self, trans): ## pass def ConcatRotation(self, matrix): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Rotates the camera around the lookAt point""" self._modified = True x,y,z = self.lookFrom import numpy matrix = Numeric.reshape( matrix, (4,4) ) newFrom = numpy.dot((x,y,z,1), matrix ) self.Set(lookFrom=newFrom[:3]) ## glPushMatrix() ## glLoadIdentity() ## matrix = Numeric.reshape( matrix, (4,4) ) ## ## rot = Numeric.reshape( self.rotation, (4,4)) ## ## m = Numeric.dot(rot, matrix) ## ## m = Numeric.dot(m, Numeric.transpose(rot)) ## ## self.direction = Numeric.dot(self.direction, m[:3,:3]) ## ## self.lookFrom = self.lookAt - self.direction ## matrix = Numeric.reshape( Numeric.transpose( matrix ), (16,) ) ## glMultMatrixf(matrix) ## glMultMatrixf(self.rotation) ## self.rotation = Numeric.array(glGetDoublev(GL_MODELVIEW_MATRIX)).astype('f') ## self.rotation = glCleanRotMat(self.rotation).astype('f') ## self.rotation.shape = (16,) ## glPopMatrix() ## #self.pivot = self.lookAt self.viewer.deleteOpenglList() # needed to redraw the clippingplanes little frame def ConcatTranslation(self, trans, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Translate the camera from lookFrom to looAt""" self._modified = True newFrom = self.lookFrom+trans newAt = self.lookAt+trans # FIXME to update near far and fog we should compute deltaZ using view direction rather than assuming Z self.Set(lookFrom = newFrom, lookAt=newAt, near=self.near_real+trans[2], far= max(self.nearDefault+.1, self.far+trans[2])) self.fog.Set(start=self.fog.start+trans[2], end=self.fog.end+trans[2]) self.viewer.GUI.NearFarFog.Set(self.near, self.far, self.fog.start, self.fog.end) #print 'GOGO123' #self.AutoDepthCue() ## trans = Numeric.array(trans) ## sign = Numeric.add.reduce(trans) ## if sign > 0.0: ## n = 1 + (math.sqrt(Numeric.add.reduce(trans*trans)) * 0.01 ) ## newdir = self.direction*n ## diff = self.direction-newdir ## diff = math.sqrt(Numeric.add.reduce(diff*diff)) ## else: ## n = 1 - (math.sqrt(Numeric.add.reduce(trans*trans)) * 0.01 ) ## newdir = self.direction*n ## diff = self.direction-newdir ## diff = -math.sqrt(Numeric.add.reduce(diff*diff)) ## self.direction = newdir ## # print self.lookFrom, self.near, self.far, self.fog.start, self.fog.end ## # update near and far ## near = self.near_real + diff ## far = self.far + diff ## if near < far: ## self.Set(near=near, far=far, redo=redo) ## # update fog start and end ## #self.fog.Set(start=self.fog.start, end=self.fog.end + diff) ## if self.fog.start < self.fog.end + diff: ## self.fog.Set(end=self.fog.end + diff) ## # update viewerGUI ## if self == self.viewer.currentCamera: ## self.viewer.GUI.NearFarFog.Set(self.near, self.far, ## self.fog.start, self.fog.end) ## self.lookFrom = self.lookAt - self.direction #self.viewer.Redraw() self.viewer.deleteOpenglList() # needed to redraw the clippingplanes little frame def ConcatScale(self, scale, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Open and close camera's FOV """ #print "Camera.ConcatScale", scale self._modified = True if scale > 1.0 or self.scale[0] > 0.001: #fovy = abs(math.atan( math.tan(self.fovy*math.pi/180.) * scale ) * 180.0/math.pi) fovy = self.fovy * scale if fovy < 180.: self.Set(fov=fovy, redo=redo) def Geometry(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ Resize the Tk widget holding the camera to: self.widthxself.height+self.rootx+self.rooty This only applies when the camera is in its own top level. """ # get a handle to the master of the frame containing the Togl widget window = self.frame.master # if window is a toplevel window # replaced this test by test for geometry method #if isinstance(, Tkinter.Tk) or \ # isinstance(self.frame.master, Tkinter.Toplevel): if hasattr(window, 'geometry') and callable(window.geometry): # we have to set the geoemtry of the window to be the requested # size plus 2 times the border width of the frame containing the # camera off = 2*self.frameBorderWidth geom = '%dx%d+%d+%d' % (self.width+off, self.height+off, self.rootx, self.rooty) window.geometry(geom) def getGeometry(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """return the posx, posy, width, height of the window containing the camera""" geom = self.winfo_geometry() size, x, y = geom.split('+') w, h = size.split('x') return int(x), int(y), int(w), int(h) def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return self.name def __init__(self, master, screenName, viewer, num, check=1, cnf={}, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "StandardCamera.__init__" self.name = 'Camera'+str(num) self.num = num self.uniqID = self.name+viewer.uniqID # used for unprojection un gluUnProject self.unProj_model = None self.unProj_proj = None self.unProj_view = None self.swap = True # set to false to prevent camera from swapping after # redraw (used by tile renderer) self.suspendRedraw = False # set to True to prevent camera to be redraw # Use for ARViewer ( Added by AG 01/12/2006) self.lastBackgroundColorInPhotoMode = (0.,0.,0.,1.) if __debug__: if check: apply( checkKeywords, (self.name,self.initKeywords), kw) self.initialized = 0 self.swap = True Transformable.__init__(self, viewer) # FIXME: quick hack. Flag set by SetCurrentXxxx. When set object's # transformation and material are saved in log file self.hasBeenCurrent = 0 self._modified = False #self.posLog = [] # Once togl will allow to create widgets with same context # but for now we ignore it ==> no more multiple cameras # kw['samecontext'] = 1 # # Togl Tk widget options as of Version 1.5 # -height [DEFAULT_WIDTH=400], -width [DEFAULT_HEIGHT=400], # -rgba [true] # -redsize [1], -greensize [1], -bluesize [1] # -double [false] # -depth [false] # -depthsize [1] # -accum [false] # -accumredsize [1], -accumgreensize [1], -accumbluesize [1], -accumalphasize [1] # -alpha [false], -alphasize [1] # -stencil [false], -stencilsize [1] # -auxbuffers [0] # -privatecmap [false] # -overlay [false] # -stereo [false] # -time [DEFAULT_TIME = "1"] # -sharelist [NULL] # -sharecontext [NULL] # -ident [DEFAULT_IDENT = ""] if not kw.has_key('double'): kw['double'] = 1 # if not kw.has_key('overlay'): kw['overlay'] = 1 if not kw.has_key('depth'): kw['depth'] = 1 if not kw.has_key('stencil'): kw['stencil'] = 1 if hasattr(viewer, 'accumBuffersError') and viewer.accumBuffersError: # if we tried to create a context with accumulation buffers before # and it failed we set accum to False kw['accum'] = 0 else: # if the user did not specify accumulation we turn them on by defaut if not kw.has_key('accum'): kw['accum'] = 1 if not kw.has_key('stereo'): kw['stereo'] = 'none' if not kw.has_key('ident'): kw['ident'] = self.uniqID # kw['ident'] = 'camera%d' % num if not kw.has_key('sharelist') and len(viewer.cameras): # share list with the default camera. cam = viewer.cameras[0] kw['sharelist'] = cam.uniqID if not kw.has_key('sharecontext') and len(viewer.cameras): # share context with the default camera. cam = viewer.cameras[0] kw['sharecontext'] = cam.uniqID if not hasattr(cam, 'shareCTXWith'): cam.shareCTXWith = [] cam.shareCTXWith.append(self) ## if master is None: ## from os import path ## from opengltk.OpenGL import Tk ## toglInstallDir = path.dirname(path.abspath(Tk.__file__)) ## tclIncludePath = master.tk.globalgetvar('auto_path') ## master.tk.globalsetvar('auto_path', toglInstallDir + ' ' + ## tclIncludePath) ## master.tk.call('package', 'require', 'Togl') self.frameBorderWidth = 3 self.frame = Tkinter.Frame(master, bd=self.frameBorderWidth) #self.frame.master.protocol("WM_DELETE_WINDOW", self.hide) cfg = 0 if 'width' in cnf.keys(): self.width = cnf['width'] cfg = 1 else: cnf['width'] = self.width = 406 if 'height' in cnf.keys(): self.height = cnf['height'] cfg = 1 else: cnf['height'] = self.height = 406 self.rootx = 320 if 'rootx' in cnf.keys(): self.rootx = cnf['rootx'] del cnf['rootx'] cfg = 1 self.rooty = 180 if 'rooty' in cnf.keys(): self.rooty = cnf['rooty'] del cnf['rooty'] cfg = 1 if cfg: self.Geometry() if 'side' in cnf.keys(): side = cnf['side'] del cnf['side'] else: side = 'top' self.frame.pack(fill=Tkinter.BOTH, expand=1, side=side) self.defFrameBack = self.frame.config()['background'][3] self.ResetTransformation(redo=0) self.currentTransfMode = 'Object' # or 'Clip', 'Camera' self.renderMode = GL_RENDER self.pickNum = 0 self.objPick = [] self.drawBB = 0 self.drawMode = None # bit 1: for Opaque objects with no dpyList # bit 2: for objects using dpy list # bit 3: for Transp Object with dpyList self.drawTransparentObjects = 0 self.hasTransparentObjects = 0 self.selectDragRect = 0 self.fillSelectionBox = 0 # variable used for stereographic display self.sideBySideRotAngle = 3. self.sideBySideTranslation = 0. self.imageRendered = 'MONO' # can be LEFT_EYE or RIGHT_EYE self.stereoMode = 'MONO' # or 'SIDE_BY_SIDE' self.TV3DTranslation = 0.0 self.TV3DRotAngle = 1.5 self.TV3DScaling = (0.5, 0.5, 0.25) self.backgroundColor = (.0,.0,.0, 1.0) self.selectionColor = (1.0, 1.0, 0.0, 1.0) self.fillDelay = 200 # delay in miliseconds for filling selection box toglVersion = loadTogl(self.frame) #print "Togl Version:", toglVersion if os.name == 'nt': if kw['stereo'] == 'none': kw['stereo'] = 0 else: kw['stereo'] = 1 # after this line self.master will be set to self frame from Tkinter import TclError from opengltk.exception import GLerror try: Tkinter.Widget.__init__(self, self.frame, 'togl', cnf, kw) try: GL.glAccum(GL.GL_LOAD, 1.0) viewer.accumBuffersError = False except GLerror: viewer.accumBuffersError = True #viewer.accumBuffersError = False except TclError, e: print "Warning: disabling accumulation buffers",e viewer.accumBuffersError = True kw.pop('accum') Tkinter.Widget.__init__(self, self.frame, 'togl', cnf, kw) #currentcontext = self.tk.call(self._w, 'contexttag') #print "StandardCamera.__init__ currentcontext", currentcontext if (DejaVu.preventIntelBug_BlackTriangles is None) \ or (DejaVu.preventIntelBug_WhiteTriangles is None): isIntelOpenGL = GL.glGetString(GL.GL_VENDOR).find('Intel') >= 0 if isIntelOpenGL is True: isIntelGmaRenderer = GL.glGetString(GL.GL_RENDERER).find("GMA") >= 0 lPreventIntelBugs = isIntelOpenGL and not isIntelGmaRenderer else: lPreventIntelBugs = False if DejaVu.preventIntelBug_BlackTriangles is None: DejaVu.preventIntelBug_BlackTriangles = lPreventIntelBugs if DejaVu.preventIntelBug_WhiteTriangles is None: DejaVu.preventIntelBug_WhiteTriangles = lPreventIntelBugs if DejaVu.defaultAntiAlias is None: if os.name == 'nt': DejaVu.defaultAntiAlias = 0 else: try: from opengltk.extent import _glextlib # tells us the graphic card is not too bad DejaVu.defaultAntiAlias = 4 except: DejaVu.defaultAntiAlias = 0 self.antiAliased = DejaVu.defaultAntiAlias self._wasAntiAliased = 0 self.drawThumbnailFlag = False if self.antiAliased == 0: self.accumWeigth = 1. self.jitter = None else: self.accumWeigth = 1./self.antiAliased self.jitter = eval('jitter._jitter'+str(self.antiAliased)) self.newList = GL.glGenLists(1) self.dpyList = None self.visible = 1 self.ownMaster = False # set tot tru is the master of self.Frame # has to be destroyed when Camera is deleted self.exposeEvent = False # set to true on expose events and reset in # Viewer.ReallyRedraw self.firstRedraw = True # create a TK-event manager for this camera self.eventManager = EventManager(self) self.eventManager.AddCallback('', self.Map) self.eventManager.AddCallback('', self.Expose) self.eventManager.AddCallback('', self.Expose) self.eventManager.AddCallback('', self.Enter_cb) self.onButtonUpCBlist = [] # list of functions to be called when self.onButtonDownCBlist = [] # mouse button is pressed or depressed # they take 1 argument of type Tk event # register funtion to swi self.addButtonDownCB(self.suspendAA) self.addButtonUpCB(self.restoreAA) self.addButtonDownCB(self.suspendNPR) self.addButtonUpCB(self.restoreNPR) self.addButtonDownCB(self.reduceSSAOQuality) self.addButtonUpCB(self.restoreSSAOQuality) self.addButtonUpCB(self.capClippedGeoms) # these are used in bindPickingToMouseButton to bind picking to a # given mouse button self.mouseButtonModifiers = ['None', 'Shift', 'Control', 'Alt', 'Meta'] # this keys if self.mouseButtonActions are the objects to which the # trackball can be attached i.e. 'Object', 'Insert2d', 'Camera' etc. # for each such key there is a dict with buttonnum as key (1,2,3) # for each such key there is a dict with keys modifiers and values # a string describing an action # # e.g mouseButtonActions['Object'][3]['Shift'] = 'Ztranslation' self.mouseButtonActions = {} for bindings in ['Object', 'Insert2d', 'Camera', 'Clip', 'Light', 'Texture', 'Scissor']: self.mouseButtonActions[bindings] = { 1:{}, 2:{}, 3:{} } bd = self.mouseButtonActions[bindings] for b in (1,2,3): d = bd[b] for mod in self.mouseButtonModifiers: d[mod] = 'None' # initialize actions for object bd = self.mouseButtonActions['Object'] for mod in self.mouseButtonModifiers: bd[2][mod] = 'picking' bd[1]['None'] = 'rotation' bd[1]['Shift'] = 'addToSelection' bd[1]['Control'] = 'removeFromSelection' bd[2]['None'] = 'None' #bd[2]['Alt'] = 'camZtranslation' bd[2]['Control'] = 'scale' bd[2]['Shift'] = 'zoom' bd[3]['None'] = 'XYtranslation' bd[3]['Control'] = 'pivotOnPixel' bd[3]['Shift'] = 'Ztranslation' # initialize actions for Insert2d bd = self.mouseButtonActions['Insert2d'] for mod in self.mouseButtonModifiers: bd[1][mod] = 'picking' #bd[2]['Alt'] = 'camZtranslation' bd[2]['Shift'] = 'zoom' # initialize actions for Clip bd = self.mouseButtonActions['Clip'] bd[1]['None'] = 'rotation' #bd[2]['None'] = 'rotation' #bd[2]['Alt'] = 'camZtranslation' bd[2]['Control'] = 'scale' bd[2]['Shift'] = 'zoom' bd[3]['None'] = 'screenXYtranslation' bd[3]['Control'] = 'screenZtranslation' bd[3]['Shift'] = 'Ztranslation' # initialize actions for Light bd = self.mouseButtonActions['Light'] bd[1]['None'] = 'rotation' #bd[2]['None'] = 'rotation' #bd[2]['Alt'] = 'camZtranslation' bd[2]['Shift'] = 'zoom' # initialize actions for Camera bd = self.mouseButtonActions['Camera'] bd[1]['None'] = 'camRotation' #bd[2]['None'] = 'camRotation' #bd[2]['Alt'] = 'camZtranslation' #bd[2]['Control'] = 'zoom' bd[3]['Shift'] = 'zoom ' bd[3]['None'] = 'camXYtranslation' bd[3]['Control'] = 'camZtranslation' # initialize actions for Texture bd = self.mouseButtonActions['Texture'] bd[1]['None'] = 'rotation' #bd[2]['None'] = 'rotation' #bd[2]['Alt'] = 'camZtranslation' bd[2]['Control'] = 'scale' bd[2]['Shift'] = 'zoom' bd[3]['None'] = 'XYtranslation' bd[3]['Shift'] = 'Ztranslation' # initialize actions for Scissor bd = self.mouseButtonActions['Scissor'] #bd[2]['Alt'] = 'camZtranslation' bd[2]['Control'] = 'scale' bd[2]['Shift'] = 'zoom' bd[3]['None'] = 'translation' bd[3]['Shift'] = 'ratio' # define actionName and callback fucntions equivalence self.actions = { 'Object': { 'picking':self.initSelectionRectangle, 'addToSelection':self.initSelectionRectangle, 'removeFromSelection':self.initSelectionRectangle, 'rotation':viewer.RotateCurrentObject, 'scale':viewer.ScaleCurrentObject, 'XYtranslation':viewer.TranslateCurrentObjectXY, 'Ztranslation':viewer.TranslateCurrentObjectZ, 'zoom':viewer.ScaleCurrentCamera, 'camZtranslation':viewer.TranslateCurrentCamera, 'pivotOnPixel':viewer.pivotOnPixel, }, 'Insert2d': { 'picking':self.SetInsert2dPicking, 'zoom':viewer.ScaleCurrentCamera, 'camZtranslation':viewer.TranslateCurrentCamera, }, 'Clip': { 'picking':None, 'rotation':viewer.RotateCurrentClipPlane, 'scale':viewer.ScaleCurrentClipPlane, 'screenXYtranslation':viewer.screenTranslateCurrentObjectXY, 'Ztranslation':viewer.TranslateCurrentObjectZ, 'zoom':viewer.ScaleCurrentCamera, 'camZtranslation':viewer.TranslateCurrentCamera, 'screenZtranslation':viewer.screenTranslateCurrentObjectZ, }, 'Light': { 'picking':None, 'rotation':viewer.RotateCurrentDLight, 'zoom':viewer.ScaleCurrentCamera, 'camZtranslation':viewer.TranslateCurrentCamera, }, 'Camera': { 'picking':None, 'camRotation':viewer.RotateCurrentCamera, 'zoom':viewer.ScaleCurrentCamera, 'zoom ':viewer.ScaleCurrentCamera, #it doesn't work if we use the same name 'camZtranslation':viewer.TranslateCurrentCamera, 'camXYtranslation':viewer.TranslateXYCurrentCamera, #it doesn't work if we use the same name }, 'Texture': { 'picking':None, 'rotation':viewer.RotateCurrentTexture, 'scale':viewer.ScaleCurrentTexture, 'XYtranslation':viewer.TranslateCurrentTextureXY, 'Ztranslation':viewer.TranslateCurrentTextureZ, 'zoom':viewer.ScaleCurrentCamera, 'camZtranslation':viewer.TranslateCurrentCamera, }, 'Scissor': { 'picking':None, 'ratio':viewer.AspectRatioScissor, 'scale':viewer.ScaleCurrentScissor, 'translation':viewer.TranslateCurrentScissor, 'zoom':viewer.ScaleCurrentCamera, 'camZtranslation':viewer.TranslateCurrentCamera, }, } # add a trackball self.AddTrackball() for binding in ['Object', 'Insert2d', 'Camera', 'Clip', 'Light', 'Texture', 'Scissor']: self.actions[binding]['None'] = self.trackball.NoFunc if os.name == 'nt': #sys.platform == 'win32': self.eventManager.AddCallback( #"", viewer.scaleCurrentCameraMouseWheel) "", viewer.translateCurrentCameraMouseWheel) #self.bind("", viewer.scaleCurrentCameraMouseWheel) else: self.eventManager.AddCallback( #"", viewer.scaleCurrentCameraMouseWheel) "", viewer.translateCurrentCameraMouseWheel) self.eventManager.AddCallback( # "", viewer.scaleCurrentCameraMouseWheel) "", viewer.translateCurrentCameraMouseWheel) #self.bind("", viewer.scaleCurrentCameraMouseWheel) #self.bind("", viewer.scaleCurrentCameraMouseWheel) # light model is define in Viewer for all cameras # self.lightModel = None self.fog = Fog(self) self.fog.Set(color=self.backgroundColor) self.pack(side='left', expand=1, fill='both') # attributes used to draw black outlines # self.imCanvastop = None # top level window for silhouette rendering self.contouredImage = None # will hole the final PIL image self.outlineim = None # will hole the final contour self.outline = None # accumulation buffer used for AA contour self.contours = False # set to True to enable contouring self.d1scale = 0.013 self.d1off = 4 self.d1cutL = 0 self.d1cutH = 60 self.d1ramp = Numeric.arange(0,256,1,'f') self.d2scale = 0.0 # turn off second derivative self.d2off = 1 self.d2cutL = 150 self.d2cutH = 255 self._suspendNPR = False # used during motion # we save it so it can be reapplied if the projection matrix is recreated self.pickMatrix = None # prepare contour highlight self.contourTextureName = int(glGenTextures(1)[0]) glPrioritizeTextures(numpy.array([self.contourTextureName]), numpy.array([1.])) # supposedly make this texture fast _gllib.glBindTexture(GL_TEXTURE_2D, int(self.contourTextureName) ) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) self.stencilTextureName = int(glGenTextures(1)[0]) # glPrioritizeTextures supposedly make this texture fast glPrioritizeTextures(numpy.array([self.stencilTextureName]), numpy.array([1.])) _gllib.glBindTexture(GL_TEXTURE_2D, int(self.stencilTextureName) ) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) # prepare patterned highlight self.textureName = int(glGenTextures(1)[0]) lTexture = Numeric.array( ( (.0,.0,.0,.8),(.0,.0,.0,.8),(.0,.0,.0,.8),(.0,.0,.0,.8),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), (.0,.0,.0,.8),(1.,1.,1.,.6),(1.,1.,1.,.6),(.0,.0,.0,.8),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), (.0,.0,.0,.8),(1.,1.,1.,.6),(1.,1.,1.,.6),(.0,.0,.0,.8),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), (.0,.0,.0,.8),(.0,.0,.0,.8),(.0,.0,.0,.8),(.0,.0,.0,.8),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), (.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), (.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), (.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), (.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0),(.0,.0,.0,.0), ),'f') _gllib.glBindTexture(GL_TEXTURE_2D, self.textureName ) glPrioritizeTextures(numpy.array([self.textureName]), numpy.array([1.])) # supposedly make this texture fast glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST) _gllib.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL.GL_FLOAT, lTexture) #glEnable(GL_TEXTURE_GEN_S) #glEnable(GL_TEXTURE_GEN_T) #glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ) #glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR ) #glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND) # to protect our texture, we bind the default texture while we don't use it self.dsT = 0 # to protect our texture, we bind the default texture while we don't use it self.ssao_method = 0 self.copy_depth_ssao = True if 'ssao' not in kw: kw['ssao'] = False self.ssao = False self.use_mask_depth = 0 else : self.ssao = kw['ssao'] if 'SSAO_OPTIONS' in kw : self.SSAO_OPTIONS = kw['SSAO_OPTIONS'] else : self.use_mask_depth = 0 self.setDefaultSSAO_OPTIONS() self.setShaderSSAO() _gllib.glBindTexture(GL_TEXTURE_2D, 0 ) self.setShaderSelectionContour() self.cursorStack = [] self.currentCursor = 'default' def addButtonDownCB(self, func): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() assert callable(func) if func not in self.onButtonDownCBlist: self.onButtonDownCBlist.append(func) def delButtonDownCB(self, func, silent=False): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if func in self.onButtonDownCBlist: self.onButtonDownCBlist.remove(func) else: if not silent: print 'WARNING: delButtonDownCB: function not found', func def addButtonUpCB(self, func): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() assert callable(func) if func not in self.onButtonUpCBlist: self.onButtonUpCBlist.append(func) def delButtonUpCB(self, func, silent=False): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if func in self.onButtonUpCBlist: self.onButtonUpCBlist.remove(func) else: if not silent: print 'WARNING: delButtonUpCB: function not found', func def reduceSSAOQuality(self, event): if self.ssao: self._oldSSAOSamples = self.SSAO_OPTIONS['samples'][0] if len(self.SSAO_OPTIONS['samples']) == 5 : self.SSAO_OPTIONS['samples'][-1].set(2) else: self.SSAO_OPTIONS['samples'][0] = 2 def restoreSSAOQuality(self, event): if self.ssao: if len(self.SSAO_OPTIONS['samples']) == 5 : self.SSAO_OPTIONS['samples'][-1].set(self._oldSSAOSamples) else: self.SSAO_OPTIONS['samples'][0] = self._oldSSAOSamples del self._oldSSAOSamples def suspendAA(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Function used to turn off anti-aliasing during motion """ #print "suspendAA" if self.antiAliased == False: self.antiAliased = 0 assert isinstance(self.antiAliased, types.IntType), self.antiAliased if self._wasAntiAliased == 0 : # else it is already suspended if self.antiAliased <= DejaVu.allowedAntiAliasInMotion: # save the state self._wasAntiAliased = self.antiAliased # we don't suspend anti alias or anti alias is already suspended else: # save the state self._wasAntiAliased = self.antiAliased # we suspend anti alias self.antiAliased = 0 def restoreAA(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Function used to restore anti-aliasing after motion """ #print "restoreAA" self.antiAliased = self._wasAntiAliased self._wasAntiAliased = 0 def capClippedGeoms(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Function used to cap clipped geoms when button is released""" if self.currentTransfMode!='Clip': return for geom, cp, capg in self.viewer.cappedGeoms: if cp != self.viewer.currentClip: continue vc, fc = cp.getCapMesh(geom) capg.Set(vertices=vc, faces=fc) def suspendNPR(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Function used to turn off NPR during motion """ if self.viewer.contourTk.get() is True: self._suspendNPR = True self._suspendNPR_rootMaterialsPropDiffuse = self.viewer.rootObject.materials[GL.GL_FRONT].prop[1] self._suspendNPR_rootMaterialsbindDiffuse = self.viewer.rootObject.materials[GL.GL_FRONT].binding[1] #print "self._suspendNPR_rootMaterialsPropDiffuse", self._suspendNPR_rootMaterialsPropDiffuse #print "self._suspendNPR_rootMaterialsbindDiffuse", self._suspendNPR_rootMaterialsbindDiffuse if self._suspendNPR_rootMaterialsbindDiffuse == 1 \ and len(self._suspendNPR_rootMaterialsPropDiffuse) == 1 \ and len(self._suspendNPR_rootMaterialsPropDiffuse[0]) >= 3 \ and self._suspendNPR_rootMaterialsPropDiffuse[0][0] == 1 \ and self._suspendNPR_rootMaterialsPropDiffuse[0][1] == 1 \ and self._suspendNPR_rootMaterialsPropDiffuse[0][2] == 1 : # root color is set to grey self.viewer.rootObject.materials[GL.GL_FRONT].prop[1] = Numeric.array( ((.5, .5, .5, 1.0 ), ), 'f' ) self.viewer.rootObject.materials[GL.GL_FRONT].binding[1] = viewerConst.OVERALL # lighting is turned on self._suspendNPR_OverAllLightingIsOn = self.viewer.OverAllLightingIsOn.get() self.viewer.OverAllLightingIsOn.set(1) self.viewer.deleteOpenglListAndCallRedrawAndCallDisableGlLighting() def restoreNPR(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Function used to restore NPR after motion """ if self.viewer.contourTk.get() is True: # root color is set to what it was self.viewer.rootObject.materials[GL.GL_FRONT].prop[1] = self._suspendNPR_rootMaterialsPropDiffuse self.viewer.rootObject.materials[GL.GL_FRONT].binding[1] = self._suspendNPR_rootMaterialsbindDiffuse # lighting is set to what it was self.viewer.OverAllLightingIsOn.set(self._suspendNPR_OverAllLightingIsOn) self.viewer.deleteOpenglListAndCallRedrawAndCallDisableGlLighting() self._suspendNPR = False def pushCursor(self, cursorName): self.configure(cursor=cursorsDict[cursorName]) self.cursorStack.append(self.currentCursor) self.currentCursor = cursorName def popCursor(self): if len(self.cursorStack): self.currentCursor = cursorName = self.cursorStack.pop(-1) self.configure(cursor=cursorsDict[cursorName]) def setCursor(self, buttonNum): modDict = self.viewer.kbdModifier xform = self.viewer.Xform.get() if modDict['Shift_L']: action = self.mouseButtonActions[xform][buttonNum]['Shift'] elif modDict['Control_L']: action = self.mouseButtonActions[xform][buttonNum]['Control'] elif modDict['Alt_L']: action = self.mouseButtonActions[xform][buttonNum]['Alt'] else: action = self.mouseButtonActions[xform][buttonNum]['None'] #print 'AAAAAAAAAAAA', action#, modDict if cursorsDict.has_key(action): self.configure(cursor=cursorsDict[action]) def bindAllActions(self, actionDict): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "bindAllActions", actionDict for b in (1,2,3): d = self.mouseButtonActions[actionDict][b] for mod in self.mouseButtonModifiers: self.bindActionToMouseButton(d[mod], b, mod, actionDict) def findButton(self, action, actionDict): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() for b in (1,2,3): d = self.mouseButtonActions[actionDict][b] for mod in self.mouseButtonModifiers: if d[mod]==action: return b, mod return None, None # FIXME picking and other mouse actions should be unified # Press events register the motion and release callbacks # this will enable to process picking and others in the same way def bindActionToMouseButton(self, action, buttonNum, modifier='None', actionDict='Object'): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """registers callbacks to trigger picking when the specified mouse button is pressed. buttonNum can be 1,2,3 or 0 to remove call backs """ #print "bindActionToMouseButton", buttonNum, action, modifier, actionDict ehm = self.eventManager func = self.actions[actionDict][action] # find button and modifier to which actions is bound currently oldnum, oldmod = self.findButton(action, actionDict) if action in ['picking', 'addToSelection', 'removeFromSelection', 'pivotOnPixel']: if oldnum: # picking action was bound to a mouse button # remove the picking callbacks from previous picking button if modifier=='None': modifier1='' else: modifier1=modifier+'-' ev = '<'+modifier1+'ButtonPress-'+str(oldnum)+'>' ehm.RemoveCallback(ev, func) # remove all motion call back on buttonNum for all modifiers if modifier=='None': modifier1='' else: modifier1=modifier+'-' setattr(self.trackball, modifier1+'B'+str(buttonNum)+'motion', self.trackball.NoFunc) # now bind picking to buttonNum for all modifiers self.mouseButtonActions[actionDict][buttonNum][modifier] = action if modifier=='None': modifier1='' else: modifier1=modifier+'-' ev = '<'+modifier1+'ButtonPress-'+str(buttonNum)+'>' ehm.AddCallback(ev, func) else: # not picking if oldnum: # action was bound to a mouse button # remove the picking callbacks from previous picking button if oldmod=='None': mod1='' else: mod1=oldmod+'-' ev = '<'+mod1+'ButtonPress-'+str(oldnum)+'>' oldaction = self.mouseButtonActions[actionDict][buttonNum][oldmod] if oldaction=='picking' or oldaction=='pivotOnPixel': ehm.RemoveCallback(ev, self.actions[actionDict][oldaction]) # remove motion callback on oldbuttonNum for oldmodifier if oldmod=='None': mod='' else: mod=oldmod setattr(self.trackball, mod+'B'+str(oldnum)+'motion', self.trackball.NoFunc) self.mouseButtonActions[actionDict][oldnum][oldmod] = 'None' # remove picking callback on buttonNum for modifier if modifier=='None': mod='' else: mod=modifier+'-' oldaction = self.mouseButtonActions[actionDict][buttonNum][modifier] if oldaction=='picking' or oldaction=='pivotOnPixel': ev = '<'+mod+'ButtonPress-'+str(buttonNum)+'>' ehm.RemoveCallback(ev, self.actions[actionDict][oldaction]) # now bind picking to buttonNum for all modifiers if modifier=='None': mod='' else: mod=modifier setattr(self.trackball, mod+'B'+str(buttonNum)+'motion', func) self.mouseButtonActions[actionDict][buttonNum][modifier] = action def AddTrackball(self, size=0.8, rscale=2.0, tscale=0.05, sscale=0.01, renorm=97): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add a Trackball to this camera with default bindings """ #print "AddTrackball" self.trackball = Trackball(self, size, rscale, tscale, sscale, renorm ) ehm = self.eventManager #print 'FOO1' # COMMENTED OUT BY MS when I moved rotation to button 1 #self.bindActionToMouseButton('rotation', 1) ## ehm.AddCallback('', self.recordMousePosition_cb) ## ehm.AddCallback('', self.SelectPick) ## ehm.AddCallback('', self.CenterPick_cb) ## ehm.AddCallback('', self.DoubleSelectPick_cb) ## ehm.AddCallback('', self.TransfCamera_cb) # is set by default to record the mouse position # add drawing of first selection rectangle # ehm.AddCallback("", self.initSelectionRectangle ) # ehm.AddCallback("", self.initSelectionRectangle ) # ehm.AddCallback("", self.initSelectionRectangle ) # ehm.AddCallback("", self.initSelectionRectangle ) def ListBoundEvents(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """List all event bound to a callback function""" if not event: return self.bind() else: return self.bind(event) def __del__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Destroy the camera """ #print "StandardCamera.__del__", self self.frame.master.destroy() def Enter_cb(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Call back function trigger when the mouse enters the camera """ if widgetsOnBackWindowsCanGrabFocus is False: lActiveWindow = self.focus_get() if lActiveWindow is not None \ and ( lActiveWindow.winfo_toplevel() != self.winfo_toplevel() ): return self.focus_set() self.tk.call(self._w, 'makecurrent') if not self.viewer: return self.SelectCamera() if not hasattr(self.viewer.GUI, 'Xform'): return self.viewer.Xform.set(self.currentTransfMode) if self.currentTransfMode=='Object': self.viewer.GUI.enableNormalizeButton(Tkinter.NORMAL) self.viewer.GUI.enableCenterButton(Tkinter.NORMAL) else: self.viewer.GUI.enableNormalizeButton(Tkinter.DISABLED) self.viewer.GUI.enableCenterButton(Tkinter.DISABLED) def _setFov(self, fov): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if fov > 0.0 and fov < 180.0: self.fovy = fov else: raise AttributeError('fov has to be < 180.0 and > 0.0 was %f'%fov) def _setLookFrom(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() mat = numpy.array(val, 'f') self.lookFrom = mat self.direction = self.lookAt - self.lookFrom def Set(self, check=1, redo=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set various camera parameters """ #print "Camera.Set", redo if __debug__: if check: apply( checkKeywords, (self.name,self.setKeywords), kw) val = kw.get( 'tagModified', True ) assert val in [True, False] self._modified = val # we disable redraw because autoRedraw could cause ReallyRedraw # to set camera.width and camera.height BEFORE te window gets # resized by Tk if self.viewer.autoRedraw: restoreAutoRedraw = True self.viewer.stopAutoRedraw() else: restoreAutoRedraw = False w = kw.get( 'width') if not w is None: assert type(w)==types.IntType if w > 0: self.width = w else: raise AttributeError('width has to be > 0') h = kw.get( 'height') if not h is None: assert type(h)==types.IntType if h > 0: # we disable redraw because autoRedraw could cause ReallyRedraw # to set camera.width and camera.height BEFORE te window gets # resized by Tk self.height = h else: raise AttributeError('height has to be > 0') px = kw.get( 'rootx') if not px is None: px = max(px, 0) master = self.frame.master while hasattr(master, 'wm_maxsize') is False: master = master.master xmax, ymax = master.wm_maxsize() px = min(px, xmax -100) self.rootx = px py = kw.get( 'rooty') if not py is None: py = max(py, 0) master = self.frame.master while hasattr(master, 'wm_maxsize') is False: master = master.master xmax, ymax = master.wm_maxsize() py = min(py, ymax - 100) self.rooty = py # if width, height of position of camera changed apply changes if w or h or px or py: self.Geometry() self.viewer.update() if restoreAutoRedraw: self.viewer.startAutoRedraw() fov = kw.get( 'fov') if not fov is None: if fov > 0.0 and fov < 180.0: self.fovy = fov else: raise AttributeError('fov has to be < 180.0 and > 0.0 was %f'%fov) near = kw.get( 'near', self.near) far = kw.get( 'far', self.far) self.zclipWidth = far - near near = kw.get( 'near') if not near is None: #print 'NEAR:', near, far, if near >= far: raise AttributeError('near sould be smaller than far') if near > far-self.zclipWidth: near = max(far-self.zclipWidth, self.nearDefault) # truncate near at 0.1 self.near = max(near, self.nearDefault) self.near_real = near #print self.near, self.near_real, self.far, self.zclipWidth if not far is None: #print 'FAR:', self.near, far, if far <= self.near: self.far = self.near + self.zclipWidth #if self.near == self.nearDefault: # self.far = self.near * 1.5 #else: # raise AttributeError('far sould be larger than near') else: self.far = far #print self.near, self.near_real, self.far, self.zclipWidth if fov or near or far: self.SetupProjectionMatrix() val = kw.get( 'color') if not val is None: color = colorTool.OneColor( val ) if color: self.backgroundColor = color val = kw.get( 'antialiased') if not val is None: if val in jitter.jitterList: self.antiAliased = val if val!=0: self.accumWeigth = 1.0/val self.jitter = eval('jitter._jitter'+str(val)) else: raise ValueError('antiAliased can only by one of', \ jitter.jitterList) # NPR parameters #first derivative val = kw.get( 'd1ramp') if not val is None: self.d1ramp=val val = kw.get( 'd1scale') if not val is None: assert isinstance(val, float) assert val>=0.0 self.d1scale = val val = kw.get( 'd1off') if not val is None: assert isinstance(val, int) self.d1off = val val = kw.get( 'd1cutL') if not val is None: assert isinstance(val, int) assert val>=0 self.d1cutL = val val = kw.get( 'd1cutH') if not val is None: assert isinstance(val, int) assert val>=0 self.d1cutH = val #second derivative val = kw.get( 'd2scale') if not val is None: assert isinstance(val, float) assert val>=0.0 self.d2scale = val val = kw.get( 'd2off') if not val is None: assert isinstance(val, int) self.d2off = val val = kw.get( 'd2cutL') if not val is None: assert isinstance(val, int) assert val>=0 self.d2cutL = val val = kw.get( 'd2cutH') if not val is None: assert isinstance(val, int) assert val>=0 self.d2cutH = val val = kw.get( 'contours') if not val is None: assert val in [True, False] if self.contours != val: self.contours = val if val is True: self.lastBackgroundColorInPhotoMode = self.backgroundColor self.backgroundColor = (1.,1.,1.,1.) if self.viewer.OverAllLightingIsOn.get() == 1: self.viewer.OverAllLightingIsOn.set(0) else: self.backgroundColor = self.lastBackgroundColorInPhotoMode if self.viewer.OverAllLightingIsOn.get() == 0: self.viewer.OverAllLightingIsOn.set(1) self.fog.Set(color=self.backgroundColor) self.viewer.deleteOpenglListAndCallRedrawAndCallDisableGlLighting() # if val: # self.imCanvastop = Tkinter.Toplevel() # self.imCanvas = Tkinter.Canvas(self.imCanvastop) # self.imCanvas1 = Tkinter.Canvas(self.imCanvastop) # self.imCanvas2 = Tkinter.Canvas(self.imCanvastop) # self.imCanvas3 = Tkinter.Canvas(self.imCanvastop) # self.canvasImage = None # self.canvasImage1 = None # self.canvasImage2 = None # self.canvasImage3 = None # elif self.imCanvastop: # self.imCanvastop.destroy() # self.imCanvas = None # self.imCanvas1 = None # self.imCanvas2 = None # self.imCanvas3 = None # if hasattr(self, 'ivi'): # self.ivi.Exit() # from opengltk.OpenGL import GL # if not hasattr(GL, 'GL_CONVOLUTION_2D'): # print 'WARNING: camera.Set: GL_CONVOLUTION_2D nor supported' # self.contours = False # else: # from DejaVu.imageViewer import ImageViewer # self.ivi = ImageViewer(name='zbuffer') val = kw.get( 'boundingbox') if not val is None: if val in viewerConst.BB_MODES: self.drawBB = val else: raise ValueError('boundingbox can only by one of NO, \ ONLY, WITHOBJECT') val = kw.get( 'rotation') if not val is None: self.rotation = Numeric.identity(4, 'f').ravel() mat = Numeric.reshape(Numeric.array(val), (4,4)).astype('f') self.ConcatRotation(mat) val = kw.get( 'translation') if not val is None: self.translation = Numeric.zeros( (3,), 'f') mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') self.ConcatTranslation(mat, redo=redo) val = kw.get( 'scale') if not val is None: self.SetScale( val, redo=redo ) val = kw.get( 'pivot') if not val is None: self.SetPivot( val ) val = kw.get( 'direction') if not val is None: mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') self.direction = mat valLookFrom = kw.get('lookFrom') if valLookFrom is not None: mat = numpy.array(valLookFrom, 'f') assert mat.shape==(3,) self.lookFrom = mat self.direction = self.lookAt - self.lookFrom valLookAt = kw.get('lookAt') if valLookAt is not None: mat = numpy.array(valLookAt, 'f') assert mat.shape==(3,) self.lookAt = mat self.direction = self.lookAt - self.lookFrom valUp = kw.get('up') if valUp is not None: mat = numpy.array(valUp, 'f') assert mat.shape==(3,) self.up = mat ## # compute .translation and .rotation used to build camera transformation ## # FIXME .. could recompute only if one changed ## if valLookAt is not None \ ## or valLookFrom is not None \ ## or valUp is not None: ## glPushMatrix() ## glLoadIdentity() ## glMatrixMode(GL_MODELVIEW) ## fx, fy, fz = self.lookFrom ## ax, ay, az = self.lookAt ## ux, uy, uz = self.up ## gluLookAt( float(fx), float(fy), float(fx), ## float(ax), float(ay), float(az), ## float(ux), float(uy), float(uz) ) ## lMatrix = Numeric.array(glGetDoublev(GL_MODELVIEW_MATRIX)).astype('f') ## lRotation, lTranslation, lScale = self.Decompose4x4(lMatrix, cleanup=False) ## glPopMatrix() ## if numpy.any(lMatrix): ## self.rotation = lRotation ## self.translation = lTranslation ## self.lookAt = Numeric.reshape(Numeric.array(valLookAt), (3,)).astype('f') ## val = kw.get( 'lookAt') ## if not val is None: ## mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') ## self.lookAt = mat ## self.direction = self.lookAt - self.lookFrom ## val = kw.get( 'lookFrom') ## if not val is None: ## mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') ## self.lookFrom = mat ## self.direction = self.lookAt - self.lookFrom val = kw.get( 'projectionType') if val==self.PERSPECTIVE: if self.projectionType==self.ORTHOGRAPHIC: self.projectionType = val self.OrthogonalToPerspective() elif val==self.ORTHOGRAPHIC: if self.projectionType==self.PERSPECTIVE: self.projectionType = val self.PerspectiveToOrthogonal() val = kw.get( 'sideBySideRotAngle') if not val is None: assert type(val)==types.FloatType self.sideBySideRotAngle = val if self.viewer: self.viewer.Redraw() val = kw.get( 'sideBySideTranslation') if not val is None: assert type(val)==types.FloatType self.sideBySideTranslation = val if self.viewer: self.viewer.Redraw() val = kw.get( 'TV3DTranslation') if not val is None: assert type(val)==types.FloatType self.TV3DTranslation = val if self.viewer: self.viewer.Redraw() val = kw.get( 'TV3DRotAngle') if not val is None: assert type(val)==types.FloatType self.TV3DRotAngle = val if self.viewer: self.viewer.Redraw() val = kw.get( 'TV3DScaling') if not val is None: assert len(val)==3 assert type(val[0])==types.FloatType assert type(val[1])==types.FloatType assert type(val[2])==types.FloatType self.TV3DScaling = val if self.viewer: self.viewer.Redraw() val = kw.get( 'ssao') if not val is None: self.ssao = kw["ssao"] val = kw.get( 'SSAO_OPTIONS') if not val is None: self.SSAO_OPTIONS = kw['SSAO_OPTIONS'] val = kw.get( 'stereoMode') if val is not None: assert val in self.stereoModesList glDrawBuffer(GL_BACK) if self.viewer is None: warnings.warn("""Stereo buffers are not present or not enabled on this system. enableStereo must be set to True in: ~/.mgltools/(ver_number)/DejaVu/_dejavurc """ ) val = 'MONO' elif self.viewer.activeStereoSupport is False: if val == 'STEREO_BUFFERS': warnings.warn("""Stereo buffers are not present or not enabled on this system. enableStereo must be set to True in: ~/.mgltools/(ver_number)/DejaVu/_dejavurc """ ) val = 'MONO' self.stereoMode = val if self.viewer: self.viewer.Redraw() val = kw.get( 'suspendRedraw') if val is not None: assert val in [True, False] self.suspendRedraw = val val = kw.get( 'drawThumbnail') if val is not None: assert val in [True, False] self.drawThumbnailFlag = val # def deleteOpenglList(self): # #import traceback;traceback.print_stack() # #print "Camera.deleteOpenglList" # if self.dpyList is not None: # self.tk.call(self._w, 'makecurrent') # currentcontext = self.tk.call(self._w, 'contexttag') # if currentcontext != self.dpyList[1]: # warnings.warn("""deleteOpenglList failed because the current context is the wrong one""") # #print "currentcontext != self.dpyList[1]", currentcontext, self.dpyList[1] # else: # #print '-%d'%self.dpyList[0], currentcontext, "glDeleteLists Viewer" # GL.glDeleteLists(self.dpyList[0], 1) # self.dpyList = None def SwapBuffers(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.tk.call(self._w, 'swapbuffers') def Activate(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Make this Opengl widget the current destination for drawing.""" self.tk.call(self._w, 'makecurrent') def OrthogonalToPerspective(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Compute left, right, top, bottom from field of view""" d = self.near + (self.far - self.near)*0.5 self.fovy = (math.atan(self.top/d) * 360.0) / math.pi self.SetupProjectionMatrix() def PerspectiveToOrthogonal(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Compute left, right, top, bottom from field of view""" aspect = self.width / float(self.height) fov2 = (self.fovy*math.pi) / 360.0 # fov/2 in radian d = self.near + (self.far - self.near)*0.5 self.top = d*math.tan(fov2) self.bottom = -self.top self.right = aspect*self.top self.left = -self.right self.SetupProjectionMatrix() def SetupProjectionMatrix(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Setup the projection matrix""" if not self.initialized: return self.tk.call(self._w, 'makecurrent') glViewport(0, 0, self.width, self.height) glMatrixMode(GL_TEXTURE) glLoadIdentity() glMatrixMode(GL_PROJECTION); glLoadIdentity() ## if self.viewer.tileRender: ## print 'FUGU' ## if self.projectionType==self.PERSPECTIVE: ## self.viewer.tileRenderCtx.perspective(self.fovy, ## float(self.width)/float(self.height), ## self.near, self.far) ## else: ## self.viewer.tileRenderCtx.ortho(self.left, self.right, ## self.bottom, self.top, ## self.near, self.far) ## print 'near', self.viewer.tileRenderCtx.Near if self.projectionType==self.PERSPECTIVE: # protect from bug in mac intel when zomming on molecule 1BX4 if sys.platform == 'darwin': if self.fovy < .003: self.fovy = .003 gluPerspective(float(self.fovy), float(self.width)/float(self.height), float(self.near), float(self.far)) else: glOrtho(float(self.left), float(self.right), float(self.bottom), float(self.top), float(self.near), float(self.far)) glMatrixMode(GL_MODELVIEW) glLoadIdentity() ## from opengltk.OpenGL import GLU ## GLU.gluLookAt(0., 0., 30., 0.,0.,0., 0.,1.,0.) ## print 'Mod Mat:', glGetDoublev(GL_MODELVIEW_MATRIX) ## glLoadIdentity(); # The first 6 arguments are identical to the glFrustum() call. # # pixdx and pixdy are anti-alias jitter in pixels. # Set both equal to 0.0 for no anti-alias jitter. # eyedx and eyedy are depth-of field jitter in pixels. # Set both equal to 0.0 for no depth of field effects. # # focus is distance from eye to plane in focus. # focus must be greater than, but not equal to 0.0. # # Note that AccFrustum() calls glTranslatef(). You will # probably want to insure that your ModelView matrix has been # initialized to identity before calling accFrustum(). def AccFrustum(self, left, right, bottom, top, near, far, pixdx, pixdy, eyedx, eyedy, focus): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() viewport = Numeric.array(glGetDoublev (GL_VIEWPORT)) xwsize = right - left ywsize = top - bottom dx = -(pixdx*xwsize/viewport[2] + eyedx*near/focus) dy = -(pixdy*ywsize/viewport[3] + eyedy*near/focus) glMatrixMode(GL_PROJECTION) glLoadIdentity() glFrustum (float(left + dx), float(right + dx), float(bottom + dy), float(top + dy), float(near), float(far)) glMatrixMode(GL_MODELVIEW) glLoadIdentity() glTranslatef (float(-eyedx), float(-eyedy), 0.0) # The first 4 arguments are identical to the gluPerspective() call. # pixdx and pixdy are anti-alias jitter in pixels. # Set both equal to 0.0 for no anti-alias jitter. # eyedx and eyedy are depth-of field jitter in pixels. # Set both equal to 0.0 for no depth of field effects. # # focus is distance from eye to plane in focus. # focus must be greater than, but not equal to 0.0. # Note that AccPerspective() calls AccFrustum(). def AccPerspective(self, pixdx, pixdy, eyedx, eyedy, focus, left=None, right=None, bottom=None, top=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Build perspective matrix for jitter""" from math import pi, cos, sin fov2 = self.fovy*pi / 360.0; if top is None: top = self.near / (cos(fov2) / sin(fov2)) if bottom is None: bottom = -top if right is None: right = top * float(self.width)/float(self.height) if left is None: left = -right; self.AccFrustum (left, right, bottom, top, self.near, self.far, pixdx, pixdy, eyedx, eyedy, focus) def InitGL(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Initialize some GL features""" self.tk.call(self._w, 'makecurrent') glEnable(GL_CULL_FACE) glEnable(GL_NORMALIZE) # required if glScale is used, # else the lighting doesn't work anymore glDepthFunc(GL_LESS) glEnable(GL_DEPTH_TEST) # blend function used for line anti-aliasing glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA) self.initialized = 1 def Map(self, *dummy): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Cause the opengl widget to redraw itself.""" self.Expose() ## def Configure(self, *dummy): ## """Cause the opengl widget to redraw itself.""" ## self.tk.call(self._w, 'makecurrent') ## self.width = self.winfo_width() ## self.height = self.winfo_height() ## self.rootx = self.winfo_rootx() ## self.rooty = self.winfo_rooty() ## # FIXME .. this is not symetrical ... should we just recompute left, right, ## # top and botom here ??? ## if self.projectionType==self.ORTHOGRAPHIC: ## self.PerspectiveToOrthogonal() ## else: ## self.SetupProjectionMatrix() ## self.Expose() def Expose(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set the camera's exposeEvent so that at the next redraw the camera width and height are updated """ if not self.viewer.isInitialized: self.after(100, self.Expose) else: # if viewer is in autoRedraw mode the next redraw will handle it if not self.exposeEvent and self.viewer.autoRedraw: self.viewer.Redraw() self.exposeEvent = True for o in self.viewer.rootObject.AllObjects(): if o.needsRedoDpyListOnResize or o.scissor: self.viewer.objectsNeedingRedo[o] = None ## moved the width and height into viewer.ReallyRedraw ## def ReallyExpose(self, *dummy): ## """Redraw the widget. ## Make it active, update tk events, call redraw procedure and ## swap the buffers. Note: swapbuffers is clever enough to ## only swap double buffered visuals.""" ## self.tk.call(self._w, 'makecurrent') ## self.width = self.winfo_width() ## self.height = self.winfo_height() ## #self.SetupProjectionMatrix() ## #self.InitGL() ## self.Redraw() def drawOneObjectThumbnail(self, obj): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.ActivateClipPlanes( obj.clipP, obj.clipSide ) if obj.scissor: glEnable(GL_SCISSOR_TEST) glScissor(obj.scissorX, obj.scissorY, obj.scissorW, obj.scissorH) inst = 0 v = obj.vertexSet.vertices.array v = Numeric.reshape(v, (-1,3)).astype('f') for m in obj.instanceMatricesFortran: inst = inst + 1 glPushMatrix() glMultMatrixf(m) if isinstance(obj, Transformable): v = obj.vertexSet.vertices.array if len(v.shape) >2 or v.dtype.char!='f': v = Numeric.reshape(v, (-1,3)).astype('f') if len(v) >0: #t1 = time() namedPoints(len(v), v) #glVertexPointer(2, GL_FLOAT, 0, v) #glEnableClientState(GL_VERTEX_ARRAY) #glDrawArrays(GL_POINTS, 0, len(v) ) #glDisableClientState(GL_VERTEX_ARRAY) else: #Insert2d obj.pickDraw() glPopMatrix() for c in obj.clipP: # disable object's clip planes c._Disable() if obj.scissor: glDisable(GL_SCISSOR_TEST) def DrawObjThumbnail(self, obj): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """draws an object for picking purposes. If type is 'vertices' a display list for vertices identification is used. If type is parts a display list identifying geometric primitives such as triangles or lines is used """ if isinstance(obj, Transformable): glPushMatrix() obj.MakeMat() self.ActivateClipPlanes( obj.clipPI, obj.clipSide ) inst = 0 for m in obj.instanceMatricesFortran: glPushMatrix() glMultMatrixf(m) for child in obj.children: if child.visible: self.DrawObjThumbnail(child) glPopMatrix() inst = inst + 1 if obj.visible: self.drawOneObjectThumbnail(obj) for c in obj.clipPI: # disable object's clip planes that are c._Disable() # inherited by children glPopMatrix() # Restore the matrix def RedrawThumbnail(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() glClear(GL_DEPTH_BUFFER_BIT) glPushMatrix() glPointSize(1.0) self.BuildTransformation() # camera transformation obj = self.viewer.rootObject obj.MakeMat() if len(obj.clipPI): self.ActivateClipPlanes( obj.clipPI, obj.clipSide ) inst = 0 for m in obj.instanceMatricesFortran: glPushMatrix() glMultMatrixf(m) for child in obj.children: if child.visible: self.DrawObjThumbnail(child) glPopMatrix() inst = inst + 1 for c in obj.clipPI: c._Disable() glPopMatrix() def drawThumbnail(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.tk.call(self._w, 'makecurrent') glViewport(0, 0, self.width/10, self.height/10) glMatrixMode (GL_PROJECTION) glPushMatrix() glLoadIdentity () # create projection matrix and modeling # self.SetupProjectionMatrix() if self.projectionType==self.PERSPECTIVE: gluPerspective(float(self.fovy), float(self.width)/float(self.height), float(self.near),float(self.far)) else: glOrtho(float(self.left),float(self.right), float(self.bottom), float(self.top), float(self.near), float(self.far)) glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.RedrawThumbnail() glFlush () glMatrixMode (GL_PROJECTION) glPopMatrix () glMatrixMode(GL_MODELVIEW) def DoPick(self, x, y, x1=None, y1=None, type=None, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Makes a redraw in GL_SELECT mode to pick objects """ if self.stereoMode != 'MONO': return if type is None: type = self.viewer.pickLevel if x1 is None: x1 = x if y1 is None: y1 = y #print 'pick at', x, y, x1, y1 self.tk.call(self._w, 'makecurrent') vp = [0,0,self.width, self.height] selectBuf = glSelectBuffer( 1000000 ) # 500000 was insuficient on bigger molecule as 2plv.pdb with MSMS y1 = vp[3] - y1 y = vp[3] - y dx = x - x1 dy = y - y1 #x = x pickWinSize = 10 if math.fabs(dx) < pickWinSize: dx=pickWinSize else: x = x1 + (dx/2) if math.fabs(dy) < pickWinSize: dy=pickWinSize else: y = y1 + (dy/2) if dx==pickWinSize and dy==pickWinSize: mode = 'pick' else: mode = 'drag select' abdx = int(math.fabs(dx)) abdy = int(math.fabs(dy)) #print 'pick region ', x-math.fabs(dx), y-math.fabs(dy), x+math.fabs(dx), y+math.fabs(dy), mode # debug glRenderMode (GL_SELECT) self.renderMode = GL_SELECT glInitNames() glPushName(0) glMatrixMode (GL_PROJECTION) glPushMatrix() glLoadIdentity () # create abs(dx)*abs(dy) pixel picking region near cursor location gluPickMatrix( x, y, abdx, abdy, vp) # we save it so it can be reapplied if the projection matrix is recreated self.pickMatrix = glGetFloatv(GL_PROJECTION_MATRIX) # create projection matrix and modeling # self.SetupProjectionMatrix() if self.projectionType==self.PERSPECTIVE: gluPerspective(self.fovy,float(self.width)/float(self.height), self.near, self.far) else: glOrtho(float(self.left),float(self.right), float(self.bottom),float(self.top), float(self.near), float(self.far)) glMatrixMode(GL_MODELVIEW) glLoadIdentity() self.RedrawPick(type); glFlush () # debug ###self.tk.call(self._w, 'swapbuffers') ###return PickObject('pick') self.renderMode = GL_RENDER; # get the number of hits selectHits = glRenderMode (GL_RENDER) #print "hits", selectHits #removed because it generates bug in displaylist #if selectHits == 0: # # if we pick the background, root becomes selected # self.viewer.SetCurrentObject(self.viewer.rootObject) # restore projection matrix glMatrixMode (GL_PROJECTION) glPopMatrix () # unproject points x and y glMatrixMode(GL_MODELVIEW) glLoadIdentity() # restore matrix for unproject self.BuildTransformation() self.viewer.rootObject.MakeMat() self.unProj_model = glGetDoublev(GL_MODELVIEW_MATRIX) self.unProj_proj = glGetDoublev(GL_PROJECTION_MATRIX) self.unProj_view = glGetIntegerv(GL_VIEWPORT) p1 = gluUnProject( (x, y, 0.), self.unProj_model, self.unProj_proj, self.unProj_view) p2 = gluUnProject( (x, y, 1.), self.unProj_model, self.unProj_proj, self.unProj_view) glLoadIdentity() if selectHits: if mode == 'pick': pick = self.handlePick(selectHits, selectBuf, type) else: pick = self.handleDragSelect(selectHits, selectBuf, type) else: pick = PickObject('pick', self) ## if selectHits and self.viewer.showPickedVertex: ## self.DrawPickingSphere(pick) pick.p1 = p1 pick.p2 = p2 pick.box = (x, y, x1, y1) pick.event = event self.viewer.lastPick = pick #DEBUG used to debug picking # from IndexedPolylines import IndexedPolylines # l = IndexedPolylines('line', vertices = (self._p1,self._p2), faces=((0,1),) ) # self.viewer.AddObject(l) # return o, parts, self.viewer.lastPickedVertex, self._p1, self._p2 return pick # ## DEPRECATED, is not using instance for computing coordinates (MS 12/04) # def DrawPickingSphere(self, pick): # """display a transient sphere at picked vertex""" # from warnings import warn # warnings.warn('DrawPickingSphere is deprecated', # DeprecationWarning, stacklevel=2) # # obj = pick.hits.keys()[0] # varray = obj.vertexSet.vertices.array # coords = Numeric.take( varray, pick.hits[obj] ) # p = self.viewer.pickVerticesSpheres # mat = obj.GetMatrix( obj.LastParentBeforeRoot() ) # mat = Numeric.transpose(mat) # p.Matrix = Numeric.reshape(mat, (16, )) # p.SetMatrix(mat) # self.viewer.pickVerticesSpheres.Set(vertices=coords, # transient=self.viewer.pickReminiscence, # redo=redo) # self.Redraw() def xyzFromPixel( self, winx, winy): """compute x, and y values in scene from x and y corrdinates in event find z from Zbuffer. pt3d, background = xyzFromPixel( self, winx, winy) background is True if pick occured on background""" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # unproject pixel self.tk.call(self._w, 'makecurrent') glPushMatrix() self.BuildTransformation() # camera transformation nar = Numeric.zeros(1, 'f') glFinish() from opengltk.extent import _gllib as gllib gllib.glReadPixels( winx, winy, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, nar) winz = float(nar[0]) background = winz == 1.0 #print 'xyzFromPixel: picks',winz, background #print "winx, winy, winz", winx, winy, winz l3dPoint = gluUnProject( (winx, winy, winz), glGetDoublev(GL_MODELVIEW_MATRIX), glGetDoublev(GL_PROJECTION_MATRIX), glGetIntegerv(GL_VIEWPORT) ) #print "l3dPoint", l3dPoint glPopMatrix() return l3dPoint, background def handleDragSelect(self, selectHits, selectBuf, type): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() pick = PickObject('drag select', self, type) p = 0 for i in range(selectHits): nb_names = selectBuf[p] z1 = float(selectBuf[p+1]) #/ 0x7fffffff end = int(p+3+nb_names) instance = list(selectBuf[p+3:end-2]) obj = self.objPick[int(selectBuf[end-2])] vertex = selectBuf[end-1] #print 'vertex', vertex, obj.name, instance pick.add(object=obj, vertex=vertex, instance=instance) p = end return pick def handlePick(self, selectHits, selectBuf, type): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """We are looking for the vertex closest to the viewer""" # now handle selection mini = 9999999999.9 p = 0 vertex = None obj = None # loop over hits. selectBuf contains for each hit: # - number of names for that hit (num) # - z1 # - z2 # - instNumRoot, instNumRootParent_1, instNumRootParent_2, ... , # geomIndex, vertexNum # For each parent we have an instance number # the geomIndex is the index of the geometry in self.objPick # vertexNum is the index of the vertex in the geometry's vertexSet # pick = PickObject('pick', self, type) for i in range(selectHits): nb_names = selectBuf[p] z1 = float(selectBuf[p+1]) #/ 0x7fffffff # compute the end of the pick info for this hit end = int(p+3+nb_names) #print 'vertex', selectBuf[end-1], self.objPick[selectBuf[end-2]], list(selectBuf[p+3:end-2]), z1 if z1 < mini: #end = p+3+nb_names mini = z1 instance = list(selectBuf[p+3:end-2]) obj = self.objPick[int(selectBuf[end-2])] vertex = selectBuf[end-1] # advance p to begin of next pick hit data p = end pick.add( object=obj, vertex=vertex, instance=instance ) return pick def drawOneObjectPick(self, obj, type): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # skip object if it is in list of objects not shown in this Camera if obj.hiddenInCamera.has_key(self): return lIsInstanceTransformable = isinstance(obj, Transformable) if lIsInstanceTransformable: self.ActivateClipPlanes( obj.clipP, obj.clipSide ) if obj.scissor: glEnable(GL_SCISSOR_TEST) glScissor(obj.scissorX, obj.scissorY, obj.scissorW, obj.scissorH) obj.pickNum = self.pickNum self.objPick.append(obj) inst = 0 if lIsInstanceTransformable and type=='vertices': #print 'using vertices', obj.name v = obj.vertexSet.vertices.array v = Numeric.reshape(v, (-1,3)).astype('f') for m in obj.instanceMatricesFortran: glPushName(inst) # instance number inst = inst + 1 glPushName(self.pickNum) # index into self.objPick glPushMatrix() glMultMatrixf(m) if lIsInstanceTransformable: if type=='vertices': #print 'using vertices', obj.name v = obj.vertexSet.vertices.array if len(v.shape) >2 or v.dtype.char!='f': v = Numeric.reshape(v, (-1,3)).astype('f') if len(v) >0: #t1 = time() namedPoints(len(v), v) #print 'draw points:', time()-t1 ## i = 0 ## for p in v: ## glPushName(i) ## glBegin(GL_POINTS) ## glVertex3f(p[0], p[1], p[2]) ## glEnd() ## glPopName() ## i = i + 1 # can't be used since we cannot push and pop names ## glVertexPointer(2, GL_FLOAT, 0, v) ## glEnableClientState(GL_VERTEX_ARRAY) ## glDrawArrays(GL_POINTS, 0, len(v) ) ## glDisableClientState(GL_VERTEX_ARRAY) elif type=='parts': if obj.pickDpyList: #print "pick displayFunction" currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if currentcontext != obj.pickDpyList[1]: warnings.warn("""DisplayFunction failed because the current context is the wrong one""") #print "currentcontext != obj.pickDpyList[1]", currentcontext, obj.pickDpyList[1] else: print '#%d'%obj.pickDpyList[0], currentcontext, "glCallList Camera" glCallList(obj.pickDpyList[0]) else: #print "displayFunction" obj.DisplayFunction() else: print 'Error: bad type for PickRedraw: ',type else: #Insert2d obj.pickDraw() glPopMatrix() glPopName() # instance number glPopName() # index into self.objPick self.pickNum = self.pickNum + 1 if lIsInstanceTransformable: for c in obj.clipP: # disable object's clip planes c._Disable() if obj.scissor: glDisable(GL_SCISSOR_TEST) def DrawObjPick(self, obj, type): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """draws an object for picking purposes. If type is 'vertices' a display list for vertices identification is used. If type is parts a display list identifying geometric primitives such as triangles or lines is used""" lIsInstanceTransformable = isinstance(obj, Transformable) if lIsInstanceTransformable: glPushMatrix() obj.MakeMat() self.ActivateClipPlanes( obj.clipPI, obj.clipSide ) inst = 0 for m in obj.instanceMatricesFortran: glPushName(inst) # instance number glPushMatrix() glMultMatrixf(m) for child in obj.children: if child.visible: self.DrawObjPick(child, type) glPopMatrix() glPopName() # instance number inst = inst + 1 if obj.pickable: self.drawOneObjectPick(obj, type) if lIsInstanceTransformable: for c in obj.clipPI: # disable object's clip planes that are c._Disable() # inherited by children glPopMatrix() # Restore the matrix def RedrawPick(self, type): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.pickNum = 0 self.objPick = [ ] glClear(GL_DEPTH_BUFFER_BIT) glPushMatrix() glPointSize(1.0) self.BuildTransformation() # camera transformation obj = self.viewer.rootObject obj.MakeMat() if len(obj.clipPI): self.ActivateClipPlanes( obj.clipPI, obj.clipSide ) inst = 0 for m in obj.instanceMatricesFortran: glLoadName(inst) glPushMatrix() glMultMatrixf(m) for child in obj.children: if child.visible: self.DrawObjPick(child, type) glPopMatrix() inst = inst + 1 for c in obj.clipPI: c._Disable() glPopMatrix() def drawRect(self, P1, P2, P3, P4, fill=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if fill: prim=GL_POLYGON else: prim=GL_LINE_STRIP glBegin(prim) glVertex3f( float(P1[0]), float(P1[1]), float(P1[2]) ) glVertex3f( float(P2[0]), float(P2[1]), float(P2[2]) ) glVertex3f( float(P3[0]), float(P3[1]), float(P3[2]) ) glVertex3f( float(P4[0]), float(P4[1]), float(P4[2] )) glVertex3f( float(P1[0]), float(P1[1]), float(P1[2] )) glEnd() def Insert2dPickingCallBack(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # this shoudn't be necessary but somewhere/sometimes the # current object is set without a call to SetCurrentObject # So self.viewer.currentCamera.bindAllActions('Insert2d') is no set if isinstance(self.viewer.currentObject, Insert2d) is False: assert isinstance(self.viewer.currentObject, Transformable), self.viewer.currentObject self.viewer.SetCurrentObject(self.viewer.currentObject) return self.viewer.currentObject.respondToMouseMove(event) def SetInsert2dPicking(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() num = str(self.findButton('picking', 'Insert2d')[0]) ehm = self.eventManager for mod in self.mouseButtonModifiers: if mod == 'None': mod = '' else: mod = mod + '-' ev = '<' + mod + 'B' + num + '-Motion>' #print "ev", ev ehm.AddCallback(ev, self.Insert2dPickingCallBack ) pick = self.DoPick(event.x, event.y, event=event) #if pick and len(pick.hits): self.viewer.processPicking(pick) def initSelectionRectangle(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if isinstance(self.viewer.currentObject, Insert2d): return if self.stereoMode != 'MONO': return self.selectDragRect = 1 self.afid=None self.fill=0 self.tk.call(self._w, 'makecurrent') glPushMatrix() self.BuildTransformation() # camera transformation glDrawBuffer(GL_FRONT) # glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) # glDisable(GL_CULL_FACE) glLineWidth( 1.0 ) glDisable( GL_LIGHTING ) glColor3f( float(self.selectionColor[0]), float(self.selectionColor[1]), float(self.selectionColor[2]) ) glDisable(GL_DEPTH_TEST) glEnable(GL_COLOR_LOGIC_OP) glLogicOp(GL_XOR) x2 = self._x1 = event.x y2 = self._y1 = self.height - event.y self.unProj_model = glGetDoublev(GL_MODELVIEW_MATRIX) self.unProj_proj = glGetDoublev(GL_PROJECTION_MATRIX) self.unProj_view = glGetIntegerv(GL_VIEWPORT) from opengltk.extent import _glulib as glulib self._P1 = gluUnProject( (self._x1, self._y1, 0.5), self.unProj_model, self.unProj_proj, self.unProj_view ) self._P2 = gluUnProject( (self._x1, y2, 0.5), self.unProj_model, self.unProj_proj, self.unProj_view ) self._P3 = gluUnProject( (x2, y2, 0.5), self.unProj_model, self.unProj_proj, self.unProj_view ) self._P4 = gluUnProject( (x2, self._y1, 0.5), self.unProj_model, self.unProj_proj, self.unProj_view ) # draw first rectangle #self.history = [ ('draw', self._P3) ] self.drawRect( self._P1, self._P2, self._P3, self._P4 ) glPopMatrix() # set "" to call draw selection rectangle # add un-drawing of last selection rectangle and call functions ehm = self.eventManager num = str(event.num)#str(self.findButton('picking', 'Object')[0]) for mod in self.mouseButtonModifiers: if mod=='None': mod='' else: mod=mod+'-' ev = '<'+mod+'B'+num+'-Motion>' ehm.AddCallback(ev, self.drawSelectionRectangle ) ehm.AddCallback("<"+mod+"ButtonRelease-"+num+">", self.endSelectionRectangle ) def drawSelectionRectangle(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not self.selectDragRect: return self.tk.call(self._w, 'makecurrent') glPushMatrix() self.BuildTransformation() # camera transformation #print 'AAAAAAAAAAA2 drawSelectionRectangle' # draw over previous rectangle #self.history.append( ('hide', self._P3) ) glDisable(GL_DEPTH_TEST) if self.fill: self.drawRect( self._P1, self._P2, self._P3, self._P4, 1 ) self.fill = 0 else: self.drawRect( self._P1, self._P2, self._P3, self._P4, 0 ) # draw new rectangle x2 = event.x y2 = self.height - event.y self.unProj_model = glGetDoublev(GL_MODELVIEW_MATRIX) self._P2 = gluUnProject( (self._x1, y2, 0.5), self.unProj_model, self.unProj_proj, self.unProj_view) self._P3 = gluUnProject( (x2, y2, 0.5), self.unProj_model, self.unProj_proj, self.unProj_view) self._P4 = gluUnProject( (x2, self._y1, 0.5), self.unProj_model, self.unProj_proj, self.unProj_view) #self.history.append( ('draw', self._P3) ) self.drawRect( self._P1, self._P2, self._P3, self._P4, self.fill ) glPopMatrix() glFlush() if self.fillSelectionBox: if self.afid: self.after_cancel(self.afid) self.afid = self.after(self.fillDelay, self.DrawFilledSelectionBox) def DrawFilledSelectionBox(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.fill = 1 self.tk.call(self._w, 'makecurrent') glPushMatrix() self.BuildTransformation() # camera transformation # draw over previous rectangle self.drawRect( self._P1, self._P2, self._P3, self._P4, 0 ) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL) glDisable(GL_CULL_FACE) glColor3f( float(self.selectionColor[0]), float(self.selectionColor[1]), float(self.selectionColor[2] )) self.drawRect( self._P1, self._P2, self._P3, self._P4, 1 ) glFlush() glPopMatrix() def endSelectionRectangle(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Camera.endSelectionRectangle" if not self.selectDragRect: return if self.afid: self.after_cancel(self.afid) # remove "" to call draw selection rectangle # remove un-drawing of last selection rectangle and call functions ehm = self.eventManager num = str(event.num)#str(self.findButton('picking', 'Object')[0]) for mod in self.mouseButtonModifiers: if mod=='None': mod='' else: mod=mod+'-' ev = '<'+mod+'B'+num+'-Motion>' ehm.RemoveCallback(ev, self.drawSelectionRectangle ) ehm.RemoveCallback("<"+mod+"ButtonRelease-"+num+">", self.endSelectionRectangle ) self.selectDragRect = 0 self.tk.call(self._w, 'makecurrent') glPushMatrix() self.BuildTransformation() # camera transformation # this line is required for last rectangle to disappear ! # not sure why # oct 2001: apparently not necessary #glEnable(GL_COLOR_LOGIC_OP) #self.history.append( ('hide', self._P3) ) self.drawRect( self._P1, self._P2, self._P3, self._P4 ) #self.drawRect( self._P1, self._P2, self._P3, self._P4 ) glPopMatrix() glEnable(GL_DEPTH_TEST) glDisable(GL_COLOR_LOGIC_OP) #glEnable(GL_LIGHTING) if self.viewer is not None: self.viewer.enableOpenglLighting() glDrawBuffer(GL_BACK) pick = self.DoPick(event.x, event.y, self._x1, self.height-self._y1, event=event) del self._x1 del self._y1 del self._P1 del self._P2 del self._P3 del self._P4 if self.viewer and len(pick.hits): self.viewer.processPicking(pick) #print "len(pick.hits)", len(pick.hits) def SelectCamera(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """First pick in a non current camera selects it""" curCam = self.viewer.currentCamera if curCam == self: return 0 curCam.frame.config( background = self.defFrameBack ) self.frame.config( background = "#900000" ) if self.viewer: self.viewer.currentCamera = self self.viewer.BindTrackballToObject(self.viewer.currentObject) self.SetupProjectionMatrix() return 1 def DoubleSelectPick_cb(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Handle a double pick event in this camera""" self.DoPick(event.x, event.y, event=event) self.viewer.BindTrackballToObject(self.viewer.rootObject) ## DEPRECATED, is not using instance for computing coordinates def CenterPick_cb(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Handle a pick event. Center the cur. object on the picked vertex""" from warnings import warn warnings.warn('CenterPick_cbg is deprecated', DeprecationWarning, stacklevel=2) pick = self.DoPick(event.x, event.y, event=event) if len(pick.hits)==0: return g = Numeric.zeros( (3), 'f' ) object = self.viewer.currentObject inv = object.GetMatrixInverse() for obj, vertInd in pick.hits.items(): if len(vertInd)==0: print 'WARNING: object',obj.name,' is not vertex pickable' else: m = Numeric.dot( inv, obj.GetMatrix() ) vert = obj.vertexSet.vertices * m vertsel = Numeric.take( vert, vertInd ) g = g + Numeric.sum(vertsel)/len(vertsel) object.SetPivot( g ) ## varray = obj.vertexSet.vertices.array ## vert = Numeric.take( varray, vertInd ) ## vert = Numeric.concatenate( vert, Numeric.ones( (1,len(vert))), 1) ## vert = Numeric.dot(m, vert) ## obj.SetPivot( (Numeric.sum(vert)/len(vert))[:3] ) ## obj.SetPivot( self.viewer.lastPickedVertex[1] ) def TransfCamera_cb(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.viewer.BindTrackballToCamera(self.viewer.currentCamera) def ActivateClipPlanes(self, cplist, cpside): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """activate a list of clipping planes""" if len(cplist)==0: return glPushMatrix() glLoadIdentity() glMultMatrixf(self.rootObjectTransformation) glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_LINE_BIT) glDisable (GL_LIGHTING) for c in cplist: # display them if c.visible: # if we push a name here we won't know how many values # to skip in handlePick after z1 and z2 #if self.renderMode == GL_SELECT: # c.pickNum = self.pickNum # self.objPick.append(c) # self.pickNum = self.pickNum + 1 # glLoadName(c.pickNum) c.DisplayFunction() glPopAttrib() for c in cplist: # enable them c._Enable(cpside[c.num]) glPopMatrix(); def DrawAllDirectionalLights(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Draw all directional lights""" glDisable (GL_LIGHTING) for l in self.viewer.lights: if l.positional is True or l.visible in (False,0): continue if self.renderMode == GL_SELECT: l.pickNum = self.pickNum self.objPick.append(l) self.pickNum = self.pickNum + 1 glLoadName(l.pickNum) l.DrawDirectionalLight(self) def drawWithCap(self, obj): MY_CLIP_PLANE = obj.cap # compute clip plane number cpn = MY_CLIP_PLANE - GL.GL_CLIP_PLANE0 #GL.glPushAttrib(GL.GL_ENABLE_BIT | GL.GL_STENCIL_BUFFER_BIT | # GL.GL_POLYGON_BIT | GL_CURRENT_BIT) ## ## SINGLE PASS ## ## GL.glDepthMask(0) ## GL.glColorMask(0,0,0,0) ## GL.glDisable(GL_CULL_FACE) ## GL.glEnable(GL.GL_STENCIL_TEST) ## GL.glEnable(GL.GL_STENCIL_TEST_TWO_SIDE_EXT) ## GL.glActiveStencilFaceEXT(GL.GL_BACK) ## GL.glStencilOp(GL.GL_KEEP, # stencil test fail ## GL.GL_KEEP, # depth test fail ## GL.GL_DECR_WRAP_EXT) # depth test pass ## GL.glStencilMask(~0) ## GL.glStencilFunc(GL_ALWAYS, 0, ~0) ## GL.glActiveStencilFaceEXT(GL.GL_FRONT) ## GL.glStencilOp(GL.GL.GL_KEEP, # stencil test fail ## GL.GL.GL_KEEP, # depth test fail ## GL.GL.GL_INCR_WRAP_EXT); # depth test pass ## GL.glStencilMask(~0) ## GL.glStencilFunc(GL.GL_ALWAYS, 0, ~0) ## obj.Draw() ## 2 passes version GL.glEnable(GL.GL_CULL_FACE) GL.glEnable(GL.GL_STENCIL_TEST) glStencilMask(1) GL.glEnable(GL.GL_DEPTH_TEST) #GL.glDisable(GL.GL_DEPTH_TEST) GL.glClear(GL.GL_STENCIL_BUFFER_BIT) GL.glColorMask(GL.GL_FALSE, GL.GL_FALSE, GL.GL_FALSE, GL.GL_FALSE) # first pass: increment stencil buffer value on back faces GL.glStencilFunc(GL.GL_ALWAYS, 0, 0) GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_INCR) GL.glPolygonMode(GL.GL_BACK, GL.GL_FILL) GL.glCullFace(GL.GL_FRONT) # render back faces only obj.Draw() # second pass: decrement stencil buffer value on front faces GL.glStencilOp(GL.GL_KEEP, GL.GL_KEEP, GL.GL_DECR) GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL) GL.glCullFace(GL.GL_BACK) # render front faces only obj.Draw() # FIXME this can create problems whent there are multiple geoms GL.glClear(GL_DEPTH_BUFFER_BIT) # drawing clip planes masked by stencil buffer content #_gllib.glBindTexture(GL_TEXTURE_2D, 0) GL.glEnable(GL.GL_DEPTH_TEST) GL.glColorMask(GL.GL_TRUE, GL.GL_TRUE, GL.GL_TRUE, GL.GL_TRUE) GL.glDisable(MY_CLIP_PLANE) GL.glDisable(GL.GL_CULL_FACE) #GL.glStencilFunc(GL.GL_ALWAYS, 0, 1) #GL.glStencilFunc(GL.GL_LESS, 0, 1) #GL.glStencilFunc(GL.GL_NOTEQUAL, 0, 1) GL.glStencilFunc(GL.GL_NOTEQUAL, 0, 1) GL.glMaterialfv( GL.GL_FRONT, GL.GL_DIFFUSE, obj.capFrontColor) GL.glMaterialfv( GL.GL_BACK, GL.GL_DIFFUSE, obj.capBackColor) GL.glBegin(GL.GL_QUADS) #rendering the plane quad. Note, it should be #big enough to cover all clip edge area. GL.glNormal3fv( (1, 0, 0)) if obj.clipSide[cpn]==-1: pts = [(0, 9999, -9999), (0, 9999, 9999), (0, -9999, 9999), (0, -9999, -9999) ] else: pts = [ (0, -9999, -9999), (0, -9999, 9999), (0, 9999, 9999), (0, 9999, -9999) ] cp = self.viewer.clipP[cpn] xpts = self.transformPoints(cp.translation, cp.rotation, pts) #GL.glDrawBuffer(GL.GL_FRONT) for p in xpts: GL.glVertex3fv( p ) GL.glEnd() #****** Rendering object ********* #GL.glPopAttrib() GL.glDisable(GL.GL_STENCIL_TEST) GL.glClear(GL_STENCIL_BUFFER_BIT) GL.glEnable(MY_CLIP_PLANE) # enabling clip plane again obj.SetupGL() obj.Draw() GL.glStencilFunc(GL.GL_ALWAYS, 0, 0) glStencilMask(0) def transformPoints(self, trans, rot, points): tx,ty,tz = trans pos = [] for xs,ys,zs in points: x = rot[0]*xs + rot[4]*ys + rot[8]*zs + tx y = rot[1]*xs + rot[5]*ys + rot[9]*zs + ty z = rot[2]*xs + rot[6]*ys + rot[10]*zs + tz pos.append( [x,y,z] ) return pos def DrawOneObject(self, obj): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set up clipping planes, activate scissors and call display function for all instances of obj """ #print "Camera.DrawOneObject", obj lIsInstancetransformable = isinstance(obj, Transformable) if lIsInstancetransformable: self.ActivateClipPlanes( obj.clipP, obj.clipSide ) if obj.scissor: glDisable(GL_LIGHTING) lViewport = glGetIntegerv(GL_VIEWPORT) GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() GL.glLoadIdentity() GL.glOrtho(float(lViewport[0]), float(lViewport[2]), float(lViewport[1]), float(lViewport[3]), -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() glEnable(GL_COLOR_LOGIC_OP) glLogicOp(GL_XOR) glBegin(GL_LINE_STRIP) glVertex2f( float(obj.scissorX), float(obj.scissorY )) glVertex2f( float(obj.scissorX+obj.scissorW), float(obj.scissorY )) glVertex2f( float(obj.scissorX+obj.scissorW), float(obj.scissorY+obj.scissorH)) glVertex2f( float(obj.scissorX), float(obj.scissorY+obj.scissorH )) glVertex2f( float(obj.scissorX), float(obj.scissorY )) glEnd() glDisable(GL_COLOR_LOGIC_OP) GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPopMatrix() glEnable(GL_SCISSOR_TEST) glScissor(obj.scissorX, obj.scissorY, obj.scissorW, obj.scissorH) #glEnable(GL_LIGHTING) if self.viewer is not None: self.viewer.enableOpenglLighting() if obj.drawBB: obj.DrawBoundingBox() # hack to fix this inheritence problem without slowing down # the "many object case (see Expensive inheritence pb above) # MS oct 11 2001. removed this code since obj.shadModel is set to # the proper value when it is inherited (see RenderMode()) and # shading is called by SetupGL for each object #if not obj.inheritShading and \ # obj.shading != GL_NONE: # glShadeModel(obj.shading) if (lIsInstancetransformable and obj.drawBB != viewerConst.ONLY) \ or isinstance(obj, Insert2d): if lIsInstancetransformable and obj.texture: glActiveTexture(GL_TEXTURE0) _gllib.glBindTexture(GL_TEXTURE_2D, 0) obj.texture.Setup() if lIsInstancetransformable and obj.invertNormals is True \ and isinstance(obj, Ellipsoids) is False \ and isinstance(obj, Cylinders) is False \ and (isinstance(obj, Spheres) is True and DejaVu.enableVertexArray is True): lCwIsOn = True GL.glFrontFace(GL.GL_CW) #print "GL.glGetIntegerv(GL.GL_FRONT_FACE)",GL.glGetIntegerv(GL.GL_FRONT_FACE) else: lCwIsOn = False mi = 0 for m in obj.instanceMatricesFortran: if lIsInstancetransformable and not obj.inheritMaterial: obj.InitMaterial(mi) obj.InitColor(mi) mi = mi + 1 glPushMatrix() glMultMatrixf(m) if obj.immediateRendering or \ (self.viewer.tileRender and obj.needsRedoDpyListOnResize): if hasattr(obj, "cap") and obj.cap: self.drawWithCap(obj) else: obj.Draw() #obj.Draw() elif self.viewer.singleDpyList: obj.Draw() else: obj.DisplayFunction() glPopMatrix() if lCwIsOn is True: GL.glFrontFace(GL.GL_CCW) #print obj.name, self.glError() if lIsInstancetransformable and obj.texture: glActiveTexture(GL_TEXTURE0); _gllib.glBindTexture(GL_TEXTURE_2D, 0) glDisable(obj.texture.dim) if lIsInstancetransformable: for c in obj.clipP: # disable object's clip planes c._Disable() if obj.scissor: glDisable(GL_SCISSOR_TEST) def Draw(self, obj, pushAttrib=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Draw obj and subtree below it """ #print "Camera.Draw", obj assert obj.viewer is not None # skip object if it is in list of objects not shown in this Camera if obj.hiddenInCamera.has_key(self): return # if object is not visible, all subtree is hidden --> we can return if obj.getVisible() in [False, 0]: #not obj.visible: return if self.drawMode & 5: # immediateRendring draw mode if obj.immediateRendering: pass elif (self.viewer.tileRender and obj.needsRedoDpyListOnResize): pass else: return glPushMatrix() # Protect our matrix lIsInstanceTransformable = isinstance(obj, Transformable) if lIsInstanceTransformable: if not obj.inheritXform: glPushMatrix() glLoadIdentity() glMultMatrixf(self.beforeRootTransformation) obj.MakeMat() # VERY expensive and I am not sure what I need it for if pushAttrib: glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT) glDisable(GL_LIGHTING) # required for the transparent box of AutoGrid not to affect the molecule's # color binding. The box is FLAT shaded and this shade models gets propagated # to the molecule preventing color interpolation over bonds. # This shows that thi models of inheritence has serious limitations :( # gl.glPushAttrib(GL_LIGHTING_BIT) if lIsInstanceTransformable: obj.SetupGL() # setup GL properties the can be inherited # enable and display object's clipping planes that also # clip its children self.ActivateClipPlanes( obj.clipPI, obj.clipSide ) if obj.scissor: glEnable(GL_SCISSOR_TEST) glScissor(obj.scissorX, obj.scissorY, obj.scissorW, obj.scissorH) if self.drawMode == 2: # recusive call for children # for o in obj.children: self.Draw(o) mi = 0 for m in obj.instanceMatricesFortran: if lIsInstanceTransformable and not obj.inheritMaterial: obj.InitMaterial(mi) obj.InitColor(mi) mi = mi + 1 glPushMatrix() glMultMatrixf(m) map ( self.Draw, obj.children) glPopMatrix() # Should be done in a function to setup GL properties that cannot # be inherited # should actually only be done once since all transparent objects # have to be drawn after all opaque objects for this to work draw = 1 transp = obj.transparent #obj.isTransparent() if obj.immediateRendering or \ (self.viewer.tileRender and obj.needsRedoDpyListOnResize): if transp: if not self.drawMode & 4: # only render if immediate & transp draw = 0 else: if not self.drawMode & 1: # only render if immediate & opaque draw = 0 ## if draw==1: ## print 'drawing immediate opaque object' if draw and obj.visible: if transp: if self.drawTransparentObjects: glEnable(GL_BLEND) if not obj.getDepthMask(): glDepthMask(GL_FALSE) glBlendFunc(obj.srcBlendFunc, obj.dstBlendFunc) self.DrawOneObject(obj) glDisable(GL_BLEND) glDepthMask(GL_TRUE) else: self.hasTransparentObjects = 1 else: # was: elif not self.drawTransparentObjects: self.DrawOneObject(obj) # VERY Expensif if pushAttrib: glPopAttrib() if lIsInstanceTransformable: for c in obj.clipPI: # disable object's clip planes that are c._Disable() # inherited by children if obj.scissor: glDisable(GL_SCISSOR_TEST) if not obj.inheritXform: glPopMatrix() glPopMatrix() # Restore the matrix def RedrawObjectHierarchy(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() glPushMatrix() # setup GL state for root object obj = self.viewer.rootObject if self.drawBB: obj.DrawTreeBoundingBox() if self.drawBB != viewerConst.ONLY: # save the transformation before the root object # used by some object who do not want to inherit transform m = Numeric.array(glGetDoublev(GL_MODELVIEW_MATRIX)).astype('f') self.beforeRootTransformation = Numeric.reshape( m, (16,) ) obj.MakeMat() # root object transformation # mod_opengltk #m = glGetDoublev(GL_MODELVIEW_MATRIX).astype('f') m = Numeric.array(glGetDoublev(GL_MODELVIEW_MATRIX)).astype('f') self.rootObjectTransformation = Numeric.reshape( m, (16,) ) # no reason to push and pop attribute of root object # glPushAttrib(GL_CURRENT_BIT | GL_LIGHTING_BIT | # GL_POLYGON_BIT) #obj.InitColor() # init GL for color with ROOT color #obj.InitMaterial() # init GL for material with ROOT material obj.SetupGL() # setup GL with ROOT properties if len(obj.clipPI): self.ActivateClipPlanes( obj.clipPI, obj.clipSide ) # draw all object that do not want a display List #print "self.viewer.noDpyListOpaque", self.viewer.noDpyListOpaque if len(self.viewer.noDpyListOpaque): self.drawMode = 1 # no dispaly list Opaque for m in obj.instanceMatricesFortran: glPushMatrix() glMultMatrixf(m) #map( self.Draw, obj.children) map( self.Draw, self.viewer.noDpyListOpaque ) glPopMatrix() # for "Continuity" (ucsd - nbcr) as we don't have vertexArrays yet if hasattr(self, 'vertexArrayCallback'): self.vertexArrayCallback() # when redraw is triggered by pick event self.viewer has been set # to None if self.dpyList and self.viewer.useMasterDpyList: #print 'calling master list' currentcontext = self.tk.call(self._w, 'contexttag') if currentcontext != self.dpyList[1]: warnings.warn("""RedrawObjectHierarchy failed because the current context is the wrong one""") #print "currentcontext != self.viewer.dpyList[1]", currentcontext, self.viewer.dpyList[1] else: #print '#%d'%self.dpyList[0], currentcontext, "glCallList Camera2" glCallList(self.dpyList[0]) else: #print 'rebuilding master list' if self.viewer.useMasterDpyList: lNewList = glGenLists(1) #lNewList = self.newList lContext = self.tk.call( self._w, 'contexttag' ) #print "lNewList StandardCamera.RedrawObjectHierarchy", lNewList, lContext, self.name self.dpyList = ( lNewList, lContext ) glNewList(self.dpyList[0], GL_COMPILE) #print '+%d'%self.dpyList[0], lContext, "glNewList Camera" # call for each subtree with root in obj.children # for o in obj.children: self.Draw(o) self.drawMode = 2 self.drawTransparentObjects = 0 self.hasTransparentObjects = 0 for m in obj.instanceMatricesFortran: glPushMatrix() glMultMatrixf(m) map( self.Draw, obj.children) glPopMatrix() if self.hasTransparentObjects: self.drawTransparentObjects = 1 for m in obj.instanceMatricesFortran: glPushMatrix() glMultMatrixf(m) map( self.Draw, obj.children) glPopMatrix() if self.viewer.useMasterDpyList: #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Camera" glEndList() #print "self.viewer.dpyList", self.viewer.dpyList if self.dpyList: currentcontext = self.tk.call(self._w, 'contexttag') if currentcontext != self.dpyList[1]: warnings.warn("""RedrawObjectHierarchy failed because the current context is the wrong one""") #print "currentcontext != self.viewer.dpyList[1]", currentcontext, self.viewer.dpyList[1] else: #print '#%d'%self.dpyList[0], currentcontext, "glCallList Camera3" glCallList(self.dpyList[0]) # draw all object that do not want a display List #print "self.viewer.noDpyListTransp", self.viewer.noDpyListTransp if len(self.viewer.noDpyListTransp): self.drawTransparentObjects = 1 self.drawMode = 4 for m in obj.instanceMatricesFortran: glPushMatrix() glMultMatrixf(m) #map( self.Draw, obj.children) map( self.Draw, self.viewer.noDpyListTransp ) glPopMatrix() self.drawTransparentObjects = 0 ## glPopAttrib() for c in obj.clipPI: c._Disable() glPopMatrix() def _RedrawCamera(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Actual drawing of lights, clipping planes and objects """ if self.stereoMode.startswith('SIDE_BY_SIDE'): if self.viewer.tileRender: glPushMatrix() # setup GL state for camera self.BuildTransformation() # camera transformation self.SetupLights() self.DrawAllDirectionalLights() if self.imageRendered == 'RIGHT_EYE': glTranslatef( float(-self.sideBySideTranslation), 0, 0 ) glRotatef( float(-self.sideBySideRotAngle), 0., 1., 0.) elif self.imageRendered == 'LEFT_EYE': glTranslatef( float(self.sideBySideTranslation), 0, 0 ) glRotatef( float(self.sideBySideRotAngle), 0., 1., 0.) else: assert False, 'self.imageRendered is not set correctly' glViewport(0, 0, int(self.width), int(self.height)) glScalef( 1., 0.5, 1.) self.RedrawObjectHierarchy() glPopMatrix() elif self.stereoMode.endswith('_CROSS'): halfWidth = self.width/2 # setup GL state for camera glPushMatrix() self.BuildTransformation() # camera transformation self.SetupLights() # set GL lights; moved from Light object to here self.DrawAllDirectionalLights() # render image for right eye self.imageRendered = 'RIGHT_EYE' glPushMatrix() glTranslatef( float(-self.sideBySideTranslation), 0, 0 ) glRotatef( float(-self.sideBySideRotAngle), 0., 1., 0.) glViewport(0, 0, int(halfWidth), int(self.height) ) glScalef( 1., 0.5, 1.) self.RedrawObjectHierarchy() glPopMatrix() # render image for left eye self.imageRendered = 'LEFT_EYE' glPushMatrix() glTranslatef( float(self.sideBySideTranslation), 0, 0 ) glRotatef( float(self.sideBySideRotAngle), 0., 1., 0.) glScalef( 1., 0.5, 1.) glViewport(int(halfWidth), 0, int(halfWidth), int(self.height)) self.RedrawObjectHierarchy() glPopMatrix() glPopMatrix() glViewport(0, 0, int(self.width), int(self.height)) elif self.stereoMode.endswith('_STRAIGHT'): halfWidth = self.width/2 # setup GL state for camera glPushMatrix() self.BuildTransformation() # camera transformation self.SetupLights() # set GL lights; moved from Light object to here self.DrawAllDirectionalLights() # render image for left eye self.imageRendered = 'LEFT_EYE' glPushMatrix() glTranslatef( float(self.sideBySideTranslation), 0, 0 ) glRotatef( float(self.sideBySideRotAngle), 0., 1., 0.) glScalef( 1., 0.5, 1.) glViewport(0, 0, halfWidth, self.height) self.RedrawObjectHierarchy() glPopMatrix() # render image for right eye self.imageRendered = 'RIGHT_EYE' glPushMatrix() glTranslatef( float(-self.sideBySideTranslation), 0, 0 ) glRotatef( float(-self.sideBySideRotAngle), 0., 1., 0.) glViewport(int(halfWidth), 0, int(halfWidth), int(self.height)) glScalef( 1., 0.5, 1.) self.RedrawObjectHierarchy() glPopMatrix() glPopMatrix() glViewport(0, 0, self.width, self.height) elif self.stereoMode=='3DTV': halfWidth = self.width/2 # setup GL state for camera glPushMatrix() self.BuildTransformation() # camera transformation self.SetupLights() # set GL lights; moved from Light object to here self.DrawAllDirectionalLights() # render image for left eye self.imageRendered = 'LEFT_EYE' glPushMatrix() glTranslatef( float(self.TV3DTranslation), 0, 0 ) glRotatef( float(self.TV3DRotAngle), 0., 1., 0.) sx, sy, sz = self.TV3DScaling glScalef( sx, sy, sz) glViewport(0, 0, halfWidth, self.height) self.RedrawObjectHierarchy() glPopMatrix() # render image for right eye self.imageRendered = 'RIGHT_EYE' glPushMatrix() glTranslatef( float(-self.TV3DTranslation), 0, 0 ) glRotatef( float(-self.TV3DRotAngle), 0., 1., 0.) glViewport(int(halfWidth), 0, int(halfWidth), int(self.height)) glScalef( sx, sy, sz) self.RedrawObjectHierarchy() glPopMatrix() glPopMatrix() glViewport(0, 0, self.width, self.height) elif self.stereoMode.startswith('COLOR_SEPARATION'): if self.stereoMode.endswith('_RED_BLUE'): left = (GL_TRUE, GL_FALSE, GL_FALSE) right = (GL_FALSE, GL_FALSE, GL_TRUE) elif self.stereoMode.endswith('_BLUE_RED'): left = (GL_FALSE, GL_FALSE, GL_TRUE) right = (GL_TRUE, GL_FALSE, GL_FALSE) elif self.stereoMode.endswith('_RED_GREEN'): left = (GL_TRUE, GL_FALSE, GL_FALSE) right = (GL_FALSE, GL_TRUE, GL_FALSE) elif self.stereoMode.endswith('_GREEN_RED'): left = (GL_FALSE, GL_TRUE, GL_FALSE) right = (GL_TRUE, GL_FALSE, GL_FALSE) elif self.stereoMode.endswith('_RED_GREENBLUE'): left = (GL_TRUE, GL_FALSE, GL_FALSE) right = (GL_FALSE, GL_TRUE, GL_TRUE) elif self.stereoMode.endswith('_GREENBLUE_RED'): left = (GL_FALSE, GL_TRUE, GL_TRUE) right = (GL_TRUE, GL_FALSE, GL_FALSE) elif self.stereoMode.endswith('_REDGREEN_BLUE'): left = (GL_TRUE, GL_TRUE, GL_FALSE) right = (GL_FALSE, GL_FALSE, GL_TRUE) elif self.stereoMode.endswith('_BLUE_REDGREEN'): left = (GL_FALSE, GL_FALSE, GL_TRUE) right = (GL_TRUE, GL_TRUE, GL_FALSE) glPushMatrix() # setup GL state for camera self.BuildTransformation() # camera transformation self.SetupLights() # set GL lights; moved from Light object to here self.DrawAllDirectionalLights() # render image for left eye self.imageRendered = 'MONO' #'LEFT_EYE' glPushMatrix() glTranslatef( float(self.sideBySideTranslation), 0, 0 ) glRotatef( float(self.sideBySideRotAngle), 0., 1., 0.) glViewport(0, 0, int(self.width), int(self.height)) glColorMask(int(left[0]), int(left[1]), int(left[2]), GL_FALSE) self.RedrawObjectHierarchy() glPopMatrix() self.drawHighlight() glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) # render image for right eye self.imageRendered = 'RIGHT_EYE' glPushMatrix() glTranslatef( float(-self.sideBySideTranslation), 0, 0 ) glRotatef( float(-self.sideBySideRotAngle), 0., 1., 0.) glViewport(0, 0, int(self.width), int(self.height)) glColorMask(int(right[0]),int(right[1]),int(right[2]), GL_FALSE) self.RedrawObjectHierarchy() glPopMatrix() self.drawHighlight() glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE) glPopMatrix() elif self.stereoMode == 'STEREO_BUFFERS': glPushMatrix() # setup GL state for camera self.BuildTransformation() # camera transformation self.SetupLights() # set GL lights; moved from Light object to here self.DrawAllDirectionalLights() # render image for left eye self.imageRendered = 'LEFT_EYE' glPushMatrix() glTranslatef( float(self.sideBySideTranslation), 0, 0 ) glRotatef( float(self.sideBySideRotAngle), 0., 1., 0.) glViewport(0, 0, int(self.width), int(self.height)) self.RedrawObjectHierarchy() glPopMatrix() self.drawHighlight() # render image for right eye self.imageRendered = 'RIGHT_EYE' glDrawBuffer(GL_BACK_RIGHT) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) glPushMatrix() glTranslatef( float(-self.sideBySideTranslation), 0, 0 ) glRotatef( float(-self.sideBySideRotAngle), 0., 1., 0.) glViewport(0, 0, int(self.width), int(self.height)) self.RedrawObjectHierarchy() glPopMatrix() self.drawHighlight() glPopMatrix() glDrawBuffer(GL_BACK_LEFT) else: # default to "Mono mode" self.imageRendered = 'MONO' glPushMatrix() # setup GL state for camera self.BuildTransformation() # camera transformation self.SetupLights() self.DrawAllDirectionalLights() glViewport(0, 0, int(self.width), int(self.height)) self.RedrawObjectHierarchy() glPopMatrix() # def secondDerivative(self, im, width, height): # return im.filter(sndDerivK) def firstDerivative(self, im, width, height): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() fstDeriveV1K = ImageFilter.Kernel( (3,3), fstDeriveV1, self.d1scale) c = im.filter(fstDeriveV1K) fstDeriveV2K = ImageFilter.Kernel( (3,3), fstDeriveV2, self.d1scale) d = im.filter(fstDeriveV2K) fstDeriveH1K = ImageFilter.Kernel( (3,3), fstDeriveH1, self.d1scale) e = im.filter(fstDeriveH1K) fstDeriveH2K = ImageFilter.Kernel( (3,3), fstDeriveH2, self.d1scale) f = im.filter(fstDeriveH2K) result1 = ImageChops.add(c, d, 2.) result2 = ImageChops.add(e, f, 2.) result = ImageChops.add(result1, result2, 2.) return result ## alternative adding numeric arrays seems slower ## t1 = time() ## c = im.filter(fstDeriveV1K) ## c = Numeric.fromstring(c.tostring(), Numeric.UInt8) ## d = im.filter(fstDeriveV2K) ## d = Numeric.fromstring(d.tostring(), Numeric.UInt8) ## e = im.filter(fstDeriveH1K) ## e = Numeric.fromstring(e.tostring(), Numeric.UInt8) ## f = im.filter(fstDeriveH2K) ## f = Numeric.fromstring(f.tostring(), Numeric.UInt8) ## result = Numeric.fabs(c) + Numeric.fabs(d) +\ ## Numeric.fabs(e) + Numeric.fabs(f) ## result.shape = im.size ## result = Numeric.array( result )*0.25 ## return result def drawNPR(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() t1 = time() if self.viewer.tileRender is False: zbuf = self.GrabZBuffer(lock=False, flipTopBottom=False) #imageZbuf = Image.fromstring('L', (self.width, self.height), zbuf.tostring() ) #imageZbuf.save("zbuf.png") else: zbuf = self.GrabZBuffer(lock=False, flipTopBottom=False, zmin=self.viewer.tileRenderCtx.zmin, zmax=self.viewer.tileRenderCtx.zmax ) imageFinal = Image.new('L', (self.width+2, self.height+2) ) #padding # the 4 corners imageFinal.putpixel((0, 0), zbuf.getpixel((0, 0)) ) imageFinal.putpixel((0, self.height+1), zbuf.getpixel((0, self.height-1)) ) imageFinal.putpixel((self.width+1, 0), zbuf.getpixel((self.width-1, 0)) ) imageFinal.putpixel((self.width+1, self.height+1), zbuf.getpixel((self.width-1, self.height-1)) ) # the top and bottom line for i in range(self.width): imageFinal.putpixel((i+1, 0), zbuf.getpixel((i, 0)) ) imageFinal.putpixel((i+1, self.height+1), zbuf.getpixel((i, self.height-1)) ) # the left and right columns for j in range(self.height): imageFinal.putpixel((0, j+1), zbuf.getpixel((0, j)) ) imageFinal.putpixel((self.width+1, j+1), zbuf.getpixel((self.width-1, j)) ) # the main picture imageFinal.paste( zbuf, (1 , 1) ) zbuf = imageFinal d1strong = d2strong = None useFirstDerivative = self.d1scale!=0.0 useSecondDerivative = self.d2scale!=0.0 if useFirstDerivative: if self.viewer.tileRender: d1 = self.firstDerivative(zbuf, self.width+2, self.height+2) d1 = d1.crop((1,1,self.width+1,self.width+1)) else: d1 = self.firstDerivative(zbuf, self.width, self.height) #d1.save('first.jpg') #d1strong = Numeric.fromstring(d1.tostring(),Numeric.UInt8) #print 'first', min(d1.ravel()), max(d1.ravel()), Numeric.sum(d1.ravel()) #print self.d1cut, self.d1off d1 = Numeric.fromstring(d1.tostring(),Numeric.UInt8) #mini = min(d1) #maxi = max(d1) #print 'd1',mini, maxi # d1strong = Numeric.clip(d1, self.d1cutL, self.d1cutH) # d1strong = d1strong.astype('f')*self.d1off #print 'd1',min(d1strong), max(d1strong) #print 'first', d1strong.shape, min(d1strong.ravel()), max(d1strong.ravel()), Numeric.sum(d1strong.ravel()) # LOOKUP ramp #print "self.d1ramp", len(self.d1ramp), self.d1ramp #d1strong = Numeric.choose(d1.astype('B'), self.d1ramp ) d1strong = numpy.zeros(len(d1)) for index, elt in enumerate(d1.astype('B')): d1strong[index] = self.d1ramp[elt] #print 'firstramp', d1strong.shape, min(d1strong.ravel()), max(d1strong.ravel()), Numeric.sum(d1strong.ravel()) if useSecondDerivative: #d2 = self.secondDerivative(zbuf, self.width, self.height) sndDerivK = ImageFilter.Kernel( (3,3), sndDeriv, self.d2scale) d2 = zbuf.filter(sndDerivK) if self.viewer.tileRender: d2 = d2.crop((1,1,self.width+1,self.width+1)) #d2.save('second.jpg') #print 'second1', min(d2.ravel()), max(d2.ravel()), Numeric.sum(d2.ravel()) #print self.d2cut, self.d2off d2 = Numeric.fromstring(d2.tostring(),Numeric.UInt8) #mini = min(d2) #maxi = max(d2) #print 'd2',mini, maxi d2strong = Numeric.clip(d2, self.d2cutL, self.d2cutH) d2strong = d2strong.astype('f')*self.d2off #d2strong = Numeric.where(Numeric.greater(d2,self.d2cutL), # d2, 0) #d2strong = Numeric.where(Numeric.less(d2strong,self.d2cutH), # d2, 0) #d2strong += self.d2off #print 'd2',min(d2strong), max(d2strong) #print 'second2', d2strong.shape, min(d2strong.ravel()), max(d2strong.ravel()), Numeric.sum(d2strong.ravel()) if useFirstDerivative and useSecondDerivative: self.outline = Numeric.maximum(d1strong, d2strong) #self.outline = (d1strong + d2strong)/2 #self.outlineim = ImageChops.add(d1strong, d2strong) elif useFirstDerivative: self.outline = d1strong elif useSecondDerivative: self.outline = d2strong else: self.outline = None ## working OpenGL version ## zbuf = self.GrabZBuffer(lock=False) ## self.ivi.setImage(zbuf) ## deriv = self.ivi.firstDerivative() ## d1strong = Numeric.where(Numeric.greater(deriv,self.d1cut), ## self.d1scale*(deriv+self.d1off), 0) ## deriv2 = self.ivi.secondDerivative() ## d2strong = Numeric.where(Numeric.greater(deriv2,self.d2cut), ## self.d2scale*(deriv2+self.d2off), 0) ## self.outline = Numeric.maximum(d1strong, d2strong) ## self.tk.call(self._w, 'makecurrent') #print 'time NPR rendering', time()-t1 return def displayNPR(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() t1 = time() if self.outline is None: return lViewport = glGetIntegerv(GL_VIEWPORT) glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() glOrtho(float(lViewport[0]), float(lViewport[0]+lViewport[2]), float(lViewport[1]), float(lViewport[1]+lViewport[3]), -1, 1) glMatrixMode(GL_MODELVIEW) glPushMatrix() glLoadIdentity() glDisable(GL_DEPTH_TEST) glEnable(GL_BLEND) glBlendFunc(GL_DST_COLOR, GL_ZERO); glRasterPos2f(0.0, 0.0) self.outline = Numeric.fabs(self.outline-255) self.outline = self.outline.astype('B') # glActiveTexture(GL_TEXTURE0); GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) _gllib.glDrawPixels(self.width, self.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, self.outline ) glMatrixMode(GL_PROJECTION) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() #print 'time NPR display', time()-t1 def RedrawAASwitch(self, *dummy): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Redraw all the objects in the scene""" glStencilMask(1) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE) glStencilFunc ( GL_ALWAYS, 0, 1 ) ; glEnable ( GL_STENCIL_TEST ) ; if not self.viewer.accumBuffersError and \ self.antiAliased and self.renderMode==GL_RENDER: dist = math.sqrt(Numeric.add.reduce(self.direction*self.direction)) # jitter loop if self.antiAliased>0: sca = 1./self.antiAliased accumContour = None for i in range(self.antiAliased): glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) if self.projectionType == self.PERSPECTIVE: if self.viewer.tileRender: tr = self.viewer.tileRenderCtx left = tr.tileleft right = tr.tileright bottom = tr.tilebottom top = tr.tiletop else: left=right=top=bottom=None self.AccPerspective (self.jitter[i][0], self.jitter[i][1], 0.0, 0.0, dist, left, right, bottom, top) self._RedrawCamera() else: W = self.right-self.left # width in world coordinates H = self.top-self.bottom # height in world coordinates glPushMatrix() glTranslatef (self.jitter[i][0]*W/self.width, self.jitter[i][1]*H/self.height, 0.0) self._RedrawCamera() glPopMatrix() if i == 0 and self.ssao : self.copyDepth() # we accumulate the back buffer glReadBuffer(GL_BACK) if i==0: glAccum(GL_LOAD, self.accumWeigth) else: glAccum(GL_ACCUM, self.accumWeigth) if self.contours and self._suspendNPR is False: self.drawNPR() if self.outline is not None: if accumContour is None: accumContour = self.outline.copy() accumContour *= sca else: accumContour += sca*self.outline glAccum (GL_RETURN, 1.0) if self.contours and self._suspendNPR is False: self.outline = accumContour else: # plain drawing if self.ssao : self.copy_depth_ssao = True self._RedrawCamera() if self.contours and self._suspendNPR is False: self.drawNPR() if self.contours and self._suspendNPR is False: glViewport(0, 0, self.width, self.height) self.displayNPR() if self.stereoMode.startswith('COLOR_SEPARATION') is False \ and self.stereoMode != 'STEREO_BUFFERS': self.drawHighlight() if self.ssao : self.drawSSAO() glDisable(GL_STENCIL_TEST) if self.drawThumbnailFlag: self.drawThumbnail() if self.swap: self.tk.call(self._w, 'swapbuffers') def setShaderSelectionContour(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #import pdb;pdb.set_trace() #if DejaVu.enableSelectionContour is True: # if GL.glGetString(GL.GL_VENDOR).find('Intel') >= 0: # DejaVu.enableSelectionContour = False # print "intel (even gma) gpu drivers don't handle properly the stencil with FBO" if DejaVu.enableSelectionContour is True: try: ## do not try to import this before creating the opengl context, it would fail. from opengltk.extent import _glextlib DejaVu.enableSelectionContour = True except ImportError: DejaVu.enableSelectionContour = False print "could not import _glextlib" #import pdb;pdb.set_trace() if DejaVu.enableSelectionContour is True: extensionsList = glGetString(GL_EXTENSIONS) if extensionsList.find('GL_EXT_packed_depth_stencil') < 0: DejaVu.enableSelectionContour = False print "opengl extension GL_EXT_packed_depth_stencil is not present" if DejaVu.enableSelectionContour is True: f = _glextlib.glCreateShader(_glextlib.GL_FRAGMENT_SHADER) # This shader performs a 9-tap Laplacian edge detection filter. # (converted from the separate "edges.cg" file to embedded GLSL string) self.fragmentShaderCode = """ uniform float contourSize; uniform vec4 contourColor; uniform sampler2D texUnit; void main(void) { float lOffset = .001 * contourSize ; // (1./512.); vec2 texCoord = gl_TexCoord[0].xy; if ( ( texCoord [ 0 ] > lOffset ) // to suppress artifacts on frame buffer bounds && ( texCoord [ 1 ] > lOffset ) && ( texCoord [ 0 ] < 1. - lOffset ) && ( texCoord [ 1 ] < 1. - lOffset ) ) { float c = texture2D(texUnit, texCoord)[0]; float bl = texture2D(texUnit, texCoord + vec2(-lOffset, -lOffset))[0]; float l = texture2D(texUnit, texCoord + vec2(-lOffset, 0.0))[0]; float tl = texture2D(texUnit, texCoord + vec2(-lOffset, lOffset))[0]; float t = texture2D(texUnit, texCoord + vec2( 0.0, lOffset))[0]; float tr = texture2D(texUnit, texCoord + vec2( lOffset, lOffset))[0]; float r = texture2D(texUnit, texCoord + vec2( lOffset, 0.0))[0]; float br = texture2D(texUnit, texCoord + vec2( lOffset, lOffset))[0]; float b = texture2D(texUnit, texCoord + vec2( 0.0, -lOffset))[0]; if ( 8. * (c + -.125 * (bl + l + tl + t + tr + r + br + b)) != 0. ) { gl_FragColor = contourColor; //vec4(1., 0., 1., .7) ; } else { //due to bizarre ATI behavior gl_FragColor = vec4(1., 0., 0., 0.) ; } } } """ _glextlib.glShaderSource(f, 1, self.fragmentShaderCode, 0x7FFFFFFF) _glextlib.glCompileShader(f) lStatus = 0x7FFFFFFF lStatus = _glextlib.glGetShaderiv(f, _glextlib.GL_COMPILE_STATUS, lStatus ) if lStatus == 0: print "compile status", lStatus charsWritten = 0 shaderInfoLog = '\0' * 2048 charsWritten, infoLog = _glextlib.glGetShaderInfoLog(f, len(shaderInfoLog), charsWritten, shaderInfoLog) print "shaderInfoLog", shaderInfoLog DejaVu.enableSelectionContour = False print "selection contour shader didn't compile" else: self.shaderProgram = _glextlib.glCreateProgram() _glextlib.glAttachShader(self.shaderProgram,f) _glextlib.glLinkProgram(self.shaderProgram) lStatus = 0x7FFFFFFF lStatus = _glextlib.glGetProgramiv(self.shaderProgram, _glextlib.GL_LINK_STATUS, lStatus ) if lStatus == 0: print "link status", lStatus DejaVu.enableSelectionContour = False print "selection contour shader didn't link" else: _glextlib.glValidateProgram(self.shaderProgram) lStatus = 0x7FFFFFFF lStatus = _glextlib.glGetProgramiv(self.shaderProgram, _glextlib.GL_VALIDATE_STATUS, lStatus ) if lStatus == 0: print "validate status", lStatus DejaVu.enableSelectionContour = False print "selection contour shader not validated" else: # Get location of the sampler uniform self.texUnitLoc = int(_glextlib.glGetUniformLocation(self.shaderProgram, "texUnit")) #print "selection contour shader successfully compiled and linked" # Get location of the contourSize uniform self.contourSizeLoc = int(_glextlib.glGetUniformLocation(self.shaderProgram, "contourSize")) # Get location of the contourSize uniform self.contourColorLoc = int(_glextlib.glGetUniformLocation(self.shaderProgram, "contourColor")) ## create a framebuffer to receive the texture self.fb = 0 self.fb = _glextlib.glGenFramebuffersEXT(1, self.fb) #print "self.fb", self.fb lCheckMessage = _glextlib.glCheckFramebufferStatusEXT(_glextlib.GL_FRAMEBUFFER_EXT) if lCheckMessage != _glextlib.GL_FRAMEBUFFER_COMPLETE_EXT: # 0x8CD5 print 'glCheckFramebufferStatusEXT %x'%lCheckMessage DejaVu.enableSelectionContour = False def drawHighlight(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # lStencil = numpy.zeros(self.width*self.height, dtype='uint32') # GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) # _gllib.glReadPixels( 0, 0, self.width, self.height, # GL.GL_STENCIL_INDEX, GL.GL_UNSIGNED_INT, # lStencil) # print "lStencil", lStencil[0] # background is 254 # fill is 255 # lStencilImage = Image.fromstring('L', (self.width, self.height), # lStencil.astype('uint8').tostring() ) # lStencilImage.save("lStencil.png") # zbuf = self.GrabZBuffer(lock=False, flipTopBottom=False) # imageZbuf = Image.fromstring('L', (self.width, self.height), zbuf.tostring() ) # imageZbuf.save("lZbuff.png") # to draw only the highlight zone from the stencil buffer GL.glEnable(GL.GL_STENCIL_TEST) glStencilMask(0) glStencilFunc(GL_EQUAL, 1, 1) glPushMatrix() glLoadIdentity() glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() lViewport = glGetIntegerv(GL_VIEWPORT) glOrtho(float(lViewport[0]), float(lViewport[0]+lViewport[2]), float(lViewport[1]), float(lViewport[1]+lViewport[3]), -1, 1) glDisable(GL_DEPTH_TEST) glDisable(GL_LIGHTING) # glActiveTexture(GL_TEXTURE0); ## here we apply the patterned highlight if DejaVu.selectionPatternSize >= 3: #glEnable(GL_COLOR_LOGIC_OP) #glLogicOp(GL_AND) glEnable(GL_TEXTURE_2D) _gllib.glBindTexture(GL_TEXTURE_2D, self.textureName) glEnable(GL_BLEND) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) glBegin(GL_POLYGON) glTexCoord2f(0., 0.) glVertex2i(0, 0) lTexWidth = float(self.width)/DejaVu.selectionPatternSize # determine how big the pattern will be lTexHeight = float(self.height)/DejaVu.selectionPatternSize glTexCoord2f(lTexWidth, 0.) glVertex2i(self.width, 0) glTexCoord2f(lTexWidth, lTexHeight) glVertex2i(self.width, self.height) glTexCoord2f(0., lTexHeight) glVertex2i(0, self.height) glEnd() glDisable(GL_BLEND) glDisable(GL_TEXTURE_2D) #glDisable(GL_COLOR_LOGIC_OP) if DejaVu.enableSelectionContour is True \ and DejaVu.selectionContourSize != 0: from opengltk.extent import _glextlib #import pdb;pdb.set_trace() ## copying the current stencil to a texture _gllib.glBindTexture(GL_TEXTURE_2D, self.stencilTextureName ) glCopyTexImage2D(GL_TEXTURE_2D, 0, _glextlib.GL_DEPTH_STENCIL_EXT, 0, 0, self.width, self.height, 0) ## switch writting to the FBO (Frame Buffer Object) _glextlib.glBindFramebufferEXT(_glextlib.GL_FRAMEBUFFER_EXT, self.fb ) #lCheckMessage = _glextlib.glCheckFramebufferStatusEXT(_glextlib.GL_FRAMEBUFFER_EXT) #print 'glCheckFramebufferStatusEXT 0 %x'%lCheckMessage ## attaching the current stencil to the FBO (Frame Buffer Object) _glextlib.glFramebufferTexture2DEXT(_glextlib.GL_FRAMEBUFFER_EXT, _glextlib.GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, self.stencilTextureName,0) #lCheckMessage = _glextlib.glCheckFramebufferStatusEXT(_glextlib.GL_FRAMEBUFFER_EXT) #print 'glCheckFramebufferStatusEXT 1 %x'%lCheckMessage _glextlib.glFramebufferTexture2DEXT(_glextlib.GL_FRAMEBUFFER_EXT, _glextlib.GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, self.stencilTextureName, 0) #lCheckMessage = _glextlib.glCheckFramebufferStatusEXT(_glextlib.GL_FRAMEBUFFER_EXT) #print 'glCheckFramebufferStatusEXT 2 %x'%lCheckMessage ## attaching the texture to be written as FBO _gllib.glBindTexture(GL_TEXTURE_2D, self.contourTextureName ) _gllib.glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self.width, self.height, 0, GL_RGBA, GL.GL_FLOAT, 0 ) _glextlib.glFramebufferTexture2DEXT(_glextlib.GL_FRAMEBUFFER_EXT, _glextlib.GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, self.contourTextureName, 0) #lCheckMessage = _glextlib.glCheckFramebufferStatusEXT(_glextlib.GL_FRAMEBUFFER_EXT) #print 'glCheckFramebufferStatusEXT 3 %x'%lCheckMessage ## verifying that everything gets attached to the FBO lCheckMessage = _glextlib.glCheckFramebufferStatusEXT(_glextlib.GL_FRAMEBUFFER_EXT) if lCheckMessage != _glextlib.GL_FRAMEBUFFER_COMPLETE_EXT: # 0x8CD5 print 'glCheckFramebufferStatusEXT %x'%lCheckMessage DejaVu.enableSelectionContour = False _glextlib.glBindFramebufferEXT(_glextlib.GL_FRAMEBUFFER_EXT, 0 ) print 'opengl frame buffer object not available, selection contour is now disabled.' #print 'you may need to set enableSelectionContour to False in the following file:' #print '~/.mgltools/(version numer)/DejaVu/_dejavurc' else: ## writing the stencil to the texture / FBO glClear(GL_COLOR_BUFFER_BIT) glBegin(GL_POLYGON) glVertex2i(0, 0) glVertex2i(self.width, 0) glVertex2i(self.width, self.height) glVertex2i(0, self.height) glEnd() ## switch writing to the regular frame buffer (normaly the back buffer) _glextlib.glBindFramebufferEXT(_glextlib.GL_FRAMEBUFFER_EXT, 0 ) ## here we obtain the contour of the stencil copied in the texture and draw it from opengltk.extent import _glextlib _glextlib.glUseProgram( self.shaderProgram ) _glextlib.glUniform1i( self.texUnitLoc, 0) _glextlib.glUniform1f( self.contourSizeLoc, float(DejaVu.selectionContourSize)) _glextlib.glUniform4f( self.contourColorLoc, DejaVu.selectionContourColor[0], DejaVu.selectionContourColor[1], DejaVu.selectionContourColor[2], DejaVu.selectionContourColor[3] ) glEnable(GL_BLEND) glStencilFunc(GL_NOTEQUAL, 1, 1) #so the contour is drawn only outside of the highlighted area glBegin(GL_POLYGON) glTexCoord2i(0, 0) glVertex2i(0, 0) glTexCoord2i(1, 0) glVertex2i(self.width, 0) glTexCoord2i(1, 1) glVertex2i(self.width, self.height) glTexCoord2i(0, 1) glVertex2i(0, self.height) glEnd() glDisable(GL_BLEND) _glextlib.glUseProgram( 0 ) # to protect our texture, we bind the default texture while we don't use it _gllib.glBindTexture(GL_TEXTURE_2D, 0) glEnable(GL_DEPTH_TEST) glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() glStencilMask(1) glStencilFunc ( GL_ALWAYS, 0, 1 ) #=============================================================================== # SSAO Shader #=============================================================================== def setTextureSSAO(self): self.depthtextureName = int(glGenTextures(1)[0]) glPrioritizeTextures(numpy.array([self.depthtextureName]), numpy.array([1.])) _gllib.glBindTexture (GL_TEXTURE_2D, self.depthtextureName); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ) _gllib.glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, self.width, self.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None); #SSAO depthexture self.illumtextureName = int(glGenTextures(1)[0]) glPrioritizeTextures(numpy.array([self.illumtextureName]), numpy.array([1.])) _gllib.glBindTexture (GL_TEXTURE_2D, self.illumtextureName); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ) _gllib.glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, self.width, self.height, 0, GL_LUMINANCE, GL_UNSIGNED_INT, None); #SSAO depthexture self.rendertextureName = int(glGenTextures(1)[0]) glPrioritizeTextures(numpy.array([self.rendertextureName]), numpy.array([1.])) _gllib.glBindTexture (GL_TEXTURE_2D, self.rendertextureName); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ) _gllib.glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, self.width, self.height, 0, GL_RGB, GL_UNSIGNED_INT, None); #depth mask texture self.depthmasktextureName = int(glGenTextures(1)[0]) glPrioritizeTextures(numpy.array([self.depthmasktextureName]), numpy.array([1.])) _gllib.glBindTexture (GL_TEXTURE_2D, self.depthmasktextureName); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glTexParameteri (GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ) _gllib.glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, self.width, self.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, None); #SSAO randomtexture # # self.randomTexture = Texture() # import Image # img = Image.open(DejaVu.__path__[0]+os.sep+"textures"+os.sep+"random_normals.png") # self.randomTexture.Set(enable=1, image=img) self.randomtextureName = int(glGenTextures(1)[0]) glPrioritizeTextures(numpy.array([self.randomtextureName]), numpy.array([1.])) # _gllib.glBindTexture (GL_TEXTURE_2D, self.randomtextureName); # glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); # glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); # glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); # glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); # glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE ) # _gllib.glTexImage2D (GL_TEXTURE_2D, 0, self.randomTexture.format, # self.randomTexture.width, self.randomTexture.height, # 0, self.randomTexture.format, GL_UNSIGNED_INT, # self.randomTexture.image); _gllib.glBindTexture (GL_TEXTURE_2D,0) def setShaderSSAO(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not DejaVu.enableSSAO : return try: ## do not try to import this before creating the opengl context, it would fail. from opengltk.extent import _glextlib DejaVu.enableSSAO = True except ImportError: DejaVu.enableSSAO = False print "could not import _glextlib" #import pdb;pdb.set_trace() if DejaVu.enableSSAO is True: extensionsList = glGetString(GL_EXTENSIONS) if extensionsList.find('GL_EXT_packed_depth_stencil') < 0: DejaVu.enableSSAO = False print "opengl extension GL_EXT_packed_depth_stencil is not present" if DejaVu.enableSSAO is True: # self.setDefaultSSAO_OPTIONS() self.setTextureSSAO() f = _glextlib.glCreateShader(_glextlib.GL_FRAGMENT_SHADER) sfile = open(DejaVu.__path__[0]+os.sep+"shaders"+os.sep+"fragSSAO","r") lines = sfile.readlines() sfile.close() self.fragmentSSAOShaderCode="" for l in lines : self.fragmentSSAOShaderCode+=l v = _glextlib.glCreateShader(_glextlib.GL_VERTEX_SHADER) sfile = open(DejaVu.__path__[0]+os.sep+"shaders"+os.sep+"vertSSAO","r") lines = sfile.readlines() sfile.close() self.vertexSSAOShaderCode="" for l in lines : self.vertexSSAOShaderCode+=l lStatus = 0x7FFFFFFF _glextlib.glShaderSource(v, 1, self.vertexSSAOShaderCode, lStatus) _glextlib.glCompileShader(v) _glextlib.glShaderSource(f, 1, self.fragmentSSAOShaderCode, lStatus) _glextlib.glCompileShader(f) lStatus1 = _glextlib.glGetShaderiv(f, _glextlib.GL_COMPILE_STATUS, lStatus ) #print "SSAO compile status frag: %s"%lStatus, lStatus2 = _glextlib.glGetShaderiv(v, _glextlib.GL_COMPILE_STATUS, lStatus ) #print " vertex: %s"%lStatus if lStatus1 == 0 or lStatus2 == 0: # print "compile status", lStatus charsWritten = 0 shaderInfoLog = '\0' * 2048 charsWritten, infoLog = _glextlib.glGetShaderInfoLog(f, len(shaderInfoLog), charsWritten, shaderInfoLog) print "shaderInfoLog", shaderInfoLog DejaVu.enableSSAO = False print "SSAO shader didn't compile" else: self.shaderSSAOProgram = _glextlib.glCreateProgram() _glextlib.glAttachShader(self.shaderSSAOProgram,v) _glextlib.glAttachShader(self.shaderSSAOProgram,f) _glextlib.glLinkProgram(self.shaderSSAOProgram) lStatus = 0x7FFFFFFF lStatus = _glextlib.glGetProgramiv(self.shaderSSAOProgram, _glextlib.GL_LINK_STATUS, lStatus ) if lStatus == 0: # print "link status", lStatus log = "" charsWritten = 0 progInfoLog = '\0' * 2048 charsWritten, infoLog = _glextlib.glGetProgramInfoLog(self.shaderSSAOProgram, len(progInfoLog), charsWritten, progInfoLog) DejaVu.enableSSAO = False print "SSAO shader didn't link" print "log ",progInfoLog else: _glextlib.glValidateProgram(self.shaderSSAOProgram) lStatus = 0x7FFFFFFF lStatus = _glextlib.glGetProgramiv(self.shaderSSAOProgram, _glextlib.GL_VALIDATE_STATUS, lStatus ) if lStatus == 0: print "SSAO shader did not validate, status:", lStatus DejaVu.enableSSAO = False print "enableSSAO not validated" else: # Get location self.SSAO_LOCATIONS = { 'RandomTexture': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'RandomTexture' ), 'DepthTexture': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'DepthTexture' ), 'RenderedTexture': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'RenderedTexture' ), 'LuminanceTexture': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'LuminanceTexture' ), 'DepthMaskTexture': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'DepthMaskTexture' ), 'RenderedTextureWidth': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'RenderedTextureWidth' ), 'RenderedTextureHeight': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'RenderedTextureHeight' ), 'realfar': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'realfar' ), #'realnear': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'realnear' ), # 'fogS': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'fogS' ), # 'fogE': _glextlib.glGetUniformLocation( self.shaderSSAOProgram, 'fogE' ), } for k in self.SSAO_OPTIONS : self.SSAO_LOCATIONS[k] = _glextlib.glGetUniformLocation( self.shaderSSAOProgram, k ) def setDefaultSSAO_OPTIONS(self): from opengltk.extent import _glextlib #can be Intel, NVIDIA self.SSAO_OPTIONS={'far': [300.0,0.,1000.,"float"], 'near': [self.near,0.,100.,"float"], 'method':[self.ssao_method,0,1,"int"], 'do_noise':[0,0,1,"int"], 'fog':[0,0,1,"int"], 'use_fog':[1,0,1,"int"], 'use_mask_depth':[self.use_mask_depth,0,1,"int"], 'only_depth':[0,0,1,"int"], 'mix_depth':[0,0,1,"int"], 'only_ssao':[0,0,1,"int"], 'show_mask_depth':[0,0,1,"int"], 'scale':[1.0,1.0,100.0,"float"], 'samples': [6,1,8,"int"], 'rings': [6,1,8,"int"], 'aoCap': [1.2,0.0,10.0,"float"], 'aoMultiplier': [100.0,1.,500.,"float"], 'depthTolerance': [0.0,0.0,1.0,"float"], 'aorange':[60.0,1.0,500.0,"float"], 'negative':[0,0,1,"int"], 'correction':[6.0,0.0,1000.0,"float"], #'force_real_far':[0,0,1,"int"], } vendor = GL.glGetString(GL.GL_VENDOR) #if vendor.find("ATI"): self.SSAO_OPTIONS["near"][0] = 2.0 self.Set(near = 2.0) self.SSAO_OPTIONS_ORDER = ['use_fog','only_ssao','only_depth','mix_depth', 'negative','do_noise','near','scale','rings','samples','aoCap','aoMultiplier', 'aorange','depthTolerance','use_mask_depth']#'far','correction', def copyDepth(self): _gllib.glBindTexture (GL_TEXTURE_2D, self.depthtextureName); glCopyTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT, 0, 0, self.width, self.height, 0); self.copy_depth_ssao = False def copyBuffer(self, depthmask=False): if depthmask : _gllib.glBindTexture (GL_TEXTURE_2D, self.depthmasktextureName); glCopyTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT, 0, 0, self.width, self.height, 0); return if self.copy_depth_ssao : _gllib.glBindTexture (GL_TEXTURE_2D, self.depthtextureName); glCopyTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT, 0, 0, self.width, self.height, 0); _gllib.glBindTexture (GL_TEXTURE_2D, self.illumtextureName); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 0, 0, self.width, self.height, 0); _gllib.glBindTexture (GL_TEXTURE_2D, self.rendertextureName); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, self.width, self.height, 0); _gllib.glBindTexture (GL_TEXTURE_2D, 0); def drawSSAO(self,combine=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if DejaVu.enableSSAO is True and self.ssao: #if not self.AR.use_mask: self.copyBuffer() from opengltk.extent import _glextlib import numpy _glextlib.glBindFramebufferEXT(_glextlib.GL_FRAMEBUFFER_EXT, 0 ) _glextlib.glUseProgram( self.shaderSSAOProgram ) glActiveTexture(GL_TEXTURE3); _gllib.glBindTexture (GL_TEXTURE_2D, self.depthtextureName); _glextlib.glUniform1i(self.SSAO_LOCATIONS['DepthTexture'],3) glActiveTexture(GL_TEXTURE4); _gllib.glBindTexture (GL_TEXTURE_2D, self.rendertextureName); _glextlib.glUniform1i(self.SSAO_LOCATIONS['RenderedTexture'],4) glActiveTexture(GL_TEXTURE5); _gllib.glBindTexture (GL_TEXTURE_2D, self.illumtextureName); _glextlib.glUniform1i(self.SSAO_LOCATIONS['LuminanceTexture'],5) glActiveTexture(GL_TEXTURE6); _gllib.glBindTexture (GL_TEXTURE_2D, self.randomtextureName); _glextlib.glUniform1i(self.SSAO_LOCATIONS['RandomTexture'],6) glActiveTexture(GL_TEXTURE7); _gllib.glBindTexture (GL_TEXTURE_2D, self.depthmasktextureName); _glextlib.glUniform1i(self.SSAO_LOCATIONS['DepthMaskTexture'],7) _glextlib.glUniform1f(self.SSAO_LOCATIONS['RenderedTextureWidth'],self.width) _glextlib.glUniform1f(self.SSAO_LOCATIONS['RenderedTextureHeight'],self.height) _glextlib.glUniform1f(self.SSAO_LOCATIONS['realfar'],self.far) #_glextlib.glUniform1f(self.SSAO_LOCATIONS['realnear'],self.near) for k in self.SSAO_OPTIONS: if len(self.SSAO_OPTIONS[k]) == 5 : self.SSAO_OPTIONS[k][0] = self.SSAO_OPTIONS[k][-1].get() val = self.SSAO_OPTIONS[k][0] if k == "correction" : #val = self.SSAO_OPTIONS[k][0] self.SSAO_OPTIONS[k][0] = val = self.far / 10.0 if len(self.SSAO_OPTIONS[k]) == 5 : val = self.SSAO_OPTIONS[k][-1].get() if k == "far" : #val = self.SSAO_OPTIONS[k][0] val = self.far + 230. if len(self.SSAO_OPTIONS[k]) == 5 : val = self.SSAO_OPTIONS[k][-1].get() if k == "fog" : self.SSAO_OPTIONS[k][0] = val = int(self.fog.enabled) if len(self.SSAO_OPTIONS[k]) == 5 : self.SSAO_OPTIONS[k][-1].set(val) if self.SSAO_OPTIONS[k][3] == "float": _glextlib.glUniform1f(self.SSAO_LOCATIONS[k],val) else : _glextlib.glUniform1i(self.SSAO_LOCATIONS[k],val) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) self.drawTexturePolygon() self.endSSAO() def endSSAO(self): if DejaVu.enableSSAO is True : from opengltk.extent import _glextlib _glextlib.glUseProgram(0) glActiveTexture(GL_TEXTURE0); _gllib.glBindTexture (GL_TEXTURE_2D, 0); # _gllib.glBindTexture (GL_TEXTURE_2D,GL_TEXTURE0) def drawTexturePolygon(self): glPushMatrix() glLoadIdentity() glMatrixMode(GL_PROJECTION) glPushMatrix() glLoadIdentity() lViewport = glGetIntegerv(GL_VIEWPORT) glOrtho(float(lViewport[0]), float(lViewport[0]+lViewport[2]), float(lViewport[1]), float(lViewport[1]+lViewport[3]), -1, 1) glEnable(GL_BLEND) # glEnable(GL_TEXTURE_2D) # if self.dsT == 0 : # _gllib.glBindTexture (GL_TEXTURE_2D, self.depthtextureName); # elif self.dsT == 1 : # _gllib.glBindTexture (GL_TEXTURE_2D, self.illumtextureName); # else : # _gllib.glBindTexture (GL_TEXTURE_2D, self.rendertextureName); glBegin(GL_POLYGON) glTexCoord2i(0, 0) glVertex2i(0, 0) glTexCoord2i(1, 0) glVertex2i(self.width, 0) glTexCoord2i(1, 1) glVertex2i(self.width, self.height) glTexCoord2i(0, 1) glVertex2i(0, self.height) glEnd() glDisable(GL_BLEND) _gllib.glBindTexture (GL_TEXTURE_2D, 0); glPopMatrix() glMatrixMode(GL_MODELVIEW) glPopMatrix() ## def DrawImage(self, imarray, mode='RGB', format=GL.GL_UNSIGNED_BYTE, ## filter=None, swap=False): ## """Draw an array of pixel in the camera ## """ ## if imarray is None: ## return ## GL.glViewport(0, 0, self.width, self.height) ## GL.glMatrixMode(GL.GL_PROJECTION) ## GL.glPushMatrix() ## GL.glLoadIdentity() ## GL.glOrtho(0, self.width, 0, self.height, -1.0, 1.0) ## GL.glMatrixMode(GL.GL_MODELVIEW) ## GL.glPushMatrix() ## GL.glLoadIdentity() ## GL.glRasterPos2i( 0, 0) ## GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) ## if not swap: ## GL.glDrawBuffer(GL.GL_BACK) ## if filter: ## GL.glEnable(GL.GL_CONVOLUTION_2D) ## GL.glConvolutionFilter2D(GL.GL_CONVOLUTION_2D, GL.GL_LUMINANCE, ## 3, 3, GL.GL_LUMINANCE, GL.GL_FLOAT, ## filter) ## if mode=='RGB': ## _gllib.glDrawPixels( self.width, self.height, ## GL.GL_RGB, format, imarray) ## elif mode in ['L','P']: ## _gllib.glDrawPixels( self.width, self.height, ## GL.GL_LUMINANCE, format, imarray) ## GL.glMatrixMode(GL.GL_PROJECTION) ## GL.glPopMatrix() ## GL.glMatrixMode(GL.GL_MODELVIEW) ## GL.glPopMatrix() ## GL.glDisable(GL.GL_CONVOLUTION_2D) ## GL.glFlush() ## if swap: ## self.tk.call(self._w, 'swapbuffers') ## def secondDerivative(self, imarray, mode='RGB', format=GL.GL_UNSIGNED_BYTE, ## swap=False): ## sndDeriv = Numeric.array([ [-0.125, -0.125, -0.125,], ## [-0.125, 1.0, -0.125,], ## [-0.125, -0.125, -0.125,] ], 'f') ## self.DrawImage(imarray, mode, format, sndDeriv, swap) ## if not swap: ## buffer=GL.GL_BACK ## deriv = self.GrabFrontBufferAsArray(lock=False, buffer=buffer) ## return Numeric.fabs(deriv).astype('B') ## def firstDerivative(self, imarray, mode='RGB', format=GL.GL_UNSIGNED_BYTE, ## swap=False): ## if not swap: ## buffer=GL.GL_BACK ## else: ## buffer=GL.GL_FRONT ## fstDeriveV = Numeric.array([ [-0.125, -0.25, -0.125], ## [ 0.0 , 0.0, 0.0 ], ## [0.125, 0.25, 0.125] ], 'f') ## self.DrawImage(imarray, mode, format, fstDeriveV, swap) ## derivV = self.GrabFrontBufferAsArray(lock=False, buffer=buffer) ## if derivV is None: ## return None ## fstDeriveV = Numeric.array([ [ 0.125, 0.25, 0.125], ## [ 0.0 , 0.0, 0.0 ], ## [-0.125, -0.25, -0.125] ], 'f') ## self.DrawImage(imarray, mode, format, fstDeriveV, swap) ## derivV += self.GrabFrontBufferAsArray(lock=False, buffer=buffer) ## derivV = Numeric.fabs(derivV*0.5) ## fstDeriveH = Numeric.array([ [-0.125, 0.0, 0.125], ## [-0.25 , 0.0, 0.25 ], ## [-0.125, 0.0, 0.125] ], 'f') ## self.DrawImage(imarray, mode, format, fstDeriveH, swap) ## derivH = self.GrabFrontBufferAsArray(lock=False, buffer=buffer) ## fstDeriveH = Numeric.array([ [ 0.125, 0.0, -0.125], ## [ 0.25 , 0.0, -0.25 ], ## [ 0.125, 0.0, -0.125] ], 'f') ## self.DrawImage(imarray, mode, format, fstDeriveH, swap) ## derivH += self.GrabFrontBufferAsArray(lock=False, buffer=buffer) ## derivH = Numeric.fabs(derivH*0.5) ## return derivH+derivV.astype('B') def Redraw(self, *dummy): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.selectDragRect: return if not self.initialized: return if not self.visible: return if not self.master.winfo_ismapped(): return # was causing very slow update of light source # This function shoudl force redrawing and hence not # wait for other things to happen #self.update_idletasks() # At this point We expect no interruption after this # and this OpenGL context should remain the current one until # we swap buffers self.tk.call(self._w, 'makecurrent') #glPushAttrib(GL_ALL_ATTRIB_BITS) if not self.viewer.tileRender: # only setup camera projection if we are not rendering tiles # when tiles are rendered the projection is set by the tile # renderer tr.beginTile() method if self.projectionType==self.ORTHOGRAPHIC: self.PerspectiveToOrthogonal() else: self.SetupProjectionMatrix() if self.renderMode == GL_RENDER: # This activate has to be done here, else we get a # GLXBadContextState on the alpha. If we are in # GL_SELECT mode we did already an activate in DoPick # here we need to restore the camrea's GLstate if self.viewer and len(self.viewer.cameras) > 1: #self.SetupProjectionMatrix() self.fog.Set(enabled=self.fog.enabled) r,g,b,a = self.backgroundColor glClearColor(r, g, b, a ) self.RedrawAASwitch() while 1: errCode = glGetError() if not errCode: break errString = gluErrorString(errCode) print 'GL ERROR: %d %s' % (errCode, errString) def glError(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() while 1: errCode = glGetError() if not errCode: return errString = gluErrorString(errCode) print 'GL ERROR: %d %s' % (errCode, errString) def SetupLights(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ loops over the lights and sets the direction and/or position of a light only if it is enabled and the flag is set to positive. Also, if there is more than one camera, it always sets the lights that are on""" for l in self.viewer.lights: if l.enabled is True: if len(self.viewer.cameras) > 1: if l.positional is True: glLightfv(l.num, GL_POSITION, l.position) glLightfv(l.num, GL_SPOT_DIRECTION, l.spotDirection) else: # directional glLightfv(l.num, GL_POSITION, l.direction) else: if l.positional is True: if l.posFlag: glLightfv(l.num, GL_POSITION, l.position) l.posFlag = 0 if l.spotFlag: glLightfv(l.num, GL_SPOT_DIRECTION, l.spotDirection) l.spotFlag = 0 else: #directional if l.dirFlag: #rot = Numeric.reshape(self.rotation, (4,4)) #dir = Numeric.dot(l.direction, rot).astype('f') #glLightfv(l.num, GL_POSITION, dir) glLightfv(l.num, GL_POSITION, l.direction) l.dirFlag = 0 #self.posLog.append(l.direction) #print 'setting light to ',l.direction ## l.posFlag = 0 ## l.spotFlag = 0 def activeStereoSupport(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() try: root = Tkinter.Tk() root.withdraw() loadTogl(root) Tkinter.Widget(root, 'togl', (), {'stereo':'native'} ) #currentcontext = self.tk.call(self._w, 'contexttag') #print "StandardCamera.activeStereoSupport currentcontext", currentcontext if GL.glGetIntegerv(GL.GL_STEREO)[0] > 0: lReturn = True else: #print 'Stereo buffering is not available' lReturn = False Tkinter.Widget(root, 'togl', (), {'stereo':'none'} ) return lReturn except Exception, e: if str(e)=="Togl: couldn't get visual": #print 'Stereo buffering is not available:', e lReturn = False elif str(e)=="Togl: couldn't choose stereo pixel format": #print 'Stereo buffering is not available:', e lReturn = False else: print 'something else happend',e lReturn = False Tkinter.Widget(root, 'togl', (), {'stereo':'none'} ) return lReturn try: import pymedia.video.vcodec as vcodec class RecordableCamera(StandardCamera): """Subclass Camera to define a camera supporting saving mpg video """ def __init__(self, master, screenName, viewer, num, check=1, cnf={}, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() StandardCamera.__init__( self, *(master, screenName, viewer, num, check, cnf), **kw) # this attribute can be 'recording', 'autoPaused', 'paused' or 'stopped' self.videoRecordingStatus = 'stopped' self.videoOutputFile = None self.pendingAutoPauseID = None self.pendingRecordFrameID = None self.encoder = None self.autoPauseDelay = 1 # auto pause after 1 second self.pauseLength = 15 # if recording pauses automatically # add self.pauseLength frames will be added # when recording resumes self.videoRecorder = None self.nbRecordedframes = 0 self.vidimage = None def setVideoOutputFile(self, filename='out.mpg'): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # open the file self.videoOutputFile = open( filename, 'wb' ) assert self.videoOutputFile, 'ERROR, failed to open file: '+filename def setVideoParameters(self, width=None, height=None, pauseLength=0, autoPauseDelay=1, outCodec = 'mpeg1video'): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # make sure image is dimensions are even if width is None: width = self.width w = self.videoFrameWidth = width - width%2 if height is None: height = self.height h = self.videoFrameHeight = height - height%2 if h != self.height or w != self.width: self.Set(width=w, height=h) ## FIXME here we should lock the size of the Camera ## params= { 'type': 0, 'gop_size': 12, 'frame_rate_base': 125, 'max_b_frames': 0, 'width': w, 'height': h, 'frame_rate': 2997,'deinterlace': 0, #'bitrate': 9800000, 'id': vcodec.getCodecID(outCodec) } ## params= { 'type': 0, 'gop_size': 12, 'frame_rate_base': 125, ## 'max_b_frames': 0, 'width': w, 'height': h, ## 'frame_rate': 2997,'deinterlace': 0, 'bitrate': 2700000, ## 'id': vcodec.getCodecID( 'mpeg1video' ) ## } if outCodec== 'mpeg1video': params['bitrate']= 2700000 else: params['bitrate']= 9800000 self.encoder = vcodec.Encoder( params ) self.pauseLength = pauseLength self.autoPauseDelay = autoPauseDelay def start(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # toggle to recording mode if self.videoOutputFile is None or self.encoder is None: return self.videoRecordingStatus = 'recording' self.nbRecordedframes = 0 self.viewer.master.after(1, self.recordFrame) def recordFrame(self, force=False, imageFile=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not self.viewer.hasRedrawn and not force: return root = self.viewer.master if self.videoRecordingStatus=='paused': self.pendingRecordFrameID = root.after(1, self.recordFrame) return ## if self.videoRecordingStatus=='autopaused': ## # add frames for pause ## #print 'adding %d pause frames --------------', self.pauseLength ## imstr = self.lastFrame.tostring() ## for i in range(self.pauseLength): ## bmpFrame = vcodec.VFrame( ## vcodec.formats.PIX_FMT_RGB24, self.lastFrame.size, ## (imstr, None, None)) ## yuvFrame = bmpFrame.convert(vcodec.formats.PIX_FMT_YUV420P) ## self.videoOutputFile.write( ## self.encoder.encode(yuvFrame).data) ## self.videoRecordingStatus = 'recording' if self.videoRecordingStatus=='recording' or force: if self.pendingAutoPauseID: print 'auto pause id', self.pendingAutoPauseID root.after_cancel(self.pendingAutoPauseID) self.pendingAutoPauseID = None # if DejaVu.enableSSAO is True and self.ssao :#and self.vidimage is not None: # image = self.GrabFrontBuffer(lock=False) # else : image = self.GrabFrontBuffer(lock=False) # FIXME this resizing can be avoided if camera size is locked image = image.resize((self.videoFrameWidth, self.videoFrameHeight)) self.lastFrame = image bmpFrame = vcodec.VFrame( vcodec.formats.PIX_FMT_RGB24, image.size, (self.lastFrame.tostring(), None, None)) #print "bmp rate_base", bmpFrame.rate_base, "rate:", bmpFrame.rate, "bitrate", bmpFrame.bitrate, "size:", bmpFrame.size yuvFrame = bmpFrame.convert(vcodec.formats.PIX_FMT_YUV420P) #print "yuv rate_base", yuvFrame.rate_base, "rate:", yuvFrame.rate, "bitrate", yuvFrame.bitrate, "size:", yuvFrame.size self.videoOutputFile.write(self.encoder.encode(yuvFrame).data) #self.pendingAutoPauseID = root.after(self.autoPauseDelay*1000, # self.autoPause) if imageFile != None: image.save(imageFile) self.viewer.hasRedrawn = False self.pendingRecordFrameID = root.after(1, self.recordFrame) self.nbRecordedframes += 1 def Redraw(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() StandardCamera.Redraw(self) self.viewer.hasRedrawn = True self.recordFrame() def autoPause(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print 'autoPause ==========================' self.videoRecordingStatus = 'autoPaused' if self.pendingRecordFrameID: root = self.viewer.master root.after_cancel(self.pendingRecordFrameID) self.pendingAutoPauseID = None def pause(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print 'pause ==========================' self.videoRecordingStatus = 'paused' if self.pendingRecordFrameID: root = self.viewer.master root.after_cancel(self.pendingRecordFrameID) self.pendingAutoPauseID = None def stop(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.videoRecordingStatus = 'stopped' self.videoOutputFile.close() root = self.viewer.master if self.pendingAutoPauseID: root.after_cancel(self.pendingAutoPauseID) if self.pendingRecordFrameID: root.after_cancel(self.pendingRecordFrameID) Camera = RecordableCamera except ImportError: Camera = StandardCamera mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/ColorWheel.py0000644000175000017500000001662611120056642022312 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/ColorWheel.py,v 1.10 2008/12/11 00:24:02 vareille Exp $ # # $Id: ColorWheel.py,v 1.10 2008/12/11 00:24:02 vareille Exp $ # import types import Tkinter import numpy.oldnumeric as Numeric import math import colorTool import Slider from EventHandler import CallbackFunctions from DejaVu.colorTool import ToHSV class ColorWheel(CallbackFunctions): def MakeWheelGeometry(self): """Compute vertex coordinates to draw the wheel's color patches""" # makes the master circle r = float(self.radius / self.circles) angle = 2.0 * math.pi / self.stripes c = Numeric.zeros( (self.stripes+1,2),'f' ) c[0][0] = c[self.stripes][0] = r; c[0][1] = c[self.stripes][1] = 0.0; for i in range(1, self.stripes): c[i][0] = r * math.cos(i*angle); c[i][1] = r * math.sin(i*angle); # now build the color wheel geometry # center point self.centerX = self.width / 2 self.centerY = self.height / 2 self.c[0][0] = self.centerX self.c[0][1] = self.centerY nco = 1 # strips+1 points on a circle (first point == last point) for j in range(1,self.circles+1): for i in range(self.stripes+1): self.c[nco][0] = self.centerX + (j * c[i][0]) self.c[nco][1] = self.centerY + (j * c[i][1]) nco = nco+1 def MakeWheelColors(self, intensity): """build the array of colors to draw a wheel""" self.hsvColor[2] = intensity Hinc = 1.0 / float(self.stripes) Sinc = 1.0 / float(self.circles) # center color self.rgbCol[0][0] = self.rgbCol[0][1] = self.rgbCol[0][2] = intensity ncol = 1; # now make the wheel colors for j in range(1,self.circles+1): s = j * Sinc; for i in range(self.stripes): self.rgbCol[ncol] = colorTool.ToRGB( (i*Hinc, s, intensity) ) ncol = ncol+1 def DrawWheel(self): """draw the color wheel""" c = self.c col = self.tkColors # draw center circle as triangle fan for i in range(1, self.stripes+1): self.canvas.create_polygon( c[0][0], c[0][1], c[i][0], c[i][1], c[i+1][0], c[i+1][1], fill = col[i], outline = col[i], tag='wheel' ) s = self.stripes ncol = self.stripes+1 for i in range(1,self.circles): c1 = 1 + (i-1)*s + i-1 c2 = c1 + s + 1 k = ncol for j in range(self.stripes): self.canvas.create_polygon( c[c1+1+j][0], c[c1+1+j][1], c[c1+j][0], c[c1+j][1], c[c2+j][0], c[c2+j][1], c[c2+j+1][0], c[c2+j+1][1], fill = col[ncol], outline = col[ncol], tag='wheel' ) ncol = ncol+1 def DrawCursor(self): """Compute cursor position from hsv value and draw it""" rad = self.hsvColor[1] * self.radius angle = 2.0 * math.pi * self.hsvColor[0] x = self.centerX + int(rad * math.cos(angle)) y = self.centerY + int(rad * math.sin(angle)) dx = x-self.cursorX dy = y-self.cursorY self.canvas.move( 'cursor', dx, dy) self.cursorX = self.cursorX + dx self.cursorY = self.cursorY + dy def _MoveCursor(self, x, y): # find the saturation based on distance s = math.sqrt(x*x + y*y) / self.radius if s > 1.0: s = 1.0 x = x / s y = y / s # now find the hue based on the angle if x or y: angle = math.atan2(y, x) if angle < 0.0: angle = angle + (2.0 * math.pi) h = angle / (2.0 * math.pi) else: h = 0 # check if redraw and callback are needed if self.hsvColor[0] != h or self.hsvColor[1] != s: if type(self.hsvColor) == types.TupleType: self.hsvColor = list(self.hsvColor) self.hsvColor[0] = h; self.hsvColor[1] = s; self.DrawCursor() if self.immediate: self.Callbacks() def MoveCursor(self, event=None): """Compute the new color for the cursor position, redraw cursor""" x = event.x - self.width*0.5 y = event.y - self.height*0.5 self._MoveCursor(x,y) def Callbacks(self): """Implement callback functions """ rgb = colorTool.ToRGB(self.hsvColor) for f in self.callbacks: f( colorTool.OneColor(rgb, self.alpha) ) def Get(self, mode='HSV'): """Get the current color""" if mode == 'RGB': rgb = colorTool.ToRGB(self.hsvColor) return colorTool.OneColor(rgb) elif mode == 'HSV': return colorTool.OneColor(self.hsvColor) elif mode == 'TkRGB': col = Numeric.array(colorTool.ToRGB(self.hsvColor[:3]), 'f') * 255 return colorTool.TkColor(col) def Set(self, color, mode='HSV', run=True): """Set the current color """ assert len(color) in (3,4) color2 = colorTool.OneColor(color) if mode=='RGB': color2 = colorTool.ToHSV(color[:3]) if len(color)==4: self.alpha = color[3] else: self.alpha = 1.0 if color2[2] != self.hsvColor[2] and self.wysiwyg: self.BuildWheel(color2[2]) self.hsvColor = color2 self.DrawCursor() if self.immediate and run: self.Callbacks() def BuildWheel(self, value): """Compute the colors, convert them to Tk, draw wheel, draw cursor""" self.canvas.delete('wheel') self.canvas.delete('cursor') self.MakeWheelColors(value) self.tkColors = map( colorTool.TkColor, self.rgbCol*255 ) self.DrawWheel() cx = self.cursorX cy = self.cursorY cs = self.cursorSize self.canvas.create_line( cx-cs, cy-cs, cx+cs, cy-cs, cx+cs, cy+cs, cx-cs, cy+cs, cx-cs, cy-cs, width=2, fill='black', tag = 'cursor') def setWysiwyg(self, onOff): """Toggle Wysiwyg mode. When on, wheel colors are recomputed""" assert onOff in (0,1) self.wysiwyg = onOff if onOff: self.BuildWheel(self.hsvColor[2]) else: self.BuildWheel(1.0) def setImmediate(self, onOff): """Toggle Wysiwyg mode. When on, wheel colors are recomputed""" assert onOff in (0,1) self.immediate = onOff def __init__(self, parent, width=100, height=100, radius=None, circles=5, stripes=10, immediate=1, wysiwyg=0, wheelPad=10, startingColorRGB=(1,1,1,1)): CallbackFunctions.__init__(self) self.width = width self.height = height self.wheelPad = wheelPad if radius is None: self.radius = max(width,height) / 2 else: self.radius = min( max(width,height) / 2, self.radius ) self.circles = circles self.stripes = stripes self.wysiwyg = wysiwyg self.immediate = immediate self.ncol = 1 + self.circles * (self.stripes + 1) self.rgbCol = Numeric.zeros( (self.ncol,3), 'f' ) self.c = Numeric.zeros( (self.ncol,2), 'f' ) self.MakeWheelGeometry() self.hsvColor = Numeric.array(ToHSV(startingColorRGB)) self.cursorX = self.centerX self.cursorY = self.centerY self.cursorSize = 2 self.alpha = 1.0 self.canvas = Tkinter.Canvas(parent, relief=Tkinter.SUNKEN, width = self.width, height = self.height) self.BuildWheel(1.0) self.canvas.pack(padx=wheelPad, pady=wheelPad, side=Tkinter.RIGHT, expand='no') self.canvas.bind( "<1>", self.MoveCursor) self.canvas.bind( "", self.MoveCursor) if not immediate: self.canvas.bind( "", self.MouseUp) self.callbacks = [] self.DrawCursor() if __name__ == '__main__': def MyCallback(color): print color def MyCallback2(color): print 'hello' root = Tkinter.Tk() cw = ColorWheel(root) cw.AddCallback(MyCallback) cw1 = ColorWheel(root, immediate=0) cw1.AddCallback(MyCallback2) cw2 = ColorWheel(root, immediate=0) cw1.AddCallback(MyCallback) cw2.AddCallback(MyCallback2) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/GleObjects.py0000644000175000017500000003543511532033110022257 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER, Sophie Coon # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # $Header: /opt/cvs/python/packages/share1.5/DejaVu/GleObjects.py,v 1.34 2011/02/25 23:07:52 annao Exp $ # # $Id: GleObjects.py,v 1.34 2011/02/25 23:07:52 annao Exp $ # DEBUG = False try: import gle except: if DEBUG: print 'Sorry you need the GLE extension module' from DejaVu.viewerFns import checkKeywords from DejaVu.Geom import Geom from DejaVu.triangle_strip import Triangle_strip from opengltk.OpenGL import GL import numpy.oldnumeric as Numeric class GleObject(Triangle_strip): keywords = Triangle_strip.keywords + [ 'normalStyle', 'joinStyle' ] def __init__(self, name=None, check=1, **kw): self.normalStyle = gle.TUBE_NORM_PATH_EDGE self.joinStyle = gle.TUBE_JN_ANGLE apply( Triangle_strip.__init__, (self, name, check), kw) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ if kw.has_key('materials') and kw['materials'] is not None: materials = Numeric.array((kw['materials']),'f') else: materials = Numeric.array(((0.,0.,1.,1.),),'f') redoFlags = apply( Triangle_strip.Set, (self, check, 0), kw ) nm = kw.get( 'normalStyle') # nm can be TUBE_NORM_FACET, TUBE_NORM_EDGE, TUBE_NORM_PATH_EDGE if nm: self.normalStyle = self.normalStyle & ~gle.TUBE_NORM_MASK self.normalStyle = self.normalStyle | nm gle.gleSetJoinStyle (self.normalStyle | self.joinStyle) ja = kw.get( 'joinStyle') # ja can be TUBE_JN_RAW, TUBE_JN_ANGLE, TUBE_JN_CUT, TUBE_JN_ROUND, # TUBE_JN_CAP if ja: self.joinStyle = self.joinStyle & ~gle.TUBE_JN_MASK self.joinStyle = self.joinStyle | ja gle.gleSetJoinStyle (self.normalStyle | self.joinStyle) return self.redoNow(redo, updateOwnGui, redoFlags) def extrude(self): """Virtual Method to do the extrusion along a 3D path with a 2D shape using the gle extrusion. We then get the geometry information using the extrusion method in Feedback mode. This will then be used to build a triangle strip.""" pass def asIndexedPolygons(self, run=1, quality=None, **kw): """ run=0 returns 1 if this geom can be represented as an IndexedPolygon and None if not. run=1 returns the IndexedPolygon object.""" if run==0: return 1 # yes, I can be represented as IndexedPolygons faces = self.faceSet.faces.array verts = self.vertexSet.vertices.array size = faces.shape # number of triangles in each face (containing triangle strip # vertices) from faces array. ntr = size[1]-2 # new length of triangles array nfaces = size[0]*ntr new_faces = Numeric.zeros((nfaces, 3), 'i') i = 0 for f in faces: for n in range(ntr): if (n/2)*2 == n: new_faces[i] = [f[n], f[n+1], f[n+2]] else: new_faces[i] = [f[n+2], f[n+1], f[n]] i = i + 1 from DejaVu.IndexedPolygons import IndexedPolygons new_obj = IndexedPolygons('gleobj', vertices = verts, faces = new_faces, visible=1, invertNormals=self.invertNormals) return new_obj class GleExtrude(GleObject): keywords = GleObject.keywords + [ 'shape2D', 'trace3D', 'contourUp', 'capsFlag' ] def __init__(self, name=None, check=1, **kw): if __debug__: if check: apply( checkKeywords, (name,self.keywords), kw) apply( GleObject.__init__, (self, name, 0), kw) self.Set(trace3D = kw.get('trace3D'), shape2D = kw.get('shape2D'), contourUp = kw.get( 'contourUp'), capsFlag = kw.get('capsFlag')) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = 0 capsFlag = kw.get('capsFlag') if capsFlag is None: if not hasattr(self, 'capsFlag'): self.capsFlag = 0 else: self.capsFlag = capsFlag shape2D = kw.get('shape2D') if shape2D is None: if not hasattr(self, 'shape2D'): self.shape2D = None else: self.shape2D = shape2D contourUp = kw.get('contourUp') if contourUp is None: if not hasattr(self, 'contourUp'): self.contourUp= (0.,0.,1.) else: self.contourUp = contourUp trace3D = kw.get('trace3D') if trace3D is None: if not hasattr(self, 'trace3D'): self.trace3D = Numeric.zeros( (0,3), 'f') else: self.trace3D = trace3D if kw.has_key('materials') and kw['materials'] is not None: materials = Numeric.array((kw['materials']),'f') redoFlags |= self._redoFlags['redoDisplayListFlag'] else: materials = Numeric.array(((0.,0.,1.,1.),),'f') if not shape2D is None: v,n,s = self.extrude() if self.capsFlag == 1: v, n, s = self.addCaps(v, n, s) redoFlags |= self._redoFlags['redoDisplayListFlag'] if v is not None: kw['vertices']=v if n is not None: kw['vnormals']=n if s is not None: kw['stripBegin']=[0] + list( s[:-1,0] ) kw['stripEnd'] = list( s[:,0]) redoFlags |= apply( GleObject.Set, (self, check, 0), kw ) return self.redoNow(redo, updateOwnGui, redoFlags) def addCaps(self, v, n, s): """ Method to add front and end caps to the extruded geometry.""" # calculate the length of each strip lenStrip = 2*self.shape2D.lenShape # 1- Front Cap: #================ # Get the midPoint of the front cap frontMid = self.trace3D[1] # Get the coordinates of the contourPoints of the cap shapePoints = v[1:lenStrip:2] # Organize the points so the strip creates the cap frontCapPts = [] for point in shapePoints.tolist(): frontCapPts.append(point) frontCapPts.append(frontMid) # Add the new strip to the front of the vertices vertices = Numeric.concatenate( (frontCapPts, v) ) #Compute normal of the cap by computing the cross product of (M3 M1). if self.shape2D.vertDup == 0: fm1 = shapePoints[0] - frontMid fm3 = shapePoints[1] - frontMid elif self.shape2D.vertDup == 1: fm1 = shapePoints[0] - frontMid fm3 = shapePoints[2] - frontMid # Cross product nc = [[(fm3[1]*fm1[2] - fm3[2]*fm1[1]), (fm3[0]*fm1[2] - fm3[2]*fm1[0]), (fm3[0]*fm1[1] - fm3[0]*fm1[1])],] frontNorm = Numeric.array(nc*lenStrip, 'd') # Add the normals to the normal array normals = Numeric.concatenate( (frontNorm, n) ) lastVert = s[-1][0]+lenStrip strip = Numeric.concatenate((s, [[lastVert,lastVert],])) # 2- End cap: #================ # Get the midPoint of the end cap endMid = self.trace3D[-2] # Get the coordinates of the contourPoints of the last cap endShape = v[-lenStrip:-1:2] # Organize the points so the strip creates the cap endCapPts = [] # Definition of the strip for point in endShape.tolist(): endCapPts.append(endMid) endCapPts.append(point) # Add the new strip to the front of the vertices vertices = Numeric.concatenate( (vertices, endCapPts) ) #Compute normal of the cap by computing the cross product of 2 vectors\ # defined by the mid cap point and a point of the shape. if self.shape2D.vertDup == 0: em1 = endShape[0] - endMid em3 = endShape[1] - endMid elif self.shape2D.vertDup == 1: em1 = endShape[2] - endMid em3 = endShape[0] - endMid # Cross product nc = [[(em3[1]*em1[2] - em3[2]*em1[1]), (em3[0]*em1[2] - em3[2]*em1[0]), (em3[0]*em1[1] - em3[0]*em1[1])],] endNorm = Numeric.array(nc*lenStrip, 'd') # Add the normals to the normal array normals = Numeric.concatenate( (normals, endNorm) ) lastVert = strip[-1][0]+lenStrip strip = Numeric.concatenate((strip, [[lastVert,lastVert],])) return vertices, normals, strip def extrude(self): """Virtual Method to do the extrusion along a 3D path with a 2D shape using the gle extrusion. We then get the geometry information using the extrusion method in Feedback mode. This will then be used to build a triangle strip.""" from gle import glec gle.gleSetJoinStyle ( self.normalStyle | self.joinStyle ) glec.gleFeedBack() contpts = Numeric.array(self.shape2D.contpts) contourPoints = contpts[:,:2] contnorm = Numeric.array(self.shape2D.contnorm) contourNormals = contnorm[:,:2] gle.gleExtrusion(contourPoints, contourNormals, self.contourUp, self.trace3D, self.materials[1028].prop[0][:,:3] ) glec.gleTextureMode(0) v,n,s = glec.gleGetTriangleMesh() vinv = Numeric.zeros( v.shape, 'd') vinv[::2] = v[1::2] vinv[1::2] = v[::2] ninv = Numeric.zeros( n.shape, 'd') ninv[::2] = n[1::2] ninv[1::2] = n[::2] return vinv, ninv, s def getFaces(self): """returns a handle to the faces array""" return self.IndexedFaceSet.faces.array # # WARNING the extrusion in this object ONLY works after this object has # been added to a viewer # class GlePolyCylinder(GleExtrude): keywords = GleExtrude.keywords + [ 'trace3D', 'radius' ] def __init__(self, name=None, check=1, **kw): if __debug__: if check: apply( checkKeywords, (name,self.keywords), kw) r = kw.get('radius') if not r: r=1.0 self.radius = r apply( GleExtrude.__init__, (self, name, 0), kw) self.Set(trace3D = kw.get( 'trace3D')) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( GleExtrude.Set, (self, check, 0), kw) if kw.has_key('materials') and kw['materials'] is not None: materials = Numeric.array((kw['materials']),'f') else: materials = Numeric.array(((0.,0.,1.,1.),),'f') self.trace3D = kw.get('trace3D') if not self.trace3D: v,n,s = (None,None,None) redoFlags |= self._redoFlags['redoDisplayListFlag'] else: v,n,s = self.extrude() redoFlags |= self._redoFlags['redoDisplayListFlag'] if v is not None: kw['vertices']=v if n is not None: kw['vnormals']=n if s is not None: kw['stripBegin']=[0] + list( s[:,0] ) return self.redoNow(redo, updateOwnGui, redoFlags) def extrude(self): """Virtual Method to do the extrusion along a 3D path with a 2D shape using the gle extrusion. We then get the geometry information using the extrusion method in Feedback mode. This will then be used to build a triangle strip.""" from gle import glec gle.gleSetJoinStyle ( self.joinStyle | self.normalStyle ) glec.gleFeedBack() #DisplayFunction of the old GlePolyCylinder GL.glColorMaterial (GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT) GL.glEnable (GL.GL_COLOR_MATERIAL) #glEnable(GL_LIGHTING) if self.viewer is not None: self.viewer.enableOpenglLighting() colors = self.materials[GL.GL_FRONT].prop[0][:,:3] gle.glePolyCylinder(self.trace3D, colors, self.radius) GL.glDisable (GL.GL_COLOR_MATERIAL) glec.gleTextureMode(0) v,n,s = glec.gleGetTriangleMesh() return v,n,s class GlePolyCone(GlePolyCylinder): keywords = GleExtrude.keywords + [ 'trace3D', 'radii' ] def __init__(self, name=None, check=1, **kw): if __debug__: if check: apply( checkKeywords, (name,self.keywords), kw) apply( GlePolyCylinder.__init__, (self, name, 0), kw ) apply( self.Set, (), kw) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( GlePolyCylinder.Set, (self, check, 0), kw ) r = kw.get('radii') if r is not None: assert len(r) self.radii = r return self.redoNow(redo, updateOwnGui, redoFlags) def extrude(self): """Extrude a cone with radii specified at each point of the extrusion""" assert len(self.radii)==len(self.trace3D) from gle import glec gle.gleSetJoinStyle ( self.joinStyle | self.normalStyle ) glec.gleFeedBack() #DisplayFunction of the old GlePolyCylinder GL.glColorMaterial (GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT) GL.glEnable (GL.GL_COLOR_MATERIAL) if self.viewer is not None: self.viewer.enableOpenglLighting() colors = self.materials[GL.GL_FRONT].prop[0][:,:3] gle.glePolyCone(self.trace3D, colors, self.radii) GL.glDisable (GL.GL_COLOR_MATERIAL) glec.gleTextureMode(0) v,n,s = glec.gleGetTriangleMesh() return v,n,s mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/0000755000175000017500000000000012146210043023302 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/animationGUI.py0000644000175000017500000014411112064444610026212 0ustar debiandebianimport os import Tkinter, Pmw #from DejaVu.GeomChooser import GeomChooser from mglutil.util.callback import CallbackFunction from DejaVu.scenarioInterface.animations import FlyInObjectMAA, FlyOutObjectMAA,\ FadeInObjectMAA, FadeOutObjectMAA, VisibleObjectMAA, ColorObjectMAA,\ RotationMAAOptionsGUI, RotationMAA, RockMAA, SnapshotMAAGroup # from DejaVu.scenarioInterface.animations import FocusMAA from Scenario2.gui.Tk.clipboard import ClipboardGUI from Scenario2.sequenceAnimator import SequenceAnimator from Scenario2.gui.Tk.sequenceAnimator import SequenceAnimatorGUI from Scenario2 import _clipboard, _MAATargets from DejaVu.states import setRendering, getRendering, getOrientation from DejaVu.scenarioInterface.animations import OrientationMAA, RenderingTransitionMAA from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel class MAAEditor: """ Editor for an MAA the base class provides mainly the buttons at the bottom of the form the .edit(maa) method will save the maa in self.maa, show the form and configure it with the paramters gotten from the maa using maa.getValues(). when OK or Preview are clicked the execute method has to configure self.maa and run the maa for Preview subclass will implement: populateForm() to add gui elements to self.dialog.interior() getValues() to return a dictionary of parameter names and values setValues() to take a dictionary of parameter names and values show them in the editor execute(name) to configure self.maa and run it for Preview """ def __init__(self, master=None, title='Editor', buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK'): """ base class bur creating MAA editors editorObject <- MAAEditor( maa, master=None, title='Editor', buttons=['OK','Preview', 'Cancel'], defaultButton='OK') - maa is the MAA instance for which we want to see and modify params - master can be used to specify where to place the GUI. If master is None: if showOptionForm was called as callback from a Tk event, the dialog just below the button that was clicked else the dialogue will appear at position 100, 100 - title is the title of the Editor window - buttons is a list of string specifying which buttons to create at the bottom of the dialog - defaultButton is a string that appears in buttons and will be set as the default button for the form """ self.master = master self.maa = None # will be set in self.edit(maa) self.exitStatus = None # will be saet to the name of the button # save list of desired buttons assert len(buttons)>0 self.buttons = buttons assert defaultButton in buttons self.defaultButtons = defaultButton # save the title assert isinstance(title, str) self.title = title # create the dialog self.dialog = self.createGUI() self.populateForm() def createGUI(self): """ Create the form. This base class form is a Pmw dialog containing a set of Radiobuttons and a counter to select speed of animation(number of frames) """ self.balloon = Pmw.Balloon(self.master) # create the Dialog dialog = Pmw.Dialog( self.master, buttons=self.buttons, defaultbutton='OK', title=self.title, command=self.execute) dialog.withdraw() # create a frame to hold group to force setting orient and rendering bframe = Tkinter.Frame(dialog.interior()) ## ## create group to define if action sets orients self.actionGrp = grp = Pmw.Group(bframe, tag_text='Action sets') frame = grp.interior() self.forcew = w = Pmw.RadioSelect( frame, selectmode='multiple', orient='horizontal', buttontype='checkbutton') for text in ['Orientation', 'Rendering']: w.add(text) w.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) grp.pack(side = 'left', fill='x', expand=1) self.balloon.bind(grp, "When an action is created the current orientation and rendering are saved.\nCheck these buttons to have the action set the orientation\nand/or Rendering on its first frame during playback") ## ## create a group of buttons to overwrite self.recordGrp = grp = Pmw.Group(bframe, tag_text='Record:') frame = grp.interior() b1 = Tkinter.Button(frame, text='Orientation', command=self.recordOrient) b1.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) b2 = Tkinter.Button(frame, text='Rendering', command=self.recordRendering) b2.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) grp.pack(side = 'bottom', fill='x', expand=1) self.balloon.bind(grp, "Record current orientation/rendering for this action") bframe.pack( fill='x', expand=1) return dialog def recordOrient(self, event=None): self.maa.recordOrient() def recordRendering(self, event=None): self.maa.recordRendering() def edit(self, maa, event=None): self.maa = maa # configure the editor with current values self.setValues( **maa.getValues() ) # activate and place the dialog just below the button that was clicked: if event: x = event.x_root y = event.y_root if y + self.master.winfo_height() > self.master.winfo_screenheight(): y = self.master.winfo_screenheight() - self.master.winfo_height() #dialog.activate(globalMode = 'grab', geometry = '+%d+%d' % (x, y )) # does not work self.dialog.activate(geometry = '+%d+%d' % (x, y )) else: self.dialog.activate(geometry = '+%d+%d' % (100, 100 )) if self.exitStatus=='OK': return self.getValues() elif self.exitStatus in ('None', 'Cancel'): return None def _hide(self): self.dialog.deactivate() def execute(self, name): # called when buttons are clicked ot windows is closed self.exitStatus = name if name in ('None', 'Cancel', 'OK'): self._hide() ## ## the following methods should be subclassed ## def populateForm(self): """ subclassses will place GUI items for various parameters in this method """ return def getValues(self): """ return a dictionary of parameterName:parameterValues """ return {} def setValues(self, **kw): """ take a dictionary of parameterName:parameterValues set the editor to these values """ return class MAAEditorWithSpeed(MAAEditor): """ Sub class adding basic animation force orient/rendering and speed GUI """ def __init__(self, master=None, title='Orientation Editor', buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK', speedDict =None): """ Provides a dialog form for setting Orientation actions parameters speedDict: dictionary of speed anmes and nbframes (constr only) The following parameters are handled by getValues and setValues: nbFrames: int """ if speedDict is None: speedDict = {'slow': 50, 'medium': 30, 'fast': 10} self.speedDict = speedDict self.custom_speed_flag = False self.speed = 'medium' MAAEditor.__init__(self, master=master, title=title, buttons=buttons, defaultButton=defaultButton) def populateForm(self): """ added radiobuttons for speed dict and custom speed """ # create group for speed parent = self.dialog.interior() grp = Pmw.Group(parent, tag_text='speed (in frames)') frame = grp.interior() self.speedw = sp = Pmw.RadioSelect( frame, selectmode='single', orient='horizontal', buttontype='radiobutton', command=self.setSpeed_cb) for text in ['slow', 'medium', 'fast', 'custom']: sp.add(text) sp.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) for key, val in self.speedDict.items(): self.balloon.bind(sp.button(key), "%d frames"%val) # add counter for overall custom speed self.speedcr = cr = Pmw.Counter( frame, entry_width=6, entryfield_value=100, entryfield_validate = {'validator':'integer', 'min':1 }) self.balloon.bind(cr, "Enter overall number of frames") cr.pack(side = 'left', anchor = 'w', fill = 'x', expand = 1) grp.pack(side='top', fill='x', expand=1 ) def setSpeed_cb(self, val=None): if val == "custom": self.custom_speed_flag = True else: self.custom_speed_flag = False self.setCounterState() def setCounterState(self): cr = self.speedcr entry = cr._counterEntry._entryFieldEntry up = cr._upArrowBtn down = cr._downArrowBtn if self.custom_speed_flag: # activate counter entry.configure(state='normal') down.bind('', cr._countDown) up.bind('', cr._countUp) else: # deactivate: entry.configure(state='disabled') down.unbind('') up.unbind('') def getValues(self): kw = {'forceOrient':False, 'forceRendering':False} sp = self.speedw.getvalue() if sp == "None": return kw if sp == "custom": nbFrames = int(self.speedcr.get()) else: nbFrames = self.speedDict[sp] kw['nbFrames'] = nbFrames for val in self.forcew.getvalue(): if val=='Orientation': kw['forceOrient'] = True elif val=='Rendering': kw['forceRendering'] = True return kw def setValues(self, **kw): """ configure the option form with the values provided in **kw keys can be: 'nbFrames', 'easeInOut', 'direction' """ forceList = [] # if kw has kfpos use last frame in list as nbframes kfpos = kw.pop('kfpos', None) if kfpos: kw['nbFrames'] = kfpos[-1]-kfpos[0] for k,v in kw.items(): if k == 'nbFrames': assert int(v) assert v>0 # set speed radio button found = False for name, speed in self.speedDict.items(): if speed==v: self.speedw.invoke(name) found = True break if not found: self.speedw.invoke('custom') self.speedcr.setvalue(v) elif k == 'forceOrient' and v: forceList.append('Orientation') elif k == 'forceRendering' and v: forceList.append('Rendering') #else: # print 'WARNING: unknown key:value',k,v self.forcew.setvalue(forceList) def execute(self, name): # called when buttons are clicked ot windows is closed self.exitStatus = name if name in ('None', 'Cancel', 'OK'): self._hide() values = self.getValues() self.maa.forceOrient = values['forceOrient'] self.maa.forceRendering = values['forceRendering'] class SSp_MAAEditor(MAAEditorWithSpeed): """ Editor providing speed, and sortPoly parameters """ def populateForm(self): """ add radio buttons for direction and easeInOut """ MAAEditorWithSpeed.populateForm(self) parent = self.dialog.interior() grp = Pmw.Group(parent, tag_text='Zsort Polygons') frame = grp.interior() ordergrp = Pmw.Group(frame, tag_pyclass = None) ordergrp.pack(side = 'left', fill='x', expand=1) self.sortOrderw = Pmw.RadioSelect( ordergrp.interior(), selectmode='single', orient='horizontal', buttontype='radiobutton') for text in ['+Zsort', '-Zsort']: self.sortOrderw.add(text) self.sortOrderw.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) self.balloon.bind(self.sortOrderw, "-Z sorts by furthest Z first,\n+Z sorts by closest Z first") whengrp = Pmw.Group(frame, tag_pyclass = None) whengrp.pack(side = 'left', fill='x', expand=1) self.sortPolyw = w = Pmw.RadioSelect( whengrp.interior(), selectmode='single', orient='horizontal', buttontype='radiobutton') for text in ['Never', 'Once', 'Always']: w.add(text) w.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) self.balloon.bind(w, "Select when to Z-sort polygons for proper trancparency") grp.pack(side = 'left', fill='x', expand=1) def getValues(self): """ return a dictionary of parameterName:parameterValues """ values = MAAEditorWithSpeed.getValues(self) values.update({'sortPoly': self.sortPolyw.getvalue(), 'sortOrder': self.sortOrderw.getvalue()}) return values def setValues(self, **kw): """ take a dictionary of parameterName:parameterValues set the editor to these values """ MAAEditorWithSpeed.setValues(self, **kw) self.sortPolyw.setvalue(kw['sortPoly']) self.sortOrderw.setvalue(kw['sortOrder']) class OrientationMAAEditor(MAAEditorWithSpeed): def __init__(self, master=None, title='Orientation Editor', buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK'): """ Provides a dialog form for setting Orientation actions parameters parameters: keyframes: [0, a,b,c] """ MAAEditorWithSpeed.__init__( self, master=master, title=title, buttons=buttons, defaultButton=defaultButton) def populateForm(self): """ add entryfield for 3 integers to specify 3 intervals """ MAAEditorWithSpeed.populateForm(self) # add 3 custom intervals entry form parent = self.dialog.interior() grp = Pmw.Group(parent, tag_text='Custom intervals') frame = grp.interior() self._3intw = Pmw.EntryField( frame, labelpos = 'w', value = '10 20 30', label_text = 'nb frames for zoom out, rotate, zoom in:', validate = self.custom_validate) self._3intw.pack(side='top') self.balloon.bind(self._3intw, "Enter 3 space-separated integers\ndefining the zoom out, rotate, and zoom in intervals\ne.g. 10 20 30 means zoom out for 10 frames, rotate for 10 and zoom in for 10") grp.pack(side = 'top', fill='x', expand=1 ) def custom_validate(self, text): words = text.split() if len(words)!=3: return -1 a,b,c = map(int, words) if a>0 and b > a and c>b: return 1 else: return -1 def setSpeed_cb(self, val=None): # set self._3intw based on the selected speed val = MAAEditorWithSpeed.getValues(self).get('nbFrames',None) if val: self._3intw.setentry("%d %d %d"%(val/3, 2*val/3, val)) def getValues(self): """ return a dictionary of parameterName:parameterValues """ a,b,c = map(int, self._3intw.getvalue().split()) kw = {'keyframes':[0,a,b,c], 'forceOrient':False, 'forceRendering':False} for val in self.forcew.getvalue(): if val=='Orientation': kw['forceOrient'] = True elif val=='Rendering': kw['forceRendering'] = True return kw def setValues(self, **kw): """ take a dictionary of parameterName:parameterValues set the editor to these values """ zero, a, b, c = kw['keyframes'] found = False for name, value in self.speedDict.items(): if c==value: self.speedw.invoke(name) found = True break if not found: self.speedw.invoke('custom') self.speedcr.setvalue(value) return def execute(self, name): # configure the MAA with the values from the editor MAAEditorWithSpeed.execute(self, name) if name in ('OK', 'Preview'): self.maa.setKeyframePositions( self.getValues()['keyframes'] ) if name == 'Preview': self.maa.run() class SnapshotMAAGroupEditor(SSp_MAAEditor): def __init__(self, master=None, title='Snapshot Editor', buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK'): """ Provides a dialog form for setting Snapshot actions parameters parameters: keyframes: [kf1, kf2] """ SSp_MAAEditor.__init__( self, master=master, title=title, buttons=buttons, defaultButton=defaultButton) self.actionGrp._tag.configure(text='Interpolate') self.balloon.bind(self.actionGrp, "Check these buttons to interpolate orientation/rendering during playback.") def getValues(self): """ return a dictionary of parameterName:parameterValues """ #print "snapshot getValues" kw = SSp_MAAEditor.getValues(self) nbframes = kw.get('nbFrames',None) if nbframes is not None: kw.pop('nbFrames') kw['keyframes'] = [0, nbframes] orient = kw.get('forceOrient', None) if orient is not None: kw['forceOrient'] = False kw['interpolateOrient'] = orient rend = kw.get('forceRendering', None) if rend is not None: kw['forceRendering'] = False kw['interpolateRendering'] = rend return kw def setValues(self, **kw): """ take a dictionary of parameterName:parameterValues set the editor to these values """ k1, k2 = kw['keyframes'] found = False for name, value in self.speedDict.items(): if k2==value: self.speedw.invoke(name) found = True break if not found: self.speedw.invoke('custom') self.speedcr.setvalue(k2) forceList = [] if kw.get('interpolateOrient'): forceList.append('Orientation') if kw.get('interpolateRendering'): forceList.append('Rendering') self.forcew.setvalue(forceList) self.sortPolyw.setvalue(kw['sortPoly']) if kw.has_key('sortOrder'): self.sortOrderw.setvalue(kw['sortOrder']) def execute(self, name): #print "snapshot execute" # configure the MAA with the values from the editor MAAEditorWithSpeed.execute(self, name) self.maa.sortPoly = sortPoly = self.sortPolyw.getvalue() self.maa.renderMaa.sortPoly = sortPoly self.maa.orientMaa.sortPoly = sortPoly self.maa.sortOrder = sortOrder = self.sortOrderw.getvalue() self.maa.renderMaa.sortOrder = sortOrder self.maa.orientMaa.sortOrder = sortOrder values = self.getValues() if values.has_key('interpolateRendering'): self.maa.interpolateRendering = values['interpolateRendering'] if values.has_key('interpolateOrient'): self.maa.interpolateOrient = values['interpolateOrient'] if name in ('OK', 'Preview'): self.maa.setKeyframePositions( self.getValues()['keyframes'] ) if name == 'Preview': self.maa.run() class SE_MAAEditor(MAAEditorWithSpeed): """ Editor providing speed and easeInOut parameters """ def __init__(self, master=None, title='Speed EaseInOut Editor', buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK', speedDict =None, ): self.easeInEnd = 0.3 self.easeOutStart = 0.7 MAAEditorWithSpeed.__init__(self, master=master, title=title, buttons=buttons, defaultButton=defaultButton, speedDict=speedDict) def populateForm(self): """ add radio buttons for direction and easeInOut """ MAAEditorWithSpeed.populateForm(self) parent = self.dialog.interior() grp = Pmw.Group(parent, tag_text='Ease In/Out') frame = grp.interior() self.easew = w = Pmw.RadioSelect( frame, selectmode='single', orient='horizontal', buttontype='radiobutton', command=self.setEase_cb) for text in ['none', 'ease in', 'ease out', 'ease in and out']: w.add(text) w.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) self.balloon.bind(w, "Ease in will slow down the start of the action,\n ease out will slow down the end of the action") self.easeInEndTw = ThumbWheel( frame, width=70, height=14, type=float,oneTurn=1.0, value=self.easeInEnd, continuous=False, wheelPad=1, min=0.0, max = 1.0, callback=self.setEaseInEnd_cb, labCfg = {'text': 'easeInEnd', 'side':'top'}, increment=0.1, showLabel=0, lockShowLabel=1) self.easeInEndTw.pack(side = 'left', anchor = 'w', fill = 'x', expand = 1) self.balloon.bind(self.easeInEndTw, """ 'ease in' occurs from 0 to EaseInEnd (in range [0, 1])""") self.easeOutStartTw = ThumbWheel( frame, width=70, height=14, type=float,oneTurn=1.0, value=self.easeOutStart, continuous=False, wheelPad=1, min=0.0, max = 1.0, callback=self.setEaseOutStart_cb, labCfg = {'text': 'easeOutStart', 'side':'top'}, increment=0.1, showLabel=0, lockShowLabel=1) self.easeOutStartTw.pack(side = 'left', anchor = 'w', fill = 'x', expand = 1) self.balloon.bind(self.easeOutStartTw, """ 'ease out' occurs from easeOutStart to 1(in range [0, 1])""") grp.pack(side = 'top', fill='x', expand=1) def getValues(self): """ return a dictionary of parameterName:parameterValues """ values = MAAEditorWithSpeed.getValues(self) nbFrames = values.pop('nbFrames') self.easeInEnd = self.easeInEndTw.get() self.easeOutStart = self.easeOutStartTw.get() easeInOut = self.easew.getvalue() if easeInOut == "ease in and out": if self.easeOutStart < self.easeInEnd: self.easeOutStart = self.easeInEnd values.update( {'kfpos': [0,nbFrames], 'easeInOut': self.easew.getvalue(), 'easeInEnd': self.easeInEnd, 'easeOutStart': self.easeOutStart} ) #print "SE_MAAEditor, getValues:", values return values def setValues(self, **kw): """ take a dictionary of p self.easeOutStart: self.easeOutStart = self.easeInEnd self.enableThumbWheel(self.easeInEndTw, self.easeInEnd) self.enableThumbWheel(self.easeOutStartTw, self.easeOutStart) else: self.disableThumbWheel(self.easeInEndTw) self.disableThumbWheel(self.easeOutStartTw) def setEaseInEnd_cb(self, val): self.easeInEnd = val def setEaseOutStart_cb(self, val): self.easeOutStart=val def disableThumbWheel(self, tw): """disables a thumbwheel widgets used to specify easeInEnd and easeOutStart""" def foo(val): pass tw.configure(showLabel=0) tw.canvas.bind("", foo) tw.canvas.bind("", foo) tw.canvas.bind("", foo) tw.canvas.bind("", foo) def enableThumbWheel(self, tw, val=None): """enables a thumbwheel widgets used to specify easeInEnd and easeOutStart""" tw.canvas.bind("", tw.mouseDown) tw.canvas.bind("", tw.mouseUp) tw.canvas.bind("", tw.mouseMove) tw.canvas.bind("", tw.toggleOptPanel) tw.configure(showLabel=1) if val: tw.set(val, update=0) def execute(self, name): # configure the MAA with the values from the editor MAAEditorWithSpeed.execute(self, name) if name in ('OK', 'Preview'): self.maa.configure( **self.getValues() ) if name == 'Preview': self.maa.run() class SED_MAAEditor(SE_MAAEditor): """ Editor providing speed, easeInOut and direction parameters """ def __init__(self, master=None, title='Editor', directions=['left', 'right'], buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK', speedDict=None, addEaseInOut=True): """ Provides a dialog form for setting Fly actions parameters parameters: kfpos: [a,b] 2 integer key frame positions direction: can be 'left', 'right', 'top', or 'bottom' easeInOut: can be 'none', 'ease in', 'ease out', 'ease in and out' speedDict: dictionary of speed anmes and nbframes (constr. only) """ self.directions = directions self.addEaseInOut = addEaseInOut if addEaseInOut: SE_MAAEditor.__init__( self, master=master, title=title, buttons=buttons, defaultButton=defaultButton, speedDict=speedDict) else: MAAEditorWithSpeed.__init__(self, master=master, title=title, buttons=buttons, defaultButton=defaultButton, speedDict=speedDict) def populateForm(self): """ add radio buttons for direction and easeInOut """ if self.addEaseInOut: SE_MAAEditor.populateForm(self) else: MAAEditorWithSpeed.populateForm(self) parent = self.dialog.interior() grp = Pmw.Group(parent, tag_text='Direction') frame = grp.interior() self.directionw = w = Pmw.RadioSelect( frame, selectmode='single', orient='horizontal', buttontype='radiobutton') for text in self.directions: w.add(text) w.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) grp.pack(side = 'top', fill='x', expand=1) self.balloon.bind(w, "Select the action direction") def getValues(self): """ return a dictionary of parameterName:parameterValues """ if self.addEaseInOut: values = SE_MAAEditor.getValues(self) else: values = MAAEditorWithSpeed.getValues(self) nbFrames = values.pop('nbFrames') values.update( {'kfpos': [0,nbFrames]}) values.update({'direction': self.directionw.getvalue()}) #print 'SED_MAAEditor, getValues:', values return values def setValues(self, **kw): """ take a dictionary of parameterName:parameterValues set the editor to these values """ if self.addEaseInOut: SE_MAAEditor.setValues(self, **kw) else: MAAEditorWithSpeed.setValues(self, **kw) self.directionw.setvalue(kw['direction']) #print 'SED_MAAEditor, setValues:', kw class SESp_MAAEditor(SE_MAAEditor): """ Editor providing speed, easeInOut and sortPoly parameters """ def populateForm(self): """ add radio buttons for direction and easeInOut """ SE_MAAEditor.populateForm(self) parent = self.dialog.interior() grp = Pmw.Group(parent, tag_text='Zsort Polygons') frame = grp.interior() ordergrp = Pmw.Group(frame, tag_pyclass = None) ordergrp.pack(side = 'left', fill='x', expand=1) self.sortOrderw = Pmw.RadioSelect( ordergrp.interior(), selectmode='single', orient='horizontal', buttontype='radiobutton') for text in ['+Zsort', '-Zsort']: self.sortOrderw.add(text) self.sortOrderw.pack(side='top', anchor='w', fill='x', expand=1, padx=8, pady=8) self.balloon.bind(self.sortOrderw, "-Zsort sorts by furthest z first,\n+Zsort sorts by closest z first") whengrp = Pmw.Group(frame, tag_pyclass = None) whengrp.pack(side = 'left', fill='x', expand=1) self.sortPolyw = w = Pmw.RadioSelect( whengrp.interior(), selectmode='single', orient='horizontal', buttontype='radiobutton') for text in ['Never', 'Once', 'Always']: w.add(text) w.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) self.balloon.bind(w, "Select when to Z-sort polygons for proper trancparency") grp.pack(side = 'top', fill='x', expand=1) def getValues(self): """ return a dictionary of parameterName:parameterValues """ values = SE_MAAEditor.getValues(self) values.update({'sortPoly': self.sortPolyw.getvalue(), 'sortOrder': self.sortOrderw.getvalue()}) #print "SESp_MAAEditor getValues:", values return values def setValues(self, **kw): """ take a dictionary of parameterName:parameterValues set the editor to these values """ SE_MAAEditor.setValues(self, **kw) self.sortPolyw.setvalue(kw['sortPoly']) self.sortOrderw.setvalue(kw['sortOrder']) #print "SESp_MAAEditor setValues:", kw from mglutil.gui.BasicWidgets.Tk.colorWidgets import ColorChooser class SECol_MAAEditor(SE_MAAEditor): """ Editor providing speed, easeInOut parameters and ColorChooser widget """ def __init__(self, master=None, title='Colors Editor', buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK', speedDict =None, choosecolor = False): self.choosecolor = choosecolor self.color = None SE_MAAEditor.__init__( self, master=master, title=title, buttons=buttons, defaultButton=defaultButton, speedDict=speedDict) def populateForm(self): """ add radio buttons for direction and easeInOut """ SE_MAAEditor.populateForm(self) if self.choosecolor: parent = self.dialog.interior() self.colorChooser = ColorChooser(master = parent, commands = self.setColor_cb) self.colorChooser.pack(side = "top") def setColor_cb(self, colors): self.color = colors def getValues(self): """ return a dictionary of parameterName:parameterValues """ values = SE_MAAEditor.getValues(self) if self.choosecolor: if self.color: values['color'] = [self.color,] #print "SECol_MAAEditor getValues", values return values class Rotation_MAAEditor(SED_MAAEditor): """ Editor providing Rotation animation parameters """ def __init__(self, master=None, title='Rotation Editor', directions=['counter clockwise', 'clockwise'], buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK', speedDict=None, addEaseInOut=True): """ Provides a dialog form for setting Rotation action parameters parameters: nbFrames: number of keyframes angle: rotation angular amplitude in degrees vector: rotation axis direction: can be 'counter clockwise' or 'clockwise' easeInOut: can be 'none', 'ease in', 'ease out', 'ease in and out' """ SED_MAAEditor.__init__( self, master=master, title=title, buttons=buttons, defaultButton=defaultButton, directions=directions, speedDict=speedDict, addEaseInOut=addEaseInOut) def populateForm(self): """ add counter for angle and GUI for rotation vector """ SED_MAAEditor.populateForm(self) parent = self.dialog.interior() # Create and pack the dropdown ComboBox for axis grp = Pmw.Group(parent, tag_text='rotation axis') axes = self.axes = ('X', 'Y', 'Z', 'XY', 'XZ', 'YZ', 'XYZ') self.axisDropdownw = w = Pmw.ComboBox( grp.interior(), scrolledlist_items=axes) w.pack(side='left', anchor='n', fill='x', expand=1, padx=8, pady=8) w.selectitem('Y') grp.pack(side = 'top', fill='x', expand=1) grp = Pmw.Group(parent, tag_text='rotation angle') self.anglew = w = Pmw.Counter( grp.interior(), entry_width=6, entryfield_value = 360, entryfield_validate = {'validator':'real', 'min' : 1 } ) w.pack(side='left', anchor='w', fill='x', expand=1, padx=8, pady=8) grp.pack(side = 'top', fill='x', expand=1) #self.balloon.bind(w, "Select when to Z-sort polygons for proper trancparency") def getVector(self): """ return (x, y, z) vector according to axis widget value """ axis = self.axisDropdownw.getvalue()[0] if axis=='X': vector = (1., 0., 0.) elif axis=='Y': vector = (0., 1., 0.) elif axis=='Z': vector = (0., 0., 1.) elif axis=='XY': vector = (1., 1., 0.) elif axis=='XZ': vector = (1., 0., 1.) elif axis=='YZ': vector = (0., 1., 1.) elif axis=='XYZ': vector = (1., 1., 1.) return vector def getAxis(self, vector): """ return axis anme based in (x, y, z) vector """ x,y,z = vector if x==1 and y==0 and z==0: return 'X' elif x==0 and y==1 and z==0: return 'Y' elif x==0 and y==0 and z==1: return 'Z' elif x==1 and y==1 and z==0: return 'XY' elif x==0 and y==1 and z==1: return 'YZ' elif x==1 and y==0 and z==1: return 'XZ' elif x==1 and y==1 and z==1: return 'XYZ' else: return 'custom' def getValues(self): """ return a dictionary of parameterName:parameterValues """ values = SED_MAAEditor.getValues(self) nbFrames = values.pop('kfpos')[-1] values.update({'nbFrames':nbFrames, 'angle': float(self.anglew.get()), 'vector': self.getVector(), } ) #print "Rotation_MAAEditor, getValues:", values return values def setValues(self, **kw): """ take a dictionary of parameterName:parameterValues set the editor to these values """ SED_MAAEditor.setValues(self, **kw) self.axisDropdownw.selectitem(self.getAxis(kw['vector'])) self.anglew.setvalue(kw['angle']) #print "Rotation_MAAEditor, setValues:", kw class Rock_MAAEditor(Rotation_MAAEditor): """ Editor providing Rock animation paramters """ def __init__(self, master=None, title='Rock Editor', directions=['counter clockwise', 'clockwise'], buttons=['OK', 'Preview', 'Cancel'], defaultButton='OK', addEaseInOut=False): """ Provides a dialog form for setting Rotation action parameters parameters: nbFrames: number of keyframes angle: rotation angular amplitude in degrees vector: rotation axis direction: can be 'counter clockwise' or 'clockwise' easeInOut: can be 'none', 'ease in', 'ease out', 'ease in and out' """ Rotation_MAAEditor.__init__( self, master=master, title=title, buttons=buttons, defaultButton=defaultButton, directions=directions, speedDict={'slow': 60, 'medium': 30, 'fast': 10}, addEaseInOut=addEaseInOut) ## def expandGeoms(geoms): ## newgeoms = [] ## for g in geoms: ## for child in g.AllObjects(): ## if len(child.getVertices())>0 and child.visible: ## newgoms.append( child ) ## return newgeoms class orientationGUI: """ Scrolled frame holding orientations (snapshots) """ def __init__(self, viewer, viewerName, master=None): """ orientationGUI constructor orientationGUIObject <- orientationGUI(viewer, viewerName, master=None) """ self.viewer = viewer self.viewerName = viewerName #self.orientations = {} self.snapshots = {} self.nbOrients = 0 self.master = master self.row = 0 self.col = 0 self.speedDict = {'slow': 50, 'medium': 30, 'fast': 10} #self.editor = OrientationMAAEditor(master=master) self.editor = SnapshotMAAGroupEditor(master=master) self.modifyOrient = Tkinter.IntVar() self.modifyOrient.set(1) self.modifyRendering = Tkinter.IntVar() self.modifyRendering.set(1) self.forceRendering = Tkinter.BooleanVar() self.forceRendering.set(False) self.createGUI() self._animNB = None # will become a reference to the AnimationNotebook instance self.nButtonsRow = 5 def createGUI(self): """ Create a ScrolledFrame to old orientations entries """ if self.master is None: self.master = master = Tkinter.Toplevel() self.ownsMaster = True else: self.ownsMaster = False self.balloon = Pmw.Balloon(self.master) # create a group with a button to record an orientation w = self.orientsContainer = Pmw.Group( self.master, tag_pyclass = Tkinter.Button, tag_text='Record Snapshot') w.configure(tag_command = self.recordOrient) # create a scrolled frame to display recorded orientation w1 = self.MAAContainer = Pmw.ScrolledFrame( w.interior(), usehullsize=0, hull_width=40, hull_height=200, vscrollmode='dynamic', hscrollmode='none') w1.pack(padx=5, pady=3, fill='both', expand=1) w.pack(fill='both', expand=1, padx = 6, pady = 6) # bind right button to show option form editor button = w.component('tag') button.bind('', self.startEditor) def startEditor(self, event=None): objString = self.viewerName+'.rootObject' #orient = getOrientation(object) orient = None rendering = getRendering(self.viewer, checkAnimatable=True) orientMaa = OrientationMAA(self.viewer.rootObject, 'temp', orient, rendering, objectFromString=objString) kfpos = [orientMaa.firstPosition, orientMaa.lastPosition] renderMaa = RenderingTransitionMAA(self.viewer, rendering, kfpos=kfpos, startFlag = "with previous") maa = SnapshotMAAGroup(orientMaa, renderMaa,"snapshot%d"% (self.nbOrients+1, ) ) values = self.editor.edit(maa) if values: self.nbOrients += 1 self.saveMAA(maa) def recordOrient(self, event=None): """ build default orientation transition (left clicks) """ self.nbOrients += 1 object = self.viewer.rootObject #orient = getOrientation(object) orient = None rendering = getRendering(self.viewer, checkAnimatable=True) #maa1 = OrientationMAA(object, 'orient%d'% self.nbOrients, orient, rendering, # objectFromString=self.viewerName+'.rootObject') orientMaa = OrientationMAA(object, 'temp', orient, rendering, objectFromString=self.viewerName+'.rootObject') kfpos = [orientMaa.firstPosition, orientMaa.lastPosition] renderMaa = RenderingTransitionMAA(self.viewer, rendering, kfpos=kfpos, startFlag = "with previous") maa = SnapshotMAAGroup(orientMaa, renderMaa,"snapshot%d"%self.nbOrients ) self.saveMAA(maa) def saveMAA(self, maagroup): """ adds MAA to the list and adds a button for it in the panel """ assert isinstance(maagroup, SnapshotMAAGroup) if not maagroup.name: maagroup.name = "snapshot%d"%self.nbOrients snName = self.checkName(maagroup.name) if maagroup.name != snName: maagroup.name = snName orientMaa = maagroup.orientMaa renderMaa = maagroup.renderMaa renderMaa._animNB = self._animNB orientMaa.name = snName+"orient" renderMaa.name = snName+"rendering" self.snapshots[snName] = maagroup self.addOrientButton(maagroup) def checkName(self, name): """check if the name exists in the self.snapshots or in the sequence player. If exists - create unique name""" allnames = self.snapshots.keys() ## if self._animNB: ## for maa, pos in self._animNB().seqAnim.maas: ## if maa.name not in allnames: ## allnames.append(maa.name) if name in allnames: i = 1 while(name in allnames): name = name+"_%d"%i i = i+1 return name def addOrientButton(self, maa): master = self.MAAContainer.interior() if hasattr(maa, 'ims') and maa.ims is not None: import ImageTk photo = ImageTk.PhotoImage(maa.ims) else: self.viewer.master.lift() self.viewer.master.master.lift() self.viewer.OneRedraw() photo, ims = self.viewer.GUI.getButtonIcon() maa.ims = ims b = Tkinter.Button(master=master ,compound='left', image=photo, command=CallbackFunction(self.runMaa, maa)) b.photo = photo b.name = maa.name b.grid(row = self.row, column = self.col, sticky = 'nsew') b.bind('', CallbackFunction( self.showOrientMenu_cb, maa)) self.balloon.bind(b, maa.name) if self.col == self.nButtonsRow-1: self.col = 0 self.row = self.row + 1 else: self.col = self.col + 1 def runMaa(self, maagroup): orient = maagroup.orientMaa render = maagroup.renderMaa #print "run maa:", maagroup.name, 'force rendering:', orient.forceRendering if orient.forceRendering: setRendering(orient.viewer, orient.rendering) orient.run() else: #modify (morph) rendering #render.setValuesAt(0) #render.run() #orient.run() maagroup.run() def editMaa_cb(self, maagroup): values = self.editor.edit(maagroup) #check if the maa has been added to the sequence animator: animNB = self._animNB() for i , _maa in enumerate(animNB.seqAnim.maas): if _maa[0] == maagroup: position = _maa[1] animNB.seqAnimGUI.update(i, position) return def setForceRendering(self, orient, event = None): #print "setForceRendering", self.forceRendering.get() orient.forceRendering = self.forceRendering.get() def showOrientMenu_cb(self, maagroup, event=None): """ Create button menu and post it """ # create the button menu orient = maagroup.orientMaa render = maagroup.renderMaa #orient, render = maagroup.maas menu = Tkinter.Menu(self.master, title = orient.name) #cb = CallbackFunction(self.setForceRendering, orient) #self.forceRendering.set(orient.forceRendering) #menu.add_checkbutton(label="Force Rendering", # var = self.forceRendering, # command=cb) from Scenario2 import addTargetsToMenu #addTargetsToMenu(menu, [orient, render]) #addTargetsToMenu(menu, maagroup) cb = CallbackFunction(self.addAsTransition_cb, maagroup) #menu.add_command(label="Add to animation as transition", command = cb) menu.add_command(label="Add to animation", command = cb) #cb = CallbackFunction(self.addAsKeyframe_cb, maagroup) #menu.add_command(label="Add to animation as keyframe", command = cb) cb = CallbackFunction(self.editMaa_cb, maagroup) menu.add_command(label="Edit", command = cb) cb = CallbackFunction(self.renameOrient_cb, maagroup) menu.add_command(label="Rename", command = cb) cb = CallbackFunction(self.removeOrient_cb, maagroup) menu.add_command(label="Delete", command = cb) menu.add_command(label="Dismiss") menu.post(event.x_root, event.y_root) def addToClipboard(self, orient, render=None): """ adds this orientation animation to the clipboard """ _clipboard.addMaa(orient) if render is not None: _clipboard.addMaa(render) def addAsTransition_cb(self, maagroup): kf1, kf2 = maagroup.kfpos #if kf2 - kf1 <=1: # values = self.editor.edit(maagroup) self._animNB().seqAnim.addMAA(maagroup) def addAsKeyframe_cb(self, maagroup): maagroup.setKeyframePositions([0, 1]) self._animNB().seqAnim.addMAA(maagroup) def renameOrient_cb(self, maagroup): name = maagroup.name container = self.MAAContainer.interior() from tkSimpleDialog import askstring newname = askstring("Rename %s"%name, "Enter new name:", initialvalue = name, parent = container) if newname != None and newname != name: if self.snapshots.has_key(newname): from tkMessageBox import showwarning showwarning("Warning", "Name %s already exists"%newname,parent = self.master) return #find cooresponding button, rename it and update the bindings: self.snapshots.pop(name) self.snapshots[newname] = maagroup maagroup.name = newname orient = maagroup.orientMaa render = maagroup.renderMaa #orient, render = maagroup.maas orient.name = newname+"orient" render.name = newname+"rendering" for b in container.grid_slaves(): if hasattr(b, "name"): if b.name == name: b.name = newname self.balloon.bind(b, newname) break seqmaas = [maa[0] for maa in self._animNB().seqAnim.maas] if maagroup in seqmaas: self._animNB().seqAnimGUI.refreshGUI() def removeOrient_cb(self, maagroup): orientB = None name = maagroup.name frame = self.MAAContainer.interior() for b in frame.grid_slaves(): if hasattr(b, "name"): if b.name == name: orientB = b break if orientB: # check if this maa has been added to the sequence animator: seqAnim = self._animNB().seqAnim seqmaas = [maa[0] for maa in seqAnim.maas] ind = None if maagroup in seqmaas: # ask the user i f he really wants to delete this snapshot # since it will be removed from the sequence animator too: import tkMessageBox ok = tkMessageBox.askokcancel("Delete %s?"%name,"%s is in Sequence Anim.\nThis will also remove the snapshot from Sequence Anim."%name) if not ok: return ind = seqmaas.index(maagroup) orientB.destroy() # regrid the buttons to fill the space freed by the removed button : buttons = frame.grid_slaves() # the widgets in this list # seem to be stored in "last created, first in the list" order buttons.reverse() col = 0 row = 0 for i, b in enumerate(buttons): b.grid(row=row, column= col, sticky='nsew') if col == self.nButtonsRow-1: col = 0 row = row + 1 else: col = col + 1 self.col = col self.row = row # remove the orient entry from self.orientations self.snapshots.pop(name) if ind != None: # remove from sequence anim. seqAnim.removeMAA(maagroup, seqAnim.maas[ind][1]) def getSavedMaas(self): maas = [] for b in reversed(self.MAAContainer.interior().grid_slaves()): if hasattr(b, "name"): name = b.name if self.snapshots.has_key(name): maas.append(self.snapshots[name]) return maas mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/animations.py0000644000175000017500000050761212064445143026043 0ustar debiandebian""" This module provide objects building DejaVu animation in the form of MultipleActorsActions objects """ import math, numpy, copy from Scenario2.multipleActorsActions import MultipleActorsActions, MAAGroup from Scenario2.keyframes import KFValueFromFunction, KFAutoCurrentValue, \ Interval, KF from Scenario2.interpolators import matToQuaternion from DejaVu import Viewer from DejaVu.scenarioInterface import getActor from DejaVu.scenarioInterface.actor import RedrawActor from DejaVu.scenarioInterface.actor import DejaVuAxisConcatRotationActor from DejaVu.states import getRendering, getOrientation, setRendering from mglutil.math.rotax import rotax from mglutil.util.callback import CallbackFunction import types from DejaVu.scenarioInterface.actor import getActorName ## For an MAA object ot be editable the folllowing conditions must be met: ## 1 - the MAA has a .editorClass set to the class of the editor for this MAA ## 2 - the folloing method have to work ## MAA.getValues() ## MAAEditor.setValuest(**kw) ## MAAEditor.getValues() ## MAAEditor.execute(self, name) has to configure self.maa ## with the current parameters (MAAEditor.getValues() ) def expandGeoms(geoms): newgeoms = [] try: len(geoms) except: geoms = [geoms] for g in geoms: allObjects = g.AllObjects() if len(allObjects) == 1 and len(allObjects[0].getVertices())>0 : obj = allObjects[0] if hasattr(obj, "animatable") and obj.animatable == True: newgeoms.append(allObjects[0]) else: for child in allObjects: if len(child.getVertices())>0 and child.visible: if hasattr(child, "animatable") and child.animatable == True: newgeoms.append( child ) return newgeoms def getObjectName(objects): """Create a string representing the objects name. objects - list of one or more DejaVu geom. objects""" name = "" for object in objects: try: objectName = object.fullName if objectName.split("|")[-1] != 'root': if objectName.find('root') == 0: if not len(name): name = objectName[5:] else: name = name + ";" + objectName[5:] break except: pass return name def getObjectFromString(objects): objectFromString = None try: objectFromString = "[" for object in objects: objectFromString = objectFromString + "viewer.FindObjectByName('%s'), " % object.fullName objectFromString = objectFromString + "]" except: objectFromString = None return objectFromString def numarr2str(val): """Returns a string representing the input numeric array""" assert type(val) == numpy.ndarray dims = val.shape if len(dims) == 1: _valstr = "%.4f,"*dims[0] % tuple(val) valstr = "array([" + _valstr + "], '%s')" % val.dtype.char elif len(dims) == 2: _valstr = ("[" + "%.4f," * dims[1] +"],") * dims[0] % tuple(val.flatten()) valstr = "array([" + _valstr + "], '%s')" % val.dtype.char else: threshold = numpy.get_printoptions()["threshold"] numpy.set_printoptions(threshold=val.size) valstr = "array(" + numpy.array2string(val, precision =4, separator =",") + ", '%s')"%val.dtype.char #valstr.replace("\n", "\n\t") numpy.set_printoptions(threshold=threshold) return valstr def comparefloats(a, b, precision = 0.0001 ): """Compare two float scalars or arrays""" aa = numpy.ravel(numpy.array(a)) bb = numpy.ravel(numpy.array(b)) if len(aa) == len(bb) == 0: return True if len(aa) != len(bb): return False diff = numpy.abs(aa-bb) if diff.max() > precision: return False ## mask0 = aa == 0 ## masknz = aa != 0. ## if numpy.any(mask0): ## if diff[mask0].max()> 0.: ## return False ## if numpy.any(masknz): ## if (diff[masknz]/aa[masknz]).max() > precision: ## return False return True ## ## MAA building classes ## from DejaVu.Spheres import Spheres from DejaVu.Cylinders import Cylinders from DejaVu.IndexedGeom import IndexedGeom from time import time class RenderingTransitionMAA(MultipleActorsActions): """ MMA containing a RedrawActor for a DejaVu Viewer and actors to morph between representations """ def __init__(self, viewer, rendering = None, kfpos=[0,30], name='morphRepr', startFlag='after previous', saveAtomProp=True): """ constructor MAA <- RenderingTransitionMAA(viewer, name='morphRepr', startFlag='after previous') viewer is a DejaVu Viewer Object name is a string used to name this RedrawMAA startFlag - flag used in a sequence animator for computing time position of the maa . the MultipleActorsActions (MAA) is built with a RedrawActor for the viewer. The name of the RedrawActor name is 'redraw'+viewer.uniqID. """ assert isinstance(viewer, Viewer) MultipleActorsActions.__init__(self, name=name, startFlag=startFlag) redrawActor = RedrawActor(viewer) self.viewer = viewer self.redrawActor = self.addActor(redrawActor) self.forceRendering = False self.rendering = rendering self.sortPoly = 'Once' self.sortOrder = "-Zsort" self.editorClass = None self.kfpos = kfpos self.firstPosition = kfpos[0] self.lastPosition = kfpos[1] self._maaGroup = None # will be a weakref to MAAGroup self.atomSets = {} self.msmsPtrs = {} self._animNB = None if saveAtomProp: try: self.saveGeomAtomProp() except: pass def makeMAA(self, rendering, kfpos): self.kfpos = kfpos if not self.rendering: return # build list of differences r1 = rendering r2 = self.rendering viewer = self.viewer if kfpos[-1] - kfpos[0] == 1: from DejaVu.scenarioInterface.actor import DejaVuActor actor = DejaVuActor("viewer.rendering", viewer.rootObject, setFunction=lambda actor, val:setRendering(actor.object.viewer, val) ) #kf1 = KF(self.kfpos[-1], r2) kf1 = KF(self.kfpos[0], r2) actor.actions.addKeyframe(kf1) self.AddActions( actor, actor.actions ) return modDict = {} appear = [] disappear = [] for g in viewer.rootObject.AllObjects(): #print 'IIIIIIIIIIIIII', g.name r1g = r1.get(g.fullName, None) r2g = r2.get(g.fullName, None) if r1g is None and r2g is None: continue if r1g is not None and r2g is not None and \ r1g['visible']==0 and r2g['visible']==0: continue elif r1g is None: #print "1111, add to appear", g.name appear.append(g) elif r1g['visible'] == 0: if r2g is not None : # g appears if r2g.has_key('faces') and len(r2g['faces']) == 0: continue mod = self.compareGeomState(r1g,r2g) if mod.has_key('vertices') or mod.has_key('faces'): modDict[g] = mod else: #print "2222, add to appear", g.name appear.append(g) elif r2g is None: ff = r1g.get('faces', None) if ff is not None: if len(ff) != 0: #print "3333 add to disappear", g.name disappear.append(g) else: vv = r1g.get('vertices', None) if vv is not None and len(vv) != 0: #print "4444 add to disappear", g.name disappear.append(g) elif r2g['visible']==0: # g disappears #print "5555 add to disappear", g.name disappear.append(g) else: mod = self.compareGeomState(r1g,r2g) if len(mod): modDict[g] = mod # create actors for objects that appear for obj in appear: #print 'APPEAR', obj.name self.appear(obj) # create actors for objects that disappear for obj in disappear: #print 'DISAPPEAR', obj.name self.disappear(obj) # loop over geometries and their modes: for g,mod in modDict.items(): scissorvals = {} keys = mod.keys() gname = g.fullName #print 'JJJJJJJJJJJJJJJJJ', gname, keys if mod.has_key('vertices'): #print "VERTICES" # create actors for "Spheres" or "Indexed Geoms" objects that have different vertex sets # in rendering 1 and 2 if (isinstance(g, Spheres) or isinstance(g, IndexedGeom)): visibleactor = getActor(g, 'visible') #kf1 = KF(self.kfpos[0]+1, 1) kf1 = KF(self.kfpos[0], 1) visibleactor.actions.addKeyframe(kf1) self.AddActions( visibleactor, visibleactor.actions ) # Since AddActions() creates a clone of visible actor - find the actual visible actor #visibleactor = self.findActor(visibleactor) #if len(visibleactor.actions.keyframes) == 2: # visibleactor.actions.keyframes.pop(0) # we are going to create 3 keyframes. # first keyframe sets the vertex union of both renderings(and corresponding values for colors, opacity, radii and faces) #second keyframe sets opacity and colors . #The opacity and colors are interpolated between two first frames , #so that the object in rendering 1 is fading out while the object in rendering 2 # is fading in . # Last keyframe sets the vertices (and faces) of the second (destination) rendering. val1 = {} # first keyframe values val3 = {} #last (third) keyframe values vv1 = mod['vertices'][1] # vertices of the first rendering vv2 = mod['vertices'][2] # vertices of the second rendering vnorms = None if mod.has_key('vnormals'): vnorms = mod['vnormals'][2] nvert1 = len(vv1) nvert2 = len(vv2) # 'radii' radiiactor = None rad1 = rad2 = None if r1[gname].has_key("radii"): radiiactor = getActor(g, "radii") rad1 = r1[gname]["radii"] rad2 = r2[gname]["radii"] val3['radii'] = rad2 # 'colors' col1 = numpy.array(r1[gname]["rawMaterialF"]["diffuse"], numpy.float32)[:,:3] ncol1 = len(col1) if ncol1 == 1 or ncol1 != nvert1: col1 = numpy.array([col1[0]] *nvert1 ,'f') col2 = numpy.array(r2[gname]["rawMaterialF"]["diffuse"], numpy.float32)[:,:3] ncol2 = len(col2) if ncol2 == 1 or ncol2 != nvert2: col2 = numpy.array([col2[0]] *nvert2 ,'f') #'opacity' #op1 = numpy.array(r1[gname]["rawMaterialF"]['opacity'], "f") op1 = numpy.array(r1[gname]["rawMaterialF"]['diffuse'], "f")[:,3] if len(op1) != nvert1: op1 = numpy.ones(nvert1).astype('f') if len(op1) == 1: n = op1[0] op1 = numpy.ones(nvert1).astype('f')*n #op2 = numpy.array(r2[gname]["rawMaterialF"]['opacity'], "f") op2 = numpy.array(r2[gname]["rawMaterialF"]['diffuse'], "f")[:,3] if len(op2) != nvert2: op2 = numpy.ones(nvert2).astype('f') if len(op2) == 1: n = op2[0] op2 = numpy.ones(nvert2).astype('f')*n vis1 = r1[gname].get('visible') #get values for the first two keyframes if isinstance(g, Spheres): # get arrays of vertices, faces, radii, opacities , colors for # the first keyframe and arrays of opacities and colors for # the second keyframe verts1, radii, opacity1, opacity2, colors1, colors2 =\ self.getSpheresTransitionValues(g, vv1, vv2, op1, op2, col1, col2, rad1, rad2, visible1 = vis1) else: # IndexedGeom f1 = numpy.array(r1[gname]["faces"], 'f') f2 = numpy.array(r2[gname]["faces"], 'f') if len(f1) and len(f2): # get arrays of vertices, faces, radii, opacities , colors for # the first keyframe and arrays of opacities and colors for # the second keyframe verts1, faces1, radii, opacity1, opacity2, colors1, colors2 = \ self.getIndGeomsTransitionValues(g, vv1, vv2, op1, op2, col1, col2, f1, f2, rad1, rad2, visible1 = vis1) val3['faces'] = f2 elif len(f1) == 0: verts1 = vv2; faces1 = f2 radii = rad2 colors1 = col2; colors2 = None opacity1 = [0]; opacity2 = op2 val3 = None elif len(f2) == 0: verts1 = vv1; faces1 = f1 radii = rad1 colors1 = col1; colors2 = None opacity1 = op1; opacity2 = [0] val1['faces'] = f1 val1['faces'] = faces1 #keyframe values for Spheres and Indexed Geoms: val1['vertices'] = verts1 if radii is not None: val1['radii'] = radii if colors2 is None: val1["materials"] = colors1 #matkw = {"redo":1, "tagModified":False, "transparent": 'implicit', "inheritMaterial":0} matkw = {"redo":1, "tagModified":False, "transparent": True, "inheritMaterial":0} val1.update(matkw) tr = r2[g.fullName].get("transparent", None) if tr is not None: matkw['transparent'] = tr inhmat = r2[g.fullName].get("inheritMaterial", None) if inhmat is not None: matkw["inheritMaterial"] = inhmat if val3 is not None: val3['vertices'] = vv2 val3["materials"] = col2 if vnorms is not None: val3['vnormals'] = vnorms val3.update(matkw) ### ACTORS: ###### # create actor that calls g.Set() method to set vertices, faces, # radii and colors of the geometry: from DejaVu.scenarioInterface.actor import DejaVuActor setactor = DejaVuActor('setactor', g, setFunction=lambda actor, val: actor.object.Set(**val) ) kf0 = KF(self.kfpos[0], val1) setactor.actions.addKeyframe(kf0) if val3: kf1 = KF(self.kfpos[1], val3) setactor.actions.addKeyframe(kf1) self.AddActions( setactor, setactor.actions ) # opacity actor opacactor = getActor(g, 'opacity') kf1 = KF(self.kfpos[0], opacity1) kf2 = KF(self.kfpos[1]-1, opacity2) i1 = Interval( kf1, kf2, generator=opacactor.behaviorList) opacactor.addIntervals( [i1] ) kf3 = KF(self.kfpos[1], op2) opacactor.actions.addKeyframe(kf3) self.AddActions( opacactor, opacactor.actions ) if colors2 is not None: # add color actor: coloractor = getActor(g, 'colors') kf1 = KF(self.kfpos[0], colors1) kf2 = KF(self.kfpos[1]-1, colors2) i1 = Interval( kf1, kf2, generator=coloractor.behaviorList) coloractor.addIntervals( [i1] ) self.AddActions( coloractor, coloractor.actions ) # depthMask actor depthactor = getActor(g, 'depthMask') kf0 = KF(self.kfpos[0], 0) kf1 = KF(self.kfpos[1], depthactor.getValueFromObject()) depthactor.actions.addKeyframe(kf0) depthactor.actions.addKeyframe(kf1) self.AddActions( depthactor, depthactor.actions ) if self.msmsPtrs.has_key(g.fullName): self.msmsPtrs[g.fullName][1] = True elif mod.has_key("faces"): # create actors for objects that appear through faces #print "FACES" ff1 = mod["faces"][1] ff2 = mod["faces"][2] nface1 = len(ff1) nface2 = len(ff2) #print "JJJJJJJ1 faces" if nface1==0: #print 'APPEAR1', g.name if len(r1[gname].get('vertices',[])) > 0: facesactor = getActor(g, 'faces') kf0 = KF(self.kfpos[0], ff2) facesactor.actions.addKeyframe(kf0) self.AddActions( facesactor, facesactor.actions ) self.appear(g) elif nface2 ==0: #print 'DISAPPEAR1', g.name facesactor = getActor(g, 'faces') kf0 = KF(self.kfpos[0], ff1) facesactor.actions.addKeyframe(kf0) self.AddActions( facesactor, facesactor.actions ) self.disappear(g) else: vv1 = r1[gname].get('vertices',[]) vv2 = r2[gname].get('vertices',[]) nvert1 = len(vv1) nvert2 = len(vv2) if nvert1 == 0 or nvert2 == 0: continue # visibility actor visibleactor = getActor(g, 'visible') kf1 = KF(self.kfpos[0], 1) visibleactor.actions.addKeyframe(kf1) self.AddActions( visibleactor, visibleactor.actions ) #face actor facesactor = getActor(g, 'faces') kf0 = KF(self.kfpos[0], numpy.concatenate((ff1, ff2)) ) facesactor.actions.addKeyframe(kf0) kf1 = KF(self.kfpos[1], ff2) facesactor.actions.addKeyframe(kf1) self.AddActions( facesactor, facesactor.actions ) # opacity actor opacactor = getActor(g, 'opacity') from DejaVu import viewerConst pnum = g.materials[1028].diff bind1 = r1[gname]["rawMaterialF"]['binding'][pnum] #origop1 = r1[gname]["rawMaterialF"]['opacity'] origop1 = numpy.array(r1[gname]["rawMaterialF"]['diffuse'], "f")[:,3] oplen1 = len(origop1) if bind1 == viewerConst.PER_PART: # this could be in case of secondary structure if oplen1 != nface1: origop1 = numpy.ones(nface1).astype('f')*origop1[0] else: if oplen1 != nvert1: origop1 = numpy.ones(nvert1).astype('f')*origop1[0] bind2 = r2[gname]["rawMaterialF"]['binding'][pnum] #origop2 = r2[gname]["rawMaterialF"]['opacity'] origop2 = numpy.array(r2[gname]["rawMaterialF"]['diffuse'], "f")[:,3] oplen2 = len(origop2) if bind2 == viewerConst.PER_PART: # this could be in case of secondary structure if oplen2 != nface2: origop2 = numpy.ones(nface2).astype('f')*origop2[0] if len(origop1) != nface1: origop1 = numpy.ones(nface1).astype('f')*origop1[0] else: if oplen2 != nvert2: origop2 = numpy.ones(nvert2).astype('f')*origop2[0] col1 = numpy.array(r1[gname]["rawMaterialF"]["diffuse"], numpy.float32)[:,:3] col2 = numpy.array(r2[gname]["rawMaterialF"]["diffuse"], numpy.float32)[:,:3] if len(origop1) == nface1 and len(origop2) == nface2: #print "face change: per_part", g.name nface = nface1+nface2 #opacities op1 = numpy.zeros(nface).astype('f') op2 = numpy.zeros(nface).astype('f') op1[0:nface1] = origop1 op2[nface1:] = origop2 # colors: l1 = len(col1) l2 = len(col2) addColors = False if not comparefloats(col1,col2): if l1 != nface1: col1 = numpy.ones(nface1*3, 'f').reshape(nface1, 3) * col1[0][:3] if l2 != nface2: col2 = numpy.ones(nface2*3, 'f').reshape(nface2, 3) * col2[0][:3] _col1 = numpy.concatenate((col1, col2)) _col2 = numpy.concatenate((col1, col2)) addColors = True # find intersecting faces: # create fast lookup for vertices in ff1 n = len(ff1[0]) # number of verts in a face fs = n*"%i," # string format # keys: string of varts in a face , value: face index in the face array f1dict = dict([(fs % tuple(f), i) for i,f in enumerate(ff1)]) intersect = 0 for i, f in enumerate(ff2): f1key = fs % tuple(f) if f1dict.has_key(f1key): intersect +=1 op1[nface1+i] = origop1[f1dict[f1key]] op2[f1dict[f1key]] = origop2[i] if addColors: _col1[nface1+i] = col1[f1dict[f1key]] _col2[f1dict[f1key]] = col2[i] kf1 = KF(self.kfpos[0], op1) kf2 = KF(self.kfpos[1]-1, op2) i1 = Interval( kf1, kf2, generator=opacactor.behaviorList) opacactor.addIntervals( [i1] ) kf3 = KF(self.kfpos[1], origop2) opacactor.actions.addKeyframe(kf3) self.AddActions( opacactor, opacactor.actions ) if addColors: if intersect > 0 : coloractor = self.createActor(g, "colors", _col1, _col2, kfpos=[self.kfpos[0], self.kfpos[1]-1]) kf3 = KF(self.kfpos[1], col2) coloractor.actions.addKeyframe(kf3) else: coloractor = self.createActor(g, "colors", _col1, col2, addInterval=False) self.AddActions( coloractor, coloractor.actions ) else: #print "face change: per_vertex", g.name op1 = numpy.zeros(nvert1).astype('f') op2 = numpy.zeros(nvert1).astype('f') # create fast lookup for vertices in ff2 f2key = {}.fromkeys(ff2.flatten().tolist()) if r1[gname].get('visible') == 1: # create fast lookup for vertices in ff1 f1key = {}.fromkeys(ff1.flatten().tolist()) for i in xrange(nvert1): if f1key.has_key(i): op1[i] = origop1[i] if f2key.has_key(i): op2[i] = origop2[i] else: for i in range(nvert1): if f2key.has_key(i): op2[i] = origop2[i] kf1 = KF(self.kfpos[0], op1) kf2 = KF(self.kfpos[1], op2) i1 = Interval( kf1, kf2, generator=opacactor.behaviorList) opacactor.addIntervals( [i1] ) self.AddActions( opacactor, opacactor.actions ) # the following color setting is done if the geometry # has one color. In this case setting opacity per vertex does not work # properly -> create array of color - same color per vertex. # # destination color col2 = r2[gname]["rawMaterialF"]["diffuse"] if len(col2)==1: _col2 = numpy.ones(nvert1*4, 'f').reshape(nvert1, 4) _col2 = _col2 * col2[0] r2[gname]["rawMaterialF"]["diffuse"] = _col2.tolist() # get current color of the object: #col1 = g.materials[1028].prop[1][:, :3] col1 = r1[gname]["rawMaterialF"]["diffuse"] if len(col1)==1: #_col1 = numpy.ones(nvert1*3, 'f').reshape(nvert1, 3) _col1 = numpy.ones(nvert1*4, 'f').reshape(nvert1, 4) _col1 = _col1 * col1[0] g.Set(materials=_col1, tagModified=False, transparent='implicit', inheritMaterial=0) # actors for other parameters for k, _mod in mod.items(): typ, v1, v2 = _mod if k in ["rawMaterialF", "rawMaterialB"]: if mod.has_key('vertices'): continue # find out if we need to add color actor: aname = "colors" if k == "rawMaterialB": aname = "colorsB" if not self.findActor(getActorName(g, aname)): addColor = False col1 = numpy.array(v1["diffuse"], numpy.float32)[:,:3] col2 = numpy.array(v2["diffuse"], numpy.float32)[:,:3] l1 = len(col1) l2 = len(col2) #nface1 = len(r1[gname]['faces']) #nface2 = len(r2[gname]['faces']) if (l1 == l2 and comparefloats(col1,col2) == False) or (l1 == 1 and l2 != 1) or (l2 == 1 and l1 != 1): addColor = True else: if r1[gname].has_key('faces'): nface1 = len(r1[gname]['faces']) nface2 = len(r2[gname]['faces']) if l1 != l2 and nface1 == nface2: if l1 == nface1: col2 = numpy.ones(nface1*3, 'f').reshape(nface1, 3) * col2[0] addColor = True elif l2 == nface1: col1 = numpy.ones(nface1*3, 'f').reshape(nface1, 3) * col1[0] addColor = True if addColor: #print "creating color actor for:", g.name coloractor = self.createActor(g, aname, col1, col2) self.AddActions( coloractor, coloractor.actions ) # find out if we need to add material actor mater1 = [v1['ambient'], v1['emission'], v1['specular'], v1['shininess']] mater2 = [v2['ambient'], v2['emission'], v2['specular'], v2['shininess']] materialactor = getActor(g, "material") if materialactor is not None: if materialactor.compareValues(mater1, mater2) == False: if k == "rawMaterialB": materialactor.mode = "back" kf1 = KF(self.kfpos[0], mater1) kf2 = KF(self.kfpos[1], mater2) i1 = Interval( kf1, kf2, generator = materialactor.behaviorList) materialactor.addIntervals( [i1] ) self.AddActions( materialactor, materialactor.actions ) if not self.findActor(getActorName(g,'opacity')): opac1 = v1['opacity'] opac2 = v2['opacity'] if not comparefloats(opac1, opac2): aname = 'opacityF' if k == "rawMaterialB": if mod.has_key("rawMaterialF"): continue aname = 'opacityB' opacactor = getActor(g, aname) kf1 = KF(self.kfpos[0], opac1) kf2 = KF(self.kfpos[1], opac2) i1 = Interval( kf1, kf2, generator=opacactor.behaviorList) opacactor.addIntervals( [i1] ) self.AddActions( opacactor, opacactor.actions ) elif k in ['scissorH', 'scissorW', 'scissorX', 'scissorY']: scissorvals[k] = [v1, v2] elif k in ['pointWidth', 'lineWidth', 'quality']: intactor = self.createActor(g, k, v1, v2) if intactor is not None: self.AddActions(intactor, intactor.actions) elif k == "radii" : if not self.findActor(getActorName(g, 'setactor')): radactor = self.createActor(g, "radii", v1, v2) if not self.findActor(radactor): self.AddActions(radactor, radactor.actions) elif k in [ 'inheritStippleLines', 'stippleLines', 'disableStencil', 'immediateRendering', 'inheritLighting', 'invertNormals', 'outline', 'inheritPointWidth', 'pickable', 'stipplePolygons', 'pickableVertices', 'depthMask', 'inheritSharpColorBoundaries', 'lighting', 'inheritCulling', 'inheritShading', 'sharpColorBoundaries', 'inheritFrontPolyMode', 'inheritStipplePolygons', 'scissor', 'inheritBackPolyMode', 'inheritLineWidth', 'inheritMaterial', 'inheritXform']: # ,'visible', 'transparent',]: from DejaVu.scenarioInterface.actor import DejaVuActor from Scenario2.interpolators import BooleanInterpolator from Scenario2.datatypes import BoolType if k == "depthMask": if self.findActor(getActorName(g, "depthMask")): continue elif k == "inheritMaterial": if self.findActor(getActorName(g, "opacity")): continue boolactor = DejaVuActor(k, g, interp=BooleanInterpolator, datatype=BoolType) kf1 = KF(self.kfpos[0], v1) kf2 = KF(self.kfpos[1], v2) i1 = Interval( kf1, kf2, generator = boolactor.behaviorList) boolactor.addIntervals( [i1] ) self.AddActions( boolactor, boolactor.actions ) elif k == 'transparent': if not self.findActor(getActorName(g, 'setactor')): from DejaVu.scenarioInterface.actor import DejaVuActor tpactor = DejaVuActor(k, g, interp=None) kf1 = KF(self.kfpos[0], v1) kf2 = KF(self.kfpos[1], v2) tpactor.actions.addKeyframe(kf1) tpactor.actions.addKeyframe(kf2) self.AddActions( tpactor, tpactor.actions ) elif k == 'clipPlanes': clip1 = map(lambda x:x[0], v1) clip2 = map(lambda x:x[0], v2) val = [] for i, n in enumerate(clip1): if not n in clip2: # clipping plane n needs to be disabled #print "adding clipplane actor to disable clipP ", n cp = viewer.clipP[n] val.append([cp, v1[i][1], v1[i][2] , False]) #[cp, side, inherit, enable/disable] for i, n in enumerate(clip2): if n not in clip1: # clipping plane n needs to be enabled #print "adding clipplane actor to enable clipP ", n cp = viewer.clipP[n] val.append([cp, v2[i][1], v2[i][2], True]) #[cp, side, inherit, enable/disable] clipactor = getActor(g,'clipEnable') if len(val): kf1 = KF(self.kfpos[0], val) clipactor.actions.addKeyframe(kf1) self.AddActions( clipactor, clipactor.actions ) # ends "for" loop if len(scissorvals): scissoractor = getActor(g, 'scissorResize') if scissoractor is not None: val1 = scissoractor.getValue() val2 = scissoractor.getValue() for i, var in enumerate (scissoractor.varnames): if scissorvals.has_key(var): val1[i]= scissorvals[var][0] val2[i]= scissorvals[var][1] kf1 = KF(self.kfpos[0], val1) kf2 = KF(self.kfpos[1], val2) i1 = Interval( kf1, kf2, generator = scissoractor.behaviorList) scissoractor.addIntervals( [i1] ) self.AddActions(scissoractor, scissoractor.actions) # camera actors cammod = {} if r1.has_key('camera') and r2.has_key('camera'): cammod = self.compareCameraState(r1['camera'], r2['camera']) if len(cammod): camera = viewer.cameras[0] ## if cammod.has_key('near') and cammod.has_key('far'): ## val1 = [cammod['near'][1], cammod['far'][1]] ## val2 = [cammod['near'][2], cammod['far'][2]] ## camclipzactor = self.createActor(camera, 'clipZ',val1, val2) ## if camclipzactor is not None: ## self.AddActions(camclipzactor,camclipzactor.actions) ## cammod.pop('near') ## cammod.pop('far') for k, val in cammod.items(): if k == 'color': camcoloractor = self.createActor(camera, 'backgroundColor', val[1], val[2]) if camcoloractor is not None: self.AddActions(camcoloractor, camcoloractor.actions) elif k in ['height', 'width', 'antialiased', 'boundingbox', 'projectionType','drawThumbnail','contours']: camactor = getActor(camera, k) if camactor is not None: kf1 = KF(self.kfpos[0], val[1]) kf2 = KF(self.kfpos[1], val[2]) camactor.actions.addKeyframe(kf1) camactor.actions.addKeyframe(kf2) self.AddActions( camactor, camactor.actions ) elif k in ['near', 'far']: camactor = self.createActor(camera, k, val[1], val[2]) if camactor is not None: self.AddActions( camactor, camactor.actions ) #clipplane actors clipmode = {} for i , cp in enumerate(viewer.clipP): clipname = 'clipplane%d'%i if r1.has_key(clipname) and r2.has_key(clipname): clipmode = self.compareClipState(r1[clipname], r2[clipname]) for k, val in clipmode.items(): if k == 'rotation': actor = getActor(cp, 'rotation') kf0 = KF(self.kfpos[0] , matToQuaternion(val[1])) kf1 = KF(self.kfpos[1], matToQuaternion(val[2]) ) i = Interval( kf0, kf1, generator=actor.behaviorList) actor.addIntervals( [i] ) self.AddActions( actor, actor.actions ) elif k in ['translation', 'scale', 'pivot', 'color']: actor = getActor(cp, k) kf0 = KF(self.kfpos[0], val[1]) kf1 = KF(self.kfpos[1], val[2]) actor.addIntervals( [ (kf0, kf1) ] ) self.AddActions( actor, actor.actions ) elif k == 'visible': # visibility actor visibleactor = getActor(cp, 'visible') kf1 = KF(self.kfpos[0], val[2]) visibleactor.actions.addKeyframe(kf1) self.AddActions( visibleactor, visibleactor.actions ) #if self._maaGroup is not None: # self._maaGroup().makeActorList() def appear(self, obj): #print "APPEAR", obj.name # ?? sortPoly can be set in the maa editor. # Do we need to make set it here ?? #self.sortPoly = 'Always' #if self._maaGroup: # self._maaGroup().sortPoly = 'Always' visibleactor = getActor(obj, 'visible') kf1 = KF(self.kfpos[0], 1) visibleactor.actions.addKeyframe(kf1) depthactor = getActor(obj, 'depthMask') kf0 = KF(self.kfpos[0], 0) kf1 = KF(self.kfpos[1], depthactor.getValueFromObject()) depthactor.actions.addKeyframe(kf0) depthactor.actions.addKeyframe(kf1) #actors = [visibleactor, depthactor] #actors = [depthactor] actors = [] opacityactor = None #if len(obj.vertexSet): if self.rendering[obj.fullName].has_key("vertices") and len(self.rendering[obj.fullName]["vertices"]): opacityactor = getActor(obj, 'opacity') kf1 = KF(self.kfpos[0], 0.) opacF = numpy.array(self.rendering[obj.fullName]["rawMaterialF"]['diffuse'], "f")[:,3] kf2 = KF(self.kfpos[1], opacF) i1 = Interval( kf1, kf2, generator=opacityactor.behaviorList) opacityactor.addIntervals( [i1] ) actors.append( opacityactor ) ## opacityactorB = getActor(obj, 'opacityB') ## kf1 = KF(self.kfpos[0], 0.) ## opacB = numpy.array(self.rendering[obj.fullName]["rawMaterialB"]['diffuse'], "f")[:,3] ## kf2 = KF(self.kfpos[1], opacB) ## i1 = Interval( kf1, kf2, generator=opacityactorB.behaviorList) ## opacityactorB.addIntervals( [i1] ) ## actors.append( opacityactorB ) if self.rendering.has_key(obj.fullName): from copy import deepcopy r = deepcopy(self.rendering[obj.fullName]) if opacityactor and r.has_key("rawMaterialF"): r["rawMaterialF"]["opacity"] = [0] if r.has_key('inheritMaterial'): r['inheritMaterial'] = 0 if r.has_key("depthMask"): r.pop("depthMask") if r.has_key("visible"): r.pop("visible") ractor = getActor(obj ,'rendering') kf0 = KF(self.kfpos[0], r) ractor.actions.addKeyframe(kf0) actors.append(ractor) actors.append(visibleactor) for actor in actors: if actor.actions is not None: self.AddActions( actor, actor.actions ) #visibleactor = self.findActor(visibleactor) #if len(visibleactor.actions.keyframes) == 2: # visibleactor.actions.keyframes.pop(0) def disappear(self, obj): # ?? sortPoly can be set in the maa editor. # Do we need to make set it here ?? #self.sortPoly = 'Always' #if self._maaGroup: # self._maaGroup().sortPoly = 'Always' visibleactor = getActor(obj, 'visible') kf0 = KF(self.kfpos[0], 1.) # visible at the begining kf1 = KF(self.kfpos[1], 0) # not visible at the end visibleactor.actions.addKeyframe(kf0) visibleactor.actions.addKeyframe(kf1) depthactor = getActor(obj, 'depthMask') #kf0 = KF((self.kfpos[0]+self.kfpos[1])/2, 0) kf0 = KF(self.kfpos[0], 0) kf1 = KF(self.kfpos[1], depthactor.getValueFromObject()) depthactor.actions.addKeyframe(kf0) depthactor.actions.addKeyframe(kf1) #actors = [visibleactor, depthactor] actors = [visibleactor] if len(obj.vertexSet): opacityactorF = getActor(obj, 'opacity') originalOpac = opacityactorF.getValueFromObject()[0] kf1 = KF(self.kfpos[0], originalOpac) kf2 = KF(self.kfpos[1], 0.) i1 = Interval( kf1, kf2, generator=opacityactorF.behaviorList) opacityactorF.addIntervals( [i1] ) #kf3 = KF(self.kfpos[1]+1, originalOpac) # restore opac #opacityactor.actions.addKeyframe(kf3) actors.append( opacityactorF ) ## opacityactorB = getActor(obj, 'opacityB') ## originalOpac = opacityactorB.getValueFromObject()[0] ## kf1 = KF(self.kfpos[0], originalOpac) ## kf2 = KF(self.kfpos[1], 0.) ## i1 = Interval( kf1, kf2, generator=opacityactorB.behaviorList) ## opacityactorB.addIntervals( [i1] ) ## actors.append( opacityactorB ) for actor in actors: if actor.actions is not None: self.AddActions( actor, actor.actions ) def createActor(self, object, actorName, val1, val2, kfpos=None, addInterval=True): actor = getActor(object, actorName) if not kfpos: kfpos = self.kfpos if actor is not None: kf1 = KF(kfpos[0], val1) kf2 = KF(kfpos[1], val2) if addInterval: i1 = Interval( kf1, kf2, generator = actor.behaviorList) actor.addIntervals( [i1] ) else: actor.actions.addKeyframe(kf1) actor.actions.addKeyframe(kf2) return actor def setValuesAt(self, frame, off=0, actor=None, run=True): if frame == off + self.firstPosition: if len(self.actors) >1: self.removeNonRedrawActors() #print self, "setValuesAt, makeMAA" #create actors on the first frame of the MAA: self.makeMAA(getRendering(self.viewer, checkAnimatable=True), self.kfpos) if self._director is not None: self._director().updateEndFrame() if run: MultipleActorsActions.setValuesAt(self, frame, off, actor) def removeNonRedrawActors(self): """ remove all actors except for redraw actors. """ # use by subclasses then they want to rebuild the MAA keptActors = [] for actor in self.actors: if isinstance(actor, RedrawActor): keptActors.append( actor) self.actors = keptActors def compareGeomState(self, s1, s2): mod = {} for k in s1.keys(): # list of states that are skipped if k in ['protected', 'replace', 'listed', 'vertexArrayFlag', 'needsRedoDpyListOnResize', #'vnormals', #'vertices', 'fnormals', '',]: continue elif k == "vertices": vv1 = s1[k] vv2 = s2[k] nvert1 = len(vv1) nvert2 = len(vv2) if nvert1 == 0 or nvert2 == 0: continue if nvert1 != nvert2: mod[k] = ('vertices', vv1, vv2) else: #if numpy.alltrue(numpy.equal(vv1, vv2)) != True: if not comparefloats(vv1, vv2): mod[k] = ('vertices', vv1, vv2) elif k == "vnormals": vv1 = s1[k] vv2 = s2[k] nvert1 = len(vv1) nvert2 = len(vv2) if nvert1 == 0 or nvert2 == 0: continue if nvert1 != nvert2: mod[k] = ('vnormals', vv1, vv2) else: if not comparefloats(vv1, vv2): mod[k] = ('vnormals', vv1, vv2) elif k in ['faces']: if len(s1[k])!=len(s2[k]): mod[k] = ('faces', s1[k], s2[k] ) elif len(s1[k]) == len(s2[k]) == 0: continue else: n = len(s1[k][0]) fs = n*"%i," facedic2 = dict([(fs % tuple(f),None) for f in s2[k]]) for f in s1[k]: if not facedic2.has_key(fs % tuple(f)): mod[k] = ("faces", s1[k], s2[k]) break elif k in [ 'inheritStippleLines', 'stippleLines', 'disableStencil', 'visible', 'immediateRendering', 'inheritLighting', 'invertNormals', 'outline', 'inheritPointWidth', 'pickable', 'stipplePolygons', 'pickableVertices', 'depthMask', 'inheritSharpColorBoundaries', 'lighting', 'inheritCulling', 'inheritShading', 'transparent', 'sharpColorBoundaries', 'inheritFrontPolyMode', 'inheritStipplePolygons', 'scissor', 'inheritBackPolyMode', 'inheritLineWidth', 'inheritMaterial', 'inheritXform']: if s1[k]!=s2[k]: mod[k]= (bool, s1[k], s2[k] ) elif k in ['quality', 'scissorH', 'scissorX', 'scissorY', 'pointWidth', 'scissorW', 'lineWidth' ]: if s1[k]!=s2[k]: mod[k]= (int, s1[k], s2[k]) elif k in ['scissorAspectRatio']: if s1[k]!=s2[k]: mod[k] =(float, s1[k], s2[k] ) elif k in ['frontPolyMode', 'shading', 'culling', 'backPolyMode']: if s1[k]!=s2[k]: mod[k]= (str, s1[k], s2[k]) elif k in ['rawMaterialF', 'rawMaterialB']: if s1[k]!=s2[k]: mod[k] = ('material', s1[k], s2[k]) elif k in ['instanceMatricesFromFortran']: if s1[k]!=s2[k]: mod[k] = ('instances', s1[k], s2[k]) elif k in ['blendFunctions']: if s1[k]!=s2[k]: mod[k] = (tuple, s1[k], s2[k]) elif k == "radii": if type(s1[k])==numpy.ndarray: #if len(s1[k]) != len(s2[k]) or numpy.alltrue(numpy.equal(s1[k], s2[k])) != True: if len(s1[k]) != len(s2[k]) or comparefloats(s1[k], s2[k]) != True: mod[k] = ("radii", s1[k], s2[k]) else: if s1[k]!=s2[k]: mod[k]= ("radii", s1[k], s2[k]) elif k == 'clipPlanes' and s2.has_key(k): if s1[k] != s2[k]: mod[k] = ('clipPlanes', s1[k], s2[k]) #else: # print 'SKIPPED', k return mod def compareCameraState(self, s1, s2): mod = {} for k in s1.keys(): # list of states that are skipped if k in ['rotation', 'translation','scale','pivot', 'direction','lookAt', 'height', 'width', 'near', 'far']: continue elif k in ['antialiased', 'boundingbox', 'projectionType', 'drawThumbnail','contours']: if s1[k] != s2[k]: mod[k]= (int, s1[k], s2[k]) elif k == 'color': if not comparefloats(s1[k], s2[k]): mod[k]= (tuple, s1[k], s2[k]) return mod def compareClipState(self, s1, s2): mod = {} for k in s1.keys(): if k in ['rotation', 'translation','scale','pivot', 'color']: if not comparefloats(s1[k], s2[k]): mod[k]= (k, s1[k], s2[k]) elif k == 'visible': if s1[k]!=s2[k]: mod[k]= (bool, s1[k], s2[k] ) return mod def getSourceCode(self, varname, indent=0, saverendering=True): """ Return python code creating this object """ tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import RenderingTransitionMAA\n""" if saverendering and self.rendering is not None: lines += tabs + """from numpy import *\n""" from numpy import set_string_function, array_repr set_string_function(numarr2str) lines += tabs + """rendering=%s\n""" % (self.rendering) set_string_function(array_repr) else: lines += tabs + """rendering=None\n""" newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = RenderingTransitionMAA(viewer, rendering = rendering, kfpos=%s, name='%s', startFlag='%s',saveAtomProp=False)\n"""%(varname, self.kfpos, self.name, self.startFlag) lines += self.saveGeomAtomProp2File(varname, newtabs) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines def getSpheresTransitionValues(self, geom, vv1, vv2, op1, op2, col1, col2, rad1=None, rad2=None, visible1 = 1): import numpy.oldnumeric as Numeric vdict = {} inter1 = [] #inter2 = [] diff2 = [] nvert1 = len(vv1) nop1 = Numeric.zeros(nvert1, "f") ncol1 = col1.astype('f') for i,v in enumerate(vv1): vdict["%.4f,%.4f,%.4f"%(v[0],v[1],v[2])] = i for i, v in enumerate(vv2): vkey = "%.4f,%.4f,%.4f"%(v[0],v[1],v[2]) if vdict.has_key(vkey): j = vdict[vkey] inter1.append(j) #inter2.append(i) nop1[j] = op2[i] ncol1[j] = col2[i] else: diff2.append(i) #print "len vv1:" , len(vv1), "vv2:", len(vv2), "inter:", len(inter1), len(vv1)+len(diff2) if len(inter1) > 0: nvert2 = len(diff2) verts = Numeric.concatenate((vv1, Numeric.take(vv2, diff2))) #print "new verts array:", verts.shape if rad1 is not None and rad2 is not None: radii = Numeric.concatenate((rad1, Numeric.take(rad2, diff2))) else: radii = None if not visible1: opacity1 = Numeric.zeros(nvert1+nvert2).astype('f') else: opacity1 = Numeric.concatenate((op1, Numeric.zeros(nvert2))) opacity2 = Numeric.concatenate((nop1, Numeric.take(op2, diff2))) colors1 = Numeric.concatenate((col1, Numeric.take(col2, diff2))) colors2 = Numeric.concatenate((ncol1, Numeric.take(col2, diff2))) sverts, sradii, scolors1, scolors2, sopac1, sopac2 = self.sortVerts(geom, verts, radii,colors1, colors2, opacity1, opacity2, order=-1) return sverts, sradii, sopac1, sopac2, scolors1, scolors2 else: verts = Numeric.concatenate((vv1, vv2)) nvert2 = len(vv2) if not visible1: opacity1 = Numeric.zeros(nvert1+nvert2).astype('f') else: opacity1 = Numeric.concatenate((op1, Numeric.zeros(nvert2))) opacity2 = Numeric.concatenate((Numeric.zeros(nvert1), op2)) colors1 = Numeric.concatenate((col1, col2)) colors2 = None if rad1 is not None and rad2 is not None: radii = Numeric.concatenate((rad1, rad2)) else: radii = None return verts, radii, opacity1, opacity2, colors1, colors2 def getIndGeomsTransitionValues(self, geom, vv1, vv2, op1, op2, col1, col2, f1, f2, rad1=None, rad2=None, visible1 = 1): """function parameters: - geom - animatable geometry; - [vv1, vv2], [op1, op2], [col1, col2], [f1, f2], [rad1, rad2] - arrays of vertices, opacities, colors, faces and radii of the specified geometry in snapshots 1 and 2; Checks if the geometries specified by vertices and faces intersect returns 'union' arrays of vertices and faces of the two geometries returns opacity an color arrays representing transition between two states. """ import numpy.oldnumeric as Numeric inter1 = [] # list containig face indices of f1 array that are also found in f2 diff2 = [] # list of f2 face indices that are not in f1 ncol1 = col1.astype("f") nvert1 = len(vv1) nvert2 = len(vv2) nop1 = Numeric.zeros(nvert1, 'f') fdict = {} # dict: key - vertex coords in a face , value - face index nv = len(f1[0]) # number of vertices in each face # find intersecting faces if nv == 2: # loop over geom faces in snapshot 1 for i, ff1 in enumerate(f1): # construct a string containing coordinates of each vertex in the face: st1 = "%.4f,%.4f,%.4f,"% tuple(vv1[ff1[0]]) + "%.4f,%.4f,%.4f"% tuple(vv1[ff1[1]]) fdict[st1] = i # loop over geom faces in snapshot 2 for j , ff2 in enumerate(f2): # vertex indices of ff2 face ind20 = ff2[0] ind21 = ff2[1] # construct a string containing coordinates of each vertex in the face: st2 = "%.4f,%.4f,%.4f,"% tuple(vv2[ind20]) + "%.4f,%.4f,%.4f"% tuple(vv2[ind21]) if fdict.has_key(st2): # face ff2 of f2 array is in f1 array i = fdict[st2] # index of face ff2 in f1 array # ff2 vertex indices in f1 array: ind10 = f1[i][0] ind11 = f1[i][1] inter1.append(i) ncol1[ind10] = col2[ind20] ncol1[ind11] = col2[ind21] nop1[ind10] = op2[ind20] nop1[ind11] = op2[ind21] else: diff2.append(j) elif nv ==3: # loop over geom faces in snapshot 1 for i, ff1 in enumerate(f1): # construct a string containing coordinates of each vertex in the face: st1 = "%.4f,%.4f,%.4f,"% tuple(vv1[ff1[0]]) + "%.4f,%.4f,%.4f,"% tuple(vv1[ff1[1]])+ "%.4f,%.4f,%.4f"% tuple(vv1[ff1[2]]) fdict[st1] = i # loop over geom faces (f2) in snapshot 2 for j , ff2 in enumerate(f2): # vertex indices of ff2 face ind20 = ff2[0] ind21 = ff2[1] ind22 = ff2[2] # construct a string containing coordinates of each vertex in the face: st2 = "%.4f,%.4f,%.4f,"% tuple(vv2[ind20]) + "%.4f,%.4f,%.4f,"% tuple(vv2[ind21])+ "%.4f,%.4f,%.4f"% tuple(vv2[ind22]) if fdict.has_key(st2): # face ff2 of f2 array is in f1 array i = fdict[st2] ind10 = f1[i][0] ind11 = f1[i][1] ind12 = f1[i][2] inter1.append(i) ncol1[ind10] = col2[ind20] ncol1[ind11] = col2[ind21] ncol1[ind12] = col2[ind22] nop1[ind10] = op2[ind20] nop1[ind11] = op2[ind21] nop1[ind12] = op2[ind22] else: diff2.append(j) #print "found intersected faces:", len(inter1) #print len(fdict.keys()) # concatenate arrays of vertices, radii opacities and colors: verts = Numeric.concatenate((vv1, vv2)) radii = None if rad1 is not None and rad2 is not None: radii = Numeric.concatenate((rad1, rad2)) colors1 = Numeric.concatenate((col1, col2)) if not visible1: opacity1 = Numeric.zeros(nvert1+nvert2).astype('f') else: opacity1 = Numeric.concatenate((op1, Numeric.zeros(nvert2))) #print "len verts:", len(vv1), "max face ind:", f1.ravel().max() if len(inter1)>0: # f2 array faces that are not in f1 array: #nf2 = Numeric.take(f2, diff2) + (f1.ravel().max()+1) nf2 = Numeric.take(f2, diff2) + len(vv1) #print len(diff2), nf2.shape faces = Numeric.concatenate((f1 , nf2 ) ) colors2 = Numeric.concatenate((ncol1, col2)) opacity2 = Numeric.concatenate((nop1, op2)) else: #faces = Numeric.concatenate((f1 , f2 +(f1.ravel().max()+1)) ) faces = Numeric.concatenate((f1 , f2 + len(vv1)) ) colors2 = None opacity2 = Numeric.concatenate((Numeric.zeros(nvert1), op2)) ## sfaces, snorms = self.sortFaces(geom, verts, faces, order=-1) ## return verts, sfaces, radii, opacity1, opacity2, colors1, colors2 return verts, faces, radii, opacity1, opacity2, colors1, colors2 def sortFaces(self, geom, verts, faces, normals = None, order=-1): """faces, fnormals <- sortFaces(geom, verts, faces, normals = None, order=-1) Sorts the geometry polygons according to z values of polygon's geometric centers. Order=-1 sorts by furthest z first, order=1 sorts by closest z first""" #print "sort faces", geom import numpy.oldnumeric as Numeric mat = geom.GetMatrix() mat = Numeric.reshape(mat, (4,4)) nv = len(verts) verts1 = Numeric.reshape(numpy.ones(nv*4, 'f'), (nv,4)) verts1[:, :3] = verts vt = Numeric.dot(verts1, numpy.transpose(mat))[:, :3] triv = Numeric.take(vt, faces.astype('i')) nn = faces.shape[1] * 1. trig = Numeric.sum(triv,1)/nn trigz = trig[:,2] #triangle's center of gravity z value ind = Numeric.argsort(trigz) # sorted indices sfaces = Numeric.take(faces, ind[::order]) if normals is None: snormals = None else: if len(normals)>1: snormals = Numeric.take(normals, ind[::order]) else: snormals = normals return sfaces, snormals def sortVerts(self, geom, verts, radii, colors1, colors2, opac1, opac2 = None, order=-1): #print "sort verts", geom nv = len(verts) if len(opac1) != nv or len(colors1)!= nv or len(colors2) != nv: return verts, radii, colors1, colors2, opac1, opac2 if radii is not None and len(radii) != nv: return verts, radii, colors1, colors2, opac1, opac2 import numpy.oldnumeric as Numeric mat = geom.GetMatrix() mat = Numeric.reshape(mat, (4,4)) verts1 = Numeric.reshape(numpy.ones(nv*4, 'f'), (nv,4)) verts1[:, :3] = verts vt = Numeric.dot(verts1, numpy.transpose(mat))[:, :3] ind = Numeric.argsort(vt[:,2]) sverts = Numeric.take(verts, ind[::order]) sopac1 = Numeric.take(opac1, ind[::order]) sopac2 = None scolors1 = Numeric.take(colors1, ind[::order]) scolors2 = Numeric.take(colors2, ind[::order]) sradii = None if radii is not None: sradii = Numeric.take(radii, ind[::order]) if opac2 is not None: sopac2 = Numeric.take(opac2, ind[::order]) return sverts, sradii, scolors1, scolors2, sopac1, sopac2 def intersects(self, bb1, bb2): # find out if two bounding boxes intersect return (bb1[0][0] < bb2[1][0]) and (bb1[1][0] > bb2[0][0]) and \ (bb1[0][1] < bb2[1][1]) and (bb1[1][1] > bb2[0][1]) and \ (bb1[0][2] < bb2[1][2]) and (bb1[1][2] > bb2[0][2]) def saveGeomAtomProp(self): t1 = time() self.atomSets = {} self.msmsPtrs = {} allobj = self.viewer.rootObject.AllObjects() from MolKit.molecule import AtomSet for obj in allobj: if hasattr(obj, "mol"): mol = obj.mol set = mol.geomContainer.atoms.get(obj.name, None) if set is not None and len(set): #self.atomSets[obj.fullName] = AtomSet(set.data[:]) self.atomSets[obj.fullName] = set.__class__(set.data[:]) gc = mol.geomContainer if gc.msms.has_key(obj.name): # save the msms swig pointer self.msmsPtrs[obj.fullName] = [(obj.name, gc.msms[obj.name]), False] # False will be replaced by True if we need to reset the pointer # after animation (in the case when there is transformation # between two same name surfaces with different vertex arrays). #print 'time to save prop', time()-t1 def setGeomAtomProp(self): t1 = time() if not len(self.atomSets) : return #print "setGeomAtomProp" for actor in self.actors: #if actor.name.find("setactor") > 0 or actor.name.find("faces") > 0: if actor.name.split(".")[-1] in ["setactor", "faces", "rendering"]: obj = actor.object if self.atomSets.has_key(obj.fullName): aset = self.atomSets[obj.fullName] if type(aset) == types.StringType: if self._animNB: pmv = self._animNB().pmv self.viewer.stopAutoRedraw() self.viewer.suspendRedraw = True hasGui = pmv.hasGui pmv.hasGui = False try: aset = pmv.select(aset).copy() pmv.clearSelection() except: pass pmv.hasGui = hasGui self.viewer.suspendRedraw = False self.viewer.startAutoRedraw() else: aset = [] if len(aset): obj.mol.geomContainer.atoms[obj.name] = aset val = self.msmsPtrs.get(obj.fullName, None) if val is not None and val[1] == True: surfname = val[0][0] geomC = obj.mol.geomContainer geomC.msms[surfname] = val[0][1] if hasattr(geomC,'msmsAtoms') and geomC.msmsAtoms.has_key(obj.name): surf = val[0][1][0] if surf.perMol == 0: geomC.msmsAtoms[obj.name] = aset else: geomC.msmsAtoms[obj.name]= obj.mol.allAtoms[:] #obj.mol.geomContainer.msms.update(val[0]) #print "time to set atom prop" , time()-t1 def saveGeomAtomProp2File(self, name, indent): ats = {} for k, val in self.atomSets.items(): if type(val) == types.StringType: ats[k] = val else: ats[k] = val.getStringRepr() lines = indent + "%s.atomSets = %s \n" % (name, ats) if len(self.msmsPtrs): vi = self.viewer for objFullname, val in self.msmsPtrs.items(): if self.rendering.has_key(objFullname) and self.rendering[objFullname]['visible']\ and self.atomSets.has_key(objFullname): obj = vi.FindObjectByName(objFullname) #print "saveGeomAtomProp2File, swig ptr", obj.mol.geomContainer.msms[obj.name], val[0][1] if obj: srf = val[0][1][0] #we will have to recompute msms surface when the maa is restored from the file setSwigPtr = val[1] if not setSwigPtr and not srf.perMol: setSwigPtr = True lines += indent + """pmv.computeMSMS(%s.atomSets['%s'], hdensity=%f, hdset=%s, density=%f, pRadius=%f, perMol=%d, noHetatm=%d, display=False, surfName='%s')\n"""% (name , objFullname, srf.hdensity, srf.hdset, srf.density, srf.probeRadius, srf.perMol, srf.noHetatm, obj.name) lines += indent + """mol = pmv.Mols.get('%s')[0]\n""" % obj.mol.name lines += indent + """%s.msmsPtrs['%s'] = [('%s', mol.geomContainer.msms['%s']), %s]\n""" % (name, objFullname, obj.name, obj.name, setSwigPtr) #print "saveGeomAtomProp2File:", lines return lines def saveGeomAtomProp0(self): t1 = time() self.atomSets = {} allobj = self.viewer.rootObject.AllObjects() from MolKit.molecule import Atom from copy import copy for obj in allobj: if hasattr(obj, "mol"): mol = obj.mol set = mol.geomContainer.atoms.get(obj.name, None) if set is not None and len(set): #print "saving aset for:" , obj.fullName aset = set.findType(Atom) from MolKit.stringSelector import StringSelector selector = StringSelector() g = mol.geomContainer atList = [] func = g.geomPickToAtoms.get(obj.name) if func: atList = func(obj, range(len(obj.vertexSet.vertices))) else: allAtoms = g.atoms[obj.name] if hasattr(obj, "vertexSet") and len(allAtoms) == len(obj.vertexSet): atList = allAtoms if len(atList): self.atomSets[obj.fullName] = {'atomset': set.full_name()} self.atomSets[obj.fullName]['atlist'] = atList print 'time to save prop', time()-t1 def setGeomAtomProp0(self): t1 = time() if not len(self.atomSets) : return from MolKit.molecule import Atom for actor in self.actors: if actor.name.find("setactor") > 0 or actor.name.find("faces") > 0: obj = actor.object if self.atomSets.has_key(obj.fullName): asetstr = self.atomSets[obj.fullName]['atomset'] atList = self.atomSets[obj.fullName].get('atlist', None) g = obj.mol.geomContainer from MolKit.stringSelector import StringSelector selector = StringSelector() aset, msg = selector.select(atList, asetstr) if len(aset): #print "setting atoms to:", obj, len(aset) if g.atoms[obj.name].elementType == Atom: g.atoms[obj.name] = aset #print 'AAAAAAAAAAa', time()-t1 t1 = time() for actor in self.actors: #print actor.name prop = None if actor.name.find('colors') > 0: prop = 'colors' elif actor.name.find('opacity') > 0: prop = 'opacities' if prop: obj = actor.object if self.atomSets.has_key(obj.fullName): atList = self.atomSets[obj.fullName].get('atlist', None) g = obj.mol.geomContainer if not atList: continue set=obj.mol.geomContainer.atoms.get(obj.name, None) if set is not None and len(set): values = actor.getLastKeyFrame().getValue() if len(values) != 1 and len(values) != len(atList): continue aset = set.findType(Atom) asetstr = aset.full_name(0) oname = None if getattr(aset, prop).has_key(obj.name): oname = obj.name elif getattr(aset, prop).has_key(obj.parent.name): oname = obj.parent.name if not oname: continue #print "setting", prop , "to", oname, len(atList) , if prop == "colors": if len(values) == 1: for a in atList: a.colors[oname] = tuple(values[0]) else: for i, a in enumerate(atList): a.colors[oname] = tuple(values[i]) elif prop == 'opacities': if len(values) == 1: for a in atList: a.opacities[oname] = values[0] else: for i, a, in enumerate(atList): a.opacities[oname] = values[i] from MolKit.stringSelector import StringSelector selector = StringSelector() nset, msg = selector.select(atList, asetstr) g.atoms[obj.name] = nset #print len(self.atomSets[obj.fullName]['atlist']) print 'time to restore prop', time()-t1 class RedrawMAA(MultipleActorsActions): """ MMA containin a RedrawActor for a DejaVu Viewer. This object always makes sure the RedrawActor is the last one in the list of actors. """ def __init__(self, viewer, name='redraw', startFlag='after previous'): """ constructor MAA <- RedrawMAA(viewer, name='redraw', startFlag='after previous') viewer is a DejaVu Viewer Object name is a string used to name this RedrawMAA startFlag - flag used in a sequence animator for computing time position of the maa . the MultipleActorsActions (MAA) is built with a RedrawActor for the viewer. The name of the RedrawActor name is 'redraw'+viewer.uniqID. """ assert isinstance(viewer, Viewer) MultipleActorsActions.__init__(self, name=name, startFlag=startFlag) redrawActor = RedrawActor(viewer) self.redrawActor = self.addActor(redrawActor) self.redrawActor.name = 'redraw' self.viewer = viewer self.origValues = {} self.editorClass = None self.editorKw = {} self.editorArgs = [] # when True the original orientation (of root object) is set on the first frame self.forceOrient = True self.orient = None # when True the original rendering style is set on the first frame self.forceRendering = True self.rendering = None # save the orientation in maa self.recordOrient() # save the representation in maa self.recordRendering() # Flag to set saved orientation of all parents of self.object self.setOrient = False self.geomOrients = {} def configure(self, **kw): """ handle forceOrient, forceRendering parameters """ self.forceOrient = kw.get('forceOrient', self.forceOrient) self.forceRendering = kw.get('forceRendering', self.forceRendering) def removeNonRedrawActors(self): """ remove all actors except for redraw actors. """ # use by subclasses then they want to rebuild the MAA keptActors = [] for actor in self.actors: if isinstance(actor, RedrawActor): keptActors.append( actor) self.actors = keptActors def addMultipleActorsActionsAt(self, maa, position=None): """ override the base class method to make sure RedrawActor is always last in the self.actors list """ val = MultipleActorsActions.addMultipleActorsActionsAt( self, maa, position=None) if self.redrawActor is not None: self.actors.remove(self.redrawActor) self.actors.append(self.redrawActor) if hasattr(maa, "origValues"): if len(maa.origValues): if hasattr(self, "origValues"): self.origValues.update(maa.origValues) else: self.origValues = maa.origValues return val def afterAnimation_cb(self): # reset maa actors original values if hasattr(self, "origValues"): for actor in self.actors: val = self.origValues.get(actor.name) if val is not None: #print "afterAnimation_cb: setting actor %s of object %s"% (actor.name, actor.object.name), val actor.setValue(val) def recordOrient(self): self.orient = getOrientation(self.viewer.rootObject) def recordRendering(self): self.rendering = getRendering(self.viewer, checkAnimatable=True) def getRenderingString(self, objects, indent=0): """returns a string representation of stored rendering """ tabs = " "*indent if not objects: rr = self.rendering else: rr = {} for obj in objects: if self.rendering.has_key(obj.fullName): rr[obj.fullName] = self.rendering[obj.fullName] if len(rr): lines = tabs + """from numpy import *\n""" from numpy import set_string_function, array_repr set_string_function(numarr2str) lines += tabs + """rendering=%s\n""" % (rr) #numpy.set_printoptions(threshold=oldopts["threshold"], precision=oldopts["precision"]) set_string_function(array_repr) else: lines += tabs + """rendering=None\n""" return lines def getDictString(self, datadict): """returns a string representation of specified simple dictionary. Replaces numeric arrays by lists""" newdict = {} import numpy for k , val in datadict.items(): if type(val) == numpy.ndarray: val = val.tolist() newdict[k]=val return """%s"""%newdict class VisibleObjectMAA(RedrawMAA): """ Create an MAA for making an object visible/invisible """ def __init__(self, object, objectName='NoName', kfpos=0, visible=1, objectFromString=None, startFlag="after previous", **kw): """ constructor MAA <- VisibleObjectMAA( object, objectName=None, name=None, kfpos=0, visible = 1, objectFromString=None, startFlag='after previous') - object - a list of- or a single DejaVu Transformable object - objectName - a short name used to name the MAA - kfpos - keyframe position at which object.visible attribute will be set - objectFromString is a string that yields the specified object(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa . """ if not hasattr(object, "__len__"): objects = [object] else: objects = object name = "%s %s"% ({0:"Hide", 1:"Show"}.get(visible), objectName) RedrawMAA.__init__(self, objects[0].viewer, name, startFlag) self.forceOrient = False self.forceRendering = False assert visible in (0,1, True, False) self.visible = visible self.kfpos = kfpos self.objectName = objectName if objectFromString is None: objectFromString = getObjectFromString(objects) self.objectFromString = objectFromString if visible: self.shortName = "Show" else: self.shortName = "Hide" for geom in objects: actor = getActor(geom, "visible") self.origValues[actor.name] = actor.getValueFromObject() kf1 = KF(kfpos, visible) actor.actions.addKeyframe(kf1) self.AddActions( actor, actor.actions ) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import VisibleObjectMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = VisibleObjectMAA(object, objectName='%s', kfpos=%s, visible=%s, objectFromString = "%s", startFlag='%s')\n""" % (varname, self.objectName, self.kfpos, self.visible, self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines from DejaVu.Transformable import Transformable class OrientationMAA(RedrawMAA): """ create a MAA for going from any orientation to the current orientation The orientation includes: the object's rotation, translation, scale, pivot point, and teh camera field of view is modified to zoom out between the 2 first keyframes and zoom back in between the 2 last keyframes """ def __init__(self, object, name, orient, rendering, keyPos=[0, 10, 20, 30], # rotation=None, translation=None, scale=None, # pivot=None, fieldOfView=None, lookFrom=None, objectFromString=None, startFlag="after previous"): """ constructor MAA <- OrientationMAA( object, name, keyPos=[0, 10, 20, 30], rotation=None, translation=None, scale=None, pivot=None, fieldOfView=None, lookFrom=None, objectFromString=None, startFlag='after previous') - object is a DejaVu Transformable object that belongs to a DejaVu Viewer - name is the name for the MAA - orient is a dictionary with the following keys: -- rotation -- translation -- scale -- pivot -- fieldOfView -- lookFrom -- near -- far -- fogStart -- fogEnd - rendering is a dictionary storing the state of all geometries; - keyPos is a list of 4 positions. Zoom out will happen between the 2 first keyframes and zoom in between the 2 last. - objectFromString is a string that yields the viewer's oject when evaluated. - startFlag - flag used in a sequence animator for computing time position of the maa . """ assert isinstance(object, Transformable) assert isinstance(object.viewer, Viewer) RedrawMAA.__init__(self, object.viewer, name, startFlag) self.forceOrient = False self.forceRendering = False ## define the class of the editor for this MAA ## the presence of the .editorClass attribute will enable the edit ## button in the sequence animator ## For this to work the folloing method have to work ## self.getValues() ## MAAEditor.setValues(**kw) ## MAAEditor.getValues() ## MAAEditor.execute(self, name) has to configure self.maa ## with the current parameters (MAAEditor.getValues() ) from DejaVu.scenarioInterface.animationGUI import OrientationMAAEditor self.editorClass = OrientationMAAEditor self.object = object if objectFromString is None: try: objectFromString = "viewer.FindObjectByName('%s')" % object.fullName except: pass self.objectFromString = objectFromString self._maaGroup = None # will be a weakref to MAAGroup self.orient = {} if not orient: orient = self.getCurrentOrient() self.makeMAA(keyPos, orient, rendering) def getCurrentOrient(self): orient = {} cam = self.object.viewer.currentCamera fieldOfView = cam.fovy lookFrom = cam.lookFrom.copy() orient['fieldOfView'] = fieldOfView orient['lookFrom'] = lookFrom orient['near'] = cam.near orient['far'] = cam.far orient['fogStart'] = cam.fog.start orient['fogEnd'] = cam.fog.end for obj in self.object.AllObjects(): if not obj.animatable: continue oname = obj.fullName orient[oname] = {'rotation':obj.rotation[:], 'translation':obj.translation[:], 'scale':obj.scale[:], 'pivot':obj.pivot[:]} return orient def makeMAA(self, keyPos, orient=None, rendering=None): # create all actors and their actions and add them to the MAA #print "makeMaa:", self.name, keyPos self.keyPos = keyPos if rendering: self.rendering = rendering if orient: self.orient = orient else: orient = self.orient cam = self.object.viewer.currentCamera fieldOfView = orient['fieldOfView'] lookFrom = orient['lookFrom'] near = orient['near'] far = orient['far'] fogStart = orient['fogStart'] fogEnd = orient['fogEnd'] if keyPos[-1] - keyPos[0] == 1: p1 = keyPos[0] actor = getActor(cam, 'fieldOfView') actor.actions.addKeyframe(KF( p1, fieldOfView)) self.AddActions( actor, actor.actions ) actor = getActor(cam, 'lookFrom') actor.actions.addKeyframe(KF( p1, lookFrom)) kf2 = KF( keyPos[-1], 'Nothing There') actor.actions.addKeyframe(kf2) self.AddActions( actor, actor.actions ) actor = getActor(cam, 'near') actor.actions.addKeyframe(KF( p1, near)) self.AddActions( actor, actor.actions ) actor = getActor(cam, 'far') actor.actions.addKeyframe(KF( p1, far)) self.AddActions( actor, actor.actions ) actor = getActor(cam.fog, 'start') actor.actions.addKeyframe(KF( p1, fogStart)) self.AddActions( actor, actor.actions ) actor = getActor(cam.fog, 'end') actor.actions.addKeyframe(KF( p1, fogEnd)) self.AddActions( actor, actor.actions ) else: p1, p2, p3, p4 = keyPos actor = getActor(cam, 'fieldOfView') k0 = KFAutoCurrentValue( p1, actor) #k1 = KF( p2, cam.fovyNeutral) #k2 = KF( p3, cam.fovyNeutral) k3 = KF( p4, fieldOfView) #actor.addIntervals( [ Interval(k0,k1), Interval(k1,k2), # Interval(k2,k3), Interval(k2,k3) ] ) actor.addIntervals( [ Interval(k0,k3)] ) self.AddActions( actor, actor.actions ) actor = getActor(cam, 'lookFrom') kf0 = KFAutoCurrentValue( p1, actor) kf1 = KF( p4, lookFrom) i = Interval( kf0, kf1) actor.addIntervals( [i] ) self.AddActions( actor, actor.actions ) actor = getActor(cam, 'near') kf0 = KFAutoCurrentValue( p1, actor) kf1 = KF( p4, near) actor.addIntervals( [Interval(kf0,kf1)] ) self.AddActions( actor, actor.actions ) actor = getActor(cam, 'far') kf0 = KFAutoCurrentValue( p1, actor) kf1 = KF( p4, far) actor.addIntervals( [Interval(kf0,kf1)] ) self.AddActions( actor, actor.actions ) actor = getActor(cam.fog, 'start') kf0 = KFAutoCurrentValue( p1, actor) kf1 = KF( p4, fogStart) actor.addIntervals( [Interval(kf0,kf1)] ) self.AddActions( actor, actor.actions ) actor = getActor(cam.fog, 'end') kf0 = KFAutoCurrentValue( p1, actor) kf1 = KF( p4, fogEnd) actor.addIntervals( [Interval(kf0,kf1)] ) self.AddActions( actor, actor.actions ) #from time import time #t1 = time() for obj in self.object.AllObjects(): if not obj.animatable: continue oname = obj.fullName objorient = orient.get(oname, None) if not objorient: continue rotation = objorient['rotation'] translation = objorient['translation'] scale = objorient['scale'] pivot = objorient['pivot'] val = [matToQuaternion(rotation), translation, scale, pivot] if keyPos[-1] - keyPos[0] == 1: #create one key frame with current (at maa creation time) values p1 = keyPos[0] actor = getActor(obj, 'transformation') actor.actions.addKeyframe(KF( p1, val)) self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'rotation') ## actor.actions.addKeyframe(KF( p1, matToQuaternion(rotation)) ) ## self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'translation') ## actor.actions.addKeyframe(KF( p1, translation ) ) ## self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'scale') ## actor.actions.addKeyframe(KF( p1, scale) ) ## self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'pivot') ## actor.actions.addKeyframe(KF( p1, pivot)) ## self.AddActions( actor, actor.actions ) else: # create transition from current at play time to what it is at creation time p1, p2, p3, p4 = keyPos actor = getActor(obj, 'transformation') kf0 = KFAutoCurrentValue( p1 , actor) kf1 = KF( p4, val) i = Interval( kf0, kf1, generator=actor.behaviorList) actor.addIntervals( [i] ) self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'rotation') ## kf0 = KFAutoCurrentValue( p1 , actor) ## kf1 = KF( p4, matToQuaternion(rotation) ) ## i = Interval( kf0, kf1, generator=actor.behaviorList) ## actor.addIntervals( [i] ) ## self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'translation') ## kf0 = KFAutoCurrentValue( p1 , actor ) ## kf1 = KF( p4, translation ) ## actor.addIntervals( [ (kf0, kf1) ] ) ## self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'scale') ## kf0 = KFAutoCurrentValue( p1, actor) ## kf1 = KF( p4, scale) ## i = Interval( kf0, kf1 ) ## actor.addIntervals( [i] ) ## self.AddActions( actor, actor.actions ) ## actor = getActor(obj, 'pivot') ## kf0 = KFAutoCurrentValue( p1, actor) ## kf1 = KF( p4, pivot) ## i = Interval( kf0, kf1 ) ## actor.addIntervals( [i] ) ## self.AddActions( actor, actor.actions ) #print self.getStringRepr()[-1] def setKeyframePositions(self, keyPos): """ change all KF to reflect the positions """ self.removeNonRedrawActors() self.makeMAA(keyPos) #def configure(self, **kw): # self.setKeyframePositions(kw['keyframes']) def getValues(self): """ returns the parameters of this MAA, i.e. 3 keyframes positions """ return {'keyframes': self.keyPos, 'forceOrient':self.forceOrient, 'forceRendering':self.forceRendering} def orient2string(self): """returns a string representation of stored orientation. Replaces numeric arrays by lists""" orient = {} import numpy, types allkeys = self.orient.keys() for k in ['lookFrom', 'fieldOfView']: val = self.orient[k] if type(val) == numpy.ndarray: val = val.tolist() orient[k]=val allkeys.remove(k) for k in ['fogStart', 'fogEnd', 'far', 'near']: orient[k] = self.orient[k] allkeys.remove(k) for name in allkeys: objorient = self.orient[name] orient[name] = {} for k, val in objorient.items(): if type(val) == numpy.ndarray: val = val.tolist() orient[name][k] = val return """%s"""%orient def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import OrientationMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) lines += tabs + """from numpy import *\n""" import numpy, types # avoid array summarization in the string (ex: "[0, 1, 2, ..., 7, 8, 9]" ) ## oldopts = numpy.get_printoptions() ## maxlen = oldopts["threshold"] ## for val in self.rendering.values(): ## if type(val) == types.DictType: ## for val1 in val.values(): ## if type(val1) == numpy.ndarray: ## maxlen = max(maxlen, len(val1.flat)) ## elif type(val) == numpy.ndarray: ## maxlen = max(maxlen, len(val.flat)) ## numpy.set_printoptions(threshold = maxlen, precision=4) numpy.set_string_function(numarr2str) #print "maxlen", maxlen lines += tabs + """rendering=%s\n""" % (self.rendering) lines += tabs + """orient=%s\n""" % self.orient2string() newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = OrientationMAA(object, '%s', orient, rendering, keyPos=%s, objectFromString="%s", startFlag='%s')\n"""%(varname, self.name, self.keyPos, self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" #numpy.set_printoptions(threshold=oldopts["threshold"], precision=oldopts["precision"]) from numpy import array_repr numpy.set_string_function(array_repr) return lines from time import time class SnapshotMAAGroup(MAAGroup): """Create an MAA Group consisting of OrientationMAA and RenderingTransitionMAA""" def __init__(self, orientMaa, renderMaa, name='snapshot', startFlag="after previous"): """SnapshotMAAGroup constructor SnapshotMAAGroup <- SnapshotMAAGroup(orientMaa, renderMaa, name='snapshot', startFlag='after previous') """ assert isinstance(orientMaa, OrientationMAA) assert isinstance(renderMaa, RenderingTransitionMAA) MAAGroup.__init__(self, name=name, maalist=[orientMaa, renderMaa], startFlag=startFlag) self.orientMaa = orientMaa self.renderMaa = renderMaa self.sortPoly = 'Once' self.sortOrder = "-Zsort" from DejaVu.scenarioInterface.animationGUI import SnapshotMAAGroupEditor self.editorClass = SnapshotMAAGroupEditor #orientMaa.editorClass # if the following attributes are set to False - we will not #interpolate orientation or rendering self.interpolateOrient = True self.interpolateRendering = True self.forceRendering = False self.forceOrient = False self.editorKw = {} self.editorArgs = [] self.rendering = orientMaa.rendering self.orient = orientMaa.orient self.kfpos = renderMaa.kfpos def run(self): ## if self.orientMaa.forceRendering: ## setRendering(self.orientMaa.viewer, self.orientMaa.rendering) ## self.orientMaa.run() if self.interpolateRendering : # modify (morph) rendering t1 = time() self.renderMaa.setValuesAt(0, run=False) if self.interpolateOrient: self.makeActorList([self.renderMaa, self.orientMaa], reverse=True) else: self.makeActorList([self.renderMaa], reverse=True) t2 = time() #print 'time to makeActorList', t2-t1 t1 = t2 MAAGroup.run(self) t2 = time() #print 'time to MAAGroup.run', t2-t1 t1 = t2 try: self.setGeomAtomProp() t2 = time() #print 'time to setGeomAtomProp', t2-t1 except: pass else: if self.interpolateOrient: self.orientMaa.run() def getValues(self): """ returns the parameters of this MAA, i.e. 3 keyframes positions """ return {'keyframes': self.renderMaa.kfpos, 'interpolateOrient':self.interpolateOrient, 'interpolateRendering':self.interpolateRendering, 'sortPoly': self.sortPoly, 'sortOrder': self.sortOrder} def recordOrient(self): #print self.name, "record orient" orient = self.orient = self.orientMaa.getCurrentOrient() self.orientMaa.removeNonRedrawActors() kf1, kf2 = self.kfpos self.orientMaa.makeMAA([kf1, kf2/3, 2*kf2/3, kf2], orient=orient) def recordRendering(self): #print self.name, "record rendering" self.rendering = getRendering(self.orientMaa.viewer, checkAnimatable=True) self.orientMaa.rendering = self.rendering self.renderMaa.rendering = self.rendering try: self.renderMaa.saveGeomAtomProp() except: pass def setKeyframePositions(self, keyPos): #print "Setting keyframePositions:", keyPos assert len(keyPos) == 2 nbframes = keyPos[1] self.orientMaa.setKeyframePositions([0, nbframes/3, 2*nbframes/3, nbframes]) self.kfpos = self.renderMaa.kfpos = keyPos self.firstPosition, self.lastPosition = keyPos #print "firstPosition:", self.firstPosition, "lastPosition:", self.lastPosition self.makeActorList() def configure(self, **kw): if kw.has_key('kfpos'): self.setKeyframePositions(kw['kfpos']) def setValuesAt(self, frame, pos=0): self.needsRedraw = False if self.interpolateOrient: self.orientMaa.setValuesAt(frame, pos) if self.interpolateRendering: self.renderMaa.setValuesAt(frame, pos) #if self.renderMaa.needsRedraw: # self.needsRedraw = True if self.renderMaa.needsRedraw or self.orientMaa.needsRedraw: self.needsRedraw = True if frame == pos + self.lastPosition: if self._director and frame == self._director().endFrame-1: try: self.setGeomAtomProp() except: pass def getSourceCode(self, varname, indent = 0): """ Return python code creating this object """ tabs = " "*indent newtabs = tabs + 4*" " lines = tabs + """from DejaVu.scenarioInterface.animations import SnapshotMAAGroup\n""" lines += tabs + """%sorient = None\n""" % (varname,) lines += self.orientMaa.getSourceCode("%sorient" % varname, indent=indent) lines += tabs + """%srender = None\n""" % (varname,) lines += self.renderMaa.getSourceCode("%srender" % varname, indent=indent, saverendering=False) lines += tabs + """if %sorient is not None and %srender is not None:\n"""%(varname, varname) lines += newtabs + """%srender.rendering = %sorient.rendering\n"""%(varname, varname) lines += newtabs +"""%s = SnapshotMAAGroup(%sorient, %srender, name='%s', startFlag='%s')\n""" %(varname, varname, varname, self.name, self.startFlag) lines += newtabs +"""%s.interpolateOrient = %s\n""" % (varname, self.interpolateOrient) lines += newtabs +"""%s.interpolateRendering = %s\n""" % (varname, self.interpolateRendering) return lines def setGeomAtomProp(self): self.renderMaa.setGeomAtomProp() def findOpacityGeoms(self): return self.renderMaa.findOpacityGeoms() def reorderTransparentChildren(self, parents): return self.renderMaa.reorderTransparentChildren(parents) def copy(self): object = self.orientMaa.object orient = self.orientMaa.orient rendering = self.renderMaa.rendering orientMaa = OrientationMAA(object, self.orientMaa.name, orient, rendering, objectFromString=self.orientMaa.objectFromString, keyPos=self.orientMaa.keyPos, startFlag=self.orientMaa.startFlag) renderMaa = RenderingTransitionMAA(self.renderMaa.viewer, rendering = rendering, kfpos=self.renderMaa.kfpos, name=self.renderMaa.name, startFlag=self.renderMaa.startFlag, saveAtomProp=False) renderMaa.atomSets = self.renderMaa.atomSets newmaa = self.__class__(orientMaa, renderMaa, self.name) return newmaa class FlyObjectMAA(RedrawMAA): """ Create an MAA for flying an object in or out of the scene """ def __init__(self, object, objectName=None, kfpos=[0, 30], direction="left", easeInOut='none', objectFromString=None, startFlag="after previous", inViewTranslation=None): """ constructor MAA <- FlyObjectMAA( object, name, objectName=None, kfpos=0, visible = 1, objectFromString=None, startFlag='after previous') - object - a DejaVu Transformable object - objectName - a short name used to name the MAA - kfpos - list of 2 keyframe position defining length of transition - direction - can be 'left', 'right', 'top', bottom' - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - objectFromString is a string that yields the specified object(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa """ if not hasattr(object, "__len__"): objects = [object] else: objects = object RedrawMAA.__init__(self, objects[0].viewer, None, startFlag) # set the editor class so this MAA is editable from DejaVu.scenarioInterface.animationGUI import SED_MAAEditor self.editorClass = SED_MAAEditor self.editorKw = {'directions': ['left', 'right', 'top', 'bottom']} self.setOrient = True if objectFromString is None: objectFromString = getObjectFromString(objects) self.objectFromString = objectFromString self.objects = objects self.objectName = objectName self.inViewTranslation = {} if inViewTranslation is not None: for obj in self.objects: if inViewTranslation.has_key(obj.fullName): self.inViewTranslation[obj.fullName] = inViewTranslation[obj.fullName] else: self.inViewTranslation[obj.fullName] = self.getInViewTranslation(obj) else: for obj in self.objects: #self.inViewTranslation[obj] = obj.translation.copy() self.inViewTranslation[obj.fullName] = self.getInViewTranslation(obj) self.geomOrients = {} for obj in self.objects: current = obj while current.parent: parent = current.parent if not self.geomOrients.has_key(parent): cameraInfo = False if parent == self.viewer.rootObject: cameraInfo = True self.geomOrients[parent] = getOrientation(parent, camera=cameraInfo) current = parent self.makeMAA(kfpos=kfpos, direction=direction, easeInOut=easeInOut) def makeMAA(self, kfpos=[0,30], direction='left', easeInOut='none', easeInEnd=0.3, easeOutStart=0.7): # save what we need to be able to recreate this object assert len(kfpos)==2 self.kfpos = kfpos assert direction in ['left', 'right', 'top', 'bottom'] self.direction = direction assert easeInOut in ['none', 'ease in', 'ease out', 'ease in and out'] self.easeInOut = easeInOut self.easeInEnd = easeInEnd self.easeOutStart = easeOutStart for obj in self.objects: # add visible actor visibleactor = getActor(obj, 'visible') kf1 = KF(self.kfpos[0], 1) visibleactor.actions.addKeyframe(kf1) self.AddActions( visibleactor, visibleactor.actions ) # add translation actor translationactor = getActor(obj, 'translation') translationactor.setEaseInOut(easeInOut) self.setActorsActions(translationactor, self.inViewTranslation[obj.fullName]) if translationactor.actions is not None: self.AddActions( translationactor, translationactor.actions ) self.name = self.getMAAname() def getInViewTranslation(self, object): """ Get translation of the object when it is in the camera view""" vi = object.viewer if object != vi.rootObject: return numpy.array([0,0,0], 'f') # root object # the following is based on code from Viewer.NormalizeCurrentObject() mini, maxi = object.ComputeBB() g = numpy.add.reduce( (mini, maxi) ) * .5 d = list(-g[:3])+[1.0] rot = numpy.reshape( object.R, (4,4) ) translation = object.translation + object.multMat4pt(rot, d) #print "in view translation:", object.name, translation return translation def setActorsActions(self, actor, inViewTranslation ): """ create a keyframes and interval for fly action """ #method overwriden in FlyInObjectMAA and FlyOutObjectMAA pass def getMAAname(self): """Create name for this MAA """ #method overwriden in FlyInObjectMAA and FlyOutObjectMAA pass def getFlyObjectVal(self, actor, direction, inViewTranslation): """ compute a translation that moves the object out of the view. """ actor = self.findActor(actor) if not actor: return obj = actor.object vi = obj.viewer c = vi.cameras[0] Xc , Yc, Zc = c.lookFrom Xo , Yo, Zo = obj.getCumulatedTranslation() #d = math.sqrt( (Xc -Xo)*(Xc -Xo) + (Yc -Yo)*(Yc -Yo) + (Zc -Zo)*(Zc -Zo) ) d = math.fabs(Zc -Zo) tgTetaOver2 = math.tan(.5*c.fovy * math.pi/180.) w = c.width h = c.height tgAlphaOver2 = tgTetaOver2 * w/float(h) lx = d * tgAlphaOver2 ly = d * tgTetaOver2 #print "getFlyObjectVal: object", obj, "in view transl:", inViewTranslation trans = numpy.array(inViewTranslation) minbb, maxbb = obj.ComputeBB() if direction == "left": d = maxbb[0] - minbb[0] trans[0] = -lx - d elif direction == "right": d = maxbb[0] - minbb[0] trans[0] = lx + d elif direction == "top": d = maxbb[1] - minbb[1] trans[1] = ly + d else: d = maxbb[1] - minbb[1] trans[1] = -ly - d #print "translation = ", trans # to correct the existing rotation of the rootObject if obj != vi.rootObject: lInvMat = vi.rootObject.GetMatrixInverse() lInvMat.shape= (16) rot, transl, scale = vi.rootObject.Decompose4x4(lInvMat) rot.shape= (4,4) ltrans = numpy.array([trans[0],trans[1],trans[2],1.]) ltrans.shape= (4,1) trans = numpy.dot( rot , ltrans ) trans = [trans[0,0],trans[1,0],trans[2,0]] #print "final trans", trans return trans def getValues(self): """ returns the parameters of this MAA, i.e. 3 keyframes positions """ return {'kfpos': self.kfpos, 'direction': self.direction, 'easeInOut': self.easeInOut, 'forceOrient':self.forceOrient, 'forceRendering':self.forceRendering, 'easeInEnd': self.easeInEnd, 'easeOutStart': self.easeOutStart} def configure(self, **kw): """ set kfpos, direction and easeInOut and rebuild MAA """ self.removeNonRedrawActors() # handle forceOrient and force Rendering RedrawMAA.configure(self, **kw) if kw.has_key('forceOrient'): kw.pop('forceOrient') if kw.has_key('forceRendering'): kw.pop('forceRendering') # add missing keys to avoid default values to override current values if not kw.has_key('direction'): kw['direction'] = self.direction if not kw.has_key('kfpos'): kw['kfpos'] = self.kfpos if not kw.has_key('easeInOut'): kw['easeInOut'] = self.easeInOut self.makeMAA( **kw ) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import %s\n""" % (self.__class__.__name__) lines += tabs + """object = %s\n"""%(self.objectFromString) lines += tabs + """geomOrients={}\n""" for k, val in self.geomOrients.items(): lines += tabs + """obj = viewer.FindObjectByName('%s')\n""" % (k.fullName,) lines += tabs + """objorient = %s\n""" % self.getDictString(val) lines += tabs + """if obj: geomOrients[obj] = objorient\n""" newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = %s(object, objectName='%s', kfpos=%s, direction='%s', easeInOut='%s', objectFromString="%s", startFlag='%s', inViewTranslation=%s)\n""" % (varname, self.__class__.__name__, self.objectName, self.kfpos, self.direction, self.easeInOut, self.objectFromString, self.startFlag, self.getDictString(self.inViewTranslation) ) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += self.getRenderingString(None, indent+4) lines += newtabs + """%s.rendering=rendering\n"""% (varname,) lines += newtabs + """%s.orient=%s\n""" % (varname, self.getDictString(self.orient)) lines += newtabs + """%s.geomOrients = geomOrients\n"""% (varname,) if not self.forceRendering: lines += newtabs + """%s.forceRendering = False\n"""% (varname, ) if not self.forceOrient: lines += newtabs + """%s.forceOrient = False\n"""% (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines class FlyInObjectMAA(FlyObjectMAA): """ Create an MAA for flying an object in to the camera view. The user specifies the direction to fly the object from. The direction is one of the following: left, top, right, bottom. """ def __init__(self, object, objectName=None, kfpos=[0, 30], direction="left", easeInOut='none', objectFromString=None, startFlag="after previous", inViewTranslation=None): """ constructor MAA <- FlyInObjectMAA( object, objectName=None, kfpos=[0,30], direction='left', easeInOut='none', objectFromString=None, startFlag='after previous') - object - a DejaVu Transformable object - objectName - a short name used to name the MAA - kfpos - list of 2 keyframe position defining length of transition - direction - can be 'left', 'right', 'top', bottom' - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - objectFromString is a string that yields the specified object(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa """ FlyObjectMAA.__init__( self, object, objectName=objectName, kfpos=kfpos, direction=direction, easeInOut=easeInOut, objectFromString=objectFromString, startFlag=startFlag, inViewTranslation=inViewTranslation) self.editorKw['title'] = 'Fly Out Editor' self.shortName = "FlyIn" def setActorsActions(self, actor, inViewTranslation): """ Add keyframes and a valuegenerating interval to the actor. create a keyframe that computes it's value at run time to move the object out of view. """ kf1 = KFValueFromFunction( self.kfpos[0], CallbackFunction( self.getFlyObjectVal, actor, self.direction, inViewTranslation) ) kf2 = KF(self.kfpos[1], inViewTranslation) i1 = Interval( kf1, kf2, generator=actor.behaviorList, easeInEnd=self.easeInEnd, easeOutStart=self.easeOutStart) actor.addIntervals( [i1] ) def getMAAname(self): """Create name for this MAA """ return "fly in %s from %s"% (self.objectName, self.direction) class FlyOutObjectMAA(FlyObjectMAA): """ Create an MAA for flying an object out of the camera view. The user specifies the direction to fly the object to. The direction is one of the following: left, top, right, bottom. """ def __init__(self, object, objectName=None, kfpos=[0,30], direction="left", easeInOut='none', objectFromString=None, startFlag="after previous", inViewTranslation=None): """ constructor MAA <- FlyOutObjectMAA( object, objectName=None, kfpos=[0,30], direction='left', easeInOut='none', objectFromString=None, startFlag='after previous') - object - a DejaVu Transformable object - objectName - a short object name used to name the MAA - kfpos - list of 2 keyframe position defining length of transition - direction - can be 'left', 'right', 'top', bottom' - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - objectFromString is a string that yields the specified object(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa """ FlyObjectMAA.__init__( self, object, objectName=objectName, kfpos=kfpos, direction=direction, easeInOut=easeInOut, objectFromString=objectFromString, startFlag=startFlag, inViewTranslation=inViewTranslation) self.editorKw['title'] = 'Fly Out Editor' self.shortName = "FlyOut" def setActorsActions(self, actor, inViewTranslation): """ Add keyframes and a valuegenerating interval to the actor. create a keyframe that computes it's value at run time to move the object out of view. """ kf1 = KF(self.kfpos[0], inViewTranslation) kf2 = KFValueFromFunction(self.kfpos[1], CallbackFunction( self.getFlyObjectVal, actor, self.direction, inViewTranslation)) i1 = Interval( kf1, kf2, generator=actor.behaviorList,easeInEnd=self.easeInEnd, easeOutStart=self.easeOutStart) actor.addIntervals( [i1] ) def getMAAname(self): """Create name for this MAA """ return "fly out %s %s"% (self.objectName, self.direction) class FadeObjectMAA(RedrawMAA): """ Create an MAA for fading one or more objects in or out """ def __init__(self, objects, name, objectName, kfpos=[0, 30], easeInOut='none', sortPoly='Once', sortOrder='-Zsort', objectFromString=None, startFlag="after previous"): """ constructor MAA <- FadeObjectMAA( objects, name, objectName, kfpos=[0,30], easeInOut='none', sortPoly='Once', sortOrder='-Zsort', objectFromString=None, startFlag='after previous') - object - a DejaVu Transformable object - name - maa name - objectName - a short name used to name the MAA - kfpos - list of 2 keyframe position defining length of transition - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - sortPoly - can be 'Once', 'Never', 'Always' - sortOrder - can be '+Zsort', '-Zsort' - objectFromString is a string that yields the specified object(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa """ vi = objects[0].viewer RedrawMAA.__init__(self, vi, name, startFlag) from DejaVu.scenarioInterface.animationGUI import SESp_MAAEditor self.editorClass = SESp_MAAEditor if objectFromString is None: objectFromString = getObjectFromString(objects) self.objectFromString = objectFromString self.objects = objects self.objectName = objectName self.makeMAA(kfpos=kfpos, easeInOut=easeInOut, sortPoly=sortPoly, sortOrder=sortOrder) def makeMAA(self, kfpos=[0,30], easeInOut='none', sortPoly='Once', sortOrder="-Zsort", easeInEnd=0.3, easeOutStart=0.7 ): # save what we need to be able to recreate this object self.kfpos = kfpos self.easeInOut = easeInOut self.easeInEnd=easeInEnd self.easeOutStart=easeOutStart self.sortPoly = sortPoly # can be 'Never', 'Once', or 'Always' self.sortOrder = sortOrder for obj in self.objects: # create opacity actor opacityactor = getActor(obj, 'opacity') self.origValues[opacityactor.name] = opacityactor.getValueFromObject() opacityactor.setEaseInOut(easeInOut) # create visibility actor visibleactor = getActor(obj, 'visible') self.origValues[visibleactor.name] = visibleactor.getValueFromObject() kf1 = KF(self.kfpos[0], 1) visibleactor.actions.addKeyframe(kf1) # call method tha creates keyframes and intervals for Fade In or Out actors = [opacityactor, visibleactor] self.setActorsActions(actors) # add actions from visibility and opacity actors to maa for actor in actors: if actor.actions is not None: self.AddActions( actor, actor.actions ) def setActorsActions(self, actor): """this method should be overwritten be FlyInObjectMAA and FlyOutObjectMAA classes""" pass def getValues(self): """ returns the parameters of this MAA, i.e. 3 keyframes positions """ return {'kfpos': self.kfpos, 'sortPoly': self.sortPoly, 'sortOrder': self.sortOrder, 'easeInOut': self.easeInOut, 'forceOrient':self.forceOrient, 'forceRendering':self.forceRendering, 'easeInEnd': self.easeInEnd, 'easeOutStart': self.easeOutStart} def configure(self, **kw): """ set kfpos, direction and easeInOut and rebuild MAA """ self.removeNonRedrawActors() # handle forceOrient and force Rendering RedrawMAA.configure(self, **kw) if kw.has_key('forceOrient'): kw.pop('forceOrient') if kw.has_key('forceRendering'): kw.pop('forceRendering') # add missing keys to avoid default values to override current values if not kw.has_key('sortPoly'): kw['sortPoly'] = self.sortPoly if not kw.has_key('sortOrder'): kw['sortOrder'] = self.sortOrder if not kw.has_key('kfpos'): kw['kfpos'] = self.kfpos if not kw.has_key('easeInOut'): kw['easeInOut'] = self.easeInOut self.makeMAA( **kw ) def copy(self): newmaa = self.__class__(objects, name, objectName, kfpos=[0, 30], easeInOut='none', sortPoly='Once', objectFromString=None, startFlag="after previous") newmaa.forceOrient = self.forceOrient newmaa.orient = self.orient newmaa.forceRendering = self.forceRendering newmaa.rendering = self.rendering newmaa.sortOrder = self.sortOrder return newmaa class FadeInObjectMAA(FadeObjectMAA): """ Create an MAA for 'fading in' a geometric object by interpolating the opacity of the object from 0 to 1 """ def __init__(self, objects, name = None, objectName=None, kfpos=[0,30], easeInOut='none', sortPoly='Once', sortOrder='-Zsort', objectFromString=None, startFlag="after previous"): """ constructor MAA <- FadeInObjectMAA( objects, objectName=None, kfpos=[0,30], easeInOut='none', sortPoly='Once', sortOrder='-Zsort', objectFromString=None, startFlag='after previous') - object - one or a list of DejaVu Transformable objects - objectName - a short name used to name the MAA - kfpos - list of 2 keyframe position defining length of transition - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - sortPoly - can be 'Once', 'Never', 'Always' - sortOrder - can be '+Zsort', '-Zort' - objectFromString is a string that yields the specified object(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa """ if not hasattr(objects, "__len__"): objects = [objects] else: objects = objects geometries = expandGeoms(objects) #print "geometries:", geometries if not len(geometries): self.actors = [] raise ValueError("No geometry to fade for:" , objects) if not name: name = "fade in %s"% (objectName) if objectFromString is None: objectFromString = getObjectFromString(objects) FadeObjectMAA.__init__( self, geometries, name, objectName, kfpos=kfpos, easeInOut=easeInOut, sortPoly=sortPoly, sortOrder=sortOrder, objectFromString=objectFromString, startFlag=startFlag) self.editorKw['title'] = 'Fade In Editor' self.shortName = "FadeIn" def setActorsActions(self, actors): """ Add keyframes and a valuegenerating interval to the actor. """ for actor in actors: if actor.name.find("opacity") > 0: kf1 = KF(self.kfpos[0], 0.) kf2 = KFAutoCurrentValue(self.kfpos[1], actor) val = kf2.getValue() val = actor.initialValue if hasattr(val, "__len__") : if sum(val) == 0: actor.initialValue = [1.] #kf2.getValue([1.]) elif val == 0: #kf2.setValue(1.) actor.initialValue = 1.0 i1 = Interval( kf1, kf2, generator = actor.behaviorList, easeInEnd=self.easeInEnd, easeOutStart=self.easeOutStart) actor.addIntervals( [i1] ) elif actor.name.find("visible") > 0: kf1 = KF(self.kfpos[0], 1) actor.actions.addKeyframe(kf1) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import FadeInObjectMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = FadeInObjectMAA(object, objectName='%s', kfpos=%s, easeInOut='%s', objectFromString="%s", startFlag='%s')\n""" % (varname, self.objectName, self.kfpos, self.easeInOut, self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += self.getRenderingString(None, indent+4) lines += newtabs + """%s.rendering=rendering\n"""% (varname,) lines += newtabs + """%s.orient=%s\n""" % (varname, self.getDictString(self.orient)) if not self.forceRendering: lines += newtabs + """%s.forceRendering = False\n"""% (varname, ) if not self.forceOrient: lines += newtabs + """%s.forceOrient = False\n"""% (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines class FadeOutObjectMAA(FadeObjectMAA): """ Create an MAA for 'fading out' a geometric object by interpolating the opacity of the object from 1 to 0 """ def __init__(self, object, name=None, objectName=None, kfpos=[0,30], easeInOut='none', sortPoly='Once', sortOrder='-Zsort', objectFromString=None, startFlag="after previous"): """ constructor MAA <- FadeInObjectMAA( object, objectName=None, kfpos=[0,30], easeInOut='none', sortPoly='Once', sortOrder='-Zsort', objectFromString=None, startFlag='after previous') - object - one or a list of DejaVu Transformable object - objectName - the object's name. If it is not specified, the class constructor will try to use 'fullName' attribute of the object. - kfpos - list of 2 keyframe position defining length of transition - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - sortPoly - can be 'Once', 'Never', 'Always' - sortOrder can be '-Zsort', '+Zsort' - objectFromString is a string that yields the specified oject(s) when evaluated. - startFlag - flag used in a sequence animator for computing time position of the maa . """ if not hasattr(object, "__len__"): objects = [object] else: objects = object geometries = expandGeoms(objects) if not len(geometries): self.actors = [] raise ValueError("No geoemtry to fade") if not name: name = "fade out %s"% (objectName) if objectFromString is None: objectFromString = getObjectFromString(objects) FadeObjectMAA.__init__( self, geometries, name, objectName, kfpos=kfpos, easeInOut=easeInOut, sortPoly=sortPoly, sortOrder=sortOrder, objectFromString=objectFromString, startFlag=startFlag) self.editorKw['title'] = 'Fade Out Editor' self.shortName = "FadeOut" def setActorsActions(self, actors): """ Add keyframes and a valuegenerating interval to the actor. """ #print "FadeoutObjectMAA", actor for actor in actors: if actor.name.find("opacity") > 0: kf1 = KFAutoCurrentValue(self.kfpos[0], actor) kf2 = KF(self.kfpos[1], 0.) i1 = Interval( kf1, kf2, generator = actor.behaviorList, easeInEnd=self.easeInEnd, easeOutStart=self.easeOutStart) actor.addIntervals( [i1] ) elif actor.name.find("visible") > 0: kf1 = KF(self.kfpos[0], 1) actor.actions.addKeyframe(kf1) #kf2 = KF(self.kfpos[1], 0) #actor.actions.addKeyframe(kf2) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import FadeOutObjectMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = FadeOutObjectMAA(object, objectName='%s', kfpos=%s, easeInOut='%s', objectFromString="%s", startFlag='%s')\n""" % (varname, self.objectName, self.kfpos, self.easeInOut, self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += self.getRenderingString(None, indent+4) lines += newtabs + """%s.rendering=rendering\n"""% (varname,) lines += newtabs + """%s.orient=%s\n""" % (varname, self.getDictString(self.orient)) if not self.forceRendering: lines += newtabs + """%s.forceRendering = False\n"""% (varname, ) if not self.forceOrient: lines += newtabs + """%s.forceOrient = False\n"""% (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines class RotationMAA(RedrawMAA): """ create an MAA for rotation animation """ def __init__(self, object, objectName=None, angle=360, nbFrames=180, vector=(0,1,0), easeInOut='none', direction='counter clockwise', objectFromString=None, startFlag="after previous"): """ constructor MAA <- RotationMAA(object, objectName=None, angle=360, nbFrames=180, vector=(0,1,0), easeInOut='none', irection='counter clockwise', objectFromString=None, startFlag='after previous') - object is an instance of a DejaVu Geom object - objectName - the object's name. If it is not specified, the class - angle is the angular amplitude of the rotation in degrees - nbFrames is the number of Frames for the animation - direction can be either 'clockwise' or 'counter clockwise' - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - objectFromString is a string that yields the specified oject(s) when evaluated. - startFlag - flag used in a sequence animator for computing time position of the maa . """ if not hasattr(object, "__len__"): objects = [object] else: objects = object for obj in objects: assert isinstance(obj, Transformable) assert isinstance(obj.viewer, Viewer) self.objects = objects RedrawMAA.__init__(self, objects[0].viewer, name=None, startFlag=startFlag) from DejaVu.scenarioInterface.animationGUI import Rotation_MAAEditor self.editorClass = Rotation_MAAEditor if objectFromString is None: objectFromString = getObjectFromString(objects) self.objectFromString = objectFromString self.objectName = objectName self.makeMAA( angle=angle, nbFrames=nbFrames, vector=vector, easeInOut=easeInOut, direction=direction) self.shortName = "Rot. " def makeMAA(self, angle=360, nbFrames=180, vector=(0,1,0), easeInOut='none', direction='counter clockwise', easeInEnd=0.3, easeOutStart=0.7): self.angle = angle self.nbFrames = nbFrames self.vector = vector self.easeInOut = easeInOut self.easeInEnd=easeInEnd self.easeOutStart=easeOutStart self.direction = direction # compute rotation increment matrix if direction=='counter clockwise': angleIncr = float(angle) / nbFrames else: angleIncr = 0.0-float(angle) / nbFrames # 2 keyframes are created. The first is at frame 0 and set the # rotation increment matrix. The second one is as nbframes-1 and has # the same rotation increment matrix leading to a constant # interpolation. for obj in self.objects: actor = DejaVuAxisConcatRotationActor( 'axisRotation', obj, axis=vector) actor.setEaseInOut(easeInOut) kf0 = KF( 0 , angleIncr) kf1 = KF( nbFrames-1, angleIncr) actor.addKeyframe( kf0 ) i1 = Interval( kf0, kf1, generator=actor.behaviorList, fullValue=angle, easeInEnd=easeInEnd, easeOutStart=easeOutStart) actor.behaviorList.constant = True actor.addIntervals( [i1] ) self.AddActions( actor, actor.actions ) self.name = '%s %s %s (%s) rotation'% (self.objectName, str(angle), direction, self.getAxis(vector)) def getAxis(self, vector): """ return axis name based in (x, y, z) vector """ x,y,z = vector if x==1 and y==0 and z==0: return 'X' elif x==0 and y==1 and z==0: return 'Y' elif x==0 and y==0 and z==1: return 'Z' elif x==1 and y==1 and z==0: return 'XY' elif x==0 and y==1 and z==1: return 'YZ' elif x==1 and y==0 and z==1: return 'XZ' elif x==1 and y==1 and z==1: return 'XYZ' else: return str(vector) def getValues(self): """ returns the parameters of this MAA, i.e. 3 keyframes positions """ return {'angle': self.angle, 'nbFrames': self.nbFrames, 'vector': self.vector, 'easeInOut': self.easeInOut, 'direction': self.direction, 'forceOrient':self.forceOrient, 'forceRendering':self.forceRendering, 'easeInEnd': self.easeInEnd, 'easeOutStart': self.easeOutStart} def configure(self, **kw): """ set angle, nbFrames, vector, easeInOut, direction, forceOrient and forceRendering and rebuild MAA """ self.removeNonRedrawActors() # handle forceOrient and force Rendering RedrawMAA.configure(self, **kw) if kw.has_key('forceOrient'): kw.pop('forceOrient') if kw.has_key('forceRendering'): kw.pop('forceRendering') # add missing keys to avoid default values to override current values for attr in ['angle', 'nbFrames', 'vector', 'easeInOut', 'direction']: if not kw.has_key(attr): kw[attr] = getattr(self, attr) self.makeMAA( **kw ) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import RotationMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = RotationMAA(object, '%s', nbFrames=%d, angle=%f,"""%( varname, self.objectName, self.nbFrames, self.angle) if self.vector is not None: lines += """ vector=%s,"""%(str(self.vector),) lines += """ direction='%s', """%(self.direction,) lines += """easeInOut='%s', """%(self.easeInOut,) lines += """objectFromString="%s", startFlag='%s')\n""" % (self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += self.getRenderingString(None, indent+4) lines += newtabs + """%s.rendering=rendering\n"""% (varname,) lines += newtabs + """%s.orient=%s\n""" % (varname, self.getDictString(self.orient)) if not self.forceRendering: lines += newtabs + """%s.forceRendering = False\n"""% (varname, ) if not self.forceOrient: lines += newtabs + """%s.forceOrient = False\n"""% (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines class RockMAA(RotationMAA): """ create an MAA for rock animation """ def __init__(self, object, objectName=None, angle=60, nbFrames=60, vector=(0,1,0), objectFromString=None, startFlag='after previous', name=None): """ MAA <- RockMAA(object, objectName=None, nbFrames=180, angle=60, vector=None, objectFromString=None, startFlag='after previous', name=None) - object is an instance of a DejaVu Geom object - objectName - the object's name. - angle is the angular amplitude of the rotation in degrees - nbFrames is the number of Frames for the animation - direction can be either 'clockwise' or 'counter clockwise' - easeInOut - can be 'none', 'ease in', 'ease out', 'ease in and out' - objectFromString is a string that yields the specified oject(s) when evaluated. - startFlag - flag used in a sequence animator for computing time position of the maa . - name - name of this maa.If not cpecified - it is created from objectName+angle+axis of rotation. """ RotationMAA.__init__(self, object, objectName=objectName, angle=angle, nbFrames=nbFrames, vector=vector, objectFromString=objectFromString, startFlag=startFlag) from DejaVu.scenarioInterface.animationGUI import Rock_MAAEditor self.editorClass = Rock_MAAEditor self.shortName = "Rock" if name is not None: self.name=name def makeMAA(self, angle=360, nbFrames=180, vector=(0,1,0), easeInOut='none', direction='counter clockwise', easeInEnd=0.3, easeOutStart=0.7): self.angle = angle self.nbFrames = nbFrames self.vector = vector self.easeInOut = easeInOut self.easeInEnd = easeInEnd self.easeOutStart = easeOutStart self.direction = direction angleIncr = float(angle) / (nbFrames/4) p1 = (0,0,0) p2 = vector mat0 = rotax(p1, p2, 0) mat1 = rotax( p1, p2, angleIncr*math.pi/180.) mat2 = rotax( p1, p2, -angleIncr*math.pi/180.) quat0 = matToQuaternion(mat0.flatten()) quat1 = matToQuaternion(mat1.flatten()) quat2 = matToQuaternion(mat2.flatten()) for obj in self.objects: actor = getActor(obj, 'concatRotation') #actor.setEaseInOut(easeInOut) kf0 = KF( 0 , quat1) # identity matrix at frame 0 kf1 = KF( nbFrames/4, quat0) kf2 = KF( (nbFrames/4)*2, quat2) kf3 = KF( (nbFrames*3)/4, quat0) kf4 = KF( (nbFrames-1), quat1) i1 = Interval( kf0, kf1, generator = actor.behaviorList, easeInEnd=1.0, easeOutStart=1.0) i2 = Interval( kf1, kf2, generator = actor.behaviorList) i3 = Interval( kf2, kf3, generator = actor.behaviorList) i4 = Interval( kf3, kf4, generator = actor.behaviorList, easeInEnd=0.0, easeOutStart=0.0) actor.addIntervals( [i1] ) actor.addIntervals( [i2] ) actor.addIntervals( [i3] ) actor.addIntervals( [i4] ) self.AddActions( actor, actor.actions ) ## actor = self.findActor(actor) ## if easeIn: ## actor.actions.intervals[0].valGen.generator.easeIn = True ## if easeOut: ## actor.actions.intervals[-1].valGen.generator.easeOut = True self.name = '%s %s %s rock'% (self.objectName, str(angle), str(vector)) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import RockMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) newtabs = tabs + 4*" " lines += tabs + """try:\n""" lines += newtabs + """%s = RockMAA(object, '%s', nbFrames=%d, angle=%f,"""%( varname, self.objectName, self.nbFrames, self.angle) if self.vector is not None: lines += """ vector=%s,"""%(str(self.vector),) lines += """ name='%s', """%(self.name,) lines += """objectFromString="%s", startFlag='%s')\n""" % (self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += self.getRenderingString(None, indent+4) lines += newtabs + """%s.rendering=rendering\n"""% (varname,) lines += newtabs + """%s.orient=%s\n""" % (varname, self.getDictString(self.orient)) if not self.forceRendering: lines += newtabs + """%s.forceRendering = False\n"""% (varname, ) if not self.forceOrient: lines += newtabs + """%s.forceOrient = False\n"""% (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines class PartialFadeMAA(FadeObjectMAA): """ Create an MAA for fading in parts of a geometry using per vertex opacity """ def __init__(self, object, initOpac, finalOpac, objectName=None, name=None, nbFrames=None, kfpos=[0,30], easeInOut='none', objectFromString=None, startFlag="after previous"): """ constructor MAA <- PartialFadeMAA( object, initOpac, finalOpac, objectName=None, name=None, nbFrames=None, kfpos=[0,30], easeInOut='none', objectFromString=None, startFlag='after previous') - object - a DejaVu Transformable object (or list of objects) that belong to a DejaVu Viewer; - initOpac - a dictionary {object: opacity array at the beginning of animation}, - finalOpac- a dictionary {object: opacity array at the end of animation}, - objectName - the object's name. If it is not specified, the class constructor will try to use 'fullName' attribute of the object. - name - the MAA name; - kfpos - a list of two keyframe positions specifying the start and end times of the animation; - easeInOut - used to set easeIn and easeOut atributes of all value generators, can be one of the following : 'none', 'ease in', 'ease out', 'ease in and out'; - objectFromString is a string that yields the specified oject(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa . """ if not hasattr(object, "__len__"): objects = [object] else: objects = object nobjects = len(objects) assert len(initOpac) == nobjects assert len(finalOpac) == nobjects self.initOpac = initOpac self.finalOpac = finalOpac if objectName is None: objectName = getObjectName(objects) self.objectName = objectName if name is None: name = "partial fade %s"% (objectName) self.shortName = "pFade" if objectFromString is None: objectFromString = getObjectFromString(objects) #print "object name:", objectName, object.fullName FadeObjectMAA.__init__(self, objects, name, objectName, kfpos=kfpos, easeInOut=easeInOut, objectFromString=objectFromString, startFlag=startFlag) self.objects = objects def setActorsActions(self, actors): """Add keyframes and a valuegenerating interval to the actor.""" #print "PartialFadeinObjectMAA", actor for actor in actors: if actor.name.find("opacity") > 0: obj = actor.object kf1 = KF(self.kfpos[0], self.initOpac[obj]) kf2 = KF(self.kfpos[1], self.finalOpac[obj]) i1 = Interval( kf1, kf2, generator = actor.behaviorList) actor.addIntervals( [i1] ) elif actor.name.find("visible") > 0: kf1 = KF(self.kfpos[0], 1) actor.actions.addKeyframe(kf1) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from numpy import array\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import PartialFadeMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) newtabs = tabs + 4*" " initOpac = """initOpac = {""" finalOpac = """finalOpac = {""" for i, obj in enumerate(self.objects): val1 = self.initOpac[obj] if type(val1) == numpy.ndarray: valstr1 = numarr2str(val1) else: valstr1 = "%s"%val1 initOpac += """object[%d]:%s, """%(i, valstr1) val2 = self.finalOpac[obj] if type(val2) == numpy.ndarray: valstr2 = numarr2str(val2) else: valstr2 = "%s"%val2 finalOpac += """object[%d]:%s, """%(i, valstr2) initOpac += """}\n""" finalOpac += """}\n""" lines += tabs + initOpac lines += tabs + finalOpac lines += self.getRenderingString(None, indent) lines += tabs + """try:\n""" lines += newtabs + """%s = PartialFadeMAA(object, initOpac, finalOpac, objectName='%s', name='%s', kfpos=%s, easeInOut='%s', objectFromString="%s", startFlag='%s')\n""" % (varname, self.objectName, self.name, self.kfpos, self.easeInOut, self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) lines += newtabs + """%s.rendering=rendering\n"""% (varname,) lines += newtabs + """%s.orient=%s\n""" % (varname, self.getDictString(self.orient)) if not self.forceRendering: lines += newtabs + """%s.forceRendering = False\n"""% (varname, ) if not self.forceOrient: lines += newtabs + """%s.forceOrient = False\n"""% (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines from numpy import copy class ColorObjectMAA(RedrawMAA): """ Create an MAA to color an object. ColorObjectMAAobject <- ColorObjectMAA(object, initColors={}, finalColors={}, objectName=None, name=None, nbFrames=None, kfpos=[0,30], colortype = 'choose color', objectFromString=None, startFlag='after previous') arguments: - object - a geometry object (or list of objects) to color; - objectName - the object's name. If it is not specified, the class constructor will try to use 'fullName' attribute of the object. - name - the MAA name; - initColors - a dictionary {object: array of (r,g,b) tuples at the beginning of animation}, - finalColors - a dictionary {object: rray of (r,g,b) tuples at the end of animation}; - objectFromString is a string that yields the specified oject(s) when evaluated; - startFlag - flag used in a sequence animator for computing time position of the maa . """ def __init__(self, object, initColors, finalColors, objectName=None, name=None, nbFrames=None, kfpos=[0,30], colortype="choose color", objectFromString=None, startFlag="after previous", easeInOut='none', **kw): if not hasattr(object, "__len__"): objects = [object] else: objects = object nobjects = len(objects) assert len(initColors) == nobjects assert len(finalColors) == nobjects self.actors = [] self.objects = objects vi = objects[0].viewer if objectName is None: objectName = getObjectName(objects) if objectFromString is None: objectFromString = getObjectFromString(objects) self.objectFromString = objectFromString RedrawMAA.__init__(self, vi, name, startFlag) self.forceOrient = False self.forceRendering = False self.objectName = objectName if name is None: name = "%s %s" % (colortype, objectName) self.name = name if nbFrames: kfpos = [0, nbFrames] self.initColors = initColors self.finalColors = finalColors from DejaVu.scenarioInterface.animationGUI import SECol_MAAEditor self.editorClass = SECol_MAAEditor self.makeMAA(kfpos=kfpos, easeInOut=easeInOut, colortype=colortype) def makeMAA(self, kfpos=[0,30], easeInOut='none', colortype="choose color", easeInEnd=0.3, easeOutStart=0.7): # create visible actor(s) and color actor(s). self.easeInOut = easeInOut self.easeInEnd = easeInEnd self.easeOutStart = easeOutStart for object in self.objects: visibleactor = getActor(object, 'visible') self.origValues[visibleactor.name] = visibleactor.getValueFromObject() kf1 = KF(kfpos[0], 1) visibleactor.actions.addKeyframe(kf1) self.AddActions( visibleactor, visibleactor.actions ) # create color actor. coloractor = self.getColorActor(object, self.finalColors[object], kfpos) self.origValues[coloractor.name] = self.initColors[object] self.kfpos = kfpos self.colortype = colortype def getColorActor(self, object, colors, kfpos): actor = getActor(object, 'colors') actor.setEaseInOut(self.easeInOut) kf1 = KFAutoCurrentValue(kfpos[0], actor) kf2 = KF(kfpos[1], colors) i1 = Interval( kf1, kf2, generator = actor.behaviorList, easeInEnd=self.easeInEnd, easeOutStart=self.easeOutStart) actor.addIntervals( [i1] ) #print "adding actions for actor", actor.name #print "color:" , type(colors) #print col self.AddActions(actor, actor.actions ) return actor def getValues(self): """ returns the parameters of this MAA, i.e. 3 keyframes positions """ return {'kfpos': self.kfpos, #'sortPoly': self.sortPoly, 'easeInOut': self.easeInOut, 'forceOrient':self.forceOrient, 'forceRendering':self.forceRendering, 'colortype': self.colortype, 'easeInEnd': self.easeInEnd, 'easeOutStart': self.easeOutStart} def configure(self, **kw): """ set kfpos, direction and easeInOut and rebuild MAA """ self.removeNonRedrawActors() # handle forceOrient and force Rendering RedrawMAA.configure(self, **kw) if kw.has_key('forceOrient'): kw.pop('forceOrient') if kw.has_key('forceRendering'): kw.pop('forceRendering') # add missing keys to avoid default values to override current values ## if not kw.has_key('sortPoly'): ## kw['sortPoly'] = self.sortPoly if not kw.has_key('kfpos'): kw['kfpos'] = self.kfpos if not kw.has_key('easeInOut'): kw['easeInOut'] = self.easeInOut self.makeMAA( **kw ) def getSourceCode(self, varname, indent=0): """ Return python code creating this object """ if not self.objectFromString: return "" tabs = " "*indent lines = tabs + """import tkMessageBox\n""" lines += tabs + """from numpy import array\n""" lines += tabs + """from DejaVu.scenarioInterface.animations import ColorObjectMAA\n""" lines += tabs + """object = %s\n"""%(self.objectFromString) newtabs = tabs + 4*" " initColors = """initColors = {""" finalColors = """finalColors = {""" for i, obj in enumerate(self.objects): val1 = self.initColors[obj] if type(val1) == numpy.ndarray: valstr1 = numarr2str(val1) else: valstr1 = "%s"%val1 initColors += """object[%d]:%s, """%(i, valstr1) val2 = self.finalColors[obj] if type(val2) == numpy.ndarray: valstr2 = numarr2str(val2) else: valstr2 = "%s"%val2 finalColors += """object[%d]:%s, """%(i, valstr2) initColors += """}\n""" finalColors += """}\n""" lines += tabs + initColors lines += tabs + finalColors lines += tabs + """try:\n""" lines += newtabs + """%s = ColorObjectMAA(object, initColors, finalColors, objectName='%s', name='%s', kfpos=%s, colortype='%s', objectFromString="%s", startFlag='%s')\n""" % (varname, self.objectName, self.name, self.kfpos, self.colortype, self.objectFromString, self.startFlag) lines += newtabs + """assert len(%s.actors) > 0 \n""" % (varname,) if not self.forceRendering: lines += newtabs + """%s.forceRendering = False\n"""% (varname, ) if not self.forceOrient: lines += newtabs + """%s.forceOrient = False\n"""% (varname,) lines += tabs + """except:\n""" lines += newtabs + """if showwarning: tkMessageBox.showwarning('AniMol warning', 'Could not create MAA %s')\n""" % self.name lines += newtabs + """print sys.exc_info()[1]\n""" return lines class FocusMAA(RedrawMAA): """ create an MAA for focucing the camera on the object. """ def __init__(self, object, objectName, name, nbFrames = None, translation=None, scale=None, pivot=None, fieldOfView=None, lookFrom=None): """ constructor MAA <- FocusMAA( object, objectName, name, nbFrames = None, translation=None, scale=None, pivot=None, fieldOfView=None, lookFrom=None) object is a DejaVu Transformable object that belongs to a DejaVu Viewer name ifs the name for the MAA kfpos is a list of 2 positions. translation scale pivot fieldOfView lookFrom """ assert isinstance(object, Transformable) assert isinstance(object.viewer, Viewer) self.objectName = objectName self.nbFrames = nbFrames RedrawMAA.__init__(self, object.viewer, name) # create all actors and their actions and add them to the MAA cam = self.camera = object.viewer.currentCamera p1, p2 = [0, nbFrames-1] # actor look at actor = getActor(cam, "lookAt") actor.actions.addKeyframe(KF(p1, numpy.array([0.,0.,0.] ) )) self.AddActions( actor, actor.actions ) # scale actor for root object rootObject = self.rootObject=object.viewer.rootObject actor = getActor(rootObject, 'scale') self.origValues[actor.name] = actor.getValueFromObject() actor.actions.addKeyframe(KF(p1, [1.,1.,1.] )) self.AddActions( actor, actor.actions ) # translation actor for rootObject actor = getActor(rootObject, 'translation') self.origValues[actor.name] = actor.getValueFromObject() if translation is None: translation = rootObject.translation.copy() self.translation = translation ## kf0 = KFValueFromFunction( p1, self.getRootObjTranslation ) ## kf1 = KFValueFromFunction( p2, self.getRootObjTranslation ) trans = self.getRootObjTranslation() kf0 = KFValueFromFunction( p1, trans) kf1 = KFValueFromFunction( p2, trans) actor.setFunction = self.concatTranslation actor.addIntervals( [ (kf0, kf1) ] ) self.AddActions( actor, actor.actions ) # add field of view actor of current camera actor = getActor(cam, 'fieldOfView') if fieldOfView is None: fieldOfView = cam.fovy self.fieldOfView = fieldOfView diff_fovy = cam.fovyNeutral - fieldOfView k0 = KFAutoCurrentValue( p1, actor) k1 = KF( p2, fieldOfView + (self.nbFrames-1)*diff_fovy/self.nbFrames) actor.addIntervals( [ Interval(k0,k1), Interval(k1,k2)]) self.AddActions( actor, actor.actions ) # actor lookfrom actor = getActor(cam, 'lookFrom') if lookFrom is None: lookFrom = cam.lookFrom.copy() self.lookFrom = lookFrom ## lNewDist = lHalfObject / math.tan(self.currentCamera.fovy/2*math.pi/180.0) ## newDist = self.currentCamera.nearDefault+lNewDist+lHalfObject ## dist = oldLookFrom*(steps-i-1.)/steps + newDist*(i+1.)/steps ## self.currentCamera.lookFrom = Numeric.array( ( 0., 0., dist ) ) ## self.currentCamera.direction = self.currentCamera.lookAt - self.currentCamera.lookFrom def getRootObjTranslation(self): Rmini, Rmaxi = self.rootObject.ComputeBB() Rg = numpy.add.reduce( (Rmini, Rmaxi) ) * .5 diffVect = -g-self.rootObject.translation if not (g-Rg).any(): diffVect = -Rg return diffVect[:3]/float(self.nbFrames) def concatTranslation(self, val): self.rootObject.ConcatTranslation( val ) ############################################################################ ## ## GUI stuff ## ############################################################################ import Pmw, Tkinter from Scenario2 import _clipboard class RotationMAAOptionsGUI: def __init__(self, master, object, objectName): self.object = object self.objectName = objectName if not master: self.parent = parent = Tkinter.Toplevel() else: self.parent = parent = master self.axis = 'Y' self.direction = 'clockwise' self.maa = None self.dialog = Pmw.Dialog(parent, buttons = ('OK', 'Preview', 'Cancel', 'Copy To Clipboard'), defaultbutton = 'Preview', title = 'Full Rotation Options:', command = self.execute) self.dialog.withdraw() parent = self.dialog.interior() self.buttonBox = Pmw.ButtonBox( parent, labelpos = 'nw', label_text = 'Full Rotation Options:', frame_borderwidth = 2, frame_relief = 'groove') # animation name self.namew = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Name:', value = 'Full Rotation Y',) # file name for movie self.filenamew = Pmw.EntryField(parent, labelpos = 'w', label_text = 'Filename:', value='pmvMovie.mpeg') self.namew.pack(side='top', fill='x', expand=1, padx=10, pady=5) self.filenamew.pack(side='top', fill='x', expand=1, padx=10, pady=5) # Create and pack the dropdown ComboBox for axis axes = ('X', 'Y', 'Z', 'XY', 'XZ', 'YZ', 'XYZ') self.axisDropdownw = Pmw.ComboBox( parent, label_text = 'Axis:', labelpos = 'w', selectioncommand = self.changeAxis, scrolledlist_items = axes) self.axisDropdownw.pack(side = 'top', anchor = 'n', fill = 'x', expand = 1, padx = 8, pady = 8) self.axisDropdownw.selectitem(self.axis) self.directionw = Pmw.ComboBox( parent, label_text = 'direction:', labelpos = 'w', selectioncommand = self.changeDirection, scrolledlist_items = ['clockwise', 'counter clockwise']) self.directionw.pack(side = 'top', anchor = 'n', fill = 'x', expand = 1, padx = 8, pady = 8) self.directionw.selectitem(self.direction) # frame number self.nbframesw = Pmw.Counter(parent, labelpos = 'w', label_text = 'Number of Frames:', entry_width = 6, entryfield_value = 180, entryfield_validate = {'validator' : 'integer', 'min' : 1 } ) self.nbframesw.pack(side='top', padx=10, pady=5) self.anglew = Pmw.Counter(parent, labelpos = 'w', label_text = 'Angle (degrees):', entry_width = 6, entryfield_value = 360, entryfield_validate = {'validator':'integer', 'min' : 1 } ) self.anglew.pack(side='top', padx=10, pady=5) # record checkbutton self.recordVar = Tkinter.IntVar() c = Tkinter.Checkbutton(parent, text="Record", variable=self.recordVar) c.pack(side='top', padx=10, pady=5) def changeAxis(self, axis): self.axis = axis self.namew.setvalue('Full Rotation '+self.axis) def changeDirection(self, direction): self.direction = direction self.namew.setvalue('Full Rotation '+self.axis) def _processReturnKey(self, event): self.buttonBox.invoke() def execute(self, result): if result == 'Preview' or result=='OK': self.preview_cb() if result == 'OK' or result=='Cancel': self.hide() if result == 'Copy To Clipboard': if self. maa is None: return from tkSimpleDialog import askstring angle = float(self.anglew.get()) nbFrames = int(self.nbframesw.get()) name = 'Rotation of %d degrees in %d steps about %s'%( angle, nbFrames, str(self.axis)) d = self.buildMAA() _clipboard.addMaa(d) def getName(self, result): if result is None or result == 'Cancel': self.clipboardName = None self.dialog.deactivate(result) else: if result == 'OK': print 'Password entered ' + self.dialog.get() self.dialog.deactivate() def buildMAA(self): angle = float(self.anglew.get()) nbFrames = int(self.nbframesw.get()) name = 'Rotation of %d degrees in %d steps about %s'%( angle, nbFrames, str(self.axis)) self.maa = d = RotationMAA( self.object, self.objectName, angle=angle, axis=self.axis, nbFrames=nbFrames, name=self.namew.getvalue(), direction=self.directionw.get()) return d def preview_cb(self): d = self.buildMAA() if self.recordVar.get(): d.redrawActor.startRecording(self.filenamew.getvalue()) d.run() if self.recordVar.get(): d.redrawActor.stopRecording() def hide(self): self.dialog.deactivate() def show(self, event=None): self.dialog.activate(globalMode = 'nograb') mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/actorFromFile.py0000644000175000017500000000657411063536710026435 0ustar debiandebian import Tkinter import Pmw import tkFileDialog class fromFileForm: """ A class to build a GUI form to get the user's input for creating an actor from file data""" def __init__(self, scenario, propnames, object, command=None): master = Tkinter.Toplevel(scenario.application.master) master.title("Create Actor from File") self.master = master #master.protocol('WM_DELETE_WINDOW', self.dismissCreateActor_cb ) frame = Tkinter.Frame(master, borderwidth=1, relief='ridge') l = Tkinter.Label(frame, text = "Object: %s" % object.fullName) l.grid(column=0, row=0, sticky='w') self.chooser =Pmw.ComboBox(frame, labelpos ='n', label_text='Actors: ', entryfield_value=propnames[0], scrolledlist_items=propnames, fliparrow=1, selectioncommand=self.updateFuncName) self.chooser.grid(column=0, row=1)#, rowspan=3) self.startEF = Pmw.EntryField(frame, labelpos = 'n', label_text = 'start frame: ', entry_width = 8, value = 0, validate = {'validator': 'numeric'}) self.startEF.grid(column = 1, row = 0) self.endEF = Pmw.EntryField(frame, labelpos = 'n', label_text = 'end frame: ', entry_width = 8, ) #validate = {'validator': 'numeric'}) self.endEF.grid(column = 2, row = 0) self.funcnameEF = Pmw.EntryField(frame, labelpos = 'n', label_text = 'function name: ', value = "set_"+propnames[0],) self.funcnameEF.grid(column = 1, row=1, columnspan = 2) b = self.createB = Tkinter.Button(frame, text='Create From File ...', command=self.getValues_cb) b.grid(column=1, row=3, columnspan = 2) frame.pack() self.frame = frame self.command = command self.object = object self.file = None def updateFuncName(self, val): self.funcnameEF.setvalue("set_" + val) def getValues_cb(self): actor = self.chooser.get() #print "actor:", actor try: kf1 = int(self.startEF.get()) except: kf1 = 0 #print "start frame:", kf1 try: kf2 = int(self.endEF.get()) except: kf2 = -1 #print "end frame:", kf2 functionName = self.funcnameEF.get() if not functionName: functionName = "func" if actor is not None: file = tkFileDialog.askopenfilename(parent = self.master, initialdir = '.', title='Actor file', filetypes=[('', '*.py'), ('all', '*')] , initialfile = self.file) if file: #print "open from file :", file if self.command is not None: self.command(self.object, actor, "DejaVuScenario", start = kf1, end = kf2, file = file ,functionName = functionName) self.file = file mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/actor.py0000644000175000017500000006152411573531151025005 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by from Scenario2.actor import Actor, CustomActor from Scenario2.datatypes import DataType from Scenario2.interpolators import Interpolator, FloatScalarInterpolator,\ BooleanInterpolator from SimPy.Simulation import now import numpy.oldnumeric as Numeric ## class ActionWithRedraw(Action): ## # subclass Action to have these actions set a redraw flag in the director ## # so that the redraw process only triggers a redraw if something changed ## def __init__(self, *args, **kw): ## Action.__init__(self, *args, **kw) ## self.postStep_cb = (self.setGlobalRedrawFlag, (), {}) ## def setGlobalRedrawFlag(self): ## #print 'setting needs redraw at', now(), self._actor().name ## self._actor()._maa().needsRedraw = True class RedrawActor(Actor): def __init__(self, vi, *args, **kw): Actor.__init__(self, "redraw", vi) #self.addAction( Action() ) self.visible = False self.recording = False self.scenarioname = "DejaVuScenario" self.guiVar = None def setValueAt(self, frame=None, off=0): self.setValue() def setValue(self, value=None): needsRedraw = True if self._maa: if self._maa().needsRedraw == False: needsRedraw = False if self._maa()._director and self._maa()._director().needsRedraw: needsRedraw = True if not needsRedraw: return #print "oneRedraw from redraw actor" self.object.OneRedraw() # handle recording a frame if need be camera = self.object.currentCamera if hasattr(camera, 'videoRecordingStatus'): if camera.videoRecordingStatus == 'recording': camera.recordFrame() def onAddToDirector(self): gui = self._maa().gui if gui: try: from DejaVu.Camera import RecordableCamera isrecordable = True except: isrecordable = False if isrecordable: camera = self.object.currentCamera if isinstance(camera, RecordableCamera): gui.createRecordMovieButton() def startRecording(self, file): camera = self.object.currentCamera camera.setVideoOutputFile(file) camera.setVideoParameters() camera.videoRecordingStatus = 'recording' def stopRecording(self): self.object.currentCamera.stop() def clone(self): return RedrawActor( self.object ) def getActorName(object, propname): # create a name for object's actor objname = object.name import string if hasattr(object, "fullName"): names = object.fullName.split("|") if len(names)> 1: objname = string.join(names[1:], ".") if objname.count(" "): # remove whitespaces from the object's name objname = string.join(objname.split(), "") return "%s.%s"%(objname, propname) class DejaVuActor(CustomActor): """ class for DejaVu actors. initialValue= None - initial value of the object's attribute (object.name), interp = None - interpolator class, setFunction = None - function to set the value on the object, if None, object.Set(name=value) will be used setMethod: method of the object to be called at each time step. The function will be called using obj.method(value) getFunction = None - function that can be called to get the current value of the attribute (object.name) The function and its arguments have to be specified as a 3-tuple (func, *args, **kw). It will be called using func(*(object,)+args), **kw) if it is a function or func(*args, **kw) if it is a method; if None, getattr(object, name) will be used to get the value to set the value and getattr(geom, name) to get the value """ def __init__(self, name, object, initialValue=None, datatype=None, interp=None, setFunction=None, setMethod=None, getFunction=None): assert isinstance(name, str) self.varname = name if not getFunction: if hasattr(object, name): getFunction = (getattr, (name,), {}) actorname = getActorName(object, name) ## objname = object.name ## if objname.count(" "): ## # remove whitespaces from the object's name ## import string ## objname = string.join(objname.split(), "") CustomActor.__init__(self, actorname, object, initialValue, datatype, interp, setFunction=setFunction, setMethod=setMethod, getFunction=getFunction) if self.hasGetFunction: self.recording = True self.guiVar = None self.scenarioname = "DejaVuScenario" def setValue(self, value): if self.setFunction: self.setFunction( *(self, value) ) elif self.setMethod: self.setMethod(value) else: self.object.Set( **{self.varname:value} ) def setValueAt(self, frame, off=0): #print 'GGGGGGGGGGGGGGG', self.name value = self.actions.getValue(frame-off) if value != 'Nothing There': self.setValue(value) maa = self._maa() maa.needsRedraw = True #print 'HHHHHHHHHHHHHHHHHH', maa.name ## if maa._director is not None: ## print maa._director(), 'LLLLLLLLLLLLLLLL' ## maa._director().needsRedraw = True def clone(self): if self.setMethod is not None: setMethod = self.setMethod.__name__ else: setMethod = None datatype = None if self.datatype is not None: datatype = self.datatype.__class__ newActor = self.__class__( self.varname, self.object, initialValue=self.initialValue, datatype=datatype, interp=self.interp, setFunction=self.setFunction, setMethod=setMethod) newActor.getFuncTuple = self.getFuncTuple if self.getFuncTuple: newActor.hasGetFunction = True newActor.behaviorList.easeIn = self.behaviorList.easeIn newActor.behaviorList.easeOut = self.behaviorList.easeOut newActor.behaviorList.constant = self.behaviorList.constant return newActor from interpolators import MaterialInterpolator from Scenario2.datatypes import FloatType, IntType, BoolType,IntVectorType,\ FloatVectorType, IntVarType, FloatVarType, VarVectorType class DejaVuCameraActor(DejaVuActor): def __init__(self, name, object, initialValue=None, datatype=DataType, interp=BooleanInterpolator, setFunction=None, setMethod=None, getFunction=None): assert hasattr(object, 'viewer') self.cameraind = 0 for i, c in enumerate(object.viewer.cameras): if c == object: self.cameraind=i break DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, setFunction=setFunction, setMethod=setMethod, getFunction=getFunction) def getCameraObject(self): vi = self.object.viewer camera = vi.cameras[self.cameraind] if camera != self.object: self.object = camera if self.setMethod is not None: method = getattr(self.object, self.setMethod.__name__) self.setMethod = method return camera def setValue(self, value): self.getCameraObject() DejaVuActor.setValue(self, value) def getValueFromObject(self): self.getCameraObject() return DejaVuActor.getValueFromObject(self) class DejaVuGeomVisibilityActor(DejaVuActor): """ Actor to set geometry visibility flag when set to 1 we need to make sure each parent's visibility flag is 1 else the object will not appear """ def __init__(self, name, object, initialValue=None, datatype=DataType, interp=BooleanInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) def setValue(self, value): obj = self.object self.object.Set( visible = value) if value: # set all parents visibility to 1 while obj.parent: obj = obj.parent obj.Set( visible=value ) #else: # for child in obj.AllObjects(): # if child!=self: # child.Set( visible = value) def getValue(self): # MS: maybe we should return 0 if 1 parent is not visible return self.object.visible class DejaVuGeomEnableClipPlaneActor(DejaVuActor): """ Actor to enable clipping plane for a geometry """ def __init__(self, name, object, initialValue=None, datatype=DataType, interp=None, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=None) def setValue(self, value): if not value: return geom = self.object for clip in value: assert len(clip) == 4 if clip[3] == True: #print "addclipplane:", clip[0], clip[0].num geom.AddClipPlane(clip[0], clip[1], clip[2]) else: #print "removeClipPlane:", clip[0], clip[0].num geom.RemoveClipPlane(clip[0]) def getValue(self): geom = self.object val = [] clip = [] inh = False if len(geom.clipP): clip = geom.clipP elif len(geom.clipPI): clip = geom.clipPI inh = True for cp in clip: val.append([cp, geom.clipSide[cp.num], inh, True]) return val class DejaVuMaterialActor(DejaVuActor): def __init__(self, name, object, initialValue=None, datatype=DataType, interp=MaterialInterpolator, setFunction=None, setMethod=None, getFunction=None, mode="front"): self.mode = mode DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.hasGetFunction = True def setValue(self, value): object = self.object ## i=0 ## for v,name in zip(value, ('ambi', 'emis', 'spec', 'shini')): ## #if self.activeVars[i]: ## object.Set(propName=name, materials=v, transparent='implicit', redo=1) ## i +=1 #mat = [ value[0], None, value[1], value[2], value[3], None] mat = {'ambient':value[0], 'emission': value[1], 'specular':value[2], 'shininess':value[3]} mask = [1, 0, 1, 1, 1, 0] if self.mode == "front": object.Set(rawMaterialF=mat, matMask=mask,transparent='implicit', redo=1) else: object.Set(rawMaterialB=mat, matMask=mask,transparent='implicit', redo=1) def getValue(self): if self.mode == "front": mat = self.object.materials[1028].prop else: mat = self.object.materials[1029].prop return [mat[0], mat[2], mat[3], mat[4]] def compareValues(self, oldval, newval): vvt = VarVectorType() fvt = FloatVectorType() for i in range(3): if not vvt.isEqual(oldval[i], newval[i]): return False if not fvt.isEqual(oldval[3], newval[3]): return False return True def clone(self): newactor = DejaVuActor.clone(self) newactor.mode = self.mode newactor.hasGetFunction = self.hasGetFunction return newactor from Scenario2.interpolators import FloatVectorInterpolator, VarVectorInterpolator class DejaVuScissorActor(DejaVuActor): """ This actor manages resizing of DejaVu object's scissor""" def __init__(self, name, object, initialValue=None, datatype=FloatVectorType, interp=FloatVectorInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.hasGetFunction = True self.varnames = ['scissorH', 'scissorW', 'scissorX', 'scissorY'] self.activeVars = ['scissorH', 'scissorW', 'scissorX', 'scissorY'] def setValue(self, value): object = self.object kw = {} for i, var in enumerate (self.varnames): if var in self.activeVars: kw[var] = value[i] object.Set(**kw) def getValue(self): obj = self.object return [float(obj.scissorH), float(obj.scissorW), float(obj.scissorX), float(obj.scissorY)] from Scenario2.interpolators import RotationInterpolator from mglutil.math.transformation import UnitQuaternion, Transformation from mglutil.math.rotax import mat_to_quat from DejaVu.Camera import Camera from math import cos, acos, sin, pi from Scenario2.interpolators import matToQuaternion, quatToMatrix class DejaVuRotationActor(DejaVuActor): """ This actor manages rotation of DejaVu object by setting the rotation """ def __init__(self, name, object, initialValue=None, datatype=FloatVectorType, interp=RotationInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.hasGetFunction = True ## def setValue(self, value): ## object = self.object ## q = (value[0], Numeric.array(value[1:], 'f')) ## t = Transformation(quaternion=q) ## object.Set(rotation = t.getRotMatrix(shape=(16,), transpose=1)) ## if isinstance(object, Camera): ## object.Redraw() ## def getValue(self): ## obj = self.object ## value = self.object.rotation ## if len(value)==16: ## q = UnitQuaternion(mat_to_quat(value)) ## value = [q.real, q.pure[0], q.pure[1], q.pure[2]] ## #print "in DejaVuRotationActor.getValue: ", value ## return value def setValue(self, value): object = self.object mat = quatToMatrix(value) #object._setRotation(mat) object.Set(rotation=mat) if isinstance(object, Camera): object.Redraw() def getValue(self): mat = self.object.rotation quat = matToQuaternion(mat) return quat class DejaVuConcatRotationActor(DejaVuRotationActor): """ This actor manages rotation of DejaVu object by concatenating the rotation """ def __init__(self, name, object, initialValue=None, datatype=FloatVectorType, interp=RotationInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuRotationActor.__init__( self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.hasGetFunction = True def setValue(self, value): object = self.object mat = quatToMatrix(value) object.ConcatRotation(mat) if isinstance(object, Camera): object.Redraw() from mglutil.math.rotax import rotax import math from DejaVu.scenarioInterface.interpolators import RotationConcatInterpolator class DejaVuAxisConcatRotationActor(DejaVuActor): """ This actor manages rotation of DejaVu object by concatenating the rotation """ def __init__(self, name, object, initialValue=None, datatype=FloatVectorType, axis=(0,1,0), interp=RotationConcatInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype, interp) self.axis = axis self.hasGetFunction = False def setValue(self, value): #print 'Rotate by', value mat = rotax( (0,0,0), self.axis, value*math.pi/180.) object = self.object object.ConcatRotation(mat.flatten()) if isinstance(object, Camera): object.Redraw() def clone(self): newactor = DejaVuActor.clone(self) newactor.axis = self.axis newactor.hasGetFunction = self.hasGetFunction return newactor class DejaVuClipZActor(DejaVuCameraActor): """ This actor manages the near and far camera's atributes""" def __init__(self, name, object, initialValue=None, datatype=FloatVectorType, interp=FloatVectorInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuCameraActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.hasGetFunction = True self.varnames = ['near', 'far'] self.activeVars = ['near', 'far'] def setValue(self, value): camera = self.getCameraObject() kw = {} for i, var in enumerate (self.varnames): if var in self.activeVars: kw[var] = value[i] camera.Set(**kw) camera.Redraw() def getValue(self): c = self.getCameraObject() return Numeric.array([c.near, c.far,], "f") class DejaVuFogActor(DejaVuCameraActor): """ This actor manages the start and end atributes of camera's fog""" def __init__(self, name, object, attr='start', initialValue=None, datatype=FloatType, interp=FloatScalarInterpolator, setFunction=None, setMethod=None, getFunction=None): from DejaVu.Camera import Fog if isinstance(object, Fog): assert object.camera is not None object = object.camera() self.attr = attr DejaVuCameraActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.hasGetFunction = True def setValue(self, value): camera = self.getCameraObject() kw = {self.attr: value} camera.fog.Set(**kw) #camera.Redraw() def getValue(self): c = self.getCameraObject() return getattr(c.fog, self.attr) def clone(self): newactor = DejaVuCameraActor.clone(self) newactor.attr = self.attr return newactor from Scenario2.interpolators import FloatVarScalarInterpolator from interpolators import LightColorInterpolator class DejaVuLightColorActor(DejaVuActor): def __init__(self, name, object, initialValue=None, datatype = DataType, interp = LightColorInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.varnames = ['ambient', 'diffuse', 'specular'] self.activeVars = ['ambient', 'diffuse', 'specular'] self.hasGetFunction = True def setValue(self, value): object = self.object kw = {} for v,name in zip(value, ('ambient', 'diffuse', 'specular')): if name in self.activeVars: kw[name] = v object.Set(**kw) def getValue(self): obj = self.object return [obj.ambient, obj.diffuse, obj.specular] def compareValues(self, oldval, newval): fvt = FloatVectorType() for i in range(3): if not fvt.isEqual(oldval[i], newval[i]): return False return True class DejaVuSpheresRadiiActor(DejaVuActor): """ This actor manages the raduis attribute of spheres""" def __init__(self, name, object, initialValue=None, datatype=FloatVarType, interp=FloatVarScalarInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype=datatype, interp=interp, getFunction=self.getValue) self.hasGetFunction = True self.varnames = ['radii'] self.activeVars = ['radii'] def setValue(self, value): object = self.object object.Set(radii=value) def getValue(self): object = self.object if object.oneRadius: return object.radius else: return object.vertexSet.radii.array.ravel() from interpolators import TransformInterpolator class DejaVuTransformationActor(DejaVuActor): def __init__(self, name, object, initialValue=None, datatype=DataType, interp=TransformInterpolator, setFunction=None, setMethod=None, getFunction=None): DejaVuActor.__init__(self, name, object, initialValue, datatype, interp, getFunction=self.getValue) self.hasGetFunction = True def setValue(self, value): object = self.object rotation = quatToMatrix(value[0]) redo = False if object != object.viewer.rootObject: # need to rebuild display list if the object is not root redo = True object.Set(rotation=rotation,translation = value[1],scale = value[2], pivot = value[3], redo=redo) def getValue(self): obj = self.object rotation = matToQuaternion(obj.rotation) return [rotation, obj.translation[:], obj.scale[:], obj.pivot[:] ] def compareValues(self, oldval, newval): fvt = FloatVectorType() for i in range(len(oldval)): if not fvt.isEqual(oldval[i], newval[i]): return False return True def clone(self): newactor = DejaVuActor.clone(self) newactor.hasGetFunction = self.hasGetFunction return newactor def getAllSubclasses(klass): # recursively build a list of all sub-classes bases = klass.__bases__ klassList = list(bases) for k in bases: klassList.extend( getAllSubclasses(k) ) return klassList import inspect from actorsDescr import actorsDescr from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from Scenario2.interpolators import FloatScalarInterpolator, IntScalarInterpolator def getAnimatableAttributes(object): # return two dicts that contain a dict for each attribute of object # that can be animated. The first dict is for attribute foudn in # actorsDescr, the second is for attributes picked up on the fly # merge the dict of attribute for all base classes d1 = {} for klass, d2 in actorsDescr.items(): if isinstance(object, klass): d1.update(d2) d2 = {} # find all attribute that are float attrs = inspect.getmembers(object, lambda x: isinstance(x, float)) for name,value in attrs: if d1.has_key(name): continue d2[name] = { 'interp': FloatScalarInterpolator, 'interpKw': {'values':[value, value]}, 'valueWidget': ThumbWheel, 'valueWidgetKw': {'type': 'float', 'initialValue':value}, } # find all attribute that are bool or int attrs = inspect.getmembers(object, lambda x: isinstance(x, int)) for name,value in attrs: if d1.has_key(name): continue d2[name] = { 'interp': IntScalarInterpolator, 'interpKw': {'values':[value, value]}, 'valueWidget': ThumbWheel, 'valueWidgetKw': {'type':'int', 'initialValue':value}, } return d1, d2 def getDejaVuActor(object, attribute): # return a DejaVu Actor given a DejaVu object and attribute name baseClasses = [object.__class__] baseClasses.extend( getAllSubclasses(object.__class__) ) #print 'getDejaVuActor', object,attribute for klass in baseClasses: d1 = actorsDescr.get(klass, None) if d1: d2 = d1.get(attribute, None) if d2: actorCalss, args, kw = d2['actor'] args = (attribute,object) + args actor = actorCalss( *args, **kw ) return actor ## else: # attribute not found in dictionary ## if attribute in object.keywords: # it is setable ## if hasattr(object, attribute): ## actor = DejaVuActorSetGetattr( ## object, name=actorName, setName=attribute, ## getName=attribute) ## else: ## return None # FIXME ## else: return None mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/interpolators.py0000644000175000017500000000673311553674100026603 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import numpy.oldnumeric as Numeric from Scenario2.interpolators import VarVectorInterpolator,CompositeInterpolator, \ FloatVectorInterpolator, RotationInterpolator, FloatScalarInterpolator class MaterialInterpolator(CompositeInterpolator): nbvar = 4 def __init__(self, firstVal, lastVal, interpolation='linear', interpolators=None, active = True): if not interpolators: interpolators = [VarVectorInterpolator, # for ambient RGB VarVectorInterpolator, # for specular RGB VarVectorInterpolator, # for emissive RGB FloatVectorInterpolator, # for shininess ] CompositeInterpolator.__init__(self, firstVal, lastVal, interpolators=interpolators, interpolation=interpolation) class LightColorInterpolator(CompositeInterpolator): nbvar = 3 def __init__(self, firstVal, lastVal, interpolation='linear', interpolators=None, active = True): if not interpolators: ## interpolators = [VarVectorInterpolator, # for ambient ## VarVectorInterpolator, # for diffuse ## VarVectorInterpolator, # for specular ## ] interpolators = [FloatVectorInterpolator, # for ambient FloatVectorInterpolator, # for diffuse FloatVectorInterpolator, # for specular ] CompositeInterpolator.__init__(self, firstVal, lastVal, interpolators=interpolators, interpolation=interpolation) class TransformInterpolator(CompositeInterpolator): nbvar = 4 def __init__(self, firstVal, lastVal, interpolation='linear', interpolators=None, active = True): if not interpolators: interpolators = [RotationInterpolator, # for rotation FloatVectorInterpolator, # for translation FloatVectorInterpolator, # for scale FloatVectorInterpolator# for pivot ] CompositeInterpolator.__init__(self, firstVal, lastVal, interpolators=interpolators, interpolation=interpolation) class RotationConcatInterpolator(FloatScalarInterpolator): def getValue(self, fraction, interval): # problem .. how to store last value ==> who calls Interval._getValue2KF easeIn = False easeOut = False if self.behaviorList is not None: bl = self.behaviorList() #print "Rtation ,easeIn-Out", bl.easeIn , bl.easeOut easeIn = bl.easeIn easeOut = bl.easeOut if not easeIn and not easeOut: return FloatScalarInterpolator.getValue(self, fraction, interval) fullValue = interval.data['fullValue'] if fraction == 0: interval._lastSetValue = 0 _d = self.ease(fraction, interval)*fullValue # whole distance from time 0 to time t if interval._lastSetValue: dd = _d-interval._lastSetValue # distance increment else: dd = _d #print fraction, dd , _d, interval.data['fullValue'], interval._lastSetValue #sum = sum + dd # check the distance interval._lastSetValue = _d return dd mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/actorsDescr.py0000644000175000017500000004077111533313305026145 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by from DejaVu.Transformable import Transformable from DejaVu.Displayable import Displayable from DejaVu.Geom import Geom from DejaVu.IndexedGeom import IndexedGeom from DejaVu.Cylinders import Cylinders from DejaVu.Light import Light from DejaVu.Spheres import Spheres from DejaVu.Clip import ClippingPlane from DejaVu.Camera import Camera, Fog from DejaVu.Materials import propertyNum from opengltk.OpenGL import GL from Scenario2.interpolators import VarVectorInterpolator, FloatVectorInterpolator,\ IntScalarInterpolator, RotationInterpolator,\ BooleanInterpolator, FloatVarScalarInterpolator, FloatScalarInterpolator ## ReadDataInterpolator from Scenario2.datatypes import FloatType, IntType, BoolType,IntVectorType,\ FloatVectorType, IntVarType, FloatVarType, VarVectorType from actor import DejaVuActor, DejaVuMaterialActor, DejaVuScissorActor, \ DejaVuClipZActor, DejaVuFogActor, DejaVuLightColorActor, \ DejaVuSpheresRadiiActor, DejaVuRotationActor, DejaVuConcatRotationActor, \ DejaVuGeomVisibilityActor, DejaVuTransformationActor, DejaVuGeomEnableClipPlaneActor,\ DejaVuCameraActor from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from DejaVu.states import getRendering, setRendering, setObjectRendering import numpy.oldnumeric as Numeric id4x4 = Numeric.identity(4).astype('f') from numpy import copy actorsDescr = { Transformable: { 'rotation': { 'actor': (DejaVuRotationActor, (), {}) } , 'concatRotation': { 'actor': (DejaVuConcatRotationActor, (), {}) } , 'translation': { 'actor': (DejaVuActor, (), {'interp':FloatVectorInterpolator, #'setMethod': '_setTranslation', 'datatype': FloatVectorType} ) }, 'scale': { 'actor': (DejaVuActor, (), {'interp':FloatVectorInterpolator, #'setMethod': '_setScale', 'datatype': FloatVectorType} ) }, 'pivot': { 'actor': (DejaVuActor, (), {'interp': FloatVectorInterpolator, #'setMethod': '_setPivot', 'datatype': FloatVectorType} ) }, 'transformation':{ 'actor': (DejaVuTransformationActor, (), {}) } , }, Displayable: { 'colors':{ 'actor': (DejaVuActor, (), { 'setFunction':\ #lambda actor, value: actor.object.Set(materials=value, inheritMaterial=0), lambda actor, value: actor.object.Set(materials=value, redo=1, tagModified=False, transparent='implicit', inheritMaterial=0), 'getFunction':(lambda x,y: copy(x.materials[y].prop[1][:, :3]), (GL.GL_FRONT,), {}), 'interp': VarVectorInterpolator, 'datatype':VarVectorType }, ), }, 'colorsB':{ 'actor': (DejaVuActor, (), { 'setFunction':\ #lambda actor, value: actor.object.Set(materials=value, inheritMaterial=0), lambda actor, value: actor.object.Set(materials=value, redo=1, tagModified=False, polyFace = GL.GL_BACK, transparent='implicit', inheritMaterial=0), 'getFunction':(lambda x,y: copy(x.materials[y].prop[1][:, :3]), (GL.GL_BACK,), {}), 'interp': VarVectorInterpolator, 'datatype':VarVectorType }, ), }, 'lineWidth': { 'actor': (DejaVuActor, (), {'setFunction': \ lambda actor, value: actor.object.Set(lineWidth=value, inheritLineWidth=0), 'interp': IntScalarInterpolator, 'datatype':IntType}) }, 'pointWidth': { 'actor': (DejaVuActor, (), {'setFunction': \ lambda actor, value: actor.object.Set(pointWidth=value, inheritPointWidth=0), 'interp': IntScalarInterpolator, 'datatype':IntType}) }, 'rendering': { 'actor': (DejaVuActor, (), {'getFunction': lambda object: getRendering(object.viewer,checkAnimatable=True).get(object.fullName, None), 'setFunction': lambda actor, value: setObjectRendering(actor.object.viewer, actor.object, value)}) }, }, Geom: { 'material': { 'actor': (DejaVuMaterialActor, (), {} ), }, 'opacity': { 'actor': (DejaVuActor, (), {'setFunction': \ lambda actor, value: actor.object.Set(opacity=value, transparent='implicit', polyFace=GL.GL_FRONT_AND_BACK, inheritMaterial=0), 'getFunction':( lambda x,y: x.materials[y].prop[propertyNum['opacity']], (GL.GL_FRONT,), {} ), 'interp': FloatVarScalarInterpolator, 'datatype': FloatVarType } ), }, 'opacityF': { 'actor': (DejaVuActor, (), {'setFunction': \ lambda actor, value: actor.object.Set(opacity=value, transparent='implicit', polyFace=GL.GL_FRONT, inheritMaterial=0), 'getFunction':( lambda x,y: x.materials[y].prop[propertyNum['opacity']], (GL.GL_FRONT,), {} ), 'interp': FloatVarScalarInterpolator, 'datatype': FloatVarType } ), }, 'opacityB': { 'actor': (DejaVuActor, (), {'setFunction': \ lambda actor, value: actor.object.Set(opacity=value, transparent='implicit', polyFace=GL.GL_BACK, inheritMaterial=0), 'getFunction':( lambda x,y: x.materials[y].prop[propertyNum['opacity']], (GL.GL_BACK,), {} ), 'interp': FloatVarScalarInterpolator, 'datatype': FloatVarType } ), }, 'visible': { 'actor': (DejaVuGeomVisibilityActor, (), {'interp': BooleanInterpolator, 'datatype': BoolType}) }, 'depthMask': { 'actor': (DejaVuActor, (), {'interp': BooleanInterpolator, 'datatype': BoolType}) }, 'scissor': { 'actor': (DejaVuActor, (), {'interp': BooleanInterpolator, 'datatype': BoolType}) }, # turns the scissor on/off. 'scissorResize': { 'actor': ( DejaVuScissorActor, (), {}), }, 'xyz':{ 'actor': (DejaVuActor, (), { 'setFunction': lambda actor, value: actor.object.Set(vertices=value), 'getFunction':(lambda obj: obj.vertexSet.vertices.array, (), {}), 'interp': VarVectorInterpolator, 'datatype':VarVectorType }, ), }, 'clipEnable': { 'actor': (DejaVuGeomEnableClipPlaneActor, (), {}), }, ## 'function':{ ## 'actor':(DejaVuActor, (), {'setFunction': None, 'getFunction': None, ## 'interp':ReadDataInterpolator, 'datatype': None}) ## } }, IndexedGeom: { 'faces':{ 'actor': (DejaVuActor, (), { 'setFunction': lambda actor, value: actor.object.Set(faces=value), 'getFunction':(lambda obj: obj.faceSet.faces.array, (), {}), 'interp': VarVectorInterpolator, 'datatype':VarVectorType },), }, 'vertface':{ 'actor': (DejaVuActor, (), { 'setFunction': lambda actor, value: actor.object.Set(vertices=value[0], faces=value[1]), 'getFunction':(lambda obj: [obj.vertexSet.vertices.array, obj.faceSet.faces.array], (), {}), },), }, }, Spheres: { 'radii': { 'actor': (DejaVuSpheresRadiiActor, (), {}), }, 'quality': { 'actor': (DejaVuActor, (), { 'setFunction': lambda actor, value: actor.object.Set(quality=value), 'interp': IntScalarInterpolator, 'datatype':IntType }), }, 'vertices':{ 'actor': (DejaVuActor, (), {'setFunction': lambda actor, value: actor.object.Set(vertices=value), 'getFunction':(lambda obj: obj.vertexSet.vertices.array, (), {}) } ), } }, Cylinders: { 'radii': { 'actor': (DejaVuActor, (), {'setFunction': lambda actor, value: actor.object.Set(radii=list(value)), 'getFunction':(lambda obj: obj.vertexSet.radii.array, (), {}), 'interp': FloatVectorInterpolator, 'datatype': FloatVectorType} ), }, 'quality': { 'actor': (DejaVuActor, (), { 'setFunction': lambda actor, value: actor.object.Set(quality=value), 'interp': IntScalarInterpolator, 'datatype':IntType }), }, 'vertices':{ 'actor': (DejaVuActor, (), {'setFunction': lambda actor, value: actor.object.Set(vertices=value), 'getFunction':(lambda obj: obj.vertexSet.vertices.array, (), {}) } ), } }, Fog:{ ## 'start': { ## 'actor': (DejaVuActor, (), ## { ## 'getFunction':(getattr, ('start',), {}), ## 'interp': FloatScalarInterpolator, ## 'datatype': FloatType ## }, ## ), ## }, ## 'end': { ## 'actor': (DejaVuActor, (), ## { ## 'getFunction':(getattr, ('end',), {}), ## 'interp': FloatScalarInterpolator, ## 'datatype': FloatType ## }, ## ), ## }, 'start': {'actor': (DejaVuFogActor, (), {'attr':'start'},)}, 'end': {'actor': (DejaVuFogActor, (), {'attr':'end'},) }, }, Camera:{ 'clipZ':{ 'actor': (DejaVuClipZActor, (), {} ), }, 'backgroundColor': { 'actor': (DejaVuCameraActor, (), #(lambda c, value: c.Set(color=value), ), {'setFunction': lambda actor, value: (actor.object.Set(color=value), actor.object.fog.Set(color=value)), #,actor.object.Redraw()), 'getFunction':(getattr, ('backgroundColor',), {}), 'interp': FloatVectorInterpolator, 'datatype': FloatVectorType }, ), }, 'fieldOfView': { 'actor': (DejaVuCameraActor, (), {'setMethod': '_setFov', 'getFunction':(getattr, ('fovy',), {}), 'interp': FloatScalarInterpolator, 'datatype': FloatType }, ), }, 'near': { 'actor': (DejaVuCameraActor, (), { 'getFunction':(getattr, ('near',), {}), 'interp': FloatScalarInterpolator, 'datatype': FloatType }, ), }, 'far': { 'actor': (DejaVuCameraActor, (), { 'getFunction':(getattr, ('far',), {}), 'interp': FloatScalarInterpolator, 'datatype': FloatType }, ), }, 'width': { 'actor': (DejaVuCameraActor, (), { 'getFunction':(getattr, ('width',), {}), 'interp': IntScalarInterpolator, 'datatype': IntType }, ), }, 'heigt': { 'actor': (DejaVuCameraActor, (), { 'getFunction':(getattr, ('heigt',), {}), 'interp': IntScalarInterpolator, 'datatype': IntType }, ), }, 'antialiased': { 'actor': (DejaVuCameraActor, (), { 'getFunction':(getattr, ('antiAliased',), {}), 'interp': IntScalarInterpolator, 'datatype': IntType }, ), }, 'boundingbox': { 'actor': (DejaVuCameraActor, (), { 'interp': IntScalarInterpolator, 'getFunction':(getattr, ('drawBB',), {}), 'datatype':IntType }), }, 'projectionType': { 'actor': (DejaVuCameraActor, (), {'interp': BooleanInterpolator, 'datatype': BoolType}) }, 'drawThumbnail': { 'actor': (DejaVuCameraActor, (), {'interp': BooleanInterpolator, 'datatype': BoolType}) }, 'contours': { 'actor': (DejaVuCameraActor, (), {'interp': BooleanInterpolator, 'getFunction':(getattr, ('drawThumbnailFlag',), {}), 'datatype': BoolType}) }, 'lookFrom': { 'actor': (DejaVuCameraActor, (), {'setMethod': '_setLookFrom', 'getFunction':(getattr, ('lookFrom',), {}), 'interp':FloatVectorInterpolator, 'datatype': FloatVectorType} ) }, 'lookAt': { 'actor': (DejaVuCameraActor, (), {'getFunction':(getattr, ('lookAt',), {}), 'interp':FloatVectorInterpolator, 'datatype': FloatVectorType} ) }, }, ClippingPlane: { 'visible': { 'actor': (DejaVuActor, (), {'interp': BooleanInterpolator, 'datatype': BoolType }) }, 'color': { 'actor': (DejaVuActor, (), {'interp': FloatVectorInterpolator, 'datatype': FloatVectorType }) }, }, Light: { 'visible': { 'actor': (DejaVuActor, (), {'interp': BooleanInterpolator, 'datatype': BoolType }) }, 'color': { 'actor':(DejaVuLightColorActor, (), {}), }, 'direction': { 'actor': (DejaVuActor, (), {'interp': FloatVectorInterpolator, 'datatype': FloatVectorType} ) } } } mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/animationPanels.py0000644000175000017500000003137511533314134027014 0ustar debiandebian## ## GUI panels for creation Actions or MAA for example used in ## PMV/scenarioInterface/animationGui.py AnimationNotebook ## import Tkinter, Pmw from Scenario2.multipleActorsActions import MultipleActorsActions from mglutil.util.callback import CallbackFunction from Scenario2 import _clipboard from DejaVu.states import setRendering, setOrientation class AnimationPanel: """ base class for creating a panel in which . This class create a frame (self.frame) containing: a group for geometry chooser self.geomChooserG a group for widget to create Actions self.makeActionsG a group for created actions: self.createdActionsG the created MAAs are in self.maa list """ def __init__(self, viewer, viewerName, master=None): """ Creates a GUI form containing a groupGeometry Chooser widget and a Pmw.Group widget that can be populated with animation effects buttons. viewer - an instance of molecular viewer """ self.viewer = viewer self.viewerName = viewerName self.master = master self.createGUI() self.maas = [] # created MAAs self.maaButtons = [] # buttons representing created MAAs self.maaButtonNames = {} # for each short name count how many we have self._animNB = None # will become a reference to the AnimationNotebook instance def createGUI(self): # set or create master if self.master is None: self.master = master = Tkinter.Toplevel() self.ownsMaster = True else: self.ownsMaster = False # create balloon self.balloon = Pmw.Balloon(self.master) # create top frame self.frame = fm = Tkinter.Frame(self.master) # create group for geometry chooser self.geomChooserG = w = Pmw.Group(fm, tag_text='Animateable objects') w.pack(side='left', fill='both', expand=1, padx=6, pady=6) # add a group for animation buttons (clips) self.makeActionsG = w = Pmw.Group(fm, tag_text='Create Action') w.pack(side='top', fill='both', expand=1, padx=6, pady=6) self.effectsContainer= w.interior() # add a group for saved animation clips self.createdActionsG = w = Pmw.Group(fm, tag_text="Created Actions") w.pack(side='top', fill='both', expand=1, padx=6, pady=6) self.frame.pack(side='left', fill='both', expand=1) def makeMAA(self, maaClass, args, kw): """ create an MAA maaClass( *args, **kw) ans add it to self.maas """ maa = maaClass( *args, **kw ) if len(maa.actors) > 0: self.makeMAAButton(maa) def runMaa(self, maa): if hasattr(maa, "geomOrients") and maa.setOrient: for o, val in maa.geomOrients.items(): #print "setting orient for:", o.name setOrientation(o, val) elif maa.forceOrient: setOrientation(maa.viewer.rootObject, maa.orient) if maa.forceRendering: setRendering(maa.viewer, maa.rendering) maa.run() def makeMAAButton(self, maa): """ Places a button into created Actions group """ assert isinstance( maa, MultipleActorsActions) # add the maa self.maas.append(maa) master = self.createdActionsG.interior() cb = CallbackFunction( self.runMaa, maa) b = Tkinter.Button(master=master ,compound='left', command=cb, width=0, height=0) self.maaButtons.append(b) if hasattr(maa, "shortName"): shortName = maa.shortName else: shortName = maa.__class__.__name__ if not self.maaButtonNames.has_key(shortName): self.maaButtonNames[shortName] = 1 count = self.maaButtonNames[shortName] self.maaButtonNames[shortName] += 1 text = "%s%d" % (maa.shortName, count) b.configure(text = text) nbuttons = len(self.maas)-1 row = nbuttons/4 col = nbuttons%4 b.grid(row = row, column = col, sticky = 'w') #self.balloon.bind(b, maa.name) # the balloon will display a string returned by maa.__repr__() self.balloon.bind(b, maa) b.bind('', CallbackFunction( self.maaMenu_cb, maa, b)) def maaMenu_cb(self, maa, button, event=None): """ Opens the saved clip menu (right mouse click on the clip button) """ menu = Tkinter.Menu(self.master, title=maa.name) ## cb = CallbackFunction(_clipboard.addMaa, maa) ## menu.add_command(label="Add to Clipboard", command=cb) from Scenario2 import addTargetsToMenu addTargetsToMenu(menu, maa) if maa.editorClass: cb = CallbackFunction(self.editMAA_cb, maa, button) menu.add_command(label="Edit ...", command=cb) menu.add_command(label = "Delete", command=CallbackFunction(self.deleteMAA_cb, maa, button) ) menu.add_command(label="Dismiss menu") menu.post(event.x_root, event.y_root) def editMAA_cb(self, maa, button=None, args=(), kw={}, event=None): kw = maa.editorKw args = maa.editorArgs kw['master'] = self.master editor = maa.editorClass( *args, **kw) if editor == None: return "Cancel" editor.edit(maa) # the maa name could have been modified: #if button: # self.balloon.bind(button, maa.name) # if this maa is in the sequence animator it should update ! animNB = self._animNB() for i , _maa in enumerate(animNB.seqAnim.maas): if _maa[0] == maa: position = _maa[1] animNB.seqAnimGUI.update(i, position) return return editor.exitStatus def deleteMAA_cb(self, maa, button, event=None): """removes the specified maa and its button from Created Actions frame""" # if this maa is in the sequence animator it will be removed too position = None seqAnim = self._animNB().seqAnim for i , _maa in enumerate(seqAnim.maas): if _maa[0] == maa: name = maa.name import tkMessageBox ok = tkMessageBox.askokcancel("Delete %s?"%name,"%s is in Sequence Anim.\nThis will also remove the action from Sequence Anim."%name) if not ok: return position = _maa[1] break button.destroy() master = self.createdActionsG.interior() buttons = master.grid_slaves() buttons.reverse() nb = 4 for i, b in enumerate(buttons): #print b.maa.name, "row", i/nb, "column", i%nb b.grid(row=i/nb, column= i%nb, sticky='w') if maa in self.maas: self.maas.remove(maa) if position != None: seqAnim.removeMAA(maa, position) from DejaVu.scenarioInterface.animations import \ FlyInObjectMAA, FlyOutObjectMAA,\ FadeInObjectMAA, FadeOutObjectMAA, VisibleObjectMAA, ColorObjectMAA,\ RotationMAAOptionsGUI, RotationMAA, RockMAA class ShowHideGeomPanel(AnimationPanel): """ Panel providing buttons to create fly, fade, show/hide actions """ def __init__(self, viewer, viewerName, geomChooserClass, geomChooserClassOpt, master=None): """ viewer is a DejaVu Viewer instance viewerName is a string which when evaluated yields viewer geomChooserClass is class defining the geomChooser object to create geomChooserClassOpt is a sequence or *args and **kw used to create the geomChooser. (viewer,) is automatically inserted at the begining of args and 'root', and 'command' are automatically set in kw. other possible kw include 'filterFunction', 'refreshButton', 'showAllButton' """ AnimationPanel.__init__(self, viewer, viewerName, master) args, kw = geomChooserClassOpt kw['root'] = self.geomChooserG.interior() kw['command'] = self.onSelect_cb args = (viewer,) + args gc = self.geomChooser = geomChooserClass( *args, **kw) gc.pack(side='top', fill='both', expand=1, anchor="w") self.selectedGeom = None # add action creating buttons lastRow = 0 parent = self.makeActionsG.interior() # fly in button cb = CallbackFunction(self.makeMAA, FlyInObjectMAA, (), {}) w = self.flyinB = Tkinter.Button(parent, text='Fly In', command=cb) w.grid(column=0, row=lastRow, sticky='ew') w.bind('', CallbackFunction( self.showMaaEditor_cb, FlyInObjectMAA, (), {})) # fly out button cb = CallbackFunction(self.makeMAA, FlyOutObjectMAA, (), {}) w = self.flyoutB = Tkinter.Button(parent, text='Fly Out', command=cb) w.grid(column=1, row=lastRow, sticky='ew') w.bind('', CallbackFunction( self.showMaaEditor_cb, FlyOutObjectMAA , (), {})) lastRow += 1 # fade in button cb = CallbackFunction(self.makeMAA, FadeInObjectMAA, (), {}) w = self.fadeinB = Tkinter.Button(parent, text='Fade In', command=cb) w.bind('', CallbackFunction( self.showMaaEditor_cb, FadeInObjectMAA, (), {})) w.grid(column=0, row=lastRow, sticky='ew') # fade out button cb = CallbackFunction(self.makeMAA, FadeOutObjectMAA, (), {}) w = self.fadeoutB = Tkinter.Button(parent, text='Fade Out', command=cb) w.bind('', CallbackFunction( self.showMaaEditor_cb, FadeOutObjectMAA, (), {})) w.grid(column=1, row=lastRow, sticky='ew') lastRow += 1 # show button cb = CallbackFunction(self.makeMAA, VisibleObjectMAA, (), {'visible':1}) w = self.showB = Tkinter.Button(parent, text='Show', command=cb) w.grid(column=0, row=lastRow, sticky='ew') # hide button cb = CallbackFunction(self.makeMAA, VisibleObjectMAA, (), {'visible':0}) w = self.hideB = Tkinter.Button(parent, text='Hide', command=cb) w.grid(column=1, row=lastRow, sticky='ew') lastRow += 1 # rotation button cb = CallbackFunction(self.makeMAA, RotationMAA, (), {}) w = self.rotationB = Tkinter.Button(parent, text='Rotate', command=cb) w.grid(column=0, row=lastRow, sticky='ew') w.bind('', CallbackFunction( self.showMaaEditor_cb, RotationMAA, (), {})) # rock button cb = CallbackFunction(self.makeMAA, RockMAA, (), {}) w = self.rockB = Tkinter.Button(parent, text='Rock', command=cb) w.grid(column=1, row=lastRow, sticky='ew') w.bind('', CallbackFunction( self.showMaaEditor_cb, RockMAA, (), {})) lastRow += 1 self.lastRow = lastRow def getSelectedGeoms(self): gc = self.geomChooser geometries = gc.get() kw = {} if len(geometries): # get the name of the currently selected geometry en = gc.chooserW.entries ind = gc.chooserW.getInd()[0] objname= en[ind][0].strip() # remove leading blanks # build a name gparent = geometries[0].parent if gparent is not None and gparent.name != "root": objname = gparent.name + "|" + objname kw['objectName'] = objname if hasattr(gc, "getNodes"): kw['nodes'] = gc.getNodes() return geometries, kw def makeMAA(self, maaClass, args, kw, event=None): """ callback for action creating buttons """ geometries, geomkw = self.getSelectedGeoms() if len(geometries)==0: from tkMessageBox import showwarning showwarning("Warning", 'No geometry selected', parent = gc.root) return kw.update(geomkw) args = (geometries, ) maa = maaClass( *args, **kw ) self.makeMAAButton(maa) def showMaaEditor_cb(self, maaClass, args, kw, event=None): """ open maa editor, create maa based on specified options """ geometries, geomkw = self.getSelectedGeoms() if len(geometries)==0: from tkMessageBox import showwarning showwarning("Warning", 'No geometry selected', parent = gc.root) return kw.update(geomkw) args = (geometries, ) maa = maaClass( *args, **kw ) st = self.editMAA_cb(maa) if st == "OK": self.makeMAAButton(maa) def onSelect_cb(self, event = None): self.selectedGeom = [self.geomChooser.chooserW.getInd(), self.geomChooser.chooserW.get()] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/Tests/0000755000175000017500000000000012146210043024404 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/Tests/test_animations.py0000644000175000017500000005734411241373370030204 0ustar debiandebianfrom DejaVu import Viewer from DejaVu.Spheres import Spheres from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.Materials import propertyNum from time import sleep import unittest import sys #declare the 'showwarning' variable that is used in the code returned by maa.getSourceCode() showwarning = False class CustomAnimations_Tests(unittest.TestCase): def setUp(self): """Create DejaVu Viewer """ #if not hasattr(self, "vi"): self.vi = Viewer() def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass def test_flyin(self): """Tests: - creation of FlyInObjectMAA with different options (number of keyframes, direction) - playing different frames of maa . """ vi = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,0,0), (0,1,0), (0,0,1) ], inheritMaterial=False) vi.AddObject(sph) from DejaVu.scenarioInterface.animations import FlyInObjectMAA # fly in from left maa1 = FlyInObjectMAA(sph, objectName=None, direction='left', kfpos=[0, 30]) actors = maa1.actors self.assertEqual(len(actors), 3) vi.OneRedraw() sph.Set(translation=[0,0,0]) # check that the position (translation) of the object changes from left to center # of the viewer at frames 0 - 15 - 30 maa1.setValuesAt(0) t1 = sph.translation[0] vi.OneRedraw() self.assertEqual(t1 < 0, True) maa1.setValuesAt(15) t2 = sph.translation[0] self.assertEqual( int(t1/2), int(t2)) vi.OneRedraw() maa1.setValuesAt(30) t3 = sph.translation[0] self.assertEqual(t3, 0) vi.OneRedraw() # fly in from right maa2 = FlyInObjectMAA(sph, objectName=None, direction='right', kfpos=[0, 60]) actors = maa2.actors self.assertEqual(len(actors), 3) sph.Set(translation=[0,0,0]) # check that the position (translation) of the object changes from right to center # of the viewer at frames 0 - 30- 60 maa2.setValuesAt(0) vi.OneRedraw() t1 = sph.translation[0] self.assertEqual(t1 > 0, True) maa2.setValuesAt(30) vi.OneRedraw() t2 = sph.translation[0] self.assertEqual(int(t1/2), int(t2)) maa2.setValuesAt(60) vi.OneRedraw() t3 = sph.translation[0] self.assertEqual(t3, 0) # fly in from top maa3 = FlyInObjectMAA(sph, objectName=None, direction='top', kfpos=[0, 30]) actors = maa3.actors self.assertEqual(len(actors), 3) sph.Set(translation=[0,0,0]) # check that the position (translation) of the object changes from top to center # of the viewer at frames 0 - 15 - 30 maa3.setValuesAt(0) vi.OneRedraw() t1 = sph.translation[1] self.assertEqual(t1 > 0, True) maa3.setValuesAt(15) vi.OneRedraw() t2 = sph.translation[1] self.assertEqual(int(t1/2), int(t2)) maa3.setValuesAt(30) vi.OneRedraw() t3 = sph.translation[1] self.assertEqual(t3, 0) # fly in from bottom maa4 = FlyInObjectMAA(sph, objectName=None, direction='bottom', kfpos=[0, 60]) actors = maa4.actors self.assertEqual(len(actors),3) sph.Set(translation=[0,0,0]) sph.Set(visible = 0) # check that the position (translation) of the object changes from bottom to center # of the viewer at frames 0 - 30 - 60 maa4.setValuesAt(0) vi.OneRedraw() # check that the "visible" maa's actor sets the sph.visible attribute to 1 self.assertEqual(sph.visible, 1) t1 = sph.translation[1] self.assertEqual( t1 < 0, True) maa4.setValuesAt(30) vi.OneRedraw() t2 = sph.translation[1] self.assertEqual( int(t1/2), int(t2)) maa4.setValuesAt(60) vi.OneRedraw() t3 = sph.translation[1] self.assertEqual(t3, 0) #run maa maa1.run() maa2.run() maa3.run() self.assertEqual(sph.visible, 1) maa4.run() #check we can reproduce the maa from it's sourcecode: maa5 = None maasrc = maa4.getSourceCode("maa5") viewer = vi exec(maasrc) assert maa5 != None self.assertEqual(len(maa5.actors),3) sph.Set(translation=[0,0,0]) # check that the position (translation) of the object changes from bottom to center # of the viewer at frames 0 - 30 - 60 maa5.setValuesAt(0) vi.OneRedraw() # check that the "visible" maa's actor sets the sph.visible attribute to 1 self.assertEqual(sph.visible, 1) t1 = sph.translation[1] self.assertEqual( t1 < 0, True) maa5.setValuesAt(30) vi.OneRedraw() t2 = sph.translation[1] self.assertEqual( int(t1/2), int(t2)) maa5.setValuesAt(60) vi.OneRedraw() t3 = sph.translation[1] self.assertEqual(t3, 0) def test_flyout(self): """Test creation of FlyOutObjectMAA with different options (number of keyframes, direction); playing different frames of maa .""" vi = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,0,0), (0,1,0), (0,0,1) ], inheritMaterial=False) vi.AddObject(sph) from DejaVu.scenarioInterface.animations import FlyOutObjectMAA # direction: left sph.Set(translation=[0,0,0]) maa1 = FlyOutObjectMAA(sph, objectName=None, direction='left', kfpos=[0, 30]) actors = maa1.actors self.assertEqual (len(actors), 3) vi.OneRedraw() sph.Set(translation=[5,-5,5]) # check that the position (translation) of the object changes from center to left side # of the viewer at frames 0 - 15 - 30 maa1.setValuesAt(0) t1 = sph.translation vi.OneRedraw() self.assertEqual ([t1[0], t1[1], t1[2]] , [0, 0, 0]) maa1.setValuesAt(15) t2 = sph.translation[0] self.assertEqual(t2 < 0, True) vi.OneRedraw() maa1.setValuesAt(30) t3 = sph.translation[0] self.assertEqual(int(t3/2), int(t2)) vi.OneRedraw() # direction: right sph.Set(translation=[0,0,0]) maa2 = FlyOutObjectMAA(sph, objectName=None, direction='right', kfpos=[0, 60]) actors = maa2.actors self.assertEqual(len(actors), 3) vi.OneRedraw() sph.Set(translation=[5,5,5]) # check that the position (translation) of the object changes from center to right side # of the viewer at frames 0 - 30 - 60 maa2.setValuesAt(0) t1 = sph.translation vi.OneRedraw() self.assertEqual([t1[0], t1[1], t1[2]] , [0, 0, 0]) maa2.setValuesAt(30) t2 = sph.translation[0] self.assertEqual(t2 > 0, True) vi.OneRedraw() maa2.setValuesAt(60) t3 = sph.translation[0] self.assertEqual(int(t3/2), int(t2)) vi.OneRedraw() # direction: top sph.Set(translation=[0,0,0]) maa3 = FlyOutObjectMAA(sph, objectName=None, direction='top', kfpos=[0, 30]) actors = maa3.actors self.assertEqual (len(actors), 3) vi.OneRedraw() sph.Set(translation=[-5,5,5]) # check that the position (translation) of the object changes from center to top side # of the viewer at frames 0 - 15 - 30 maa3.setValuesAt(0) t1 = sph.translation vi.OneRedraw() self.assertEqual([t1[0], t1[1], t1[2]] , [0, 0, 0]) maa3.setValuesAt(15) t2 = sph.translation[1] self.assertEqual(t2 > 0, True) vi.OneRedraw() maa3.setValuesAt(30) t3 = sph.translation[1] self.assertEqual(int(t3/2), int(t2)) vi.OneRedraw() # direction: bottom sph.Set(translation=[0,0,0]) maa4 = FlyOutObjectMAA(sph, objectName=None, direction='bottom', kfpos=[0, 60]) actors = maa4.actors self.assertEqual (len(actors), 3) sph.Set(visible = 0) vi.OneRedraw() sph.Set(translation=[5,5,5]) # check that the position (translation) of the object changes from center to top side # of the viewer at frames 0 - 30 - 60 maa4.setValuesAt(0) t1 = sph.translation vi.OneRedraw() self.assertEqual([t1[0], t1[1], t1[2]] , [0, 0, 0]) # check that the "visible" maa's actor sets the sph.visible attribute to 1 self.assertEqual(sph.visible, 1) maa4.setValuesAt(30) t2 = sph.translation[1] self.assertEqual(t2 < 0, True) vi.OneRedraw() maa4.setValuesAt(60) t3 = sph.translation[1] self.assertEqual(int(t3/2), int(t2)) vi.OneRedraw() #run maas maa1.run() maa2.run() maa3.run() self.assertEqual(sph.visible, 1) maa4.run() #check we can reproduce the maa from it's sourcecode: maa5 = None maasrc = maa4.getSourceCode("maa5") viewer = vi exec(maasrc) assert maa5 != None self.assertEqual (len(maa5.actors), 3) sph.Set(translation=[5,5,5]) vi.OneRedraw() # check that the position (translation) of the object changes from center to top side # of the viewer at frames 0 - 30 - 60 ## maa5.setValuesAt(0) ## t1 = sph.translation ## vi.OneRedraw() ## self.assertEqual([t1[0], t1[1], t1[2]] , [0, 0, 0]) ## # check that the "visible" maa's actor sets the sph.visible attribute to 1 ## self.assertEqual(sph.visible, 1) ## maa5.setValuesAt(30) ## t2 = sph.translation[1] ## self.assertEqual(t2 < 0, True) ## vi.OneRedraw() ## maa5.setValuesAt(60) ## t3 = sph.translation[1] ## self.assertEqual(int(t3/2), int(t2)) maa5.run() def check_fadevals(self, maa, obj, vi): # check that the opacity of the object changes from 0 to 1 # at frames 0 - 15 - 30 maa.setValuesAt(0) val1 = obj.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual (val1[0] , 0) self.assertEqual(obj.visible, 1) vi.OneRedraw() maa.setValuesAt(15) val2 = obj.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual (val2[0] , 0.5) vi.OneRedraw() maa.setValuesAt(30) val3 = obj.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual(val3[0], 1) vi.OneRedraw() def test_fadein(self): """Test creation of FadeInObjectMAA and playing different frames of maa .""" vi = viewer = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,0,0), (0,1,0), (0,0,1) ], inheritMaterial=False) viewer.AddObject(sph) from DejaVu.scenarioInterface.animations import FadeInObjectMAA maa1 = FadeInObjectMAA(sph, objectName=None, kfpos=[0, 30]) #check we can reproduce the maa from it's sourcecode: maa2 = None maasrc = maa1.getSourceCode("maa2") #viewer = vi exec(maasrc) assert maa2 != None sph.Set(visible = 0) for maa in [maa1, maa2]: actors = maa.actors self.assertEqual (len(actors), 3) viewer.OneRedraw() # check that the opacity of the object changes from 0 to 1 # at frames 0 - 15 - 30 maa.setValuesAt(0) val1 = sph.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual (val1[0] , 0) self.assertEqual(sph.visible, 1) vi.OneRedraw() maa.setValuesAt(15) val2 = sph.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual (val2[0] , 0.5) vi.OneRedraw() maa.setValuesAt(30) val3 = sph.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual(val3[0], 1) vi.OneRedraw() # run maa maa.run() def test_fadeout(self): """Test creation of FadeInObjectMAA and playing different frames of maa .""" vi = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,0,0), (0,1,0), (0,0,1) ], inheritMaterial=False) vi.AddObject(sph) sph.Set(opacity = 0.8) from DejaVu.scenarioInterface.animations import FadeOutObjectMAA #from DejaVu.Materials import propertyNum # create an instance of FadeOutObjectMAA object maa1 = FadeOutObjectMAA(sph, objectName=None, kfpos=[0, 60]) #check we can reproduce the maa from it's sourcecode: maa2 = None maasrc = maa1.getSourceCode("maa2") viewer = vi print maasrc exec(maasrc) assert maa2 != None # check the maas for maa in [maa1, maa2]: actors = maa.actors self.assertEqual (len(actors), 3) vi.OneRedraw() # check that the opacity of the object changes from 0 to 1 # at frames 0 - 30 - 60 maa.setValuesAt(0) val1 = sph.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual ("%.2f"%val1[0] , "0.80") vi.OneRedraw() maa.setValuesAt(30) val2 = sph.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual ("%.2f"%val2[0] , "0.40") vi.OneRedraw() maa.setValuesAt(60) val3 = sph.materials[1028].prop[propertyNum['opacity']] self.assertEqual(len(val1), 1) self.assertEqual(val3[0], 0) vi.OneRedraw() maa.run() maa.afterAnimation_cb() # check that the last maa's afterAnimation method sets the opacity # to it's original value val = sph.materials[1028].prop[propertyNum['opacity']][0] self.assertEqual("%.2f"%val, "0.80") def test_partialFade(self): """Test creation of PartialFadeMAA, and playing different frames of maa .""" vi = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,0,0), (0,1,0), (0,0,1) ], inheritMaterial=False) vi.AddObject(sph) from DejaVu.scenarioInterface.animations import PartialFadeMAA #from DejaVu.Materials import propertyNum import numpy initVal = {sph: [0.80, 1.0, 0.80, 1.0]} finalVal = {sph: numpy.array([0.0,1.0, 0.0, 1.0], 'f')} maa1 = PartialFadeMAA(sph, initVal, finalVal, kfpos=[0, 100]) #check we can reproduce the maa from it's sourcecode: maa2 = None maasrc = maa1.getSourceCode("maa2") viewer = vi exec(maasrc) assert maa2 != None sph.Set(visible = 0) for maa in [maa1, maa2]: actors = maa.actors self.assertEqual (len(actors), 3) # test that the opacity of the object is changing from initVal to finalVal when maa is set to frames 0 - 50 -100 maa.setValuesAt(0) self.assertEqual(sph.visible , 1) val = sph.materials[1028].prop[1][:,3] #print "val:" , val testval = numpy.array(initVal[sph], "f") self.assertEqual(numpy.alltrue(numpy.equal(val, testval)), True) vi.OneRedraw() maa.setValuesAt(50) val = sph.materials[1028].prop[1][:,3] #print "val:" , val testval = numpy.array([0.40, 1., 0.40, 1.], "f") self.assertEqual(numpy.alltrue(numpy.equal(val, testval)), True) vi.OneRedraw() maa.setValuesAt(100) val = sph.materials[1028].prop[1][:,3] testval = numpy.array(finalVal[sph], "f") self.assertEqual(numpy.alltrue(numpy.equal(val, testval)), True) #print "val:" , val vi.OneRedraw() maa.run() maa.afterAnimation_cb() #check that the afterAnimation method sets the opacity attribute # of the object to its original value val = sph.materials[1028].prop[1][:,3] #print "val:" , val testval = numpy.array([1., 1., 1., 1.], "f") self.assertEqual(numpy.alltrue(numpy.equal(val, testval)), True) def test_visible(self): """Test creation of VisibleObjectMAA """ vi = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,0,0), (0,1,0), (0,0,1) ], inheritMaterial=False) vi.AddObject(sph) from DejaVu.scenarioInterface.animations import VisibleObjectMAA # create maa that sets "visible" attribute of the object to False maa1 = VisibleObjectMAA(sph, visible=0) self.assertEqual (len(maa1.actors), 2) maa1.setValuesAt(0) self.assertEqual(sph.visible , 0) maa1.run() maa1.afterAnimation_cb() # afterAnimation_cb() should set the attribute to it's original value self.assertEqual(sph.visible , 1) # create maa that sets "visible" attribute of the object to True maa2 = VisibleObjectMAA(sph, visible=1) #check we can reproduce the maa from it's sourcecode: maa3 = None maasrc = maa2.getSourceCode("maa3") viewer = vi exec(maasrc) assert maa3 != None for maa in [maa2, maa3]: self.assertEqual (len(maa.actors), 2) sph.Set(visible = 0) maa.setValuesAt(0) self.assertEqual(sph.visible , 1) maa.run() def test_colors(self): """Test creation of ColorObjectMAA and setting the maa to different frames """ vi = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,1,1), (1,1,1), (1,1,1) ], inheritMaterial=False) lines = IndexedPolylines('lines' ,materials=((0,1,0),), vertices=((0,0,0), (5, 0,0), (0,5,0), (0, 0,5)), faces=((0,1),(1,2),(2,3),(3,0)), inheritMaterial = False) vi.AddObject(sph) vi.AddObject(lines) from DejaVu.scenarioInterface.animations import ColorObjectMAA import numpy initColors = {sph: [ (1,1,1), (1,1,1), (1,1,1), (1,1,1)], lines: [(0,1,0),]} finalColors = {sph: [ (1,0,1), (0,0,1), (1,0,0), (0,1,0) ], lines: [(1,0,0)]} root = vi.rootObject lines.Set(visible = 0 ) ## maa = ColorObjectMAA(sph, initColors[sph], finalColors[sph], nbFrames = 200) ## maa1 = ColorObjectMAA(lines, initColors[lines], finalColors[lines], nbFrames = 200) ## maa.addMultipleActorsActionsAt(maa1) maa1 = ColorObjectMAA([sph, lines], initColors, finalColors, nbFrames = 200) #check we can reproduce the maa from it's sourcecode: maa2 = None maasrc = maa1.getSourceCode("maa2") viewer = vi exec(maasrc) assert maa2 != None for maa in [maa1, maa2]: self.assertEqual(len(maa.actors), 5) self.assertEqual(len(maa.origValues), 4) maa.setValuesAt(0) val1 = sph.materials[1028].prop[1][:, :3] #print "1:", val1 val2 = lines.materials[1028].prop[1][:, :3] #print "2", val2 vi.OneRedraw() self.assertEqual(numpy.alltrue(numpy.equal(val1, numpy.array(initColors[sph], "f"))), True) self.assertEqual(numpy.alltrue(numpy.equal(val2, numpy.array(initColors[lines], "f"))), True) self.assertEqual(lines.visible , 1) maa.setValuesAt(100) val1 = sph.materials[1028].prop[1][:, :3] testval1 = numpy.array([[ 1., 0.5, 1. ], [0.5,0.5, 1.], [1., 0.5, 0.5], [0.5, 1., 0.5]],'f') #print "1:", val1 val2 = lines.materials[1028].prop[1][:, :3] #print "2:", val2 testval2 = numpy.array([[ 0.5, 0.5, 0. ]],'f') vi.OneRedraw() self.assertEqual(numpy.alltrue(numpy.equal(val1, testval1)), True) self.assertEqual(numpy.alltrue(numpy.equal(val2, testval2)), True) maa.setValuesAt(200) val1 = sph.materials[1028].prop[1][:, :3] #print "1:", val1 val2 = lines.materials[1028].prop[1][:, :3] #print "2:", val2 vi.OneRedraw() self.assertEqual(numpy.alltrue(numpy.equal(val1, numpy.array(finalColors[sph], "f"))), True) self.assertEqual(numpy.alltrue(numpy.equal(val2, numpy.array(finalColors[lines], "f"))), True) sph.Set(materials = [ (0,0,1), (0.5,0,1), (0,0,1), (05,1,1)], inheritMaterial = 0) lines.Set(materials = [ (1,1,1),], inheritMaterial = 0) # check that the original values are set to the geometries after the maa run. maa.run() maa.afterAnimation_cb() val1 = sph.materials[1028].prop[1][:, :3] val2 = lines.materials[1028].prop[1][:, :3] self.assertEqual(numpy.alltrue(numpy.equal(val1, numpy.array(initColors[sph], "f"))), True) self.assertEqual(numpy.alltrue(numpy.equal(val2, numpy.array(initColors[lines], "f"))), True) self.assertEqual(lines.visible , 0) vi.OneRedraw() def test_rotationMAA(self): from DejaVu.scenarioInterface.animations import RotationMAA import numpy vi = self.vi sph = Spheres( 'sph', centers=[ (0,0,0), (5, 0,0), (0,5,0), (0, 0,5) ], materials = [ (1,1,1), (1,1,1), (1,1,1), (1,1,1) ], inheritMaterial=False) vi.AddObject(sph) root = vi.rootObject origRot = root.rotation.copy() maa1 = RotationMAA(root, angle = 120, nbFrames= 90 ) maa2 = None maasrc = maa1.getSourceCode("maa2") viewer = vi exec(maasrc) assert maa2 != None for maa in [maa1, maa2]: for i in range(30): maa.setValuesAt(i) vi.OneRedraw() rots = [origRot, root.rotation.copy()] assert numpy.alltrue(numpy.equal(rots[0], rots[1])) == False for i in range(30, 60): maa.setValuesAt(i) vi.OneRedraw() for rr in rots: assert numpy.alltrue(numpy.equal(rr, root.rotation)) == False rots.append(root.rotation.copy()) for i in range(60, 90): maa.setValuesAt(i) vi.OneRedraw() for rr in rots: assert numpy.alltrue(numpy.equal(rr, root.rotation)) == False # check that afterAnimation() sets the object to it's orig. value maa.run() #assert numpy.alltrue(numpy.equal(origRot, root.rotation)) == True #print "rotation after run", root.rotation mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/Tests/test_actor.py0000644000175000017500000003233711156030520027135 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################### ## ## ## Author: Sowjanya Karnati ## ## ############################################################################### #$Id: test_actor.py,v 1.4 2009/03/11 21:46:56 annao Exp $ #Contents Tested #ActionWithRedraw #RedrawActor #DejaVuActor #DejaVuFogActor #DejaVuClipZActor #DejaVuScissorActor #DejaVuSpheresRadiiActor #getDejaVuActor import unittest from DejaVu.scenarioInterface.actor import * from Scenario2.interpolators import * from Scenario2.actor import * from DejaVu.Viewer import Viewer from DejaVu.Spheres import Spheres from Scenario2.director import * from DejaVu.IndexedPolylines import IndexedPolylines from numpy.oldnumeric import array class ActionWithRedrawBaseTest(unittest.TestCase): def test_action_defaultargs(self): """testing Action with default args""" myaction=ActionWithRedraw() self.assertEqual(myaction.startFrame,None) self.assertEqual(myaction.endFrame,None) self.assertEqual(myaction.interpolator,None) self.assertEqual(myaction.isFullRange(),True) self.assertEqual(myaction.getFirstFrame(),0) self.assertEqual(myaction.preStep_cb,None) self.assertEqual(str(myaction.postStep_cb)!=None,True) def test_action_with_args(self): """testing Action with args""" myaction=ActionWithRedraw(startFrame=0,endFrame=2,interpolator=KeyFrameInterpolator([10,20])) self.assertEqual(myaction.startFrame,0) self.assertEqual(myaction.endFrame,2) self.assertEqual(isinstance(myaction.interpolator,KeyFrameInterpolator),True) self.assertEqual(myaction.isFullRange(),False) self.assertEqual(myaction.getFirstFrame(),0) self.assertEqual(myaction.preStep_cb,None) self.assertEqual(str(myaction.postStep_cb)!=None,True) #RedrawActorBaseTest(unittest.TestCase): def test_RedrawActor_1(self): """testing calling RedrawActor""" vi = Viewer() myactor=RedrawActor(vi) self.assertEqual(myactor.name,"redraw") self.assertEqual(myactor.object,vi) self.assertEqual(len(myactor.actions),1) self.assertEqual(isinstance(myactor.actions[0],Action),True) vi.Exit() class DejaVuActorBaseTest(unittest.TestCase): #DejaVuActor def test_DejaVuActor_1(self): """tests interpolating radii ,calling DejaVuActor with args setName and getName""" vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, ) vi.AddObject(sph) mydirector=Director() #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuActor myactor=DejaVuActor("radii",sph,setName="radii",getName="radius") myaction=ActionWithRedraw(startFrame=0,endFrame=20,interpolator=KeyFrameInterpFloat((0.6,3.5))) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() self.assertEqual(myactor.setName,"radii") self.assertEqual(myactor.getName,"radius") self.assertEqual(myactor.hasGetFunction,True) self.assertEqual(myactor.initialValue,2.0) vi.Exit() def test_DejaVuActor_2(self): """tests interpolating quality calling DejaVuActor with args setName and getName""" vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, ) vi.AddObject(sph) vi.update() mydirector=Director() #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuActor myactor=DejaVuActor("quality",sph,setName="quality",getName="stacks") myaction=ActionWithRedraw(startFrame=0,endFrame=20,interpolator=KeyFrameInterpFloat((10,40))) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() self.assertEqual(myactor.setName,"quality") self.assertEqual(myactor.getName,"stacks") self.assertEqual(myactor.hasGetFunction,True) self.assertEqual(myactor.initialValue,30) vi.Exit() def test_DejaVuActor_3(self): """tests interpolating scale""" vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, ) vi.AddObject(sph) vi.update() mydirector=Director() #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuActor myactor=DejaVuActor("scale",sph) myaction=ActionWithRedraw(startFrame=0,endFrame=100,interpolator=ScaleInterpolator([(1.0,1.0,1.0),(5.0,5.0,5.0)])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() self.assertEqual(myactor.setName,"scale") self.assertEqual(myactor.getName,"scale") self.assertEqual(myactor.hasGetFunction,True) self.assertEqual(myactor.initialValue,[1.0,1.0,1.0]) vi.Exit() def test_DejaVuActor_4(self): """tests interpolating rotation""" vi = Viewer() points = ((0,0,0),(5,0,0),(0,5,0)) indices = ((0,1),(0,2)) polylines= IndexedPolylines("box", vertices=points, faces=indices, visible=1) vi.AddObject(polylines) lines_set_rotation = lambda actor,value:actor.object.Set(rotation=value) start_mat=Numeric.identity(4,'f') z=[[0,-1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]] mat=array(z) s=Numeric.reshape(start_mat,(16,)) e=Numeric.reshape(mat,(16,)) mydirector=Director() #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuActor myactor=DejaVuActor("rotation",polylines) myaction=ActionWithRedraw(startFrame=0,endFrame=100,interpolator=RotationInterpolator(values=[s,e])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() self.assertEqual(myactor.setName,"rotation") self.assertEqual(myactor.getName,"rotation") self.assertEqual(myactor.hasGetFunction,True) self.assertEqual(myactor.initialValue, array([ 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.],'f')) vi.Exit() def test_DejaVuActor_translation(self): """tests interpolating translation""" mydirector=Director() vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, inheritLineWidth=0, inheritMaterial=False) vi.AddObject(sph) #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuActor starts=Numeric.zeros(3,'f') ends = Numeric.array([1,1,1],'f') myactor=DejaVuActor("translation",sph) myaction=ActionWithRedraw(startFrame=0,endFrame=200,interpolator=TranslationInterpolator(values=[starts,ends])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() self.assertEqual(myactor.setName,"translation") self.assertEqual(myactor.getName,"translation") self.assertEqual(myactor.hasGetFunction,True) self.assertEqual(myactor.initialValue,[0.0,0.0,0.0]) vi.Exit() def test_DejaVuActor_pivot(self): """tests interpolating pivot""" mydirector=Director() vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, inheritLineWidth=0, inheritMaterial=False) vi.AddObject(sph) #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuActor starts=Numeric.zeros(3,'f') ends = Numeric.array([1,1,1],'f') myactor=DejaVuActor("pivot",sph) myaction=ActionWithRedraw(startFrame=0,endFrame=200,interpolator=TranslationInterpolator(values=[starts,ends])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() self.assertEqual(myactor.setName,"pivot") self.assertEqual(myactor.getName,"pivot") self.assertEqual(myactor.hasGetFunction,True) self.assertEqual(myactor.initialValue,[0.0,0.0,0.0]) vi.Exit() class DejaVuFogActorBaseTest(unittest.TestCase): def test_DejaVuFogActor_1(self): """tests calling DejaVuFogActor""" mydirector=Director() vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, inheritLineWidth=0, inheritMaterial=False) vi.AddObject(sph) #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuFogActor myactor=DejaVuFogActor("fog",vi.currentCamera) myaction=ActionWithRedraw(startFrame=0,endFrame=10,interpolator=SequenceLinearInterpolator([[0.1,50.0],[45.0,50.0]])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() vi.Exit() class DejaVuClipZActorBaseTest(unittest.TestCase): def test_DejaVuClipZActor_1(self): """tests calling DejaVuClipZActor""" mydirector=Director() vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, inheritLineWidth=0, inheritMaterial=False) vi.AddObject(sph) #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuClipZActor myactor=DejaVuClipZActor("clipZ",vi.currentCamera) myaction=ActionWithRedraw(startFrame=0,endFrame=10,interpolator=SequenceLinearInterpolator([[0.1,50.0],[45.0,50.0]])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() vi.Exit() class DejaVuSperesRadiiActorBaseTest(unittest.TestCase): def test_DejaVuSperesRadiiActor_1(self): """tests calling DejaVuSperesRadiiActor""" mydirector=Director() vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, inheritLineWidth=0, inheritMaterial=False) vi.AddObject(sph) #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuSperesRadiiActor vi.update() myactor=DejaVuSperesRadiiActor("radii",sph) myaction=ActionWithRedraw(startFrame=0,endFrame=200,interpolator=listNFloatInterpolator([[1.0,4.0],[4.0,1.0]])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() vi.Exit() class DejaVuScissorActorBaseTest(unittest.TestCase): def test_DejaVuScissorActor_1(self): """tests calling DejaVuScissorActor""" mydirector=Director() vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, inheritLineWidth=0, inheritMaterial=False) vi.AddObject(sph) sph.Set(scissor=1) #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuScissorActor myactor=DejaVuScissorActor("scissor",sph) myaction=ActionWithRedraw(startFrame=0,endFrame=200,interpolator=KeyFrameInterp4Float([[2.0,3.0,4.0,5.0],[120.0,130.0,140.0,150.0]])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() self.assertEqual(sph.getState()['scissorH'],120.0) self.assertEqual(sph.getState()['scissorW'],130.0) self.assertEqual(sph.getState()['scissorX'],140.0) self.assertEqual(sph.getState()['scissorY'],150.0) vi.Exit() #getDejaVuActor def test_getDejaVuActor_1(self): """tests calling getDejaVuActor""" mydirector=Director() vi = Viewer() sph = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=2.0, quality=30, inheritLineWidth=0, inheritMaterial=False) vi.AddObject(sph) #RedrawActor myactor1=RedrawActor(vi) mydirector.addActor(myactor1) #DejaVuScissorActor myactor=getDejaVuActor(sph,"radii") myaction=ActionWithRedraw(startFrame=0,endFrame=200,interpolator=listNFloatInterpolator([[1.0,1.0],[4.0,4.0],[1.0,1.0]])) myactor.addAction(myaction) mydirector.addActor(myactor) mydirector.run() vi.Exit() if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/Tests/__init__.py0000644000175000017500000000006010625424054026522 0ustar debiandebian# ignore = { 'test_actor' : [] } mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/Tests/test_view.py0000644000175000017500000001070111440251735026777 0ustar debiandebianfrom DejaVu import Viewer from DejaVu.Spheres import Spheres import numpy def test_views001(): """ Test that: we can create a view, add it to a director, move the scene toa new place, save the new place as a second view use the director to go back to the initial view add the second view to the director at position 40 move to a new position play the animation going from the current position to the initial view and the to the second view """ vi = Viewer() sph = Spheres( 'sph', centers=[ (0,0,0), (10, 0,0), (0,10,0), (0, 0,10) ], materials = [ (1,1,1), (1,0,0), (0,1,0), (0,0,1) ], inheritMaterial=False) vi.AddObject(sph) root = vi.rootObject cam = vi.currentCamera mat1g = root.GetMatrix() mat1c = cam.GetMatrix() # create view with identity transformation from DejaVu.scenarioInterface.animations import OrientationMAA from DejaVu.states import getRendering, getOrientation #orient = getOrientation(root) orient = None rendering = getRendering(vi) maa1 = OrientationMAA(root, 'temp', orient, rendering) # create a director ## from Scenario2.director import Director ## d = Director() from Scenario2.director import MAADirector d = MAADirector() # add the maa1 to the director #val = d.addMultipleActorsActionsAt(maa1) val = d.addMAAat(maa1, 0) assert val ==True # check the animation names, posLabel, posStr, actStr, fullStr = maa1.getStringRepr() redrawActor = maa1.actors[0] ## check that we have this: ## 1 2 3 ## 0 0 0 0 ## | : | : | : | ## root.rotation x-----------------------------x ## root.translati x-----------------------------x ## root.scale x-----------------------------x ## root.pivot x-----------------------------x ## Camera0.fieldO x---------x---------x---------x ## Camera0.lookFr x-----------------------------x ## redraw_******* No Keyframes ## testStr = " 1 2 3\n 0 0 0 0\n | : | : | : |\n root.rotation x-----------------------------x\nroot.translati x-----------------------------x\n root.scale x-----------------------------x\n root.pivot x-----------------------------x\nCamera0.fieldO x---------x---------x---------x\nCamera0.lookFr x-----------------------------x\n%014s No Keyframes\n" % redrawActor.name[:14] ## assert fullStr == testStr # translate the scene to (10, 0, 0) root.SetTranslation( numpy.array( (10, 0, 0) ) ) vi.OneRedraw() #save this position as our second view #orient = getOrientation(root) orient = None rendering = getRendering(vi) maa2 = OrientationMAA(root, 'temp2', orient, rendering) #maa2 = OrientationMAA(root, "Viewer", 'view1') mat2g = root.GetMatrix() mat2c = cam.GetMatrix() # play the director. We shoudl move from current position to identity tranformation #d.actors[1].printValuesWhenSetting = True #d.run() d.play() #maa1.run() # check that transformation matrices are correctly returned to identity mat3g = root.GetMatrix() mat3c = cam.GetMatrix() assert numpy.sum(mat1g-mat3g)==0.0 assert numpy.sum(mat1c-mat3c)==0.0 # add second view to director at 40 #val = d.addMultipleActorsActionsAt(maa2, 40) val = d.addMAAat(maa2, 40) assert val == True # move to other position root.SetTranslation( numpy.array( (-10, 0, 0) ) ) vi.OneRedraw() #play back motion from this position to origin and then to view1 #d.run() d.play() mat4g = root.GetMatrix() mat4c = cam.GetMatrix() assert numpy.sum(mat4g-mat2g)==0.0 assert numpy.sum(mat4c-mat2c)==0.0 maa3 = None viewer = vi showwarning = 0 # check if we can reproduce MAA from it's source maasrc = maa2.getSourceCode("maa3") exec(maasrc) assert maa3 != None # replace the original MAA (maa2) with the one created from source d.removeMAA(maa2, 40) d.addMAAat(maa3,40) # move to other position and play : root.SetTranslation( numpy.array( (-10, 0, 0) ) ) vi.OneRedraw() d.play() # check the values mat5g = root.GetMatrix() mat5c = cam.GetMatrix() assert numpy.sum(mat5g-mat2g)==0.0 assert numpy.sum(mat5c-mat2c)==0.0 vi.Exit() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/scenarioInterface/__init__.py0000644000175000017500000007035111243106553025430 0ustar debiandebianfrom DejaVu.scenarioInterface.actor import getAnimatableAttributes, getActorName def getActor(object, propname): """ create an actor from a DejaVu object instance and a property name. Actor <- getActor(object, propname) object is an instance of a DejaVu obbject (e.g. Geom, Camera, etc) propname is the name of the attribute in object that willbe animated """ animatableProps = getAnimatableAttributes(object) if not animatableProps[0].has_key(propname): print "DejaVu.scenarioInterface.getActor: cannot create %s actor for object:" % (propname,), object return None descr = animatableProps[0][propname] actorname = getActorName(object, propname) actorClass, args, kw = descr['actor'] actor = actorClass( *(propname, object)+args, **kw ) return actor ## def rotationAboutMat(pivot, rotation): ## """ ## build and return rotation matrix for a rotation about a pivot point ## """ ## m = rotation.copy() ## m.shape = (4,4) ## # first multiply rotation by -pivot ## m[0][3] = m[0][0]*(-pivot[0]) + m[0][1]*(-pivot[1]) + m[0][2]*(-pivot[2]) ## m[1][3] = m[1][0]*(-pivot[0]) + m[1][1]*(-pivot[1]) + m[1][2]*(-pivot[2]) ## m[2][3] = m[2][0]*(-pivot[0]) + m[2][1]*(-pivot[1]) + m[2][2]*(-pivot[2]) ## # now multiply pivot by m ## m[0][3] += pivot[0] ## m[1][3] += pivot[1] ## m[2][3] += pivot[2] ## mat = (numpy.transpose(numpy.reshape(m, (4,4)))).flatten() ## return mat ## from Scenario2.multipleActorsActions import MultipleActorsActions ## def fullRot(viewer, nbFrames=180., pivot=(0.,0.,0.), axis='Y' ): ## """ ## build a full rotation animation adn return it as a MultipleActorActions ## MAA <- fullRot(viewer, nbFrames=180., point1=None, point2=None, axis='Y' ) ## viewer is an instance of a DejaVu Viewer ## nbFrames is the number of Frames the animation will take ## The rotation axis can be specified either by specifying a rotation axis ## using a letter in 'X' 'x' 'Y' 'y' 'Z' and 'z' or by specifying 2 a list ## of two 3D points (e.g. [(0.,0.,0.), (1,.1,.1.)] ## The rotation axis will be going through the pivot point ## 4 Keyframes are created, one for the identity rotation, one for an angle ## of 120 degrees, one at 240 degrees and finally one at lastAngle degrees. ## LastAngle is computed to be the last increment before getting back to the ## initial position. ## """ ## # FIXME we should compute the rotation center and add it to p1 and p2 ## root = viewer.rootObject ## from DejaVu.scenarioInterface import getActor ## from scenario.interpolators import matToQuaternion ## from Scenario2.keyframes import Interval, KF ## import numpy, math ## actor = getActor(root, 'rotation') ## from mglutil.math.rotax import rotax ## # define the axis ## p1 = (0.,0.,0.) ## try : ## point1, point2 = axis ## x1, y1, z1 = point1 ## p1 = (x1, y1, z1) ## x2,y2,z2 = point2 ## p2 = (x2, y2, z2) ## except: ## axis = axis.lower() ## p1 = pivot ## if axis=='x': ## p2 = (pivot[0]+1., pivot[1], pivot[2]) ## elif axis=='y': ## p2 = (pivot[0], pivot[1]+1., pivot[2]) ## elif axis=='z': ## p2 = (pivot[0], pivot[1], pivot[2]+1.) ## else: ## raise ValueError("bad axis for fullRot: %s"%str(axis)) ## # compute number of frames for each interval ## nbFrames1 = int(nbFrames/3.) ## nbFrames2 = nbFrames-nbFrames1-nbFrames1 ## angleIncr = 360. / nbFrames ## lastAngle = 360. - angleIncr ## # compute 4 quaternions ## q0 = matToQuaternion(numpy.identity(4).flatten()) ## mat1 = rotax( p1, p2, 120*math.pi/180.) ## q120 = matToQuaternion( mat1.flatten() ) ## mat2 = rotax( p1, p2, 240*math.pi/180.) ## q240 = matToQuaternion( mat2.flatten() ) ## mat3 = rotax( p1, p2, lastAngle*math.pi/180.) ## qlast = matToQuaternion( mat3.flatten() ) ## kf0 = KF( 0 , q0) ## kf1 = KF( nbFrames1, q120) ## kf2 = KF( 2*nbFrames1, q240) ## kf3 = KF( nbFrames-1, qlast) ## i1 = Interval( kf0, kf1, generator = actor.behaviorList) ## actor.addIntervals( [i1] ) ## i2 = Interval( kf1, kf2, generator = actor.behaviorList) ## actor.addIntervals( [i2] ) ## i3 = Interval( kf2, kf3, generator = actor.behaviorList) ## actor.addIntervals( [i3] ) ## from Scenario2.multipleActorsActions import MultipleActorsActions ## maa = MultipleActorsActions('full rotation Y') ## maa.AddActions( actor, actor.actions ) ## ## # translation ## ## actor = getActor(root, 'translation') ## ## kf0 = KF( 0 , [0,0,0]) ## ## kf1 = KF( nbFrames1, mat1[3,:3]) ## ## kf2 = KF( 2*nbFrames1, mat2[3,:3]) ## ## kf3 = KF( nbFrames-1, mat3[3,:3]) ## ## i1 = Interval( kf0, kf1, generator = actor.behaviorList) ## ## actor.addIntervals( [i1] ) ## ## i2 = Interval( kf1, kf2, generator = actor.behaviorList) ## ## actor.addIntervals( [i2] ) ## ## i3 = Interval( kf2, kf3, generator = actor.behaviorList) ## ## actor.addIntervals( [i3] ) ## ## maa.AddActions( actor, actor.actions ) ## return maa ## def fullRot1(viewer, nbFrames=180., pivot=(0.,0.,0.), axis='Y' ): ## """ ## build a full rotation animation adn return it as a MultipleActorActions ## MAA <- fullRot(viewer, nbFrames=180., point1=None, point2=None, axis='Y' ) ## viewer is an instance of a DejaVu Viewer ## nbFrames is the number of Frames the animation will take ## The rotation axis can be specified either by specifying a rotation axis ## using a letter in 'X' 'x' 'Y' 'y' 'Z' and 'z' or by specifying 2 a list ## of two 3D points (e.g. [(0.,0.,0.), (1,.1,.1.)] ## The rotation axis will be going through the pivot point ## A Keyframes is create ofr every angular increment ## """ ## root = viewer.rootObject ## from DejaVu.scenarioInterface import getActor ## from scenario.interpolators import matToQuaternion ## from Scenario2.keyframes import Interval, KF ## from mglutil.math.rotax import rotax ## import numpy, math ## rotActor = getActor(root, 'rotation') ## transActor = getActor(root, 'translation') ## # define the axis ## p1 = (0.,0.,0.) ## try : ## point1, point2 = axis ## x1, y1, z1 = point1 ## p1 = (x1, y1, z1) ## x2,y2,z2 = point2 ## p2 = (x2, y2, z2) ## except: ## axis = axis.lower() ## p1 = pivot ## if axis=='x': ## p2 = (pivot[0]+1., pivot[1], pivot[2]) ## elif axis=='y': ## p2 = (pivot[0], pivot[1]+1., pivot[2]) ## elif axis=='z': ## p2 = (pivot[0], pivot[1], pivot[2]+1.) ## else: ## raise ValueError("bad axis for fullRot: %s"%str(axis)) ## # compute number of frames for each interval ## angleIncr = 360. / nbFrames ## angle = 0 ## torad = math.pi/180. ## for i in range(nbFrames): ## mat = rotax( p1, p2, angle*torad) ## kfr = KF( i , matToQuaternion( mat.flatten() ) ) ## rotActor.addKeyframe(kfr) ## kft = KF( i, mat[3,:3]) ## transActor.addKeyframe(kft) ## angle += angleIncr ## from Scenario2.multipleActorsActions import MultipleActorsActions ## maa = MultipleActorsActions('full rotation %s'%str(axis)) ## maa.AddActions( rotActor, rotActor.actions ) ## maa.AddActions( transActor, transActor.actions ) ## return maa try: import Tkinter #from Scenario2.director import Director #from Scenario2.gui import DirectorGUI from Scenario2.actor import Actor from mglutil.util.callback import CallbackFunction from DejaVu.Geom import Geom from DejaVu.Camera import Camera from DejaVu.Light import Light from DejaVu.Clip import ClippingPlane from DejaVu.Viewer import SetCurrentObjectEvent, SetCurrentCameraEvent, SetCurrentLightEvent, SetCurrentClipEvent, AddObjectEvent from actor import RedrawActor, getAnimatableAttributes, getActorName import numpy from SimpleDialog import SimpleDialog import weakref class DejaVuScenario: """Class binding a DejaVu Viewer to a Scenario Director """ ## This class allows to connect a DejaVu Viewer to a scenario Director ## The DejaVu viewer will have a new attribute director. ## a RedrawActor is added automatically to the director ## The director gets a new attribute .needRedraw that the RerawActor uses to ## optimize redraw calls ## A menu buttons are added to the Viewer GUI to allow animation of objects ## A callback function is register in the viewer to handle setting the current( ## Object, Camera, light, ciping plane. ## DejaVu objects that are animated get new attribute: ## object.animatableProps which is a list of 2 dictionaries. ## Both dicts contain {attribute name:{actorDescr}} items. The first ## dict contains attributes explicitely decalared, the second contains ## attributes picked up on the fly ## def __init__(self, vi, director=None): self.application = vi if director is None: director = Director() self.menuCreated = False self.name = "DejaVuScenario" self.fileactorGui = {} self._director = weakref.ref(director) ## animatedProperties is a dict {actor.name : Actor instance } self.animatedProperties = {} def start(self): director = self._director() director.start() self.setDirector() def setDirector(self): if not self.menuCreated: vi = self.application director = self._director() vi.director = director # add needsRedraw attribute director.needsRedraw = False # add RedrawActor actor actor = RedrawActor(vi) #actor.setKeyframe(50,0) director.addActor(actor ) director.redrawActor = actor director.gui.setDuration(50) # add menu button to ViewerGUI # Objects self.animObjMenuB = menuB = Tkinter.Menubutton( vi.GUI.inheritF, text='Animate', relief='raise' ) menuB.menu = Tkinter.Menu(menuB) menuB['menu'] = menuB.menu menuB.pack(fill='x') # Cameras self.animCamMenuB = menuB = Tkinter.Menubutton( vi.GUI.CameraProp, text='Animate', relief='raise' ) menuB.menu = Tkinter.Menu(menuB) menuB['menu'] = menuB.menu menuB.pack(fill='x') # Lights self.animLightMenuB = menuB = Tkinter.Menubutton( vi.GUI.LightProp, text='Animate', relief='raise' ) menuB.menu = Tkinter.Menu(menuB) menuB['menu'] = menuB.menu menuB.pack(fill='x') # Cliping planes self.animClipMenuB = menuB = Tkinter.Menubutton( vi.GUI.ClipProp, text='Animate', relief='raise' ) menuB.menu = Tkinter.Menu(menuB) menuB['menu'] = menuB.menu menuB.pack(fill='x') # expand viewergui to accomodate Animate buttons vi.GUI.propertyNoteBook.setnaturalsize(pageNames=(vi.GUI.propertyNoteBook.getcurselection(),)) vi.GUI.sf.interior().pack(fill = 'both', expand = 1) vi.GUI.sf.pack(fill = 'both', expand = 1) # register interest in setting current(object, camera, light, clip) func = self.setCurrentObjectAttrList_cb vi.registerListener(SetCurrentObjectEvent, func) vi.registerListener(SetCurrentCameraEvent, func) vi.registerListener(SetCurrentLightEvent, func) vi.registerListener(SetCurrentClipEvent, func) # call the callback once to fill menus for current object self.setCurrentObjectAttrList(vi.currentObject) self.setCurrentObjectAttrList(vi.currentCamera) self.setCurrentObjectAttrList(vi.currentClip) self.setCurrentObjectAttrList(vi.currentLight) self.menuCreated = True def setCurrentObjectAttrList_cb(self, event): self.setCurrentObjectAttrList(event.object) def setCurrentObjectAttrList(self, object, event=None): if not hasattr(object, 'animatableProps'): object.animatableProps = getAnimatableAttributes(object) #if not hasattr(object, 'animatedProperties'): # object.animatedProperties = {} self.createCheckbuttons(object) def createCheckbuttons(self, object): # get menu button if isinstance(object, Geom): menuB = self.animObjMenuB elif isinstance(object, Camera): menuB = self.animCamMenuB elif isinstance(object, Light): menuB = self.animLightMenuB elif isinstance(object, ClippingPlane): menuB = self.animClipMenuB else: print 'no menu button for object:', object, object.__class__ return # clear menu's content menuB.menu.delete(0, 'end') # get list of properties p1 = object.animatableProps[0].keys() p1.sort() propnames = p1 #p2 = object.animatableProps[1].keys() #p2.sort() #propnames = p1+p2 # get dict of currently animated properties for this object #aprop = object.animatedProperties aprop = self.animatedProperties for i, name in enumerate(propnames): var = Tkinter.IntVar() actorname = getActorName(object, name) if aprop.has_key(actorname): var.set(1) aprop[actorname].guiVar = var cb = CallbackFunction( self.toggleAnimatePropVar, name, var, object) menuB.menu.add_checkbutton( label=name, command=cb, variable = var) menuB.menu.add_separator() cb = CallbackFunction(self.actorFromFile_cb, propnames, object) menuB.menu.add_command( label="Create Actor From File", command=cb) def toggleAnimatePropVar(self, propname, var, object): # toggle variable associated with the checkbutton for this # object.propname actor value = var.get() if value: self.createActor(object, propname, var) else: self.deleteActor(object, propname) def deleteActor(self, object, propname): # delete the actor for object.name actorname = getActorName(object, propname) #actor = object.animatedProperties[actorname] actor = self.animatedProperties[actorname] if actor.object != object: return self._director().deleteActor(actor) #del object.animatedProperties[actorname] del self.animatedProperties[actorname] def createActor(self, object, propname, variable = None, check = True, addToDirector = True, actorData=None, redraw = True, valueGenerator = None): #if not object.hasBeenCurrent : # self.setCurrentObjectAttrList(object) #if not hasattr(object, 'animatedProperties'): # object.animatedProperties = {} if not hasattr(object, 'animatableProps'): object.animatableProps = getAnimatableAttributes(object) # create an actor for object.propname descr = object.animatableProps[0][propname] actorname = getActorName(object, propname) director = self._director() newactor = True if check: for i, a in enumerate(director.actors): if a.name == actorname: text = "Actor %s exists. Do you want to overwrite it?\n"%actorname d = SimpleDialog(director.gui.root, text=text, buttons=["Yes", "No"], default=1, title="Overwrite Actor Dialog") result = d.go() if result == 1: return None else: newactor = False # actorind = i break #create the actor actorClass, args, kw = descr['actor'] if valueGenerator is not None: kw['interp'] = valueGenerator if actorData is not None: from scenario.actor import FileActor actor = FileActor(*(propname, object, actorClass, actorData)+args, **kw) actorname = actor.name else: actor = actorClass( *(propname, object)+args, **kw ) actor.scenario = self #object.animatedProperties[actorname] = actor self.animatedProperties[actorname] = actor if not newactor: # director already has an actor with name "actorname", # and the user wishes to overwrite it # replace existing actor whith the new one oldactor = director.actors.pop(actorind) director.gui.deleteActor(oldactor) director.actors.insert(actorind, actor) actor._director = weakref.ref(director) posy = oldactor._posy director.gui.drawActor(actor, posy) if oldactor.guiVar: variable = oldactor.guiVar else: if addToDirector: # add actor to the director director.addActor(actor, redraw) if variable: actor.guiVar = variable return actor def numarr2str(self, val): threshold = numpy.get_printoptions()["threshold"] numpy.set_printoptions(threshold=val.size) valstr = "array(" + numpy.array2string(val, precision =3, separator =",") + ", '%s')"%val.dtype.char #valstr.replace("\n", "\n\t") numpy.set_printoptions(threshold=threshold) return valstr def getActorScript(self, actor, indent, actorind): lines = [] lines.append(indent + "vi = sci.application \n") object = actor.object name = actor.name if name == "redraw": lines.append(indent + "if not director.redrawActor:\n") lines.append(indent + " from DejaVu.scenarioInterface.actor import RedrawActor\n") lines.append(indent + " actor%d = RedrawActor(vi)\n" % actorind) lines.append(indent + " director.addActor(actor%d)\n" % actorind) lines.append(indent + " director.redrawActor = actor%d\n" % actorind) return lines, indent propname = name.split(".")[-1] scenarioname = actor.scenarioname from scenario.actor import FileActor isFileActor = False if isinstance(actor, FileActor): isFileActor = True else: lines.append(indent + "# keyframe values: \n") lines.append(indent + "vals = [] \n") if hasattr(actor, "keyframeValues"): values = actor.keyframeValues else: values = actor.keyframes.values for val in values: if type(val) == numpy.ndarray: lines.append(indent + "from numpy import array\n") valstr = indent + "vals.append(" + self.numarr2str(val) + ")" else: try: # value can be a list of arrays nbval = len(val) isarray = False valstr = indent + "vals.append([" for n in range(nbval): if type(val[n]) == numpy.ndarray: isarray = True valstr = valstr + self.numarr2str(val[n]) + "," else: valstr = valstr + "%s"%val[n] + "," valstr = valstr + "])" if isarray: lines.append(indent + "from numpy import array\n") except: valstr = indent + "vals.append(%s)" %(val,) lines.append(valstr) lines.append("\n") if hasattr(object, "fullName"): objname = object.fullName lines.append(indent+"obj%d = vi.FindObjectByName('%s')\n"%(actorind, objname)) setCurrentFunc = "vi.SetCurrentObject(obj%d)\n"%actorind else: objname = object.name if isinstance(object, Camera): ind = self.application.cameras.index(object) lines.append(indent + "obj%d = vi.cameras[%d]\n"%(actorind, ind)) setCurrentFunc = "vi.SetCurrentCamera(obj%d)\n"%actorind elif isinstance(object, Light): ind = self.application.lights.index(object) lines.append(indent + "obj%d = vi.lights[%d]\n"%(actorind, ind)) setCurrentFunc = "vi.SetCurrentLight(obj%d)\n"%actorind elif isinstance(object, ClippingPlane): ind = self.application.clipP.index(object) lines.append(indent + "obj%d = vi.clipP[%d]\n"%(actorind, ind)) setCurrentFunc = "vi.SetCurrentClip(obj%d)\n"%actorind lines.append(indent + "if not obj%d: tkMessageBox.showwarning('DejaVu Scenario Warning', 'Object %s does not exist.\\nCannot create actor %s')\n"% (actorind, objname, name)) lines.append(indent + "else: \n") indent = indent + " " lines.append(indent + setCurrentFunc) if not isFileActor: lines.append(indent+"try:\n") newindent = indent + " " lines.append(newindent+"actor%d = sci.createActor(obj%d, '%s', redraw=False)\n"% (actorind, actorind, propname)) lines.append(indent+"except: tkMessageBox.showwarning('DejaVu Scenario warning', 'Could not create actor %s')\n" % name) lines.append(indent+"if actor%d:\n"%actorind) lines.append(newindent+"if hasattr(actor%d, 'keyframeValues'):\n"%actorind) lines.append(newindent+" actor%d.keyframeValues = vals\n" % actorind) return lines, indent def getNewActors(self): # return a dictionary containing all available actors that are not in the # scenario's director. vi = self.application director = self._director() autotrackDict = director.autotrackDict if not vi.eventListeners.has_key(AddObjectEvent): func = self.getNewActor_cb vi.registerListener(AddObjectEvent, func) newDict = {} actornames = map(lambda x: x.name, director.actors[1:]) allobjects = [] for object in vi.rootObject.AllObjects(): ## if object.name != "root": ## v = hasattr(object, 'vertexSet') ## f = hasattr(object, 'faceSet') ## if v and f: ## numv = len(object.vertexSet) ## numf = len(object.faceSet) ## if numv == numf == 0: ## continue ## elif v: ## numv = len(object.vertexSet) ## if numv == 0: ## continue ## if not object.visible: ## continue if object.listed: # FIX THIS: we probably do not need to track all of the objects (too many actors), # currently, do not include Viewer's objects under 'root|misc' and 'selection' objects if object.fullName.find("misc") < 0 and object.fullName.find("selection") < 0: allobjects.append(object) for c in vi.cameras: allobjects.append(c) for lt in vi.lights: if lt.enabled: allobjects.append(lt) if vi.activeClippingPlanes > 0: allobjects.append(vi.currentClip) #for cp in vi.clipP: # if cp.enabled: # allobjects.append(cp) for object in allobjects: #self.setCurrentObjectAttrList(object) props = getAnimatableAttributes(object)[0] #print "object : ", object, props.keys() for propname in props.keys(): descr = props[propname] actorname = getActorName(object, propname) if not autotrackDict.has_key(actorname): if not actorname in actornames: # actor 'actorname' does not exist - create it and add to # newDict actorClass, args, kw = descr['actor'] actor = actorClass( *(propname, object)+args, **kw ) actor.scenario = self newDict[actorname] = actor return newDict def getNewActor_cb(self, event): object = event.object if object.listed: if hasattr(object, "fullName"): if object.fullName.find("selection") >= 0: return vi = self.application director = self._director() autotrackDict = director.autotrackDict props = getAnimatableAttributes(object)[0] #print "object : ", object, props.keys() for propname in props.keys(): descr = props[propname] actorname = getActorName(object, propname) if not autotrackDict.has_key(actorname): actorClass, args, kw = descr['actor'] actor = actorClass( *(propname, object)+args, **kw ) actor.scenario = self autotrackDict[actorname] = actor if actor.hasGetFunction: val = actor.getValueFromObject() else: val = None def actorFromFile_cb(self, propnames, object): director = self._director() #from actorFromFile import fromFileForm #form = fromFileForm(self, propnames, object, command = director.createFileActor) from scenario.fileActorGUI import fileActorGUI if object in self.fileactorGui.keys(): self.fileactorGui[object].show() else: self.fileactorGui[object] = fileActorGUI(self, propnames, object, director.createActorFromData) def onAddActorToDirector(self, actor): # create check buttons on the Viewer's gui (used when actor is added by # 'autotrack; feature object = actor.object #if not hasattr(object, 'animatedProperties'): # object.animatedProperties = {} #object.animatedProperties[actor.name] = actor self.animatedProperties[actor.name] = actor self.setCurrentObjectAttrList(object) except ImportError: import traceback traceback.print_exc() traceback.print_stack() print 'WARNING: failed to import package Scenario2' mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Arrows.py0000644000175000017500000005023111316245140021512 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Alex T. GILLET # # Copyright: A. Gillet TSRI 2003 # ############################################################################# # # $Header: # # $Id: w # ## # class to draw a arrow in DejaVu ## from opengltk.OpenGL import GL import numpy.oldnumeric as Numeric from numpy.oldnumeric import array from IndexedGeom import IndexedGeom import datamodel, viewerConst from viewerFns import checkKeywords from Materials import Materials from colorTool import glMaterialWithCheck, resetMaterialMemory class Arrows(IndexedGeom): """Class for sets of arrows""" keywords = IndexedGeom.keywords def __init__(self, name=None, check=1, **kw): if __debug__: if check: apply( checkKeywords, (name,self.keywords), kw) if not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set apply( IndexedGeom.__init__, (self, name, 0), kw) self.culling = GL.GL_BACK self.inheritCulling = 0 assert len(self.vertexSet.vertices.ashape)==2 self.frontPolyMode = GL.GL_FILL self.inheritFrontPolyMode = viewerConst.NO self.lighting = viewerConst.YES self.realFMat = Materials() # used in RedoDisplayList to build self.realBMat = Materials() # used in RedoDisplayList to build # material taking getFrom into account self.radius = 0.2 self.oneRadius = viewerConst.YES self._arrowTemplate(4) Arrows.Set(self) self._modified = False def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( IndexedGeom.Set, (self, check, 0), kw ) v=kw.get('vertices') if v: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.oneRadius = viewerConst.NO return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): if len(self.vertexSet.vertices) == 0: return 0 if self.inheritMaterial: fp = None bp = None face = None else: mat = self.materials[GL.GL_FRONT] rmat = self.realFMat bind = [10,10,10,10] for pInd in range(4): bind[pInd], rmat.prop[pInd] = mat.GetProperty(pInd) rmat.prop[4] = mat.prop[4] rmat.prop[5] = mat.prop[5] rmat.binding[:4] = bind rmat.binding[4:] = rmat.binding[4:] fp = rmat if fp: if self.frontAndBack: face = GL.GL_FRONT_AND_BACK bp = None else: face = GL.GL_FRONT mat = self.materials[GL.GL_BACK] rmat = self.realBMat bind = [10,10,10,10] for pInd in range(4): bind[pInd], rmat.prop[pInd]=mat.GetProperty(pInd) rmat.prop[4] = mat.prop[4] rmat.prop[5] = mat.prop[5] rmat.binding[:4] = bind rmat.binding[4:] = rmat.binding[4:] bp = rmat c = self.vertexSet.vertices.array #if self.oneRadius == viewerConst.NO: #radii = self.vertexSet.radii.array pickName = 0 for i in xrange(len(self.faceSet.faces.array)): for j in xrange(len(self.faceSet.faces.array[i])-1): vi1 = self.faceSet.faces.array[i][j] vi2 = self.faceSet.faces.array[i][j+1] #print vi1,vi2 if fp: fpp1 = [None,None,None,None,None] fpp2 = [None,None,None,None,None] for m in (0,1,2,3,4): if fp.binding[m] == viewerConst.PER_VERTEX: fpp1[m] = fp.prop[m][vi2] # to make sure array is contiguous fpp1[m] = array(fpp1[m],copy=1) fpp2[m] = fp.prop[m][vi1] fpp2[m] = array(fpp2[m],copy=1) elif fp.binding[m] == viewerConst.PER_PART: fpp2[m]= fpp1[m] = fp.prop[m][i] fpp1[m] = array(fpp1[m],copy=1) fpp2[m] = array(fpp2[m],copy=1) else: fpp1 = fpp2 = None if bp and not self.frontAndBack: bpp1 = [None,None,None,None,None] bpp2 = [None,None,None,None,None] for m in (0,1,2,3,4): if bp.binding[m] == viewerConst.PER_VERTEX: bpp1[m] = bp.prop[m][vi2] bpp1[m] = array(bpp1[m],copy=1) bpp2[m] = bp.prop[m][vi1] bpp2[m] = array(bpp2[m],copy=1) elif bp.binding[m] == viewerConst.PER_PART: bpp2[m] = bpp1[m] = bp.prop[m][i] bpp1[m] = array(bpp1[m],copy=1) else: bpp1 = bpp2 = None GL.glPushName(pickName) self.arrowdraw(c[vi1], c[vi2],fpp1, bpp1, fpp2, bpp2,face) GL.glPopName() pickName = pickName +1 return 1 def _arrowTemplate(self, npoly): assert (npoly >1) import numpy.oldnumeric as Numeric, math self.npoly = npoly self.v = Numeric.zeros( ((npoly+2),3), 'f') a = -math.pi # starting angle d = 2*math.pi / npoly # increment # coord of 1st point of arrow self.v[0][0] = 0. self.v[0][1] = 0. self.v[0][2] = 0. # coord of 2st point of arrow self.v[1][0] = 0. self.v[1][1] = 0. self.v[1][2] = 1. # coord of the others points for i in range(npoly): h = i+2 self.v[h][0] = math.cos(a)/10. self.v[h][1] = math.sin(a)/10. self.v[h][2] = 0.75 a=a+d def arrowdraw(self, x, y, colxf=None, colxb=None, colyf=None, colyb=None,face=None): # draw a cylinder going from x to y # col for materials # face can be GL_FRONT_AND_BACK or something else # determine scale and rotation of template import math sz=0.0 for i in (0,1,2): sz=sz+(x[i]-y[i])*(x[i]-y[i]) if sz <= 0.0: return sz = math.sqrt(sz) rx = -180.0*math.acos((y[2]-x[2])/sz)/math.pi dx = y[0]-x[0] dy = y[1]-x[1] if math.fabs(dx) < 0.00001 and math.fabs(dy) < 0.00001: rz = 0.0 else: rz = -180.0*math.atan2(dx,dy)/math.pi GL.glPushMatrix() GL.glTranslatef(float(x[0]),float(x[1]),float(x[2])) if rz<=180.0 and rz >=-180.0: GL.glRotatef(float(rz), 0., 0., 1.) GL.glRotatef(float(rx), 1., 0., 0.) # draw arrow GL.glBegin(GL.GL_LINES) if colxf: for m in (0,1,2,3,4): if colxf[m] is not None: glMaterialWithCheck( face, viewerConst.propConst[m], colxf[m] ) if colxb and face!=GL.GL_FRONT_AND_BACK: for m in (0,1,2,3,4): if colxb[m] is not None: glMaterialWithCheck( GL.GL_BACK, viewerConst.propConst[m], colxb[m] ) GL.glVertex3f(float(self.v[0][0]), float(self.v[0][1]), float(self.v[0][2]*sz)) GL.glVertex3f(float(self.v[1][0]), float(self.v[1][1]), float(self.v[1][2]*sz)) for i in range(self.npoly): h = i+2 vx = self.v[h] GL.glVertex3f(float(self.v[1][0]), float(self.v[1][1]), float(self.v[1][2]*sz)) GL.glVertex3f(float(vx[0]*sz), float(vx[1]*sz), float(vx[2]*sz)) GL.glEnd() GL.glPopMatrix() ############################################################################# # # Author: Yong Zhao # # Copyright: Y.Zhao, 2004 # ############################################################################# from DejaVu.Cylinders import Cylinders #from opengltk.OpenGL import GL from math import sqrt #import numpy.oldnumeric as Numeric from warnings import warn from mglutil.util.defaultPalettes import ChooseColor import types import numpy class Axis(Cylinders): """This class displays an axis in a viewer""" keywords = Cylinders.keywords + ['point1', 'point2', 'radius', 'color', 'point', 'unitVector', 'length' ] def __init__(self, name=None, check=1, **kw): """constructor: two ways of building the axis: 1) by specifing point and unit vector, axis goes through 'point', with center at the point, unit vector gives the direction of axis 2) by two points, axis goes through the center (average) of the two points, axis pointing to the direction of ( point1--> point2) if both definitions are specified 2) will overwrite 1) """ apply(Cylinders.__init__, (self, name), {}) self.length = None self.point1 = None self.point2 = None #print 'kw: ', kw if kw.get('faces') == None: kw['faces'] = [ [0,1], [1,2], [2,3], [3,4] ] if kw.get('quality') == None: kw['quality']=20 if kw.get('inheritMaterial') == None: kw['inheritMaterial'] = 0 if kw.get('culling') == None: kw['culling'] = GL.GL_NONE apply(self.Set, (check,), kw) def Set(self, check=1, redo=1, **kw): cylkw = {} updateverts = False point = kw.get('point', None) if point != None: kw.pop('point') unitVector = kw.get('unitVector', None) if unitVector != None: assert len(unitVector) == 3 kw.pop('unitVector') if point is not None and unitVector is not None: p=numpy.array(point, 'f') v=numpy.array(unitVector, 'f') self.point1=p - 0.5 * v self.point2=p + 0.5 * v updateverts = True point1 = kw.get('point1') if point1 is not None: assert len(point1) == 3 self.point1 = numpy.array(point1, 'f') updateverts = True kw.pop('point1') point2 = kw.get('point2') if point2 is not None: assert len(point2) == 3 self.point2 = numpy.array(point2, 'f') updateverts=True kw.pop('point2') length = kw.get('length', None) if length is not None and length != self.length: updateverts=True kw.pop('length') self.length = length if updateverts: cylkw['vertices'] = self.calculateVertices(self.length) radius = kw.get('radius', None) if radius is not None: kw.pop('radius') cylkw ['radii'] = [0.0, radius, radius, 2*radius, 0.0] color = kw.get('color') if color is not None: self.color = color cylkw['materials'] = [self.getColor(color),] kw.pop('color') cylkw.update(kw) return apply(Cylinders.Set , (self, check, redo), cylkw) def getColor(self, color): """returns the color of axis, color can be string (e.g. 'red' ) or tuple (e.g. (1., 0., 0.) ) The default color is white (1,1,1) """ if type(color) == types.TupleType and len(color)==3: return color if type(color) == types.StringType: if color in ChooseColor.keys(): return ChooseColor[color] return ChooseColor['white'] def calculateVertices(self, length, center=None): """ tail -> head """ p1=self.point1 p2=self.point2 #if not center: center = (p1+p2) /2.0 vector = p2-p1 distance = sqrt( (p2[0]-p1[0])**2 +(p2[1]-p1[1])**2 +(p2[2]-p1[2])**2 ) if distance < 0.000001: warn("The two points specified are too close.") return half = vector * (length / distance/2.0) head= center + half tail= center - half # the arrow's length is 10% of shaft summit = center + vector * \ (length / distance /2.0 * 1.2) ## ## |\ ## |-----------------| \ ## |-----------------| / <- summit ## |/ ## d_tail, d_head ## tail head summit d_half = vector * ((length+0.0001) / distance/2.0) d_tail= center - d_half d_head= center + d_half head=head.tolist() tail=tail.tolist() d_head=d_head.tolist() d_tail=d_tail.tolist() summit = summit.tolist() return [d_tail, tail, d_head, head, summit] #from DejaVu.Arrows import Axis #xx = Axis('axis', point=[0,0,0 ], unitVector=[1,0,0], length=20., radius=0.3, color = 'green') #self.GUI.VIEWER.AddObject(xx) class AxisOld: """This class displays an axis in a viewer""" def __init__(self, point1=None, point2=None, point=None, unitVector=None, length = 1.0, viewer=None, radius = 1.0, color='white', name=None): """constructor: two ways of building the axis: 1) by specifing point and unit vector, axis goes through 'point', with center at the point, unit vector gives the direction of axis 2) by two points, axis goes throw the center (average) of the two points, axis pointing to the direction of ( point1--> point2) if both definitions are specified 2) will overwrite 1) """ if point is not None and unitVector is not None: p=Numeric.array(point, 'f') v=Numeric.array(unitVector, 'f') self.point1=p - 0.5 * v self.point2=p + 0.5 * v if point1 is not None and point2 is not None: self.point1=Numeric.array(point1,'f') self.point2=Numeric.array(point2,'f') self.length=length self.radius=radius self.viewer = viewer self.color=self.getColor(color) if name is None: name='Axis' self.shaft = Cylinders(name=name, quality=20, materials = [self.color], inheritMaterial=0, culling=GL.GL_NONE) if self.viewer: self.viewer.AddObject(self.shaft) self.display() def getColor(self, color): """returns the color of axis, color can be string (e.g. 'red' ) or tuple (e.g. (1., 0., 0.) ) The default color is white (1,1,1) """ if type(color) == types.TupleType and len(color)==3: return color if type(color) == types.StringType: if color in ChooseColor.keys(): return ChooseColor[color] return ChooseColor['white'] def display(self): """Display the """ ## |\ ## |-----------------| \ ## |-----------------| / <- summit ## |/ ## v1,v2 v3,v4 # v = [v1, v2, v3, v4, summit] v = self.calculateVertices() # faces = [ [v1,v2],[v2,v3], [v3,v4], [v4,v5],[v5,summit] ] faces = [ [0,1], [1,2], [2,3], [3,4] ] # radii r=self.radius radii=( 0.0, r, r, 2*r, 0.0) self.shaft.Set( vertices=v, faces=faces, radii=radii, materials = [self.color], ) ## self.shaft = Cylinders("shaft", vertices=v, ## faces=faces, ## radii=radii, ## quality=20, materials = [(1,0,0)], ## inheritMaterial=0, ## cull =GL.GL_NONE) ## self.shaft = Cylinders("shaft", vertices=v[:3], ## faces=faces[:2], ## radii=radii[:2], ## quality=20, materials = [(1,0,0)], ## inheritMaterial=0, ## cull =GL.GL_NONE) ## self.arrow = Cylinders("arrow", vertices=v[2:], ## #faces=faces[2:], ## faces = [ [0,1], [1,2] ], ## radii=radii[2:], ## quality=20, materials = [(1,0,0)], ## inheritMaterial=0, ## cull =GL.GL_NONE) if self.viewer: self.shaft.Set(culling=GL.GL_NONE, backPolyMode=GL.GL_FILL, vertices=v, faces=faces, radii=radii, materials = [self.color], ) ## self.viewer.AddObject(self.shaft) self.viewer.Redraw() def calculateVertices(self, center=None): """ tail -> head """ p1=self.point1 p2=self.point2 length = self.length #if not center: center = (p1+p2) /2.0 vector = p2-p1 distance = sqrt( (p2[0]-p1[0])**2 +(p2[1]-p1[1])**2 +(p2[2]-p1[2])**2 ) if distance < 0.000001: warn("The two points specified are too close.") return half = vector * (length / distance/2.0) head= center + half tail= center - half # the arrow's length is 10% of shaft summit = center + vector * \ (length / distance /2.0 * 1.2) ## ## |\ ## |-----------------| \ ## |-----------------| / <- summit ## |/ ## d_tail, d_head ## tail head summit d_half = vector * ((length+0.0001) / distance/2.0) d_tail= center - d_half d_head= center + d_half head=head.tolist() tail=tail.tolist() d_head=d_head.tolist() d_tail=d_tail.tolist() summit = summit.tolist() return [d_tail, tail, d_head, head, summit] def configure(self, length=None, radius=None, point1=None, point2=None, viewer=None , color =None): """ change the configuration of axis""" update=False if length is not None and length != self.length: self.length=length update=True if point1 is not None and point1 != self.point1: self.point1 = point1 update=True if point2 is not None and point2 != self.point2: self.point2 = point2 update=True if radius is not None and radius != self.radius: self.radius = radius update=True if viewer is not None and viewer != self.viewer: self.viewer = viewer update=True if color is not None and color != self.color: self.color = color update=True if update: self.display() ## Fixme: ## after changing point1, point2, some parts of the axis is not upated. def getShaft(self): return self.shaft # fixme unit tests to be added # example of usage """ from DejaVu.Arrows import AxisOld as Axis xx= Axis(point=[0,0,0 ], unitVector=[1,0,0], length=60., viewer=self.GUI.VIEWER, radius=0.3, color='red', name='X axis') yy= Axis(point=[0,0,0 ], unitVector=[0,1,0], length=60., viewer=self.GUI.VIEWER, radius=0.3, color='green', name='Y axis') zz= Axis(point=[0,0,0 ], unitVector=[0,0,1], length=60., viewer=self.GUI.VIEWER, radius=0.3, color='blue', name='Z axis') """ mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/DataInput.py0000644000175000017500000002770311754554601022151 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################### # # Date: DEC 2003 Author: Daniel Stoffler # # stoffler@scripps.edu # # Copyright: Daniel Stoffler and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/DataInput.py,v 1.17 2012/05/15 22:32:33 sanner Exp $ # # $Id: DataInput.py,v 1.17 2012/05/15 22:32:33 sanner Exp $ # import string import os from struct import unpack import numpy.oldnumeric as Numeric try: from geomutils.geomalgorithms import detectObjFileContent, readObjFileGroup except: pass from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.Materials import Materials def pythonStringFromCString(aCString): lPythonString = '' for c in aCString: if c == '\x00' or c == '': break lPythonString += c assert c == '\x00' or c =='', c return lPythonString def readOBJ(filename): if (filename is None) or (filename == ''): return None lGroupNames = Numeric.zeros(128*256, typecode = "c") lGroupNames.shape = (128,256) lLibNames = Numeric.zeros(128*256, typecode = "c") lLibNames.shape = (128,256) lMaterialNames = Numeric.zeros(128*256, typecode = "c") lMaterialNames.shape = (128,256) out = detectObjFileContent(filename, lGroupNames, lLibNames, lMaterialNames) lGeoms = [] if out[0] is True: lMaterialNames = lMaterialNames[:out[3]] lNumOfLibs = out[2] materialDict = {'default': Materials()} for i in range(len(lMaterialNames)): materialName = pythonStringFromCString(lMaterialNames[i]) materialDict[materialName] = Materials() libNames = [] for i in range(lNumOfLibs): libNames.append(pythonStringFromCString(lLibNames[i])) materialDict.update(readMTL(libNames[-1])) materialList = [] for i in range(len(lMaterialNames)): materialName = pythonStringFromCString(lMaterialNames[i]) materialList.append(materialDict[materialName]) lNumOfGeoms = out[1] for i in range(lNumOfGeoms): lGroupName = pythonStringFromCString(lGroupNames[i]) out = readObjFileGroup(filename, lGroupName, None, None, None, None, None, None ) if out[0] is True and out[2] > 0 and out[3] > 0: vertices = Numeric.zeros(out[2]*3, typecode = "f") vertices.shape = (out[2],3) faces = Numeric.zeros(out[3]*3, typecode = "i") faces.shape=(out[3],3) textureVertices = Numeric.zeros(out[4]*2, typecode = "f") textureVertices.shape = (out[4],2) textureFaces = Numeric.zeros(out[5]*3, typecode = "i") textureFaces.shape=(out[5],3) if ( len(libNames) > 0 ) and ( len(lMaterialNames) > 1 ): triangleMaterialIndices = Numeric.zeros(len(faces)*1, typecode = "i") else: triangleMaterialIndices = None out = readObjFileGroup(filename, lGroupName, lMaterialNames, vertices, faces, textureVertices, textureFaces, triangleMaterialIndices ) if out[0] is True: if len(textureVertices)>0: geom = IndexedPolygons(vertices=vertices, faces=faces, textureCoords=textureVertices) else: geom = IndexedPolygons(vertices=vertices, faces=faces) if triangleMaterialIndices is not None: breaked = False for triangleMaterialIndex in triangleMaterialIndices: if triangleMaterialIndex != triangleMaterialIndices[0]: breaked = True break if breaked is False: if triangleMaterialIndex == 0: # use inherited pass else: geom.Set(materials=[materialList[triangleMaterialIndex].prop[1],], propName='diffuse', inheritMaterial=False) else: triangleMaterials = [] for triangleMaterialIndex in triangleMaterialIndices: triangleMaterials.append(materialList[triangleMaterialIndex].prop[1]) geom.Set(materials=triangleMaterials, propName='diffuse', inheritMaterial=False) if (lGroupName == 'default'): nameSplit = os.path.splitext(filename) geom.name = os.path.split(nameSplit[0])[-1] else: geom.name = lGroupName #print "geom.name", geom.name lGeoms.append(geom) return lGeoms else: return None def readMTL(filename): if (filename is None) or (filename == ''): return None file = open(filename, "r") materials = {} material = None for line in file: if line.startswith('#'): continue tokens = line.split() if not tokens: continue if tokens[0] == 'newmtl': material = Materials() materials[tokens[1]] = material elif material is None: warnings.warn("missing newmtl statement in mtl file") elif tokens[0] == 'Ka': material.Set(ambient=(eval(tokens[1]),eval(tokens[2]),eval(tokens[3]),1.)) elif tokens[0] == 'Kd': material.Set(diffuse=(eval(tokens[1]),eval(tokens[2]),eval(tokens[3]),1.)) elif tokens[0] == 'Ks': material.Set(specular=(eval(tokens[1]),eval(tokens[2]),eval(tokens[3]),1.)) elif tokens[0] == 'Ns': material.Set(shininess=eval(tokens[1])) elif tokens[0] == 'd' or tokens[0] == 'Tr': material.Set(opacity=eval(tokens[1])) elif tokens[0] == 'map_Kd': # load the texture map pass return materials def readAnySTL(filename): if (filename is None) or (filename == ''): return nameSplit = os.path.splitext(filename) name = os.path.split(nameSplit[0])[-1] P = ReadASCIISTL() l = P.read(filename) geoms = P.doit(l) if len(geoms) > 0: geoms[0].name = name for i in range(1, len(geoms)): geoms[i].name = name + '+' + str(i) return geoms P = ReadBinarySTL() geom = P.doit(filename) if geom is not None: geom.name = name geoms = [geom] return geoms else: return None class ReadASCIISTL: """This class parses a ASCII STL file and converts it into a DejaVu IndexedPolygon geometry. Usage: R = ReadASCIISTL() # instanciate object lines = R.read(filename) # read ASCII STL file geoms = R.doit(lines) # parse file, build geoms """ def __init__(self): self.geoms = [] # list storing all Indexed Geoms that will be built # in the doit() method def read(self, filename): """For your convenience, a read lines method""" f = open(filename, "r") lines = f.readlines() f.close() return lines def doit(self, lines): """Parse ASCII STL files, build DejaVu IndexedPolygons and return them """ self.geoms = [] faces = [] vertices = [] normals = [] name = 'IndexedGeom' faceIndex = 0 # counter # parse ASCII STL for line in lines: spl = string.split(string.lower(line)) if len(spl)==0: continue if spl[0] == 'solid': name = spl[1] continue elif spl[0] == 'facet' and spl[1] == 'normal': normals.append( [float(spl[2]), float(spl[3]), float(spl[4])] ) continue elif spl[0] == 'vertex': vertices.append( [float(spl[1]), float(spl[2]), float(spl[3])]) continue elif spl[0] == 'endfacet': faces.append( [faceIndex, faceIndex+1, faceIndex+2] ) faceIndex = faceIndex + 3 continue elif spl[0] == 'endsolid': geom = IndexedPolygons(name, vertices=vertices, faces=faces, fnormals = normals) self.geoms.append(geom) faces = [] vertices = [] normals = [] name = 'IndexedGeom' faceIndex = 0 # counter continue else: continue return self.geoms class ReadBinarySTL: # (c) Daniel Stoffler, Biozentrum, University of Basel, Switzerland, # August 2005 """This class parses a Binary STL file and converts it into a DejaVu IndexedPolygon geometry. Usage: R = ReadBinarySTL() # instanciate object geoms = R.doit(filename) # parse file, build geoms """ def doit(self, filename): """Parse ASCII STL files, build DejaVu IndexedPolygons and return them """ # open file to read in binary mode f = open(filename, 'rb') # read the 84 bytes of the header header = f.read(84) # get the comment comment = unpack("80c", header[0:80]) # get the total number of facets lenFaces = unpack("1i", header[80:84])[0] data = f.read() # read to end f.close() # organize the data normals = [] vertices = [] faces = [] j = 0 # counter for reading binary data f = 0 # counter for generating faces for i in range(lenFaces): normal = unpack("3f", data[j:j+12]) normals.append(normal) faces.append((f, f+1, f+2)) verts = unpack("9f", data[j+12:j+48]) vertices.append(verts[0:3]) vertices.append(verts[3:6]) vertices.append(verts[6:9]) #spacer = unpack("2c", data[j+48:j+50]) # increment binary counter j = j + 50 # increment faces counter f = f + 3 name = "IndexedGeom" geom = IndexedPolygons(name, vertices=vertices, faces=faces, fnormals = normals) return geom def info(self): txt = """Binary STL files consist of a 80 byte header line that can be interpreted as a comment string. The following 4 bytes interpreted as a long integer give the total number of facets. What follows is a normal and 3 vertices for each facet, each coordinate represented as a 4 byte floating point number (12 bytes in all). There is a 2 byte spacer between each facet. The result is that each facet is represented by 50 bytes, 12 for the normal, 36 for the 3 vertices, and 2 for the spacer. """ return txt if __name__ == '__main__': # P = ReadASCIISTL() # l = P.read('test.stl') # geoms = P.doit(l) # from DejaVu import Viewer # vi = Viewer() # vi.AddObject(geoms[0]) #geoms = readOBJ('sample.obj') geoms = readAnySTL('test.stl') print "len(geoms)", len(geoms) from DejaVu import Viewer vi = Viewer() for g in geoms: vi.AddObject(g) #import pdb;pdb.set_trace() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Points.py0000644000175000017500000001661511111132470021513 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Points.py,v 1.29 2008/11/20 00:54:16 vareille Exp $ # # $Id: Points.py,v 1.29 2008/11/20 00:54:16 vareille Exp $ # from opengltk.OpenGL import GL from opengltk.extent.utillib import glDrawIndexedGeom from Geom import Geom import datamodel, viewerConst import numpy.oldnumeric as Numeric from viewerFns import checkKeywords class Points(Geom): """Class for sets of spheres""" keywords = Geom.keywords + [ 'centers', ] def __init__(self, name=None, check=1, **kw): v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init elif not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set if not kw.get('frontPolyMode'): kw['frontPolyMode'] = GL.GL_POINT if not kw.get('inheritFrontPolyMode'): kw['inheritFrontPolyMode'] = viewerConst.NO if not kw.get('lighting'): kw['lighting'] = viewerConst.NO if not kw.get('inheritLighting'): kw['inheritLighting'] = viewerConst.NO apply( Geom.__init__, (self, name, check), kw) assert len(self.vertexSet.vertices.ashape)==2 self._modified = False def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ # Exceptionnaly this has to be before the call to Geom.Set v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init redoFlags = apply( Geom.Set, (self, check, 0), kw) return self.redoNow(redo, updateOwnGui, redoFlags) def Add(self, check=1, redo=1, **kw): """Add spheres""" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init self.redoDspLst = 1 apply(Geom.Add, (self, 0, 0), kw) if self.viewer and redo: if self.redoDspLst: self.viewer.objectsNeedingRedo[self] = None # self.RedoDisplayList() def Draw(self): centers = self.vertexSet.vertices.array if len(centers)==0: return faces = map (lambda x: [x], range(len(centers))) if self.materials[GL.GL_FRONT] and \ not self.inheritMaterial: fpProp = self.materials[GL.GL_FRONT].prop[:5] fpBind = self.materials[GL.GL_FRONT].binding[:5] else: fpProp = None fpBind = None if self.materials[GL.GL_BACK] and \ not self.inheritMaterial: bpProp = self.materials[GL.GL_BACK].prop[:5] bpBind = self.materials[GL.GL_BACK].binding[:5] else: bpProp = None bpBind = None texCoords = None if self.normals is None: GL.glDisable(GL.GL_LIGHTING) status = glDrawIndexedGeom( GL.GL_POINTS, self.vertexSet.vertices.array, faces, self.normals, texCoords, fpProp, bpProp, fpBind, bpBind, self.frontAndBack, 1) return status # FIXME picking is probably not working onthis geometry class CrossSet(Points): keywords = Points.keywords + [ 'offset', ] def __init__(self, name=None, check=1, **kw): v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init # has to be fone before Points.__init__ offset = kw.get( 'offset') if offset != None: self.offset = offset else: self.offset = 0.3 # if not kw.get('transparent'): # kw['transparent'] = viewerConst.YES apply( Points.__init__, (self, name, check), kw) self._modified = False def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ # Exceptionnaly this has to be before the call to Geom.Set v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init redoFlags = apply( Points.Set, (self, check, 0), kw) offset = kw.get( 'offset') if offset is not None: self.offset = offset redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def getCoords(self, c): c = Numeric.array(c) x1 = c - (self.offset, 0, 0) x2 = c + (self.offset, 0, 0) y1 = c - (0, self.offset, 0) y2 = c + (0, self.offset, 0) z1 = c - (0, 0, self.offset) z2 = c + (0, 0, self.offset) return Numeric.concatenate( (x1,x2,y1,y2,z1,z2) ) def getFaces(self, length=None): if length is None: length = len(self.vertexSet.vertices.array) off = [] for i in range(1,6): off.append(i*length) faces = [] for i in xrange(length): faces.append( (i, i+off[0]) ) faces.append( (i+off[1], i+off[2]) ) faces.append( (i+off[3], i+off[4]) ) return faces def Draw(self): centers = self.getCoords(self.vertexSet.vertices.array) if len(centers)==0: return #faces = Numeric.zeros((0,3), 'i') else: faces = self.getFaces(len(self.vertexSet.vertices.array)) if self.materials[GL.GL_FRONT] and \ not self.inheritMaterial: fpProp = self.materials[GL.GL_FRONT].prop[:5] fpBind = self.materials[GL.GL_FRONT].binding[:5] else: fpProp = None fpBind = None if self.materials[GL.GL_BACK] and \ not self.inheritMaterial: bpProp = self.materials[GL.GL_BACK].prop[:5] bpBind = self.materials[GL.GL_BACK].binding[:5] else: bpProp = None bpBind = None texCoords = None if self.lighting: if (self.invertNormals) and (self.normals is not None): norms = - self.normals else: norms = self.normals else: norms = None #GL.glDisable(GL.GL_DEPTH_TEST) if self.disableStencil is True: GL.glDisable(GL.GL_STENCIL_TEST) status = glDrawIndexedGeom( GL.GL_LINES, centers.astype('f'), faces, norms, texCoords, fpProp, bpProp, fpBind, bpBind, self.frontAndBack, 1) if self.disableStencil is True: GL.glEnable(GL.GL_STENCIL_TEST) #GL.glEnable(GL.GL_DEPTH_TEST) return status mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Legend.py0000644000175000017500000007204010651210742021436 0ustar debiandebian######################################################################## # # Date: Febuary 2006 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # # Revision: # ######################################################################### # # $Header$ # # $Id$ # from copy import deepcopy from opengltk.OpenGL import GL from mglutil.util.colorUtil import ToHSV from pyglf import glf def drawSelfOrientedLegend( fullWidth, fullHeight, ramp, mini, maxi, name = '', unit = '', labelValues = [], roomLeftToLegend = 0, roomBelowLegend = 50, legendShortSide = 10, legendLongSide = 150, significantDigits = 3, backgroundColor = (0,0,0,.8), interpolate = True, frame=True, selected=False, numOfLabels=None, resizeSpotRadius=5, fontScale=8, glfFontID=0, tile=None, ): lRoomLeftToViewportCenter = fullWidth / 2 lRoombelowViewportCenter = fullHeight / 2 twiceFontHeight = 2*fontScale if roomLeftToLegend < lRoomLeftToViewportCenter: if roomBelowLegend < lRoombelowViewportCenter: # 1 and 8 if roomBelowLegend > roomLeftToLegend: #1 #print "1" lVerticalLegend=True lLeftOrBelowLabels=False if roomLeftToLegend < 0: roomLeftToLegend = 0 if roomBelowLegend < 0: roomBelowLegend = 0 else: # 8 #print "8" lVerticalLegend=False lLeftOrBelowLabels=False if roomLeftToLegend < 0: roomLeftToLegend = 0 if roomBelowLegend < 0: roomBelowLegend = 0 else: # 2 and 3 if fullHeight-roomBelowLegend > roomLeftToLegend + (fullHeight/8): #2 #print "2" lVerticalLegend=True lLeftOrBelowLabels=False if roomLeftToLegend < 0: roomLeftToLegend = 0 if roomBelowLegend > fullHeight: roomBelowLegend = fullHeight else: #3 #print "3" lVerticalLegend=False lLeftOrBelowLabels=True if roomLeftToLegend < 0: roomLeftToLegend = 0 if roomBelowLegend > fullHeight: roomBelowLegend = fullHeight else: if roomBelowLegend < lRoombelowViewportCenter: # 6 and 7 if roomBelowLegend + (fullWidth/8) < fullWidth-roomLeftToLegend: #7 #print "7" lVerticalLegend=False lLeftOrBelowLabels=False if roomLeftToLegend > fullWidth : roomLeftToLegend = fullWidth if roomBelowLegend < 0: roomBelowLegend = 0 else: # 6 #print "6" lVerticalLegend=True lLeftOrBelowLabels=True if roomLeftToLegend > fullWidth : roomLeftToLegend = fullWidth if roomBelowLegend < twiceFontHeight: roomBelowLegend = twiceFontHeight else: # 4 and 5 if fullHeight-roomBelowLegend < fullWidth-roomLeftToLegend: #2 #print "4" lVerticalLegend=False lLeftOrBelowLabels=True if roomLeftToLegend > fullWidth : roomLeftToLegend = fullWidth if roomBelowLegend > fullHeight: roomBelowLegend = fullHeight else: #5 #print "5" lVerticalLegend=True lLeftOrBelowLabels=True if roomLeftToLegend > fullWidth : roomLeftToLegend = fullWidth if roomBelowLegend > fullHeight: roomBelowLegend = fullHeight if lVerticalLegend is True: if legendLongSide > fullHeight: legendLongSide = fullHeight if legendShortSide > fullWidth: legendShortSide = fullWidth else: if legendLongSide > fullWidth: legendLongSide = fullWidth if legendShortSide > fullHeight: legendShortSide = fullHeight bgHSV = ToHSV(backgroundColor[:3]) if bgHSV[2] < .5: labelColor = (1, 1, 1) else: labelColor = (0, 0, 0) return drawLegendLabelName( fullWidth=fullWidth, fullHeight=fullHeight, ramp=ramp, mini=mini, maxi=maxi, name=name, unit=unit, labelValues=labelValues, verticalLegend=lVerticalLegend, leftOrBelowLabels=lLeftOrBelowLabels, roomLeftToLegend=roomLeftToLegend, roomBelowLegend=roomBelowLegend, legendShortSide=legendShortSide, legendLongSide=legendLongSide, significantDigits=significantDigits, backgroundColor=backgroundColor, labelColor=labelColor, interpolate=interpolate, frame=frame, selected=selected, numOfLabels=numOfLabels, resizeSpotRadius=resizeSpotRadius, fontScale=fontScale, glfFontID=glfFontID, tile=tile, ) def drawLegendLabelName( fullWidth, fullHeight, ramp, mini, maxi, name='', unit='', labelValues=[], verticalLegend=True, leftOrBelowLabels=False, roomLeftToLegend=0, roomBelowLegend=50, legendShortSide=10, legendLongSide=150, significantDigits=3, backgroundColor=(0,0,0,.8), labelColor=(1,1,1), interpolate=True, frame=True, selected=False, numOfLabels=None, resizeSpotRadius=5, fontScale=8, glfFontID=0, tile=None, ): if ramp is None or len(ramp) == 0: return if tile is not None and selected is True: selected = False # some glf font initialisation glf.glfSetCurrentFont(glfFontID) glf.glfStringCentering(GL.GL_FALSE) glf.glfStringDirection(glf.GLF_LEFT) # calculate name and unit size lNameMinAndMax = glf.glfGetStringBounds(name) lNameMinAndMax = ( lNameMinAndMax[0]*fontScale, lNameMinAndMax[1]*fontScale, lNameMinAndMax[2]*fontScale, lNameMinAndMax[3]*fontScale ) lNameWidth = lNameMinAndMax[2]-lNameMinAndMax[0] lNameHeight = lNameMinAndMax[3]-lNameMinAndMax[1] if lNameWidth == 0: lNameWidth = fontScale if unit is not None and (len(unit) > 0): lUnitMinAndMax = glf.glfGetStringBounds(unit) lUnitMinAndMax = ( lUnitMinAndMax[0]*fontScale, lUnitMinAndMax[1]*fontScale, lUnitMinAndMax[2]*fontScale, lUnitMinAndMax[3]*fontScale ) lUnitWidth = lUnitMinAndMax[2]-lUnitMinAndMax[0] lUnitHeight = lUnitMinAndMax[3]-lUnitMinAndMax[1] else: lUnitWidth = fontScale lUnitHeight = 0 lMaxNameUnitHeight = max(lNameHeight, lUnitHeight) lMaxNameUnitWidth = max(lNameWidth, lUnitWidth) # deducted values fontScaleHalf = fontScale/2 if verticalLegend is True: lRoomToLegendCloseLongSide = roomLeftToLegend lRoomToLegendCloseShortSide = roomBelowLegend if legendShortSide < 1: legendShortSide = 1 if legendLongSide < 1: legendLongSide = 1 else: lRoomToLegendCloseLongSide = roomBelowLegend lRoomToLegendCloseShortSide = roomLeftToLegend if legendShortSide < lMaxNameUnitHeight + fontScaleHalf: legendShortSide = lMaxNameUnitHeight + fontScaleHalf if legendLongSide < 1: legendLongSide = 1 lRoomToLegendFarLongSide = lRoomToLegendCloseLongSide + legendShortSide lRoomToLegendFarShortSide = lRoomToLegendCloseShortSide + legendLongSide # prepare the legend labels if len(labelValues) > 0: lOnScreenLabelValues = labelValues else: if numOfLabels == None or numOfLabels < 0: if verticalLegend is True: numOfLabels = 6 else: numOfLabels = 4 if ( numOfLabels == 0 ) or maxi is None or mini is None: lOnScreenLabelValues = [] elif numOfLabels == 1: lOnScreenLabelValues = [(mini+maxi)*0.5] else: delta = (maxi - mini) / float(numOfLabels-1) lOnScreenLabelValues = [] for i in range(numOfLabels): lOnScreenLabelValues.append(mini+i*delta) lMaxLabelDigits = 0 for v in lOnScreenLabelValues: lLabel = "%.*g" % (significantDigits,v) if lMaxLabelDigits < len(lLabel): lMaxLabelDigits = len(lLabel) # calculate labels size lLabelsMinAndMax = [] lLabelsWidth = [] lLabelsHeight = [] lMaxLabelsWidth = 0 lMaxLabelsHeight = 0 for v in lOnScreenLabelValues: lLabel = "%.*g" % (significantDigits,v) lLabelsMinAndMax.append( glf.glfGetStringBounds(lLabel) ) lLabelsMinAndMax[-1] = ( lLabelsMinAndMax[-1][0]*fontScale, lLabelsMinAndMax[-1][1]*fontScale, lLabelsMinAndMax[-1][2]*fontScale, lLabelsMinAndMax[-1][3]*fontScale ) lLabelsWidth.append( lLabelsMinAndMax[-1][2]-lLabelsMinAndMax[-1][0] ) lLabelsHeight.append( lLabelsMinAndMax[-1][3]-lLabelsMinAndMax[-1][1] ) if lLabelsWidth[-1] > lMaxLabelsWidth: lMaxLabelsWidth = lLabelsWidth[-1] if lLabelsHeight[-1] > lMaxLabelsHeight: lMaxLabelsHeight = lLabelsHeight[-1] # calculate frame size lMaxWidth = max(lMaxLabelsWidth + legendShortSide, lMaxNameUnitWidth) lMaxNameUnitHeightHalf = lMaxNameUnitHeight/2 legendShortSideHalf = legendShortSide/2 if verticalLegend is True: if leftOrBelowLabels is False: lPt1 = (lRoomToLegendCloseLongSide, -fontScale+lRoomToLegendCloseShortSide-lMaxLabelsHeight-lNameHeight,0) lPt2 = (fontScale+lRoomToLegendCloseLongSide+lMaxWidth, -fontScale+lRoomToLegendCloseShortSide-lMaxLabelsHeight-lNameHeight,0) lPt3 = (fontScale+lRoomToLegendCloseLongSide+lMaxWidth, fontScale+lRoomToLegendFarShortSide+lMaxLabelsHeight+lUnitHeight,0) lPt4 = (lRoomToLegendCloseLongSide, fontScale+lRoomToLegendFarShortSide+lMaxLabelsHeight+lUnitHeight,0) else: lPt1 = (-fontScale+lRoomToLegendFarLongSide-lMaxWidth, -fontScale+lRoomToLegendCloseShortSide-lMaxLabelsHeight-lNameHeight,0) lPt2 = (lRoomToLegendCloseLongSide+legendShortSide, -fontScale+lRoomToLegendCloseShortSide-lMaxLabelsHeight-lNameHeight,0) lPt3 = (lRoomToLegendCloseLongSide+legendShortSide, fontScale+lRoomToLegendFarShortSide+lMaxLabelsHeight+lUnitHeight,0) lPt4 = (-fontScale+lRoomToLegendFarLongSide-lMaxWidth, fontScale+lRoomToLegendFarShortSide+lMaxLabelsHeight+lUnitHeight,0) else: if leftOrBelowLabels is False: lPt1 = (-fontScale+lRoomToLegendCloseShortSide-lNameWidth, lRoomToLegendCloseLongSide,0) lPt2 = (fontScale+lRoomToLegendFarShortSide+lUnitWidth, lRoomToLegendCloseLongSide,0) lPt3 = (fontScale+lRoomToLegendFarShortSide+lUnitWidth, fontScale+lRoomToLegendCloseLongSide \ + legendShortSide \ + lMaxLabelsHeight, 0) lPt4 = (-fontScale+lRoomToLegendCloseShortSide-lNameWidth, fontScale+lRoomToLegendCloseLongSide \ + legendShortSide \ + lMaxLabelsHeight, 0) else: lPt1 = (-fontScale+lRoomToLegendCloseShortSide-lNameWidth, -fontScale+lRoomToLegendCloseLongSide-lMaxLabelsHeight, 0) lPt2 = (fontScale+lRoomToLegendFarShortSide+lUnitWidth, -fontScale+lRoomToLegendCloseLongSide-lMaxLabelsHeight, 0) lPt3 = (fontScale+lRoomToLegendFarShortSide+lUnitWidth, lRoomToLegendFarLongSide,0) lPt4 = (-fontScale+lRoomToLegendCloseShortSide-lNameWidth, lRoomToLegendFarLongSide,0) if selected is True: labelColor2 = (.5, .5, .5) else: labelColor2 = labelColor GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() GL.glLoadIdentity() if tile is None: GL.glOrtho(0, float(fullWidth), 0, float(fullHeight), -1, 1) else: GL.glOrtho(float(tile[0]), float(tile[1]), float(tile[2]), float(tile[3]), -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glDisable( GL.GL_LIGHTING ) GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL ) if len(backgroundColor) == 4: GL.glEnable(GL.GL_BLEND) GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) #because of an unexplained bug on michel's laptop, #we don't draw the background when there is no frame #(so michel has a way to manage the legend) if frame is True: #draw transparent background GL.glDepthMask(GL.GL_FALSE) if len(backgroundColor) == 3: GL.glColor3fv(backgroundColor) else: GL.glColor4fv(backgroundColor) GL.glBegin(GL.GL_QUADS) GL.glVertex3fv(lPt1) GL.glVertex3fv(lPt2) GL.glVertex3fv(lPt3) GL.glVertex3fv(lPt4) GL.glEnd() GL.glDepthMask(GL.GL_TRUE) #draw frame if frame is True: GL.glPolygonMode(GL.GL_FRONT, GL.GL_LINE ) GL.glLineWidth(1) GL.glColor3fv(labelColor2) GL.glBegin(GL.GL_QUADS) GL.glVertex3fv(lPt1) GL.glVertex3fv(lPt2) GL.glVertex3fv(lPt3) GL.glVertex3fv(lPt4) GL.glEnd() GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL) if mini is not None and maxi is not None and maxi > mini: lUnitStep = legendLongSide/float(maxi-mini) else: lUnitStep = legendLongSide GL.glDisable( GL.GL_LIGHTING ) if verticalLegend is True: if leftOrBelowLabels is True: lRoomLeftToLabel = -fontScaleHalf + lRoomToLegendCloseLongSide lRoomLeftToName = -fontScaleHalf + lRoomToLegendFarLongSide - lNameWidth lRoomLeftToUnit = -fontScaleHalf + lRoomToLegendFarLongSide - lUnitWidth lRoomBelowName = -fontScaleHalf + roomBelowLegend - lMaxLabelsHeight - lNameHeight lRoomBelowUnit = fontScaleHalf + roomBelowLegend + legendLongSide + lMaxLabelsHeight else: lRoomLeftToLabel = fontScaleHalf + lRoomToLegendFarLongSide lRoomLeftToName = fontScaleHalf + lRoomToLegendCloseLongSide lRoomLeftToUnit = lRoomLeftToName lRoomBelowName = -fontScaleHalf + roomBelowLegend - lMaxLabelsHeight - lNameHeight lRoomBelowUnit = fontScaleHalf + roomBelowLegend + legendLongSide + lMaxLabelsHeight else: if leftOrBelowLabels is True: lRoomBelowLabel = -fontScaleHalf + lRoomToLegendFarLongSide \ - legendShortSide - lMaxLabelsHeight lRoomBelowName = lRoomToLegendCloseLongSide + legendShortSideHalf \ - lMaxNameUnitHeightHalf else: lRoomBelowLabel = fontScaleHalf + lRoomToLegendCloseLongSide \ + legendShortSide lRoomBelowName = lRoomToLegendCloseLongSide + legendShortSideHalf \ - lMaxNameUnitHeightHalf lRoomBelowUnit = lRoomBelowName lRoomLeftToName = -fontScaleHalf + lRoomToLegendCloseShortSide - lNameWidth lRoomLeftToUnit = fontScaleHalf + lRoomToLegendFarShortSide # set the color of the text GL.glColor3fv(labelColor2) # print the legend name GL.glPushMatrix() GL.glTranslatef( float(lRoomLeftToName+fontScale), float(lRoomBelowName-lNameMinAndMax[1]), 0) GL.glScalef(float(fontScale), float(fontScale), 0); glf.glfDrawSolidString(name) GL.glPopMatrix() if unit is not None and (len(unit) > 0): GL.glPushMatrix() GL.glTranslatef( float(lRoomLeftToUnit+fontScale), float(lRoomBelowUnit-lUnitMinAndMax[1]), 0) GL.glScalef(float(fontScale), float(fontScale), 1); glf.glfDrawSolidString(unit) GL.glPopMatrix() if mini is not None and maxi is not None: i = 0 for v in lOnScreenLabelValues: #calculate label position lLabel = "%.*g" % (significantDigits,v) lStep = (v - mini) * lUnitStep GL.glPushMatrix() if verticalLegend: if leftOrBelowLabels: GL.glTranslatef( float(lRoomLeftToLabel+fontScale-lLabelsWidth[i]), float(roomBelowLegend-(lLabelsHeight[i]/2+lLabelsMinAndMax[i][1])+lStep), 0) else: GL.glTranslatef( float(lRoomLeftToLabel+fontScale), float(roomBelowLegend-(lLabelsHeight[i]/2+lLabelsMinAndMax[i][1])+lStep), 0) else: GL.glTranslatef( float(roomLeftToLegend-(lLabelsWidth[i]/2)+fontScale+lStep), float(lRoomBelowLabel-lLabelsMinAndMax[i][1]), 0) GL.glScalef(float(fontScale), float(fontScale), 1); glf.glfDrawSolidString("%s" % lLabel) GL.glPopMatrix() i += 1 if len(backgroundColor) == 4: GL.glDisable(GL.GL_BLEND) # GL.glEnable(GL.GL_LIGHTING) GL.glPopMatrix() GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) drawLegendOnly( fullWidth=fullWidth, fullHeight=fullHeight, ramp=ramp, verticalLegend=verticalLegend, roomLeftToLegend=roomLeftToLegend, roomBelowLegend=roomBelowLegend, legendShortSide=legendShortSide, legendLongSide=legendLongSide, interpolate=interpolate, selected=selected, tile=tile, ) if selected is True: GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() GL.glLoadIdentity() GL.glOrtho(0, float(fullWidth), 0, float(fullHeight), -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glDisable( GL.GL_LIGHTING ) GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL ) GL.glDisable(GL.GL_DEPTH_TEST) GL.glDepthMask(GL.GL_FALSE) GL.glDisable(GL.GL_LIGHTING) resizeSpot = [] if verticalLegend: resizeSpot= [ roomLeftToLegend + legendShortSide, roomBelowLegend + legendLongSide ] else: resizeSpot = [ roomLeftToLegend + legendLongSide, roomBelowLegend + legendShortSide ] GL.glColor3fv(labelColor) GL.glBegin(GL.GL_QUADS) GL.glVertex2f(float(resizeSpot[0]+resizeSpotRadius),float(resizeSpot[1]-resizeSpotRadius)) GL.glVertex2f(float(resizeSpot[0]+resizeSpotRadius),float(resizeSpot[1]+resizeSpotRadius)) GL.glVertex2f(float(resizeSpot[0]-resizeSpotRadius),float(resizeSpot[1]+resizeSpotRadius)) GL.glVertex2f(float(resizeSpot[0]-resizeSpotRadius),float(resizeSpot[1]-resizeSpotRadius)) GL.glEnd() GL.glEnable(GL.GL_DEPTH_TEST) GL.glDepthMask(GL.GL_TRUE) # GL.glEnable(GL.GL_LIGHTING) GL.glPopMatrix() GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) else: resizeSpot = None return [(lPt1[0], lPt1[1]), (lPt2[0], lPt2[1]), (lPt3[0], lPt3[1]), (lPt4[0], lPt4[1]) ] , resizeSpot , verticalLegend def drawLegendOnly( fullWidth, fullHeight, ramp, verticalLegend=True, roomLeftToLegend=0, roomBelowLegend=50, legendShortSide=10, legendLongSide=150, interpolate=True, selected=False, tile=None, ): if ramp is None or len(ramp) == 0: return if tile is not None and selected is True: selected = False # deducted values if verticalLegend is True: lRoomToLegendCloseLongSide = roomLeftToLegend lRoomToLegendCloseShortSide = roomBelowLegend if legendShortSide < 1: legendShortSide = 1 if legendLongSide < 1: legendLongSide = 1 else: lRoomToLegendCloseLongSide = roomBelowLegend lRoomToLegendCloseShortSide = roomLeftToLegend if legendShortSide < 1: legendShortSide = 1 if legendLongSide < 1: legendLongSide = 1 lRoomToLegendFarLongSide = lRoomToLegendCloseLongSide + legendShortSide GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() GL.glLoadIdentity() if tile is None: GL.glOrtho(0, float(fullWidth), 0, float(fullHeight), -1, 1) else: GL.glOrtho(float(tile[0]), float(tile[1]), float(tile[2]), float(tile[3]), -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glDisable( GL.GL_LIGHTING ) GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL) GL.glDisable(GL.GL_DEPTH_TEST) GL.glDepthMask(GL.GL_FALSE) if len(ramp[0]) == 4: # there are alpha values, draw checkered bg GL.glEnable(GL.GL_BLEND) GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) #draw a bunch of quads as background lCheckerSquareSize = legendShortSide * .5 if lCheckerSquareSize != 0: nbquads = int(legendLongSide / lCheckerSquareSize) else: nbquads = 1 c1 = ( 0.1, 0.1, 0.1 ) c2 = ( 0.3, 0.3, 0.3 ) c = c1 x2 = None for i in range(nbquads+1): GL.glColor3fv(c) if i==nbquads and nbquads != 0: x1=x2 x2=legendLongSide else: x1 = i*lCheckerSquareSize x2 = min (x1+lCheckerSquareSize, legendLongSide) GL.glBegin(GL.GL_QUADS) if verticalLegend is True: GL.glVertex2f(float(lRoomToLegendCloseLongSide), float(lRoomToLegendCloseShortSide + x1)) GL.glVertex2f(float(lRoomToLegendCloseLongSide+lCheckerSquareSize), float(lRoomToLegendCloseShortSide + x1)) GL.glVertex2f(float(lRoomToLegendCloseLongSide+lCheckerSquareSize), float(lRoomToLegendCloseShortSide + x2)) GL.glVertex2f(float(lRoomToLegendCloseLongSide), float(lRoomToLegendCloseShortSide + x2)) else: GL.glVertex2f(float(lRoomToLegendCloseShortSide + x2), float(lRoomToLegendCloseLongSide)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x2), float(lRoomToLegendCloseLongSide+lCheckerSquareSize)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x1), float(lRoomToLegendCloseLongSide+lCheckerSquareSize)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x1), float(lRoomToLegendCloseLongSide)) GL.glEnd() if c==c1: c=c2 else: c=c1 GL.glColor3fv(c) GL.glBegin(GL.GL_QUADS) if verticalLegend is True: GL.glVertex2f(float(lRoomToLegendCloseLongSide+lCheckerSquareSize), float(lRoomToLegendCloseShortSide + x1)) GL.glVertex2f(float(lRoomToLegendFarLongSide), float(lRoomToLegendCloseShortSide + x1)) GL.glVertex2f(float(lRoomToLegendFarLongSide), float(lRoomToLegendCloseShortSide + x2)) GL.glVertex2f(float(lRoomToLegendCloseLongSide+lCheckerSquareSize), float(lRoomToLegendCloseShortSide + x2)) else: GL.glVertex2f(float(lRoomToLegendCloseShortSide + x2), float(lRoomToLegendCloseLongSide+lCheckerSquareSize)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x2), float(lRoomToLegendFarLongSide)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x1), float(lRoomToLegendFarLongSide)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x1), float(lRoomToLegendCloseLongSide+lCheckerSquareSize)) GL.glEnd() #interp = False if interpolate and (len(ramp) > 1): # we interpolate colors # draw a quad strip for the color map lDelta = legendLongSide/float(len(ramp)-1) GL.glBegin(GL.GL_QUAD_STRIP) for i in range(len(ramp)): if selected is True: c = deepcopy(ramp[i]) for j in range(3): c[j] = .35 + c[j]*.3 else: c = ramp[i] if len(c)==3: GL.glColor3fv(c) elif len(c)==4: GL.glColor4fv(c) lStep = i*lDelta if verticalLegend is True: GL.glVertex2f(float(lRoomToLegendCloseLongSide), float(lRoomToLegendCloseShortSide + lStep)) GL.glVertex2f(float(lRoomToLegendFarLongSide), float(lRoomToLegendCloseShortSide + lStep)) else: GL.glVertex2f(float(lRoomToLegendCloseShortSide + lStep), float(lRoomToLegendFarLongSide)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + lStep), float(lRoomToLegendCloseLongSide)) GL.glEnd() else: # we draw a quad for each color lDelta = legendLongSide/float(len(ramp)) for i in range(len(ramp)): if selected is True: c = deepcopy(ramp[i]) for j in range(3): c[j] = .35 + c[j]*.3 else: c = ramp[i] if len(c)==3: GL.glColor3fv(c) elif len(c)==4: GL.glColor4fv(c) x1 = i*lDelta x2 = x1+lDelta GL.glBegin(GL.GL_QUADS) if verticalLegend is True: GL.glVertex2f(float(lRoomToLegendCloseLongSide), float(lRoomToLegendCloseShortSide + x1)) GL.glVertex2f(float(lRoomToLegendFarLongSide), float(lRoomToLegendCloseShortSide + x1)) GL.glVertex2f(float(lRoomToLegendFarLongSide), float(lRoomToLegendCloseShortSide + x2)) GL.glVertex2f(float(lRoomToLegendCloseLongSide), float(lRoomToLegendCloseShortSide + x2)) else: GL.glVertex2f(float(lRoomToLegendCloseShortSide + x2), float(lRoomToLegendCloseLongSide)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x2), float(lRoomToLegendFarLongSide)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x1), float(lRoomToLegendFarLongSide)) GL.glVertex2f(float(lRoomToLegendCloseShortSide + x1), float(lRoomToLegendCloseLongSide)) GL.glEnd() if len(ramp[0])==4: GL.glDisable(GL.GL_BLEND) GL.glEnable(GL.GL_DEPTH_TEST) GL.glDepthMask(GL.GL_TRUE) # GL.glEnable(GL.GL_LIGHTING) GL.glPopMatrix() GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Spheres.py0000644000175000017500000010114211533766127021662 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Authors: Michel F. SANNER, Daniel Stoffler # # sanner@scripps.edu # stoffler@scripps.edu # # Copyright: M. Sanner, Daniel Stoffler TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Spheres.py,v 1.106 2011/03/03 19:30:31 sanner Exp $ # # $Id: Spheres.py,v 1.106 2011/03/03 19:30:31 sanner Exp $ # import warnings import numpy.oldnumeric as Numeric, math from opengltk.OpenGL import GL, GLU from opengltk.extent.utillib import glDrawSphereSet, extractedGlutSolidSphere import DejaVu from DejaVu.Geom import Geom from DejaVu import datamodel, viewerConst from DejaVu.viewerFns import checkKeywords from DejaVu.colorTool import glMaterialWithCheck, resetMaterialMemory from DejaVu.IndexedPolygons import IndexedPolygons if hasattr(DejaVu, 'enableVertexArrayNonVBO') is False: DejaVu.enableVertexArrayNonVBO = False try: from UTpackages.UTimposter import utimposterrend UTImposterRendererFound = True except ImportError: #warnings.warn('UTpackages.UTimposter not found') UTImposterRendererFound = False class GLUSpheres(Geom): """Class for sets of spheres""" if glDrawSphereSet: fastSpheres = 1 else: fastSpheres = 0 keywords = Geom.keywords + [ 'centers', 'radii', 'quality', 'slices', #deprecated 'stacks' #deprecated ] def getState(self, full=False): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() state = Geom.getState(self, full) state['quality'] = self.quality if full: rad = self.vertexSet.radii.array if len(rad): state['radii'] = rad return state def __init__(self, name=None, check=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Spheres.__init__" v = kw.get('centers') if v is not None: kw['vertices'] = v # rename centers in vertices for Geom.__init elif not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set self.templateDSPL = None # (displayList, openglContext) #self.firstList = GL.glGenLists(3) self.culling = GL.GL_BACK self.inheritCulling = 0 self.frontPolyMode = GL.GL_FILL self.inheritFrontPolyMode = viewerConst.NO self.oneRadius = viewerConst.YES self.radius = 1.0 self.quality = None #self.immediateRendering = True apply( Geom.__init__, (self, name, check), kw ) assert len(self.vertexSet.vertices.ashape)==2 self._modified = False def Set(self, check=1, redo=1, updateOwnGui=True, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = 0 # Exceptionnaly this has to be before the call to Geom.Set v = kw.pop( 'centers', None) if v is not None: kw['vertices'] = v # rename centers in vertices for Geom.__init # Exceptionnaly this has to be before the call to Geom.Set # because we want to override the treatment of it by Geom.Set invertNormals = kw.pop('invertNormals', None) if invertNormals is not None: if self.invertNormals != invertNormals: self.invertNormals = invertNormals self.chooseTemplate() redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= apply( Geom.Set, (self, check, 0), kw) if len(kw) == 0: return self.redoNow(redo, updateOwnGui, redoFlags) rad = kw.pop('radii', None) if rad is not None: if type(rad).__name__ in ('float','int'): self.oneRadius = viewerConst.YES self.radius = rad self.vertexSet.radii = datamodel.ScalarProperties('radii', shape=(0,), datatype=viewerConst.FPRECISION) else: # type(rad).__name__ in ('list', 'tuple', 'ndarray'): if len(rad)==1: self.oneRadius = viewerConst.YES self.radius = rad[0] self.vertexSet.radii = datamodel.ScalarProperties('radii', rad, datatype=viewerConst.FPRECISION) elif hasattr(self.vertexSet, 'radii') is False: self.vertexSet.radii = datamodel.ScalarProperties( 'radii', shape=(0,), datatype=viewerConst.FPRECISION) if rad is not None or v is not None: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.vertexSet.radii.PropertyStatus(len(self.vertexSet)) if self.vertexSet.radii.status < viewerConst.COMPUTED: self.oneRadius = viewerConst.YES else: self.oneRadius = viewerConst.NO kw.pop( 'stacks', None) # deprecated kw.pop( 'slices', None) # deprecated quality = kw.pop('quality', None) if quality is not None or self.quality not in [1,2,3,4,5]: lOldQuality = self.quality if quality in [1,2,3,4,5]: self.quality = quality else: if len(self.vertexSet.vertices.array) < 500: self.quality = 5 elif len(self.vertexSet.vertices.array) < 5000: self.quality = 4 elif len(self.vertexSet.vertices.array) < 50000: self.quality = 3 elif len(self.vertexSet.vertices.array) < 100000: self.quality = 2 else: self.quality = 1 if lOldQuality != self.quality: if self.templateDSPL is not None: redoFlags |= self._redoFlags['redoTemplateFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def deleteTemplate(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Spheres.deleteTemplate", self.templateDSPL # it is asumed the right OpenGL context is active if GL.glGetIntegerv(GL.GL_LIST_INDEX) == [0]: assert self.templateDSPL is not None currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if currentcontext != self.templateDSPL[1]: import traceback;traceback.print_stack() warnings.warn('deleteTemplate failed because the current context is the wrong one') print "currentcontext != self.templateDSPL[1]", currentcontext, self.templateDSPL[1] else: #print '-%d'%self.templateDSPL[0], currentcontext, "glDeleteLists Spheres0" #print '-%d'%(self.templateDSPL[0]+1), currentcontext, "glDeleteLists Spheres1" #print '-%d'%(self.templateDSPL[0]+2), currentcontext, "glDeleteLists Spheres2" GL.glDeleteLists(self.templateDSPL[0], 3) self.templateDSPL = None def makeTemplate(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Spheres.makeTemplate", self.quality # it is asumed the right OpenGL context is active # make sure we are not already in a newlist if GL.glGetIntegerv(GL.GL_LIST_INDEX) == [0]: assert self.templateDSPL is None lFirstList = GL.glGenLists(3) #lFirstList = self.firstList #print "Spheres.makeTemplate", lFirstList #print "lFirstList Spheres.makeTemplate", lFirstList, self.name lCurrentContext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') self.templateDSPL = ( lFirstList, lCurrentContext ) if (hasattr(DejaVu, 'enableVBO') and DejaVu.enableVBO) \ or DejaVu.enableVertexArrayNonVBO is True : lSphereGeom = self.asIndexedPolygons(run=1, quality=self.quality-1, centers=((0,0,0),), radii=((1.,),) ) GL.glNewList(lFirstList+1, GL.GL_COMPILE) lSphereGeom.Draw() GL.glEndList() lSphereGeom.Set(invertNormals=True) GL.glNewList(lFirstList+2, GL.GL_COMPILE) lSphereGeom.Draw() GL.glEndList() else: quality = self.quality * 5 GL.glNewList(lFirstList+1, GL.GL_COMPILE) #print '+%d'%(lFirstList+1), lCurrentContext, "glNewList Spheres1" extractedGlutSolidSphere(1, quality, quality, 0) #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Spheres1" GL.glEndList() GL.glNewList(lFirstList+2, GL.GL_COMPILE) #print '+%d'%(lFirstList+2), lCurrentContext, "glNewList Spheres2" extractedGlutSolidSphere(1, quality, quality, 1) #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Spheres2" GL.glEndList() self.chooseTemplate() def redoTemplate(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.viewer: lSuspendRedraw = self.viewer.suspendRedraw self.viewer.suspendRedraw = True self.deleteTemplate() self.makeTemplate() if self.viewer: self.viewer.suspendRedraw = lSuspendRedraw def chooseTemplate(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # make sure we are not already in a newlist if GL.glGetIntegerv(GL.GL_LIST_INDEX) == [0]: GL.glNewList(self.templateDSPL[0], GL.GL_COMPILE) #print '+%d'%self.templateDSPL[0], "glNewList Spheres0" if self.invertNormals: #print "GLU_INSIDE reversed normals" #print '#%d'%(self.templateDSPL[0]+2), "glCallList Spheres2" GL.glCallList(self.templateDSPL[0]+2) else: #print "GLU_OUTSIDE regular normals" #print '#%d'%(self.templateDSPL[0]+1), "glCallList Spheres1" GL.glCallList(self.templateDSPL[0]+1) #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Spheres0" GL.glEndList() def Add(self, check=1, redo=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add spheres""" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init apply( Geom.Add, (self,0,0), kw) rad = kw.get( 'radii') if rad: if type(rad).__name__ == 'float': self.oneRadius = viewerConst.YES self.radius = rad else: self.vertexSet.radii.AddValues( rad ) if rad or v: self.redoDspLst=1 self.vertexSet.radii.PropertyStatus(len(self.vertexSet)) if self.vertexSet.radii.status < viewerConst.COMPUTED: self.oneRadius = viewerConst.YES else: self.oneRadius = viewerConst.NO if self.viewer and redo: if self.redoDspLst and self not in self.viewer.objectsNeedingRedo: self.viewer.objectsNeedingRedo[self] = None # self.RedoDisplayList() def Draw(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Draw function of the geom return status 0 or 1 If you want fast rendering, you need to set self.templateDSPL using MakeTemplate. """ #print "Spheres.Draw", self.name assert self.templateDSPL is not None currentcontext = self.viewer.currentCamera.tk.call( self.viewer.currentCamera._w, 'contexttag') if currentcontext != self.templateDSPL[1]: import traceback;traceback.print_stack() warnings.warn("""draw failed because the current context is the wrong one""") #print "currentcontext != self.templateDSPL[1]", currentcontext, self.templateDSPL[1] return 0 centers = self.vertexSet.vertices.array if len(centers) == 0: return 0 # handle overall binding of material if self.inheritMaterial: fp = None fpProp = None bp = None else: mat = self.materials[GL.GL_FRONT] fpProp = [] for propInd in range(4): b, p = mat.GetProperty(propInd) fpProp.append(p) fpProp.append(mat.prop[4]) fp = self.materials[GL.GL_FRONT] #colorFront = Numeric.array(self.materials[GL.GL_FRONT].prop[1], copy=1) colorFront = Numeric.array(fpProp[1], copy=1) if self.frontAndBack: bp = None face = GL.GL_FRONT_AND_BACK else: bp = self.materials[GL.GL_BACK] face = GL.GL_FRONT if fp: for m in (0,1,2,3,4): if fp.binding[m] == viewerConst.OVERALL: glMaterialWithCheck( face, viewerConst.propConst[m], fpProp[m][0]) if fp.binding[1] == viewerConst.OVERALL: GL.glColor4fv(colorFront[0]) if fp: for m in (0,1,2,3,4): if fp.binding[m] != viewerConst.OVERALL: glMaterialWithCheck( face, viewerConst.propConst[m], fpProp[m][0]) if fp.binding[1] != viewerConst.OVERALL: GL.glColor4fv(colorFront[0]) if bp: for m in (0,1,2,3,4): if bp.binding[m] != viewerConst.OVERALL: glMaterialWithCheck( GL.GL_BACK, viewerConst.propConst[m], bp.prop[m][0]) #print self.name #if fp: print fp.prop[1], fp.binding #else: print if self.fastSpheres: #print "self.fastSpheres", self.fastSpheres if self.oneRadius == viewerConst.NO: radii = self.vertexSet.radii.array #FIXME: quick fix because can be called from base class Set # method after centers have been set BUT before radii have been # set if len(self.vertexSet.vertices) != len(radii): return 0 else: radii = Numeric.ones( centers.shape[0] ) * self.radius radii.shape = (-1,1) coords = Numeric.concatenate ( (centers, radii), 1 ) ## if not self.inheritMaterial: ## mat = self.materials[GL.GL_FRONT] ## fpProp = [] ## for propInd in range(4): ## b, p = mat.GetProperty(propInd) ## fpProp.append(p) ## fpProp.append(mat.prop[4]) ## #fpProp = self.materials[GL.GL_FRONT].prop[:5] ## else: ## fpProp = None #print 'FUGU OVERWRITE COLOR', fpProp #import numpy #GL.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, numpy.array((.6,.6,.6,1), 'f')) #GL.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, numpy.array((1.,1.,1.,1), 'f')) #GL.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, numpy.array((.4,.4,.4,1), 'f')) #GL.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, numpy.array((0,0,0,1), 'f')) #GL.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, 1.) status = glDrawSphereSet( self.templateDSPL[0], coords.astype('f'), fpProp, #self.materials[GL.GL_FRONT].prop, highlight=self.highlight, ) #print "Spheres, status: ", status return status else: resetMaterialMemory() #print "SLOW Spheres" if self.oneRadius == viewerConst.NO: radii = self.vertexSet.radii.array else: radii = Numeric.ones( centers.shape[0] ) * self.radius if len(self.vertexSet.vertices) != len(radii): return 0 for i in xrange(centers.shape[0]): GL.glPushName(i) GL.glPushMatrix() GL.glTranslatef(float(centers[i][0]), float(centers[i][1]), float(centers[i][2])) if not self.oneRadius: GL.glScalef(float(radii[i]),float(radii[i]),float(radii[i])) else: GL.glScalef(float(self.radius), float(self.radius), float(self.radius)) #print '#%d'%self.templateDSPL[0], "glCallList Spheres0" if fp: for m in (0,1,2,3,4): if fp.binding[m] != viewerConst.OVERALL: glMaterialWithCheck( face, viewerConst.propConst[m], fp.prop[m][0], geom=self) GL.glCallList(self.templateDSPL[0]) GL.glPopMatrix() GL.glPopName() return 1 def asIndexedPolygons(self, run=1, quality=None, centers=None, radii=None, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """implement the sphere as an icosaedre. run=0 returns 1 if this geom can be represented as an IndexedPolygon and None if not. run=1 returns the IndexedPolygon object. """ #print "Spheres.asIndexedPolygons", quality if run==0: return 1 # yes, I can be represented as IndexedPolygons if quality in [1,2,3,4,5]: quality = quality elif quality < 0 and self.quality in [2,3,4,5]: quality = self.quality - 2 else: quality = self.quality - 1 # get centers if centers is None: centers = self.vertexSet.vertices.array # get radii if radii is None: if self.oneRadius == viewerConst.NO: radii = self.vertexSet.radii.array else: radii = Numeric.ones( centers.shape[0] ) * self.radius # create template sphere S = TriangulateIcosByEdgeCenterPoint(quality=quality) tmpltVertices = S.getVertices(quality=quality) tmpltFaces = S.getFaces(quality=quality) tmpltNormals = S.getVNormals(quality=quality) # these lists will store the data for the new spheres vertices = [] faces = [] normals = [] # loop over spheres for i in range(len(centers)): vert = Numeric.array(tmpltVertices[:])*radii[i] + centers[i] vertices.extend(list(vert)) fac = Numeric.array(tmpltFaces[:]) + i*len(tmpltVertices) faces.extend(list(fac)) norm = Numeric.array(tmpltNormals[:]) normals.extend(list(norm)) sphGeom = IndexedPolygons("sph", vertices=Numeric.array(vertices), faces=faces, vnormals=Numeric.array(normals), visible=1, invertNormals=self.invertNormals) # copy Spheres materials into sphGeom matF = self.materials[GL.GL_FRONT] matB = self.materials[GL.GL_BACK] sphGeom.materials[GL.GL_FRONT].binding = matF.binding[:] sphGeom.materials[GL.GL_FRONT].prop = matF.prop[:] sphGeom.materials[GL.GL_BACK].binding = matB.binding[:] sphGeom.materials[GL.GL_BACK].prop = matB.prop[:] if sphGeom.materials[GL.GL_FRONT].binding[1] == viewerConst.PER_VERTEX: newprop = [] index = 0 cnt = 0 for i in range(len(vertices)): newprop.append(sphGeom.materials[GL.GL_FRONT].prop[1][index]) cnt = cnt + 1 if cnt == len(tmpltVertices): index = index + 1 cnt = 0 sphGeom.materials[GL.GL_FRONT].prop[1] = newprop #print "Spheres.asIndexedPolygons out", quality return sphGeom if UTImposterRendererFound: class UTSpheres(GLUSpheres): keywords = list(GLUSpheres.keywords) for kw in ['quality', 'stacks', 'slices']: keywords.remove(kw) def makeTemplate(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() pass def __init__(self, name=None, check=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() apply( GLUSpheres.__init__, (self, name, check), kw) def __init__(self, name=None, check=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.imposterRenderer = utimposterrend.ImposterRenderer() apply(GLUSpheres.__init__, (self, name, 0), kw ) self.immediateRendering = 1 def Set(self, check=1, redo=1, updateOwnGui=True, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ v = kw.get( 'centers') mat = kw.has_key('materials') rad = kw.get( 'radii') redoFlags = apply( GLUSpheres.Set, (self, 0, 0), kw) if mat or rad or v: self.redoDspLst=1 coords = self.vertexSet.vertices.array rad = self.vertexSet.radii.array mat = self.materials[GL.GL_FRONT].prop[1] self.initializeImposterRenderer(coords, rad, mat) return self.redoNow(redo, updateOwnGui, redoFlags) def initializeImposterRenderer(self, coords, rad, col): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() status = self.imposterRenderer.initRenderer() #print "initializeImposterRenderer status:", status if not status: print "Could not initialize the imposter renderer\n" return False self.imposterRenderer.initSubRenderers(0) self.imposterRenderer.clear() #brp = utimposterrend.BallRendererPtr(self.imposterRenderer.m_BallRenderer) #print "coords:", coords #print "radius:", rad #print "colors:", col if type(coords) == Numeric.ndarray: coords = coords.tolist() if type(rad)== Numeric.ndarray: rad = rad.tolist() if type(col) == Numeric.ndarray: col = col.tolist() #print "adding spheres...", len(rad) brp = self.imposterRenderer.m_BallRenderer if len(col) == len(coords): for i in range(len(coords)): #print "adding ball", i brp.addBall(coords[i][0], coords[i][1], coords[i][2], rad[i], col[i][0], col[i][1], col[i][2]) elif len(rad) == len(coords): for i in range(len(coords)): #print "adding ball", i brp.addBall(coords[i][0], coords[i][1], coords[i][2], rad[i], col[0][0], col[0][1], col[0][2]) else: for i in range(len(coords)): #print "adding ball", i brp.addBall(coords[i][0], coords[i][1], coords[i][2], 1., col[0][0], col[0][1], col[0][2]) #print "done" return True def Draw(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.imposterRenderer.renderBuffer(True, False, None, None, 0, False, 1.0) Spheres = GLUSpheres # UTSpheres GLUSpheres class TriangulateIcos: """Base class to compute vertices, faces and normals of a sphere based on icosahedral subdivision. Subclassed will implement different subdivision methods. A quality can be passed to the constructur which will trigger the precomputation of spheres of quality 0 to quality. To access the data, use getVertices(quality=val), getFaces(quality=val), getVNormals(quality=val) where val is the quality level """ def __init__(self, quality=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if quality is None: quality = 5 # set default to 5 self.quality = quality self.vertices=[] # stores vertices # face lists are created dynamically later on # normals == vertices X = 0.525731112119133606 # X coord Z = 0.850650808352039932 # Y coord # build initial icosahedron (lowest quality) self.vertices = [ [-X, 0., Z], [X, 0., Z], [-X, 0., -Z], [X, 0., -Z], [0., Z, X], [0., Z, -X], [0., -Z, X], [0., -Z, -X], [Z, X, 0.], [-Z, X, 0.], [Z, -X, 0.], [-Z, -X, 0.] ] self.facesQ0 = [ [11,6,0], [9,11,0], [0,6,1], [6,10,1], [9,5,2], [7,11,2], [5,3,2], [8,10,3], [5,8,3], [0,1,4], [9,4,5], [4,8,5], [7,10,6], [2,3,7], [4,1,8], [0,4,9], [8,1,10], [7,3,10], [7,6,11], [9,2,11] ] def subsample(self, vertices, faces, quality): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() lenF = len(faces) lenV = len(vertices) for i in xrange(lenF): v0 = vertices[faces[i][0]] v1 = vertices[faces[i][1]] v2 = vertices[faces[i][2]] self.subdivideVert(v0, v1, v2) self.subdivideFaces(faces, lenV, quality) def normalize(self, v): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() d = math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) if d == 0.0: print 'Zero length vector!' return return [v[0] / d, v[1] / d, v[2] / d] def getVertices(self, quality=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ has to be implemented by subclass """ pass def getVNormals(self, quality=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ has to be implemented by subclass """ pass def getFaces(self, quality=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return getattr(self, 'facesQ%d'%quality) class TriangulateIcosByEdgeCenterPoint(TriangulateIcos): def __init__(self, quality=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "TriangulateIcosByEdgeCenterPoint.__init__" TriangulateIcos.__init__(self, quality) if self.quality > 0: for qu in range(1, self.quality+1): self.subsample(self.vertices, getattr(self, 'facesQ%d'%(qu-1,) ), qu) def subdivideVert(self, v0, v1, v2): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "TriangulateIcosByEdgeCenterPoint.subdivideVert" # called by subsample v01 = [] v12 = [] v20 = [] for i in range(3): v01.append(v0[i] + v1[i]) v12.append(v1[i] + v2[i]) v20.append(v2[i] + v0[i]) v01=self.normalize(v01) v12=self.normalize(v12) v20=self.normalize(v20) self.vertices.append(v01) self.vertices.append(v12) self.vertices.append(v20) def subdivideFaces(self, faces, lenV, quality): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "TriangulateIcosByEdgeCenterPoint.subdivideFaces" # called by subsample newFaces = [] for i in xrange(len(faces)): j = i j = j * 3 f0 = faces[i][0] f1 = faces[i][1] f2 = faces[i][2] f01 = j+lenV f12 = j+lenV+1 f20 = j+lenV+2 newFaces.append([f0, f01, f20]) newFaces.append([f01, f12, f20]) newFaces.append([f01, f1, f12]) newFaces.append([f20, f12, f2]) # dynamically create a self.facesQ setattr(self, 'facesQ%d'%quality, newFaces[:]) def getVertices(self, quality=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "TriangulateIcosByEdgeCenterPoint.getVertices" # the vertex list is very big, since vertices are added to this # list after every subsampling. Thus, only what is needed is returned v = 12 # vertices of icosahedron f = 20 # faces of icosahedron for i in range(quality): v = v+f*3 f = f*4 return self.vertices[:v] def getVNormals(self, quality=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "TriangulateIcosByEdgeCenterPoint.getVNormals" # normals == vertices self.normals = self.getVertices(quality=quality)[:] return self.normals class TriangulateIcosByFaceCenterPoint(TriangulateIcos): """ This class subdivides each face in 3 new faces by putting a center in the middle of a face triangle.""" def __init__(self, quality=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() TriangulateIcos.__init__(self, quality) if self.quality > 0: for qu in range(1, self.quality+1): self.subsample(self.vertices, getattr(self, 'facesQ%d'%(qu-1,) ), qu) def subdivideVert(self, v0, v1, v2): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # called by subsample v012 = [] for i in range(3): v012.append(v0[i] + v1[i] + v2[i]) v012 = self.normalize(v012) self.vertices.append(v012) def subdivideFaces(self, faces, lenV, quality): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # called by subsample newFaces = [] for i in xrange(len(faces)): f0 = faces[i][0] f1 = faces[i][1] f2 = faces[i][2] f012 = i+lenV newFaces.append([f0, f1, f012]) newFaces.append([f1, f2, f012]) newFaces.append([f2, f0, f012]) # dynamically create a self.facesQ setattr(self, 'facesQ%d'%quality, newFaces[:]) def getVertices(self, quality=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # the vertex list is very big, since vertices are added to this # list after every subsampling. Thus, only what is needed is returned v = 12 # vertices of icosahedron f = 20 # faces of icosahedron for i in range(quality): v = v+f f = f*3 return self.vertices[:v] def getVNormals(self, quality=0): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # normals == vertices return self.getVertices(quality=quality) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/colorMapLegend.py0000644000175000017500000005536612014533451023147 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: April 2003 Authors: Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/colorMapLegend.py,v 1.78 2012/08/20 22:16:09 annao Exp $ # # $Id: colorMapLegend.py,v 1.78 2012/08/20 22:16:09 annao Exp $ # import os import types import Tkinter import Pmw from weakref import ref from copy import deepcopy import string from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from viewerFns import checkKeywords from opengltk.OpenGL import GL from DejaVu.IndexedGeom import IndexedGeom from colorTool import RGBRamp, resetMaterialMemory from DejaVu.Insert2d import Insert2d import viewerConst from pyglf import glf class ColorMapLegend(Insert2d): """Class for displaying a colormap legend. arguments for the constructor or Set method are: ramp: Numeric array of shape Nx3 or Nx4 (default is RBGRamp()) height: height of colormap legend width: width of colormap legend interp: 1 or 0 to turn color interpolation on and off resp. mini: minimum values (i.e which corresponds to the first color) maxi: maximum values (i.e which corresponds to the last color) If interp is set to 1 QUAD_STRIPS are used and colors are interpolated, else one QUAD is drawn for each entry in the colormap. If the color provide alpha values, a chechered background is drawn. """ keywords = Insert2d.keywords + [ 'ramp', 'height', 'width', 'interp', # 1: for color interpolation, or 0 'mini', # 'maxi', # 'labelValues', # floating point numbers to be written below cml 'glfFont', 'fontScale', 'numOfLabels', 'unitsString', 'interp', 'visibleFrame', 'invertLabelsColor', ] glfVectorFontList = [ 'arial1.glf', 'courier1.glf', 'crystal1.glf', 'techno0.glf', 'techno1.glf', 'times_new1.glf', 'aksent1.glf', 'alpine1.glf', 'broadway1.glf', 'chicago1.glf', 'compact1.glf', 'cricket1.glf', 'garamond1.glf', 'gothic1.glf', 'penta1.glf', 'present_script1.glf' ] def __init__(self, colormapgui, name='color map legend', check=1, **kw): # GLF FONTS Initialisations glf.glfInit() glf.glfEnable(glf.GLF_CONSOLE_MESSAGES) lGlfModulePath = os.path.split(glf.__file__)[-2] lPathToFonts = lGlfModulePath+os.sep+'fonts'+os.sep self.glfVectorFontLoadIdDict = {} for font in self.glfVectorFontList: self.glfVectorFontLoadIdDict[font] = glf.glfLoadFont(lPathToFonts+font) self.fontScale = 8 self.glfFontID = 0 # other initialisations self.colormapguiRef = ref(colormapgui) self.resizeSpotRadius = 5 self.resizeSpot = None self.verticalLegend = True self.mini = None self.maxi = None kw['ramp'] = RGBRamp() kw['height'] = 1. kw['width'] = len(kw['ramp']) kw['interp'] = 1 # kw['mini'] = None # kw['maxi'] = None kw['labelValues'] = [] kw['numOfLabels'] = 5 kw['unitsString'] = 'law' kw['invertLabelsColor'] = False kw['visibleFrame'] = True #kw['protected'] = True kw['immediateRendering'] = False kw['visible'] = False kw['transparent'] = True kw['size'] = [12, 120] # override the default value in Insert2d self.clickPosFromLegendBottomLeft = [0, 0] apply( Insert2d.__init__, (self, name, check), kw) # Insert2d initialisations # (need to be done after the Insert2d.__init__ otherwise it overrides) self.needsRedoDpyListOnResize = True self.initialPosition = [1, 350] # override the default value in Insert2d self.coord2d = deepcopy(self.initialPosition) # 2d coordinates in pixels from top left self.animatable = False self.hiddenInCamera = {} # key:Camera object, value dummy def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: add faces (polygon or lines) to this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ #print "colorMapLegend.Set" redoFlags = apply( Insert2d.Set, (self, check, 0), kw) ramp=kw.get('ramp') if ramp is not None: assert len(ramp) > 0 assert len(ramp[0])==3 or len(ramp[0])==4 self.ramp = ramp redoFlags |= self._redoFlags['redoDisplayListFlag'] height = kw.get('height') if height: assert height > 0.0 self.height = height redoFlags |= self._redoFlags['redoDisplayListFlag'] width = kw.get('width') if width: assert width > 0.0 self.width = width redoFlags |= self._redoFlags['redoDisplayListFlag'] mini = kw.get('mini') if mini is not None: #assert isinstance(mini, types.FloatType) self.mini = mini redoFlags |= self._redoFlags['redoDisplayListFlag'] maxi = kw.get('maxi') if maxi is not None: #assert isinstance(maxi, types.FloatType) self.maxi = maxi redoFlags |= self._redoFlags['redoDisplayListFlag'] labelValues = kw.get('labelValues') if labelValues is not None: # for v in labelValues: # assert isinstance(v, types.FloatType) self.labelValues = labelValues redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] glfFont = kw.get('glfFont') if glfFont is not None: if glfFont in self.glfVectorFontLoadIdDict.keys(): self.glfFontID = self.glfVectorFontLoadIdDict[glfFont] redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] fontScale = kw.get('fontScale') if fontScale is not None: assert isinstance(fontScale, types.IntType) self.fontScale = fontScale redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] numOfLabels = kw.get('numOfLabels') if numOfLabels is not None: assert isinstance(numOfLabels, types.IntType) self.numOfLabels = numOfLabels redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] unitsString = kw.get('unitsString') if unitsString is not None: self.unitsString = unitsString redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] interp = kw.get('interp') if interp is not None: assert interp in (0, 1) self.interp = interp redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] visibleFrame = kw.get('visibleFrame') if visibleFrame is not None: self.visibleFrame = visibleFrame redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] invertLabelsColor = kw.get('invertLabelsColor') if invertLabelsColor is not None: self.invertLabelsColor = invertLabelsColor redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): #print "colorMapLegend.Draw", self if self.viewer.tileRender: tile = self.getTile() #print "tile", tile else: tile = None fullWidth = self.viewer.currentCamera.width fullHeight = self.viewer.currentCamera.height if self.invertLabelsColor is False: backgroundColor = ( self.viewer.currentCamera.backgroundColor[0], self.viewer.currentCamera.backgroundColor[1], self.viewer.currentCamera.backgroundColor[2], .5) else: backgroundColor = ( 1-self.viewer.currentCamera.backgroundColor[0], 1-self.viewer.currentCamera.backgroundColor[1], 1-self.viewer.currentCamera.backgroundColor[2], .5) from DejaVu.Legend import drawSelfOrientedLegend self.polygonContour , self.resizeSpot , self.verticalLegend = drawSelfOrientedLegend( fullWidth=fullWidth, fullHeight=fullHeight, tile=tile, ramp=self.ramp, mini=self.mini, maxi=self.maxi, name=self.name, unit=self.unitsString, labelValues=self.labelValues, roomLeftToLegend=self.coord2d[0], roomBelowLegend=fullHeight-self.coord2d[1], legendShortSide=self.size[0], legendLongSide=self.size[1], significantDigits=3, backgroundColor=backgroundColor, interpolate=self.interp, frame=self.visibleFrame, selected=(self.viewer.currentObject == self), numOfLabels=self.numOfLabels, resizeSpotRadius=self.resizeSpotRadius, fontScale=self.fontScale, glfFontID=self.glfFontID, ) return 1 def pickDraw(self): """called by the picking process to operate the selection """ #print "colorMapLegend.pickDraw", self # we draw just flat quad of the insert2d GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() #GL.glLoadIdentity() GL.glLoadMatrixf(self.viewer.currentCamera.pickMatrix) GL.glOrtho(0, float(self.viewer.currentCamera.width), 0, float(self.viewer.currentCamera.height), -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL) #GL.glColor3f(1,0,0) if self.resizeSpot is not None: GL.glPushName(1) GL.glBegin(GL.GL_QUADS) GL.glVertex2f(float(self.resizeSpot[0]+self.resizeSpotRadius), float(self.resizeSpot[1]-self.resizeSpotRadius)) GL.glVertex2f(float(self.resizeSpot[0]+self.resizeSpotRadius), float(self.resizeSpot[1]+self.resizeSpotRadius)) GL.glVertex2f(float(self.resizeSpot[0]-self.resizeSpotRadius), float(self.resizeSpot[1]+self.resizeSpotRadius)) GL.glVertex2f(float(self.resizeSpot[0]-self.resizeSpotRadius), float(self.resizeSpot[1]-self.resizeSpotRadius)) GL.glEnd() GL.glPopName() GL.glPushName(0) GL.glBegin(GL.GL_QUADS) GL.glVertex2fv(self.polygonContour[0]) GL.glVertex2fv(self.polygonContour[1]) GL.glVertex2fv(self.polygonContour[2]) GL.glVertex2fv(self.polygonContour[3]) GL.glEnd() GL.glPopName() GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPopMatrix() def setPosition(self, event, redo=1): """the trackball transmit the translation info """ #print "colorMapLegend.setPosition", event.x, event.y self.coord2d[0] = event.x - self.clickPosFromLegendBottomLeft[0] self.coord2d[1] = event.y - self.clickPosFromLegendBottomLeft[1] if self.coord2d[0] < 0: self.coord2d[0] = 0 if self.coord2d[1] < 0: self.coord2d[1] = 0 if self.coord2d[0] > self.viewer.currentCamera.width: self.coord2d[0] = self.viewer.currentCamera.width if self.coord2d[1] > self.viewer.currentCamera.height: self.coord2d[1] = self.viewer.currentCamera.height self.viewer.objectsNeedingRedo[self] = None def setSize(self, event, redo=1): """override the Insert2d function """ #print "colorMapLegend.setSize", self if self.verticalLegend is True: self.size[0] = event.x - self.coord2d[0] self.size[1] = self.coord2d[1] - event.y if self.size[0] > self.viewer.currentCamera.width: self.size[0] = self.viewer.currentCamera.width if self.size[1] > self.viewer.currentCamera.height: self.size[1] = self.viewer.currentCamera.height else: self.size[1] = event.x - self.coord2d[0] self.size[0] = self.coord2d[1] - event.y if self.size[1] > self.viewer.currentCamera.width: self.size[1] = self.viewer.currentCamera.width if self.size[0] > self.viewer.currentCamera.height: self.size[0] = self.viewer.currentCamera.height if self.size[0] < 1: self.size[0] = 1 if self.size[1] < 1: self.size[1] = 1 if self.needsRedoDpyListOnResize and self.viewer: self.viewer.objectsNeedingRedo[self] = None def ResetPosition(self): self.coord2d = deepcopy(self.initialPosition) if self.viewer: self.viewer.objectsNeedingRedo[self] = None def respondToDoubleClick(self, event): """ """ self.showOwnGui() if self.needsRedoDpyListOnResize and self.viewer: self.viewer.objectsNeedingRedo[self] = None def processHit_cb(self, pick): #print "colorMapLegend.processHit_cb", self #print "pick",pick #print "pick.event",dir(pick) #print "pick.type",pick.type #print "pick.event",dir(pick.event) #print "pick.event",pick.event #print "pick.event.type",pick.event.type #print "pick.event.state",pick.event.state #print "pick.event.time",pick.event.time #print "pick.hits",pick.hits if ( len(pick.hits) == 1) and pick.hits.has_key(self): if self.viewer.currentObject != self: # if the only hit is the legend, # it becomes the current object self.viewer.SetCurrentObject(self) self.isMoving = True elif pick.event.time - self.lastPickEventTime < 200: #double click self.viewer.SetCurrentObject(self.viewer.rootObject) self.respondToDoubleClick(pick.event) elif pick.hits[self][0][0] == 1: # the click in inside the resize button #print "resize" self.isMoving = False elif pick.hits[self][0][0] == 0: # the click in inside the legend but outside # the resize button self.isMoving = True self.clickPosFromLegendBottomLeft = [pick.event.x - self.coord2d[0], pick.event.y - self.coord2d[1]] #print "self.clickPosFromLegendBottomLeft", self.clickPosFromLegendBottomLeft if self.viewer: self.viewer.objectsNeedingRedo[self] = None elif self.viewer.currentObject == self: #print "the insert2d is selected, but picking is outside" self.isMoving = None self.viewer.SetCurrentObject(self.viewer.rootObject) if self.needsRedoDpyListOnResize and self.viewer: self.viewer.objectsNeedingRedo[self] = None self.lastPickEventTime = pick.event.time def createOwnGui(self): self.ownGui = Tkinter.Toplevel() self.ownGui.title(self.name) self.ownGui.protocol('WM_DELETE_WINDOW', self.ownGui.withdraw ) frame1 = Tkinter.Frame(self.ownGui) frame1.pack(side='top') #unit self.unitsEnt = Pmw.EntryField(frame1, label_text='Units ', labelpos='w', value=self.unitsString, command=self.setWithOwnGui) self.unitsEnt.pack(side='top', fill='x') #glf vector font self.glfFont = Tkinter.StringVar() self.glfFont.set('chicago1.glf') self.glfFontCB = Pmw.ComboBox(frame1, label_text='Font ', labelpos='w', entryfield_value=self.glfFont.get(), scrolledlist_items=self.glfVectorFontList, selectioncommand=self.setWithOwnGui) self.glfFontCB.pack(side='top', fill='x') #fontScale self.fontScaleThumb = ThumbWheel(frame1, labCfg={'text':'font scale ', 'side':'left'}, showLabel=1, width=90, height=14, min=0, max=200, type=int, value=self.fontScale, callback=self.setWithOwnGui, continuous=True, oneTurn=10, wheelPad=0) self.fontScaleThumb.pack(side='top') #label lLabelValuesString = '' for lLabelValue in self.labelValues: lLabelValuesString += str(lLabelValue) + ' ' self.labelValsEnt = Pmw.EntryField( frame1, label_text='Numeric labels ', labelpos='w', value=lLabelValuesString, command=self.setWithOwnGui) self.labelValsEnt.component('entry').config(width=6) self.labelValsEnt.pack(side='top', fill='x') #numOfLabel self.numOfLabelsCtr = ThumbWheel(frame1, labCfg={'text':'Automatic labels', 'side':'left'}, showLabel=1, width=90, height=14, min=0, max=200, type=int, value=self.numOfLabels, callback=self.setWithOwnGui, continuous=True, oneTurn=20, wheelPad=0) self.numOfLabelsCtr.pack(side='top') # Interpolate self.interpVar = Tkinter.IntVar() self.interpVar.set(0) self.checkBoxFrame = Tkinter.Checkbutton( frame1, text='Interpolate', variable=self.interpVar, command=self.setWithOwnGui) self.checkBoxFrame.pack(side='top') # frame self.frameVar = Tkinter.IntVar() self.frameVar.set(1) self.checkBoxFrame = Tkinter.Checkbutton( frame1, text='Frame', variable=self.frameVar, command=self.setWithOwnGui) self.checkBoxFrame.pack(side='top') # invert labels color self.invertLabelsColorVar = Tkinter.IntVar() self.invertLabelsColorVar.set(0) self.checkBoxinvertLabelsColor = Tkinter.Checkbutton( frame1, text='Invert labels color', variable=self.invertLabelsColorVar, command=self.setWithOwnGui) #self.checkBoxFrame.pack(side='top') self.checkBoxinvertLabelsColor.pack(side='top') # colormapguiwidget: self.launchColormapWidget = Tkinter.Button( frame1, text="Show colormap settings", command=self.colormapguiRef().showColormapSettings_cb ) self.launchColormapWidget.pack(side='top', fill='x') def setWithOwnGui(self, event=None): #print "setWithOwnGui" glfFont = self.glfFontCB.get() fontScale = int(self.fontScaleThumb.get()) labelValues = map(float, string.split(self.labelValsEnt.get())) unitsString = self.unitsEnt.get() numOfLabels = int(self.numOfLabelsCtr.get()) if self.interpVar.get() == 1: interp = True else: interp = False if self.frameVar.get() == 1: visibleFrame = True else: visibleFrame = False if self.invertLabelsColorVar.get() == 1: invertLabelsColor = True else: invertLabelsColor = False self.Set( glfFont=glfFont, fontScale=fontScale, labelValues=labelValues, numOfLabels=numOfLabels, unitsString=unitsString, interp=interp, visibleFrame=visibleFrame, invertLabelsColor=invertLabelsColor, updateOwnGui=False) self.viewer.Redraw() def updateOwnGui(self): if self.ownGui is None: return self.ownGui.title(self.name) self.glfFontCB.selectitem(self.glfFont.get()) self.fontScaleThumb.set(self.fontScale) lLabelValuesString = '' for lLabelValue in self.labelValues: lLabelValuesString += str(lLabelValue) + ' ' self.labelValsEnt.setentry(lLabelValuesString) self.unitsEnt.setentry(self.unitsString) self.numOfLabelsCtr.set(self.numOfLabels) self.interpVar.set(self.interp) self.invertLabelsColorVar.set(self.visibleFrame) self.invertLabelsColorVar.set(self.invertLabelsColor) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/IndexedPolylines.py0000644000175000017500000000415411140200631023506 0ustar debiandebian############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# from inspect import isclass from DejaVu.IndexedGeom import IndexedGeom import datamodel import viewerConst from DejaVu.viewerFns import checkKeywords class IndexedPolylines(IndexedGeom): """Set of lines sharing vertices""" def __init__(self, name=None, check=1, **kw): #print "IndexedPolylines.__init__", name #kw['vertexArrayFlag'] = True #kw['immediateRendering'] = True apply( IndexedGeom.__init__, (self, name, check), kw) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: Set polygon's vertices, faces, normals or materials check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( IndexedGeom.Set, (self, check, 0), kw ) if hasattr(self, 'faceSet') \ and len(self.faceSet.faces.array) > 0 \ and len(self.faceSet.faces.array[0]) > 2 : # register functions to compute normals self.VertexNormalFunction(self.ComputeVertexNormals) self.vertexSet.normals.ComputeMode( viewerConst.AUTO ) self.FaceNormalFunction(self.ComputeFaceNormals) self.faceSet.normals.ComputeMode( viewerConst.AUTO ) self.GetNormals() from opengltk.OpenGL.GL import GL_LINE_STRIP self._PrimitiveType(type=GL_LINE_STRIP) return self.redoNow(redo, updateOwnGui, redoFlags) def Add(self, check=1, redo=1, **kw): """Add polygon's vertices, faces, normals or materials""" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) apply( IndexedGeom.Add, (self, 0, 0), kw ) if self.viewer and redo: if self.redoDspLst: self.viewer.objectsNeedingRedo[self] = None mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Polylines.py0000644000175000017500000001544711236405464022235 0ustar debiandebian############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Polylines.py,v 1.31 2009/08/05 22:44:04 vareille Exp $ # # $Id: Polylines.py,v 1.31 2009/08/05 22:44:04 vareille Exp $ # from opengltk.OpenGL import GL from opengltk.extent import _gllib as gllib from Geom import Geom import datamodel, viewerConst, types import numpy.oldnumeric as Numeric from viewerFns import checkKeywords import DejaVu class Polylines(Geom): """Class for sets of lines""" keywords = Geom.keywords + [ 'type', ] def __init__(self, name=None, check=1, **kw): if not kw.get('shape'): kw['shape'] = (0,0,3) # default shape for line's vertex set if kw.has_key('type') is False: kw['type'] = GL.GL_LINES apply( Geom.__init__, (self, name, check), kw) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( Geom.Set, (self, check, 0), kw ) type = kw.pop('type', None) if type is not None: self._PrimitveType(type) return self.redoNow(redo, updateOwnGui, redoFlags) def MaterialBindingMode(self, num, face=GL.GL_FRONT, mode=None): """Figure out how materials should be used to color the object we overwrite the method from Geom because the number of parts corresponds to the nuber of lines which is vertexSet.vertices.array.shape[0]""" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if num is None: num = self.materials[GL.GL_FRONT].diff elif type(num) is types.StringType: num = getattr(self.materials[GL.GL_FRONT], num) if face is None: face = GL.GL_FRONT f = face if face == GL.GL_FRONT_AND_BACK: f = GL.GL_FRONT self.frontAndBack = True lNumOfMaterials = self.materials[f].prop[num].shape[0] if mode is None: if lNumOfMaterials == len(self.vertexSet.vertices): self.materials[f].binding[num] = viewerConst.PER_VERTEX elif lNumOfMaterials == self.vertexSet.vertices.array.shape[0]: self.materials[f].binding[num] = viewerConst.PER_PART elif lNumOfMaterials == len(self.instanceMatricesFortran): self.materials[f].binding[num] = viewerConst.PER_INSTANCE elif lNumOfMaterials > 0: self.materials[f].binding[num] = viewerConst.OVERALL else: self.materials[f].binding[num] = viewerConst.INHERIT else: # a mode is requested if mode==viewerConst.PER_VERTEX and lNumOfMaterials >= len(self.vertexSet.vertices): self.materials[f].binding[num] = viewerConst.PER_VERTEX elif lNumOfMaterials == self.vertexSet.vertices.array.shape[0]: self.materials[f].binding[num] = viewerConst.PER_PART elif mode==viewerConst.OVERALL and lNumOfMaterials >= 1: self.materials[f].binding[num] = viewerConst.OVERALL elif mode==viewerConst.PER_INSTANCE and lNumOfMaterials >= len(self.instanceMatricesFortran): self.materials[f].binding[num] = viewerConst.PER_INSTANCE else: self.materials[f].binding[num] = viewerConst.INHERIT def __repr__(self): return '<%s> %s with %d lines' % (self.__class__, self.name, len(self.vertexSet) ) def _PrimitveType(self, type): """Find out out what type of lines """ assert type in viewerConst.LINES_PRIMITIVES, type self.fixedLength = self.vertexSet.vertices.ashape[1] if self.fixedLength == 2 and (type is None or type==GL.GL_LINES): self.primitiveType = GL.GL_LINES elif type: if self.fixedLength > viewerConst.MINIMUM_LENGTH[type]: self.primitiveType = type else: self.fixedLength = viewerConst.NO self.primitiveType = GL.GL_LINE_STRIP else: self.primitiveType = GL.GL_LINE_STRIP def Draw(self): c = self.vertexSet.vertices.array if len(c)==0: return GL.glDisable(GL.GL_LIGHTING) if self.materials[GL.GL_FRONT]: mat = self.materials[GL.GL_FRONT] binding = self.materials[GL.GL_FRONT].binding[mat.diff] else: binding = viewerConst.OVERALL if binding == viewerConst.INHERIT: for i in xrange(c.shape[0]): #loop over lines GL.glPushName(i) GL.glBegin(self.primitiveType) for v in c[i]: #GL.glVertex3dv(v.tolist()) #gllib.glVertex3dv(v) gllib.glVertex3fv(v) GL.glEnd() GL.glPopName() elif binding == viewerConst.OVERALL: if self.materials[GL.GL_FRONT]: col = mat.prop[mat.diff][0] GL.glColor4fv(col) for i in xrange(c.shape[0]): #loop over lines GL.glPushName(i) GL.glBegin(self.primitiveType) for v in c[i]: #GL.glVertex3dv(v.tolist()) #gllib.glVertex3dv(v) gllib.glVertex3fv(v) GL.glEnd() GL.glPopName() elif binding == viewerConst.PER_VERTEX: if self.materials[GL.GL_FRONT]: col = mat.prop[mat.diff] vi = 0 for i in xrange(c.shape[0]): GL.glPushName(i) GL.glBegin(self.primitiveType) for v in c[i]: GL.glColor4fv(col[vi]) vi = vi + 1 #GL.glVertex3dv(v.tolist()) #gllib.glVertex3dv(v) gllib.glVertex3fv(v) GL.glEnd() GL.glPopName() elif binding == viewerConst.PER_PART: # i.e. line if self.materials[GL.GL_FRONT]: col = mat.prop[mat.diff] for i in xrange(c.shape[0]): GL.glColor4fv(col[i]) GL.glPushName(i) GL.glBegin(self.primitiveType) for v in c[i]: #GL.glVertex3dv(v.tolist()) #gllib.glVertex3dv(v) gllib.glVertex3fv(v) GL.glEnd() GL.glPopName() #glEnable(GL_LIGHTING) if self.viewer is not None: self.viewer.enableOpenglLighting() return True mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Ellipsoids.py0000644000175000017500000004775611162263332022370 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Authors: Michel F. SANNER, Daniel Stoffler # # sanner@scripps.edu # stoffler@scripps.edu # # Copyright: M. Sanner, Daniel Stoffler TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Ellipsoids.py,v 1.38 2009/03/24 23:03:54 vareille Exp $ # # $Id: Ellipsoids.py,v 1.38 2009/03/24 23:03:54 vareille Exp $ # import warnings import numpy.oldnumeric as Numeric, math from opengltk.OpenGL import GL, GLU from opengltk.extent.utillib import glDrawSphereSet, extractedGlutSolidSphere from DejaVu.Geom import Geom import DejaVu.datamodel as datamodel import DejaVu.viewerConst as viewerConst from DejaVu.viewerFns import checkKeywords from DejaVu.colorTool import glMaterialWithCheck, resetMaterialMemory class Ellipsoids(Geom): """Class for sets of spheres""" if glDrawSphereSet: fastSpheres = 1 else: fastSpheres = 0 keywords = Geom.keywords + [ 'centers', 'quality', 'scaling', 'orientation', 'slices', 'stacks' ] def __init__(self, name=None, check=1, **kw): v = kw.get('centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init elif not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set self.culling = GL.GL_BACK self.inheritCulling = 0 self.frontPolyMode = GL.GL_FILL self.inheritFrontPolyMode = viewerConst.NO self.lighting = viewerConst.YES self.slices = 5 self.stacks = 5 self.templateDSPL = None # (displayList, openglContext) self.radius = 1.0 apply( Geom.__init__, (self, name, check), kw ) assert len(self.vertexSet.vertices.ashape)==2 self._modified = False def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = 0 # Exceptionnaly this has to be before the call to Geom.Set v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init # Exceptionnaly this has to be before the call to Geom.Set # because we want to override the treatment of it by Geom.Set invertNormals = kw.get('invertNormals') if invertNormals is not None: kw.pop('invertNormals') if self.invertNormals != invertNormals: self.invertNormals = invertNormals self.chooseTemplate() redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= apply( Geom.Set, (self, check, 0), kw) if hasattr(self.vertexSet, 'scaling') is False: self.vertexSet.scaling = datamodel.ScalarProperties('scaling', shape=(0,3), datatype=viewerConst.FPRECISION) if hasattr(self.vertexSet, 'orientation') is False: self.vertexSet.orientation = datamodel.ScalarProperties('orientation', shape=(0, 4,4), datatype=viewerConst.FPRECISION) scal = kw.get( 'scaling') if scal != None: self.scaling = Numeric.array(scal).astype('f') self.scaling.shape = (-1, 3) redoFlags |= self._redoFlags['redoDisplayListFlag'] orient = kw.get( 'orientation') if orient != None: self.orientation = Numeric.array(orient).astype('f') self.orientation.shape = (-1, 4, 4) redoFlags |= self._redoFlags['redoDisplayListFlag'] qual = kw.get( 'quality') if qual != None: if qual > 2: self.slices = qual self.stacks = qual if self.templateDSPL is not None: redoFlags |= self._redoFlags['redoTemplateFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] slices = kw.get( 'slices') if slices != None: if slices > 2: self.slices = slices if self.templateDSPL is not None: redoFlags |= self._redoFlags['redoTemplateFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] stacks = kw.get( 'stacks') if stacks != None: if stacks > 2: self.stacks = stacks if self.templateDSPL is not None: redoFlags |= self._redoFlags['redoTemplateFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def Add(self, check=1, redo=1, **kw): """Add spheres""" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) v = kw.get( 'centers') if v: kw['vertices'] = v # rename centers in vertices for Geom.__init apply( Geom.Add, (self,0,0), kw) if self.viewer and redo: if self.redoDspLst: self.viewer.objectsNeedingRedo[self] = None # self.RedoDisplayList() def deleteTemplate(self): #print "Ellipsoids.deleteTemplate" # it is asumed the right OpenGL context is active assert self.templateDSPL is not None currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if currentcontext != self.templateDSPL[1]: import traceback;traceback.print_stack() warnings.warn('deleteTemplate failed because the current context is the wrong one') print "currentcontext != self.templateDSPL[1]", currentcontext, self.templateDSPL[1] else: #print '-%d'%self.templateDSPL[0], currentcontext, "glDeleteLists Ellipsoids" #print '-%d'%(self.templateDSPL[0]+1), currentcontext, "glDeleteLists Ellipsoids" #print '-%d'%(self.templateDSPL[0]+2), currentcontext, "glDeleteLists Ellipsoids" GL.glDeleteLists(self.templateDSPL[0], 3) self.templateDSPL = None def makeTemplate(self): #print "Ellipsoids.makeTemplate" # it is asumed the right OpenGL context is active assert self.templateDSPL is None lFirstList = GL.glGenLists(3) #print "lFirstList Ellipsoids.makeTemplate", lFirstList, self.name lCurrentContext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') self.templateDSPL = ( lFirstList, lCurrentContext ) GL.glNewList(lFirstList+1, GL.GL_COMPILE) #print '+%d'%(lFirstList+1), lCurrentContext, "glNewList Ellipsoids1" extractedGlutSolidSphere(1, self.slices, self.stacks, 0) #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Ellipsoids1" GL.glEndList() GL.glNewList(lFirstList+2, GL.GL_COMPILE) #print '+%d'%(lFirstList+2), lCurrentContext, "glNewList Ellipsoids2" extractedGlutSolidSphere(1, self.slices, self.stacks, 1) #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Ellipsoids2" GL.glEndList() self.chooseTemplate() def redoTemplate(self): self.deleteTemplate() self.makeTemplate() def chooseTemplate(self): GL.glNewList(self.templateDSPL[0], GL.GL_COMPILE) #print '+%d'%self.templateDSPL[0], "glNewList Ellipsoids0" if self.invertNormals: #print "GLU_INSIDE reversed normals" #print '#%d'%(self.templateDSPL[0]+2), "glCallList Ellipsoids2" GL.glCallList(self.templateDSPL[0]+2) else: #print "GLU_OUTSIDE regular normals" #print '#%d'%(self.templateDSPL[0]+1), "glCallList Ellipsoids1" GL.glCallList(self.templateDSPL[0]+1) #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Ellipsoids0" GL.glEndList() def Draw(self): """ Draw function of the geom return status 0 or 1 If you want fast rendering, you need to set self.templateDSPL using MakeTemplate. """ #print "Ellipsoids.Draw" assert self.templateDSPL is not None currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if currentcontext != self.templateDSPL[1]: warnings.warn("""draw failed because the current context is the wrong one""") #print "currentcontext != self.templateDSPL[1]", currentcontext, self.templateDSPL[1] return 0 centers = self.vertexSet.vertices.array if len(centers) == 0: return scaling = self.scaling orientation = self.orientation vertices = self.vertexSet.vertices.array if len(vertices) != len(scaling) or len(vertices) != len(orientation): return if self.inheritMaterial: fp = None bp = None else: fp = self.materials[GL.GL_FRONT] if not self.frontAndBack: bp = self.materials[GL.GL_BACK] face = GL.GL_FRONT else: bp = None face = GL.GL_FRONT_AND_BACK for i in xrange(len(vertices)): GL.glPushName(i) if fp: for m in (0,1,2,3,4): if fp.binding[m] != viewerConst.OVERALL: glMaterialWithCheck( face, viewerConst.propConst[m], fp.prop[m][i] ) if bp: for m in (0,1,2,3,4): if bp.binding[m] != viewerConst.OVERALL: glMaterialWithCheck( face, viewerConst.propConst[m], bp.prop[m][i] ) GL.glPushMatrix() GL.glTranslatef(float(vertices[i][0]), float(vertices[i][1]), float(vertices[i][2])) GL.glMultMatrixf( orientation[i].ravel() ) GL.glScalef(float(scaling[i][0]), float(scaling[i][1]), float(scaling[i][2])) #print '#%d'%self.templateDSPL[0], "glCallList Ellipsoids0" GL.glCallList(self.templateDSPL[0]) GL.glPopMatrix() GL.glPopName() return True def asIndexedPolygons(self, run=1, quality=None, **kw): """ run=0 returns 1 if this geom can be represented as an IndexedPolygon and None if not. run=1 returns the IndexedPolygon object.""" if run==0: return 1 # yes, I can be represented as IndexedPolygons if quality is None: quality = 2 # get centers centers = self.vertexSet.vertices.array # get radii if self.oneRadius == viewerConst.NO: radii = self.vertexSet.radii.array else: radii = Numeric.ones( centers.shape[0] ) * self.radius # create template sphere S = TriangulateIcosByEdgeCenterPoint(quality=quality) tmpltVertices = S.getVertices(quality=quality) tmpltFaces = S.getFaces(quality=quality) tmpltNormals = S.getVNormals(quality=quality) # these lists will store the data for the new spheres vertices = [] faces = [] normals = [] # loop over spheres for i in range(len(centers)): vert = Numeric.array(tmpltVertices[:])*radii[i] + centers[i] vertices.extend(list(vert)) fac = Numeric.array(tmpltFaces[:]) + i*len(tmpltVertices) faces.extend(list(fac)) norm = Numeric.array(tmpltNormals[:]) normals.extend(list(norm)) from DejaVu.IndexedPolygons import IndexedPolygons sphGeom = IndexedPolygons("sph", vertices=Numeric.array(vertices), faces=faces, vnormals=Numeric.array(normals), visible=1, invertNormals=self.invertNormals) # copy Spheres materials into sphGeom matF = self.materials[GL.GL_FRONT] matB = self.materials[GL.GL_BACK] sphGeom.materials[GL.GL_FRONT].binding = matF.binding[:] sphGeom.materials[GL.GL_FRONT].prop = matF.prop[:] sphGeom.materials[GL.GL_BACK].binding = matB.binding[:] sphGeom.materials[GL.GL_BACK].prop = matB.prop[:] if sphGeom.materials[GL.GL_FRONT].binding[1] == viewerConst.PER_VERTEX: newprop = [] index = 0 cnt = 0 for i in range(len(vertices)): newprop.append(sphGeom.materials[GL.GL_FRONT].prop[1][index]) cnt = cnt + 1 if cnt == len(tmpltVertices): index = index + 1 cnt = 0 sphGeom.materials[GL.GL_FRONT].prop[1] = newprop return sphGeom class TriangulateIcos: """Base class to compute vertices, faces and normals of a sphere based on icosahedral subdivision. Subclassed will implement different subdivision methods. A quality can be passed to the constructur which will trigger the precomputation of spheres of quality 0 to quality. To access the data, use getVertices(quality=val), getFaces(quality=val), getVNormals(quality=val) where val is the quality level """ def __init__(self, quality=None): if quality is None: quality = 5 # set default to 5 self.quality = quality self.vertices=[] # stores vertices # face lists are created dynamically later on # normals == vertices X = 0.525731112119133606 # X coord Z = 0.850650808352039932 # Y coord # build initial icosahedron (lowest quality) self.vertices = [ [-X, 0., Z], [X, 0., Z], [-X, 0., -Z], [X, 0., -Z], [0., Z, X], [0., Z, -X], [0., -Z, X], [0., -Z, -X], [Z, X, 0.], [-Z, X, 0.], [Z, -X, 0.], [-Z, -X, 0.] ] self.facesQ0 = [ [11,6,0], [9,11,0], [0,6,1], [6,10,1], [9,5,2], [7,11,2], [5,3,2], [8,10,3], [5,8,3], [0,1,4], [9,4,5], [4,8,5], [7,10,6], [2,3,7], [4,1,8], [0,4,9], [8,1,10], [7,3,10], [7,6,11], [9,2,11] ] def subsample(self, vertices, faces, quality): lenF = len(faces) lenV = len(vertices) for i in xrange(lenF): v0 = vertices[faces[i][0]] v1 = vertices[faces[i][1]] v2 = vertices[faces[i][2]] self.subdivideVert(v0, v1, v2) self.subdivideFaces(faces, lenV, quality) def normalize(self, v): d = math.sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) if d == 0.0: print 'Zero length vector!' return return [v[0] / d, v[1] / d, v[2] / d] def getVertices(self, quality=0): """ has to be implemented by subclass """ pass def getVNormals(self, quality=0): """ has to be implemented by subclass """ pass def getFaces(self, quality=0): return getattr(self, 'facesQ%d'%quality) class TriangulateIcosByEdgeCenterPoint(TriangulateIcos): def __init__(self, quality=None): TriangulateIcos.__init__(self, quality) if self.quality > 0: for qu in range(1, self.quality+1): self.subsample(self.vertices, getattr(self, 'facesQ%d'%(qu-1,) ), qu) def subdivideVert(self, v0, v1, v2): # called by subsample v01 = [] v12 = [] v20 = [] for i in range(3): v01.append(v0[i] + v1[i]) v12.append(v1[i] + v2[i]) v20.append(v2[i] + v0[i]) v01=self.normalize(v01) v12=self.normalize(v12) v20=self.normalize(v20) self.vertices.append(v01) self.vertices.append(v12) self.vertices.append(v20) def subdivideFaces(self, faces, lenV, quality): # called by subsample newFaces = [] for i in xrange(len(faces)): j = i j = j * 3 f0 = faces[i][0] f1 = faces[i][1] f2 = faces[i][2] f01 = j+lenV f12 = j+lenV+1 f20 = j+lenV+2 newFaces.append([f0, f01, f20]) newFaces.append([f01, f12, f20]) newFaces.append([f01, f1, f12]) newFaces.append([f20, f12, f2]) # dynamically create a self.facesQ setattr(self, 'facesQ%d'%quality, newFaces[:]) def getVertices(self, quality=0): # the vertex list is very big, since vertices are added to this # list after every subsampling. Thus, only what is needed is returned v = 12 # vertices of icosahedron f = 20 # faces of icosahedron for i in range(quality): v = v+f*3 f = f*4 return self.vertices[:v] def getVNormals(self, quality=0): # normals == vertices self.normals = self.getVertices(quality=quality)[:] return self.normals class TriangulateIcosByFaceCenterPoint(TriangulateIcos): """ This class subdivides each face in 3 new faces by putting a center in the middle of a face triangle.""" def __init__(self, quality=None): TriangulateIcos.__init__(self, quality) if self.quality > 0: for qu in range(1, self.quality+1): self.subsample(self.vertices, getattr(self, 'facesQ%d'%(qu-1,) ), qu) def subdivideVert(self, v0, v1, v2): # called by subsample v012 = [] for i in range(3): v012.append(v0[i] + v1[i] + v2[i]) v012 = self.normalize(v012) self.vertices.append(v012) def subdivideFaces(self, faces, lenV, quality): # called by subsample newFaces = [] for i in xrange(len(faces)): f0 = faces[i][0] f1 = faces[i][1] f2 = faces[i][2] f012 = i+lenV newFaces.append([f0, f1, f012]) newFaces.append([f1, f2, f012]) newFaces.append([f2, f0, f012]) # dynamically create a self.facesQ setattr(self, 'facesQ%d'%quality, newFaces[:]) def getVertices(self, quality=0): # the vertex list is very big, since vertices are added to this # list after every subsampling. Thus, only what is needed is returned v = 12 # vertices of icosahedron f = 20 # faces of icosahedron for i in range(quality): v = v+f f = f*3 return self.vertices[:v] def getVNormals(self, quality=0): # normals == vertices return self.getVertices(quality=quality) ## import numpy.oldnumeric as N ## rotcrn = N.array( [ ## [0.62831, -0.67899, -0.37974, 0], ## [0.36979, 0.69011, -0.62210, 0], ## [0.68446, 0.25045, 0.68468, 0], ## [0, 0, 0, 1]], 'f') ## transcrn = [9.26883, 9.78728, 6.96709] ## scalecrn = [8.0957, 11.7227, 16.2550] ## rotcv = N.identity(4, 'f') ## transcv = [0.,0.,0.] ## scalecv = [7.8895, 5.5336, 3.3147] ## from DejaVu.Ellipsoids import Ellipsoids ## el1 = Ellipsoids('ellipsoids1', centers=[transcv,transcrn], ## scaling = [scalecv, scalecrn], ## orientation = [rotcv, rotcrn], ## materials=[[1,0,0],[0,1,0]], inheritMaterial=0, ## quality=30) ## mv.GUI.VIEWER.AddObject(el1) ## USING A SPHERE FOR 1 ELLIPSOID #from DejaVu.Spheres import Spheres #s = Spheres('ellipsoid1', vertices=[[0.,0.,0.]], radii=[1.], quality=30) #mv.GUI.VIEWER.AddObject(s) #s.setMatrixComponents( rotcrn, transcrn, scalecrn) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Common2d3dObject.py0000644000175000017500000004040412102555335023276 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: October 2006 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # # Revision: # ######################################################################### # # $Header$ # # $Id$ # # modified by Stefano Forli 2009 import types import numpy.oldnumeric as Numeric import warnings from opengltk.OpenGL import GL from DejaVu.viewerFns import checkKeywords class Common2d3dObject: """Base Class inherited by Insert2d and Geom """ keywords = [ 'immediateRendering', # set to 1 to avoid using dpyList 'listed', # 0/1 when set geometry appears in object list 'name', 'needsRedoDpyListOnResize', 'pickable', 'protected', # 0/1 when set geometry cannot be deleted 'replace', 'tagModified', # use False to avoid toggling _modified 'visible', 'animatable' ] _redoFlags = { 'redrawFlag' : 1, 'updateOwnGuiFlag' : 2, 'redoViewerDisplayListFlag' : 4, 'redoDisplayListFlag' : 8, 'redoTemplateFlag' : 16, 'redoDisplayChildrenListFlag' : 32 } def __init__(self, name='Common2d3dObject', check=1, **kw): """Constructor """ #self.newList = GL.glGenLists(1) self.name = name self.viewer = None self.immediateRendering = False self.needsRedoDpyListOnResize = False self.protected = False # False == not protected against deletion self.replace = True # this is used to store in a geometry the # desired behavior when adding the geom to the Viewer. # in AddObject, if replace is not specified, geom.replace will be # used self.isExpandedInObjectList = 1 # set to 1 when children of that geom # are visible in ViewerGUI object list self.parent = None # parent object self.fullName = name # object's name including parent's name self.children = [] # list of children self.listed = True # When true the name of this object appears # in the GUI's object self.pickable = True # when set the object can be picked self.pickNum = 0 self.dpyList = None # display list for drawing self.pickDpyList = None # display list for picking # FIXME: quick hack. Flag set by SetCurrentXxxx. When set object's # transformation and material are saved in log file self.hasBeenCurrent = False self.depthMask = 1 # 0: zbuffer is readOnly for transparent objects # 1: zbuffer is read write for transparent objects self.srcBlendFunc = GL.GL_SRC_ALPHA #self.dstBlendFunc = GL.GL_ONE #GL.GL_ONE_MINUS_SRC_COLOR # ONE_MINUS_SRC_ALPHA works for colorMapEditor self.dstBlendFunc = GL.GL_ONE_MINUS_SRC_ALPHA self.transparent = False #viewerConst.NO self.visible = True m = Numeric.reshape( Numeric.identity(4), (1,16) ) self.instanceMatricesFortran = m.astype('f') self.ownGui = None self.animatable = True apply( self.Set, (check, 0), kw) self._modified = False # used to decide if we should save state def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ if __debug__ and check: apply( checkKeywords, (self.name, self.keywords), kw) if self.viewer: self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'makecurrent') tagModified = kw.pop( 'tagModified', True ) assert tagModified in (True, False) self._modified = tagModified redoFlags = 0 # this allows to grab directly the correct function rather than going through the full Set function for k, v in kw.items(): if k == 'transparent': continue lFunctionName = '_set' + k[0].upper() + k[1:] if hasattr(self, lFunctionName): lFunction = getattr(self, lFunctionName) redoFlags |= lFunction(v) kw.pop(k) if len(kw) == 0: return self.redoNow(redo, updateOwnGui, redoFlags) val = kw.pop( 'name', None) if not val is None: assert type(val) == types.StringType if self.parent: # make sure name is unique amongst siblings sameName = None for o in self.parent.children: if o.name==val and o!=self: raise RuntimeError("name %s already used by child of %s geometry"%(val, self.parent.name)) oldFullName = self.fullName self.name = val self.fullName = self.BuildFullName() if self.viewer: # rename object in tree viewer self.viewer.GUI.renameObject(self, val) #self.viewer.GUI.occlusionCamera.chooser.remove(oldFullName) #self.viewer.GUI.occlusionCamera.chooser.add( (self.fullName, 'no comment available', self) ) val = kw.pop( 'protected', None) if val is not None: if val in [True, False, 0, 1]: allObjects = self.AllObjects() for obj in allObjects: obj.protected = val if self.viewer and self.viewer.GUI: if self.viewer.currentObject==self: self.viewer.SetCurrentObject(self) val = kw.pop( 'listed', None) if val is not None: if val in [True, False]: self.listed = val val = kw.pop( 'visible', None) if not val is None: if val in (True, False): if val != self.visible and self.viewer: redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] self.visible = val else: raise ValueError("visible can only be True or False") val = kw.pop( 'pickable', None) if val is not None: if val in (True, False): self.pickable = val else: raise ValueError("pickable can only be True or False") val = kw.pop( 'immediateRendering', None) if val is not None: assert val in [False,True], "only False or True are possible" self.immediateRendering = val redoFlags |= self._redoFlags['redoDisplayListFlag'] val = kw.pop( 'replace', None) if val is not None: self.replace = val val = kw.pop( 'animatable', None) if val is not None: if val in (True, False): self.animatable = val else: raise ValueError("visible can only be True or False") return self.redoNow(redo, updateOwnGui, redoFlags) def redoNow(self, redo, updateOwnGui, redoFlags, setCurrent=True): if redo and redoFlags and self.viewer: if (redoFlags & self._redoFlags['redoTemplateFlag']) != 0: self.redoTemplate() redoFlags |= self._redoFlags['redrawFlag'] if (redoFlags & self._redoFlags['redoDisplayListFlag']) != 0: if self not in self.viewer.objectsNeedingRedo.keys(): self.viewer.objectsNeedingRedo[self] = None redoFlags |= self._redoFlags['redrawFlag'] if (redoFlags & self._redoFlags['redoDisplayChildrenListFlag']) != 0: lObjectsNeedingRedo = self.viewer.objectsNeedingRedo.keys() for child in self.AllObjects(): if child not in lObjectsNeedingRedo: self.viewer.objectsNeedingRedo[child] = None redoFlags |= self._redoFlags['redrawFlag'] if (redoFlags & self._redoFlags['redoViewerDisplayListFlag']) != 0: self.viewer.deleteOpenglList() redoFlags |= self._redoFlags['redrawFlag'] if updateOwnGui is True and self.ownGui is not None \ and (redoFlags & self._redoFlags['updateOwnGuiFlag']) != 0: self.updateOwnGui() if redoFlags & self._redoFlags['redrawFlag']: self.viewer.Redraw() if setCurrent and self.viewer and self.viewer.GUI: if self.viewer.currentObject==self: # reflect changes in DejaVu GUI self.viewer.GUI.SetCurrentObject(self) return redoFlags def _Hide(self): """Transient signal handler""" self.visible = False self.viewer.deleteOpenglList() self.viewer.Redraw() def _Remove(self, a, b): """Transient signal handler""" self.protected=False self.viewer.RemoveObject(self) def getState(self, full = 1): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ state = { 'immediateRendering':self.immediateRendering, 'listed':self.listed, 'name':self.name, 'needsRedoDpyListOnResize': self.needsRedoDpyListOnResize, 'pickable':self.pickable, 'protected':self.protected, 'replace':self.replace, #'tagModified': , 'visible':self.visible, 'animatable': self.animatable } return state def getVisible(self): #print "getVisible", self.name obj = self while obj.visible: if obj.parent: obj = obj.parent else: break return obj.visible def deleteOpenglList(self): #print "Common2d3dObject.deleteOpenglList", self self.redoDspLst = 0 currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if self.dpyList is not None: if currentcontext != self.dpyList[1]: warnings.warn("""deleteOpenglList failed because the current context is the wrong one""") #print "currentcontext != self.dpyList[1]", currentcontext, self.dpyList[1] #import traceback;traceback.print_stack() else: #print '-%d'%self.dpyList[0], currentcontext,"glDeleteLists Common2d3dObject" GL.glDeleteLists(self.dpyList[0], 1) self.dpyList = None if self.pickDpyList is not None: if currentcontext != self.pickDpyList[1]: warnings.warn("""deleteOpenglList failed because the current context is the wrong one""") #print "currentcontext != self.pickDpyList[1]", currentcontext, self.pickDpyList[1] else: #print '-%d'%self.pickDpyList[0], currentcontext, "glDeleteLists Common2d3dObject2", GL.glDeleteLists(self.pickDpyList[0], 1) self.pickDpyList = None def setViewer(self, viewer, buildDisplayList): """set viewer in all children of geom object """ #print "Common2d3dObject.setViewer", self, buildDisplayList #import traceback;traceback.print_stack() assert viewer is not None self.viewer = viewer # first, we make sure the template exists for this object if it uses template if hasattr(self, 'makeTemplate') is True: if self.templateDSPL is None: viewer.currentCamera.tk.call(viewer.currentCamera._w, 'makecurrent') self.makeTemplate() if buildDisplayList: viewer.objectsNeedingRedo[self] = None for o in self.children: # set viewer in all children of geom object o.setViewer(viewer, buildDisplayList) def getDepthMask(self): return self.depthMask def BuildFullName(self): """Returns the full name of current geom """ if self.parent: return self.parent.fullName +'|'+self.name else: return self.name def LastParentBeforeRoot(self): """return the last parent of a node before the root object is reached """ obj = self #this function can be call even if the geom doesn't belong to a viewer if self.viewer is None: while obj.parent: obj = obj.parent else: while obj.parent and obj.parent!=self.viewer.rootObject: obj = obj.parent return obj def _visibleObjs(self, geom, result): if len(geom.vertexSet): result.append(geom) for child in geom.children: if child.visible: result = self._visibleObjs(child, result) return result def VisibleObjects(self): """Return a list of visible objects that contain vertices in the object sub tree. This function is recursive and respects visibility inheritence""" if not self.visible: return [] result = [] result = self._visibleObjs(self, result) return result def AllVisibleObjects(self): """Return a list of all visible children of this object in the object tree""" if not self.visible: return obj = [self] + filter(lambda x: x.visible, self.children) if len(obj) == 1: return obj oi = 1 while oi != len(obj): obj = obj + obj[oi].children oi = oi + 1 return obj def AllObjects(self): """Return a list of all children of this object in the object tree""" obj = [self] + self.children if len(obj) == 1: return obj oi = 1 while oi != len(obj): obj = obj + obj[oi].children oi = oi + 1 return obj def RedoDisplayList(self): #print "Common2d3dObject.RedoDisplayList", self if hasattr(self, 'dpyList') and self.dpyList is not None: lNewList = self.dpyList[0] else: lNewList = GL.glGenLists(1) self.viewer.deleteOpenglList() #lNewList = self.newList lContext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') #print "lNewList Common2d3dObject.RedoDisplayList", lNewList, lContext, self.name self.dpyList = ( lNewList, self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') ) GL.glNewList(self.dpyList[0], GL.GL_COMPILE) #print '+%d'%self.dpyList[0], lContext, "glNewList Common2d3dObject" if hasattr(self, 'Draw'): status = self.Draw() else: status = 0 #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList Common2d3dObject" GL.glEndList() if status == 0: self.deleteOpenglList() def DisplayFunction(self): """ display function. may be re-implemented by subclass """ #print "Common2d3dObject.DisplayFunction", self if self.dpyList is not None: currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if currentcontext != self.dpyList[1]: warnings.warn("""DisplayFunction failed because the current context is the wrong one""") #print "currentcontext != self.dpyList[1]", currentcontext, self.dpyList[1] else: #print '#%d'%self.dpyList[0], currentcontext, "glCallList Common2d3d" GL.glCallList(self.dpyList[0]) def showOwnGui(self): #print "showOwnGui", self if self.ownGui is None: self.createOwnGui() if self.ownGui.winfo_ismapped() == 0: self.ownGui.deiconify() self.ownGui.lift() def hideOwnGui(self): #print "hideOwnGui", self if self.ownGui is not None \ and self.ownGui.winfo_ismapped() == 1: self.ownGui.withdraw() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/extendedSlider.py0000644000175000017500000001137607723713121023215 0ustar debiandebian############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/extendedSlider.py,v 1.6 2003/08/29 18:07:13 sophiec Exp $ # # $Id: extendedSlider.py,v 1.6 2003/08/29 18:07:13 sophiec Exp $ # import Tkinter from DejaVu.Slider import Slider import types class ExtendedSlider(Slider): #"""Composite slider which includes a simple slider # and an entry window used to set self.value """ def MoveCursor(self, event): """Callback function for left mouse button""" x = event.x - self.left self._MoveCursor(x) val = x #minType = type(self.min) val = self.min+self.cst1 * x if self.incrCanvas: val = round(val/self.incr)*self.incr val = eval(self.cursortype+'('+str(val)+')') #if minType is types.IntType: #val = int(val) if valself.max: val = self.max self.contents.set(val) def _FixedMoveCursor(self, x): """move cursor to new position which is typed into the entry window""" # compute the new value val = x #valType = type(val) if self.incrCanvas: val = round(val/self.incr)*self.incr val = eval(self.cursortype+'('+str(val)+')') #if valType is types.IntType: #val = int(val) if valself.max: val = self.max # check if redraw and callback are needed if self.val != val: self.val = val self.DrawCursor() if self.immediate: self.Callbacks() def set(self, val, update=1): """Set Both the cursor and entry window""" if valself.max: val = self.max if self.incrCanvas: val = round(val/self.incr)*self.incr self.val = val self.DrawCursor() if update: self.Callbacks() self.contents.set(val) return self.val def isOn(self): if self.onButton: return self.entrylabel.get() else: return 1 def on_cb(self, event=None): if self.onTk.get(): self.enable() else: self.disable() def disable(self): self.onTk.set(0) self.entry.configure(state='disabled', bg='#AAAAAA') self.draw.unbind( "<1>") self.draw.unbind( "" ) self.draw.unbind( "" ) def enable(self): self.onTk.set(1) self.entry.configure(state='normal', bg='#CC9999') self.draw.bind( "<1>", self.MoveCursor) self.draw.bind( "", self.MoveCursor) self.draw.bind( "", self.MouseUp) def __init__(self, master=None, label=None, minval=0.0, maxval=100.0, incr=None, init=None, width=150, height=20, withValue=1, immediate=0, left=10, right=10, entrytext = None , textvariable=None, sd='top', labelformat = '%4.2f', cursortype = 'float', onButton=0, lookup=None): self.entrytext = entrytext try: Slider.__init__(self, master, label, minval,maxval, incr, init, width, height, withValue, immediate,left, right, labelformat, cursortype, lookup ) except ValueError: print "problem w/Slider.__init__" self.onButton = onButton if onButton: self.onTk = Tkinter.IntVar() self.onTk.set(1) self.entrylabel = Tkinter.Checkbutton( self.frame, text=self.entrytext, variable=self.onTk, command=self.on_cb) self.entrylabel.pack(side=sd, before=self.draw, anchor='w') else: self.entrylabel = Tkinter.Label(self.frame) self.entrylabel.pack(side=sd, before=self.draw, anchor='w') self.entrylabel.config(text=self.entrytext) self.entry = Tkinter.Entry(self.frame, width=4, bg='#CC9999') self.entry.pack(side=sd, after=self.draw) if textvariable: self.contents = textvariable else: self.contents = Tkinter.StringVar() if not init: init = minval self.contents.set(init) self.entry.config(textvariable=self.contents) self.entry.bind('', self.setval) def setval(self, event): """Bound to Button-1""" try: newx=float(self.contents.get()) self._FixedMoveCursor(newx) self.Callbacks() except ValueError: print "numerical values only!" self.contents.set('') if __name__ == '__main__': def MyCallback(color): print color def MyCallback2(color): print 'hello' exsl1 = ExtendedSlider(None, label='EntryLabel ', height=40, minval=0.1, maxval = 10.0, init=5.0, sd='left') exsl1.frame.pack() exsl1.AddCallback(MyCallback) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/states.py0000644000175000017500000001112611536015270021543 0ustar debiandebiandef getRendering(viewer, checkAnimatable=False): """ build and return a dictionary storing the state of all geometries renderingDict <- getRendering(viewer) """ statesMem = {} for g in viewer.rootObject.AllObjects(): if checkAnimatable: if not g.animatable: continue state = g.getState(full=1) if state.has_key('rotation'): del state['rotation'] if state.has_key('translation'): del state['translation'] if state.has_key('scale'): del state['scale'] if state.has_key('pivot'): del state['pivot'] del state['name'] if g.parent is not None and g.parent.visible == 0: state['visible'] = 0 #add clipping planes info clip = [] if hasattr(g, 'clipP'): for cp in g.clipP: clip.append([cp.num, g.clipSide[cp.num], False]) for cp in g.clipPI: clip.append([cp.num, g.clipSide[cp.num], True]) state['clipPlanes'] = clip statesMem[g.fullName] = state # get Camera state: cam = viewer.currentCamera state = {#'height':cam.height, 'width':cam.width, 'near':cam.near, 'far':cam.far, 'color':cam.backgroundColor, 'antialiased':cam.antiAliased, 'boundingbox':cam.drawBB, 'rotation':list(cam.rotation), 'translation':list(cam.translation), 'scale':list(cam.scale), 'pivot':list(cam.pivot), 'direction':list(cam.direction), 'lookAt':list(cam.lookAt), 'projectionType': cam.projectionType, 'drawThumbnail':cam.drawThumbnailFlag, 'contours': cam.contours} statesMem['camera'] = state # get light state for i,l in enumerate(viewer.lights): if not l._modified: continue statesMem['light%d'%i] = l.getState() for i,c in enumerate(viewer.clipP): if not c._modified: continue statesMem['clipplane%d'%i] = c.getState() return statesMem from opengltk.OpenGL import GL def setRendering( viewer, rendering, redraw=False): """ restore a given rendering for a viewer None <- setRendering( viewer, rendering) """ old = viewer.suspendRedraw viewer.suspendRedraw = True for g in viewer.rootObject.AllObjects(): if not rendering.has_key(g.fullName): g.Set(visible = 0) else: vis = rendering[g.fullName].get('visible', None) if vis == 0: g.Set(visible = 0) else: tmp = rendering[g.fullName].copy() mat = tmp.pop('rawMaterialF', None) if mat: g.materials[GL.GL_FRONT].Set(**mat) mat = tmp.pop('rawMaterialB', None) if mat: g.materials[GL.GL_BACK].Set(**mat) if tmp.has_key('clipPlanes'): tmp.pop('clipPlanes') g.Set( **tmp ) cam = viewer.currentCamera if rendering.has_key('camera'): cam.Set(**rendering['camera']) viewer.suspendRedraw = old if redraw: viewer.OneRedraw() def setObjectRendering(viewer, object, rendering): if not rendering: return tmp = rendering.copy() mat = tmp.pop('rawMaterialF', None) if mat: object.materials[GL.GL_FRONT].Set(**mat) mat = tmp.pop('rawMaterialB', None) if mat: object.materials[GL.GL_BACK].Set(**mat) if tmp.has_key('clipPlanes'): tmp.pop('clipPlanes') object.Set( **tmp ) def getOrientation( geom , camera=True): """ build and return a dictionary storing the orientation for geom orientDict <- getOrientation( geom ) """ orientMem = {} orientMem['rotation'] = geom.rotation[:] orientMem['translation'] = geom.translation.copy() orientMem['scale'] = geom.scale[:] orientMem['pivot'] = geom.pivot[:] if camera: cam = geom.viewer.currentCamera orientMem['fieldOfView'] = cam.fovy orientMem['lookFrom'] = cam.lookFrom.copy() return orientMem def setOrientation(geom, orient): """ restore a given orientation for a geometry and viewer None <- setOrientation( geom, orient) """ geom.Set(rotation=orient['rotation'], translation=orient['translation'], scale=orient['scale'], pivot=orient['pivot']) if orient.has_key('fieldOfView'): geom.viewer.currentCamera._setFov(orient['fieldOfView']) if orient.has_key('lookFrom'): geom.viewer.currentCamera._setLookFrom(orient['lookFrom']) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/gui/0000755000175000017500000000000012146210040020437 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/gui/AnimationPlayer.py0000644000175000017500000003645410507037506024136 0ustar debiandebian############################################################################# # # Author: Alexandre T. GILLET # # TSRI 2003 # ############################################################################# # # # $Header # # $Id # # # # import string, math,time from mglutil.gui.BasicWidgets.Tk.player import Player from mglutil.gui.InputForm.Tk.gui import InputFormDescr,InputForm,CallBackFunction from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser from DejaVu.gui.geomsChooser import geomsChooser import Pmw,Tkinter import types class AnimPlayer(Player,geomsChooser): """ provide a player to display/undisplay DejaVu object in a cylce making a animation. viewer: DejaVu viewer height,width are the property of the player gui startFrame: frame to begin endFrame: last frame to display stepSize: step between new frame playMode: #playMode options: # 0 play once and stop # 1 play continuously in 1 direction # 2 play once in 2 directions # 3 play continuously in 2 directions titleStr: title of the gui windows counter: gui with a counter on or not gui: #1 show the player gui #0 player gui not display framerate =15. # number of frame per second to be display """ def __init__(self,viewer, master=None, root=None, height=80,width=200, currentFrameIndex=0, startFrame=0, endFrame=0, maxFrame=0, stepSize=1, playMode=1, titleStr='AnimPlayer', counter = 1, gui=1,framerate=15.): if master is None: master = Tkinter.Toplevel() # viewer from which we get the geom to animate self.viewer = viewer # frame list, is a list of geom . # each frame is made of n DejaVu object to be display # it a list of tuple, each tuple is a {} and [] # {} is: {'objname':['geom1','geom2'],'objname':['geom1','geom2']} # [] is list of DejaVu object per frame self.framelist=[] Player.__init__(self, master=master,root=root,height=height, width=width,currentFrameIndex=currentFrameIndex, startFrame=startFrame,endFrame=endFrame, maxFrame=maxFrame,stepSize=stepSize, playMode=playMode,titleStr=titleStr,counter=counter, gui=gui,framerate=framerate) def nextFrame(self, id): """ id: index number of the frame to display. undisplay object from previous frame, display object of new frame. """ if not self.framelist:return id = int(id) if id >=len(self.framelist):return i = self.currentFrameIndex ## undisplay previous object frame = self.framelist[i] for obj in frame[1]: obj.Set(visible=0,redo=0) if self.hasCounter and self.gui: self.form.ent2.delete(0,'end') self.form.ent2.insert(0, str(id)) ## display new frame currentframe = self.framelist[id] for obj in currentframe[1]: obj.Set(visible=1,redo=0) self.viewer.deleteOpenglList() self.viewer.Redraw() self.currentFrameIndex = id ##################################################################### #### Animation Setting the frame def SetAnim_cb(self): self.showForm() def showForm(self): """create formdescr for setAnim form to set the animation: each frame is a list of geom to display """ entryFrame = [] for i in range(len(self.framelist)): val = 'frame_'+str(i) entryFrame.append((val,)) if not hasattr(self,'form_Setanim'): ifd = InputFormDescr(title="SetAnimation") ifd.append({'widgetType':ListChooser, 'name':'availableGeom', 'tooltip':'geom available in viewer', 'wcfg':{'mode':'extended', 'lbwcfg':{'exportselection':1}, 'command':[(self.toggleExpansion,'')], 'commandEvent':None, 'title':'availableGeom'}, 'gridcfg':{'row':0,'column':0, 'sticky':'wens','rowspan':3}}) ifd.append({'name':'newframe', 'widgetType':Tkinter.Button, 'tooltip':""" Add an empty frame to the animation""", 'wcfg':{'text':'NewFrame','command':self.addframe_cb}, 'gridcfg':{'row':0,'column':1,'rowspan':1 }}) ifd.append({'name':'add', 'widgetType':Tkinter.Button, 'tooltip':""" Add the selected geom to selected frame""", 'wcfg':{'text':'AddGeom','command':self.add_cb}, 'gridcfg':{'row':1,'column':1,'rowspan':1 }}) ifd.append({'name':'geomtoload', 'widgetType':ListChooser, 'tooltip':"""list of frame the user chose to apply to the pattern""", 'wcfg':{'entries':entryFrame, 'mode':'extended', 'lbwcfg':{'exportselection':0}, 'title':'Frame(geom) to be display'}, 'gridcfg':{'sticky':'we', 'row':0, 'column':2,'rowspan':3}}) ifd.append({'name':'remove', 'widgetType':Tkinter.Button, 'tooltip':""" Remove the selected entry from the commands to be applied to the object when loaded in the application""", 'wcfg':{'text':'REMOVE','width':10, 'command':self.remove_cb}, 'gridcfg':{'sticky':'we','row':0, 'column':3}}) ifd.append({'name':'oneup', 'widgetType':Tkinter.Button, 'tooltip':"""Move the selected entry up one entry""", 'wcfg':{'text':'Move up','width':10, 'command':self.moveup_cb}, 'gridcfg':{'sticky':'we','row':1,'column':3}}) ifd.append({'name':'onedown', 'widgetType':Tkinter.Button, 'tooltip':"""Move the selected entry down one entry""", 'wcfg':{'text':'Move down','width':10, 'command':self.movedown_cb}, 'gridcfg':{'sticky':'we','row':2,'column':3}}) self.form_Setanim = InputForm(self.master,None,descr=ifd, scrolledFrame=0) self.lc = self.form_Setanim.descr.entryByName['availableGeom']['widget'] self.lc2 = self.form_Setanim.descr.entryByName['geomtoload']['widget'] self.addObject(self.viewer.rootObject,None) val = self.form_Setanim.go() if val: self.assign() self.form_Setanim.withdraw() else: self.form_Setanim.deiconify() val = self.form_Setanim.go() if val: self.assign() self.form_Setanim.withdraw() def deleteAnim(self): """ Delete all frame from the player list.""" self.Stop_cb() self.startFrame=0 self.endFrame = -1 self.maxFrame = 0 self.targetFrame = self.endFrame self.target = self.endFrame self.currentFrameIndex =0 def assign(self,list=None): """ assign the animation. framelist ; list of {} return a list of obj for each frame """ self.deleteAnim() AllObjects = self.viewer.rootObject.AllObjects() if list : self.framelist=[] for f in list: self.framelist.append((f,[])) print "assign" print "self.framelist",self.framelist for frame in self.framelist: geomDic = frame[0] Namelist=[] for parents in geomDic.keys(): parentlist = filter(lambda x, name=parents:x.name == name,AllObjects) obj = parentlist[0] childrens = geomDic[obj.name] if len(childrens) > 0: for namegeom in childrens: child = filter(lambda x, name=namegeom:x.name == name, obj.children)[0] if child.children != []: for c in child.children: frame[1].append(c) else: frame[1].append(child) else: frame[1].append(obj) self.endFrame = self.endFrame +1 self.maxFrame = self.maxFrame +1 self.targetFrame = self.endFrame self.target = self.endFrame def movedown_cb(self): """ move entry one down """ sel = self.lc2.get() index = self.lc2.getInd() if not sel: return sel = sel[0] if string.find(sel,"frame") < 0: return # get frame Index frameInd = int(string.split(sel,'_')[1]) currentframe = self.framelist[frameInd] if (frameInd + 1) >= len(self.framelist):return # select next Frame. nextframe = self.framelist[frameInd+1] # move current frame one down in list self.framelist[frameInd] =nextframe self.framelist[frameInd+1] =currentframe self.updatelistchooser(self.framelist) def moveup_cb(self): """ move entry one up """ sel = self.lc2.get() index = self.lc2.getInd() if not sel: return sel = sel[0] if string.find(sel,"frame") < 0: return # get frame Index frameInd = int(string.split(sel,'_')[1]) currentframe=self.framelist[frameInd] if (frameInd - 1) < 0 :return # select previous Frame prevframe = self.framelist[frameInd-1] # move current frame one up in list self.framelist[frameInd] =prevframe self.framelist[frameInd-1] =currentframe self.updatelistchooser(self.framelist) def addframe_cb(self): """ add a new frame entry""" frame = ({},[]) nb = len(self.framelist) #frame.number = nbframe value = 'frame_'+ str(nb) self.framelist.append(frame) self.lc2.deselect(0,last='end') self.lc2.insert('end',value) self.lc2.select('end') def add_cb(self): listgeom=[] # get the frame index to add new geom if len(self.lc2.entries)>0: ind = self.lc2.getInd() if len(ind) ==0:return # no entry selected so create a new frame # get geom name to load o = map(int,self.lc.lb.curselection()) for Ind in o: fullName = self.getFullName(Ind) listgeom.append(fullName) # get frame instance for index in ind: value = self.lc2.entries[index][0] if string.find(value,"frame") < 0: return frameInd = int(string.split(value,'_')[1]) frameGeom = self.framelist[frameInd][0] for geom in listgeom: # strip the root l = string.split(geom,'|') if not frameGeom.has_key(l[1]): frameGeom[l[1]]=[] for i in l[2:]: if not( i in frameGeom[l[1]]): frameGeom[l[1]].append(i) self.updatelistchooser(self.framelist) else: return def updatelistchooser(self,entry): """ update what is display in the list chooser """ # save current selection sel = self.lc2.get() # remove current entry self.lc2.clear() prefix = '~' prefix2 = '~~' nb= 0 for e in entry: v = 'frame_'+str(nb) nb = nb+1 # listchooser entry has to be a tuple(value,comment) self.lc2.add((v,)) for mol in e[0].keys(): self.lc2.add((prefix+mol,)) for geom in e[0][mol]: self.lc2.add((prefix2+geom,)) # select the entry save as sel # keep the entry selected after the update for i in sel: self.lc2.select((i,)) def findFramefromGeomInd(self,index): """ return the frame number from which the geom was selected """ for i in range(index+1): value = self.lc2.entries[index-i][0] if string.find(value,"frame") >= 0: frameInd = int(string.split(value,'_')[1]) lcInd = index -i return (frameInd,lcInd) return 0 def findParentGeom(self,index): """ find the parent value name from a geom ~~ go up to find first value with onley ~ """ parent = None for i in range(index+1): parent = self.lc2.entries[index -i][0] if parent[0] == '~' and parent[1] !='~': parent = parent[1:] return parent return None def removeEntryGeom(self,value,index): """ the geom entry in the listchooser""" # first find from which frame we need to remove geom val = self.findFramefromGeomInd(index) if val: frameInd =val[0] lcInd = val[1] if value[1] == '~': parent = self.findParentGeom(index) if parent: listgeom = self.framelist[frameInd][0][parent] rindex = listgeom.index(value[2:]) del listgeom[rindex] elif self.framelist[frameInd][0].has_key(value[1:]): del self.framelist[frameInd][0][value[1:]] self.updatelistchooser(self.framelist) def removeEntryFrame(self,value,index): """ remove the frame entry in the listchooser""" # delete frame from framelist frameInd = int(string.split(value,'_')[1]) del self.framelist[frameInd] # Update list chooser self.updatelistchooser(self.framelist) def remove_cb(self): """ remove entry in litschooser (geomtoload)""" selindex = self.lc2.getInd() for index in selindex: value = self.lc2.entries[index][0] if string.find(value,"frame") >= 0: self.removeEntryFrame(value,index) elif value[0] == '~': self.removeEntryGeom(value,index) ################## Animation setup end ################################# ######################################################################## mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/gui/__init__.py0000644000175000017500000000000007723713122022554 0ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/gui/geomsChooser.py0000644000175000017500000003570611205570603023472 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Alexandre T. GILLET # # TSRI 2003 # ############################################################################# # # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/gui/geomsChooser.py,v 1.14 2009/05/22 18:40:03 vareille Exp $ # # $Id: geomsChooser.py,v 1.14 2009/05/22 18:40:03 vareille Exp $ # # # # import string, math import numpy.oldnumeric as Numeric from types import IntType import Tkinter #from Tkinter import * from mglutil.gui.InputForm.Tk.gui import InputFormDescr,InputForm,CallBackFunction from mglutil.gui.BasicWidgets.Tk.customizedWidgets import ListChooser from opengltk.OpenGL import GL import Pmw import types class geomsChooser: def __init__(self,viewer): #ViewerGUI(viewer,8,2) # the viewe where the geoms are display (for us: pmv or DejaVu) if viewer is None: return self.viewer = viewer geomDic = {} dpyList = None self.assignGeom =[geomDic,dpyList] def toggleExpansion(self, event): # get a 0-based index into list of names o = self.lc.lb.nearest(event.y) fullName = self.getFullName(o) #obj = self.objectByName(self.olist.get(o)) obj = self.viewer.FindObjectByName(fullName) if obj: childGeoms = obj.AllObjects() if len(childGeoms)==1: # this geoemtry has no children return else: # this geometry has children if obj.isExpandedInObjectList: self.collapse(obj) else: self.expand(obj) def expand(self, object): # object is a geometry if object.isExpandedInObjectList: return object.isExpandedInObjectList = 1 geoms = object.children ind = self.objectIndex(object) + 1 c = self.countParents(object) + 1 prefix = '~'*c for i in range(len(geoms)): g = geoms[i] if g==object: continue if not g.listed: continue if len(g.vertexSet) == 0 and len(g.children)==0:continue self.lc.insert(ind, prefix + g.name) ind = ind + 1 def collapse(self, object): # object is a geometry, we recursively collapse the sub-tree object.isExpandedInObjectList = 0 # delete the names from the bject list widget nbChildren = self.countDecendentsInWidget(object) ind = self.objectIndex(object) + 1 for i in range(ind, ind+nbChildren): self.lc.lb.delete(ind) # toggle isExpandedInObjectList for all descendents for child in object.AllObjects(): if child.listed: child.isExpandedInObjectList = 0 def countDecendentsInWidget(self, object): # object is a geometry, we count and return the number of # decendents shown in widget ind = self.objectIndex(object) allNames = self.lc.lb.get(0,'end') nbTild = string.count(allNames[ind],'~')+1 # count children in widget nbChildren = 0 for i in range(ind+1, len(allNames)): nbt = string.count(allNames[i],'~') if nbt >= nbTild: nbChildren = nbChildren + 1 else: break return nbChildren def getFullName(self, ind): # strip the leading ~ allNames = self.lc.lb.get(0,'end') nbTild = string.count(allNames[ind],'~') fullName = allNames[ind][nbTild:] for i in range(ind-1, -1, -1): nbt, name = self.lstripChar(allNames[i], '~') if nbt >= nbTild: continue nbTild = nbt fullName = name + '|' + fullName return fullName def objectIndex(self, object): # object is a geometry and we find this object's index in the list of # names displayed in te widget. If the ibecjt is not shown we # return -1 l = self.lc.lb.get(0,'end') for i in range(len(l)): indent, n = self.lstripChar(l[i], '~') if n==object.name: break if i==len(l): return -1 else: return i def lstripChar(self, name, char): n = string.count(name,'~') return n, name[ n : ] def countParents(self, object): c = 0 while object.parent: c = c+1 object = object.parent return c def addObject(self, obj, parent): if not obj.listed: return if not parent: self.lc.insert(0,obj.name) self.lc.select(obj.name) else: if not parent.isExpandedInObjectList: return i = self.objectIndex(parent) if i==-1: return c = self.countParents(obj) prefix = '~'*c name = prefix + obj.name # now we need to skip all children already there l = self.lc.lb.get(0,'end') while 1: i = i + 1 if i==len(l): break if self.lc.get(i)[:c]!=prefix: break self.lc.insert(i, name) def getFullNameList(self,name,list,dic): """ get the list of fullName from geomDic """ for p in dic.keys(): name1 = name +'|'+p if dic[p] != {}: list = self.getFullNameList(name1,list,dic[p]) else: list.append(name1) return list def getDpyList(self,objects): """function to obtain a display list for any object in DejaVu""" from opengltk.OpenGL import GL # Draw build a display function that contains global coloring, # transformation nd all global GL properties of this objects. # we cannot use the object's display list that does not contains this # info #if len(objects) == 1 and objects[0].dpyList: # return objects[0].dpyList # transparent object need to be drawn last # reorder object so transparent object drawn last transparent =[] opaque = [] for obj in objects: if obj.transparent: #obj.isTransparent(): transparent.append(obj) else: opaque.append(obj) objlist = opaque + transparent lNewList = GL.glGenLists(1) #print "lNewList geomsChooser.getDpyList", lNewList, self.name dpyList = ( lNewList, self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') ) camera = self.mv.GUI.VIEWER.currentCamera camera.Activate() GL.glNewList(dpyList, GL.GL_COMPILE) #print "geomChooser 208", GL.glGetIntegerv(GL.GL_LIST_INDEX) for obj in objlist: if obj.immediateRendering: # or obj.hasChildWithImmediateRendering: camera.drawMode=5 camera.Draw(obj) else: camera.drawMode=2 camera.drawTransparentObjects = 0 camera.hasTransparentObjects = 0 # draw opaque object for m in obj.instanceMatricesFortran: GL.glPushMatrix() GL.glMultMatrixf(m) if len(obj.children): map( camera.Draw, obj.children) else: camera.Draw(obj) GL.glPopMatrix() # draw transparent children of object if camera.hasTransparentObjects: camera.drawTransparentObjects = 1 for m in obj.instanceMatricesFortran: GL.glPushMatrix() GL.glMultMatrixf(m) map( camera.Draw, obj.children) GL.glPopMatrix() # draw transparent object that do not have children if obj.isTransparent() and not len(obj.children): camera.drawTransparentObjects =1 for m in obj.instanceMatricesFortran: GL.glPushMatrix() GL.glMultMatrixf(m) camera.Draw(obj) GL.glPopMatrix() GL.glEndList() return dpyList def buildForm(self): ifd = InputFormDescr(title=self.ftitle) ifd.append({'widgetType':ListChooser, 'name':'availableGeom', 'tooltip':'geom available in viewer', 'wcfg':{'mode':'extended', 'lbwcfg':{'exportselection':1}, 'command':[(self.toggleExpansion,'')], 'commandEvent':None, 'title':'availableGeom'}, 'gridcfg':{'row':0,'column':0, 'sticky':'wens','rowspan':3}}) ifd.append({'name':'add', 'widgetType':Tkinter.Button, 'tooltip':""" Add the selected geom to selected frame""", 'wcfg':{'text':'>>','command':self.add_cb}, 'gridcfg':{'row':1,'column':1,'rowspan':1 }}) ifd.append({'name':'remove', 'widgetType':Tkinter.Button, 'tooltip':""" remove the selected geom to selected """, 'wcfg':{'text':'<<','command':self.remove_cb}, 'gridcfg':{'row':2,'column':1,'rowspan':1 }}) ifd.append({'name':'toload', 'widgetType':ListChooser, 'tooltip':"""list of geom the user chose to apply to the pattern""", 'wcfg':{ 'mode':'extended', 'lbwcfg':{'exportselection':0}, 'title':self.lc2title}, 'gridcfg':{'sticky':'we', 'row':0, 'column':2,'rowspan':3}}) ifd.append({'name':'clear', 'widgetType':Tkinter.Button, 'tooltip':""" Clear entry """, 'wcfg':{'text':'Clear','width':10, 'command':self.clear_cb}, 'gridcfg':{'sticky':'we','row':0, 'column':3}}) ifd.append({'name':'remove', 'widgetType':Tkinter.Button, 'tooltip':""" remove the selected geom to selected """, 'wcfg':{'text':'<<','command':self.remove_cb}, 'gridcfg':{'row':2,'column':1,'rowspan':1 }}) return ifd def showForm(self,master,geomDic=None,func=None): """create formdescr for setGeoms geomDic = a dict of Geom """ # assign a func so we can log it in Pmv # func is a Pmv command if func: self.assign_func = func if geomDic: self.assignGeom[0]=geomDic if hasattr(self,'form'): if self.guiOn: return else: self.update_lc2() self.form.deiconify() val = self.form.go() if val: geomDic =self.assignGeom[0] self.assign_func(geomDic) self.form.withdraw() else: if not master: master = Tkinter.Toplevel() master.title('GeomChooser') else: master = master ifd = self.buildForm() self.form = InputForm(master,None,descr=ifd, scrolledFrame=0, cancelCfg={'command':self.cancel_cb}) self.lc = self.form.descr.entryByName['availableGeom']['widget'] self.lc2 = self.form.descr.entryByName['toload']['widget'] self.addObject(self.viewer.rootObject,None) self.update_lc2() val = self.form.go() if val: geomDic =self.assignGeom[0] self.assign_func(geomDic) self.form.withdraw() def cancel_cb(self,event = None, func=None): """ close setup animation form without setting anything""" if hasattr(self,'geomDicCopy'): self.patDic = self.patDicCopy.copy() def add_cb(self): lgeom=[] geomDic = self.assignGeom[0] # get geom name to load o = map(int,self.lc.lb.curselection()) for Ind in o: fullName = self.getFullName(Ind) obj = self.viewer.FindObjectByName(fullName) # strip the root l = string.split(fullName,'|')[1:] for i in range(len(l)): if i==0: if not geomDic.has_key(l[i]): dic = geomDic[l[i]]={} else: dic = geomDic[l[i]] else: if not dic.has_key(l[i]): dic[l[i]]={} dic = dic[l[i]] self.update_lc2() def insertValue(self,ind,prefix,dic): """ insert Value of a dictionnary in the listchooser2""" for key in dic.keys(): if dic[key] == {}: ind = ind+1 self.lc2.insert(ind, prefix+key) else: ind =ind +1 self.lc2.insert(ind, prefix+key) p = prefix + '~' ind=self.insertValue(ind,p,dic[key]) return ind def update_lc2(self): """ update listchooser entries display""" # save current entry selected sel = self.lc2.get() prefix = '~' self.lc2.clear() ind = 0 geomDic = self.assignGeom[0] ind = self.insertValue(ind,prefix,geomDic) # select the entry save as sel # keep the entry selected after the update for i in sel: self.lc2.select((i,)) def findParentMol(self,index): """ find the parent value name from a geom ~~ go up to find first value with onley ~ """ parent = None for i in range(index+1): parent = self.lc2.entries[index -i][0] if parent[0] == '~' and parent[1] !='~': parent = parent[1:] return parent return None def remove_cb(self): """ remove entry in litschooser (geomtoload)""" geomDic = self.assignGeom[0] selindex = self.lc2.getInd() for index in selindex: value = self.lc2.entries[index][0] if value[1] == '~': mol = self.findParentMol(index) rindex = geomDic[mol].index(value[2:]) del geomDic[mol][rindex] else: mol = value[1:] del geomDic[mol] self.update_lc2() def clear_cb(self): """ clear all entry """ self.lc2.clear() if self.assignGeom: self.assignGeom[0] = {} # geomDic self.assignGeom[1] = None # dpyList mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/jitter.py0000644000175000017500000000751210651433502021544 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/jitter.py,v 1.4 2007/07/24 17:30:42 vareille Exp $ # # $Id: jitter.py,v 1.4 2007/07/24 17:30:42 vareille Exp $ # from numpy.oldnumeric import array # 2 jitter points _jitter2 = array( ( (0.246490, 0.249999), (-0.246490, -0.249999) ), 'f' ) # 3 jitter points _jitter3 = array( ( (-0.373411, -0.250550), ( 0.256263, 0.368119), ( 0.117148, -0.117570) ), 'f' ) # 4 jitter points _jitter4 = array( ( (-0.208147, 0.353730), ( 0.203849, -0.353780), (-0.292626, -0.149945), ( 0.296924, 0.149994) ), 'f' ) # 8 jitter points _jitter8 = array( ( (-0.334818, 0.435331), ( 0.286438, -0.393495), ( 0.459462, 0.141540), (-0.414498, -0.192829), (-0.183790, 0.082102), (-0.079263, -0.317383), ( 0.102254, 0.299133), ( 0.164216, -0.054399) ), 'f' ) # 15 jitter points _jitter15 = array( ( ( 0.285561, 0.188437), ( 0.360176, -0.065688), (-0.111751, 0.275019), (-0.055918, -0.215197), (-0.080231, -0.470965), ( 0.138721, 0.409168), ( 0.384120, 0.458500), (-0.454968, 0.134088), ( 0.179271, -0.331196), (-0.307049, -0.364927), ( 0.105354, -0.010099), (-0.154180, 0.021794), (-0.370135, -0.116425), ( 0.451636, -0.300013), (-0.370610, 0.387504) ), 'f' ) # 24 jitter points _jitter24 = array( ( ( 0.030245, 0.136384), ( 0.018865, -0.348867), (-0.350114, -0.472309), ( 0.222181, 0.149524), (-0.393670, -0.266873), ( 0.404568, 0.230436), ( 0.098381, 0.465337), ( 0.462671, 0.442116), ( 0.400373, -0.212720), (-0.409988, 0.263345), (-0.115878, -0.001981), ( 0.348425, -0.009237), (-0.464016, 0.066467), (-0.138674, -0.468006), ( 0.144932, -0.022780), (-0.250195, 0.150161), (-0.181400, -0.264219), ( 0.196097, -0.234139), (-0.311082, -0.078815), ( 0.268379, 0.366778), (-0.040601, 0.327109), (-0.234392, 0.354659), (-0.003102, -0.154402), ( 0.297997, -0.417965) ), 'f' ) # 66 jitter points _jitter66 = array( ( ( 0.266377, -0.218171), (-0.170919, -0.429368), ( 0.047356, -0.387135), (-0.430063, 0.363413), (-0.221638, -0.313768), ( 0.124758, -0.197109), (-0.400021, 0.482195), ( 0.247882, 0.152010), (-0.286709, -0.470214), (-0.426790, 0.004977), (-0.361249, -0.104549), (-0.040643, 0.123453), (-0.189296, 0.438963), (-0.453521, -0.299889), ( 0.408216, -0.457699), ( 0.328973, -0.101914), (-0.055540, -0.477952), ( 0.194421, 0.453510), ( 0.404051, 0.224974), ( 0.310136, 0.419700), (-0.021743, 0.403898), (-0.466210, 0.248839), ( 0.341369, 0.081490), ( 0.124156, -0.016859), (-0.461321, -0.176661), ( 0.013210, 0.234401), ( 0.174258, -0.311854), ( 0.294061, 0.263364), (-0.114836, 0.328189), ( 0.041206, -0.106205), ( 0.079227, 0.345021), (-0.109319, -0.242380), ( 0.425005, -0.332397), ( 0.009146, 0.015098), (-0.339084, -0.355707), (-0.224596, -0.189548), ( 0.083475, 0.117028), ( 0.295962, -0.334699), ( 0.452998, 0.025397), ( 0.206511, -0.104668), ( 0.447544, -0.096004), (-0.108006, -0.002471), (-0.380810, 0.130036), (-0.242440, 0.186934), (-0.200363, 0.070863), (-0.344844, -0.230814), ( 0.408660, 0.345826), (-0.233016, 0.305203), ( 0.158475, -0.430762), ( 0.486972, 0.139163), (-0.301610, 0.009319), ( 0.282245, -0.458671), ( 0.482046, 0.443890), (-0.121527, 0.210223), (-0.477606, -0.424878), (-0.083941, -0.121440), (-0.345773, 0.253779), ( 0.234646, 0.034549), ( 0.394102, -0.210901), (-0.312571, 0.397656), ( 0.200906, 0.333293), ( 0.018703, -0.261792), (-0.209349, -0.065383), ( 0.076248, 0.478538), (-0.073036, -0.355064), ( 0.145087, 0.221726) ), 'f' ) jitterList = (0,2,3,4,8,15,24,66) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/VolumeGeom.py0000644000175000017500000002532311111132470022312 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Anna Omelchenko, Michel Sanner # # Copyright: M. Sanner TSRI 2003 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/VolumeGeom.py,v 1.19 2008/11/20 00:54:16 vareille Exp $ # # $Id: VolumeGeom.py,v 1.19 2008/11/20 00:54:16 vareille Exp $ # """ Module implementing a special DejaVu geometric object - VolumeGeom. The DisplayFunction() uses volume rendering methods. """ import numpy.oldnumeric as Numeric class CropBox: def __init__(self, volgeom): self.volgeom = volgeom self.xmin = 0 #bounds of crop box self.xmax = 0 self.ymin = 0 self.ymax = 0 self.zmin = 0 self.zmax = 0 self.midx = 0 #center of crop box self.midy = 0 self.midz = 0 self.volSize = [0, 0, 0] # volume size along the 3 dimensions self.callbackFunc = [] self.crop = None self.volgeom.cropStatus = 1 def __repr__(self): return " (%d,%d,%d) x(%d,%d) y(%d,%d) z(%d,%d)" % \ (self.dx, self.dy, self.dz, self.xmin, self.xmax, self.ymin, self.ymax, self.zmin, self.zmax) def setVolSize(self, size): assert len(size)==3 self.volSize = size def setSize(self, xmin, xmax, ymin, ymax, zmin, zmax): self.xmin = xmin self.xmax = xmax self.ymin = ymin self.ymax = ymax self.zmin = zmin self.zmax = zmax def update(self): self.dx = self.xmax - self.xmin self.dy = self.ymax - self.ymin self.dz = self.zmax - self.zmin self.crop.SetSlabs( max(0, self.xmin), min(self.xmax, self.volSize[0]), max(0, self.ymin), min(self.ymax, self.volSize[1]), max(0, self.zmin), min(self.zmax, self.volSize[2])) ## self.crop.SetSlabs( self.xmin, self.xmax, self.ymin, self.ymax, ## self.zmin, self.zmax) if self.volgeom.viewer: self.volgeom.viewer.Redraw() for f in self.callbackFunc: f(self) def updateX(self): self.dx = self.xmax - self.xmin self.crop.SetXSlab(max(0, self.xmin), min(self.xmax, self.volSize[0])) if self.volgeom.viewer: self.volgeom.viewer.Redraw() for f in self.callbackFunc: f(self) def updateY(self): self.dy = self.ymax - self.ymin self.crop.SetYSlab(max(0, self.ymin), min(self.ymax, self.volSize[1])) if self.volgeom.viewer: self.volgeom.viewer.Redraw() for f in self.callbackFunc: f(self) def updateZ(self): self.dz = self.zmax - self.zmin self.crop.SetZSlab(max(0, self.zmin), min(self.zmax, self.volSize[2])) if self.volgeom.viewer: self.volgeom.viewer.Redraw() for f in self.callbackFunc: f(self) def ScaleX(self, event, matrix, transXY, transZ): if transZ<0: delta = 1 else: delta = -1 xmin = self.xmin+delta xmax = self.xmax-delta if xmin == xmax: xmax = xmin+1 if xmin < 0 : xmin = 0 if xmax > self.volSize[0]: xmax =self.volSize[0] if xmin > xmax : return self.xmin = xmin self.xmax = xmax self.updateX() def ScaleY(self, event, matrix, transXY, transZ): if transZ<0: delta = 1 else: delta = -1 ymin = self.ymin+delta ymax = self.ymax-delta if ymin == ymax: ymax = ymin+1 if ymin < 0: ymin = 0 if ymax > self.volSize[1]: ymax = self.volSize[1] if ymin > ymax : return self.ymin = ymin self.ymax = ymax self.updateY() def ScaleZ(self, event, matrix, transXY, transZ): if transZ<0: delta = 1 else: delta = -1 zmin = self.zmin+delta zmax = self.zmax-delta if zmin == zmax: zmax = zmin+1 if zmin < 0: zmin = 0 if zmax > self.volSize[2]: zmax = self.volSize[2] if zmin > zmax : return self.zmin = zmin self.zmax = zmax self.updateZ() def ScaleAll(self, event, matrix, transXY, transZ): if transZ<0: delta = 1 else: delta = -1 xmin = self.xmin+delta xmax = self.xmax-delta if xmin == xmax: xmax = xmin+1 if xmin < 0 : xmin = 0 if xmax > self.volSize[0]: xmax =self.volSize[0] if xmin > xmax : return self.xmin = xmin self.xmax = xmax ymin = self.ymin+delta ymax = self.ymax-delta if ymin == ymax: ymax = ymin+1 if ymin < 0: ymin = 0 if ymax > self.volSize[1]: ymax = self.volSize[1] if ymin > ymax : return self.ymin = ymin self.ymax = ymax zmin = self.zmin+delta zmax = self.zmax-delta if zmin == zmax: zmax = zmin+1 if zmin < 0: zmin = 0 if zmax > self.volSize[2]: zmax = self.volSize[2] if zmin > zmax : return self.zmin = zmin self.zmax = zmax self.update() def TranslationX(self, event, matrix, transXY, transZ): if transZ>0: delta = 2 else: delta = -2 self.xmin = self.xmin+delta self.xmax = self.xmax+delta if self.xmin == self.xmax: self.xmax = self.xmin+1 if self.xmin < 0 : self.xmax = self.xmax-self.xmin self.xmin = 0 if self.xmax > self.volSize[0]: self.xmin = self.xmin - (self.xmax-self.volSize[0]) self.xmax = self.volSize[0] self.updateX() def TranslationY(self, event, matrix, transXY, transZ): if transZ>0: delta = 2 else: delta = -2 self.ymin = self.ymin+delta self.ymax = self.ymax+delta if self.ymin == self.ymax: self.ymax = self.ymin+1 if self.ymin < 0 : self.ymax = self.ymax-self.ymin self.ymin = 0 if self.ymax > self.volSize[1]: self.ymin = self.ymin - (self.ymax-self.volSize[1]) self.ymax = self.volSize[1] self.updateY() def TranslationZ(self, event, matrix, transXY, transZ): if transZ>0: delta = 2 else: delta = -2 self.zmin = self.zmin+delta self.zmax = self.zmax+delta if self.zmin == self.zmax: self.zmax = self.zmin+1 if self.zmin < 0 : self.zmax = self.zmax-self.zmin self.zmin = 0 if self.zmax > self.volSize[2]: self.zmin = self.zmin - (self.zmax-self.volSize[2]) self.zmax = self.volSize[2] self.updateZ() def Translate(self,t): ## #scl = 0.25 ## scl = 1 ## print "t:", t ## t1 = int(t[0]*scl) ## t2 = int(t[1]*scl) ## t3 = int(t[2]*scl) t1,t2,t3=Numeric.where(Numeric.less(t,0),-2, 2) xmin = self.xmin xmax = self.xmax ymin = self.ymin ymax = self.ymax zmin = self.zmin zmax = self.zmax xmin = xmin + t1 xmax = xmax + t1 nx, ny, nz = self.volSize if xmin < 0 : xmax = xmax-xmin xmin = 0 if xmax > nx: xmin = xmin - (xmax-nx) xmax = nx ymin = ymin + t2 ymax = ymax + t2 if ymin < 0 : ymax = ymax-ymin ymin = 0 if ymax > ny: ymin = ymin - (ymax-ny) ymax = ny zmin = zmin + t3 zmax = zmax + t3 if zmin < 0 : zmax = zmax-zmin zmin = 0 if zmax > nz: zmin = zmin - (zmax-nz) zmax = nz self.xmin = xmin self.xmax = xmax self.ymin = ymin self.ymax = ymax self.zmin = zmin self.zmax = zmax self.update() from DejaVu.Geom import Geom class VolumeGeom(Geom): """Base class to render a volumetric object""" keywords = Geom.keywords + ['volscale', 'masterObject', 'voltranslate'] def __init__(self, name=None, check=1, **kw): #self.immediateRendering = 1 #self.transparent = 1 self.inheritMaterial = 0 self.inheritXform = 0 self.viewer = None self.boundBox = None apply( Geom.__init__, (self, name, check), kw) self._modified = False #print "immediateRendering:", self.immediateRendering #print "transparent:", self.transparent self.immediateRendering = 1 self.transparent = 1 def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: Set polylines's vertices check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( Geom.Set, (self, check, 0), kw ) return self.redoNow(redo, updateOwnGui, redoFlags) def BindMouseToCropScale(self): """Bind the trackball to the current cropping box""" c = self.viewer.currentCamera c.bindActionToMouseButton('cropScaleX', 1, 'Control') c.bindActionToMouseButton('cropScaleY', 2, 'Control') c.bindActionToMouseButton('cropScaleZ', 3, 'Control') c.bindActionToMouseButton('cropScaleAll', 3, 'Meta') def BindMouseToCropTranslate(self): c = self.viewer.currentCamera c.bindActionToMouseButton('cropTransX', 1, 'Meta') c.bindActionToMouseButton('cropTransY', 2, 'Meta') c.bindActionToMouseButton('cropTransZ', 3, 'Meta') def BindMouseToCropTransAll(self): c = self.viewer.currentCamera c.bindActionToMouseButton('cropTransAll', 1, 'Meta') c.bindActionToMouseButton('None', 2, 'Meta') c.bindActionToMouseButton('cropScaleAll', 3, 'Meta') def translateCropbox(self, event, matrix, transXY, transZ): # FIXME won't work with instance matrices m = self.masterObject.GetMatrixInverse() for i in range(3): m[i][3] = 0 v = [transXY[0],transXY[1],0,1] v = Numeric.reshape(Numeric.array(v),(4,1)) t = Numeric.dot(m,v) t = [t[0][0], t[1][0], t[2][0]] self.cropBox.Translate(t) def LoadVolume(self, filename): #has to be implemented by a 'child' class pass def AddVolume(self, volume, dataPtr): #has to be implemented by a 'child' class pass def Draw(self): #has to be implemented by a 'child' class pass mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/viewerFns.py0000644000175000017500000000543510651433501022214 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/viewerFns.py,v 1.7 2007/07/24 17:30:41 vareille Exp $ # # $Id: viewerFns.py,v 1.7 2007/07/24 17:30:41 vareille Exp $ # import numpy.oldnumeric as Numeric import viewerConst import types def checkKeywords(_name, keywords, **kw): """test is all kyes in **kw are in list keywords""" for key in kw.keys(): if key not in keywords: print 'WARNING: Keyword %s not recognized for %s' % (key,_name) #import traceback;traceback.print_stack() def getkw(kw, name): """get a dictionary entry and remove it from the dictionary""" v = kw.get(name) if name in kw.keys(): del kw[name] return v def GetArray(vector, shape=None, precision=viewerConst.FPRECISION ): """get a vector and return it in a Numeric array""" if type(vector).__name__ == 'array': if vector.dtype.char==precision: if shape: if vector.shape == shape: return vector else: return Numeric.reshape(vector, shape) else: return vector else: vector = Numeric.array( vector, precision ) if shape: if vector.shape == shape: return vector else: return Numeric.reshape(vector, shape) else: return vector else: vector = Numeric.array( vector, precision ) if shape: if vector.shape == shape: return vector else: return Numeric.reshape(vector, shape) else: return vector def read_data(filename, function): """Read data from an ASCII file.""" import string result = [] assert type(filename) == types.StringType assert function in (None, float, int) print "reading", filename f = open(filename, "r") while 1: line = f.readline(); if not len(line): break if function: datum = map(function, string.split(line)) result.append(list(datum)) else: result.append(line) f.close() if function == float: ar = Numeric.array(result).astype(viewerConst.FPRECISION) elif function == int: ar = Numeric.array(result).astype(viewerConst.IPRECISION) else: ar = result return ar def write_data(filename,data): """Write data to an ASCII file.""" assert type(filename) == types.StringType import string f = open(filename, "w") def writedatum1(datum, f=f): line = str(datum) line = line[1:-1] + "\n" # slice off the [ , ] characters f.write(line) def writedatum(datum, f=f): import string, numpy.oldnumeric as Numeric line = string.join(map(str,Numeric.array(datum))," ") + "\n" f.write(line) map(writedatum,data) f.close() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Trackball.py0000644000175000017500000006703511746042117022154 0ustar debiandebian######################################################################## # # Date: 2000 Author: Michel F. SANNER # # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Trackball.py,v 1.60 2012/04/25 18:37:03 sanner Exp $ # # $Id: Trackball.py,v 1.60 2012/04/25 18:37:03 sanner Exp $ # import Tkinter import Pmw import math from time import time from copy import deepcopy from weakref import ref from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from mglutil.math.transformation import UnitQuaternion from mglutil.gui.BasicWidgets.Tk.vector3DGUI import vectorGUI from mglutil.util.misc import ensureFontCase from opengltk.extent.utillib import glTrackball import DejaVu from DejaVu.Transformable import Transformable from DejaVu.viewerConst import FPRECISION, YES, NO from DejaVu.viewerFns import getkw from DejaVu.cursors import cursorsDict # remove this line when we go to version 1.46 if hasattr( DejaVu, 'defaultSpinningMode') is False: DejaVu.defaultSpinningMode = 0 class Trackball: def __init__(self, camera, size=0.8, rscale=2.0, tscale=0.05, sscale=0.01, renorm=97): #print "Trackball.__init___", DejaVu.defaultSpinningMode #import traceback;traceback.print_stack() for mod in camera.mouseButtonModifiers: if mod=='None': mod='' setattr(self, mod+'B1motion', self.NoFunc) setattr(self, mod+'B2motion', self.NoFunc) setattr(self, mod+'B3motion', self.NoFunc) self.reportFrameRate = 0 # create a trackball self.tb = glTrackball(size, rscale, renorm) self.vectorXY = [0.0 ,0.0] self.vectorZ = 0.0 self.transScale = tscale self.scaleFactor = 0.0 self.scaleScale = sscale # save the Opengl widget for this trackball self.camera = ref(camera) # Current coordinates of the mouse. self.xmouse = 0 self.ymouse = 0 self.xmouseDown = 0 self.ymouseDown = 0 self.xmouseUp = 0 self.ymouseUp = 0 # setup the spin self.cancelId = 0 # used to stop the spinning self.spinRotationMat = UnitQuaternion( data=(0.,-1.,0.,1.) ).getRotMatrix(shape=(16,)) self.spinVar = self.camera().viewer.spinVar self.lastSpinVar = 0 self.resetSpinValues(updateSpinGui=False) self.createSpinGui() self.spinGui.withdraw() # Basic bindings for the virtual trackball self.ResetBindings() def set(self, otherTrackball): self.spinRotationMat = otherTrackball.spinRotationMat self.spinVar.set( otherTrackball.spinVar.get() ) self.lastSpinVar = otherTrackball.lastSpinVar self.spinAxis = otherTrackball.spinAxis self.spinAnglePerFrame = otherTrackball.spinAnglePerFrame self.rockAngle = otherTrackball.rockAngle self.numOfFrameRock = otherTrackball.numOfFrameRock self.rockCount = otherTrackball.rockCount self.updateSpinGui() if otherTrackball.cancelId != 0: self.spinCycle() def resetSpinValues(self, updateSpinGui=True): self.spinAxis = [0., 1., 0.] self.spinAnglePerFrame = .5 self.rockAngle = 30 self.numOfFrameRock = abs(self.rockAngle / self.spinAnglePerFrame) self.rockCount = self.numOfFrameRock / 2 if updateSpinGui is True: self.updateSpinGui() if self.cancelId != 0: self.camera().restoreAA(None) self.camera().after_cancel(self.cancelId) self.cancelId = 0 def ResetBindings(self): """binds default callbacks to events""" cam = self.camera() evm = cam.eventManager # Any-Button-1 acts the same as Button-1 when bound to widget; # therefore, Modifier-ButtonPress-1 overwrites it; must specify for # modifier for mod in cam.mouseButtonModifiers: if mod=='None': mod='' else: mod=mod+'-' evm.AddCallback('<'+mod+'ButtonPress-1>', self.RecordMouse) evm.AddCallback('<'+mod+'ButtonPress-2>', self.RecordMouse) evm.AddCallback('<'+mod+'ButtonPress-3>', self.RecordMouse) evm.AddCallback('<'+mod+'ButtonPress-1>', self.MouseButtonDown) evm.AddCallback('<'+mod+'ButtonPress-2>', self.MouseButtonDown) evm.AddCallback('<'+mod+'ButtonPress-3>', self.MouseButtonDown) evm.AddCallback('<'+mod+'ButtonRelease-1>', self.MouseButtonUp) evm.AddCallback('<'+mod+'ButtonRelease-2>', self.MouseButtonUp) evm.AddCallback('<'+mod+'ButtonRelease-3>', self.MouseButtonUp) evm.AddCallback('<'+mod+'ButtonRelease-1>', self.setDefaultCursor) evm.AddCallback('<'+mod+'ButtonRelease-2>', self.setDefaultCursor) evm.AddCallback('<'+mod+'ButtonRelease-3>', self.setDefaultCursor) for mod in cam.mouseButtonModifiers: if mod=='None': mod=mod1='' else: mod1=mod+'-' evm.AddCallback('<'+mod1+'B1-Motion>', eval('self.'+mod+'B1motion_cb')) evm.AddCallback('<'+mod1+'B2-Motion>', eval('self.'+mod+'B2motion_cb')) evm.AddCallback('<'+mod1+'B3-Motion>', eval('self.'+mod+'B3motion_cb')) # we put this after mouse up so we leave more time for the mouse # to move and launch the spin lButton, lModifier= cam.findButton('rotation', 'Object') self.rotationButton = lButton self.rotationModifier = lModifier if lModifier == 'None': lModifier = '' else: lModifier += '-' evm.AddCallback('<'+lModifier+'ButtonRelease-'+str(lButton)+'>', self.launchTrackbalSpin_cb) def setDefaultCursor(self, event): self.camera().configure(cursor=cursorsDict['default']) def trackMotion_cb(self, event): self.xrootBmotionPrevious = self.xrootBmotion self.yrootBmotionPrevious = self.yrootBmotion self.xrootBmotion = event.x_root self.yrootBmotion = event.y_root def B1motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.B1motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def B2motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" #print "B2motion_cb" self.computeTransformation(event) self.B2motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def B3motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.B3motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def ShiftB1motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.ShiftB1motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def ShiftB2motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.ShiftB2motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def ShiftB3motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.ShiftB3motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def ControlB1motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.ControlB1motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def ControlB2motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.ControlB2motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def ControlB3motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.ControlB3motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def AltB1motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.AltB1motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def AltB2motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.AltB2motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def AltB3motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.AltB3motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def MetaB1motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.MetaB1motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def MetaB2motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.MetaB2motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def MetaB3motion_cb(self, event): """Default callback for rotation, computes rotation matrix""" self.computeTransformation(event) self.MetaB3motion(event, self.tb.mat, self.vectorXY, self.vectorZ) self.RecordMouse(event) def computeTransformation(self, event): """compute the rotation corresponding to the latest mouse motion and the (X,Y) translation corresponding to the latest mouse motion and the Z translation corresponding to the latest mouse motion """ #print "computeTransformation", event #print "self.xmouse, x", self.xmouse, event.x #print "self.ymouse, y", self.ymouse, event.y self.trackMotion_cb(event) self.tb.update(self.xmouse, self.ymouse, event.x, event.y, self.camera().width, self.camera().height, 1 ) # now self.tb.mat has the rotation matrix self.vectorXY[0] = dx = event.x - self.xmouse self.vectorXY[1] = dy = self.ymouse - event.y if abs(dx) > abs(dy): delta = dx else: delta = dy self.vectorZ = delta # new self.vector[:2] has the (X,Y) translation vector # and self.vector[2] has the Z translation def NoFunc(self, event, matrix, transXY, transZ): pass def cursorPosition(self): """get new mouse position """ c = self.camera() x = c.tk.getint(c.tk.call('winfo', 'pointerx', c._w)) y = c.tk.getint(c.tk.call('winfo', 'pointery', c._w)) return x,y def MouseButtonDown(self, event): """Do all we have to do every time a mouse button goes down """ #print "MouseButtonDown", event.num #print "Focus on MouseButtonDown", self.camera().focus_get() #if event.num in [2]: # set cursor self.camera().setCursor(event.num) self.xrootBmotionPrevious = event.x_root self.yrootBmotionPrevious = event.y_root self.xrootBmotion = event.x_root self.yrootBmotion = event.y_root if ((event.num in [1, self.rotationButton]) and (self.cancelId != 0)): self.camera().restoreAA(None) self.camera().after_cancel(self.cancelId) self.cancelId = 0 self.resetSpinValues() v = self.camera().viewer for c in v.cameras: for func in c.onButtonDownCBlist: func(event) v.lastPickedCamera = v.currentCamera self.xmouseDown = event.x self.ymouseDown = event.y v.timeButtonDown = time() v.numberOfRedraws = 0 #print 'Down', self.xmouseDown, self.ymouseDown def MouseButtonUp(self, event): """Do all we have to do every time a mouse button is released """ self.camera().configure(cursor=cursorsDict['default']) #print "Trackball.MouseButtonUp", event.num, event, time() if self.cancelId == 0: # if we are spinning, we do as if the button wasn't up v = self.camera().viewer v.timeButtonUp = time() if self.reportFrameRate: print v.numberOfRedraws / (v.timeButtonUp - v.timeButtonDown) for c in v.cameras: for func in c.onButtonUpCBlist: #print "MouseButtonUp func", func func(event) v.lastPickedCamera = v.currentCamera self.xmouseUp = event.x self.ymouseUp = event.y #print 'UP', self.xmouseUp, self.ymouseUp v.Redraw() #print "Focus after MouseButtonUP", self.camera().focus_get() def RecordMouse(self, event): """Record the current mouse position """ #print "RecordMouse" #v = self.camera().viewer #v.trackball = self self.xmouse = event.x self.ymouse = event.y def launchTrackbalSpin_cb(self, event): """If motion after button release start auto spin """ #print "Trackball.launchTrackbalSpin_cb", event, time() c = self.camera() vi = c.viewer if vi.Xform.get() == 'Object': lSpinVar = self.spinVar.get() if lSpinVar in (1, 2, 3): x,y = self.cursorPosition() lDistanceX = (self.xrootBmotionPrevious - x) lDistanceX2 = lDistanceX * lDistanceX lDistanceY = (self.yrootBmotionPrevious - y) lDistanceY2 = lDistanceY * lDistanceY lSquaredDistance = lDistanceX2 + lDistanceY2 if lSquaredDistance > 81: #it seems that the quaternions in dejavu.i #are not the same as those in transformation.py lUnitQuat = UnitQuaternion( data=(self.tb.quat[3], self.tb.quat[:-1] ) ) self.spinAxis, lAngle = lUnitQuat.getAxisAndAngleDegres() self.spinAnglePerFrame = lAngle / 4 self.spinGui.anglePerFrameThumbwheel.set(self.spinAnglePerFrame, update=0) self.spinGui.vectorGUI.vector = list(self.spinAxis) self.spinGui.vectorGUI.setEntries() self.spinGui.rockAngleThumbwheel.set(120, update=0) self.setWithSpinGui() self.lastSpinVar = self.spinVar.get() self.rockCount = self.numOfFrameRock / 2 self.spinCycle() elif self.cancelId != 0: c.restoreAA(None) c.after_cancel(self.cancelId) self.cancelId = 0 self.resetSpinValues() def makeSpinRotationMat(self, spinAxis, spinAngle): """ """ #print "Trackball.makeSpinRot" #it seems that the quaternions in dejavu.i #are not the same as those in transformation.py lUnitQuat = UnitQuaternion( data=(spinAxis[0], spinAxis[1], spinAxis[2], spinAngle ) ) return lUnitQuat.getRotMatrix(shape=(16,)) def toggleCycle(self, docb=True): #print "toggleCycle", self.cancelId lCurrentSpinVar = self.spinVar.get() if (self.cancelId == 0) \ or (self.lastSpinVar != lCurrentSpinVar): if lCurrentSpinVar in [0, 1]: self.rockCount = self.numOfFrameRock / 2 self.spinRotationMat = self.makeSpinRotationMat( self.spinAxis, self.spinAnglePerFrame ) self.spinCycle() else: self.camera().restoreAA(None) self.camera().after_cancel(self.cancelId) self.cancelId = 0 if docb and self.camera().viewer.spinCallBack is not None: self.camera().viewer.spinCallBack(lCurrentSpinVar) def spinCycle(self): """Spin the object in continuous mode """ #print "Trackball.doSpin", self.tb.mat c = self.camera() c.after_cancel(self.cancelId) vi = c.viewer if vi.Xform.get() == 'Object': c.suspendAA(None) self.lastSpinVar = self.spinVar.get() if self.lastSpinVar == 1: vi.rootObject.ConcatRotation(self.spinRotationMat) c.Redraw() vi.afterRedraw() self.cancelId = c.after(10, self.spinCycle) elif self.lastSpinVar in [2, 3]: self.cancelId = c.after(10, self.bounceCycle) else: c.restoreAA(None) else: c.restoreAA(None) def bounceCycle(self): """Bounce the object in continuous mode """ #print "Trackball.doRock", self.tb.mat c = self.camera() c.after_cancel(self.cancelId) vi = c.viewer if vi.Xform.get() == 'Object': c.suspendAA(None) self.lastSpinVar = self.spinVar.get() if self.lastSpinVar == 2: if self.rockCount >= self.numOfFrameRock: self.rockCount = 0 self.spinAnglePerFrame = - self.spinAnglePerFrame self.spinRotationMat = self.makeSpinRotationMat( self.spinAxis, self.spinAnglePerFrame ) else: self.rockCount += 1 vi.rootObject.ConcatRotation(self.spinRotationMat) c.Redraw() vi.afterRedraw() self.cancelId = c.after(10, self.bounceCycle) elif self.lastSpinVar == 3: self.cancelId = c.after(10, self.oscillateCycle) elif self.lastSpinVar == 1: self.rockCount = self.numOfFrameRock / 2 self.cancelId = c.after(10, self.spinCycle) else: c.restoreAA(None) else: c.restoreAA(None) def oscillateCycle(self): """Oscillate the object in continuous mode """ #print "Trackball.bounceCycle", self.tb.mat c = self.camera() c.after_cancel(self.cancelId) vi = c.viewer vi.master.update_idletasks() if vi.Xform.get() == 'Object': c.suspendAA(None) self.lastSpinVar = self.spinVar.get() if self.lastSpinVar == 3: lNumOfFrameRock = self.numOfFrameRock if self.rockCount >= lNumOfFrameRock: self.rockCount = 0 self.spinAnglePerFrame = - self.spinAnglePerFrame else: self.rockCount += 1 lAtenuationFactor = math.sin(3.14159*self.rockCount/lNumOfFrameRock) * 1.57 self.spinRotationMat = self.makeSpinRotationMat( self.spinAxis, self.spinAnglePerFrame*lAtenuationFactor ) vi.rootObject.ConcatRotation(self.spinRotationMat) c.Redraw() vi.afterRedraw() self.cancelId = c.after(10, self.oscillateCycle) elif self.lastSpinVar == 2: self.spinRotationMat = self.makeSpinRotationMat( self.spinAxis, self.spinAnglePerFrame ) self.cancelId = c.after(10, self.bounceCycle) elif self.lastSpinVar == 1: self.rockCount = self.numOfFrameRock / 2 self.spinRotationMat = self.makeSpinRotationMat( self.spinAxis, self.spinAnglePerFrame ) self.cancelId = c.after(10, self.spinCycle) else: c.restoreAA(None) else: c.restoreAA(None) def showSpinGui(self, event=None): #print "showSpinGui", self if self.spinGui.winfo_ismapped() == 0: self.spinGui.deiconify() self.spinGui.lift() def hideSpinGui(self, event=None): #print "hideSpinGui", self if self.spinGui.winfo_ismapped() == 1: self.spinGui.withdraw() def toggleSpinGui(self, event=None): #print "toggleSpinGui", self if self.spinGui.winfo_ismapped() == 1: self.spinGui.withdraw() else: self.spinGui.deiconify() self.spinGui.lift() def createSpinGui(self): #print "createSpinGui" self.spinGui = Tkinter.Toplevel() self.spinGui.title('Spin Settings') self.spinGui.protocol('WM_DELETE_WINDOW', self.spinGui.withdraw ) mainFrame = Tkinter.Frame(self.spinGui, relief='ridge', borderwidth=3) lLabelSpinBold = Tkinter.Label(mainFrame, text="Spinning only occurs in \"Object\" transform mode", font=(ensureFontCase('helvetica'),10,'bold')) lLabelSpinBold.pack(side='top') lLabelSpin = Tkinter.Label(mainFrame, font=(ensureFontCase('helvetica'),'9'), justify='left', text="""start: release the middle button while the mouse is still moving stop: left click """ ) lLabelSpin.pack(side='top') anglesFrame = Tkinter.Frame(mainFrame, relief='ridge', borderwidth=3) # off/spin/rock radio buttons radioFrame = Tkinter.Frame(anglesFrame)#, relief='ridge', borderwidth=3) radioOff = Tkinter.Radiobutton( radioFrame, text='Off', value=0, variable=self.spinVar, width=8, indicatoron=0, command=self.resetSpinValues, ) radioOff.grid(row=0, column=0, sticky='we') radioSpin = Tkinter.Radiobutton( radioFrame, text='Spin', value=1, variable=self.spinVar, width=8, indicatoron=0, command=self.toggleCycle, ) radioSpin.grid(row=0, column=1, sticky='we') radioBounce = Tkinter.Radiobutton( radioFrame, text='Bounce', value=2, variable=self.spinVar, width=8, indicatoron=0, command=self.toggleCycle, ) radioBounce.grid(row=0, column=2, sticky='we') radioOscillate = Tkinter.Radiobutton( radioFrame, text='Oscillate', value=3, variable=self.spinVar, width=8, indicatoron=0, command=self.toggleCycle, ) radioOscillate.grid(row=0, column=3, sticky='we') radioFrame.pack(side='top') self.spinGui.anglePerFrameThumbwheel = ThumbWheel( anglesFrame, labCfg={'text':'Angular speed (degrees per frame)', 'side':'left'}, showLabel=1, width=90, height=14, min=.01, max=10., type=float, value=self.spinAnglePerFrame, callback=self.setWithSpinGui, continuous=True, oneTurn=5, wheelPad=0, ) self.spinGui.anglePerFrameThumbwheel.pack(side='top', anchor='e') self.spinGui.rockAngleThumbwheel = ThumbWheel( anglesFrame, labCfg={'text':'Rock angle (degrees)', 'side':'left'}, showLabel=1, width=90, height=14, min=1, max=360, type=int, value=self.rockAngle, callback=self.setWithSpinGui, continuous=True, oneTurn=60, wheelPad=0, ) self.spinGui.rockAngleThumbwheel.pack(side='top', anchor='e') def shiftRockCenter(val): lSpinRotMat = self.makeSpinRotationMat(self.spinAxis, -val) c = self.camera() c.viewer.rootObject.ConcatRotation(lSpinRotMat) c.Redraw() vi.afterRedraw() shiftRockCenterThumbwheel.set(0, update=0) shiftRockCenterThumbwheel = ThumbWheel( anglesFrame, labCfg={'text':'Shift rock center', 'side':'left'}, showLabel=0, width=90, height=14, min=-100, max=100, type=int, value=0, callback=shiftRockCenter, continuous=True, oneTurn=90, wheelPad=0, ) shiftRockCenterThumbwheel.pack(side='top', anchor='e') anglesFrame.pack(side='top') self.spinGui.vectorGUI = vectorGUI(mainFrame, size=150, vector=self.spinAxis, callback=self.setWithSpinGui, ) mainFrame.pack(side='top') def updateSpinGui(self): self.spinGui.rockAngleThumbwheel.set(self.rockAngle, update=0) self.spinGui.anglePerFrameThumbwheel.set(self.spinAnglePerFrame, update=0) self.spinGui.vectorGUI.vector = self.spinAxis self.spinGui.vectorGUI.setEntries() if self.camera().viewer.spinCallBack is not None: self.camera().viewer.spinCallBack(self.spinVar.get()) def setWithSpinGui(self, event=None): """ """ #print "setWithSpinGui", event self.rockAngle = self.spinGui.rockAngleThumbwheel.get() if (self.spinVar.get() in [2, 3] ) and (self.spinAnglePerFrame < 0): self.spinAnglePerFrame = - self.spinGui.anglePerFrameThumbwheel.get() else: self.spinAnglePerFrame = self.spinGui.anglePerFrameThumbwheel.get() self.numOfFrameRock = abs(self.rockAngle / self.spinAnglePerFrame) self.spinAxis = self.spinGui.vectorGUI.vector self.spinRotationMat = self.makeSpinRotationMat(self.spinAxis, self.spinAnglePerFrame) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/spline.py0000644000175000017500000002346710652517651021555 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/spline.py,v 1.10 2007/07/28 01:45:13 vareille Exp $ # # $Id: spline.py,v 1.10 2007/07/28 01:45:13 vareille Exp $ # """ reimplementation of lincrv.c in python MS April 2000 original code from Graphics Gem V pp220-222 Ken Shoemake, 1994 """ import numpy.oldnumeric as Numeric from copy import deepcopy # Perform a generic vector unary operation. def lerp(t, a0, a1, p0, p1): t0 = (a1-t)/(a1-a0) t1=1-t0 p = t0*p0 + t1*p1 return p.astype('f') """ DialASpline(t,a,p,m,n,work,Cn,interp,val) computes a point val at parameter t on a spline with knot values a and control points p. The curve will have Cn continuity, and if interp is TRUE it will interpolate the control points. Possibilities include Langrange interpolants, Bezier curves, Catmull-Rom interpolating splines, and B-spline curves. Points have m coordinates, and n+1 of them are provided. The work array must have room for n+1 points. """ def DialASpline( t, a, p, m=3, n=4, work=None, Cn=2, interp=1): if Cn>n-1: Cn = n-1 # Anything greater gives one polynomial k=0 while ( t>a[k]): k=k+1 # Find enclosing knot interval h=k while (t==a[k]): k = k+1 # May want to use fewer legs if k>n: k = n if h>k: h = k h = 1+Cn - (k-h) k=k-1 lo = k-Cn hi = k+1+Cn if interp: # Lagrange interpolation steps drop=0 if lo<0: lo = 0 drop = drop + Cn-k if hi-lon: hi = n drop = drop + k+1+Cn-n if hi-lo= 0.) and (anchor[0] <= 1.) \ and (anchor[1] >= 0.) and (anchor[1] <= 1.): self.anchor = anchor redoFlags |= self._redoFlags['redoDisplayListFlag'] position = kw.get( 'position') if position: self.position = position redoFlags |= self._redoFlags['redoDisplayListFlag'] size = kw.get( 'size') if size: self.size = size redoFlags |= self._redoFlags['redoDisplayListFlag'] color = kw.get( 'color') if color: print color self.color = color print self.color redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() GL.glLoadIdentity() Insert2d.Draw(self) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glDisable(GL.GL_DEPTH_TEST) GL.glDisable(GL.GL_LIGHTING); width = self.size[0] height = self.size[1] fullWidth = self.viewer.currentCamera.width fullHeight = self.viewer.currentCamera.height # we want the anchor of the image to be at the given position posxFromLeft = self.position[0] * fullWidth - self.anchor[0] * width posyFrombottom = (1.-self.position[1]) * fullHeight - (1.-self.anchor[1]) * height #print "posxFromLeft, posyFrombottom", posxFromLeft, posyFrombottom GL.glColor4fv(self.color) xo, yo = self.position dx, dy = self.size GL.glBegin(GL.GL_QUADS); GL.glVertex2f(xo, yo) GL.glVertex2f(xo+dx, yo) GL.glVertex2f(xo+dx, yo+dy) GL.glVertex2f(xo, yo+dy) GL.glEnd() # used for picking # self.polygonContour = [ (posxFromLeft, posyFrombottom), # (posxFromLeft+width, posyFrombottom), # (posxFromLeft+width, posyFrombottom+height), # (posxFromLeft, posyFrombottom+height) # ] GL.glEnable(GL.GL_DEPTH_TEST) GL.glEnable(GL.GL_LIGHTING); GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPopMatrix() return 1 class StickerImage(Insert2d): keywords = Insert2d.keywords + [ 'image', ] def __init__(self, name='StickerImage', check=1, **kw): #print "StickerImage.__init__" self.image = None apply(Insert2d.__init__, (self, name, check), kw) self.needsRedoDpyListOnResize = True def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ #print "StickerImage.Set" redoFlags = apply( Insert2d.Set, (self, check, 0), kw) image = kw.get('image') if image is not None: kw.pop('image') self.image = image self.size[0] = self.image.size[0] self.size[1] = self.image.size[1] redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): #print "StickerImage.Draw", self if self.image is None: return GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() GL.glLoadIdentity() Insert2d.Draw(self) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glDisable(GL.GL_DEPTH_TEST) GL.glDisable(GL.GL_LIGHTING); width = self.size[0] height = self.size[1] fullWidth = self.viewer.currentCamera.width fullHeight = self.viewer.currentCamera.height # we want the anchor of the image to be at the given position posxFromLeft = self.position[0] * fullWidth - self.anchor[0] * width posyFrombottom = (1.-self.position[1]) * fullHeight - (1.-self.anchor[1]) * height #print "posxFromLeft, posyFrombottom", posxFromLeft, posyFrombottom # used for picking self.polygonContour = [ (posxFromLeft, posyFrombottom), (posxFromLeft+width, posyFrombottom), (posxFromLeft+width, posyFrombottom+height), (posxFromLeft, posyFrombottom+height) ] # this accept negative values were GL.glRasterPos2f(x,y) doesn't GL.glRasterPos2f(0, 0) _gllib.glBitmap(0, 0, 0, 0, posxFromLeft, posyFrombottom, 0) GL.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1) if self.image.mode == 'RGBA': _gllib.glDrawPixels(self.image.size[0], self.image.size[1], GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, self.image.tostring() ) elif self.image.mode == 'RGB': _gllib.glDrawPixels(self.image.size[0], self.image.size[1], GL.GL_RGB, GL.GL_UNSIGNED_BYTE, self.image.tostring() ) elif self.image.mode == 'L': _gllib.glDrawPixels(self.image.size[0], self.image.size[1], GL.GL_LUMINANCE, GL.GL_UNSIGNED_BYTE, self.image.tostring() ) GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPopMatrix() return 1 def setSize(self, event, redo=1): """the trackball transmit the translation info """ pass mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/colorTool.py0000644000175000017500000003253211111122160022202 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/colorTool.py,v 1.22 2008/11/19 23:42:40 sanner Exp $ # # $Id: colorTool.py,v 1.22 2008/11/19 23:42:40 sanner Exp $ # import numpy.oldnumeric as Numeric import viewerConst from opengltk.extent import _gllib as gllib from math import fabs from opengltk.OpenGL import GL # properties are GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION, GL_SHININESS materialMemory = { GL.GL_FRONT: [[-1.,-1.,-1.,-1], [-1.,-1.,-1.,-1], [-1.,-1.,-1.,-1], [-1.,-1.,-1.,-1], -1], GL.GL_BACK: [[-1.,-1.,-1.,-1], [-1.,-1.,-1.,-1], [-1.,-1.,-1.,-1], [-1.,-1.,-1.,-1], -1] } from math import fabs def resetMaterialMemory(): global materialMemory #print 'RESET' for i in range(4): for j in range(4): materialMemory[GL.GL_FRONT][i][j] = -1 materialMemory[GL.GL_BACK][i][j] = -1 materialMemory[GL.GL_FRONT][4] = -1 materialMemory[GL.GL_BACK][4] = -1 def glAllMaterialWithCheck(face, mat, num, eps=0.001, check=True, debug=0): p = mat.prop f = face if mat.binding[0] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_AMBIENT, p[0][0], eps=eps, check=check) else: if debug: print 'ambi', p[0][num] glMaterialWithCheck(f, GL.GL_AMBIENT, p[0][num], eps=eps, check=check) if mat.binding[1] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_DIFFUSE, p[1][0], eps=eps, check=check) else: if debug: print 'diff', p[1][num] glMaterialWithCheck(f, GL.GL_DIFFUSE, p[1][num], eps=eps, check=check) if mat.binding[2] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_SPECULAR, p[2][0], eps=eps, check=check) else: if debug: print 'spec', p[2][num] glMaterialWithCheck(f, GL.GL_SPECULAR, p[2][num], eps=eps, check=check) if mat.binding[3] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_EMISSION, p[3][0], eps=eps, check=check) else: if debug: print 'emis', p[3][num] glMaterialWithCheck(f, GL.GL_EMISSION, p[3][num], eps=eps, check=check) if mat.binding[4] == viewerConst.OVERALL: glMaterialWithCheck(f, GL.GL_SHININESS, p[4][0], eps=eps, check=check) else: if debug: print 'shini', p[4][num] glMaterialWithCheck(f, GL.GL_SHININESS, p[4][num], eps=eps, check=check) def glMaterialWithCheck(face, property, material, eps=0.001, check=True): """ Only calls glMaterial if the material is different from he current value face can be GL_FRONT or GL_BACK propety can be GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR or GL_EMISSION material is a 3-sequence RGBA, Alpha values are only test for ambient and diffuse properties """ global materialMemory #print 'glMaterialWithCheck', property, material if face==GL.GL_FRONT_AND_BACK: face=GL.GL_FRONT if property==GL.GL_SHININESS: matMem = materialMemory[face] if not check or fabs(matMem[4]-material) > eps: matMem[4] = material #GL.glMaterialfv( face, property, matMem[4] ) GL.glMaterialf( face, property, float(matMem[4]) ) else: if not material.flags.contiguous: material = Numeric.array(material,copy=1) propNum = viewerConst.propNum[property] matMem = materialMemory[face][propNum] ## print 'DIFFERENCE' ## print id(matMem), id(materialMemory[face][propNum]) ## print matMem ## print material ## print fabs(matMem[0]-material[0]) > eps ## print fabs(matMem[1]-material[1]) > eps ## print fabs(matMem[2]-material[2]) > eps ## print (fabs(matMem[3]-material[3]) > eps and propNum in (0,1)) if check: newCol = fabs(matMem[0]-material[0]) > eps or \ fabs(matMem[1]-material[1]) > eps or \ fabs(matMem[2]-material[2]) > eps or \ (fabs(matMem[3]-material[3]) > eps and propNum in (0,1)) else: newCol = True if newCol: #GL.glMaterialfv( face, property, material.tolist() ) #print 'SETTING' gllib.glMaterialfv( face, property, material) matMem[0] = material[0] matMem[1] = material[1] matMem[2] = material[2] matMem[3] = material[3] #print matMem ## else: ## curcol = GL.glGetMaterialfv(face, property) ## print 'SKIPPING' ## print curcol ## print material ## print matMem #def firstMaterial( r, g, b ): # global mat_r, mat_g, mat_b # mat_r = r # mat_g = g # mat_b = b # #def sameMaterial( r, g, b ): # global mat_r, mat_g, mat_b # if fabs(mat_r-r) > 0.001 or fabs(mat_g-g) > 0.001 or fabs(mat_b-b) > 0.001: # #print r,mat_r,g,mat_g,b,mat_b # mat_r = r # mat_g = g # mat_b = b # return 0 # return 1 def OneColor(color, alpha = 1.0): """get a color RGBA Add alpha if missing, return values from 0.0 to 1.0""" if max(color) > 1.0: color = map( lambda x: x/255., color) if len(color) == 3: return list(color)+[alpha] elif len(color)==4: return color else: raise ValueError( 'Color has to be a 3 or 4 tuple (RGBA)' ) def TkColor(col): """col should be a rgb triplet of int 0-255 or 0-1""" if max(col)<=1.0: col = map( lambda x: x*255, col) return '#%02X%02X%02X' % (col[0],col[1],col[2]) def ToRGB(hsv): """Convert an HSV triplet into an RGB triplet. Values range from 0.0 to 1.0. Alpha values are optional""" l = len(hsv) assert l in (3,4) assert max(hsv) <= 1.0 assert min(hsv) >= 0.0 v = hsv[2] if v == 0.0: if l==3: return (0.0, 0.0, 0.0) else: return (0.0, 0.0, 0.0,hsv[3]) s = hsv[1] if s == 0.0: if l==3: return (v, v, v) else: return (v, v, v,hsv[3]) h = hsv[0]*6.0 if h>=6.0: h = 0.0 i = int(h) f = h - i p = v*(1.0 - s) q = v*(1.0-(s*f)) t = v*(1.0-s*(1.0-f)) if i==0: if l==3: return (v,t,p) else: return (v,t,p,hsv[3]) elif i==1: if l==3: return (q,v,p) else: return (q,v,p,hsv[3]) elif i==2: if l==3: return (p,v,t) else: return (p,v,t,hsv[3]) elif i==3: if l==3: return (p,q,v) else: return (p,q,v,hsv[3]) elif i==4: if l==3: return (t,p,v) else: return (t,p,v,hsv[3]) elif i==5: if l==3: return (v,p,q) else: return (v,p,q,hsv[3]) else: print "botch in hsv_to_rgb" def ToHSV(rgb): """Convert an RGB triplet into an HSV triplet. Values range from 0.0 to 1.0. Alpha values are optional""" l = len(rgb) assert l in (3,4) assert max(rgb) <= 1.0 assert min(rgb) >= 0.0 r = rgb[0]; g = rgb[1]; b = rgb[2]; maxi = max(rgb[:3]) mini = min(rgb[:3]) if maxi > 0.0001: s = (maxi - mini)/maxi else: s = 0.0 if s < 0.0001: h = 0.0 else: delta = maxi - mini if r == maxi: h = (g - b)/delta elif g == maxi: h = 2.0 + (b - r)/delta elif b == maxi: h = 4.0 + (r - g)/delta h = h/6.0 if h < 0.0: h = h + 1.0 if l==3: return (h,s,maxi) else: return (h,s,maxi,rgb[3]) def Map(values, colorMap, mini=None, maxi=None): """Get colors corresponding to values in a colormap""" values = Numeric.array(values) if len(values.shape)==2 and values.shape[1]==1: values.shape = ( values.shape[0], ) elif len(values.shape) > 1: print 'ERROR: values array has bad shape' return None cmap = Numeric.array(colorMap) if len(cmap.shape) !=2 or cmap.shape[1] not in (3,4): print 'ERROR: colorMap array has bad shape' return None if mini is None: mini = min(values) else: values = Numeric.maximum(values, mini) if maxi is None: maxi = max(values) else: values = Numeric.minimum(values, maxi) valrange = maxi-mini if valrange < 0.0001: ind = Numeric.ones( values.shape ) else: colrange = cmap.shape[0]-1 ind = ((values-mini) * colrange) / valrange col = Numeric.take(colorMap, ind.astype(viewerConst.IPRECISION)) return col def array2DToImage( array2D, cmap, width=None, height=None, numComponents=4,texture=1, maxi=None, mini=None): #build the image: if width is None: width=array2D.shape[0] if height is None: height=array2D.shape[1] #texture sets the image dimensions to the smallest power of two if texture: dim1 = dim2=1 while dim1< width: dim1=dim1<<1 while dim2< height: dim2=dim2<<1 colors = Map(array2D.ravel(), cmap,mini=mini, maxi=maxi ) ###7/19: because these are Numeric arrays???!!!! ###7/19colors.shape = (width, height,3) colors.shape = (height, width,3) colors = colors*255 colors = colors.astype('B') tex2Dimage = Numeric.ones((dim2,dim1,numComponents), 'B') ###7/19: because these are Numeric arrays???!!!! ###7/19tex2Dimage = Numeric.ones((dim1,dim2,numComponents), 'B') ###7/19 tex2Dimage[:width,:height,:3] = colors tex2Dimage[:height,:width,:3] = colors return tex2Dimage def HSVRamp(size=256, upperValue=.6666666666666667): """Generate an HSV color ramp, values range from 0.0 to 1.0 """ assert size > 0 h = [] v = upperValue if size > 1: step = v/(size-1) else: step = v for i in range(size): h.append(v) v -= step if v < 0: v = 0 h = Numeric.array(h,'f') h.shape = (size, 1) sv = Numeric.ones ( (size, 2), viewerConst.FPRECISION ) hsv = Numeric.concatenate( (h,sv), 1 ) return hsv def RGBRamp(size=256, upperValue=.6666666666666667): """Generate an RGB color ramp, values range from 0.0 to 1.0""" assert size > 0 hsv = HSVRamp(size, upperValue) rgb = Numeric.zeros( (hsv.shape[0], 3), viewerConst.FPRECISION ) for i in xrange(hsv.shape[0]): rgb[i] = ToRGB(hsv[i]) return rgb def RGBARamp(size=256, upperValue=.6666666666666667): """Generate an RGBA color ramp, values range from 0.0 to 1.0""" assert size > 0 hsv = HSVRamp(size, upperValue) rgb = Numeric.zeros( (hsv.shape[0], 4), viewerConst.FPRECISION ) for i in xrange(hsv.shape[0]): rgb[i][:3] = ToRGB(hsv[i]) rgb[i][3] = 1.0 return rgb def RedWhiteBlueRamp(size=256): ramp = Numeric.ones( (size, 3), 'f') mid = size/2 incr = 1./(mid-1) for i in xrange(mid): ramp[i][1] = i*incr ramp[i][2] = i*incr for i in xrange(mid): ramp[mid+i][0] = 1.-(i*incr) ramp[mid+i][1] = 1.-(i*incr) return ramp def RedWhiteBlueARamp(size=256): ramp = Numeric.ones( (size, 4), 'f') mid = size/2 incr = 1./(mid-1) for i in xrange(mid): ramp[i][1] = i*incr ramp[i][2] = i*incr for i in xrange(mid): ramp[mid+i][0] = 1.-(i*incr) ramp[mid+i][1] = 1.-(i*incr) return ramp ## had to re-implement this ramp because the version below made python crash ## aftter the ramp was created ! ## FIXME all following ramp may be problematic ## def RedWhiteBlueRamp(size=256): ## ramp = Numeric.ones( (size, 3), 'd') ## mid = size/2 ## ramp[:mid,1] = Numeric.arange(mid) / float(mid-1) ## ramp[:mid,2] = Numeric.arange(mid) / float(mid-1) ## ramp[size:mid:-1,0] = Numeric.arange(mid) / float(mid-1) ## ramp[size:mid:-1,1] = Numeric.arange(mid) / float(mid-1) ## return ramp.astype('f') ## def RedWhiteBlueARamp(size=256): ## ramp = Numeric.ones( (size, 4), 'd') ## mid = size/2 ## ramp[:mid,1] = Numeric.arange(mid) / float(mid-1) ## ramp[:mid,2] = Numeric.arange(mid) / float(mid-1) ## ramp[size:mid:-1,0] = Numeric.arange(mid) / float(mid-1) ## ramp[size:mid:-1,1] = Numeric.arange(mid) / float(mid-1) ## return ramp.astype('f') def RedWhiteRamp(size=256): ramp = Numeric.ones( (size, 3), 'd') ramp[:,1] = Numeric.arange(size) / float(size-1) ramp[:,2] = Numeric.arange(size) / float(size-1) return ramp.astype('f') def RedWhiteARamp(size=256): ramp = Numeric.ones( (size, 4), 'd') ramp[:,1] = Numeric.arange(size) / float(size-1) ramp[:,2] = Numeric.arange(size) / float(size-1) return ramp.astype('f') def WhiteBlueRamp(size=256): ramp = Numeric.ones( (size, 3), 'd') ramp[::-1,0] = Numeric.arange(size) / float(size-1) ramp[::-1,1] = Numeric.arange(size) / float(size-1) return ramp.astype('f') def WhiteBlueARamp(size=256): ramp = Numeric.ones( (size, 4), 'd') ramp[::-1,0] = Numeric.arange(size) / float(size-1) ramp[::-1,1] = Numeric.arange(size) / float(size-1) return ramp.astype('f') def GreyscaleRamp(size=256): ramp = Numeric.ones( (size, 3), 'd') ramp[:,0] = Numeric.arange(size) / float(size-1) ramp[:,1] = Numeric.arange(size) / float(size-1) ramp[:,2] = Numeric.arange(size) / float(size-1) return ramp.astype('f') if __name__ == '__main__': def test(): print '10000 hsv->rgb' for i in range(100): for j in range(100): d = rgb( (i/100, j/100, (i+j)/100) ) print '10000 rgb->hsv' for i in range(100): for j in range(100): d = hsv( (i/100, j/100, (i+j)/100) ) cmap = RGBRamp() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/.project0000644000175000017500000000055011456141347021342 0ustar debiandebian DejaVu org.python.pydev.PyDevBuilder org.python.pydev.pythonNature mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/ColorChooser.py0000644000175000017500000001777411111122322022642 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/ColorChooser.py,v 1.16 2008/11/19 23:44:18 sanner Exp $ # # $Id: ColorChooser.py,v 1.16 2008/11/19 23:44:18 sanner Exp $ # from copy import deepcopy import Pmw import Tkinter, numpy.oldnumeric as Numeric import Slider, ColorWheel class ColorChooser: """Class of a color picker """ # example of valid targetDict # lTargetDict = { # 'ambient light': # (self.viewer.lightModel.ambient[:3], # 'RGB', # self.viewer.LMColor # ), # 'background': # (self.viewer.currentCamera.backgroundColor[:3], # 'RGB', # self.viewer.CurrentCameraBackgroundColor # ), # } def __init__(self, master=None, targetDict={}, targetKey=None, gridCfg=None): self.master = master if hasattr(self.master, 'withdraw'): self.master.title('Color Chooser') self.master.protocol('WM_DELETE_WINDOW', self.master.withdraw ) self.frame = Tkinter.Frame(self.master, relief=Tkinter.RIDGE, borderwidth=3) self.topFrame = Tkinter.Frame(self.frame) # target self.targetDict = targetDict self.targetKey = None lTargetDictKeys = targetDict.keys()[:] lTargetDictKeys.sort() if targetKey is not None: self.comboBoxTarget = Pmw.ComboBox( self.master, label_text='target:', labelpos='w', #entryfield_value=, scrolledlist_items=lTargetDictKeys, selectioncommand=self.setTarget ) self.comboBoxTarget.pack(side='top', fill='x') self.saveCol = Tkinter.Frame(self.topFrame) self.currentColor = Tkinter.Label(self.saveCol, text='Current', width=10, relief = Tkinter.SUNKEN, background = '#FFFFFF', foreground = '#FF988E', borderwidth=3 ) self.currentColor.pack() f = Tkinter.Frame(self.saveCol) self.save = Tkinter.Button(f, text='Save', relief = Tkinter.RAISED, command=self.SaveColor,width=7) self.save.pack(side=Tkinter.TOP) self.swap = Tkinter.Button(f, text='Swap', relief = Tkinter.RAISED, command=self.SwapColor,width=7) self.swap.pack(side=Tkinter.TOP) self.restore = Tkinter.Button(f, text='Restore', relief = Tkinter.RAISED, command=self.RestoreColor,width=7) self.restore.pack(side=Tkinter.TOP) f.pack() self.savedColor = Tkinter.Label(self.saveCol, text='Saved', width=10, relief = Tkinter.SUNKEN, background = '#FFFFFF', foreground = '#FF988E', borderwidth=3 ) self.savedColor.pack() self.saveCol.pack(side = Tkinter.LEFT) # target if targetKey is not None: startingColorRGB = self.targetDict[targetKey][0] else: startingColorRGB = (1,1,1,1) self.hsWheel = ColorWheel.ColorWheel(self.topFrame, circles=6, stripes=30, startingColorRGB=startingColorRGB ) self.hsWheel.AddCallback(self.UpdateCurrentColor) self.hsWheel.canvas.pack(side = Tkinter.LEFT) self.topFrame.pack() self.savedHsvColor = deepcopy(self.hsWheel.Get()) if len(startingColorRGB) == 4: self.savedHsvColor[3] = startingColorRGB[3] coltk = self.hsWheel.Get(mode='TkRGB') self.currentColor.config( background = coltk ) self.savedColor.config( background = coltk ) self.value = Slider.Slider(self.frame, label='Value', immediate=1, minval=0.0, maxval = 1.0, init=1.0) self.value.frame.pack() self.value.AddCallback(self.NewValue) self.alpha = Slider.Slider(self.frame, label='Alpha', immediate=1, minval=0.0, maxval = 1.0, init=1.0) self.alpha.frame.pack() self.alpha.AddCallback(self.NewValue) if gridCfg: self.frame.grid( **gridCfg) else: self.frame.pack(ipadx=2, ipady=2, padx=2, pady=2) # target if targetKey is not None: self.setTarget(targetKey) def setTarget(self, val): #print "setTarget", val if self.targetKey is not None: self.RemoveCallback(self.targetDict[self.targetKey][2]) self.targetKey = val self.comboBoxTarget.setentry(val) lTargetTuple = self.targetDict[val] self.Set(lTargetTuple[0], mode=lTargetTuple[1]) self.AddCallback( lTargetTuple[2] ) def AddCallback(self, func): """Add a callback fuction""" self.hsWheel.AddCallback(func) def RemoveCallback(self, func): """Delete a callback fuction""" self.hsWheel.RemoveCallback(func) def UpdateCurrentColor(self, color): """Change the color of the current color label""" col = self.hsWheel.Get(mode='TkRGB') self.currentColor.config( background = col ) def NewValue(self, event): """Redo the color wheel with a new value, update color boxes""" v = self.value.Get() hsv = self.hsWheel.Get('HSV') if len(hsv) == 4: hsv[3] = self.alpha.Get() if v != hsv[2]: hsv[2]=v self.hsWheel.Set(hsv, 'HSV') self.hsWheel.Callbacks() elif len(hsv) == 4: self.hsWheel.Set(hsv, 'HSV') self.hsWheel.Callbacks() def SaveColor(self): """Save current color into second color box""" self.savedHsvColor = deepcopy(self.hsWheel.Get()) self.savedHsvColor[3] = self.alpha.Get() col = self.hsWheel.Get(mode='TkRGB') self.savedColor.config( background = col ) def RestoreColor(self): """Restore color from second color box """ self.Set(deepcopy(self.savedHsvColor), 'HSV') def SwapColor(self): """Exchange colors in first and second box""" coltk = self.hsWheel.Get(mode='TkRGB') self.savedColor.config( background = coltk ) saved_col = deepcopy(self.savedHsvColor) self.savedHsvColor = deepcopy(self.hsWheel.Get()) self.savedHsvColor[3] = self.alpha.Get() self.Set(saved_col, 'HSV') def Set(self, col, mode='RGB', run=True): """Set the color chooser to a given RGB or HSV triplet (0. to 1.) """ assert mode in ('HSV', 'RGB') assert len(col) in (3,4) self.hsWheel.Set( col, mode, run ) self.value.Set( self.hsWheel.Get('HSV')[2], update=0 ) if len(col) == 4: self.alpha.Set( col[3], update=0 ) self.UpdateCurrentColor(None) def Wysiwyg(self, onOff): """Toggle Wysiwyg mode for color wheel. When this flag iset, the colors of the wheel are recomputed for each new value""" assert onOff in (0,1) self.hsWheel.Wysiwyg(onOff) def showColorChooser(self, target=None): """ """ if self.master.winfo_ismapped() == 0: self.master.deiconify() self.master.lift() if target is not None: self.setTarget(target) def hideColorChooser(self, event=None): #print "hideColorChooser", self if self.master.winfo_ismapped() == 1: self.master.withdraw() def toggleColorChooser(self, event=None): #print "toggleColorChooser", self if self.master.winfo_ismapped() == 1: self.master.withdraw() else: self.master.deiconify() self.master.lift() if __name__ == '__main__': root = Tkinter.Tk() cc = ColorChooser(root) def MyCallback(col): print 'col', col cc.AddCallback(MyCallback) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/quad_strip.py0000644000175000017500000004210511162014333022406 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: 2000 Authors: Michel Sanner, Kevin Chan # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI 2000 # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/quad_strip.py,v 1.29 2009/03/23 23:18:51 vareille Exp $ # # $Id: quad_strip.py,v 1.29 2009/03/23 23:18:51 vareille Exp $ # from opengltk.OpenGL import GL from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.viewerFns import checkKeywords import DejaVu.datamodel, DejaVu.viewerConst, Numeric from DejaVu.colorTool import glMaterialWithCheck, resetMaterialMemory class Quad_strip(IndexedPolygons): """ Class to draw a quad strip or multiple quad strip geometries. """ keywords = IndexedPolygons.keywords + [ 'stripBegin', 'fnormals', ] def __init__(self, name=None, check=1, **kw): """ Constructor: Takes an array of vertices and splits it into separate quad strips at specific vertices specified by stripBegin, which is and array of indices. Generates faceSet. In this class, a face corresponds to a quad strip. Calls IndexedPolygons constructor. Calls MatBindingMode() to set the correct mode specific to a quad strip, overwriting the binding mode set by MaterialBindingMode in the Geom class. Initializes frontPolyMode to FILL. Initializes currentCol and currentMat.""" apply( IndexedPolygons.__init__, (self, name, check), kw) for face in self.materials.keys(): for j in range(5): self.MatBindingMode(j, face) self.frontPolyMode = GL.GL_FILL #self.inheritFrontPolyMode = 0 self.currentCol = [] for i in range(4): self.currentCol.append(-1.0) self.currentMat = [] for i in range(2): mat = [] for j in range(5): rgba = [] for k in range(4): rgba.append(-1.0) mat.append(rgba) self.currentMat.append(mat) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: Set polygon's vertices, faces, normals or materials check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ v = kw['vertices'] self.stripBegin = kw.get( 'stripBegin') if self.stripBegin is None: self.stripBegin = [0, len(v)] for j in self.stripBegin: assert j%2==0 faces = [] for i in range(0, len(self.stripBegin)-1): strip_ind = () for j in range(self.stripBegin[i], self.stripBegin[i+1]): strip_ind = strip_ind + (j,) faces.extend([strip_ind]) kw['faces'] = faces self.fnormals = kw.get( 'fnormals') redoFlags = apply( IndexedPolygons.Set, (self, check, 0), kw ) return self.redoNow(redo, updateOwnGui, redoFlags) def MatBindingMode(self, propNum, face=GL.GL_FRONT): """ For the given face and material property corresponding to propNum, the method sets the binding mode. If there is one value, the mode is OVERALL; if the number of values equals the number of vertices, strips, or faces(quads), the mode is PER_VERTEX, PER_PART, or PER_FACE, respectively. Else, mode is none. """ OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 #NONE, OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 num = propNum f = face nn = self.materials[f].prop[num].shape[0] self.inheritMaterial = 0 if nn == 1: self.materials[f].binding[num] = OVERALL elif nn == len(self.vertexSet.vertices): self.materials[f].binding[num] = PER_VERTEX elif hasattr(self, 'faceSet') and nn == len(self.faceSet): self.materials[f].binding[num] = PER_PART elif hasattr(self, 'IndexedFaceSet') and nn==len(self.IndexedFaceSet): self.materials[f].binding[num] = PER_FACE self.shading = GL.GL_FLAT self.GetNormals() else: self.materials[f].binding[num] = -1 self.inheritMaterial = 1 def buildIndexedFaceSet(self): """Build the set of indices describing the strips""" f = [] for stripNum in range(1,len(self.stripBegin)): for i in range(self.stripBegin[stripNum-1], self.stripBegin[stripNum]-3, 2): f.extend([(i, i+1, i+3, i+2)]) self.IndexedFaceSet = DejaVu.datamodel.FaceSet( f, (0,0) ) def GetNormals(self): """ Gets the proper normals for smooth or flat shading. Calls buildIndexedFaceSet(). Sets face normals or computes them if not given. Sets object normals to the vertex normals for smooth shading or to the face normals for flat shading. If shading none, normals are none.""" if self.shading==GL.GL_NONE: self.normals = None else: if hasattr(self, 'faceSet'): self.StripFaceSet = self.faceSet self.buildIndexedFaceSet() self.faceSet = self.IndexedFaceSet if self.fnormals: self.faceSet.normals.SetValues(self.fnormals) else: self.FaceNormalFunction( self.ComputeFaceNormals ) self.faceSet.normals.ComputeMode( DejaVu.viewerConst.AUTO ) if self.shading==GL.GL_FLAT: if hasattr(self, 'faceSet'): self.normals = self.faceSet.normals.GetProperty() else: self.normals = None elif self.shading==GL.GL_SMOOTH: self.normals = self.vertexSet.normals.GetProperty() self.faceSet = self.StripFaceSet else: self.normals = None def isNewColor(self, c=None): """ Compares new color c to the current color. If the same, method returns 0. If the new color is different, the current color gets the values of the new color, and the method returns 1. """ if c is None: for i in self.currentCol: i = -1.0 # set an impossible color return 0 elif abs(c[0]-self.currentCol[0]) < 0.0001 and \ abs(c[1]-self.currentCol[1]) < 0.0001 and \ abs(c[2]-self.currentCol[2]) < 0.0001 and \ abs(c[3]-self.currentCol[3]) < 0.0001: return 0 else: self.currentCol[0] = c[0] self.currentCol[1] = c[1] self.currentCol[2] = c[2] self.currentCol[3] = c[3] return 1 ## def isNewMaterial(self, face, prop, c): ## """ For the given face (face) and property number (prop), the method ## compares the new material value c to the current material. If ## the same, method returns 0. If different, the current material gets ## the new material value, and the method returns 1. """ ## f = not(face==GL.GL_FRONT) ## if not c: ## for i in range(2): ## for j in range(5): ## for k in self.currentMat[i][j]: ## k = -1.0 ## return 0 ## elif abs(c[0]-self.currentMat[f][prop][0]) < 0.0001 and \ ## abs(c[1]-self.currentMat[f][prop][1]) < 0.0001 and \ ## abs(c[2]-self.currentMat[f][prop][2]) < 0.0001 and \ ## abs(c[3]-self.currentMat[f][prop][3]) < 0.0001: ## return 0 ## else: ## self.currentMat[f][prop][0] = c[0] ## self.currentMat[f][prop][1] = c[1] ## self.currentMat[f][prop][2] = c[2] ## self.currentMat[f][prop][3] = c[3] ## return 1 def DisplayFunction(self): """ Either executes the present display list or creates a display list to display the quad strip. """ OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 #NONE, OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 propConst = DejaVu.viewerConst.propConst noCol = 0 if self.viewer.currentCamera.renderMode == GL.GL_SELECT: save = self.dpyList temp = self.primitiveType if self.frontPolyMode == GL.GL_FILL: self.primitiveType = GL.GL_POLYGON elif self.frontPolyMode == GL.GL_LINE: self.primitiveType = GL.GL_LINE_LOOP elif self.frontPolyMode == GL.GL_POINT: self.primitiveType = GL.GL_POINTS self.faceSet = self.IndexedFaceSet IndexedPolygons.DisplayFunction(self) self.faceSet = self.StripFaceSet self.primitiveType = temp self.dpyList = save return if self.dpyList: IndexedPolygons.DisplayFunction(self) def Draw(self): OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 #NONE, OVERALL, PER_VERTEX, PER_PART, PER_FACE = -1, 10, 11, 12, 13 propConst = DejaVu.viewerConst.propConst noCol = 1 vert = self.vertexSet.vertices.array if len(vert)==0: return if self.materials[GL.GL_FRONT] and not self.inheritMaterial: mat = self.materials[GL.GL_FRONT] frontMat = fpProp = [] frontMatBind = fpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) fpProp.append(p) fpBind.append(b) fpProp.append(mat.prop[4]) fpBind.append(mat.binding[4]) # frontMat = self.materials[GL.GL_FRONT].prop # frontMatBind = self.materials[GL.GL_FRONT].binding else: frontMat = None frontMatBind = None if self.materials[GL.GL_BACK] and not self.inheritMaterial: mat = self.materials[GL.GL_BACK] backMat = bpProp = [] backMatBind = bpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) bpProp.append(p) bpBind.append(b) bpProp.append(mat.prop[4]) bpBind.append(mat.binding[4]) # backMat = self.materials[GL.GL_BACK].prop # backMatBind = self.materials[GL.GL_BACK].binding else: backMat = None backMatBind = None ## texCoords = None ## if hasattr(self.vertexSet, "texCoords"): ## if self.vertexSet.texCoords.status >= viewerConst.COMPUTED: ## texCoords = self.vertexSet.texCoords.array if not self.frontAndBack is None: face = GL.GL_FRONT else: face = GL.GL_FRONT_AND_BACK if not self.normals: # overall color for no normals or lighting if frontMat: if frontMatBind[noCol] == OVERALL: GL.glColor4fv( frontMat[noCol][0] ) else: if len(self.normals)==1: # overall normal n = self.normals GL.glNormal3dv(n[0]) if frontMat: for j in range(5): # overall materials if frontMatBind[j] == OVERALL: glMaterialWithCheck( face, propConst[j], frontMat[j][0] ) if backMat and not self.frontAndBack: for j in range(5): if backMatBind[j] == OVERALL: glMaterialWithCheck( GL.GL_BACK, propConst[j], backMat[j][0] ) self.isNewColor() #self.isNewMaterial(0,0,0) n = self.normals # loop over each strip for stripNum in range(1,len(self.stripBegin)): c = vert[self.stripBegin[stripNum-1]:self.stripBegin[stripNum]] GL.glPushName(stripNum) GL.glBegin(GL.GL_QUAD_STRIP) # per part material properties if frontMat: if frontMatBind[noCol] == PER_PART: if self.isNewColor(c=frontMat[noCol][stripNum-1]): GL.glColor4fv(frontMat[noCol][stripNum-1]) if n: if frontMat: for j in range(5): if frontMatBind[j]==PER_PART: glMaterialWithCheck( face, propConst[j], frontMat[j][stripNum-1] ) if backMat and not self.frontAndBack: for j in range(5): if backMatBind[j] == PER_PART: glMaterialWithCheck( GL.GL_BACK, propConst[j], backMat[j][stripNum-1] ) # loop over each vertex in a strip i = 0 for v in c: if n: if self.shading==GL.GL_FLAT: if i > 1 and i%2==0: GL.glNormal3dv(n[(self.stripBegin[stripNum-1]+i-(2*stripNum))/2]) elif self.shading==GL.GL_SMOOTH: GL.glNormal3dv(n[self.stripBegin[stripNum-1]+i]) else: pass # per face (per triangle) material properties if not n: if frontMat: if frontMatBind[noCol] == PER_FACE: if i > 1 and i%2==0: if self.isNewColor(c=frontMat[noCol][(self.stripBegin[stripNum-1]+i-(2*stripNum))/2]): GL.glColor4fv(frontMat[noCol][(self.stripBegin[stripNum-1]+i-(2*stripNum))/2]) else: if frontMat: for k in range(5): if frontMatBind[k] == PER_FACE: if i > 1 and i%2==0: glMaterialWithCheck( face, propConst[k], frontMat[k][(self.stripBegin[stripNum-1]+i-(2*stripNum))/2] ) if backMat and not self.frontAndBack: for k in range(5): if backMatBind[k] == PER_FACE: if i > 1 and i%2==0: glMaterialWithCheck( GL.GL_BACK, propConst[k], backMat[k][(self.stripBegin[stripNum-1]+i-(2*stripNum))/2] ) # per vertex material properties if not n: if frontMat: if frontMatBind[noCol] == PER_VERTEX: if self.isNewColor(c=frontMat[noCol][self.stripBegin[stripNum-1]+i]): GL.glColor4fv(frontMat[noCol][self.stripBegin[stripNum-1]+i]) else: if frontMat: for k in range(5): if frontMatBind[k] == PER_VERTEX: glMaterialWithCheck( face, propConst[k], frontMat[k][self.stripBegin[stripNum-1]+i] ) if backMat and not self.frontAndBack: for k in range(5): if backMatBind[k] == PER_VERTEX: glMaterialWithCheck( GL.GL_BACK, propConst[k], backMat[k][self.stripBegin[stripNum-1]+i] ) # draw vertex GL.glVertex3dv(v) i = i + 1 GL.glEnd() GL.glPopName() return 1 if __name__=='__main__': import pdb, numpy.oldnumeric as Numeric from DejaVu import Viewer vi = Viewer() vert = [(0, 1, 0), (1, 0, 1), (1, 1, 0), (2, 0, -1), (2, 1, 0), (3, 0, 1), (3, 1, 0), (4, 0, -1), (4, 1, 0), (5, 0, 1), (5, 3, 0), (6, -2, 1)] v1 = Numeric.array(vert) v2 = v1 + 3.0 v3 = Numeric.concatenate( (v1,v2) ) colors = [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0)] v4 = v2 + 3.0 v5 = Numeric.concatenate( (v3,v4) ) strip3 = Quad_strip(vertices = v5, stripBegin=[0,12,24,36], materials = colors+colors[0:3]) #strip.Set(materials = [(1, 0, 0)]) vi.AddObject(strip3) strip2 = Quad_strip(vertices = v3, stripBegin=[0,12,24], materials = colors[0:10]) # strip2.Set(materials = [(0, 1, 0), (0, 0, 1)]) vi.AddObject(strip2) strip = Quad_strip(vertices = vert, materials = colors[0:5]) # strip.Set(materials = [(1, 0, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1) ]) vi.AddObject(strip) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/cw.ppm0000644000175000017500000015124507352707225021035 0ustar debiandebianP6 # CREATOR: XV Version 3.10 Rev: 12/16/94 134 134 255 insw|KPUY^cglquz8=BGMRV[`dinsw|*/4:?EJOUY^c g l q u z  !',17<BGL Q V [ ` d insw| $)/49> C H O TY^cglquz !&+0 5 < AFKPV[`dinrw|    $ ) . 38=CHMRX]cglquz     !&+05:?EJPUZ_di n r w!|!!""""""!!!     $).17=BGLQX]!b"g$l$q%u%z%&&&''''&&&%%%$$"!  "&+049>EJ O!T"Y$^%d&i'n)r)w*|**+++,,+++***))'&%$"!    %).37< A!F"K$Q%V&[)`*e+l,q.u.z.///000000///...,+*)&%$"!  !   " &!+!0"5$9$>%C&H'M)R*Y+^,c.h/m0r1w3|33444555544433310/.,+*)'&$"  ''&% $ $"!"" $%%)%.&3'7'<)A*F*K+P,U.Z/_1e3k4p5u7z7888999::999888775431/.,+*)&$!  /.,+ + *))'&'")')+*0+5+9,>.C.G/L0R1X3]4b5g7m8r9w:|<<===>>>>>>===<<:98754310/,*'&$! 75443 100/.,, ,%,*../3/80<1A1F3J4O4T5Z7_8d:iz?AAABBBCCCCBBBAAA?>=<:875430.,*'%$! =<<:9 8875443 1"1'1,30354:5>5C7H8L8Q9V:[<`=g>l?qAvB{CEFFFGGGHHGGGFFFECBA?>=<:97430.+*'%"  CBBA A ?>==<:9!9$8&7*7.73889=9A:FY>^?cBhCnEsFyG~HJJKKKLLLLLLKKKJJHGFECB?>=:97410.+)&$! HHG G FEECBAA!?$>'=*=,<0<5=:=>>C?H?MAQBVB[C`EeFkGpHuJ{KLMOOPPPQQQQPPPOOMLKJHGFECA>=:8741/,*'$! OMM L LLKJJHG"F%F'E+C.B0B4A8A=BACFCKEOFTFYG]HbHhKmLrMwO|PQRRTTUUUVVUUUTTRRQPOMLKHGECA>=:8540.+'%" TTRR RQQQPO M"M%L)K+J.J1H4G7G:F?GCGHHMJQJVK[L_LdMiOpPuQzRTUVXYYYZZZZZZYYXXVUTRQPOMKJGEBA><:741.+)%"  ZYYY XXXVVU U$T&R)R,Q/P1O5O8M:L>KBKFLKMPMTOYP^PbQgRlTqUvV|XYZ[]]^^^____^^^]][ZYXVUTQPMKHGEBA>:851/,)&$  ___^ ^^]][[ [$Z&Z*Y,X/V3V5U8TRAQEPHQMQRRVT[T`UdViVnXsYyZ~[]^``bbcccddcccbb``^][ZYXVTQOMKHFEA><853/,*&$  edd cccbbb `$`&`*_._0^3]7[9[nAmClGlJkLiPhRhUgYe[e`eegihnhsiwk|klmnqrssuuvvvvvvuussrqnmlkhgdb_^[YURPLJGCA>:73/,)%! zzz zzzyyy!w$w'w+v/v3v7u9u=sAsEsGrKqMqPpTnVmYm]l_kckhlllqmvnznpqrsuvwyyzz{{{{zzyywvusrqnmkhedb_]YVTPMKGEA=973/+'$!  ~ ~$~'|+|.{1{5{9z=zAzCyGyKyMwQvTuVuZs]r_rcqepkpnqsryr|suuvwz{|~~~~~|{zwvusqnlkhec_]ZVTQMKGCA=951.+'$   "&*.158BFJLPTX[_bdhkmqsv{~{yvsqmkhdb_[XTPLJFB>:74/+'$| wsn !%*.15:>AEHLPTVZ^behknqswz~|zwsqnkheb^ZVTPLHEA>:51.*%!~y u qlh  $'+048BFKORUY]`dhknruy{~~{yurnkhd`]YUROKFB>:71.*&!|wsp k gc^  $',048=AEHLQUY]_cgknruy||yurnkgc_]YUQLHEA=840,'$~ zuqmh d_[ "&*.37:>BGKORX[_cgimquy||yuqmigc_[XROKGB>:73.*&{"vrnie `]X  $),048=AEHMQUY^beimqsw{݃{wsqmieb^YUQMHEA=840,|)y$s pkgb^ YUP !&*.37:>CGKOTX[_dhlpsw{~މڅց~{wsplhd_[XTOKGC>:73~.z*u&q!lhc_Z VQL "'+049=AEJMQUZ^beknrvz~݌؈ԅЁ~zvrnkeb^ZUQMJEA=94{0v+r'm"id`[V RMJ  $),15:>CGKPTX[`dhlquy|ޒڏՌш΄ʀ|yuqlhd`[XTPKGC>:|5w1s,n)k$e b]XTO KFB !%*.37 "&+/48=BFKOTX]`dhmquy~ݜ٘Քё̍ȉŅ~yuqmhd`]XTOKFBz=v8q4m/h+c&_"ZVQMH E?< $),15:>CGLPUY^bgknsw{ƃƈƌŏœŘśşâæê®°ߢڟ֛Әϓʏƌˆ{wsnkgb^YUPLG{Cw>r:m5i1d,`'[$XROJF A =8 !%*.37: 51, $',059>BGKPTY]beknsw|ԁԅԊԎԒԖԛԟԢԦӫӯӳӷӺѽ߳ۯثӦϢʟƛ–|wsnkeb]YTzPvKqGmBh>d9_5[0V,R'M$HE?<7 1.)  $).17:?CHLQUZ^cglquz~كنٌُٜٔ٘١٥ةحزصعؽݵٲԭЩ̥ǡÜ~zuplgc^Z{UwQrLnHiCe?`:]7X1R,O)J$E A<73 .)%  %).37%9!40+&"  !&*/48=BFKPTY^bgkpuy~ѽιȴï~yupk{gvbq]mYhTcP_KZFUBQ=L8G4C/>*9&5!0+'"  !&+/49=BGKPUY^cglpuz~ξʺŵ~zup{lvgrcm^hYdU_P[KVGQBM=H9C4?/:+5&1!,'$   "&+049>BGLPUZ^chlqvzƺzv|qwlrhnci^dZ`U[PVLRGMBH>E9?4:07+1&,")$   "'+059>CGLQUZ_chmqv{¼{|vwqsmnhice_`Z]UXQRLOGJCE>A9<5703+.')"%    "',05:>CHLQVZ_dhmrv{~{yvsrpmkhedb_]ZXVTQOLJHFCA><:8530.,*'%"!  "',05:>CHLQVZ_dhmrv{{~vyrsmphkde_bZ]VXQTLOHJCF>A:<5803,.'*"%!   "'+059>CGLQUZ_chmqv{{v|qwmshnck_eZ`U]QXLRGOCJ>E9A5<07+3'.")%     "&+049>BGLPUZ^chlqvzzvq|lwhrcn^iZdU`P[LVGRBM>H9E4?0:+7&1",)$    !&+/49=BGKPUY^cglpuz~~zupl{gvbr^mYiUdP_K[GVBQ=M9H4C/?+:&5!1,'$   !&*/48=BFKPTY]bgkpuy~~yupkg{bv]qYmThPcK_FZBU=Q8L4G/C*>&9!50+'"  !%*/38=AFKOTX]bekpsy~~yspkebz]uXqTlOgJcF^AZ=U8P3L/G*B%>!940+& "  %*.38BGKPTY]beknsw||wsnkeb]YTPzKvGqBm>h9d5_0[,V'R$MJE?< 71.) "&+/48=AFJORX[`dimrv{{vrmid`[XRO~JzFuAp=l8g4c/^+Z&U"QLHC> :51, !%*.37940 $',15:>CGLPUY^bgknsw{{wsnkgb^YUPLGC{>w:r5n0i,d'`$[XROJ F A=8 "&+/48=BFKOTX]`dhmquy~żʽϾ~yuqmhd`]XTOKFA=z8v4q/m+h&c"_ZVQM HE?< !%*.37  $),15:>CGKPTX[`dhlquy|ƴ˵зԷٷ޷|yuqlhd`[XTPKGC>:5|1w,s)n$k eb]XT OKFB "'+049=AEJMQUZ^beknrvz~ïȲβӲֳ۳߲~zvrnkeb^ZUQMJEA=940{+v'r"mid`[ VRMJ !&*.37:>CGKOTX[_dhlpsw{~ƭ˭ЮԮٮݮ~{wsplhd_[XTOKGC>:73.~*z&u!qlhc_ ZVQL  $),048=AEHMQUY^beimqsw{ŧȩΩө֩کߩ{wsqmieb^YUQMHEA=840,)|$y spkgb ^YUP "&*.17:>BGKORX[_cgimquy|¤ƤˤХԥ٤ݤ|yuqmigc_[XROKGB>:71.*&"{wrni e`]X  $',048BFKORUY]`dhknruy{~›ƛ˜Лԛ؛ݚ~{yurnkhd`]YUQOKFB>:71.*&!|ws p kgc^  $'+048BFJLPTX[_bdhkmqsv{ŎȎ̍эՌڌފ|{yvsqmkhdb_[XTPLJFB>:73/+'$ |wsn !%),048nAmClGlJkLiPhRhUgYe[e`eegihnhsiwk|klmnprssuuvvvvvuuussrpnmlkhgdb_^[YURPLJGCA>:73/,)%! ppp p nnnmml"l%l)k,k0k4i8i:h=gAgCeFdJdLcObR`U`Y`^bcbgcldqduezghiklmnpppqqrrqqpppnmlkihgdb`^[YXUROLJFCA=:840,)%! kki i ihhhgg"e&e*e.d0d4c7c9b=`?_B_F^H]K[O[R[V[[]`^d^i_n`s`wb~cdegikkkllmmmmllkkkhgedcb`^[ZXURQOKHFB?=9740.*&" ddd c ccbbb `$`&`*_.^0^3]7[9[RAQEPHQMQRRVT[T`UdViVnXsYyZ~[]^_`bbbccddccbbb`_^][ZYXVTQOMKHFEA><853/,*&$  ZYYY XXXVVU U$T&R)Q,Q/P1O5O8M:L>KBKFLKMPMTOYP^PbQgRlTqUvV|XYZ[]]]^^____^^]]][ZYXVUTQPMKHGEBA=:841/,)&$  TTRR RQQQPO M"M%L)K+J.J1H4G7F:F?GCGHHMJQJVK[L_LdMiOpPuQzRTUVXXYYZZZZZZYYXXVUTRQPOMKJGEBA><:741.+)%"  MMM L LLKJHHG"F%F'E+C.B0B3A8A=BACFCKEOFTFYG]HbHhKmLrMwO|PQRRTTUUUVVUUUTTRRQPOMLKHGECA><:8530.*'%" HHG G FEECBAA!?$>'=*=,<0<5=:=>>C?H?LAQBVB[C`EeFkGpHuJ{KLMOOPPPQQQQPPPOOMLKJHGFECA>=:8741/,*'$! BBA ? ?>==<:9 9$8&7*7.73889=9A:FY>^?cAhCnEsFyG~HJJJKKLLLLLLKKJJJHGFECA?>=:87410.+)&$  =<<:9 8875443 1"0'1,30354:5>5C7H8L8Q9V:[<`=g>l?qAvB{CEEFFGGGHHGGGFFEECBA?>=<:97410.+*'%"  5443 100/.,, ,%,*../3/80<1A1F3J3O4T5Z7_8d:iz??AABBBCCCCBBBAA??>=<:875430.,*'%$! /.,+ + *)''&'")')+*0+5+9,>.C.G/L0R1X3]4b5g7m8r9w:|<<===>>>>>>===<<:98754310.,*'&$! ''&% $ $"!"" $%%)%.&3'7'<)A)F*K+P,U.Z/_0e3k4p5u7z7888999::999888775430/.,+*)&$!  !   " &!+!0"5"9$>%C&H'M)R*Y+^,c.h/m0r1w3|33444555544433110/.,+*)'&$"    %).37< A!F"K$Q%V&['`*e+k,q,u.z.///000000///..,,+*'&%$"!   "&+049>EJ O!T"Y$^%d&i'n)r)w*|**+++,,+++***))'&%$"!     $).17=BGLQV]!b"g$l$q%u%z%&&&''''&&&%%%$$"      !&+/5:?EJPUZ_di n r w!|!!""""""!!!     $ ) . 38=BHMRX]cglquz !&+0 5 < AFKPU[`dinrw| $).49> C H O TY^cglquz !',17<AGL Q V [ ` d insw| */4:?EJOTY^c g l q u z  8=BGMRV[`dinsw|KPUY^cglquzinsw|mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/DataOutput.py0000644000175000017500000014147511205570602022343 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Date: Jun 2002 Author: Daniel Stoffler # # stoffler@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Daniel Stoffler and TSRI # # Revision: Guillaume Vareille, Alex Gillet # ############################################################################# from opengltk.OpenGL import GL #from opengltk.extent.utillib import glTriangleNormals from geomutils.geomalgorithms import TriangleNormals import numpy.oldnumeric as Numeric, math, string, warnings from mglutil.math import rotax from mglutil.util.misc import ensureFontCase from DejaVu.Geom import Geom from DejaVu.IndexedGeom import IndexedGeom from DejaVu.Transformable import Transformable from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.Spheres import Spheres from DejaVu.Cylinders import Cylinders from DejaVu import viewerConst from DejaVu.colorTool import glMaterialWithCheck from DejaVu.GleObjects import GleExtrude from DejaVu.glfLabels import GlfLabels import Tkinter, Pmw from mglutil.gui.InputForm.Tk.gui import InputFormDescr, InputForm ########################################################################## # # functions for generating and parsing SMF format: # # http://www.csit.fsu.edu/~burkardt/data/smf/smf.txt # (also DejaVu/FileFormats/smf.txt) # # use my Michael Garland's Qslim program # ########################################################################## def IndexedPolgonsAsSMFString(geometry): """listOfStrings <-- IndexedPolgonsAsSMFString(geometry) For a given IndexedPolygons geoemtry this function generates the textual SMF description. Currently supports vertices (v), faces (f), normals(n) and colors (c). Normals and color binding mstring are generated automatically. Texture indices (r) are not used yet but could be used to store any integer property. """ assert isinstance(geometry, IndexedPolygons) # we can only handle triangles or quads assert geometry.faceSet.faces.array.shape[1] in [3,4] lines = [] lines.append('begin\n') # vertices verts = geometry.vertexSet.vertices.array lines.extend( map(lambda x: ('v %f %f %f\n'%tuple(x)), verts) ) # faces tri = geometry.faceSet.faces.array lines.extend( map(lambda x: ('f %d %d %d\n'%(x[0]+1,x[1]+1,x[2]+1)), tri) ) # normals normals = geometry.normals if len(normals)==len(verts): lines.append('bind n vertex\n') elif len(normals)==len(tri): lines.append('bind n face\n') else: normals = None if normals: lines.extend( map(lambda x: ('n %f %f %f\n'%tuple(x)), normals) ) # colors if geometry.materials[1028].binding[1]==11: #per vertex color lines.append('bind c vertex\n') cols = geometry.materials[1028].prop[1] lines.extend( map(lambda x: ('c %f %f %f\n'%tuple(x[:3])), cols) ) lines.append('end\n') return lines def writePolygonsAsSMF(geometry, filename): """Write a IndexedPolygons geometry to a file""" f = open(filename, 'w') map( lambda x, f=f: f.write(x), IndexedPolgonsAsSMFString(geometry) ) f.close() def ParseSMFString(stringList): """v,f,n,c,r <-- ParseSMFString(stringList) Parse an ascii SMF file and returnes a list of 3D vertices, triangular faces (0-based indices, faces with more edges generate warnings), normals, colors and 2D texture coordinates. """ vertices = [] faces = [] normals = [] colors = [] textures = [] fi = 0 for l in stringList: w = l.split() if w[0]=='v': # vertices vertices.append( [float(w[1]),float(w[2]),float(w[3])] ) elif w[0]=='f': # faces if len(w) > 4: warnings.warn("face %d has more than 3 edges"%fi); faces.append( [int(w[1])-1,int(w[2])-1,int(w[3])-1] ) fi += 1 if w[0]=='n': # normal vectors normals.append( [float(w[1]),float(w[2]),float(w[3])] ) if w[0]=='c': # colors colors.append( [float(w[1]),float(w[2]),float(w[3])] ) if w[0]=='r': # 2D texture indices textures.append( [float(w[1]),float(w[2])] ) return vertices, faces, normals, colors, textures def readSMF(filename): """Read an SMF ascii file and return an IndexedPolygons geometry""" f = open(filename) data = f.readlines() f.close() v, f, n, c, t = ParseSMFString(data) return v, f, n, c, t class OutputNode: """This base class recursively loops over a given DejaVu geom tree and computes the transformation matrices at each level.""" def __init__(self): self.output = [] # list describing the formated data self.lenGeoms = 0 # used for the progress bar to determine how many # visible geoms are in the viewer def configureProgressBar(self, **kw): # this method is to be implemented by the user from outside pass def updateProgressBar(self, progress=None): # this method is to be implemented by the user from outside pass def countGeoms(self, obj): for child in obj.children: if child.visible: check = self.checkGeom(child) if check: self.lenGeoms = self.lenGeoms + 1 self.countGeoms(child) def loopGeoms(self, obj): """ this calls the recursive method """ ## #commented out 2.7.02 DS, we discard now root transformation ## # we reset the scale of rootObject to 1,1,1 ## if obj == obj.viewer.rootObject: ## scaleFactor = obj.scale ## obj.SetScale([1.,1.,1.]) # initialize the progress bar to be ratio self.lenGeoms = 0 # initialize this to 0 self.countGeoms(obj) # determine lenght of visible geoms self.lenGeoms = self.lenGeoms + 1 # FIXME: dont know why whe # always have 1 too few self.configureProgressBar(init=1, mode='increment', granularity=1, progressformat='ratio', labeltext='parse geoms to vrml2', max=self.lenGeoms) GL.glPushMatrix() GL.glLoadIdentity() self._loopGeomsRec(obj) # call recursive method GL.glPopMatrix() ## #commented out 2.7.02 DS, we discard now root transformation ## # now we set the scale factor back to what it was ## if obj == obj.viewer.rootObject: ## obj.SetScale(scaleFactor) def _loopGeomsRec(self, obj): """ recursive method """ GL.glPushMatrix() # we discard root object transformation: if obj is not obj.viewer.rootObject: if hasattr(obj, 'MakeMat'): obj.MakeMat() obj.VRML2CreatedPROTOForThisGeom = 0 # flag used in vrml2 doit() for i in range(len(obj.instanceMatricesFortran)): GL.glPushMatrix() GL.glMultMatrixf(obj.instanceMatricesFortran[i]) obj.instanceMatricesFortranIndex = i # flag used in stl and vrml2 doit() matrix = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX) self.NodeRepr(obj, matrix) for child in obj.children: if child.visible: self._loopGeomsRec(child) GL.glPopMatrix() GL.glPopMatrix() # Restore the matrix del obj.instanceMatricesFortranIndex # clean up object del obj.VRML2CreatedPROTOForThisGeom def NodeRepr(self, obj, matrix): """ This method, to be implemented by sublcass, should generate stl, vrml2 etc descriptions of DejaVu geoms""" pass def checkGeom(self, geom): # decides which geoms will be output. return 0 means don't save this if geom is None: return 0 elif not isinstance(geom, Geom): return 0 elif not geom.visible: return 0 elif len(geom.vertexSet)==0: return 0 elif isinstance(geom, IndexedGeom) and len(geom.faceSet) == 0: return 0 else: return 1 class OutputSTL(OutputNode): """ generates a list of strings describing DejaVu geoms in STL (stereolithography) format (don't mix this with standard template library). """ # THIS STUFF HERE WAS USED IN GLEObject ## def getSTL(self, reverse=0, **kw): ## """ returns a string describing vertices and normals in the STL format. ## """ ## from OpenGL import GL ## # force per face normal calculation ## if self.shading != GL.GL_FLAT: ## oldmode = self.shading ## oldnorm = self.normals ## self.shading = GL.GL_FLAT ## self.GetNormals() ## norms = self.normals ## self.shading = oldmode ## self.normals = oldnorm ## faces = self.getFaces() ## if len(faces) < 1: ## raise RuntimeError("No faces found in geometry ",self.name) ## if faces.shape[1] > 3: ## raise RuntimeError("More than 3 indices per face in ",self.name) ## vert = self.getVertices() ## if len(vert)<3: ## raise RuntimeError("Less that 3 vertices found in geometry ", ## self.name) ## fn = norms ## if len(fn)!=len(faces): ## raise RuntimeError("Number of face normals does not match \ ## number of faces in geoemtry ",self.name) ## if reverse: ## fn = -1.0*fn ## l=[] ## for face in faces: ## l.append([face[0],face[2],face[1]]) ## faces = Numeric.array(l) ## stl = [] ## for i in xrange(len(faces)): ## stl.append(" facet normal %f %f %f\n"%tuple(fn[i])) ## stl.append(" outer loop\n") ## fa = faces[i] ## stl.append(" vertex %f %f %f\n"%tuple(vert[fa[0]])) ## stl.append(" vertex %f %f %f\n"%tuple(vert[fa[1]])) ## stl.append(" vertex %f %f %f\n"%tuple(vert[fa[2]])) ## stl.append(" endloop\n") ## stl.append(" endfacet\n") ## return stl def __init__(self): OutputNode.__init__(self) self.Transformable = Transformable() self.sphereQuality = -1 # set in getSTL() self.cylinderQuality = -1 # set in getSTL() def getSTL(self, root, filename, sphereQuality=0, cylinderQuality=0): self.sphereQuality = sphereQuality self.cylinderQuality = cylinderQuality self.output = [] self.output.append("solid %s\n"%filename) self.loopGeoms(root) self.output.append("endsolid %s\n"%filename) return self.output def NodeRepr(self, geom, matrix): # called recursively from loopGeom() if not self.checkGeom(geom): return # different geoms have to be treated different # IndexedGeoms are saved if isinstance(geom, IndexedPolygons): self.doitIndexedGeoms(geom, matrix) elif isinstance(geom, Spheres): self.doitSpheres(geom, matrix) elif isinstance(geom, Cylinders): self.doitCylinders(geom, matrix) # Lines are obviously not supported (no volume) elif isinstance(geom, IndexedPolylines): return def doitIndexedGeoms(self, geom, matrix): # gets called from NodeRepr() vert = geom.getVertices() faces = geom.getFaces() if faces.shape[1]==3: fn = TriangleNormals( vert, faces, 'PER_FACE') else: fn = TriangleNormals( vert, faces[:,:3], 'PER_FACE') #if geom is quads, or higher, make triangles if faces.shape[1] > 3: newfaces=[] newfn = [] n=0 # counter for normals for face in faces: for i in range(len(face)): # stop, if face contains -1 (for example, BSP Tree objects # might 'fill up' faces with -1 to make uniform arrays if face[i] == -1: break newfaces.append( [face[0],face[i-1],face[i]]) newfn.append(fn[n]) # increment normal counter n = n + 1 # finally, set new faces faces = newfaces fn = Numeric.array(newfn).astype('f') self.doit(vert, faces, fn, matrix, invertNormals=geom.invertNormals) def doitSpheres(self, geom, matrix): geom = geom.asIndexedPolygons(quality=self.sphereQuality) vert = geom.getVertices() faces = geom.getFaces() fn = TriangleNormals( vert, faces, 'PER_FACE') self.doit(vert, faces, fn, matrix, invertNormals=geom.invertNormals) def doitCylinders(self, geom, matrix): geom = geom.asIndexedPolygons(quality=self.cylinderQuality) vert = geom.getVertices() faces = geom.getFaces() fn = TriangleNormals( vert, faces, 'PER_FACE') self.doit(vert, faces, fn, matrix, invertNormals=geom.invertNormals) def doit(self, vert, faces, fn, matrix, invertNormals=False): if invertNormals: fn = -1.0*fn l=[] for face in faces: l.append([face[0],face[2],face[1]]) faces = Numeric.array(l) coords = Numeric.array(vert).astype('f') matrix = Numeric.array(matrix).astype('f') matrix.shape = (4,4) # this changed after python2.3!! one = Numeric.ones( (coords.shape[0], 1), \ coords.dtype.char ) c = Numeric.concatenate( (coords, one), 1 ) # apply the matrix to the vertices newCoords = Numeric.dot(c, \ Numeric.transpose(matrix))[:, :3] self.output.extend(self.makestl(newCoords, faces, fn)) def makestl(self, vert, faces, fn): stl = [] for i in xrange(len(faces)): stl.append(" facet normal %f %f %f\n"%tuple(fn[i])) stl.append(" outer loop\n") fa = faces[i] stl.append(" vertex %f %f %f\n"%tuple(vert[fa[0]])) stl.append(" vertex %f %f %f\n"%tuple(vert[fa[1]])) stl.append(" vertex %f %f %f\n"%tuple(vert[fa[2]])) stl.append(" endloop\n") stl.append(" endfacet\n") return stl class OutputVRML2(OutputNode): """ generates a list of strings describing DejaVu geoms in VRML 2.0 format. Usage: OutputVRML2.getVRML2(geom, complete=0/1, normals=0/1) geom represents the geoms to be converted complete=1 will add vrml2 header and footer normals=1 will add normals """ def __init__(self): OutputNode.__init__(self) self.geomName = None self.Transformable = Transformable() self.completeFlag = 1 # is set in getVRML2() self.saveNormalsFlag = 0 # is set in getVRML2() self.colorPerVertexFlag = True # set in getVRML2() self.usePROTOFlag = 0 # if set, instanceMatrice geoms are not # saved as geoms, but re-used with PROTO self.sphereQuality = -1 # default quality for sphere subsampling self.cylinderQuality = -1 # default quality for cyl. subsampling def getVRML2(self, root, complete=1, normals=0, colorPerVertex=True, usePROTO=0, sphereQuality=0, cylinderQuality=0): """ this method returns a list of strings describing DejaVu Geoms in VRML2 format """ # this is the method the user should call self.completeFlag = complete # if 1, header and footer will be added self.saveNormalsFlag = normals # if 1, normals are added self.colorPerVertexFlag = colorPerVertex # if False, color per face self.usePROTOFlag = usePROTO # if set to 1, instance geoms are saved # with one PROTO. Else: data for these # geoms will be prepared which blows up # the file size self.sphereQuality = sphereQuality # default is 0 self.cylinderQuality = cylinderQuality # default is 0 self.output = [] if self.completeFlag: self.output.extend(self.getFileHeader1()) self.output.extend(self.getCopyright()) self.output.extend(self.getFileHeader2()) self.loopGeoms(root) if self.completeFlag: self.output.extend(self.getFileTrailer()) return self.output def NodeRepr(self, geom, matrix): # called recursively from loopGeom() if not self.checkGeom(geom): return # call the progress bar update self.configureProgressBar(labeltext='parse '+geom.name) self.updateProgressBar() # IndexedGeoms, Spheres and Cylinders have to be treated differently if isinstance(geom, IndexedPolygons) or \ isinstance(geom, IndexedPolylines): self.output.extend( self.doit(geom, matrix) ) elif isinstance(geom, Spheres): # convert Spheres geom into IndexedPolygons sphGeom = geom.asIndexedPolygons(quality=self.sphereQuality) sphGeom.viewer = geom.viewer sphGeom.parent = geom.parent sphGeom.name = geom.name sphGeom.fullName = geom.fullName sphGeom.instanceMatricesFortran = geom.instanceMatricesFortran sphGeom.instanceMatricesFortranIndex = geom.instanceMatricesFortranIndex sphGeom.VRML2CreatedPROTOForThisGeom = 0 self.output.extend( self.doit(sphGeom, matrix) ) elif isinstance(geom, Cylinders): # convert Cylinders geom into IndexedPolygons cylGeom = geom.asIndexedPolygons(quality=self.cylinderQuality) cylGeom.viewer = geom.viewer cylGeom.parent = geom.parent cylGeom.name = geom.name cylGeom.fullName = geom.fullName cylGeom.instanceMatricesFortran = geom.instanceMatricesFortran cylGeom.instanceMatricesFortranIndex = geom.instanceMatricesFortranIndex cylGeom.VRML2CreatedPROTOForThisGeom = 0 self.output.extend( self.doit(cylGeom, matrix) ) elif isinstance(geom, GlfLabels): # convert Cylinders geom into IndexedPolygons glfGeom = geom.asIndexedPolygons() glfGeom.viewer = geom.viewer glfGeom.parent = geom.parent glfGeom.name = geom.name glfGeom.fullName = geom.fullName glfGeom.instanceMatricesFortran = geom.instanceMatricesFortran glfGeom.instanceMatricesFortranIndex = geom.instanceMatricesFortranIndex glfGeom.VRML2CreatedPROTOForThisGeom = 0 self.output.extend( self.doit(glfGeom, matrix) ) def doit(self, geom, matrix): # gets called from NodeRepr() vrml2 = [] # if self.usePROTO is set to 1: don't convert instance matrices # geoms into geoms, but use the vrml2 USE if self.usePROTOFlag: # create all the necessary data to be put in the PROTO which goes # in the header of the vrml2 file if geom.VRML2CreatedPROTOForThisGeom == 0: name = self.getGeomName(geom) vrml2.append("PROTO "+name+" [ ] {\n") identityMatrix = Numeric.identity(4).astype('f') vrml2.extend( self.doitReally(geom, identityMatrix) ) vrml2.append("}\n") # now insert this into the header of self.output for i in range(len(vrml2)): self.output.insert(i+1,vrml2[i]) geom.VRML2CreatedPROTOForThisGeom = 1 # don't add this geom # to the header next time # this PROTO flag will be deleted when we leave the recursive # and add it as USE to the body vrml2 = [] # clear the list because this data has been added vrml2.extend( self.doitUsePROTO(geom, matrix) ) return vrml2 else: # here we save all the data for all geoms return self.doitReally(geom, matrix) def doitReally(self, geom, matrix): # add header for geom vrml2 = [] vrml2.extend(self.getGeomHeader(geom)) vrml2.extend(self.getShape()) vrml2.extend(self.getAppearance()) mat, colors = self.getMaterial(geom) vrml2.extend(mat) # add texture if applicable: if geom.texture: vrml2.extend( self.getTexture(geom) ) vrml2.append(" }\n") vrml2.append("\n") # add coords, faces, etc vrml2.extend( self.getGeomDescr(geom) ) # add texCoord Coordinates is applicable if geom.texture: vrml2.extend( self.getTexCoords(geom) ) # add texCoordsIndex if applicable if hasattr(geom.vertexSet,'texCoordsIndex'): vrml2.extend( self.getTexCoordsIndex(geom)) # add normals if applicable if self.saveNormalsFlag and isinstance(geom, IndexedPolygons): vrml2.extend( self.getNormals(geom) ) # add colors per vertex if applicable if colors is not None and len(colors): vrml2.extend( self.getColors(geom, colors) ) # add closing brackets for geom vrml2.append(" }\n") vrml2.append(" }\n") # add transformations for geom vrml2.extend( self.getTransforms(matrix) ) # add closing bracket for Transform{} vrml2.append(" }\n") return vrml2 def doitUsePROTO(self, geom, matrix): # FIXME: this works currently only with geoms that are not grouped # i.e. it doesnt work with secondary structures, they will be saved # as PROTO too, but also for each instanceMatrix (->redundant) vrml2 = [] geom.instanceMatricesFortranIndex = 0 name = string.split(self.getGeomHeader(geom)[0])[1] vrml2.append(" Transform {\n") vrml2.append(" children "+name+" { }\n") # add transformations for geom vrml2.extend( self.getTransforms(matrix) ) # add closing bracket for Transform{} vrml2.append(" }\n") return vrml2 def getFileHeader1(self): vrml2=[] vrml2.append("#VRML V2.0 utf8 Python Molecular Viewer Geom\n") vrml2.append("\n") return vrml2 def getCopyright(self): vrml2=[] vrml2.append("WorldInfo {\n") vrml2.append(' title ""\n') vrml2.append(" info [\n") vrml2.append(' "Copyright (c) 2002 D. Stoffler, M.F. Sanner and A.J. Olson"\n') vrml2.append(' "Molecular Graphics Lab"\n') vrml2.append(' "The Scripps Research Institute, La Jolla, CA"\n') vrml2.append(' "VRML2 file generated with the Python Molecular Viewer:"\n') vrml2.append(' "http://www.scripps.edu/~sanner/python/pmv/"\n') vrml2.append(" ]\n") vrml2.append("}\n") return vrml2 def getFileHeader2(self): vrml2=[] vrml2.append("Group {\n") vrml2.append(" children [\n") return vrml2 def getFileTrailer(self): vrml2=[] vrml2.append(" ]\n") vrml2.append("}\n") return vrml2 def getGeomName(self, geom): g = geom name = "Pmv_" while g != geom.viewer.rootObject: # g.name can contain whitespaces which we have to get rid of gname = string.split(g.name) ggname = "" for i in gname: ggname = ggname + i name = name + string.strip(ggname)+"AT"+\ string.strip(str(g.instanceMatricesFortranIndex))+ '_' g = g.parent return name def getGeomHeader(self, geom): # generates geom name vrml2=[] g = geom name = self.getGeomName(geom) vrml2.append(" DEF "+name+" Transform {\n") return vrml2 def getShape(self): vrml2=[] vrml2.append(" children Shape {\n") return vrml2 def getAppearance(self): vrml2=[] vrml2.append(" appearance Appearance {\n") return vrml2 def getMaterial(self, geom): vrml2=[] mat = geom.materials[GL.GL_FRONT].prop[:] geom.materials[GL.GL_FRONT].colorIndex = None # will be used later on colors = None # if only 1 color present, skip this all and use the ambient definition # below if len(mat[1])> 1: colors = mat[1] # The ZCorp printer software doesn't support color_per_face, # but Pmv does. So, we create a colorIndex list for special cases # However, the user can still choose between coloring # per face and per vertex # FIXME: test for primitive type, i.e. tri_strip or quad_strip # currently this works only for tri_strips if isinstance(geom, GleExtrude): # special case! faces = geom.faceSet.faces.array # triangle_strips ifaces = geom.getFaces() # indexed geom # if the user forces to save color per vertex: if self.colorPerVertexFlag is True: colorIndex = Numeric.zeros( (ifaces.shape[0], \ ifaces.shape[1]) ) c = 0 cc = 0 for face in faces: for j in range(len(face)-2): # -2 because of tri_strip colorIndex[cc] = c cc = cc + 1 c = c + 1 geom.materials[GL.GL_FRONT].colorIndex = colorIndex elif isinstance(geom, IndexedPolygons): mat[1]=[mat[1][0]] vertices = geom.getVertices() faces = geom.getFaces() # if current colors are per face: if len(colors) != len(vertices) and len(colors) == len(faces): # if the user forces colors per vertices: if self.colorPerVertexFlag is True: colorIndex = Numeric.zeros( (faces.shape[0], \ faces.shape[1]) ) c = 0 for face in faces: for f in face: colorIndex[c] = c c = c + 1 geom.materials[GL.GL_FRONT].colorIndex = colorIndex # if current colors are per vertex else: # if the user forces colors per face: if self.colorPerVertexFlag is False: # code from Michel Sanner follows (thanks Michel!): vcol = geom.materials[1028].prop[1] tri = geom.faceSet.faces.array verts= geom.vertexSet.vertices.array colors = [] for t in tri: s1,s2,s3 = t col = ( (vcol[s1][0]+vcol[s2][0]+vcol[s3][0])/3., (vcol[s1][1]+vcol[s2][1]+vcol[s3][1])/3., (vcol[s1][2]+vcol[s2][2]+vcol[s3][2])/3. ) colors.append( col) ambInt = '%.5f'%mat[0][0][0] difCol = '%.5f'%mat[1][0][0]+" "+'%.5f'%mat[1][0][1]+" "+\ '%.5f'%mat[1][0][2] emCol = '%.5f'%mat[2][0][0]+" "+'%.5f'%mat[2][0][1]+" "+\ '%.5f'%mat[2][0][2] specCol = '%.5f'%mat[3][0][0]+" "+'%.5f'%mat[3][0][1]+" "+\ '%.5f'%mat[3][0][2] shin = '%.5f'%mat[4][0] trans = `1-mat[5][0]` vrml2.append(" material Material {\n") vrml2.append(" ambientIntensity "+ambInt+"\n") vrml2.append(" diffuseColor "+difCol+"\n") vrml2.append(" emissiveColor "+emCol+"\n") vrml2.append(" specularColor "+specCol+"\n") vrml2.append(" shininess "+shin+"\n") vrml2.append(" transparency "+trans+"\n") vrml2.append(" }\n") return vrml2, colors def getGeomDescr(self, geom): vrml2 = [] if isinstance(geom, IndexedPolygons): vrml2.append(" geometry IndexedFaceSet {\n") # add vertices vrml2.extend( self.getCoords(geom) ) # add face indices vrml2.extend( self.getFaces(geom) ) # add color indices if applicable if geom.materials[GL.GL_FRONT].colorIndex is not None and len(geom.materials[GL.GL_FRONT].colorIndex): vrml2.extend( self.getColorIndex(geom) ) elif isinstance(geom, IndexedPolylines): vrml2.append(" geometry IndexedLineSet {\n") # add vertices vrml2.extend( self.getCoords(geom) ) # add face indices vrml2.extend( self.getFaces(geom) ) return vrml2 ## added by A Gillet 04/13/2006 def getTexture(self,geom): """ return PixelTexture Node PixelTexture { image 0 0 0 # exposedField SFImage repeatS True # field SFBool repeatT True # field SFBool } the value of the image field specifies image size and pixel values for a texture image width (in pixel) height (in pixel) number of 8-bit bytes for each pixel recognize values are: 0 disable texturing for shape 1 Grayscale 2 Grayscale with alpha 3 RGB 4 RGB with alpha (Info taken from Book " VRML 2.0 source book by Andrea L. Ames, David R. Nadeau and John L. Moreland ") """ vrml2=[] tex = geom.texture dims = tex.image.shape vrml2.append("\n") vrml2.append(" texture PixelTexture {\n") width = dims[0] if len(dims) == 3: height = dims[1] num_byte = dims[2] elif len(dims)==1: height = 1 num_byte = len(tex.image[0]) elif len(dims)==2: height = 1 num_byte = dims[1] vrml2.append(" image "+`width`+" "+`height`+" "+`num_byte`+"\n") if len(dims) == 3: # we have a 2D texture (image) countW =0 for r in tex.image: # row for c in r: # column istring = "0x" for i in range(3): hexa = "%X"%c[i] if len(hexa)==1: hexa = "0"+hexa istring = istring+ hexa istring = istring + " " vrml2.append(istring) vrml2.append("\n") vrml2.append(" }\n") else: # we have a 1-dimensional array for line in tex.image: istring = "0x" for i in range(len(line)): hexa = "%X"%line[i] if len(hexa)==1: hexa = "0"+hexa istring = istring+ hexa istring = istring + "\n" vrml2.append(istring) vrml2.append(" }\n") return vrml2 ## Daniel Stoffler code ## def getTexture(self, geom): ## vrml2=[] ## dims = geom.texture.image.shape ## vrml2.append("\n") ## vrml2.append(" texture PixelTexture {\n") ## # FIXME : what are real dimensions of image? ## # I never tested this for images larger than one-dimensional array ## vrml2.append(" image "+`dims[0]`+" "+`1`+" "+\ ## `len(geom.texture.image[0])`+"\n") ## for line in geom.texture.image: ## istring = "0x" ## for i in range(len(line)): ## hexa = "%X"%line[i] ## if len(hexa)==1: hexa = "0"+hexa ## istring = istring+ hexa ## istring = istring + "\n" ## vrml2.append(istring) ## vrml2.append(" }\n") ## return vrml2 def getCoords(self, geom): vrml2=[] vertices = geom.getVertices() vrml2.append(" coord Coordinate {\n") vrml2.append(" point [\n") for vert in vertices: vstring = " "+'%.5f'%vert[0]+" "+\ '%.5f'%vert[1]+" "+'%.5f'%vert[2]+",\n" vrml2.append(vstring) vrml2.append(" ]\n") vrml2.append(" }\n") return vrml2 def getFaces(self, geom): #print "getFaces" vrml2=[] faces = geom.getFaces() vrml2.append(" coordIndex [\n") for face in faces: facestring = " " if geom.invertNormals: # reverse faces facestring = facestring + `face[0]` + ", " for i in range(len(face)-1,0,-1): facestring = facestring + `face[i]` + ", " else: for f in face: facestring = facestring + `f` + ", " facestring = facestring + "-1,\n" vrml2.append(facestring) vrml2.append(" ]\n") return vrml2 def getColorIndex(self, geom): # only called if len(colors) != len(faces) vrml2 = [] colorIndex = geom.materials[GL.GL_FRONT].colorIndex vrml2.append(" colorIndex [\n") for cI in colorIndex: cIstring = " " for c in cI: cIstring = cIstring + `c` +", " cIstring = cIstring + "-1,\n" vrml2.append(cIstring) vrml2.append(" ]\n") # clean up the geom object del geom.materials[GL.GL_FRONT].colorIndex return vrml2 def getNormals(self, geom): if geom.invertNormals: fn = -1.0 * geom.normals else: fn = geom.normals vrml2=[] vrml2.append(" normal Normal {\n") vrml2.append(" vector [\n") for n in fn: vrml2.append(" %.5f"%n[0]+" %.5f"%n[1]+\ " %.5f"%n[2]+" \n") vrml2.append(" ]\n") vrml2.append(" }\n") return vrml2 def getTexCoords(self, geom): vrml2=[] vrml2.append("\n") vrml2.append(" texCoord TextureCoordinate {\n") vrml2.append(" point [\n") for p in geom.vertexSet.texCoords.array: if len(p) == 1: # one dimension array vrml2.append(" "+`p[0]`+" 0,\n") else: vrml2.append(" "+`p[0]`+" "+`p[1]`+",\n") vrml2.append(" ]\n") vrml2.append(" }\n") return vrml2 def getTexCoordsIndex(self, geom): vrml2=[] texCoordsIndex = geom.vertexSet.texCoordsIndex.array vrml2.append(" texCoordIndex [\n") for face in texCoordsIndex: indexstring = " " for i in face: indexstring = indexstring + `i` + ", " indexstring = indexstring + "-1,\n" vrml2.append(indexstring) vrml2.append(" ]\n") return vrml2 def getColors(self, geom, colors): vrml2=[] vrml2.append("\n") vrml2.append(" colorPerVertex %s\n"%string.upper( str(self.colorPerVertexFlag))) # TRUE or FALSE ... capital letters vrml2.append(" color Color {\n") vrml2.append(" color [\n") for c in colors: cstring = ' %.3f'%c[0]+" "+'%.3f'%c[1]+\ " "+'%.3f'%c[2]+",\n" vrml2.append(cstring) vrml2.append(" ]\n") vrml2.append(" }\n") return vrml2 def getTransforms(self, matrix): vrml2=[] #mymatrix = matrix.__copy__() #mymatrix = Numeric.reshape(mymatrix, (16,)) mymatrix = Numeric.reshape(matrix, (16,)) rot,trans,scale=self.Transformable.Decompose4x4(mymatrix) r = rotax.mat_to_quat(rot) r[3]=r[3]*math.pi/180.0 #convert to rad r[0] = round(r[0],6) r[1] = round(r[1],6) r[2] = round(r[2],6) r[3] = round(r[3],6) vrml2.append(" translation "+`trans[0]`+" "+`trans[1]`+" "+\ `trans[2]`+"\n") vrml2.append(" rotation "+`r[0]`+" "+`r[1]`+" "+\ `r[2]`+" "+`r[3]`+"\n") vrml2.append(" scale "+`scale[0]`+" "+`scale[1]`+" "+\ `scale[2]`+"\n") return vrml2 class DatGUI: """ basic gui for DataOutput """ def __init__(self, master=None, title=None): self.master = master self.root = None self.title = title if self.title is None: self.title = 'Options Panel' if self.master is None: self.master = Tkinter.Frame() self.master.pack() self.sphInput = Tkinter.StringVar() self.cylInput = Tkinter.StringVar() self.sphereQuality = -1 # values range from -1 to 5 self.cylinderQuality = -1 # values range from -1 to 5 self.readyToRun = 0 # set to 1 in OK_cb, set to 0 in Cancel_cb self.idf = InputFormDescr(title=self.title) def sphereQuality_cb(self, event=None): val = self.sphInput.get() if len(val) == 0 or val is None: val = self.sphereQuality try: val = int(val) if val < -1: val = -1 elif val > 5: val = 5 self.sphereQuality = val self.sphInput.set(str(self.sphereQuality)) except ValueError: self.sphInput.set(str(self.sphereQuality)) def cylinderQuality_cb(self, event=None): val = self.cylInput.get() if len(val) == 0 or val is None: val = self.cylinderQuality try: val = int(val) if val < -1: val = -1 elif val > 5: val = 5 self.cylinderQuality = val self.cylInput.set(str(self.cylinderQuality)) except ValueError: self.cylInput.set(str(self.cylinderQuality)) def OK_cb(self): self.readyToRun = 1 self.sphereQuality_cb() self.cylinderQuality_cb() self.master.grab_release() self.master.quit() self.optionsForm.withdraw() def Cancel_cb(self): self.readyToRun = 0 self.master.grab_release() self.master.quit() self.optionsForm.withdraw() def displayPanel(self, create): self.readyToRun = 0 if create == 0: self.optionsForm.deiconify() else: self.optionsForm = InputForm(self.master, self.root, descr=self.idf,okcancel=0) # grab the focus, i.e. the program stops until OK or Cancel is pressed self.master.grab_set() self.master.mainloop() def getValues(self): vals = {} vals['sphereQuality'] = self.sphereQuality vals['cylinderQuality'] = self.cylinderQuality return vals class STLGUI(DatGUI): """ this is the gui for OutputSTL - Save normals adds normals to all geoms to be saved as vrml2 - Invert normals inverts the normals for all geoms to be saved as vrml2 - Sphere quality is the subsampling of the spheres. Default value is 2 lowest allowed value is 0. Higher values increase the file size significantly. - Cylinder quality is the subsampling of cylinders. Default value is 10 lowest allowed value is 3.""" def __init__(self, master=None, title=None): DatGUI.__init__(self, master, title) self.createForm() def createForm(self): self.idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Sphere quality'}, 'gridcfg':{'sticky':'w','columnspan':1, 'row':0, 'column':0}, }) self.idf.append({'name':'inpSphQual', 'widgetType':Tkinter.Entry, 'defaultValue':self.sphereQuality, 'wcfg':{'font':(ensureFontCase('Courier'),10), 'width':5,'textvariable':self.sphInput, 'command':self.sphereQuality_cb, }, 'gridcfg':{'sticky':'e', 'columnspan':1, 'row':0, 'column':1 } }) self.idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Cylinder quality'}, 'gridcfg':{'sticky':'w','columnspan':1, 'row':1, 'column':0}, }) self.idf.append({'name':'inpCylQual', 'widgetType':Tkinter.Entry, 'defaultValue':self.cylinderQuality, 'wcfg':{'font':(ensureFontCase('Courier'),10), 'width':5,'textvariable':self.cylInput, 'command':self.cylinderQuality_cb, }, 'gridcfg':{'sticky':'e', 'columnspan':1, 'row':1, 'column':1 } }) self.idf.append({'widgetType':Tkinter.Button, 'text':'OK', 'wcfg':{}, 'gridcfg':{'sticky':'wens', 'columnspan':1, 'row':2, 'column':0}, 'command': self.OK_cb}) self.idf.append({'widgetType':Tkinter.Button, 'text':'Cancel', 'wcfg':{}, 'gridcfg':{'sticky':'wens', 'columnspan':1, 'row':2, 'column':1}, 'command': self.Cancel_cb}) def invertNormals_cb(self): pass class VRML2GUI(DatGUI): """This is the gui for OutputVRML2: - Save normals adds normals to all geoms to be saved as vrml2 - Invert normals inverts the normals for all geoms to be saved as vrml2 - colorPerVertex: True by default. If set to False, color per face is used - Using PROTO will define a prototype geom which can be reused. This is usefull to lower the file size when instanceMatrices are applied. - Sphere quality is the subsampling of the spheres. Default value is 2 lowest allowed value is 0. Higher values increase the file size significantly. - Cylinder quality is the subsampling of cylinders. Default value is 10 lowest allowed value is 3. """ def __init__(self, master=None, title=None): DatGUI.__init__(self, master, title) self.saveNormals = Tkinter.IntVar() self.colorPerVertex = Tkinter.IntVar() self.colorPerVertex.set(1) # on by default self.usePROTO = Tkinter.IntVar() self.createForm() def createForm(self): row = 0 self.idf.append({'name':'savNormals', 'widgetType':Tkinter.Checkbutton, 'wcfg':{'text':'Save Normals ', 'variable':self.saveNormals, 'command':self.saveNormals_cb}, 'gridcfg':{'sticky':'w', 'columnspan':2, 'row':row, 'column':0} }) row+= 1 self.idf.append({'widgetType':Tkinter.Frame, 'wcfg':{'relief':'sunken','borderwidth':2,'height':2}, 'gridcfg':{'columnspan':2, 'row':row, 'column':0}, }) row += 1 self.idf.append({'name':'colorPerVertex', 'widgetType':Tkinter.Checkbutton, 'wcfg':{'text':'color per vertex', 'variable':self.colorPerVertex, 'command':self.colorPerVertex_cb}, 'gridcfg':{'sticky':'w', 'columnspan':2, 'row':row, 'column':0} }) row+= 1 self.idf.append({'widgetType':Tkinter.Frame, 'wcfg':{'relief':'sunken','borderwidth':2,'height':2}, 'gridcfg':{'columnspan':2, 'row':row, 'column':0}, }) row+= 1 self.idf.append({'name':'usePROTO', 'widgetType':Tkinter.Checkbutton, 'wcfg':{'text':'Use PROTO for instance\n'+\ 'matrices to lower file size', 'variable':self.usePROTO, 'command':self.usePROTO_cb}, 'gridcfg':{'sticky':'w', 'columnspan':2, 'row':row, 'column':0} }) row+= 1 self.idf.append({'widgetType':Tkinter.Frame, 'wcfg':{'relief':'sunken','borderwidth':2,'height':2}, 'gridcfg':{'columnspan':2, 'row':row, 'column':0}, }) row+= 1 self.idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Sphere quality'}, 'gridcfg':{'sticky':'w','columnspan':2, 'row':row, 'column':0}, }) self.idf.append({'name':'inpSphQual', 'widgetType':Tkinter.Entry, 'defaultValue':'2', 'wcfg':{'font':(ensureFontCase('Courier'),10), 'width':5,'textvariable':self.sphInput, 'command':self.sphereQuality_cb, }, 'gridcfg':{'sticky':'e', 'columnspan':2, 'row':row, 'column':1 } }) row+= 1 self.idf.append({'widgetType':Tkinter.Label, 'wcfg':{'text':'Cylinder quality'}, 'gridcfg':{'sticky':'w','columnspan':2, 'row':row, 'column':0}, }) self.idf.append({'name':'inpCylQual', 'widgetType':Tkinter.Entry, 'defaultValue':'10', 'wcfg':{'font':(ensureFontCase('Courier'),10), 'width':5,'textvariable':self.cylInput, 'command':self.cylinderQuality_cb, }, 'gridcfg':{'sticky':'e', 'columnspan':2, 'row':row, 'column':1 } }) row+= 1 self.idf.append({'widgetType':Tkinter.Button, 'text':'OK', 'wcfg':{}, 'gridcfg':{'sticky':'wens', 'columnspan':1, 'row':row, 'column':0}, 'command': self.OK_cb}) self.idf.append({'widgetType':Tkinter.Button, 'text':'Cancel', 'wcfg':{}, 'gridcfg':{'sticky':'wens', 'columnspan':1, 'row':row, 'column':1}, 'command': self.Cancel_cb}) def saveNormals_cb(self): pass def colorPerVertex_cb(self): pass def usePROTO_cb(self): pass def getValues(self): vals = {} vals['saveNormals'] = self.saveNormals.get() co = self.colorPerVertex.get() if co == 1: co = True else: co = False vals['colorPerVertex'] = co vals['usePROTO'] = self.usePROTO.get() vals['sphereQuality'] = self.sphereQuality vals['cylinderQuality'] = self.cylinderQuality return vals mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Light.py0000644000175000017500000004266412045001162021311 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Light.py,v 1.43 2012/11/02 17:27:14 sanner Exp $ # # $Id: Light.py,v 1.43 2012/11/02 17:27:14 sanner Exp $ # from opengltk.OpenGL import GL,GLU from opengltk.extent.utillib import glCleanRotMat import types import numpy.oldnumeric as Numeric from math import sqrt from colorTool import OneColor from viewerFns import GetArray, getkw from Transformable import Transformable class LightModel: """Class for the OpenGL light model""" def Set(self, **kw): """Set various light model parameters""" self.viewer.currentCamera.Activate() tagModified = True val = getkw(kw, 'tagModified') if val is not None: tagModified = val assert tagModified in [True, False] self._modified = tagModified ambi = getkw(kw, 'ambient') if not ambi is None: if len(ambi)==3 or len(ambi)==4: self.ambient = OneColor( ambi ) GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, self.ambient); else: raise ValueError('length of new color must be 3 or 4') localViewer = getkw(kw, 'localViewer') if not localViewer is None: if localViewer in (True,1): GL.glLightModelf(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE); elif localViewer in (False,0): GL.glLightModelf(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_FALSE); else: raise AttributeError('localViewer can only be True or False') self.localViewer = localViewer twoSide = getkw(kw, 'twoSide') if not twoSide is None: if twoSide in (True,1): GL.glLightModelf(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE); elif twoSide in (False,0): GL.glLightModelf(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE); else: raise AttributeError('twoSide can only be True or False') self.twoSide = twoSide self.broadcast() if len(kw): print 'WARNING8: Keyword(s) %s not used' % kw.keys() def broadcast(self): #print "LightModel.broadcast" if self.viewer.rootObject is None: return # self.viewer.needsRedraw = 1 for app in self.applyTo: if app and app.winfo_ismapped(): # needed otherwise tests produce seg fault on mesa app.tk.call(app._w, 'makecurrent') self.apply() app.tkRedraw() self.viewer.Redraw() def apply(self): """setup current lightmodel for current OpenGL context""" if self.ambient is not None: GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, self.ambient); if self.localViewer is True: GL.glLightModelf(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_TRUE); elif self.localViewer is False: GL.glLightModelf(GL.GL_LIGHT_MODEL_LOCAL_VIEWER, GL.GL_FALSE); if self.twoSide is True: GL.glLightModelf(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE); elif self.twoSide is False: GL.glLightModelf(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_FALSE); def getState(self): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ return {'ambient':self.ambient, 'localViewer':self.localViewer, 'twoSide':self.twoSide} def Reset(self): """Restore the default values""" # light model state self.localViewer = False self.twoSide = False # from DejaVu import preventIntelBug_WhiteTriangles # if preventIntelBug_WhiteTriangles: # self.ambient = (.4, .4, .4, 1.) # else: # self.ambient = (.2, .2, .2, 1.) # self.Set( ambient=self.ambient, localViewer=self.localViewer, twoSide=self.twoSide ) self.ambient = (.12, .12, .12, 1.) self.Set( localViewer=self.localViewer, twoSide=self.twoSide ) self._modified = False def __init__(self, viewer, **kw): self.applyTo = [] self.viewer = viewer self.Reset() # creates all state attributes kw['tagModified'] = False apply( LightModel.Set, (self,), kw ) def __repr__(self): return ' 180.: raise ValueError("spotCutoff must be in [0., 90.] or 180.") self.spotCutoff = float( val ) GL.glLightfv(self.num, GL.GL_SPOT_CUTOFF, [self.spotCutoff] ) val = getkw(kw, 'constantAttenuation') if not val is None: self.constantAttenuation = float( val ) if self.constantAttenuation < 0.0: raise ValueError("constantAttenuation must be >= 0.0") GL.glLightfv(self.num, GL.GL_CONSTANT_ATTENUATION, [self.constantAttenuation] ) val = getkw(kw, 'linearAttenuation') if not val is None: self.linearAttenuation = float( val ) if self.linearAttenuation < 0.0: raise ValueError("linearAttenuation must be >= 0.0") GL.glLightfv(self.num, GL.GL_LINEAR_ATTENUATION, [self.linearAttenuation] ) val = getkw(kw, 'quadraticAttenuation') if not val is None: self.quadraticAttenuation = float( val ) if self.quadraticAttenuation < 0.0: raise ValueError("quadraticAttenuation must be >= 0.0") GL.glLightfv(self.num, GL.GL_QUADRATIC_ATTENUATION, [self.quadraticAttenuation] ) val = getkw(kw, 'positional') if not val is None: if val is True: self.position[3] = 1.0 elif val is False: self.position[3] = 0.0 else: raise AttributeError('positional can only be True or False') self.positional = val val = getkw(kw, 'enabled') if not val is None: if val in (True, 1): GL.glEnable(self.num) elif val in (False, 0): GL.glDisable(self.num) else: raise AttributeError('enabled can only be True or False') self.enabled = val val = getkw(kw, 'visible') if not val is None: if val in (True, False): self.visible = val else: raise AttributeError('visible can only be True or False') val = getkw(kw, 'lineWidth') if not val is None: if val >= 1: self.lineWidth = int(val) else: raise AttributeError('lineWidth has to be >= 1') val = getkw(kw, 'length') if not val is None: if val > 0.0: self.length = float ( val ) else: raise AttributeError('length has to be > 0.0') # val = getkw(kw, 'antialiased') # if not val is None: # if val in (True, False): # self.antialiased = val # else: raise ValueError ('antialiased can only be True or False') val = getkw(kw, 'rotation') if not val is None: mat = Numeric.reshape(Numeric.array(val), (16,)).astype('f') self.rotation = mat val = getkw(kw, 'translation') if not val is None: mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') self.translation = mat val = getkw(kw, 'scale') if not val is None: mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') self.scale = mat val = getkw(kw, 'pivot') if not val is None: mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') self.pivot = mat if len(kw): print 'WARNING9: Keyword(s) %s not used' % kw.keys() #guillaume vareille 9/29/2005 : # was c = self.viewer.cameras[0] # was generating alternativly good and wrong rendering when 2 cameras c = self.viewer.currentCamera # force light to be update in viewer c.Redraw() # brodcast to other application that want to know about that light # using aftere does not seem to make it better #c.after_idle(self.broadcast) self.broadcast() # not needed and causes the master dispaly list to be rebuilt #self.viewer.deleteOpenglList() def setAmbient(self, val): self.Set(ambient=val) def setDiffuse(self, val): self.Set(diffuse=val) def setSpecular(self, val): self.Set(specular=val) def broadcast(self): #print "Light.broadcast" for app in self.applyTo: # provides a small performance increase but the light is not # setup the first time the window comes up if app and app.winfo_ismapped(): # needed otherwise tests produce seg fault on mesa app.tk.call(app._w, 'makecurrent') self.apply() app.tkRedraw() if self.viewer.materialEditor is not None: self.viewer.materialEditor.tk.call(self.viewer.materialEditor._w, 'makecurrent') self.apply() self.viewer.materialEditor.tkRedraw() def apply(self): """setup this light for current OpenGL context """ #print "Light.apply" num = self.num if self.ambient is not None: GL.glLightfv(num, GL.GL_AMBIENT, self.ambient ) if self.diffuse is not None: GL.glLightfv(num, GL.GL_DIFFUSE, self.diffuse ) if self.specular is not None: GL.glLightfv(num, GL.GL_SPECULAR, self.specular ) if self.positional is False: GL.glLightfv(num, GL.GL_POSITION, self.direction ) else: GL.glLightfv(num, GL.GL_POSITION, self.position ) if self.spotFlag: GL.glLightfv(num, GL.GL_SPOT_DIRECTION, self.spotDirection[:3] ) GL.glLightfv(num, GL.GL_SPOT_EXPONENT, [self.spotExponent] ) GL.glLightfv(num, GL.GL_SPOT_CUTOFF, [self.spotCutoff] ) GL.glLightfv(num, GL.GL_CONSTANT_ATTENUATION, [self.constantAttenuation] ) GL.glLightfv(num, GL.GL_LINEAR_ATTENUATION, [self.linearAttenuation] ) GL.glLightfv(num, GL.GL_QUADRATIC_ATTENUATION, [ self.quadraticAttenuation] ) if self.enabled is True: GL.glEnable(num) else: GL.glDisable(num) def getState(self): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ return { 'ambient':self.ambient, 'diffuse':self.diffuse, 'specular':self.specular, 'direction':self.direction, 'position':self.position, 'spotDirection':self.spotDirection, 'spotExponent':self.spotExponent, 'spotCutoff':self.spotCutoff, 'constantAttenuation':self.constantAttenuation, 'linearAttenuation':self.linearAttenuation, 'quadraticAttenuation':self.quadraticAttenuation, 'positional':self.positional, 'enabled':self.enabled, #'antialiased':self.antialiased, 'lineWidth':self.lineWidth, 'length':self.length, 'visible':self.visible, 'rotation':list(self.rotation), 'translation':list(self.translation), 'scale':list(self.scale), 'pivot':list(self.pivot) } def Reset(self): """Restore Light default values""" Transformable.__init__(self, self.viewer) # self.translation = 10.0 if self.num == GL.GL_LIGHT0: enabled = True else: enabled = False self.Set( ambient = [.12, .12, .12, 1.], diffuse = [1., 1., 1., 1.], specular = [.8, .8, .65, 1.], direction = [-1., 1., 1., 1.], position = [0.0, 0.0, 0.0, 0.0], spotDirection = [0.0, 0.0, -1.0, 0.0], spotExponent = 0.0, spotCutoff = 180.0, constantAttenuation = 1.0, linearAttenuation = 0.0, quadraticAttenuation = 0.0, positional = False, enabled = enabled, #antialiased = False, lineWidth = 2, length = 10.0, visible = False) self.hasBeenCurrent = False self._modified = False def __init__(self, num, viewer, **kw): self.hasBeenCurrent = False # turn to True if light is modified self.applyTo = [viewer.materialEditor] self.num = self.lightIndices[num] self.viewer = viewer self.name = 'light '+str(num) self.Reset() apply( Light.Set, (self,), kw) self._modified = False self.object = None self.dirFlag = 0 self.posFlag = 0 self.spotFlag = 0 def FrameTransform(self, camera=None): """Build the R an RI, the object's frame transformation and inverse""" Transformable.FrameTransform(self, camera) if self.redirectXform: self.redirectXform.FrameTransform(camera) for o in self.copyXform: o.FrameTransform(camera) if self.positional is False: return def ConcatRotationDir(self, matrix): """Rotate a directional light""" self._modified = True ## matrix = Numeric.reshape( matrix, (4,4) ) ## newdir = Numeric.dot( self.direction, matrix ) GL.glPushMatrix() GL.glLoadIdentity() GL.glMultMatrixf(self.Ri) GL.glMultMatrixf(matrix) GL.glMultMatrixf(self.R) mat = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') #mat = glCleanRotMat(mat).astype('f') n = glCleanRotMat(mat).astype('f') GL.glPopMatrix() #n = Numeric.reshape(mat, (4,4)) newdir = Numeric.dot( self.direction, n ) self.Set(direction = newdir) for o in self.copyXform: o.ConcatRotationDir(matrix) def DrawDirectionalLight(self, camera): """Draw a directional light as a line""" # if self.antialiased is True: # GL.glEnable(GL.GL_LINE_SMOOTH) # GL.glEnable(GL.GL_BLEND) # else: # GL.glDisable(GL.GL_LINE_SMOOTH) # GL.glDisable(GL.GL_BLEND) GL.glColor4fv (self.diffuse) GL.glLineWidth(self.lineWidth) GL.glBegin (GL.GL_LINES) GL.glVertex3f ( float(camera.lookAt[0]),float(camera.lookAt[1]),float(camera.lookAt[2]) ) v = camera.lookAt + self.direction[:3] nv = sqrt(Numeric.add.reduce(v*v)) v = (v/nv)*self.length GL.glVertex3f ( float(v[0]), float(v[1]), float(v[2]) ) GL.glEnd() GL.glPushMatrix() GL.glTranslatef(float(v[0]),float(v[1]),float(v[2])) GL.glPushAttrib(GL.GL_ALPHA_TEST); # GL.glDisable(GL.GL_LIGHTING); GL.glEnable(GL.GL_BLEND) GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA); pObj = GLU.gluNewQuadric() GLU.gluQuadricDrawStyle(pObj, GLU.GLU_FILL) GLU.gluQuadricNormals(pObj, GLU.GLU_SMOOTH) GL.glColor4ub(255,255,255,10); GLU.gluDisk(pObj, 0.0, 0.5, 20, 20); for light_color in range(100): GL.glColor4ub(255-light_color,255-light_color,255-light_color,10) GLU.gluCylinder(pObj, 0.5 - 2.*light_color/255.,0.5 - 2.*(light_color+1)/255. , light_color/255., 20, 20) GL.glTranslatef(0.0, 0.0, float(light_color)/255.); #GL.glColor4ub(255,255,255,200) #GLU.gluDisk(pObj, 0,0.5 - 2.*(light_color+1)/255. , 20, 20) GL.glPopAttrib() GL.glPopMatrix() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/MaterialEditor.py0000644000175000017500000011547712047247052023166 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: Febuary 2006 Authors: Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI # # Revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/MaterialEditor.py,v 1.61 2012/11/09 18:40:42 annao Exp $ # # $Id: MaterialEditor.py,v 1.61 2012/11/09 18:40:42 annao Exp $ # import Tkinter, os, math import numpy.oldnumeric as Numeric import Pmw import tkFileDialog from opengltk.OpenGL import GL from opengltk.extent.utillib import extractedGlutSolidSphere from colorTool import ToHSV, ToRGB, OneColor, TkColor from DejaVu.extendedSlider import ExtendedSlider from DejaVu.Materials import Materials from DejaVu import loadTogl from numpy.oldnumeric import array import DejaVu class OGLWidget(Tkinter.Widget, Tkinter.Misc): """This class implements an OpenGL widget in a Tk Frame used to display color scales in the color editor. """ def __init__(self, master, title, cnf={}, expand=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not kw.has_key('width'): kw['width']=150 if not kw.has_key('height'): kw['height']=150 if not kw.has_key('double'): kw['double']=1 if not kw.has_key('depth'): kw['depth']=1 # for unexplained reason anti-aliasing doesn't work # on mesa if we don't set the accumulation buffer if not kw.has_key('accum'): kw['accum'] = 1 self.width = kw['width'] self.height = kw['height'] # load the TK-OpenGL extension (Togl) loadTogl(master) # create an Tk-OpenGL widget from opengltk.exception import GLerror from Tkinter import TclError try: Tkinter.Widget.__init__(self, master, 'togl', cnf, kw) try: GL.glAccum(GL.GL_LOAD, 1.0) self.accumBuffersError = False except GLerror: self.accumBuffersError = True except TclError, e: self.accumBuffersError = True kw.pop('accum') Tkinter.Widget.__init__(self, master, 'togl', cnf, kw) #currentcontext = self.tk.call(self._w, 'contexttag') #print "OGLWidget.__init__ currentcontext", currentcontext, title self.bind('', self.tkExpose) self.bind('', self.Enter_cb) self.bind('', self.Configure) self.pack(side='left') def initProjection(self): """ guillaume: prepare the opengl matrices for drawing the widget (for instance the sliders in the case of the MaterialEditor) """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() GL.glMatrixMode (GL.GL_PROJECTION) GL.glLoadIdentity () GL.glOrtho(0., 1., 0., 1., -2.5, 2.5) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() GL.glTranslatef(0, 0, 2.0) def tkExpose(self, *dummy): #guillaume: (commented out) redundant,this is allready in self.tkRedraw #self.tk.call(self._w, 'makecurrent') #self.initProjection() if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.tkRedraw() def Activate(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.tk.call(self._w, 'makecurrent') def Enter_cb(self, event): """Call back function trigger when the mouse enters the camera""" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.tk.call(self._w, 'makecurrent') def Configure(self, *dummy): """guillaume: set the opengl viewport""" # unbind ') self.configure(width=self.width, height=self.height) self.bind('', self.Configure) GL.glViewport(0, 0, self.width, self.height) def tkRedraw(self, *dummy): """Cause the opengl widget to redraw itself. guillaume: call the preparation of the opengl matrices for drawing the widget then draw the widget """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #if not self.winfo_ismapped(): return self.update_idletasks() self.tk.call(self._w, 'makecurrent') self.initProjection() GL.glPushMatrix() self.redraw() GL.glFlush() GL.glPopMatrix() self.tk.call(self._w, 'swapbuffers') def setupLightModel(self): """ """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # this method has to be called explicitly by the derived classes if # a default lighting model is wanted GL.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, [.5, .5, .5, 1.0]) GL.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, [.5, .5, .5, 1.0]) GL.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, [.5, .5, .5, 1.0]) GL.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, [1.0, 1.0, 1.0, 0.0]); GL.glLightfv(GL.GL_LIGHT1, GL.GL_AMBIENT, [.5, .5, .5, 1.0]) GL.glLightfv(GL.GL_LIGHT1, GL.GL_DIFFUSE, [.5, .5, .5, 1.0]) GL.glLightfv(GL.GL_LIGHT1, GL.GL_SPECULAR, [.5, .5, .5, 1.0]) GL.glLightfv(GL.GL_LIGHT1, GL.GL_POSITION, [-1.0, 1.0, 1.0, 0.0]); GL.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, [0.2, 0.2, 0.2, 1.0]) #GL.glEnable(GL.GL_LIGHTING) if self.viewer is not None: self.viewer.enableOpenglLighting() GL.glEnable(GL.GL_LIGHT0) GL.glEnable(GL.GL_LIGHT1) class MaterialEditor(OGLWidget): """The class implements the material editor widget allowing to modify the ambient, .... The editor maintains a list of colors for each property in the .materials attribute. This list can be set using the defineMaterial(material) method. (FIXME passing a material object here ties the Material Editor to DejaVu) A material editor instance can be bound to an object to edit either its front or back facing polygons material. This is done using the setObject(object, face) method. The object bound to the matrial editor is stored in the .object attribute. To use a Material editor on objects other than a DejaVu Geometry the setObject() method should be overwritten. the sphere drawn in the upper left corner shows the effect of changing the various components of a material. Chekcbuttons allow to ... etc ... """ ambi = 0 diff = 1 emis = 2 spec = 3 shini = 4 opac = 5 def _destroy(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.peFrame.destroy() self.destroy() def Configure(self, *dummy): """guillaume: set the OpenGL Viewport for the material editor""" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print 'Configure 1' width = self.winfo_width() height = self.winfo_height() if width > height: xo = (width-height)/2 yo = 0 size = height else: xo = 0 yo = (height-width)/2 size = width GL.glViewport(xo, yo, size, size) def initProjection(self): """ guillaume: prepare the opengl matrices to display the sphere""" if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() GL.glMatrixMode (GL.GL_PROJECTION) GL.glLoadIdentity () halfSize = self.halfSize GL.glOrtho(float(-halfSize), float(halfSize), float(-halfSize), float(halfSize), float(-halfSize), float(halfSize)) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glLoadIdentity() GL.glTranslatef(0, 0, -2.0) def tkExpose(self, *dummy): """ guillaume: override the one in OGLWidget the only addition is a call to OGLWidget.configure() """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print 'Expose 1' self.tk.call(self._w, 'makecurrent') self.initProjection() self.Configure() self.tkRedraw() def redraw(self): """ redraw the Material editor opengl sphere that shows the effect of the modifications """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.tk.call(self._w, 'makecurrent') GL.glClearColor(0,0,0,0) self.initProjection() self.Configure() GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) """ draw the black background squares """ GL.glDisable( GL.GL_LIGHTING ) GL.glColor3f( 0.1, 0.1, 0.1 ) GL.glBegin(GL.GL_QUADS) GL.glVertex3f(-2, 0, 2); GL.glVertex3f(-2, 2, 2) GL.glVertex3f( 0, 2, 2); GL.glVertex3f( 0, 0, 2) GL.glEnd() GL.glBegin(GL.GL_QUADS) GL.glVertex3f( 0,-2, 2); GL.glVertex3f( 0, 0, 2) GL.glVertex3f( 2, 0, 2); GL.glVertex3f( 2,-2, 2) GL.glEnd() """ draw the grey background squares """ GL.glColor3f( 0.3, 0.3, 0.3 ) GL.glBegin(GL.GL_QUADS) GL.glVertex3f(-2,-2, 2); GL.glVertex3f(-2, 0, 2) GL.glVertex3f( 0, 0, 2); GL.glVertex3f( 0,-2, 2) GL.glEnd() GL.glBegin(GL.GL_QUADS) GL.glVertex3f( 0, 0, 2); GL.glVertex3f( 0, 2, 2) GL.glVertex3f( 2, 2, 2); GL.glVertex3f( 2, 0, 2) GL.glEnd() """ enable the sphere transparancy """ GL.glEnable(GL.GL_BLEND) GL.glDepthMask(GL.GL_FALSE) GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA) """ draw the sphere """ #GL.glEnable(GL.GL_LIGHTING) if self.viewer is not None: self.viewer.enableOpenglLighting() self.setMaterial() extractedGlutSolidSphere(1.6, 30, 30, 0) def __init__(self, master, viewer, title='MaterialEditor',cnf={}, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.ownsMaster = False if master is None: master = Tkinter.Toplevel(viewer.master)#screenName=screenName) master.title(title) master.protocol('WM_DELETE_WINDOW', self.dismiss ) self.ownsMaster = True # DO NOT USE master because OGLWidget.__init__ will define # self.master as a Frame self.root = master if not kw.has_key('width'): kw['width'] = 200 if not kw.has_key('height'): kw['height'] = 200 self.frame = Tkinter.Frame(self.root, borderwidth=3, relief='ridge') self.halfSize = 2 self.material = [ Numeric.array([[0.4, 0.4, 0.4, 1.0]],'f'), Numeric.array([[0.4, 0.4, 0.4, 1.0]],'f'), Numeric.array([[1., 1., 1., 1.0]],'f'), Numeric.array([[0., 0., 0., 1.0]],'f'), Numeric.array([50],'f'), Numeric.array([1.0],'f'), ] apply( OGLWidget.__init__, (self, self.frame, title, cnf), kw ) # self.frame.pack(pady=5, padx=10) self.frame.grid(row=0, column=0, padx=5, pady=5) self.object = None self.viewer = viewer #self.redraw = self.redraw f = self.peFrame = Tkinter.Frame(self.root) self.ambipe = MaterialPropertyEditor(f, self, 'Ambi: ') self.ambipe.setRGB(self.material[self.ambi][0]) self.ambipe.setCallback(self.setAmbient) self.diffpe = MaterialPropertyEditor(f, self, 'Diff: ') self.diffpe.setRGB(self.material[self.diff][0]) self.diffpe.setCallback(self.setDiffuse) self.emispe = MaterialPropertyEditor(f, self, 'Emis: ') self.emispe.setRGB(self.material[self.emis][0]) self.emispe.setCallback(self.setEmission) self.specpe = MaterialPropertyEditor(f, self, 'Spec: ') self.specpe.setRGB(self.material[self.spec][0]) self.specpe.setCallback(self.setSpecular) self.opacitySl = ExtendedSlider(f, label=' Opacity', minval=0.0, maxval=1.0, init=self.material[self.diff][0][3], onButton=1, sd='left', withValue=0, immediate=1) self.opacitySl.AddCallback(self.opacity_cb) self.shiniSl = ExtendedSlider(f, label='Shininess', minval=0.0, maxval=128.0, init=self.material[self.shini][0], onButton=1, sd='left', withValue=0, immediate=1) self.shiniSl.AddCallback(self.shininess_cb) self.shiniSl.frame.pack(side='top', expand=1, fill='y') self.opacitySl.frame.pack(side='top', expand=1, fill='y') f.grid(row=1, column=0, padx=5, pady=5) # f.pack(pady=5) self.currentPalette = None self.paletteNum = 0 self.lastDir = './' f = Tkinter.Frame(self.root) # # guillaume's work in progress # # target # f0 = Tkinter.Frame(f, borderwidth=3, relief = 'ridge') # self.targetOption = Pmw.OptionMenu(f0, # label_text = 'target:', # labelpos = 'w', # initialitem = 'Front', # #command = self.setTarget, # items = ('Front', 'Back'), # menubutton_pady=0, # ) # self.targetOption.grid(row=0, column=0, padx=2, pady=2) # f0.pack(padx=2, pady=2) f1 = Tkinter.Frame(f, borderwidth=3, relief = 'ridge') l = ['artdeco','autumn','glass','metal','neon','rococo','santafe', 'sheen','silky','spring','summer','tropical','winter'] self.paletteBt = Pmw.ComboBox(f1, label_text='Palettes:', labelpos='nw', entryfield_entry_width=10, scrolledlist_items=l, selectioncommand=self.selectPalette) self.paletteBt.grid(row=0, column=0, padx=2, pady=2) self.paletteNumBt = Pmw.Counter(f1, labelpos = 'nw', label_text = 'Prop number:', entry_width = 2, entryfield_value = self.paletteNum, entryfield_validate = {'validator' : 'integer', 'min' : 0, 'max' : 34} ) self.paletteNumBt.grid(row=0, column=1, padx=2, pady=2) l = Tkinter.Button(f1, text="Load ",command=self.loadPaletteMaterial) l.grid(row=1, column=0, padx=2, pady=2, sticky='ew') l = Tkinter.Button(f1, text="Apply ", command=self.broadcast) l.grid(row=1, column=1, padx=2, pady=2, sticky='ew') f1.pack(padx=2, pady=2) f1 = Tkinter.Frame(f, borderwidth=3, relief = 'ridge') l = Tkinter.Button(f1, text="Read ...",command=self.readMaterial) l.grid(row=0, column=0, padx=2, pady=2, sticky='ew') l = Tkinter.Button(f1, text="Write ..", command=self.writeMaterial) l.grid(row=0, column=1, padx=2, pady=2, sticky='ew') f1.pack(padx=2, pady=2) f.grid(row=0, column=1) f = self.ccFrame = Tkinter.Frame(self.root) self.cc = ColorChooser(f, title=None) f.grid(row=1, column=1) # f.pack(pady=5) self.dismissTk = Tkinter.Button(self.root, text='DISMISS', command=self.dismiss) self.dismissTk.grid(row=2, column=0, columnspan=2, padx=5, pady=5) self.tk.call(self._w, 'makecurrent') self.initLight(self.viewer) # def setTarget(self, face): # obj = self.viewer.currentObject # self.setObject(obj, face) # delf.defineMaterial(obj.materials[face].prop, face) def readMaterial(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() types = [('materials', '*_prop.py'), ('all files', '*.*')] title = "Read material definition" file = tkFileDialog.askopenfilename( filetypes=types, initialdir=self.lastDir, initialfile=None, title=title) if len(file)==0: return d = {} execfile(file, d) for k,v in d.items(): if k=='__builtins__': continue break self.defineMaterial(v) def writeMaterial(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() types = [('materials', '*_prop.py'), ('all files', '*.*')] title = "Save material definition" file = tkFileDialog.asksaveasfilename( filetypes=types, initialdir=self.lastDir, initialfile=None, title=title) if len(file)==0: return f = open(file, 'w') f.write("material = [\n") f.write(repr([self.material[self.ambi][0].tolist()])+', # ambient\n') f.write(repr([self.material[self.diff][0].tolist()])+', # diffuse\n') f.write(repr([self.material[self.emis][0].tolist()])+', # emission\n') f.write(repr([self.material[self.spec][0].tolist()])+', # specular\n') f.write(repr([self.material[self.shini][0].tolist()])+', # shininess\n') f.write(repr([self.material[self.opac][0].tolist()])+' # opacity\n') f.write("]\n") f.close() def loadPaletteMaterial(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.currentPalette is not None: num = int(self.paletteNumBt.get()) mat = Materials(self.currentPalette, num) self.defineMaterial(mat.prop) def selectPalette(self, palette): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.currentPalette = palette def initLight(self, viewer): """ """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if viewer: viewer.lightModel.applyTo.append(self) viewer.lightModel.apply() for l in viewer.lights: if l.enabled: self.tk.call(self._w, 'makecurrent') l.apply() else: self.setupLightModel() def setObject(self, object, face): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.object = object self.defineMaterial(object.materials[face].prop, face) def dismiss(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.frame.master.withdraw() def show(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.frame.master.deiconify() def broadcast(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.object is None: return mask = [ self.ambipe.onTk.get(), self.diffpe.onTk.get(), self.emispe.onTk.get(), self.specpe.onTk.get(), self.shiniSl.onTk.get(), self.opacitySl.onTk.get() ] material = {'ambient':self.material[self.ambi], 'diffuse':self.material[self.diff], 'emission':self.material[self.emis], 'specular': self.material[self.spec], 'shininess':self.material[self.shini], 'opacity':self.material[self.opac], 'binding':None} if self.objectFace == GL.GL_BACK: self.object.Set(rawMaterialB=material, matMask=mask, transparent='implicit', redo=1) else: self.object.Set(rawMaterialF=material, matMask=mask, transparent='implicit', redo=1) if self.viewer: self.tk.call(self.viewer.currentCamera._w, 'makecurrent') self.viewer.Redraw() def setAmbient(self, rgb): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #self.material[self.ambi][0][:3] = list(rgb[:3]) self.material[self.ambi][0][:3] = array(rgb[:3],'f',copy=1) self.tkRedraw(self) self.broadcast() def setDiffuse(self, rgb): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #self.material[self.diff][0][:3] = list(rgb[:3]) self.material[self.diff][0][:3] = array(rgb[:3],'f',copy=1) self.tkRedraw(self) self.broadcast() def setEmission(self, rgb): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #self.material[self.emis][0][:3] = list(rgb[:3]) self.material[self.emis][0][:3] = array(rgb[:3],'f',copy=1) self.tkRedraw(self) self.broadcast() def setSpecular(self, rgb): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #self.material[self.spec][0][:3] = list(rgb[:3]) self.material[self.spec][0][:3] = array(rgb[:3],'f',copy=1) self.tkRedraw(self) self.broadcast() def defineMaterial(self, material, face=GL.GL_FRONT): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # This method is used to set the material from an object to which # the material editor is bound self.objectFace = face #self.material[self.ambi] = material[self.ambi] self.material[self.ambi] = [material[self.ambi][0]] self.ambipe.setRGB(self.material[self.ambi][0]) if len(material[self.ambi]) > 1: self.ambipe.disable() # disable editing button self.ambipe.tkRedraw(self) #self.material[self.diff] = material[self.diff] self.material[self.diff] = [material[self.diff][0]] self.diffpe.setRGB(self.material[self.diff][0]) if len(material[self.diff]) > 1: self.diffpe.disable() self.diffpe.tkRedraw(self) #self.material[self.emis] = material[self.emis] self.material[self.emis] = [material[self.emis][0]] self.emispe.setRGB(self.material[self.emis][0]) if len(material[self.emis]) > 1: self.emispe.disable() self.emispe.tkRedraw(self) #self.material[self.spec] = material[self.spec] self.material[self.spec] = [material[self.spec][0]] self.specpe.setRGB(self.material[self.spec][0]) if len(material[self.spec]) > 1: self.specpe.disable() self.specpe.tkRedraw(self) #self.material[self.shini] = material[self.shini] self.material[self.shini] = [material[self.shini][0]] self.shiniSl.set(self.material[self.shini][0], update=0) if len(material[self.shini]) > 1: self.shiniSl.disable() #self.material[self.opac] = material[self.opac] self.material[self.opac] = [material[self.opac][0]] self.opacitySl.set(self.material[self.opac][0], update=0) if len(material[self.opac]) > 1: self.opacitySl.disable() self.tkRedraw(self) def opacity_cb(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.material[self.opac][0] = val self.tkRedraw(self) self.broadcast() def shininess_cb(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.material[self.shini][0] = val self.tkRedraw(self) self.broadcast() def setMaterial(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() mat = self.material GL.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, mat[self.ambi][0]) diff = mat[self.diff][0] diff[3] = mat[self.opac][0] GL.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, mat[self.diff][0]) GL.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat[self.spec][0]) GL.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, mat[self.emis][0]) GL.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, float(mat[self.shini][0])) GL.glColor4fv(mat[self.diff][0]) class MaterialPropertyEditor(OGLWidget): """This object provides a slider over a hue/saturation WISIWYG ramp""" def disable(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.onTk.set(0) self.setVal.configure(state='disabled', bg='#AAAAAA') self.setcw.configure(state='disabled') self.edit.configure(state='disabled') self.unbind('') def enable(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.onTk.set(1) self.setVal.configure(state='normal', bg='#CC9999') self.setcw.configure(state='normal') self.edit.configure(state='normal') self.bind('', self.mouse1Down) def on_cb(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.onTk.get(): self.enable() else: self.disable() def __init__(self, master, editor, label, title='MaterialPropertyEditor', width=None, height=None, cnf={}, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if width is None: kw['width'] = 180 if height is None: kw['height'] = 19 self.width = kw['width'] self.callback = None self.editor = editor tf = self.topFrame = Tkinter.Frame(master, borderwidth=3, relief='ridge') self.frame = Tkinter.Frame(tf, borderwidth=3, relief='sunken') apply( OGLWidget.__init__, (self, self.frame, title, cnf, 0), kw ) self.forget() self.pack(side='left') self.valueTk = Tkinter.StringVar() self.setVal = Tkinter.Entry(self.frame, textvariable=self.valueTk, width=5, bg='#CC9999') self.setVal.bind('', self.setVal_cb) self.setVal.pack(side='left') f = Tkinter.Frame(tf) self.onTk = Tkinter.IntVar() cb = Tkinter.Checkbutton(f, text=label, variable=self.onTk, command=self.on_cb) self.onTk.set(1) self.editTk = Tkinter.IntVar() self.edit = Tkinter.Checkbutton(f, variable=self.editTk, text='Edit', command=self.edit_cb) self.setcwTk = Tkinter.IntVar() self.setcw = Tkinter.Button(f, text='SetCW', pady=0, command=self.setcw_cb) cb.pack(side='left', padx=3) self.edit.pack(side='left', padx=3) self.setcw.pack(side='left', padx=3) f.pack(side='top') self.frame.pack(side='bottom', pady=2) tf.pack(padx=2, pady=2) self.bind('', self.mouse1Down) self.setRGB((1,1,1)) def setVal_cb(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.setValue(float(self.valueTk.get())) def setcw_cb(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.editor.cc.Set(self.rgb) def edit_cb(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() val = self.editTk.get() if val: self.editor.cc.callbacks.append(self.update) else: self.editor.cc.callbacks.remove(self.update) def setCallback(self, func): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() assert callable(func) self.callback = func def callCallback(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # called when value changes if self.callback: self.callback(self.rgb) def update(self, rgb): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # call back called by colorwheel self.h, self.s, v = ToHSV(rgb[:3]) self.rgbMax = ToRGB( (self.h, self.s, 1.0) ) self.rgb = ToRGB( (self.h, self.s, self.v) ) self.tkRedraw() self.callCallback() def setRGB(self, rgb): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # used to set the color for a given rgb tuple self.h, self.s, self.v = ToHSV(rgb[:3]) self.valueTk.set(float('%.4f'%self.v)) self.rgbMax = ToRGB( (self.h, self.s, 1.0) ) self.rgb = rgb def setValue(self, value): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # call back for value (as v in hsv) slider if value < 0.0: value = 0.0 if value > 1.0: value = 1.0 self.v = value self.valueTk.set(float('%.4f'%self.v)) self.rgb = ToRGB( (self.h, self.s, self.v) ) self.tkRedraw() self.callCallback() def mouse1Down(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.bind('', self.mouse1Move) self.bind('', self.mouse1Up) self.setValue(float(event.x)/self.width) def mouse1Move(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.setValue(float(event.x)/self.width) def mouse1Up(self, event): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.setValue(float(event.x)/self.width) self.unbind('') self.unbind('') def redraw(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.tk.call(self._w, 'makecurrent') GL.glDisable( GL.GL_DEPTH_TEST ) GL.glDisable( GL.GL_LIGHTING ) #GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL) GL.glBegin(GL.GL_QUADS) GL.glColor3f(0.,0.,0.) GL.glVertex2f(0., 1.); GL.glVertex2f(0., 0.) GL.glColor3f(float(self.rgbMax[0]),float(self.rgbMax[1]),float(self.rgbMax[2])) GL.glVertex2f( 1., 0.); GL.glVertex2f( 1., 1.) GL.glEnd() GL.glEnable(GL.GL_COLOR_LOGIC_OP) GL.glLogicOp(GL.GL_XOR) GL.glLineWidth(2) GL.glColor3f(.5,.5,.5) GL.glBegin(GL.GL_LINES) x1 = self.v-0.01 x2 = self.v+0.01 GL.glVertex2f(float(x1), 1.); GL.glVertex2f(float(x1), 0.) GL.glVertex2f(float(x2), 0.); GL.glVertex2f(float(x2), 1.) GL.glEnd() GL.glDisable(GL.GL_COLOR_LOGIC_OP) class ColorWheel: def __init__(self, master, title=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not master: master = Tkinter.Toplevel()#screenName=screenName) if title is not None: master.title(title) f = self.frame = Tkinter.Frame(master) path = __import__('DejaVu').__path__ iconfile = os.path.join(path[0],'cw.ppm') self.cwim = Tkinter.PhotoImage(master=master, file=iconfile) self.width = self.cwim.width() self.height = self.cwim.height() self.cwcanvas = Tkinter.Canvas(f, width=self.width, height=self.height, relief='sunken', borderwidth=3 ) self.cwcanvas.create_image(3, 3, anchor=Tkinter.NW, image=self.cwim) self.cwcanvas.pack() self.frame.pack() self.callback = None self.immediate = 1 self.x = 0 self.y = 0 self.radius = 55 cx = self.cx = self.width/2 + 3 cy = self.cy = self.height/2 + 3 self.cursor = self.cwcanvas.create_line( cx-3, cy-3, cx-3, cy+3, cx+3,cy+3, cx+3, cy-3, cx-3, cy-3 ) self.hsvColor = [1.,1.,1.] self.cwcanvas.bind('', self.mouse1Down) # self.cursor = self.cwcanvas.create_line(cx, cy, cx-55, cy) def _MoveCursor(self, x, y): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() # find the saturation based on distance s = math.sqrt(x*x + y*y) / self.radius if s > 1.0: x = x / s y = y / s s = 1.0 # now find the hue based on the angle if x or y: angle = math.atan2(y, x) if angle < 0.0: angle = angle + (2.*math.pi) h = 1. - angle / (2.0 * math.pi) else: h = 0 # check if redraw and callback are needed if self.hsvColor[0] != h or self.hsvColor[1] != s: self.hsvColor[0] = h self.hsvColor[1] = s cx = self.cx+x cy = self.cy+y self.cwcanvas.coords( self.cursor, cx-3, cy-3, cx-3, cy+3, cx+3,cy+3, cx+3, cy-3, cx-3, cy-3 ) if self.immediate and self.callback: self.callback(self.Get('RGB')) def mouse1Down(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.cwcanvas.bind('', self.mouse1Move) self.cwcanvas.bind('', self.mouse1Up) self._MoveCursor(event.x - self.cx, event.y - self.cy) def mouse1Move(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self._MoveCursor(event.x - self.cx, event.y - self.cy) def mouse1Up(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self._MoveCursor(event.x - self.cx, event.y - self.cy) self.cwcanvas.unbind('') self.cwcanvas.unbind('') def Get(self, mode='HSV'): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Get the current color""" if mode == 'RGB': rgb = ToRGB(self.hsvColor) return OneColor(rgb) elif mode == 'HSV': return OneColor(self.hsvColor) elif mode == 'TkRGB': col = Numeric.array(ToRGB(self.hsvColor[:3]), 'f') * 255 return TkColor(col) def Set(self, color, mode='HSV'): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the current color""" assert len(color) in (3,4) color = OneColor(color) if mode=='RGB': color[:3] = ToHSV(color[:3]) self.hsvColor = color[:3] # update cursor rad = self.hsvColor[1] * self.radius angle = 2.0 * math.pi * (1. - self.hsvColor[0]) cx = self.cx + int(rad * math.cos(angle)) cy = self.cy + int(rad * math.sin(angle)) self.cwcanvas.coords( self.cursor, cx-3, cy-3, cx-3, cy+3, cx+3,cy+3, cx+3, cy-3, cx-3, cy-3 ) if self.immediate and self.callback: self.callback(self.Get('RGB')) class ColorChooser: def __init__(self, master, title='Color Chooser'): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not master: master = Tkinter.Toplevel()#screenName=screenName) if title is not None: master.title(title) self.frame = Tkinter.Frame(master, borderwidth=3, relief='ridge') self.wheelFrame = Tkinter.Frame(self.frame) self.cw = ColorWheel(self.wheelFrame) self.wheelFrame.pack(pady=5, padx=10) f = self.chipFrame = Tkinter.Frame(self.frame, relief='ridge') self.chip1 = Tkinter.Frame(f, relief='sunken', borderwidth=3, width=60, height=30, bg='white') self.chip2 = Tkinter.Frame(f, relief='sunken', borderwidth=3, width=60, height=30, bg='white') self.chip1.pack(side='left', anchor='e') self.chip2.pack(side='right', anchor='w') f.pack(pady=2) f = self.btFrame = Tkinter.Frame(self.frame, relief='ridge') self.saveBt = Tkinter.Button(f, text='->', command=self.save) self.swapBt = Tkinter.Button(f, text='<->', command=self.swap) self.restoreBt = Tkinter.Button(f, text='<-', command=self.restore) self.saveBt.pack(side='left') self.swapBt.pack(side='left') self.restoreBt.pack(side='left') f.pack(pady=2) self.frame.pack(padx=5, pady=5) self.callbacks = [] self.cw.callback = self.updateCurrent self.currentColor = [1., 1., 1.] self.savedColor = [1., 1., 1.] def Set(self, color): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.updateCurrent(color) self.cw.Set(color, 'RGB') def updateCurrent(self, color): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.chip1.configure( bg = TkColor( Numeric.array(color, 'f')*255 ) ) self.currentColor[:3] = list(color[:3]) for f in self.callbacks: f(self.currentColor) def updateSaved(self, color): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.chip2.configure( bg = TkColor( Numeric.array(color, 'f')*255 ) ) self.savedColor[:3] = list(color[:3]) def save(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.updateSaved(self.currentColor) def swap(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() saved = self.savedColor[:] self.updateSaved(self.currentColor) self.cw.Set(saved, 'RGB') def restore(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.cw.Set(self.savedColor, 'RGB') if __name__=='__main__': import Tkinter master = Tkinter.Toplevel() from DejaVu import Viewer vi = Viewer() from DejaVu.colorMap import ColorMap test = MaterialEditor(master, vi) from DejaVu.Spheres import Spheres s = Spheres('test', centers = [[0.,0,0], [5,0,0.], [0,5,0]], quality=30, matName='tropical', matInd=0) vi.AddObject(s) from DejaVu.materialsDef.tropical import tropical test.defineMaterial(tropical[0]) test.setObject(s) ## root1 = Tkinter.Tk() ## cc = ColorChooser(root1, title='Color chooser') mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Nurbs.py0000644000175000017500000000774111352467561021353 0ustar debiandebianfrom opengltk.OpenGL import GL, GLU from opengltk.extent import _glulib import numpy import DejaVu from DejaVu.Geom import Geom class GLUSurfaceNurbs(Geom): """Class for GLU Nurbs surfaces""" keywords = Geom.keywords + [ 'knots', 'ctrlPts', 'displayMode', ] def getState(self, full=False): state = Geom.getState(self, full) # add knots, ctrlPts, displayMode to state ## state['quality'] = self.quality ## if full: ## rad = self.vertexSet.radii.array ## if len(rad): ## state['radii'] = rad return state def init_surface(self): self.ctlpoints = numpy.zeros( (4,4,3), 'f') for u in range(4): for v in range(4): self.ctlpoints[u][v][0] = 2.0*(u - 1.5) self.ctlpoints[u][v][1] = 2.0*(v - 1.5) if ( u == 1 or u == 2) and (v == 1 or v == 2): self.ctlpoints[u][v][2] = 3.0 else: self.ctlpoints[u][v][2] = -3.0 def __init__(self, name=None, check=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Spheres.__init__" self.knots = numpy.array((0.0, 0.0, 0.0, 0.0, .5, .5, .5, .5), 'f') apply( Geom.__init__, (self, name, check), kw ) self.theNurb = None self.init_surface() self.immediateRendering = True def nurbsError(self, errorCode): estring = GLU.gluErrorString(errorCode); print "Nurbs Error: %s"%estring sys.exit(0) def Draw(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() GL.glEnable(GL.GL_AUTO_NORMAL) GL.glEnable(GL.GL_NORMALIZE) if self.theNurb is None: self.theNurb = GLU.gluNewNurbsRenderer() GLU.gluNurbsProperty(self.theNurb, GLU.GLU_SAMPLING_TOLERANCE, 25.0) GLU.gluNurbsProperty(self.theNurb, GLU.GLU_DISPLAY_MODE, GLU.GLU_OUTLINE_POLYGON) GLU.gluNurbsCallback(self.theNurb, GLU.GLU_ERROR, self.nurbsError) GLU.gluBeginSurface(self.theNurb) _glulib.gluNurbsSurface( self.theNurb, 8, self.knots, 8, self.knots, 4*3, 3, self.ctlpoints, 4, 4, GL.GL_MAP2_VERTEX_3) GLU.gluEndSurface(self.theNurb) GL.glPointSize(5.0) GL.glDisable(GL.GL_LIGHTING) GL.glColor3f(1.0, 1.0, 0.0) GL.glBegin(GL.GL_POINTS) for i in range(4): for j in range(4): GL.glVertex3fv(self.ctlpoints[i][j]) GL.glEnd() GL.glDisable(GL.GL_AUTO_NORMAL) GL.glDisable(GL.GL_NORMALIZE) if __name__=='__main__': from DejaVu.Nurbs import GLUSurfaceNurbs from DejaVu import Viewer vi = Viewer() nurbsg = GLUSurfaceNurbs('nurbs') vi.AddObject(nurbsg) def move(): from random import uniform for n in range(200): for i in range(1,3): for j in range(1,3): nurbsg.ctlpoints[i][j][2] += uniform(-0.3, 0.3) vi.OneRedraw() vi.master.update() import numpy def move1(): for n in range(1, 11): v = n*0.1 nurbsg.knots = numpy.array( (0.0, 0.0, 0.0, 0.0, v, v, v, v), 'f') print nurbsg.knots vi.OneRedraw() vi.master.update() def move2(): for n in range(0, 10): v = n*0.1 nurbsg.knots = numpy.array( (v, v, v, v, 1, 1, 1, 1), 'f') print nurbsg.knots vi.OneRedraw() vi.master.update() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Geom.py0000644000175000017500000023224512100566317021137 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER, Daniel Stoffler # # Copyright: M. Sanner, Daniel Stoffler TSRI 2000 # # Revision: Guillaume Vareille # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Geom.py,v 1.269 2013/01/25 20:36:31 sanner Exp $ # # $Id: Geom.py,v 1.269 2013/01/25 20:36:31 sanner Exp $ # import numpy import numpy.oldnumeric as Numeric, types, warnings from opengltk.OpenGL import GL from opengltk.extent import _gllib import DejaVu import Materials, datamodel, Clip from DejaVu.colorTool import OneColor, resetMaterialMemory from DejaVu.Transformable import Transformable from DejaVu.Displayable import Displayable from DejaVu.viewerFns import checkKeywords from DejaVu import viewerConst from DejaVu.Common2d3dObject import Common2d3dObject class Geom(Common2d3dObject, Transformable, Displayable): """Base class for objects that can be displayed in a camera """ _numberOfDeletedGeoms = 0 ## def __del__(self): ## self.__class__._numberOfDeletedGeoms = self.__class__._numberOfDeletedGeoms + 1 ## print 'Free Geom ', self.__class__.__name__ keywords = Common2d3dObject.keywords + [ #'antialiased', 'backPolyMode', 'blendFunctions', 'culling', 'depthMask', 'disableStencil', 'frontPolyMode', 'highlight', 'inheritBackPolyMode', 'inheritCulling', 'inheritFrontPolyMode', 'inheritLighting', 'inheritStippleLines', 'inheritLineWidth', 'inheritMaterial', 'inheritPointWidth', 'inheritStipplePolygons', 'inheritShading', 'inheritSharpColorBoundaries', 'inheritXform', 'instanceMatricesFromFortran', 'instanceMatricesFromC', 'instanceMatrices', 'invertNormals', 'lighting', 'lineWidth', 'matBind', 'materials', 'matInd', 'matMask', 'matName', 'opacity', 'outline', 'pickableVertices', 'pivot', 'pointWidth', 'polyFace', 'propName', 'rawMaterialB', 'rawMaterialF', 'rotation', 'scale', 'scissor', 'scissorAspectRatio', 'scissorH', 'scissorX', 'scissorY', 'scissorW', 'shading', 'shape', 'sharpColorBoundaries', 'stippleLines', 'stipplePolygons', 'texture', 'textureCoords', 'transient', 'translation', 'transparent', # is also set when materials are defines 'vertices', 'vertexArrayFlag', 'vnormals', 'vreshape', ] sourceBlendFunctions = [ GL.GL_ZERO, GL.GL_ONE, GL.GL_DST_COLOR, GL.GL_ONE_MINUS_DST_COLOR, GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_DST_ALPHA, GL.GL_ONE_MINUS_DST_ALPHA, GL.GL_SRC_ALPHA_SATURATE ] destBlendFunctions = [ GL.GL_ZERO, GL.GL_ONE, GL.GL_SRC_COLOR, GL.GL_ONE_MINUS_SRC_COLOR, GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA, GL.GL_DST_ALPHA, GL.GL_ONE_MINUS_DST_ALPHA ] def __init__(self, name=None, check=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Geom.__init__" Transformable.__init__(self) Displayable.__init__(self) self.clipP = [] # list of clipping planes clipping only self self.clipPI = [] # list of clipping planes that are inherited self.clipSide = [] # 1 or -1 for each cliping plane # FIXME side should be stored in clipping plane # thsi dict is used to avoid drawing some objects in a given camera self.hiddenInCamera = {} # key:Camera object, value dummy self.scissor = 0 self.scissorX = 0 self.scissorY = 0 self.scissorW = 200 self.scissorH = 200 self.scissorAspectRatio = 1.0 self.drawBB = False self.colorBB = (1.0, 1.0, 1.0, 1.0) self.lineWidthBB = 1.0 self.pickableVertices = False # when set individual vertices # in geom can be picked # bounding box defaults, get overwritten in ObjSubTreeBB self.maxBB = None self.minBB = None self.lighting = True self.dpyList = None # display list for drawing self.redoDspLst = 0 # set to 1 to for Display List re-calculation self.pickDpyList = None # display list for picking self.normals = None self.vertexNormals = False self.faceNormals = False self.invertNormals = False self.sharpColorBoundaries = None if kw.has_key('sharpColorBoundaries') is False: kw['sharpColorBoundaries'] = True self.inheritSharpColorBoundaries = None if kw.has_key('inheritSharpColorBoundaries') is False: kw['inheritSharpColorBoundaries'] = True #print "kw['inheritSharpColorBoundaries']", kw['inheritSharpColorBoundaries'] if not kw.get('disableStencil'): kw['disableStencil'] = False #if not kw.get('vertexArrayFlag'): # kw['vertexArrayFlag'] = False self.highlight = [] if DejaVu.enableVertexArray is True: self.vertexArrayFlag = True kw['immediateRendering'] = True self.vertexArrayFlagBufferList = [] else: self.vertexArrayFlag = False apply( Common2d3dObject.__init__, (self, name, check), kw) assert len(self.vertexSet.vertices.ashape) < 4 self.cap = None # set to GL.CLIP_PLANE[0,..6] to cap geometry self.capMesh = 0 # set to o or 1 self.capFrontColor = (1,1,1,1) self.capBackColor = (1,1,1,1) def getState(self, full=False): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state If full is True: large arrays such as vertices, materials, normals etc are also saved in the state """ state = Common2d3dObject.getState(self).copy() lUpdate = { #'antialiased':self.antialiased, 'backPolyMode':viewerConst.POLYGON_MODES_REV[self.backPolyMode], #'blendFunctions': see bellow 'culling':viewerConst.CULLINGS_REV[self.culling], #see bellow 'depthMask':self.depthMask, 'disableStencil': self.disableStencil, 'frontPolyMode':viewerConst.POLYGON_MODES_REV[self.frontPolyMode], 'inheritBackPolyMode':self.inheritBackPolyMode, 'inheritCulling':self.inheritCulling, 'inheritFrontPolyMode':self.inheritFrontPolyMode, 'inheritLighting':self.inheritLighting, 'inheritStippleLines':self.inheritStippleLines, 'inheritLineWidth':self.inheritLineWidth, 'inheritMaterial':self.inheritMaterial, 'inheritPointWidth':self.inheritPointWidth, 'inheritStipplePolygons':self.inheritStipplePolygons, 'inheritShading':self.inheritShading, 'inheritSharpColorBoundaries': self.inheritSharpColorBoundaries, 'inheritXform':self.inheritXform, 'instanceMatricesFromFortran':self.instanceMatricesFortran.tolist(), 'invertNormals':self.invertNormals, 'lighting':self.lighting, 'lineWidth':self.lineWidth, #'matBind': covered by materialCode #'materials': covered by materialCode #'matInd': covered by materialCode #'matMask': covered by materialCode #'matName': covered by materialCode #'opacity': covered by materialCode 'outline':self.drawOutline, 'pickableVertices':self.pickableVertices, 'pivot':list(self.pivot), 'pointWidth':self.pointWidth, #'polyFace': covered by materialCode #'propName': covered by materialCode #'rawMaterialB': covered by materialCode #'rawMaterialF': covered by materialCode 'rotation':list(self.rotation), 'scale':list(self.scale), 'shading':viewerConst.SHADINGS_REV[self.shading], #'shape': geometry definition rather than attributes 'stippleLines':self.stippleLines, 'stipplePolygons':self.stipplePolygons, 'scissor':self.scissor, 'scissorAspectRatio':self.scissorAspectRatio, 'scissorH':self.scissorH, 'scissorX':self.scissorX, 'scissorY':self.scissorY, 'scissorW':self.scissorW, 'sharpColorBoundaries':self.sharpColorBoundaries, #'texture': FIXME TODO #'textureCoords': FIXME TODO #'transient': covered by visible 'translation':list(self.translation), 'transparent':self.transparent is 1, 'vertexArrayFlag':self.vertexArrayFlag, #'vertices': geometry definition rather than attributes #'vnormals': geometry definition rather than attributes #'vreshape': geometry definition rather than attributes } state.update(lUpdate) # val = self.culling # if val==viewerConst.INHERIT: val="inherit" # elif val==GL.GL_NONE: val="none" # elif val==GL.GL_FRONT: val="front" # elif val==GL.GL_BACK: val="back" # elif val==GL.GL_FRONT_AND_BACK: val="front_and_back" # state['culling']=val val = self.srcBlendFunc if val==GL.GL_ZERO: val1="GL_ZERO" elif val==GL.GL_ONE: val1="GL_ONE" elif val==GL.GL_DST_COLOR: val1="GL_DST_COLOR" elif val==GL.GL_ONE_MINUS_DST_COLOR: val1="GL_ONE_MINUS_DST_COLOR" elif val==GL.GL_SRC_ALPHA: val1="GL_SRC_ALPHA" elif val==GL.GL_ONE_MINUS_SRC_ALPHA: val1="GL_ONE_MINUS_SRC_ALPHA" elif val==GL.GL_DST_ALPHA: val1="GL_DST_ALPHA" elif val==GL.GL_ONE_MINUS_DST_ALPHA: val1="GL_ONE_MINUS_DST_ALPHA" elif val==GL.GL_SRC_ALPHA_SATURATE: val1="GL_SRC_ALPHA_SATURATE" val = self.dstBlendFunc if val==GL.GL_ZERO: val2="GL_ZERO" elif val==GL.GL_ONE: val2="GL_ONE" elif val==GL.GL_SRC_COLOR: val2 = "GL_SRC_COLOR" elif val==GL.GL_ONE_MINUS_SRC_COLOR: val2 = "GL.GL_ONE_MINUS_SRC_COLOR" elif val==GL.GL_SRC_ALPHA: val2 = "GL_SRC_ALPHA" elif val==GL.GL_ONE_MINUS_SRC_ALPHA: val2="GL_ONE_MINUS_SRC_ALPHA" elif val==GL.GL_DST_ALPHA: val2="GL_DST_ALPHA" elif val==GL.GL_ONE_MINUS_DST_ALPHA: val2="GL_ONE_MINUS_DST_ALPHA" state['blendFunctions'] = (val1,val2) if full: state['vertices'] = self.getVertices() state['vnormals'] = self.getVNormals() state['rawMaterialF'] = self.materials[GL.GL_FRONT].getState() state['rawMaterialB'] = self.materials[GL.GL_BACK].getState() return state def applyStrokes(self, color=(0,0,0,1), strength=2): # modified Stefano """configures Geom to display stroke silhouette lines by drawing back faces as lines. None <- strokes(color=(0,0,0,1), strength=1) Stroke -> None color is an RGB tuple defining the color of the strokes strength is the width of the stroke lines """ # turn on/off culling if self.culling != GL.GL_NONE: self.culling = GL.GL_NONE else: self.culling = GL.GL_BACK self.inheritCulling = False # make sure the backfaces are draw as lines self.SetBackPolyMode(GL.GL_LINE) self.inheritBackPolyMode = False # set back material to black self.inheritMaterial = False from numpy import array prop = self.materials[GL.GL_BACK].prop prop[0] = array( ( color, ), 'f' ) prop[1] = array( ( color, ), 'f' ) prop[2] = array( (( 0.0, 0.0, 0.0, 1.0 ), ), 'f' ) prop[3] = array( (( 0.0, 0.0, 0.0, 1.0 ), ), 'f' ) prop[4] = array( ( 0.0, ), 'f' ) # set the width of lines self.lineWidth = strength self.inheritLineWidth = False # set inheritence flags for all children for child in self.AllObjects(): if child==self: continue child.inheritCulling = True child.inheritBackPolyMode = True #child.inheritMaterial = True child.inheritLineWidth = True prop = child.materials[GL.GL_BACK].prop prop[0] = array( ( color, ), 'f' ) prop[1] = array( ( color, ), 'f' ) prop[2] = array( (( 0.0, 0.0, 0.0, 1.0 ), ), 'f' ) prop[3] = array( (( 0.0, 0.0, 0.0, 1.0 ), ), 'f' ) prop[4] = array( ( 0.0, ), 'f' ) def GetABSCoords(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Return the coordinates of the object if the object was a child of root. """ m = self.GetMatrix(root=self.viewer.rootObject) c = self.getVertices(homogenous=True) ct = numpy.dot(c, m) return numpy.array(ct[:,:3]) def getGeomMaterialCode(self, geomName, indent='', includeBinding=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Returns a list of strings containing Python code to restore the material of this geoemtry. indent is the level of indentation that is desired. geomName is the name of the Geom object in the source code generated. """ lines = [] lines.append(indent+"## Material for %s\n"%self.name) lines.append(indent+"if %s:\n"%geomName) fmat = self.materials[GL.GL_FRONT] if fmat._modified: lines.append(indent+" from opengltk.OpenGL import GL\n") lines.append(indent+" state = %s\n"%str(fmat.getState(includeBinding))) lines.append(indent+" %s.materials[GL.GL_FRONT].Set(**state)\n\n"%(geomName)) bmat = self.materials[GL.GL_BACK] if bmat._modified: lines.append(indent+" from opengltk.OpenGL import GL\n") lines.append(indent+" state = %s\n"%str(bmat.getState())) lines.append(indent+" %s.materials[GL.GL_BACK].Set(**state)\n\n"%(geomName)) lines.append(indent+" %s._setTransparent('implicit')\n"%(geomName)) lines.append(indent+" pass ## needed in case there no modif\n") lines.append(indent+"## End Materials for %s\n\n"%self.name) return lines def getGeomClipPlanesCode(self, geomName, indent=''): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Returns a list of strings containing Python code to restore the clipping planes of this geoemtry. indent is the level of indentation that is desired. geomName is the name of the Geom object in the source code generated. """ lines = [] lines.append(indent+"## Clipping Planes for %s\n"%self.name) lines.append(indent+"if %s:\n"%geomName) lines.append(indent+" %s.clipP = []\n"%geomName) lines.append(indent+" %s.clipPI = []\n"%geomName) for i,c in enumerate(self.clipP): lines.append(indent+" clip = %s.viewer.clipP[%d]\n"%( geomName, i)) lines.append(indent+" %s.AddClipPlane(clip, %s.clipSide[clip.num], False)\n"%(geomName,geomName)) for i,c in enumerate(self.clipPI): lines.append(indent+" clip = %s.viewer.clipP[%d]\n"%( geomName, i)) lines.append(indent+" %s.AddClipPlane(clip, %s.clipSide[clip.num], True)\n"%(geomName,geomName)) if self.capMesh: lines.append(indent+" clip.ClipCapMesh(obj, 1)\n") lines.append(indent+" pass ## needed in case there no modif\n") lines.append(indent+"## End Clipping Planes for %s\n\n"%self.name) return lines def delete(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() pass def getVertices(self, homogenous=False): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns a handle to the vertices array""" c = self.vertexSet.vertices.array if len(c) == 0: return numpy.array([]) if homogenous: ch = numpy.ones( (c.shape[0], 4) ) ch[:,:3] = c return ch else: return c def getVNormals(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns a handle to the vertices array""" if self.vertexSet.normals.status == viewerConst.NONE: self.vertexSet.normals.GetProperty() if len(self.vertexSet.normals.array) == 0: return numpy.array([]) return self.vertexSet.normals.array def getOcclusionPointsDir(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() v = self.getVertices() n = self.getVNormals() return v, n def getDepthMask(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() obj = self while obj.inheritMaterial: if obj.parent: obj = obj.parent else: break return obj.depthMask def SetPolyMode(self, face, mode): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Modify polymode""" obj = self if obj.viewer: if obj==self.viewer.rootObject and mode==viewerConst.INHERIT: return if mode==viewerConst.OUTLINED: if face==GL.GL_FRONT: obj.Set(outline=(True, obj.drawOutline[1]), frontPolyMode=GL.GL_FILL) elif face==GL.GL_BACK: obj.Set(outline=(obj.drawOutline[0], True), backPolyMode=GL.GL_FILL) elif face==GL.GL_FRONT_AND_BACK: obj.Set(outline=(True, True), frontPolyMode=GL.GL_FILL, backPolyMode=GL.GL_FILL) else: if face==GL.GL_FRONT: obj.Set(outline=(False, obj.drawOutline[1]), frontPolyMode=mode) elif face==GL.GL_BACK: obj.Set(outline=(obj.drawOutline[0], False), backPolyMode=mode) elif face==GL.GL_FRONT_AND_BACK: obj.Set(outline=(False, False), frontPolyMode=mode, backPolyMode=mode) def SetFrontPolyMode(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Modify the current Object's frontPolyMode""" obj = self if obj.frontAndBack: obj.SetPolyMode( GL.GL_FRONT_AND_BACK, val ) else: self.SetPolyMode( GL.GL_FRONT, val ) def SetBackPolyMode(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Modify the current Object's frontPolyMode""" obj = self obj.frontAndBack = viewerConst.NO obj.SetPolyMode( GL.GL_BACK, val ) def SetFrontBackPolyMode(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Modify the current Object's frontPolyMode""" obj = self obj.frontAndBack = viewerConst.YES obj.SetPolyMode( GL.GL_FRONT_AND_BACK, val ) def GetPolyMode(self, face): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() obj = self if face == 'front': while obj.inheritFrontPolyMode: if obj.parent: obj = obj.parent else: break return obj.frontPolyMode else: # face == 'back': while obj.inheritBackPolyMode: if obj.parent: obj = obj.parent else: break return obj.backPolyMode def getDrawOutlineMode(self, face): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() obj = self if face == 'front': while obj.inheritFrontPolyMode: if obj.parent: obj = obj.parent else: break return obj.drawOutline[0] else: # face == 'back': while obj.inheritBackPolyMode: if obj.parent: obj = obj.parent else: break return obj.drawOutline[1] def GetShading(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() obj = self while obj.inheritShading: if obj.parent: obj = obj.parent else: break return obj.shading def GetLighting(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() obj = self while obj.inheritLighting: if obj.parent: obj = obj.parent else: break return obj.lighting def getSharpColorBoundaries(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "getSharpColorBoundaries", self.name obj = self while obj.inheritSharpColorBoundaries: if obj.parent: obj = obj.parent else: break return obj.sharpColorBoundaries def MaterialBindingMode(self, num, face=GL.GL_FRONT, mode=None): """Figure out how materials should be used to color the object """ if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if num is None: num = self.materials[GL.GL_FRONT].diff elif type(num) is types.StringType: num = getattr(self.materials[GL.GL_FRONT], num) if face is None: face = GL.GL_FRONT f = face if face == GL.GL_FRONT_AND_BACK: f = GL.GL_FRONT self.frontAndBack = True nn = self.materials[f].prop[num].shape[0] #self.inheritMaterial = False if not mode: if nn == 1: self.materials[f].binding[num] = viewerConst.OVERALL elif nn == len(self.vertexSet.vertices): self.materials[f].binding[num] = viewerConst.PER_VERTEX elif hasattr(self, 'faceSet') and nn == len(self.faceSet): self.materials[f].binding[num] = viewerConst.PER_PART elif nn == len(self.instanceMatricesFortran): self.materials[f].binding[num] = viewerConst.PER_INSTANCE else: self.materials[f].binding[num] = -1 #self.inheritMaterial = True else: # a mode is requested if mode==viewerConst.INHERIT: self.materials[f].binding[num] = viewerConst.INHERIT if mode==viewerConst.PER_VERTEX and \ nn >= len(self.vertexSet.vertices): self.materials[f].binding[num] = viewerConst.PER_VERTEX elif hasattr(self, 'faceSet') and \ mode==viewerConst.PER_PART and nn >= len(self.faceSet): self.materials[f].binding[num] = viewerConst.PER_PART elif mode==viewerConst.OVERALL and nn >= 1: self.materials[f].binding[num] = viewerConst.OVERALL elif mode==viewerConst.PER_INSTANCE and nn >= len(self.instanceMatricesFortran): self.materials[f].binding[num] = viewerConst.PER_INSTANCE else: self.materials[f].binding[num] = -1 #self.inheritMaterial = True def AddMaterial(self, values, propNum=None, face=GL.GL_FRONT, mode=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add materials to the current set""" if not values: return if propNum is None: propNum = self.materials[GL.GL_FRONT].diff elif type(propNum) is types.StringType: propNum = getattr(self.materials[GL.GL_FRONT], propNum) f = face if face == GL.GL_FRONT_AND_BACK: f = GL.GL_FRONT self.frontAndBack = True if self.materials[f].prop[propNum].shape[0]==1 and \ self.materials[f].binding[propNum] == viewerConst.OVERALL: self.materials[f].prop[propNum] = Numeric.array( (), viewerConst.FPRECISION ) if propNum < 4: self.materials[f].prop[propNum].shape = (0,4) else: self.materials[f].prop[propNum].shape = (0,) values = Numeric.array( values ).astype(viewerConst.FPRECISION) if propNum < 4: if values.shape[1] == 3: alpha = Numeric.ones( (values.shape[0], 1), viewerConst.FPRECISION ) values = Numeric.concatenate( (values, alpha), 1 ) self.materials[f].prop[propNum] = \ Numeric.concatenate( (self.materials[f].prop[propNum], values) ) self.MaterialBindingMode(propNum, face, mode) def SetMaterial(self, values, propNum, face=GL.GL_FRONT, mode=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the materials WARNING: when back face colors are set, two sided lighting has to be enabled""" if not values: return if propNum is None: propNum = self.materials[GL.GL_FRONT].diff elif type(propNum) is types.StringType: propNum = getattr(self.materials[GL.GL_FRONT], propNum) f = face if face == GL.GL_FRONT_AND_BACK: f = GL.GL_FRONT elif face == GL.GL_BACK: self.viewer.lightModel.Set(twoSide = 1) self.materials[f].prop[propNum] = Numeric.array( (), viewerConst.FPRECISION ) if propNum < 4: self.materials[f].prop[propNum].shape = (0,4) else: self.materials[f].prop[propNum].shape = (0,) self.AddMaterial(values, propNum, face, mode) # mat = self.materials[f].prop[propNum] # if len(mat) and propNum==1: # diffuse # alphaMin = Numeric.minimum.reduce( mat[:,3] ) # if alphaMin < 1.0: # self.setTransparency(1) # else: # self.setTransparency(0) def GetNormals(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Find the normals to be used for a given shading """ lShadeModel = self.GetShading() #self.shading if lShadeModel == GL.GL_NONE: self.normals = None elif lShadeModel == GL.GL_FLAT: if hasattr(self, 'faceSet'): self.normals = self.faceSet.normals.GetProperty() else: self.normals = None elif lShadeModel == GL.GL_SMOOTH: self.normals = self.vertexSet.normals.GetProperty() def Add(self, check=1, redo=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """add data to this object set self.redoDspLst to 1 to force re-building of geometries DpyList which implies recontruction of main display list. set redoMain to 1 to force on reconstruction of main DpyList""" print "Geom.Add" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) v = kw.get( 'vertices') n = kw.get( 'vnormals') m = kw.get( 'materials') pf = kw.get( 'polyFace') mbm = kw.get( 'matBind') pn = kw.get( 'propName') if v: self.vertexSet.vertices.AddValues( v ) if n: self.vertexSet.normals.AddValues( n ) if v or n: self.redoDspLst = 1 self.vertexSet.normals.PropertyStatus(len(self.vertexSet)) # expect a set of 4x4 transformation matrices with translation in # last column. We store a flat version of the transposed matrix since # this is what can be passed to OpenGL directly imat = kw.get( 'instanceMatrices') if imat: imat = Numeric.array(imat).astype('f') imat = Numeric.reshape(imat, (-1,4,4)) assert len(imat.shape)==3 and imat.shape[1:]==(4,4) for m in imat: m = Numeric.reshape( Numeric.transpose(m), (1,16)) conc = Numeric.concatenate self.instanceMatricesFortran = conc( (self.instanceMatricesFortran, m) ) self.redoDspLst = 1 if m: self.redoDspLst = 1 self.AddMaterial( m, propNum=pn, mode=mbm ) elif v or imat: self.MaterialBindingMode(pn, face=pf, mode=mbm) if v or n: if self.shading==GL.GL_SMOOTH: if self.lighting: self.GetNormals() if self.viewer and redo: if self.redoDspLst: self.viewer.objectsNeedingRedo[self] = None def SetForChildren(self, recursive=False, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set properties for children of this object. If recursive is True the properties are set for the entire subtree. """ #print "SetForChildren", kw for c in self.children: apply( c.Set, (), kw) if recursive in (True, 1): apply( c.SetForChildren, (True,), kw) def _setRotation(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() mat = Numeric.reshape(Numeric.array(val), (16,)).astype('f') self.rotation = mat if self.viewer and self != self.viewer.rootObject: return self._redoFlags['redoViewerDisplayListFlag'] else: return 0 def _setTranslation(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') self.translation = mat return self._redoFlags['redoViewerDisplayListFlag'] def _setScale(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() try: mat = Numeric.reshape(Numeric.array(val), (3,)).astype('f') except ValueError, e: raise ValueError, e self.scale = mat return self._redoFlags['redoViewerDisplayListFlag'] def _setPivot(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.SetPivot(val) return 0 def Set(self, check=1, redo=1, updateOwnGui=True, setCurrent=True, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set data for this object check=1 : verify that all the keywords present can be handle by this func redo : if redo == 0 : display lists are not rebuilt updateOwnGui=True : allow to update owngui at the end this func """ #print "Geom.Set" redoFlags = apply( Common2d3dObject.Set, (self, check, 0), kw) if len(kw) == 0: return self.redoNow(redo, updateOwnGui, redoFlags) imat = kw.pop( 'instanceMatricesFromFortran', None) if imat is not None: fortran = True else: fortran = False imat = kw.pop( 'instanceMatricesFromC', None) if imat is None: imat = kw.pop( 'instanceMatrices', None) if imat is not None: imat = Numeric.array(imat).astype('f') imat = Numeric.reshape(imat, (-1,4,4)) assert len(imat.shape)==3 and imat.shape[1:]==(4,4) mats = [] for ma in imat: if fortran is True: mats.append( Numeric.reshape(ma, (16,) ) ) else: mats.append( Numeric.reshape(Numeric.transpose(ma), (16,) ) ) self.instanceMatricesFortran = Numeric.array(mats, 'f') redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] v = kw.pop( 'vertices', None) reshape = kw.pop( 'vreshape', None) n = kw.pop( 'vnormals', None) t = kw.pop( 'texture', None) m = kw.pop( 'materials', None) lPf = kw.pop( 'polyFace', None) mbm = kw.pop( 'matBind', None) pn = kw.pop( 'propName', None) if hasattr(self, 'vertexSet') is False: s = kw.get( 'shape') if v is None and s is None: s = (0,0) self.vertexSet = datamodel.VertexSet( v, s ) # set default face side and default material property if type(lPf) is types.StringType: lPf = lPf.lower() if lPf == 'none': lPf=GL.GL_NONE elif lPf == 'back': lPf=GL.GL_BACK elif lPf == 'front': lPf=GL.GL_FRONT elif lPf == 'frontandback': lPf=GL.GL_FRONT_AND_BACK if lPf is None: lPf = GL.GL_FRONT if not v is None: self.vertexSet.vertices.SetValues( v, reshape ) if not n is None: self.vertexSet.normals.SetValues( n, reshape ) if (v is not None) or (n is not None): redoFlags |= self._redoFlags['redoDisplayListFlag'] # the following line causes vnormals to be overwritten I think (MS) #self.vertexSet.normals.status = viewerConst.UNKNOWN # the line below does not force re-computation we the number # of coordinates is the same change self.vertexSet.normals.PropertyStatus(len(self.vertexSet)) if v is not None: if n is None: self.vertexSet.normals.status = viewerConst.NONE if hasattr(self, 'faceSet') or kw.has_key('faces'): self.faceSet.normals.status = viewerConst.NONE if t is not None: from Texture import Texture assert isinstance(t, Texture) self.texture = t t.objects.append(self) t.viewer = self.viewer redoFlags |= self._redoFlags['redoDisplayListFlag'] if t.format==GL.GL_RGBA: self._setTransparent(1) self.inheritMaterial=0 else: self._setTransparent('implicit') tx = kw.pop( 'textureCoords', None) if tx is not None: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.vertexSet.texCoords = datamodel.VectorProperties('texCoords', tx, datatype=viewerConst.FPRECISION) shp = self.vertexSet.texCoords.ashape assert len(shp)==2 and (shp[1] in (1,2,3,4)) if hasattr(self, 'texture') and self.texture: self.texture.auto = 0 if not v is None or tx is not None: if hasattr(self.vertexSet, 'texCoords'): self.vertexSet.texCoords.PropertyStatus(len(self.vertexSet)) fmode = kw.pop( 'frontPolyMode', None) if fmode: redoFlags |= self._redoFlags['redoDisplayListFlag'] if type(fmode) == types.StringType: fmode = viewerConst.POLYGON_MODES[fmode] assert fmode in viewerConst.POLYGON_MODES.values() self.frontPolyMode = fmode if fmode==viewerConst.INHERIT: self.inheritFrontPolyMode = True else: self.inheritFrontPolyMode = False if self.viewer and fmode in [GL.GL_FILL, viewerConst.OUTLINED] \ and self.lighting: self.GetNormals() bmode = kw.pop( 'backPolyMode', None) if bmode is not None: redoFlags |= self._redoFlags['redoDisplayListFlag'] if type(bmode) == types.StringType: bmode = viewerConst.POLYGON_MODES[bmode] assert bmode in viewerConst.POLYGON_MODES.values() self.backPolyMode = bmode if bmode==viewerConst.INHERIT: self.inheritBackPolyMode = True else: self.inheritBackPolyMode = False if self.viewer and bmode in [GL.GL_FILL, viewerConst.OUTLINED] \ and self.lighting: self.GetNormals() smode = kw.pop('shading', None) if smode is not None: redoFlags |= self._redoFlags['redoDisplayListFlag'] if type(smode) == types.StringType: smode = viewerConst.SHADINGS[smode] assert smode in viewerConst.SHADINGS.values() if smode==viewerConst.INHERIT: self.inheritShading = True else: self.inheritShading = False self.shading = smode if self.viewer: # and self.lighting: self.GetNormals() for object in self.AllObjects(): if isinstance(object, Geom): object.GetNormals() redoFlags |= self._redoFlags['redoDisplayChildrenListFlag'] mask = kw.pop( 'matMask', None) rawMat = kw.pop( 'rawMaterialF', None) if rawMat is not None: #assert len(rawMat)==7 mat = self.materials[GL.GL_FRONT] if mask is None: # default mask sets all properties mask = ( 1, 1, 1, 1, 1, 1 ) for i, prop in enumerate(["ambient", "diffuse", "emission", "specular", "shininess", "opacity"]): if mask[i]: mat.SetMaterial( rawMat[prop], i, self._modified) self.MaterialBindingMode(i, face=GL.GL_FRONT, mode=mbm) if mask[mat.diffuse] or mask[mat.opac]: self.MaterialBindingMode(pn, face=GL.GL_FRONT) redoFlags |= self._redoFlags['redoDisplayListFlag'] rawMat = kw.pop( 'rawMaterialB', None) if rawMat is not None: #assert len(rawMat)==7 mat = self.materials[GL.GL_BACK] if mask is None: # default mask sets all properties mask = ( 1, 1, 1, 1, 1, 1 ) for i, prop in enumerate(["ambient", "diffuse", "emission", "specular", "shininess", "opacity"]): if mask[i]: mat.SetMaterial( rawMat[prop], i, self._modified) self.MaterialBindingMode(i, face=GL.GL_BACK, mode=mbm) if mask[mat.diffuse] or mask[mat.opac]: self.MaterialBindingMode(pn, face=GL.GL_BACK) redoFlags |= self._redoFlags['redoDisplayListFlag'] if lPf == GL.GL_FRONT_AND_BACK: pfList = [GL.GL_FRONT, GL.GL_BACK] elif lPf == GL.GL_FRONT: pfList = [GL.GL_FRONT] elif lPf == GL.GL_BACK: pfList = [GL.GL_BACK] matName = kw.pop( 'matName', None) matInd = kw.pop( 'matInd', None) lOpacity = kw.pop( 'opacity', None) for pf in pfList: if not m is None: try: m = Numeric.array(m, 'f') except ValueError, e: raise ValueError, e self.materials[pf].SetMaterial( m, pn, self._modified ) if pn is None or pn==1 or pn in ['diffuse', 'DIFFUSE', 'diff', 'DIFF']: if len(m.shape)==2 and m.shape[1]==4: # opacity info was provided mat = self.materials[pf] self.MaterialBindingMode(mat.opac) mat.SetMaterial( m[:,3], mat.opac, self._modified ) self.MaterialBindingMode(pn, face=pf, mode=mbm ) redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] elif (v is not None or imat is not None) and not self.inheritMaterial: self.MaterialBindingMode(pn, face=pf, mode=mbm) elif mbm: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.MaterialBindingMode(pn, face=pf, mode=mbm) if matName is not None and matInd is not None: mat = Materials.Materials(matName, matInd) self.materials[pf] = mat #self.inheritMaterial = 0 redoFlags |= self._redoFlags['redoDisplayListFlag'] if lOpacity is not None: try: l = len(lOpacity) except: lOpacity = [lOpacity] mat = self.materials[pf] mat.SetMaterial( lOpacity, mat.opac, self._modified ) self.MaterialBindingMode(mat.opac, face=pf, mode=mbm) redoFlags |= self._redoFlags['redoDisplayListFlag'] # we do transparent here after setting opacity and materials val = kw.pop( 'transparent', None) if not val is None: redoFlags |= self._setTransparent(val) # Schedules this object to hide in val seconds val = kw.pop( 'transient', None) if not val is None: assert isinstance(val, types.IntType) if self.viewer: self.visible = 1 self.redoDspLst =1 self.viewer.cameras[0].after(val*100, self._Hide) else: raise NameError ("Object %s isn't in a viewer" % (self.name,)) val = kw.pop( 'lineWidth', None) if not val is None: assert type(val) == type(0.0) or type(val) == type(0) assert val >= 1 self.lineWidth = int(val) redoFlags |= self._redoFlags['redoDisplayListFlag'] val = kw.pop( 'pointWidth', None) if not val is None: assert type(val) == type(0.0) or type(val) == type(0) assert val >= 1 self.pointWidth = int(val) redoFlags |= self._redoFlags['redoDisplayListFlag'] val = kw.pop( 'visible', None) if not val is None: if val in (True, False): if val != self.visible and self.viewer: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.visible = val else: raise ValueError("visible can only be True or False") val = kw.pop('lighting', None) if not val is None: if val in (True, False): if self.lighting != val: self.lighting = val redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] else: raise ValueError("lighting can only be True or False") if self.lighting and self.normals is None: self.GetNormals() val = kw.pop( 'inheritLighting', None) if val is not None: assert val in (False, True), "only False or True are possible" if self.inheritLighting != val: self.inheritLighting = val redoFlags |= self._redoFlags['updateOwnGuiFlag'] redoFlags |= self._redoFlags['redoDisplayListFlag'] val = kw.pop( 'stippleLines', None) if not val is None: if val in (True, False): self.stippleLines = val else: raise ValueError("stippleLines can only be True or False") val = kw.pop( 'stipplePolygons', None) if not val is None: if val in (True, False): self.stipplePolygons = val else: raise ValueError("stipplePolygons can only be True or False") val = kw.pop( 'outline', None) if not val is None: if val in (True, False): self.drawOutline = (val, val) elif val in ((True, True),(True, False),(False, True),(False, False)): self.drawOutline = val else: raise ValueError("outline can only be True or False, or a tuple like (True, True)") redoFlags |= self._setTransparent('implicit') val = kw.pop( 'culling', None) if val is not None: if type(val) is types.StringType: if val.lower()=="inherit": val=viewerConst.INHERIT elif val.lower()=="none": val=GL.GL_NONE elif val.lower()=="front": val=GL.GL_FRONT elif val.lower()=="back": val=GL.GL_BACK elif val.lower()=="front_and_back": val=GL.GL_FRONT_AND_BACK assert val in (viewerConst.INHERIT, GL.GL_NONE, GL.GL_BACK, GL.GL_FRONT_AND_BACK, GL.GL_FRONT) redoFlags |= self._redoFlags['redoDisplayListFlag'] if val in (GL.GL_BACK, GL.GL_NONE, GL.GL_FRONT, GL.GL_FRONT_AND_BACK ): self.inheritCulling = False self.culling = val elif val == viewerConst.INHERIT: self.inheritCulling = True val = kw.pop( 'pickableVertices', None) if not val is None: if val in (True, False): self.pickableVertices = val else: raise ValueError("pickableVertices can only be True or False") val = kw.pop( 'scissor', None) if not val is None: if val in (True, False): if val == 1: val = True elif val == 0: val = False self.scissor = val if self.viewer is not None: if val is True: self.viewer.activeScissor = self.viewer.activeScissor+1 else: self.viewer.activeScissor = self.viewer.activeScissor-1 redoViewerDisplayListFlagFlag = True else: raise ValueError("scissor can only be True or False") val = kw.pop( 'scissorX', None) if not val is None: if val < 0 : val=0 self.scissorX = int(val) redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'scissorY', None) if not val is None: if val < 0 : val=0 self.scissorY = int(val) redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'scissorW', None) if not val is None: if val < 1 : val=1 self.scissorW = int(val) self.scissorAspectRatio = float(self.scissorW) /self.scissorH redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'scissorH', None) if not val is None: if val < 1 : val=1 self.scissorH = int(val) self.scissorAspectRatio = float(self.scissorW) /self.scissorH redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'scissorAspectRatio', None) if not val is None: if val < 0.0 : val=-val self.scissorAspectRatio = float(val) self.scissorW = int(self.scissorAspectRatio * self.scissorH) redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'depthMask', None) if not val is None: if val in (True, False): self.depthMask = val redoFlags |= self._redoFlags['redoDisplayListFlag'] else: raise ValueError("depthMask can only be True or False") val = kw.pop( 'blendFunctions', None) if not val is None: assert len(val)==2, "arguemnt should be a 2-tuple" src, dst = val if src=="GL_ZERO": src=GL.GL_ZER elif src=="GL_ONE": src=GL.GL_ONE elif src=="GL_DST_COLOR": src=GL.GL_DST_COLOR elif src=="GL_ONE_MINUS_DST_COLOR": src=GL.GL_ONE_MINUS_DST_COLOR elif src=="GL_SRC_ALPHA": src=GL.GL_SRC_ALPHA elif src=="GL_ONE_MINUS_SRC_ALPHA": src=GL.GL_ONE_MINUS_SRC_ALPHA elif src=="GL_DST_ALPHA": src=GL.GL_DST_ALPHA elif src=="GL_ONE_MINUS_DST_ALPHA": src=GL.GL_ONE_MINUS_DST_ALPHA elif src=="GL_SRC_ALPHA_SATURATE": src=GL.GL_SRC_ALPHA_SATURATE if dst=="GL_ZERO": dst=GL.GL_ZERO elif dst=="GL_ONE": dst=GL.GL_ONE elif dst=="GL_SRC_COLOR": dst=GL.GL_SRC_COLOR elif dst=="GL.GL_ONE_MINUS_SRC_COLOR": dst=GL.GL_ONE_MINUS_SRC_COLOR elif dst=="GL_SRC_ALPHA": dst=GL.GL_SRC_ALPHA elif dst=="GL_ONE_MINUS_SRC_ALPHA": dst=GL.GL_ONE_MINUS_SRC_ALPHA elif dst=="GL_DST_ALPHA": dst=GL.GL_DST_ALPHA elif dst=="GL_ONE_MINUS_DST_ALPHA": dst=GL.GL_ONE_MINUS_DST_ALPHA assert src in self.sourceBlendFunctions assert dst in self.destBlendFunctions self.srcBlendFunc = src self.dstBlendFunc = dst redoFlags |= self._redoFlags['redoDisplayListFlag'] inheritMaterial = kw.pop( 'inheritMaterial', None) if not inheritMaterial is None: self.inheritMaterial = inheritMaterial redoFlags |= self._redoFlags['redoDisplayListFlag'] val = kw.pop( 'inheritXform', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritXform = val redoFlags |= self._redoFlags['redoDisplayListFlag'] val = kw.pop( 'inheritPointWidth', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritPointWidth = val redoFlags |= self._redoFlags['redoDisplayListFlag'] # if container we force rebuilding main dpyList val = kw.pop( 'inheritLineWidth', None) if val is not None: assert val in [False,True], "only False or True are possible" self.inheritLineWidth = val redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] # if container we force rebuilding main dpyList val = kw.pop( 'inheritStippleLines', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritStippleLines = val redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] # if container we force rebuilding main dpyList val = kw.pop( 'inheritStipplePolygons', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritStipplePolygons = val redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'inheritFrontPolyMode', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritFrontPolyMode = val redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'inheritBackPolyMode', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritBackPolyMode = val redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'inheritShading', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritShading = val redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] val = kw.pop( 'inheritCulling', None) if val is not None: assert val in [False, True], "only False or True are possible" self.inheritCulling = val redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= self._redoFlags['redoViewerDisplayListFlag'] invertNormals = kw.pop('invertNormals', None) if invertNormals is not None: if self.invertNormals != invertNormals: self.invertNormals = invertNormals inheritSharpColorBoundaries = kw.pop('inheritSharpColorBoundaries', None) if inheritSharpColorBoundaries in [True, False, 1, 0]: if self.inheritSharpColorBoundaries != inheritSharpColorBoundaries: self.inheritSharpColorBoundaries = inheritSharpColorBoundaries redoFlags |= self._redoFlags['redoDisplayChildrenListFlag'] sharpColorBoundaries = kw.pop('sharpColorBoundaries', None) if sharpColorBoundaries in [True, False, 1, 0]: if self.sharpColorBoundaries != sharpColorBoundaries: self.sharpColorBoundaries = sharpColorBoundaries redoFlags |= self._redoFlags['redoDisplayChildrenListFlag'] highlight = kw.pop('highlight', None) if highlight is not None: if self.highlight != highlight: self.highlight = highlight redoFlags |= self._redoFlags['redoDisplayListFlag'] disableStencil = kw.pop( 'disableStencil', None) if disableStencil is not None: self.disableStencil = disableStencil redoFlags |= self._redoFlags['redoDisplayListFlag'] vertexArrayFlag = kw.pop( 'vertexArrayFlag', None) if vertexArrayFlag is not None: self.vertexArrayFlag = vertexArrayFlag redoFlags |= self._redoFlags['redoDisplayListFlag'] if DejaVu.enableVertexArray is True \ and self.vertexArrayFlag is True \ and hasattr(self, 'vertexSet') \ and len(self.vertexSet.vertices.array) > 0: if v is not None: try: DejaVu.enableVBO= True from opengltk.extent import _glextlib #mode = _glextlib.GL_STATIC_DRAW_ARB mode = _glextlib.GL_DYNAMIC_DRAW_ARB if len(self.vertexArrayFlagBufferList): vbos = self.vertexArrayFlagBufferList _glextlib.glDeleteBuffersARB(len(vbos), vbos) self.vertexArrayFlagBufferList = _glextlib.glGenBuffersARB(4) # vertices #print "contiguous", self.vertexSet.vertices.array.flags.contiguous #if self.vertexSet.vertices.array.flags.contiguous is False: # self.vertexSet.vertices.array = Numeric.array(self.vertexSet.vertices.array,copy=1) _glextlib.glBindBufferARB(_glextlib.GL_ARRAY_BUFFER_ARB, int(self.vertexArrayFlagBufferList[0])) #_glextlib.glBufferDataARB( # _glextlib.GL_ARRAY_BUFFER_ARB, # 4*len(self.vertexSet.vertices.array)*\ # len(self.vertexSet.vertices.array[0]), # self.vertexSet.vertices.array, # _glextlib.GL_STATIC_DRAW_ARB) # the following code create GLerror: out of memory on # tahiti vertices = self.vertexSet.vertices.array _glextlib.glBufferDataARB( _glextlib.GL_ARRAY_BUFFER_ARB, 4*len(vertices)*len(vertices[0]), vertices, mode) _gllib.glVertexPointer(len(self.vertexSet.vertices.array[0]), GL.GL_FLOAT, 0, 0) # normals if len(self.vertexSet.normals.array) > 0: _glextlib.glBindBufferARB(_glextlib.GL_ARRAY_BUFFER_ARB, int(self.vertexArrayFlagBufferList[1])) _glextlib.glBufferDataARB(_glextlib.GL_ARRAY_BUFFER_ARB, 4*len(self.vertexSet.normals.array)*len(self.vertexSet.normals.array[0]), self.vertexSet.normals.array, mode) _gllib.glNormalPointer(GL.GL_FLOAT, 0, 0) except (ImportError, AttributeError): DejaVu.enableVBO = False DejaVu.enableVertexArrayVBO = False if DejaVu.enableVertexArrayNonVBO is True: _gllib.glVertexPointer(len(self.vertexSet.vertices.array[0]), GL.GL_FLOAT, 0, self.vertexSet.vertices.array) if len(self.vertexSet.normals.array) > 0: _gllib.glNormalPointer(GL.GL_FLOAT, 0, self.vertexSet.normals.array) enableVertexArray = DejaVu.enableVertexArrayVBO or DejaVu.enableVertexArrayNonVBO if (m is not None or inheritMaterial is not None) \ and (DejaVu.enableVBO is True or DejaVu.enableVertexArrayNonVBO is True): if self.materials[GL.GL_FRONT] and not self.inheritMaterial: mat = self.materials[GL.GL_FRONT] fpProp = [] fpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) fpProp.append(p) fpBind.append(b) fpProp.append(mat.prop[4]) fpBind.append(mat.binding[4]) else: fpProp = None fpBind = None if self.materials[GL.GL_BACK] and not self.inheritMaterial: mat = self.materials[GL.GL_BACK] bpProp = [] bpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) bpProp.append(p) bpBind.append(b) bpProp.append(mat.prop[4]) bpBind.append(mat.binding[4]) else: bpProp = None bpBind = None if fpBind is not None and fpBind[1] == viewerConst.PER_VERTEX: lColorArray = fpProp[1][:] self.colorArray = lColorArray.ravel() self.colorArray.shape = lColorArray.shape if DejaVu.enableVBO is True: # colors from opengltk.extent import _glextlib _glextlib.glBindBufferARB(_glextlib.GL_ARRAY_BUFFER_ARB, int(self.vertexArrayFlagBufferList[3])) _glextlib.glBufferDataARB(_glextlib.GL_ARRAY_BUFFER_ARB, 4*len(self.colorArray)*len(self.colorArray[0]), self.colorArray, _glextlib.GL_STATIC_DRAW_ARB) _gllib.glColorPointer(4, GL.GL_FLOAT, 0, 0) elif DejaVu.enableVertexArrayNonVBO is True: _gllib.glColorPointer(4, GL.GL_FLOAT, 0, self.colorArray) self.colorPointerIsOn = True else: self.colorPointerIsOn = False elif DejaVu.enableVertexArray is False: DejaVu.enableVBO= False return self.redoNow(redo, updateOwnGui, redoFlags, setCurrent) def _setTransparent(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "_setTransparent", self.name, val t1 = self.materials[GL.GL_FRONT].fixOpacity() t2 = self.materials[GL.GL_BACK].fixOpacity() lDetectedTransparency = t1 or t2 if val == 'implicit': val = lDetectedTransparency \ or ( (self.getDrawOutlineMode('front') is True or \ self.getDrawOutlineMode('back') is True) and self.outline.color[3]<1.0) elif val is True: val = 1 elif val is False: val = 0 assert val in [0,1], "only 0 or 1 are possible" self.transparent = val return self._redoFlags['redoDisplayListFlag'] | self._redoFlags['redoViewerDisplayListFlag'] # if container we force rebuilding main dpyList def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() v = hasattr(self, 'vertexSet') f = hasattr(self, 'faceSet') if v and f: return '<%s> %s with %d vertices and %d faces' % (self.__class__, self.name, len(self.vertexSet), len(self.faceSet) ) if v: return '<%s> %s with %d vertices' % (self.__class__, self.name, len(self.vertexSet) ) return '<%s> ' % (self.__class__, ) def BoundingBox(self, display=None, color=None, lineWidth=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Turn Bounding Box drawing on and off, set attributs""" if not display is None: assert display in viewerConst.BB_MODES self.drawBB = display if color: color = OneColor( color ) if color: self.colorBB = color if lineWidth: self.lineWidthBB = lineWidth def Draw(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ function that make the opengl call to draw the geom Should be call by RedoDisplayList in between glNewList/ glEndList """ #print "Geom.Draw", self.name pass def deleteOpenglTemplateList(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Common2d3dObject.deleteOpenglTemplateList", self if hasattr(self, 'makeTemplate') is True: if self.templateDSPL is not None: #viewer.currentCamera.tk.call(viewer.currentCamera._w, 'makecurrent') self.deleteTemplate() def deleteOpenglList(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Geom.deleteOpenglList", self Common2d3dObject.deleteOpenglList(self) if self.outline.dpyList is not None: currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if currentcontext != self.outline.dpyList[1]: warnings.warn("""deleteOpenglList failed because the current context is the wrong one""") #print "currentcontext != self.outline.dpyList[1]", currentcontext, self.outline.dpyList[1] else: #print '-%d'%self.outline.dpyList[0], currentcontext, "glDeleteLists Geom" GL.glDeleteLists(self.outline.dpyList[0], 1) self.outline.dpyList = None def RedoDisplayList(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "Geom.RedoDisplayList", self ## if __debug__: ## print 'Spheres RedoDisplayList for', self.fullName resetMaterialMemory() Common2d3dObject.RedoDisplayList(self) def AddClipPlane(self, cp, side=-1, clipChildren=True, tagModified=True): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add the arbitrary clipping plane 'cp' to this geometry""" self._modified = tagModified if not isinstance(cp, Clip.ClippingPlane): msg = 'First agument has to be an instance of a ClippingPlane' raise AttributeError(msg) if not self.viewer: msg = 'clipping plane can only be added after the is in a viewer' raise RuntimeError(msg) if side in (-1,1): self.clipSide[cp.num] = side else: raise AttributeError('side can only be 1 or -1') if clipChildren is True: self.clipPI.append( cp ) elif clipChildren is False: self.clipP.append( cp ) else: raise AttributeError('clipChildren can only be True or False') self.viewer.activeClippingPlanes = self.viewer.activeClippingPlanes + 1 if not self.viewer.currentClip: self.viewer.currentClip = cp self.viewer.deleteOpenglList() def RemoveClipPlane(self, cp): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Remove the clip. plane from the list of CP clipping this object""" if not isinstance(cp, Clip.ClippingPlane): msg = 'First agument has to be an instance of ClippingPlane' raise AttributeError(msg) if cp in self.clipPI: self.clipPI.remove(cp) elif cp in self.clipP: self.clipP.remove(cp) self.viewer.activeClippingPlanes = self.viewer.activeClippingPlanes - 1 self.viewer.deleteOpenglList() def ApplyParentsTransform(self, coords, instance=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Return a vector of 3D coordinates transformed by all transformations up to root (excluded)""" mat = self.GetMatrix( self.LastParentBeforeRoot(), instance ) one = Numeric.ones( (coords.shape[0], 1), coords.dtype.char ) c = Numeric.concatenate( (coords, one), 1 ) return Numeric.dot(c, Numeric.transpose(mat))[:, :3] def TransformedCoords(self, root=None, instance=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Return the vertices after applying the current transformation""" if root is None: root = self.viewer.rootObject if len(self.vertexSet): m = self.GetMatrix(root, instance) return self.vertexSet.vertices * m else: return None ## def GravityCenterSubtree(self): ## """Compute the center of gravity of the object subtree""" ## allObj = self.AllObjects() ## center = Numeric.zeros( (3, ), viewerConst.FPRECISION) ## for o in allObj: ## if not o.visible: continue ## if len(o.vertexSet): ## m = o.GetMatrix(self) ## p = Numeric.concatenate( (o.vertices.GravityCenter(), [1.0]) ) ## p = Numeric.dot(m, p) ## center = center + p[:3] ## return center/len(allObj) def ObjSubTreeBB(self, obj, camera=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if camera is None: camera = self.viewer.currentCamera if obj.hiddenInCamera.has_key(camera): return if not obj.visible: return GL.glPushMatrix() obj.MakeMat() for m in obj.instanceMatricesFortran: GL.glPushMatrix() GL.glMultMatrixf(m) for child in obj.children: if child.visible and isinstance(child, Transformable): self.ObjSubTreeBB(child, camera) #if not obj.visible: # return if len(obj.vertexSet): v = obj.vertexSet.vertices.array v = Numeric.reshape(v, (-1,3)).astype('f') else: if obj.maxBB is not None and obj.minBB is not None: v = Numeric.array( [obj.maxBB, obj.minBB], 'f') else: v = [] if len(v): v = Numeric.reshape(v, (-1,3)) ones = Numeric.ones( (len(v),1) ).astype('f') vhom = Numeric.concatenate( (v,ones), 1) mat = GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX) mat = Numeric.reshape(mat,(4,4)) # apply current matrix to coordinates and check against bb ct = Numeric.dot( vhom, mat ) maxo = Numeric.maximum.reduce(ct)[:3] if self.__maxBB is None: self.__maxBB = maxo else: self.__maxBB = Numeric.maximum.reduce((self.__maxBB, maxo)) mino = Numeric.minimum.reduce(ct)[:3] if self.__minBB is None: self.__minBB = mino else: self.__minBB = Numeric.minimum.reduce((self.__minBB, mino)) # we add the radius of the sphere to the bounding box if hasattr(obj, 'radius'): lRadius = None if hasattr(obj.radius, '__len__'): if len(obj.Radius) > 0: lRadius = obj.radius[0] else: lRadius = obj.radius if lRadius is not None: self.__minBB -= lRadius self.__maxBB += lRadius GL.glPopMatrix() GL.glPopMatrix() # Restore the matrix def ComputeBB(self, camera=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """This method computes the bounding box of the visible objects in the tree rooted at this object. This method handles properly instance matrices """ # simulate a full redraw to build Xform matrices, apply to points # and find bounding box GL.glPushMatrix() GL.glLoadIdentity() self.__minBB = None self.__maxBB = None self.ObjSubTreeBB(self, camera) GL.glPopMatrix() maxBB = self.__maxBB minBB = self.__minBB del self.__maxBB del self.__minBB if minBB is None: minBB = (-10, -10, -10) if maxBB is None: maxBB = (10, 10, 10) return Numeric.array(minBB), Numeric.array(maxBB) def _DrawBox(self, bbmin, bbmax): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Draw the bounding box using lines""" GL.glPushAttrib(GL.GL_CURRENT_BIT | GL.GL_LIGHTING_BIT | GL.GL_LINE_BIT ) GL.glShadeModel(GL.GL_FLAT) GL.glDisable(GL.GL_LIGHTING) GL.glColor4fv ( self.colorBB ) GL.glLineWidth( self.lineWidthBB ) #FIXME build a display list for a cube once # just scale the 3 dimensions and translate GL.glBegin(GL.GL_LINE_STRIP) GL.glVertex3f(float(bbmin[0]),float(bbmin[1]),float(bbmin[2])) GL.glVertex3f(float(bbmax[0]),float(bbmin[1]),float(bbmin[2])) GL.glVertex3f(float(bbmax[0]),float(bbmax[1]),float(bbmin[2])) GL.glVertex3f(float(bbmin[0]),float(bbmax[1]),float(bbmin[2])) GL.glVertex3f(float(bbmin[0]),float(bbmin[1]),float(bbmin[2])) GL.glEnd() GL.glBegin(GL.GL_LINE_STRIP) GL.glVertex3f(float(bbmin[0]),float(bbmin[1]),float(bbmax[2])) GL.glVertex3f(float(bbmax[0]),float(bbmin[1]),float(bbmax[2])) GL.glVertex3f(float(bbmax[0]),float(bbmax[1]),float(bbmax[2])) GL.glVertex3f(float(bbmin[0]),float(bbmax[1]),float(bbmax[2])) GL.glVertex3f(float(bbmin[0]),float(bbmin[1]),float(bbmax[2])) GL.glEnd() GL.glBegin(GL.GL_LINES) GL.glVertex3f(float(bbmin[0]),float(bbmin[1]),float(bbmin[2])) GL.glVertex3f(float(bbmin[0]),float(bbmin[1]),float(bbmax[2])) GL.glVertex3f(float(bbmin[0]),float(bbmax[1]),float(bbmin[2])) GL.glVertex3f(float(bbmin[0]),float(bbmax[1]),float(bbmax[2])) GL.glVertex3f(float(bbmax[0]),float(bbmax[1]),float(bbmin[2])) GL.glVertex3f(float(bbmax[0]),float(bbmax[1]),float(bbmax[2])) GL.glVertex3f(float(bbmax[0]),float(bbmin[1]),float(bbmin[2])) GL.glVertex3f(float(bbmax[0]),float(bbmin[1]),float(bbmax[2])) GL.glEnd() GL.glPopAttrib() def DrawTreeBoundingBox(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Draw's the bounding box of this object and all of its visible descendants""" #bbmin, bbmax = self.BoundingBoxSubtree() bbmin, bbmax = self.ComputeBB(self.viewer.currentCamera) self._DrawBox( bbmin, bbmax ) def DrawBoundingBox(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Draw's the objects bounding box""" self._DrawBox( self.vertexSet.vertices.bbmin, self.vertexSet.vertices.bbmax ) def addVertexNormalsGeom(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "addVertexNormalsGeom" if self is self.viewer.rootObject: return None if self.name.endswith('_vertexnormals'): return None for c in self.children: if c.name.endswith('_vertexnormals'): return None n = self.getVNormals() if len(n) == 0: return None v = self.getVertices() if len(n) == 0: return None pts = map(lambda x,y: (x, (x[0]+y[0],x[1]+y[1],x[2]+y[2])), v,n) from DejaVu.Polylines import Polylines g = Polylines(self.name+'_vertexnormals', vertices=pts) g.inheritedNormarrow = GL.GL_NONE self.viewer.AddObject(g, parent=self) self.vertexNormals = True return g def faceCenterVector(self, faceIndex): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() v0 = self.vertexSet.vertices.array[self.faceSet.faces.array[faceIndex][0]] v1 = self.vertexSet.vertices.array[self.faceSet.faces.array[faceIndex][1]] v2 = self.vertexSet.vertices.array[self.faceSet.faces.array[faceIndex][2]] center = ( (v0[0] + v1[0] + v2[0]) * 0.33333333333333333333333333 , (v0[1] + v1[1] + v2[1]) * 0.33333333333333333333333333 , (v0[2] + v1[2] + v2[2]) * 0.33333333333333333333333333 ) normal = self.faceSet.normals.array[faceIndex] outsidePoint = (center[0]+normal[0],center[1]+normal[1],center[2]+normal[2]) return center, outsidePoint def addFaceNormalsGeom(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if not hasattr(self, 'faceSet'): return None if self is self.viewer.rootObject: return None if self.name.endswith('_facenormals'): return None for c in self.children: if c.name.endswith('_facenormals'): return None n = self.getFNormals() if len(n) == 0: return None f = self.getFaces() if len(n) == 0: return None v = self.getVertices() if len(n) == 0: return None pts = [] for i in range(len(self.faceSet.faces.array)): pts.append(self.faceCenterVector(i)) from DejaVu.Polylines import Polylines g = Polylines(self.name+'_facenormals', vertices=pts) g.inheritedNormarrow = GL.GL_NONE self.viewer.AddObject(g, parent=self) self.faceNormals = True return g def removeVertexNormalsGeom(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self is self.viewer.rootObject: return None if self.name.endswith('_vertexnormals'): return None for c in self.children: if c.name.endswith('_vertexnormals'): self.viewer.RemoveObject(c) self.vertexNormals = False def removeFaceNormalsGeom(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self is self.viewer.rootObject: return None if self.name.endswith('_facenormals'): return None for c in self.children: if c.name.endswith('_facenormals'): self.viewer.RemoveObject(c) self.faceNormals = False def RenderMode(self, mode=None, shading=None, face=GL.GL_FRONT, redo=1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the render mode""" warnings.warn('RenderMode is deprecated, use .Set(frontPolyMode=, shading=)', DeprecationWarning, stacklevel=2) if not mode is None: if type(mode) == types.StringType: mode = viewerConst.POLYGON_MODES[mode] if mode in viewerConst.POLYGON_MODES.values(): if face==GL.GL_BACK: self.backPolyMode = mode self.inheritBackPolyMode = False else: self.frontPolyMode = mode self.inheritFrontPolyMode = False elif mode==viewerConst.INHERIT: if face==GL.GL_BACK: self.inheritBackPolyMode = True else: self.inheritFrontPolyMode = True else: raise AttributeError('Invalide polygon mode') if not shading is None: inhSet = False if shading == viewerConst.INHERIT: shading = GL.GL_NONE self.inheritShading = True inhSet = True if shading in viewerConst.SHADINGS: if not inhSet: self.inheritShading = False self.shading = shading else: raise AttributeError('Invalid shading model %d' % (shading,)) if self.viewer: if (mode==GL.GL_FILL or shading != 'ignore'): self.redoDspLst = 1 if self.lighting: self.GetNormals() if redo: self.viewer.objectsNeedingRedo[self] = None def asIndexedPolygons(self, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Should return an IndexedPolygons object if this object can be represented using triangles, else return None""" return None def sortPoly(self, order=-1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """None <- sortPoly(order=-1) Sorts the geometry polygons according to z values of polygon's geomtric centers. Order=-1 sorts by furthest z first,, order=1 sorts by closest z first""" for g in self.children: if len(g.faceSet): g.sortPoly(order) def sortPoly_cb(self, event=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.sortPoly() def setViewer(self, viewer, buildDisplayList): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set viewer in all children of geom object """ Common2d3dObject.setViewer(self, viewer, buildDisplayList) if hasattr(self, 'texture') and self.texture: self.texture.viewer = viewer mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/.pydevproject0000644000175000017500000000046011456141350022404 0ustar debiandebian python 2.6 Default mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/LICENSE0000644000175000017500000000436411033235606020700 0ustar debiandebianThis software is copyrighted by Michel F. Sanner (sanner@scripps.edu) and TSRI. The following terms apply to all files associated with the software unless explicitly disclaimed in individual files. MGLTOOLS SOFTWARE LICENSE AGREEMENT. 1. Grant Of Limited License; Software Use Restrictions. The programs received by you will be used only for NON COMMERCIAL purposes. This license is issued to you as an individual. For COMMERCIAL use done with the software please contact Michel F. Sanner for details about commercial usage license agreements. For any question regarding license agreements, please contact Michel Sanner: TSRI, Molecular Biology Department, TCP 26, 10550 North Torrey Pines Road, La Jolla, CA 92037 sanner@scripps.edu tel (858) 784-7742 fax (858) 784-2341 2. COMMERCIAL USAGE is defined as revenues generating activities. These include using this software for consulting activities and selling applications built on top of, or using this software. Scientific research in an academic environment and teaching are considered NON COMMERCIAL. 3. Copying Restrictions. You will not sell or otherwise distribute commercially these programs or derivatives to any other party, whether with or without consideration. 4. Ownership of Software. You will not obtain, and will not attempt to obtain copyright coverage thereon without the express purpose written consent of The Scripps Research Institute and Dr. Sanner. 5. IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 6. THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/datamodel.py0000644000175000017500000003543011167702236022203 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # # Revision: Guillaume Vareille # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/datamodel.py,v 1.19 2009/04/10 17:40:46 vareille Exp $ # # $Id: datamodel.py,v 1.19 2009/04/10 17:40:46 vareille Exp $ # """Classes to store data such as vertices, faces, properties etc...""" import numpy.oldnumeric as Numeric import viewerConst import types import DejaVu def isarray(var): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return type(var).__name__ == 'array' class ValuesArray: """base class for arrays of data ValuesArray is a class used to represent data that can be stored in a Numeric array. The shape of the array holding the data and the precision is set at creation time and only data that matches this shape can be added to this array """ def _FirstValues(self, data=None, shape=None, datatype=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the initial set of values, always returns a copy""" if data is not None: if len(data)==0: self.ashape = (0,) + self.ashape[1:] return Numeric.zeros( self.ashape, self.type) elif isarray(data): # data is an Numeric array if not datatype: if self.type: datatype = self.type else: raise AttributeError('I Need a datatype') if data.typecode() == self.type: # right type if shape is None: self.ashape = data.shape if data.shape == self.ashape: return Numeric.array(data) else: return Numeric.reshape(data, shape ) else: # bad type data = data.astype(datatype) if shape is None: self.ashape = data.shape # if data.shape == self.ashape: return Numeric.array(data) if data.shape == self.ashape: return data else: return Numeric.reshape(data, shape) else: # data is not an array if datatype and shape: data = Numeric.array( data, self.type) return Numeric.reshape( data, shape ) elif datatype: d=Numeric.array( data, datatype) self.ashape = d.shape return d else: try: d=Numeric.array( data, self.type) except ValueError: raise ValueError('Bad argument') if d.dtype.char in Numeric.typecodes['Integer'] or \ d.dtype.char in Numeric.typecodes['UnsignedInteger']: d=Numeric.array( data, viewerConst.IPRECISION) else: d=Numeric.array( data, viewerConst.FPRECISION) self.ashape = d.shape return d else: # No data if datatype and shape: d = Numeric.zeros( (0,), self.type) d.shape = shape return d else: raise AttributeError('I Need a datatype and a shape') def __init__(self, name, data=None, shape=None, datatype=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Create an instance, with a name and (shape or data)""" assert type(name) == types.StringType if shape is not None and data is not None: raise AttributeError("need shape or data attribute") # if __debug__: # if data: assert type(data).__name__ == 'array' self.name = name self.array = None self.type = datatype self.ashape = shape # array's shape self.array = self._FirstValues(data, shape, datatype) self.fixedShape = self.ashape[1:] def __len__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns the number of entries""" return int(Numeric.multiply.reduce(self.array.shape)) def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """List name, number of values and the shape of this array""" #d = self.array return '' % \ (self.name, len(self), self.type, str(self.array.shape) ) def SetValues(self, values, reshape=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set values""" if values is None: return d = self._FirstValues(values) if len(self.ashape[1:]) != len(self.fixedShape): raise AttributeError("input array bad shape %s!=%s" % \ (str(self.ashape[1:]), str(self.fixedShape))) if len(self.array): if not reshape and d.shape[1:] != self.fixedShape: raise AttributeError("input array of bad shape") self.fixedShape = d.shape[1:] self.array = d self.ashape = self.array.shape def _ShapeValues(self, values): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Check type and shape, coerce if needed""" if isarray(values) and values.dtype.char == self.type: if values.shape[1:] == self.fixedShape: return values else: return Numeric.reshape( values, ( -1,) + self.fixedShape ) else: values = Numeric.array( values, self.type) return Numeric.reshape( values, ( -1,) + self.fixedShape ) def AddValues(self, values): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add values""" if values is None: return if len(self.array)==0: self.SetValues(values) self.fixedShape = self.ashape[1:] else: self.array = Numeric.concatenate( (self.array, self._ShapeValues(values)) ) self.ashape = self.array.shape class PropertiesArray(ValuesArray): """base class for property Arrays""" def __init__(self, name, data=None, shape=None, datatype=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() ValuesArray.__init__(self, name, data, shape, datatype) self.Compute = None # user settable function to compute prop. self.args = () # arguments to function Compute self.computeMode = None # computation mode self.status = viewerConst.UNKNOWN def ComputeFunction(self, func, args): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the function used to compute this property""" assert callable(func) assert type(args).__name__=='tuple' self.Compute = func self.args = args def ComputeMode(self, mode): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the computation mode for this property""" if mode in ( viewerConst.NO_COMPUTATION, viewerConst.AUTO ): self. computeMode = mode else: raise AttributeError("Bad property computation mode NO_COMPUTATION,\ AUTO") def PropertyStatus(self, neededNumber): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Check if we have as many property values as we need""" if self.array is None or neededNumber == 0: self.status = viewerConst.NONE elif len(self) == neededNumber: self.status = viewerConst.SET elif len(self) > neededNumber: self.status = viewerConst.TOO_MANY elif len(self) < neededNumber: self.status = viewerConst.TOO_FEW def AddValues(self, values, neededNumber=-1): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add values""" ValuesArray.AddValues(self, values) if neededNumber>0: self.PropertyStatus(neededNumber) def GetProperty(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """May be compute and return the values""" if self.status < viewerConst.COMPUTED: if self.Compute and self.computeMode==viewerConst.AUTO: d = apply(self.Compute, self.args) if d is not None: self.SetValues(d) self.status=viewerConst.COMPUTED else: self.status=viewerConst.NONE return None else: self.status=viewerConst.NONE return None return self.array class VectorProperties(PropertiesArray): """base class for arrays of vector property values""" def __init__(self, name, data=None, shape=None, datatype=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() PropertiesArray.__init__(self, name, data, shape, datatype) if len(self.ashape) < 2: raise AttributeError('VectorProperties require at least a 2D array') def __len__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns the number of property vectors""" return int(Numeric.multiply.reduce(self.array.shape[:-1])) def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """List name, number of values and the shape of this array""" #d = self.array return '' % \ (self.name, len(self), self.ashape[-1], self.type, str(self.ashape), self.status ) def __mul__(self, mat): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Apply the transformation matrix to the vertices""" assert self.array.shape[-1]==3 self.Flatten() one = Numeric.ones( (self.array.shape[0], 1), viewerConst.FPRECISION ) c = Numeric.concatenate( (self.array, one), 1 ) self.UnFlatten() return Numeric.dot( c, Numeric.transpose(mat) )[:, :3] def Flatten(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Reshape the coordinates to a 2D array of vectors""" self.oldshape = self.array.shape self.array = Numeric.reshape( self.array, (-1, self.oldshape[-1] ) ) def UnFlatten(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Reshape the coordinates to initial shape array""" self.array = Numeric.reshape( self.array, self.oldshape) def BoundingBox(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Compute and return the bounding box of the vectors""" self.Flatten() self.bbmax = Numeric.maximum.reduce(self.array) self.bbmin = Numeric.minimum.reduce(self.array) self.UnFlatten() return self.bbmin, self.bbmax class ScalarProperties(PropertiesArray): """base class for arrays of scalar property values""" def __init__(self, name, data=None, shape=None, datatype=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() PropertiesArray.__init__(self, name, data, shape, datatype) def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """List name, number of values and the shape of this array""" #d = self.array return '' % \ (self.name, len(self), self.type, str(self.ashape),self.status ) class Set: """base class for VertexSet and Face Set""" def __init__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() self.properties = {} def AddScalarProperty(self, name, data=None, shape=None, datatype=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """add a scalar property""" assert type(name) == types.StringType if name in self.properties.keys(): raise ValueError('Property name already used') p = ScalarProperties(name, data, shape, datatype) eval ( 'self.%s = p', name ) self.properties[name] = p def AddVectorProperty(self, name, data=None, shape=None, datatype=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """add a vector property""" assert type(name) == types.StringType if name in self.properties.keys(): raise ValueError('Property name already used') p = VectorProperties(name, data, shape, datatype) eval ( 'self.%s = p', name ) self.properties[name] = p def ListProperties(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """List names and summary of defined properties""" for p in self.properties.keys(): print repr(self.properties[p]) class VertexSet(Set): """class for vertices""" def __init__(self, vert=None, shape=None, norm=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() Set.__init__(self) if vert is not None and len(vert): self.vertices = VectorProperties('vertices', data=vert, datatype=viewerConst.FPRECISION) elif shape is not None: self.vertices = VectorProperties( 'vertices', shape=shape, datatype=viewerConst.FPRECISION) else: raise AttributeError("I need data or a shape") if norm is not None and len(vert): # self.AddVectorProperty('normals', norm, # datatype=viewerConst.FPRECISION) self.normals = VectorProperties('normals', norm, datatype=viewerConst.FPRECISION) else: nshape = len(self.vertices.ashape) * (0,) # self.AddVectorProperty('normals', norm, # datatype=viewerConst.FPRECISION) self.normals = VectorProperties('normals', shape=nshape, datatype=viewerConst.FPRECISION) if len(self.vertices) > 0: self.vertices.BoundingBox() def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return '<%s> with %d elements prop: %s' % \ (self.__class__, len(self.vertices), str(self.properties.keys())) def __len__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns the number of vertices""" return len(self.vertices) def AddValues(self, values): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Add values""" self.vertices.AddValues(values) if len(self.vertices) > 0: self.vertices.BoundingBox() class FaceSet(Set): """class for vertices""" def __init__(self, faces=None, shape=None, norm=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() Set.__init__(self) if faces: self.faces = VectorProperties('faces', data=faces, datatype=viewerConst.IPRECISION) elif shape: self.faces = VectorProperties('faces', shape=shape, datatype=viewerConst.IPRECISION) else: raise AttributeError("I need data or a shape") if norm: self.AddVectorProperty('normals', norm) else: nshape = len(self.faces.ashape) * (0,) self.normals = VectorProperties('normals', shape=nshape, datatype=viewerConst.FPRECISION) def __repr__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() return '<%s> with %d elements prop: %s' % \ (self.__class__, len(self.faces), str(self.properties.keys())) def __len__(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns the number of faces""" return len(self.faces) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/glfSticker.py0000644000175000017500000004641511627527713022361 0ustar debiandebian######################################################################## # # Date: August 2006 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/glfSticker.py,v 1.31 2011/08/31 22:03:55 sanner Exp $ # # $Id: glfSticker.py,v 1.31 2011/08/31 22:03:55 sanner Exp $ # import os import Tkinter import Pmw from math import floor, ceil from opengltk.OpenGL import GL from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from pyglf import glf from DejaVu.Insert2d import Insert2d from DejaVu.viewerFns import checkKeywords from DejaVu.ColorChooser import ColorChooser class Sticker(Insert2d): keywords = Insert2d.keywords + [ 'label', 'fontName', 'fontSpacing', 'fontColor', 'fontScales', 'wireFont', 'frameColor', 'framePolygonMode', 'frameSpace', ] glfVectorFontList = [ 'arial1.glf', 'courier1.glf', 'crystal1.glf', 'techno0.glf', 'techno1.glf', 'times_new1.glf', 'aksent1.glf', 'alpine1.glf', 'broadway1.glf', 'chicago1.glf', 'compact1.glf', 'cricket1.glf', 'garamond1.glf', 'gothic1.glf', 'penta1.glf', 'present_script1.glf' ] framePolygonModeDict = { 'none' : GL.GL_NONE, 'line' : GL.GL_LINE, 'fill' : GL.GL_FILL } framePolygonModeDictRev = { GL.GL_NONE :'none', GL.GL_LINE :'line', GL.GL_FILL :'fill'} def __init__(self, name='sticker', check=1, **kw): # GLF FONTS Initialisations glf.glfInit() glf.glfEnable(glf.GLF_CONSOLE_MESSAGES) lGlfModulePath = os.path.split(glf.__file__)[-2] lPathToFonts = lGlfModulePath+os.sep+'fonts'+os.sep self.glfVectorFontLoadIdDict = {} for font in self.glfVectorFontList: self.glfVectorFontLoadIdDict[font] = glf.glfLoadFont(lPathToFonts+font) self.label = 'No Label Yet' self.fontName = 'arial1.glf' self.glfFontID = self.glfVectorFontLoadIdDict[self.fontName] self.fontSpacing = .2 self.fontColor = (1, 1, 1, .8) self.fontScales = (10, 10) self.wireFont = False self.frameColor = (0, 1, 1, .5) self.framePolygonMode = GL.GL_LINE #GL.GL_FILL # GL.GL_NONE for no frame self.frameSpace = (.2, .2) apply( Insert2d.__init__, (self, name), kw) self.needsRedoDpyListOnResize = True def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ #print "Sticker.Set" redoFlags = apply( Insert2d.Set, (self, check, 0), kw) label = kw.get('label') if label: kw.pop('label') self.label = label redoFlags |= self._redoFlags['redoDisplayListFlag'] fontName = kw.get('fontName') if fontName: kw.pop('fontName') self.glfFontID = self.glfVectorFontLoadIdDict[fontName] redoFlags |= self._redoFlags['redoDisplayListFlag'] fontSpacing = kw.get('fontSpacing') if fontSpacing: kw.pop('fontSpacing') self.fontSpacing = fontSpacing redoFlags |= self._redoFlags['redoDisplayListFlag'] position = kw.get('position') if position: kw.pop('position') self.position = position redoFlags |= self._redoFlags['redoDisplayListFlag'] fontScales = kw.get('fontScales') if fontScales: kw.pop('fontScales') self.fontScales = fontScales redoFlags |= self._redoFlags['redoDisplayListFlag'] wireFont = kw.get('wireFont') if wireFont is not None: kw.pop('wireFont') self.wireFont = wireFont redoFlags |= self._redoFlags['redoDisplayListFlag'] fontColor = kw.get('fontColor') if fontColor: kw.pop('fontColor') self.fontColor = fontColor redoFlags |= self._redoFlags['redoDisplayListFlag'] frameColor = kw.get('frameColor') if frameColor: kw.pop('frameColor') self.frameColor = frameColor redoFlags |= self._redoFlags['redoDisplayListFlag'] framePolygonMode = kw.get('framePolygonMode') if framePolygonMode is not None: kw.pop('framePolygonMode') self.framePolygonMode = framePolygonMode redoFlags |= self._redoFlags['redoDisplayListFlag'] frameSpace = kw.get('frameSpace') if frameSpace: kw.pop('frameSpace') self.frameSpace = frameSpace redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def calculateSize(self): #print "Sticker.calculateSize", self glf.glfSetCurrentFont(self.glfFontID) glf.glfSetSymbolSpace(self.fontSpacing) lLabelbounds = glf.glfGetStringBounds(self.label) # this is the correct way to use glfGetStringBounds to obtain the exact frame around the label # (it still needs more correction when there are spaces in the label) lFramebounds = ( -1, lLabelbounds[1], -1+(lLabelbounds[2]-lLabelbounds[0])-glf.glfGetSymbolSpace(), lLabelbounds[3] ) # we want the frame to be a bit larger than the label lFramebounds = ( lFramebounds[0]-self.frameSpace[0], lFramebounds[1]-self.frameSpace[1], lFramebounds[2]+self.frameSpace[0], lFramebounds[3]+self.frameSpace[1]) self.size[0] = (lFramebounds[2] - lFramebounds[0]) * self.fontScales[0] self.size[1] = (lFramebounds[3] - lFramebounds[1]) * self.fontScales[1] self.size[0] = int(ceil( self.size[0] )) self.size[1] = int(ceil( self.size[1] )) #print "self.size", self.size return lLabelbounds def drawSticker(self, lLabelbounds): if self.framePolygonMode != GL.GL_NONE: lenFrameColor = len(self.frameColor) if lenFrameColor == 4: GL.glColor4fv(self.frameColor) elif lenFrameColor == 3: GL.glColor3fv(self.frameColor) GL.glPolygonMode(GL.GL_FRONT, self.framePolygonMode) GL.glBegin(GL.GL_QUADS) GL.glVertex2f(0, 0) GL.glVertex2f(float(self.size[0]), 0) GL.glVertex2f(float(self.size[0]), float(self.size[1])) GL.glVertex2f(0, float(self.size[1])) GL.glEnd() GL.glScalef(float(self.fontScales[0]), float(self.fontScales[1]), 0) GL.glTranslatef(float(self.frameSpace[0]), float(self.frameSpace[1]), 0) # this corrects the glf draw function to start the label at the proper position GL.glTranslatef(1, float(-lLabelbounds[1]), 0) lenFontColor = len(self.fontColor) if lenFontColor == 4: GL.glColor4fv(self.fontColor) elif lenFontColor == 3: GL.glColor3fv(self.fontColor) GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL) if self.wireFont in [0, False]: glf.glfDrawSolidString(self.label) else: glf.glfDrawWiredString(self.label) def Draw(self): #print "Sticker.Draw", self GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() GL.glLoadIdentity() Insert2d.Draw(self) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glDisable(GL.GL_DEPTH_TEST) GL.glDisable(GL.GL_LIGHTING); lLabelbounds = self.calculateSize() width = self.size[0] height = self.size[1] fullWidth = self.viewer.currentCamera.width fullHeight = self.viewer.currentCamera.height # we want the anchor of the image to be at the given position posxFromLeft = self.position[0] * fullWidth - self.anchor[0] * width posyFrombottom = (1.-self.position[1]) * fullHeight - (1.-self.anchor[1]) * height posxFromLeft = int(floor( posxFromLeft ) ) posyFrombottom = int(floor( posyFrombottom ) ) if (self.position[1] == 0.): posyFrombottom -= 1 #print "posxFromLeft, posyFrombottom", posxFromLeft, posyFrombottom # used for picking self.polygonContour = [ (posxFromLeft, posyFrombottom), (posxFromLeft+width, posyFrombottom), (posxFromLeft+width, posyFrombottom+height), (posxFromLeft, posyFrombottom+height) ] GL.glTranslatef(float(posxFromLeft), float(posyFrombottom), 0) self.drawSticker(lLabelbounds) GL.glEnable(GL.GL_DEPTH_TEST) GL.glEnable(GL.GL_LIGHTING); GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPopMatrix() return 1 def setFontColor(self, color): """ """ self.Set(fontColor=color) def setFrameColor(self, color): """ """ self.Set(frameColor=color) def respondToDoubleClick(self, event): """ """ self.showOwnGui() def createOwnGui(self): #print "GlfLabels.createOwnGui", self self.ownGui = Tkinter.Toplevel() self.ownGui.title(self.name) self.ownGui.protocol('WM_DELETE_WINDOW', self.ownGui.withdraw ) frame1 = Tkinter.Frame(self.ownGui) frame1.pack(side='top') # label self.ownGui.labelEnt = Pmw.EntryField( frame1, label_text='label', labelpos='w', value=str(self.label), command=self.setWithOwnGui) self.ownGui.labelEnt.pack(side='top', fill='x') # fontName self.ownGui.guiFontNameComboBox = Pmw.ComboBox( frame1, label_text='font name', labelpos='w', entryfield_value=self.fontName, scrolledlist_items=self.glfVectorFontList, selectioncommand=self.setWithOwnGui ) self.ownGui.guiFontNameComboBox.pack(side='top', fill='x') # wirefont self.ownGui.wireFontVar = Tkinter.IntVar() self.ownGui.wireFontVar.set(self.wireFont) self.ownGui.guiWireFont = Tkinter.Checkbutton( frame1, text='wire font', variable=self.ownGui.wireFontVar, command=self.setWithOwnGui) self.ownGui.guiWireFont.pack(side='top', fill='x') # fontSpacing self.ownGui.guiFontSpacing = ThumbWheel( frame1, labCfg={'text':'font spacing', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=self.fontSpacing, callback=self.setWithOwnGui, continuous=True, oneTurn=1, wheelPad=2 ) self.ownGui.guiFontSpacing.pack(side='top', fill='x') # font global scale self.ownGui.guiGlobalScale = ThumbWheel( frame1, labCfg={'text':'global scale', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=1., callback=self.setWithOwnGui, continuous=True, oneTurn=5, wheelPad=2 ) self.ownGui.guiGlobalScale.pack(side='top', fill='x') # font scale X self.ownGui.guiFontScaleX = ThumbWheel( frame1, labCfg={'text':'font scale X', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=int, value=self.fontScales[0], callback=self.setWithOwnGui, continuous=True, oneTurn=20, wheelPad=2 ) self.ownGui.guiFontScaleX.pack(side='top', fill='x') # font scale Y self.ownGui.guiFontScaleY = ThumbWheel( frame1, labCfg={'text':'font scale Y', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=int, value=self.fontScales[1], callback=self.setWithOwnGui, continuous=True, oneTurn=20, wheelPad=2 ) self.ownGui.guiFontScaleY.pack(side='top', fill='x') self.ownGui.guiFramePolygonModeOptionMenu = Pmw.OptionMenu( frame1, label_text='frame PolygonMode', labelpos='w', initialitem=self.framePolygonModeDictRev[self.framePolygonMode], items=self.framePolygonModeDict.keys(), command=self.setWithOwnGui ) self.ownGui.guiFramePolygonModeOptionMenu.pack(side='top', fill='x') # frame space X self.ownGui.guiFrameSpaceX = ThumbWheel( frame1, labCfg={'text':'frame space X', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=self.frameSpace[0], callback=self.setWithOwnGui, continuous=True, oneTurn=5, wheelPad=2 ) self.ownGui.guiFrameSpaceX.pack(side='top', fill='x') # frame space Y self.ownGui.guiFrameSpaceY = ThumbWheel( frame1, labCfg={'text':'frame space Y', 'side':'left'}, showLabel=1, width=80, height=16, min=0, #max=100, type=float, value=self.frameSpace[1], callback=self.setWithOwnGui, continuous=True, oneTurn=5, wheelPad=2 ) self.ownGui.guiFrameSpaceY.pack(side='top', fill='x') # fontColor self.ownGui.guiColorChooser = ColorChooser( master=frame1, targetDict={'fontColor': (self.fontColor, 'RGB', self.setFontColor ), 'frameColor': (self.frameColor, 'RGB', self.setFrameColor ) }, targetKey='fontColor') def setWithOwnGui(self, event=None): """ """ #print "setWithOwnGui", event lGlobalScale = self.ownGui.guiGlobalScale.get() self.Set(label=self.ownGui.labelEnt.get(), fontName=self.ownGui.guiFontNameComboBox.get(), wireFont=self.ownGui.wireFontVar.get(), fontSpacing=self.ownGui.guiFontSpacing.get(), fontScales = ( lGlobalScale * self.ownGui.guiFontScaleX.get(), lGlobalScale * self.ownGui.guiFontScaleY.get()), framePolygonMode=self.framePolygonModeDict[self.ownGui.guiFramePolygonModeOptionMenu.getcurselection()], frameSpace = ( self.ownGui.guiFrameSpaceX.get(), self.ownGui.guiFrameSpaceY.get()), updateOwnGui=False) def updateOwnGui(self): self.ownGui.title(self.name) self.ownGui.labelEnt.setvalue(self.label) self.ownGui.guiFontNameComboBox.selectitem(self.font) self.ownGui.wireFontVar.set(self.wireFont) self.ownGui.guiFontSpacing.set(self.fontSpacing, update=0) self.ownGui.guiGlobalScale.set(1., update=0) self.ownGui.guiFontScaleX.set(self.fontScales[0], update=0) self.ownGui.guiFontScaleY.set(self.fontScales[1], update=0) self.ownGui.guiFramePolygonModeOptionMenu.selectitem(self.framePolygonModeDictRev[self.framePolygonMode]) self.ownGui.guiFrameSpaceX.set(self.frameSpace[0], update=0) self.ownGui.guiFrameSpaceY.set(self.frameSpace[1], update=0) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/geomTree.py0000644000175000017500000000603311466133635022020 0ustar debiandebianimport Tkinter from mglutil.gui.BasicWidgets.Tk.trees.tree import IconsManager from mglutil.gui.BasicWidgets.Tk.trees.TreeWithButtons import \ ColumnDescriptor ,TreeWithButtons, NodeWithButtons from DejaVu.Geom import Geom from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.Polylines import Polylines from DejaVu.Spheres import Spheres from DejaVu.Cylinders import Cylinders from DejaVu.glfLabels import GlfLabels class DejaVuGeomTreeWithButtons(TreeWithButtons): """ Class to display a tree for DejaVu geoemtry. """ def __init__(self, master, root, iconsManager=None, idleRedraw=True, nodeHeight=18, headerHeight=30, treeWidth=150, **kw): # add a compound selector entry kw['iconsManager'] = iconsManager kw['idleRedraw'] = idleRedraw kw['nodeHeight'] = nodeHeight kw['headerHeight'] = headerHeight kw['treeWidth'] = treeWidth TreeWithButtons.__init__( *(self, master, root), **kw ) canvas = self.canvas class DejaVuGeomNode(NodeWithButtons): """ The first level of this tree is either a molecule or a container. The second level are geoemtry object. Columns are used to modify geoms """ def getChildren(self): """ return children for object associated with this node. By default we return object.children. Override this method to selectively show children """ return self.children def getIcon(self): """ return node's icons for DejaVu geometry objects """ iconsManager = self.tree().iconsManager object = self.object if isinstance(object, IndexedPolygons): icon = iconsManager.get("mesh16.png", self.tree().master) elif isinstance(object, IndexedPolylines) or \ isinstance(object, Polylines): icon = iconsManager.get("lines16.png", self.tree().master) elif isinstance(object, Spheres): icon = iconsManager.get("spheres16.png", self.tree().master) elif isinstance(object, Cylinders): icon = iconsManager.get("cyl16.png", self.tree().master) elif isinstance(object, GlfLabels): icon = iconsManager.get("labels16.png", self.tree().master) else: # isinstance(object, Geom): icon = iconsManager.get("geom16.png", self.tree().master) if icon: self.iconWidth = icon.width() else: self.iconWidth = 0 return icon if __name__ == '__main__': root = Tkinter.Toplevel() vi = self.GUI.VIEWER iconsManager = IconsManager(['Icons'], 'DejaVu') rootnode = DejaVuGeomNode(vi.rootObject, None) tree = DejaVuGeomTreeWithButtons(root, rootnode, self, nodeHeight=18, iconsManager=iconsManager, headerHeight=0, treeWidth=180, selectionMode='multiple') tree.pack(side='bottom', expand=1, fill='both') rootnode.expand() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/videoRecorder.py0000644000175000017500000004731111107373762023050 0ustar debiandebianimport Tkinter import Pmw import os import weakref from mglutil.gui.InputForm.Tk.gui import InputFormDescr,InputForm,evalString from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from mglutil.util.packageFilePath import findFilePath import tkMessageBox import tkFileDialog from SimpleDialog import SimpleDialog from os import path class Recorder(Tkinter.Frame): """Implements GUI for recording movie clips( *.mpg)""" def __init__(self, master=None, height=80,width=100, title="Video recorder", icondir= None, filetypes=[("MPG", ".mpg")], fileName = None, camera = None, gui = True): self.ifd = None self.form = None self.paramForm = None self.ifd2 = None self.fileName = fileName self.autoPauseDelay = 1 # auto pause after 1 second self.pauseLength = 30 self.cameraw = 0 self.camerah = 0 self.camera = weakref.ref(camera) if self.camera(): self.cameraw = camera.width self.camerah = camera.height if not icondir: icondir = findFilePath('icons', 'mglutil.gui.BasicWidgets.Tk') self.stopIcon = Tkinter.PhotoImage(file=os.path.join(icondir, "stop3.gif"), master=master) self.pauseIcon = Tkinter.PhotoImage(file=os.path.join(icondir, "stop2.gif"), master=master) self.recordIcon = Tkinter.PhotoImage(file=os.path.join(icondir, "record.gif"), master=master) self.record1Icon = Tkinter.PhotoImage(file=os.path.join(icondir, "record1.gif"), master=master) self.chmodIcon = Tkinter.PhotoImage(file=os.path.join(icondir, 'chmod.gif'), master=master) self.closeIcon = Tkinter.PhotoImage(file=os.path.join(icondir, 'close.gif'), master=master) self.fileTypes = filetypes if gui: self.RecVar = Tkinter.IntVar() self.RecVar.set(0) self.PauseVar = Tkinter.IntVar() self.PauseVar.set(0) form = self.buildForm(master=master, title=title,height=height, width=width) form.deiconify() def buildForm(self, master=None, width=100, height=80, title=None): if self.form: self.form.deiconify() self.createKeyBindings() return self.master = master ifd = self.ifd = InputFormDescr(title=title) ifd.append({'name':'fileopen', 'widgetType':Tkinter.Button, 'tooltip': "Opens file browser", 'wcfg':{'text':"Save As:", 'command': self.browseFile, 'width': 0, 'height': 0,}, 'gridcfg':{'sticky':'w', 'column':0} }) ifd.append({'name':'filename', 'widgetType':Pmw.EntryField, 'tooltip': "type filename", 'gridcfg':{'sticky':'w', #'columnspan': 3}, 'columnspan': 2, 'row': -1}, 'wcfg':{'command':self.getFileName, #'label_text':'Save As', 'entry_width':12, 'value':self.fileName, #'labelpos':'w'}}) }}) ## ifd.append({'name':'fileopen', ## 'widgetType':Tkinter.Button, ## 'tooltip': "Open file browser", ## 'wcfg':{'text':"...", ## 'command': self.browseFile, ## 'width': 0, 'height': 0,}, ## 'gridcfg':{'sticky':'w', 'column':2, 'row':-1} ## }) ifd.append({'name': 'recordB', 'widgetType': Tkinter.Checkbutton, 'tooltip':'start/stop recording', 'wcfg': {'variable': self.RecVar, 'bd':2, 'image':self.record1Icon, 'width':self.record1Icon.width(), 'height':self.record1Icon.height(), 'indicatoron':0, }, 'gridcfg':{'sticky':'nesw','row':-1}, 'command':self.record_cb }) ifd.append({'name': 'pauseB', 'widgetType': Tkinter.Checkbutton, 'tooltip':'pause/start recording', 'wcfg':{'variable': self.PauseVar, 'bd':2, 'image':self.pauseIcon, 'width':self.pauseIcon.width(), 'height':self.pauseIcon.height(), 'indicatoron':0, }, 'gridcfg':{'sticky':'nesw', 'row':-1}, 'command':self.pause_cb }) ifd.append({'name': 'stopB', 'widgetType': Tkinter.Button, 'tooltip':'stop recording', 'wcfg':{'bd':2, 'image':self.stopIcon, 'width':self.stopIcon.width(), 'height':self.stopIcon.height(), }, 'gridcfg':{'sticky':'nesw', 'row':-1}, 'command':self.stop_cb }) ## ifd.append({'name': 'recordB', ## 'widgetType': Tkinter.Button, ## 'tooltip':'start/pause recording', ## 'wcfg':{'bd':4, ## 'image':self.recordIcon, ## 'width':self.recordIcon.width(), ## 'height':self.recordIcon.height() ## }, ## 'gridcfg':{'sticky':'nesw','row':-1}, ## 'command':self.record_cb}) ## ifd.append({'name': 'pauseB', ## 'widgetType': Tkinter.Button, ## 'tooltip':'pause recording', ## 'wcfg':{'bd':4, ## 'image':self.pauseIcon, ## 'width':self.pauseIcon.width(), ## 'height':self.pauseIcon.height() ## }, ## 'gridcfg':{'sticky':'nesw', 'row':-1}, ## 'command':self.pause_cb}) ## ifd.append({'name': 'modeB', ## 'widgetType': Tkinter.Button, ## 'text':'Change Mode', ## 'tooltip':'opens panel to change video parameters', ## 'wcfg':{'bd':4, ## 'image':self.chmodIcon, ## 'width':self.chmodIcon.width(), ## 'height':self.chmodIcon.height() ## }, ## 'gridcfg':{'sticky':'nesw','row':-1}, ## 'command':self.setparams_cb }) ## ifd.append({'name': 'closeB', ## 'widgetType': Tkinter.Button, ## 'text':'Close', ## 'tooltip':'closes video recorder', ## 'wcfg':{'bd':2, ## 'image':self.closeIcon, ## 'width':self.closeIcon.width(), ## 'height':self.closeIcon.height(), ## }, ## 'gridcfg':{'sticky':'nesw','row':-1}, ## 'command':self.close_cb}) form = self.form = InputForm(self.master, None, descr = ifd, modal = 0, blocking = 0, closeWithWindow=1, onDestroy = self.close_cb) self.createKeyBindings() return form def getFileName(self): """ Get file name from the input form's entry field.""" if self.ifd: name = self.ifd.entryByName['filename']['widget'].get() if name: if self.fileName != name: self.fileName = name def browseFile(self): """Opens file browser.""" fileDir = None if self.fileName: if path.exists(self.fileName): fileDir = path.dirname(path.realpath(self.fileName)) else: fileDir = os.getcwd() file = tkFileDialog.asksaveasfilename( filetypes=self.fileTypes, initialdir=fileDir, initialfile=None, title="Save file") if file: if self.fileName != file: self.fileName = file self.ifd.entryByName['filename']['widget'].setentry(file) def record_cb(self): #get the value of the Record checkbutton val = self.RecVar.get() if val: #checked self.getFileName() res = 1 if self.camera: if self.camera().videoRecordingStatus == "stopped": #kw = {'filename':self.fileName, 'width':self.cameraw, 'hight':self.camerah, # 'autoPauseDelay': self.autoPauseDelay,'pauseLength':self.pauseLength} #kw = {'filename':self.fileName } #apply(self.setVideoParams, (), kw) if os.path.exists(self.fileName): # ask the user if he wants to overwrite the existing file from Dialog import Dialog d = Dialog(None, {'title': 'File exisits', 'text': 'File "%s" already exists.' ' Do you want to overwrite it ?'%self.fileName, 'bitmap': 'warning', 'default': 1, 'strings': ('Yes', 'No')}) ans = d.num if ans == 1: #no self.RecVar.set(0) return res = self.setVideoParams(filename = self.fileName) if res: #print "record_cb: recording" self.camera().start() if self.ifd: b = self.ifd.entryByName['recordB']['widget'] if res: b.config(image=self.recordIcon) pauseval = self.PauseVar.get() if pauseval: self.PauseVar.set(0) #uncheck the Pause checkbutton else: #unchecked if self.camera: #print "record_cb: stop recording" self.stop_cb() def stop_cb (self): #print "stop_cb" if self.camera: if not self.camera().videoRecordingStatus == 'stopped': #print "stop recording" self.camera().stop() if self.ifd: recval = self.RecVar.get() if recval: self.RecVar.set(0) #uncheck the Record checkbutton pauseval = self.PauseVar.get() if pauseval: self.PauseVar.set(0) #uncheck the Pause checkbutton b = self.ifd.entryByName['recordB']['widget'] b.config(image=self.record1Icon) def pause_cb(self): #print "pause_cb" val = self.PauseVar.get() if self.camera: camerastatus = self.camera().videoRecordingStatus if val: # the Pause button is checked if camerastatus == 'recording': #print "pause recording" self.camera().pause() #if self.ifd: #b = self.ifd.entryByName['recordB']['widget'] #b.config(command = self.record_cb, image=self.recordIcon) else: # the Pause button is unchecked if camerastatus == 'paused': #print "start recording after pause" self.record_cb() def spacePress_cb(self, event): if self.camera: camerastatus = self.camera().videoRecordingStatus if camerastatus == "stopped" or camerastatus == "paused": self.RecVar.set(1) self.record_cb() elif camerastatus == "recording": self.PauseVar.set(1) self.pause_cb() def setparams_cb(self): """Opens a panel to set Video Parameters""" if self.paramForm: self.paramForm.deiconify() return self.ifd2 = ifd2 = InputFormDescr(title = "Set video options") ifd2.append({'widgetType':Pmw.EntryField, 'tooltip': 'Set camera width', 'name':'cameraw', 'gridcfg':{'sticky':'w', 'columnspan':2}, 'wcfg':{#'command': self.setCameraWidth_cb, 'label_text':'width:', 'entry_width':10, 'validate': {'validator':'real', 'min': 0}, 'value':str(self.cameraw), 'labelpos':'w'}}) ifd2.append({'widgetType':Pmw.EntryField, 'name':'camerah', 'tooltip':'Set camera height', 'gridcfg':{'sticky':'w' , 'columnspan':2}, 'wcfg':{#'command': self.setCameraHeight_cb, 'label_text':'height', 'entry_width':10, 'validate': {'validator':'real', 'min': 0}, 'value':str(self.camerah), 'labelpos':'w'}}) ifd2.append({'name': 'autoPause', 'wtype':ThumbWheel, 'widgetType':ThumbWheel, 'tooltip':'set auto pause delay (seconds)', 'wcfg':{'labCfg':{'fg':'black', 'side':'left', 'text':'AutoPause Delay'}, 'showLabel':1, 'width':100, 'min':0, 'value':self.autoPauseDelay, 'oneTurn':100, 'type':'int', 'increment':1, #'callback':self.setAutoPauseDelay_cb, 'canvascfg':{'bg':'red'}, 'continuous':0, 'wheelPad':1, 'height':15}, 'gridcfg':{'sticky':'nesw', 'columnspan':2}}) ifd2.append({'name': 'pauseLength', 'wtype':ThumbWheel, 'widgetType':ThumbWheel, 'tooltip':'set number of frames to be added when\nrecording resumes after autopause', 'wcfg':{'labCfg':{'fg':'black', 'side':'left', 'text':'AutoPause Length'}, 'showLabel':1, 'width':100, 'min':0, 'value':self.pauseLength, 'oneTurn':100, 'type':'int', 'increment':1, #'callback':self.setPauseLength_cb, 'canvascfg':{'bg':'red'}, 'continuous':0, 'wheelPad':1, 'height':15}, 'gridcfg':{'sticky':'nesw','columnspan':2}}) ifd2.append({'name':'okB', 'widgetType': Tkinter.Button, 'wcfg':{'text': 'Apply', 'command': self.apply_cb,}, 'gridcfg':{'sticky':'nesw'}}) ifd2.append({'name':'cancelB', 'widgetType': Tkinter.Button, 'wcfg':{'text': 'Cancel', 'command': self.cancel_cb,}, 'gridcfg':{'sticky':'nesw', 'row':-1, 'column':1}}) self.paramForm = InputForm(self.master, None, descr = ifd2, modal = 0, blocking = 0) self.paramForm.deiconify() return self.paramForm def setCameraWidth_cb(self): """ 'Width' entry field callback of the video parameters form .""" w = int(self.ifd2.entryByName['cameraw']['widget'].get()) if w != self.cameraw: self.cameraw = w def setCameraHeight_cb(self): """'Height' entry field callback of the video parameters form .""" h = int(self.ifd2.entryByName['camerah']['widget'].get()) if h != self.camerah: self.camerah = h def setAutoPauseDelay_cb(self, val): """Callback of the autoPause thumbwheel widget (video parameters input form). """ #print val d = int(val) if d != self.autoPauseDelay: self.autoPauseDelay = d def setPauseLength_cb(self, val): """Callback of the pauseLength thumbwheel widget (video parameters input form). """ #print val l = int(val) if l != self.pauseLength: self.pauseLength = l def apply_cb(self): """Apply button callback of the video parameters input form.""" kw = {} ebn = self.ifd2.entryByName w = float(ebn['cameraw']['widget'].get()) if w != self.cameraw: self.cameraw = w kw ['width']= w h = float(ebn['camerah']['widget'].get()) if h != self.camerah: self.camerah = h kw['height']=h d = ebn['autoPause']['widget'].get() if d != self.autoPauseDelay: self.autoPauseDelay = d kw["autoPauseDelay"]=d l = ebn['pauseLength']['widget'].get() if l != self.pauseLength: self.pauseLength = l kw['pauseLength']=l #apply(self.setVideoParams, (), kw) self.cancel_cb() def setVideoParams(self, **kw): """ Uses Recordable Camera methods to set file name and other video parameters""" #print kw if self.camera: filename = kw.get('filename') if filename: try: self.camera().setVideoOutputFile(filename) except IOError: button = tkMessageBox.showerror("IOError", message="Could not open file %s\nfor writing a movie."%filename, parent = self.master) return False ## params = {} ## w = kw.get('width') ## if w is not None: ## params['width'] = w ## h = kw.get('height') ## if h is not None: ## params['height']= h ## pl = kw.get('pauseLength') ## if pl is not None: ## params['pauseLength'] = pl ## apd = kw.get('autoPauseDelay') ## if apd is not None: ## params['autoPauseDelay'] = apd ## if len(params): ## apply(self.camera().setVideoParameters, (), params) #use default parameters for now self.camera().setVideoParameters() return True def createKeyBindings(self): self.master.bind('', self.spacePress_cb) def removeKeyBindings(self): self.master.unbind('') def cancel_cb(self): self.paramForm.withdraw() def close_cb(self, event=None): if hasattr(self,'form'): self.form.withdraw() self.removeKeyBindings() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/testcsg3.py0000644000175000017500000002051210651433502021775 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by #pmv -i -d ms 1crn.pdb #execfile('testcsg3.py') #pmv -i -m ms 1crn.pdb cv.pdb blurcv1crn_net.py #pmv -i -m cpk 1crn.pdb cv.pdb #pmv -i -m ms 1crn.pdb cv.pdb #execfile('testcsg1.py') #execfile('testcsg2.py') ## TODO ## try using IndexedGeomDSPL to build self.dpyListCSG ## OpenCSGGeom.clearPrimitives leaks memory ## make PythonPrimitive::render() handle the Python global lock ## add support for instanceMatrices from OpenCSG import opencsglib as OpenCSG import numpy.oldnumeric as Numeric ## from DejaVu.Spheres import Spheres class DejaVuPrimitive(OpenCSG.PythonPrimitive): def __init__(self, geom): apply( OpenCSG.PythonPrimitive.__init__, (self, self.render, OpenCSG.Intersection, 0)) # does not work for some reason #OpenCSG.PythonPrimitive(self.render, OpenCSG.Intersection, 1) self.geom = geom self.dpyListCSG = None def redoDisplayListCSG(self): if self.dpyListCSG is not None: GL.glDeleteLists(1, self.dpyListCSG) g = self.geom self.dpyListCSG = GL.glGenLists(1) GL.glNewList(self.dpyListCSG, GL.GL_COMPILE) ## if isinstance(g, Spheres): ## g.DisplayFunction() ## else: self.drawpolygons() GL.glEndList() def drawpolygons(self): g = self.geom vertices = g.getVertices() faces = g.getFaces() normals = g.getFNormals() GL.glDisable(GL.GL_CULL_FACE) for i,f in enumerate(faces): GL.glBegin(GL.GL_POLYGON) GL.glNormal3fv(normals[i]) for vi in f: GL.glVertex3fv(vertices[vi]) GL.glEnd() i+=1 def render(self, mode='render'): # call with mode='csg' to render simple shape to setup Zbuffer for CSG # call with mode='render' to render by calling geom's draw function if self.geom: #import traceback #print traceback.print_stack() #print self.geom #print "=========================================================" root = self.geom.viewer.rootObject instance = [0] p = self.geom.parent while p: instance.append(0) p = p.parent #mat = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') #print 'mat OK', mat GL.glPushMatrix() GL.glLoadIdentity() self.geom.viewer.currentCamera.BuildTransformation() self.geom.BuildMat(self.geom, root, True, instance) #mat = Numeric.array(GL.glGetDoublev(GL.GL_MODELVIEW_MATRIX)).astype('f') #print 'mat PB', mat #print 'render ', mode, self.geom if mode=='csg': if self.dpyListCSG is None: self.redoDisplayListCSG() GL.glCallList(self.dpyListCSG) elif mode=='render': obj = self.geom if not obj.inheritMaterial: obj.InitMaterial(0) obj.InitColor(0) obj.DisplayFunction() GL.glPopMatrix() from DejaVu.Geom import Geom from opengltk.OpenGL import GL from DejaVu.viewerFns import checkKeywords class OpenCSGGeom(Geom): keywords = Geom.keywords + [ 'primitives', 'algo', 'depthalgo', ] def __init__(self, name=None, check=1, **kw): if __debug__: if check: apply( checkKeywords, (name,self.keywords), kw) apply( Geom.__init__, (self, name, 0), kw ) self.primitives = OpenCSG.PrimitiveVector() # C++ primitives self.pyprimitives = [] # python subclasses used to call python implementation or render self.algo = OpenCSG.Goldfeather self.depthalgo = OpenCSG.DepthComplexitySampling self.Set(culling='none', algo=OpenCSG.Goldfeather, depthalgo=OpenCSG.DepthComplexitySampling) def clearPrimitives(self): ## for p in self.pyprimitives: ## if p.dpyListCSG: ## print 'AAAAAAAAAAAAAAA', p.geom ## print 'AAAAAAAAAAAAAAA', p.dpyListCSG, p.geom.dpyList ## GL.glDeleteLists(1, p.dpyListCSG ) ## p.dpyListCSG = None self.primitives.clear() self.pyprimitives = [] def setPrimitives(self, *args): self.clearPrimitives() for g in args: assert isinstance(g, Geom) prim = DejaVuPrimitive(g) #self.primitives.append(prim) OpenCSG.PrimitiveVector_add(self.primitives, prim) self.pyprimitives.append(prim) def Set(self, check=1, redo=1, **kw): """Set primitives""" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) apply( Geom.Set, (self, 0, 0), kw) p = kw.get( 'primitives') if p: assert isinstance(p, OpenCSG.PythonPrimitiveVector) self.primitives = p a = kw.get( 'algo') if a: if a =='automatic': a = OpenCSG.Automatic elif a== 'goldfeather': a = OpenCSG.Goldfeather elif a == 'scs': a = OpenCSG.SCS assert a in (OpenCSG.Automatic, OpenCSG.Goldfeather, OpenCSG.SCS) self.algo = a d = kw.get( 'depthalgo') if d: if d =='DepthComplexitySampling': d = OpenCSG.DepthComplexitySampling elif d== 'NoDepthComplexitySampling': d = OpenCSG.NoDepthComplexitySampling elif d == 'OcclusionQuery': d = OpenCSG.OcclusionQuery assert d in (OpenCSG.DepthComplexitySampling, OpenCSG.NoDepthComplexitySampling, OpenCSG.OcclusionQuery) self.depthalgo = d def Draw(self): GL.glEnable(GL.GL_DEPTH_TEST); GL.glClear( GL.GL_STENCIL_BUFFER_BIT) GL.glDisable(GL.GL_FOG) #GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL) OpenCSG.render(self.primitives, self.algo, self.depthalgo) GL.glDepthFunc(GL.GL_EQUAL) # FIXME should only enable fog if it is on in camera GL.glEnable(GL.GL_FOG) self.SetupGL() for p in self.pyprimitives: p.render() GL.glDepthFunc(GL.GL_LESS); o=0 a = 20 vertices = [ (o, o, o), (o, a, o), (a, a, o), (a, o, o), (o, o, a), (o, a, a), (a, a, a), (a, o, a) ] facesInward = [ (3,2,1,0), (7,6,2,3), (5,6,7,4), (0,1,5,4), (2,6,5,1), (4,7,3,0)] facesOutward = [ (0,1,2,3), (3,2,6,7), (4,7,6,5), (4,5,1,0), (1,5,6,2), (0,3,7,4)] faces = facesOutward normals = [(0,0,1), (-1,0,0), (0,0,-1), (1,0,0), (0,-1,0), (0,1,0)] from DejaVu.IndexedPolygons import IndexedPolygons clipBox = IndexedPolygons('clipBox', vertices=vertices, faces=faces, fnormals=normals, frontPolyMode='line', shading='flat') self.readMolecule('/home/annao/python/dev23/1crn.pdb', ask=0, parser=None, log=0) #self.readMolecule('/home/annao/python/dev23/cv.pdb', ask=0, parser=None, log=0) self.browseCommands('msmsCommands', commands=None, log=0, package='Pmv') #self.computeMSMS("1crn;cv", 'MSMS-MOL', perMol=1, density=4.6, log=0, pRadius=1.5) self.computeMSMS("1crn", 'MSMS-MOL', perMol=1, density=4.6, log=0, pRadius=1.5) srf1 = self.Mols[0].geomContainer.geoms['MSMS-MOL'] #srf2 = self.Mols[1].geomContainer.geoms['MSMS-MOL'] cpk1 = self.Mols[0].geomContainer.geoms['cpk'] #cpk2 = self.Mols[1].geomContainer.geoms['cpk'] self.colorByResidueType("1crn;cv", ['MSMS-MOL'], log=0) #self.displayMSMS("1crn;cv", negate=True, only=False, surfName=['MSMS-MOL'], log=0, nbVert=1) #self.displayCPK("1crn;cv", cpkRad=0.0, scaleFactor=1.0, only=False, negate=False, quality=17) #self.showMolecules(['cv'], negate=True, log=0) #self.colorByAtomType("1crn;cv", ['cpk'], log=0) srf1.Set(frontPolyMode='line', visible=False) #srf2.Set(frontPolyMode='line') err = OpenCSG.glewInit() print "glewInit status: ", err g = OpenCSGGeom('inter') g.setPrimitives(srf1, clipBox) #g.setPrimitives(srf1, srf2) #g.setPrimitives(cpk1, clipBox) g.Set(immediateRendering=True, lighting=True) self.GUI.VIEWER.AddObject(clipBox) self.GUI.VIEWER.AddObject(g) #g.primitives[1].setOperation(OpenCSG.Subtraction) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Box.py0000644000175000017500000003707111250013737020776 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Ruth HUEY, Michel SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Box.py,v 1.36 2009/09/03 19:24:15 annao Exp $ # # $Id: Box.py,v 1.36 2009/09/03 19:24:15 annao Exp $ # import numpy.oldnumeric as Numeric from opengltk.OpenGL import GL from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.Geom import Geom from DejaVu.IndexedGeom import IndexedGeom import datamodel import viewerConst from DejaVu.viewerFns import checkKeywords def uniq(objectSequence): """ returns a list with no duplicates""" d = {} for o in objectSequence: d[id(o)] = o return d.values() class CallBackFunction: """Class to allow to specify arguments to a callback function""" def __init__(self, function, *args, **kw): self.function = function self.args = args self.kw = kw def __call__(self, *args, **kw): args = self.args + args kw.update(self.kw) return apply(self.function, args, kw) class Box(IndexedPolygons): """3-D Polygon with 8 vertices. Box has attributes center and xside, yside, zside. if vertices are supplied, vertices[2] + vertices[4] are used to define xside, yside, zside + center In addition to a set of vertices, a Box can be defined by setting any of these combinations: center + side center + xside, yside, zside origin + side (origin is 'smallest' valued point of vertices) origin + xside, yside, zside origin + center two cornerPoints where cornerPoints are ordered: center - halfsides, center + halfsides Precedence among these possible parameters is defined as follows: side < [x,y,z]side < center < origin < cornerPoints < vertices """ keywords = IndexedPolygons.keywords + [ 'maxCube', 'minCube', 'vertices', 'side', 'xside', 'yside', 'zside', 'center', 'origin', 'cornerPoints', ] def __init__(self, name=None, check=1, **kw): self.maxCube = None self.minCube = None if not kw.get('origin') \ and not kw.get('center') \ and not kw.get('cornerPoints') \ and not kw.get('minCube'): kw['origin'] = (0, 0, 0) #set up some defaults: materials = kw.get('materials') #print 'in BOX materials kw=', materials if not materials: kw['materials'] = ((0,0,1),(0,1,0),(0,0,1),(0,1,0),(1,0,0),(1,0,0),) #print 'in BOX after test for materials, kwmaterials=', kw['materials'] vertices = kw.get('vertices') if vertices is not None: assert len(vertices)==8 pt1 = Numeric.array(vertices[2]) pt2 = Numeric.array(vertices[4]) self.center = tuple(Numeric.multiply(Numeric.add(pt1,pt2), 0.5)) self.xside, self.yside, self.zside = \ Numeric.subtract(pt2,pt1) else: #set up center center = kw.get('center') #if not center: center = (0.,0.,0.) self.center = center #set up sides side = kw.get('side') if side: self.xside = side self.yside = side self.zside = side else: xside = kw.get('xside') if not xside: xside = 1.0 self.xside = xside yside = kw.get('yside') if not yside: yside = 1.0 self.yside = yside zside = kw.get('zside') if not zside: zside = 1.0 self.zside = zside #NB faces shouldn't change self.faces=((0,3,2,1), (3,7,6,2), (7,4,5,6), (0,1,5,4), (1,2,6,5), (0,4,7,3)) self.funcs = {} fkeys = ['center', 'origin', 'centerOrigin', 'xside', \ 'yside', 'zside','maxCube', 'minCube'] fs = [self.getVertsFromCenter, self.getVertsFromOrigin, \ self.getVertsFromCenterOrigin, CallBackFunction(self.getVertsFromSide, 'xside'), CallBackFunction(self.getVertsFromSide, 'yside'), CallBackFunction(self.getVertsFromSide, 'zside'), self.setMaxCube, self.setMinCube] for i in range(len(fkeys)): self.funcs[fkeys[i]] = fs[i] self.pickableVertices = 1 kw['frontPolyMode'] = 'line' apply( IndexedPolygons.__init__, (self, name, check), kw ) self.inheritMaterial = 0 #print 'calling self.Set with ', kw.get('materials') #apply(self.Set,(), kw) # register functions to compute normals self.VertexNormalFunction(self.ComputeVertexNormals) self.vertexSet.normals.ComputeMode( viewerConst.AUTO ) self.FaceNormalFunction(self.ComputeFaceNormals) self.faceSet.normals.ComputeMode( viewerConst.AUTO ) self._PrimitiveType() self.GetNormals() self.oldFPM = GL.GL_LINE def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object: Set polygon's vertices, faces, normals or materials check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = 0 #newKeyList is list of keys specified in call to Set newKeyList = kw.keys() # Setting both center AND origin is a special case # which sets all side lengths centerOrigin = 0 if 'center' in newKeyList and 'origin' in newKeyList: centerOrigin = 1 side= kw.get( 'side') if side: kw['xside'] = side kw['yside'] = side kw['zside'] = side newKeyList.extend(['xside','yside', 'zside']) newKeyList = uniq(newKeyList) apply(self.updateVal, (['xside','yside','zside'],),kw) #these are either 1 or None self.maxCube = kw.get('maxCube') self.minCube = kw.get('minCube') if self.minCube and self.maxCube: self.center = [ (self.minCube[0] + self.maxCube[0]) * .5 , (self.minCube[1] + self.maxCube[1]) * .5 , (self.minCube[2] + self.maxCube[2]) * .5 ] # kl used to implement this precedence: # side < [x,y,z]side < center < origin < cornerPoints < vertices # vertices are dealt with last cornerPoints = None kl = ['xside', 'yside', 'zside','minCube', 'maxCube', 'center', 'origin'] for key in kl: if key in newKeyList: newVal = kw.get(key) if not newVal: continue if key in ['center','origin'] and centerOrigin: self.center = kw.get('center') newVal = kw.get('origin') newKeyList.remove('center') newKeyList.remove('origin') f = self.funcs['centerOrigin'] else: del kw[key] f = self.funcs[key] cornerPoints = apply(f, (newVal,),{}) #if cornerPoints are specified, they override other info newcornerPoints = kw.get('cornerPoints') if newcornerPoints: cornerPoints = newcornerPoints if cornerPoints: ptList = self.getVertsFromCornerPts(cornerPoints) else: ptList = None #vertices overrides everything: set center+sides newVertices = kw.get('vertices') if newVertices is not None: assert len(newVertices)==8 pt1 = Numeric.array(newVertices[2]) pt2 = Numeric.array(newVertices[4]) self.center = tuple(Numeric.multiply(Numeric.add(pt1,pt2), 0.5)) self.xside, self.yside, self.zside = \ Numeric.subtract(pt2,pt1) redoFlags |= self._redoFlags['redoDisplayListFlag'] elif ptList: assert len(ptList)==8 kw['vertices'] = ptList redoFlags |= self._redoFlags['redoDisplayListFlag'] if kw.get('faces') is None: kw['faces'] = self.faces redoFlags |= apply( IndexedPolygons.Set, (self, check, 0), kw ) return self.redoNow(redo, updateOwnGui, redoFlags) def updateVal(self, keyList, **kw): for item in keyList: itemVal = kw.get(item) if itemVal: setattr(self, item, itemVal) #exec('self.'+item+'='+str(itemVal)) def setMaxCube(self, val): side = max(self.xside, self.yside, self.zside) self.xside = side self.yside = side self.zside = side return self.getVertsFromCenter(self.center) def setMinCube(self, val): side = min(self.xside, self.yside, self.zside) self.xside = side self.yside = side self.zside = side return self.getVertsFromCenter(self.center) def getVertsFromSide(self, sideStr, value): setattr(self, sideStr, value) #exec('self.'+sideStr+'=' + str(value)) return self.getVertsFromCenter(self.center) def getVertsFromCenterOrigin(self, origin): #in this case, the origin is pt0 x0,y0,z0 = origin x1,y1,z1 = self.center self.xside = x0 + 2*(x1-x0) self.yside = y0 + 2*(y1-y0) self.zside = z0 + 2*(z1-z0) pt1 = (self.xside, self.yside, self.zside) return (origin, pt1) def halfPt(self, pt): return Numeric.multiply(pt, 0.5) def getVertsFromOrigin(self, origin): #set new center here, also side = Numeric.array((self.xside, self.yside, self.zside)) self.center = tuple(Numeric.add(origin, Numeric.multiply(side, 0.5))) pt1=tuple(Numeric.add(origin, side)) return (origin, pt1) def getVertsFromCenter(self, center): self.center = center halfSide = Numeric.multiply(Numeric.array((self.xside, self.yside, self.zside)), 0.5) pt1=tuple(Numeric.add(center,halfSide)) pt0=tuple(Numeric.subtract(center,halfSide)) return (pt0, pt1) def getVertsFromCornerPts(self, cornerPoints): # cornerPoints = (center-halfsides, center+halfsides) # cornerPoints = (pt0, pt1) x1,y1,z1=cornerPoints[1] x0,y0,z0=cornerPoints[0] self.xside = x1-x0 self.yside = y1-y0 self.zside = z1-z0 center = (x1-(x1-x0)/2., y1-(y1-y0)/2., z1-(z1-z0)/2.) self.center = center # maxCube sets box to cube with side = largest of x,y,z-side # min sets box to cube with side = smallest of x,y,z-side # maxCube has precedence over minCube if self.maxCube or self.minCube: if self.maxCube: side = max((x1-x0,y1-y0,z1-z0)) elif self.minCube: side = min((x1-x0,y1-y0,z1-z0)) self.xside = side self.yside = side self.zside = side pt1=tuple(Numeric.add(center,(side/2.,side/2,side/2))) pt0=tuple(Numeric.subtract(center,(side/2,side/2,side/2))) x1,y1,z1 = pt1 x0,y0,z0 = pt0 #built list of 8 pts ptList=((x1,y1,z0), (x0,y1,z0), (x0,y0,z0), (x1,y0,z0), (x1,y1,z1), (x0,y1,z1), (x0,y0,z1), (x1,y0,z1)) return ptList def DisplayFunction(self): if self.frontPolyMode != self.oldFPM: self.RedoDisplayList() IndexedPolygons.DisplayFunction(self) def Draw(self): #print"Box.Draw" self.oldFPM = self.frontPolyMode if self.frontPolyMode == GL.GL_LINE: GL.glDisable(GL.GL_LIGHTING) #c is 8x3 array c= self.vertexSet.vertices.array #lines parallel to x-axis should be red, y->blue and z->green col = ((1,0,0),(0,1,0),(0,0,1)) #these groups of 4 pairs of points define lines parallel to x, y, and z axes alines=[[(c[0],c[1]),(c[2],c[3]),(c[4],c[5]),(c[6],c[7])], [(c[0],c[3]),(c[1],c[2]),(c[4],c[7]),(c[5],c[6])], [(c[0],c[4]),(c[1],c[5]),(c[3],c[7]),(c[2],c[6])]] namectr=0 for i in range(3): if not self.inheritMaterial: GL.glColor3fv(col[i]) for vpairs in alines[i]: GL.glPushName(namectr) GL.glBegin(GL.GL_LINES) GL.glVertex3dv(list(vpairs[0])) GL.glVertex3dv(list(vpairs[1])) GL.glEnd() GL.glPopName() namectr=namectr+1 self.viewer.enableOpenglLighting() return 1 else: return IndexedPolygons.Draw(self) class GridBox(Box): """ Specialized Box whose dimensions are controlled by spacing and npts in a grid. A GridBox has additional attributes xspacing, yspacing, zspacing and xnpts,ynpts and znpts. """ keywords = Box.keywords + [ 'npts', 'xnpts', 'ynpts', 'znpts', 'spacing', 'xspacing', 'yspacing', 'zspacing' ] def __init__(self, name=None, check=1, **kw): npts = kw.get('npts') if not npts: xnpts = kw.get('xnpts') if not xnpts: kw['xnpts'] = 40 ynpts = kw.get('ynpts') if not ynpts: kw['ynpts'] = 40 znpts = kw.get('znpts') if not ynpts: kw['znpts'] = 40 spacing = kw.get('spacing') if not spacing: spacing = (.375,.375,.375) kw['spacing'] = (.375, .375, .375) apply( Box.__init__, (self, name, check), kw ) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = apply( Box.Set, (self, check, 0), kw) #newKeyList is list of keys specified in call to Set newKeyList = kw.keys() npts= kw.get('npts') if npts: kw['xnpts'] = npts kw['ynpts'] = npts kw['znpts'] = npts newKeyList.extend(['xnpts','ynpts', 'znpts']) spacing = kw.get('spacing') if spacing: assert len(spacing)==3 kw['xspacing'] = spacing[0] kw['yspacing'] = spacing[1] kw['zspacing'] = spacing[2] newKeyList.extend(['xspacing','yspacing', 'zspacing']) newKeyList = uniq(newKeyList) #update all 6 attributes apply(self.updateVal, (['xnpts','ynpts','znpts', 'xspacing',\ 'yspacing', 'zspacing'],),kw) if 'xnpts' in newKeyList or 'xspacing' in newKeyList: kw['xside'] = self.xnpts*self.xspacing if 'ynpts' in newKeyList or 'yspacing' in newKeyList: kw['yside'] = self.ynpts*self.yspacing if 'znpts' in newKeyList or 'zspacing' in newKeyList: kw['zside'] = self.znpts*self.zspacing return self.redoNow(redo, updateOwnGui, redoFlags) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/cursors.py0000644000175000017500000000530711450205643021744 0ustar debiandebian############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2010 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/cursors.py,v 1.8 2010/09/27 21:24:51 sanner Exp $ # # $Id: cursors.py,v 1.8 2010/09/27 21:24:51 sanner Exp $ # import sys, os ## define cursors cursorsDict = { 'default':'', 'busy':'watch', 'None':'pirate', 'default':'', 'addToSelection':'', 'removeFromSelection':'', 'rotation':'exchange', 'XYtranslation':'fleur', 'Ztranslation':'double_arrow', 'scale':'', 'zoom':'sizing', 'pivotOnPixel':'cross_reverse', 'picking':'dotbox' # '':'', } import DejaVu cpath = os.path.join(DejaVu.__path__[0], 'Cursors') if sys.platform=='linux2': cursorsDict['addToSelection'] = ( '@'+os.path.join(cpath, 'AddSel.xbm'), os.path.join(cpath, 'AddSelMask.xbm'), 'black', 'white') cursorsDict['removeFromSelection'] = ( '@'+os.path.join(cpath, 'MinusSel.xbm'), os.path.join(cpath, 'MinusSelMask.xbm'), 'black', 'white') cursorsDict['Ztranslation'] = ( '@'+os.path.join(cpath, 'Ztrans.xbm'), os.path.join(cpath, 'ZtransMask.xbm'), 'black', 'white') elif os.name == 'nt': pass ## cursorsDict['None']='@'+os.path.join(cpath, 'NoAction.cur') ## cursorsDict['addToSelection']='@'+os.path.join(cpath, 'AddSel.cur') ## cursorsDict['removeFromSelection']='@'+os.path.join(cpath, ## 'MinusSel.cur') ## cursorsDict['XYtranslation']='@'+os.path.join(cpath, 'XYtrans.cur') ## cursorsDict['Ztranslation']='@'+os.path.join(cpath, 'Ztrans.cur') elif sys.platform=='darwin': cursorsDict['addToSelection'] = ( '@'+os.path.join(cpath, 'AddSel.xbm'), os.path.join(cpath, 'AddSelMask.xbm'), 'black', 'white') cursorsDict['removeFromSelection'] = ( '@'+os.path.join(cpath, 'MinusSel.xbm'), os.path.join(cpath, 'MinusSelMask.xbm'), 'black', 'white') cursorsDict['Ztranslation'] = ( '@'+os.path.join(cpath, 'Ztrans.xbm'), os.path.join(cpath, 'ZtransMask.xbm'), 'black', 'white') ## cursorsDict['None']='@'+os.path.join(cpath, 'NoAction.cur') ## cursorsDict['addToSelection']='@'+os.path.join(cpath, 'AddSel.cur') ## cursorsDict['removeFromSelection']='@'+os.path.join(cpath, ## 'MinusSel.cur') ## cursorsDict['XYtranslation']='@'+os.path.join(cpath, 'XYtrans.cur') ## cursorsDict['Ztranslation']='@'+os.path.join(cpath, 'Ztrans.cur') mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/rotationMatrices.py0000644000175000017500000000166610651433502023576 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # collection of standard 4x4 rotation matrices # about the X, Y and Z axis of 10, 30, 45, 90, 180 degrees # rotations = { } import math, numpy.oldnumeric as Numeric from mglutil.math.rotax import rotax orig = Numeric.array( (0,0,0), 'f') X = Numeric.array( (1,0,0), 'f') Y = Numeric.array( (0,1,0), 'f') Z = Numeric.array( (0,0,1), 'f') for angle in [1, 5, 10, 30, 45, 90, 180]: rotations['X'+str(angle)] = rotax( orig, X, angle*math.pi/180.) rotations['X-'+str(angle)] = rotax( orig, X, -angle*math.pi/180.) for angle in [1, 5, 10, 30, 45, 90, 180]: rotations['Y'+str(angle)] = rotax( orig, Y, angle*math.pi/180.) rotations['Y-'+str(angle)] = rotax( orig, Y, -angle*math.pi/180.) for angle in [1, 5, 10, 30, 45, 90, 180]: rotations['Z'+str(angle)] = rotax( orig, Z, angle*math.pi/180.) rotations['Z-'+str(angle)] = rotax( orig, Z, -angle*math.pi/180.) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/povray3.py0000644000175000017500000004413411156524662021660 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/povray3.py,v 1.10 2009/03/13 18:45:06 vareille Exp $ # # $Id: povray3.py,v 1.10 2009/03/13 18:45:06 vareille Exp $ # """ Povray module: driver to generate PovRay scenes form a DejaVu scene The driver currently handles: camera parameters (background color, perpective parameters, position), light sources, and Spheres, IndexedPolygons and IndexedPolylines geometries. The projection is still somewhat approximative ! still a 10 translation that is not explained :(. """ from opengltk.OpenGL import GL #from opengltk.extent.utillib import glTriangleNormals from geomutils.geomalgorithms import TriangleNormals from DejaVu import viewerConst import numpy.oldnumeric as Numeric class PovRay: """Driver for Povray v3.x """ def __init__(self, includes = []): """Create a PovRay file generator class for a given camera""" self.camera = None self.entries = [""" // // Povray scene file written by Pmv version 0.1 // // POV-Ray can be retrieved at: http://www.povray.org // N.Guex, 1995-1999 // """] for i in includes: self.entries.append('#include "%s"\n'%i) def write(self, filename): """void <- write(filename) dumps povray scene description""" self.filename = filename f = open(filename, 'w') for entry in self.entries: f.write(entry) f.close() def clear(self): """void <- clear() empties povray scene description""" self.entries = [] def coord3(self, x, y=None, z=None): """string <- coord3(x, y=None, z=None) returns a povray vector string this function inverts the z coordinates. It can be called with a sequence of 3 or with 3 values. """ if y is None: return ' <%f, %f, %f> '% (x[0],x[1],-x[2]) else: return ' <%f, %f, %f> '% (x, y, -z) def vec3(self, x, y=None, z=None): """string <- vec3(x, y=None, z=None) returns a povray vector string this function does not invert the z coordinates. It can be called with a sequence of 3 or with 3 values. """ if y is None: return ' <%.2f, %.2f, %.2f> '% (x[0],x[1],x[2]) else: return ' <%.2f, %.2f, %.2f> '% (x, y, z) def vec4(self, x, y=None, z=None, t=None): """string <- vec4(x, y=None, z=None, t=None) returns a povray 4-vector this function does not invert the z coordinates. It can be called with a sequence of 3 and a y-value or with 4 values. """ if z is None: return ' <%.2f, %.2f, %.2f, %.2f> '% (x[0],x[1],x[2],y) else: return ' <%.2f, %.2f, %.2f, %.2f> '% (x, y, z, t) def matrix(self, mat): """string <- matrix(mat) returns a 4x4 matrix as a povray matrix""" str = 'matrix < %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f >\n' % ( mat[0][0], mat[0][1], mat[0][2], mat[1][0], mat[1][1], mat[1][2], mat[2][0], mat[2][1], mat[2][2], mat[0][3], mat[1][3], mat[2][3] ) return str def addCamera(self, camera, scaleLight=2.0): """void <- addCamera(camera) adds the given camera to the povray scene handles: camera background color projection matrix (only perspective currently light sources """ # doesn't handle camera transformation yet str = 'background { color rgb ' + self.vec3(camera.backgroundColor) str = str + '}\n\n' self.entries.append( str ) str = 'camera { perspective' # I can't remember why I have to move 10 more than direction vector # but it seems familiar str = str + '\n location' + self.coord3(camera.lookFrom[0], camera.lookFrom[1], camera.lookFrom[2]+10) str = str + '\n look_at' + self.coord3(camera.lookAt) str = str + '\n angle %f'% ( camera.fovy+10.0, ) str = str + '\n up <0,1,0> // required for 1/1 aspect ratio p 277' str = str + '\n right <%d/%d,0,0>'%(camera.width,camera.height) str = str + '\n}\n\n' self.entries.append( str ) for l in camera.viewer.lights: if l.enabled: self.addLight(l, scaleLight) def addLight(self, light, scale=2.0): """void <- addLight(light) add a light source to the povray scene """ # doesn't handle light transformation yet d = light.direction str = 'light_source {' + self.coord3(d[0], d[1], d[2]) # str = str + 'color rgb' + self.vec3(light.diffuse) + '}\n\n' str = str + 'color rgb ' + self.vec3(scale*light.diffuse[0], scale*light.diffuse[1], scale*light.diffuse[2]) str += 'parallel ' str = str + '}\n\n' self.entries.append( str ) def addTexture(self, texture, col): """void <- addTexture(texture, col) Add texture to an object. texture is a dictionnary of texture properties, col is used as pigment is pimgment is not in textures """ str = ' texture {\n' if not 'pigment' in texture.keys(): str = str + ' pigment { color rgb %s }\n' %self.vec3( col ) elif texture['pigment']=='': str = str + ' pigment { color rgb %s }\n' %self.vec3( col ) else: str = str + ' pigment { %s }\n' % texture['pigment'] for k,v in texture.items(): if k=='pigment': continue if v is None: str = str + ' %s\n' % (k,) else: str = str + ' %s { %s }\n' % (k,v) str = str + ' }\n' self.entries.append( str ) def endShape(self): self.entries.append( '}\n' ); def addGeoms(self, geometries, texture = {'finish':'specular 1 roughness 0.001 ambient 0.3'}, bondRad = 0.15): """void <- addGeoms(geometries, texture) adds a list of geometries to the povray scene only visible geometries are added """ for g in geometries: if g.visible and len(g.vertexSet): self.entries.append('// geometry %s\n//\n'%g.name) self.addGeom(g, texture, bondRad) def addGeom(self, geom, texture = {'finish':'specular 1 roughness 0.001 ambient 0.3'}, bondRad = 0.15): """void <- addGeom(geometry, texture) adds a geometries to the povray scene Spheres, IndexedPolygons and IndexedPolylines are handled """ from DejaVu.Spheres import Spheres from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.Cylinders import Cylinders if isinstance(geom, Spheres): self.entries.append('// Object %s\n//\n' % geom.name) self.addSpheres(geom, texture) elif isinstance(geom, IndexedPolygons) and len(geom.faceSet): self.entries.append('// Object %s\n//\n' % geom.name) self.addIndexedPolgygons(geom, texture) elif isinstance(geom, IndexedPolylines) and len(geom.faceSet): self.entries.append('// Object %s\n//\n' % geom.name) self.addIndexedPolylines(geom, texture, bondRad) elif isinstance(geom, Cylinders) and len(geom.faceSet): self.entries.append('// Object %s\n//\n' % geom.name) self.addCylinders(geom, texture) else: print 'WARNING: %s the geometry is not yet supported'%geom.__class__ def addIndexedPolylines(self, geom, texture, bondRad): """void <- addIndexedPolylines(geom, texture) """ mat = geom.GetMatrix() v = geom.vertexSet.vertices*mat c = geom.materials[GL.GL_FRONT].prop[1] lines = geom.faceSet.faces.array for i in xrange(len(v)): if len(c)==len(v): col = c[i] else: col = c[0] self.entries.append('sphere{%s,%f\n' % (self.coord3(v[i]), bondRad) ) self.addTexture( texture, col ) self.endShape() for j in xrange(len(lines)): l = lines[j] if len(c) == len(v): col1 = c[l[0]] col2 = c[l[1]] else: col1 = col2 = c[0] if Numeric.sum(col1-col2) < 0.0001: p2 = v[l[1]] oneCyl = 1 else: p2 = (v[l[1]]+v[l[0]])/2. oneCyl = 0 self.entries.append('cylinder{%s,%s, %f open\n' % \ (self.coord3(v[l[0]]), self.coord3(p2), bondRad) ) self.addTexture( texture, col1 ) self.endShape() if not oneCyl: self.entries.append('cylinder{%s, %s, %f open\n' % \ (self.coord3(p2), self.coord3(v[l[1]]), bondRad)) self.addTexture( texture, col2 ) self.endShape() def addIndexedPolgygons(self, geom, texture): """void <- addIndexedPolgygons(geom, texture) """ mat = geom.GetMatrix() vt = geom.vertexSet.vertices*mat # FIXME need to add instance # FIXME need to handle flat shading # add vertices lines = ["mesh2 {\n\tvertex_vectors {\n\t\t%d,\n"%len(vt)] for v in vt: lines.append("\t\t%s,\n"%self.coord3(v)) lines.append("\t}\n") # add normals normals = geom.getVNormals() lines.append("\tnormal_vectors {\n\t\t%d,\n"%len(normals)) for n in normals: lines.append("\t\t%s,\n"%(self.coord3(n))) lines.append("\t}\n") # handle colors colors = geom.materials[GL.GL_FRONT].prop[1] colBinding = 'Overall' faces = geom.getFaces() if len(colors)==len(vt): colBinding = 'Per Vertex' elif len(colors)==len(faces): colBinding = 'Per Face' print len(colors), len(faces), len(vt), colBinding if colBinding!='Overall': lines.append("\ttexture_list {\n\t\t%d,\n"%len(colors)) for c in colors: lines.append( "\t\ttexture { pigment { color rgb<%6.3f, %6.3f, %6.3f> }\n"% tuple(c[:3])) lines.append("\t\t\tfinish { specular 1 roughness 0.001 ambient 0.3 } }\n") lines.append("\t}\n") # add faces lines.append("\tface_indices {\n\t\t%d,\n"%len(faces)) faceNumberLine = len(lines)-1 nbfaces = 0 if colBinding=='Overall': for t in faces: for ti in range(len(t)-2): lines.append("\t\t<%d,%d,%d>\n"%(t[0], t[ti+1], t[ti+2])) nbfaces += 1 elif colBinding=='Per Face': for fn,t in enumerate(faces): for ti in range(len(t)-2): lines.append("\t\t<%d,%d,%d>,%d\n"%( t[0], t[ti+1], t[ti+2], fn)) nbfaces += 1 elif colBinding=='Per Vertex': for t in faces: for ti in range(len(t)-2): lines.append("\t\t<%d,%d,%d>,%d,%d,%d\n"%( t[0], t[ti+1], t[ti+2], t[0], t[ti+1], t[ti+2])) nbfaces += 1 lines.append("\t}\n") lines[faceNumberLine] = "\tface_indices {\n\t\t%d,\n"%nbfaces if colBinding=='Overall': lines.append("\tpigment { color rgb<%6.3f, %6.3f, %6.3f> }\n"% tuple(colors[0][:3])) lines.append("\t\tfinish { specular 1 roughness 0.001 ambient 0.3 }\n") lines.append("}\n") self.entries.extend(lines) ## mat = geom.GetMatrix() ## v = geom.vertexSet.vertices*mat ## #v = geom.vertexSet.vertices.array ## c = geom.materials[GL.GL_FRONT].prop[1] ## n = geom.normals ## tri = geom.faceSet.faces.array ## fn = TriangleNormals( v, tri, 'PER_FACE') ## colBinding = 0 #Overall ## if not color: ## if len(c)==len(v): colBinding = 1 # Per Vertex ## elif len(c)==len(tri): colBinding = 2 # Per Face ## else: ## col = c[0] # Overall ## else: ## col = color ## vnorm = n ## for j in xrange(len(tri)): ## t = tri[j] ## if len(tri)==len(n): ## # per face normal ## pass ## # tri to fix the normals of singular vertices ## # if dot(vertex normal, face normal) < 0 negate vertex normal ## ## vnorm = [0,0,0] ## ## for i in (0,1,2): ## ## norm = n[t[0]] ## ## dot = norm[0]*fn[j][0] + norm[1]*fn[j][1] + norm[2]*fn[j][2] ## ## if dot < 0.0: ## ## vnorm[i] = 0.0 - norm ## ## else: ## ## vnorm[i] = norm ## if not color: ## if colBinding==1: ## col = (c[t[0]] + c[t[1]] + c[t[2]])*0.33333333 ## elif colBinding==2: ## col = c[j] ## self.entries.append('smooth_triangle{\n') ## self.entries.append(' %s,%s\n'% (self.coord3(v[t[0]]), ## self.coord3(vnorm[t[0]])) ) ## self.entries.append(' %s,%s\n'% (self.coord3(v[t[1]]), ## self.coord3(vnorm[t[1]])) ) ## self.entries.append(' %s,%s\n'% (self.coord3(v[t[2]]), ## self.coord3(vnorm[t[2]])) ) ## self.addTexture( texture, col ) ## self.endShape() ## if len(t)==4: ## self.entries.append('smooth_triangle{\n') ## self.entries.append(' %s,%s\n'% (self.coord3(v[t[0]]), ## self.coord3(vnorm[t[0]])) ) ## self.entries.append(' %s,%s\n'% (self.coord3(v[t[2]]), ## self.coord3(vnorm[t[2]])) ) ## self.entries.append(' %s,%s\n'% (self.coord3(v[t[3]]), ## self.coord3(vnorm[t[3]])) ) ## self.addTexture( texture, col ) ## self.endShape() def addSpheres(self, geom, texture): """void <- addSpheres(geom, texture) """ mat = geom.GetMatrix() v = geom.vertexSet.vertices*mat #v = geom.vertexSet.vertices.array c = geom.materials[1028].prop[1] if geom.oneRadius == viewerConst.NO: radii = geom.vertexSet.radii.array if geom.inheritMaterial: fp = None # FIXME bp = None else: fp = geom.materials[GL.GL_FRONT] if not geom.frontAndBack: bp = geom.materials[GL.GL_BACK] face = GL.GL_FRONT else: bp = None face = GL.GL_FRONT_AND_BACK self.entries.append('#declare unitSphere = sphere { <0.00, 0.00, 0.00> , 1 }\n\n') for i in range(len(geom.vertexSet)): self.entries.append('object { unitSphere\n') if not geom.oneRadius: self.entries.append(' scale %f\n'%(radii[i][0]/2.) ) else: self.entries.append(' scale %f\n'%geom.radius ) self.entries.append(' translate %s\n'%self.coord3(v[i]) ) if fp: col = fp.prop[1][i][:3] else: col = (1.,1.,1.) self.addTexture( texture, col ) self.endShape() def addCylinders(self, geom, texture): """void <- addSpheres(geom, texture) """ mat = geom.GetMatrix() v = geom.vertexSet.vertices*mat #v = geom.vertexSet.vertices.array c = geom.materials[1028].prop[1] radii = geom.vertexSet.radii.array if geom.inheritMaterial: fp = None # FIXME bp = None else: fp = geom.materials[GL.GL_FRONT] if not geom.frontAndBack: bp = geom.materials[GL.GL_BACK] face = GL.GL_FRONT else: bp = None face = GL.GL_FRONT_AND_BACK f = geom.getFaces() for i in range(len(geom.faceSet)): for j in range(len(f[i])-1): self.entries.append('cone { \n') if not geom.oneRadius: r1 = radii[f[i][j]]/2. r2 = radii[f[i][j+1]]/2. else: r1 = r2 = radii[0]/2. self.entries.append('\t%s, %f, %s, %f\n'%( self.coord3(v[f[i][j]]), r1, self.coord3(v[f[i][j+1]]), r2)) if fp: col = c[f[i][j]][:3] else: col = (1.,1.,1.) self.entries.append("\tpigment { color rgb<%6.3f, %6.3f, %6.3f> }\n"% tuple(col)) self.entries.append("\tfinish { specular 1 roughness 0.001 ambient 0.3 }\n") self.endShape() if __name__ == '__main__': from DejaVu import Viewer vi = Viewer() from DejaVu.Spheres import Spheres s = Spheres('test', centers = ( (0.0, 0., 0.), (3.,0.,0.) ) ) s.Set(quality = 4) vi .AddObject(s) from DejaVu.povray3 import PovRay p = PovRay() p.addCamera(vi.cameras[0]) p.addLight(vi.lights[0]) p.addGeom(s) p.write('test.pov') mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/0000755000175000017500000000000012146207756020752 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/spheres16.png0000644000175000017500000000144211466133702023272 0ustar debiandebianPNG  IHDRa pHYs  tIME 1 vIDAT8˭kU̙9܏764tW)h%HPpj\HMA nA\D ZE1i{Lܙ9gƅ1 uW,~>/}.,)~0jSQ#\<G۽~>{xj&s7˥1xLLj~XCUUgy8޿re7a0wx<6}(imaT#t__[=Z:?7ufxJQQaLh;//(,XTkF>QꯔƖH$eTPkĠ{092u5뢔R U@ʵxF!H'cc^,$I%*!w$*TYZ8XGyQ`Zk-bvwk &KLn"ت,z"Id&\k,)d{{zb:FJKi"Eh'aT+^>RIGRHJ[b2aBݧ]cmwW<~ы\}(O.~ёw~}e&֤:en3\ɵC]x鿞⥷Ϸ )yRyzVJGh))nzJ7Ο';. QIENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/spheres.png0000644000175000017500000000304611466133702023125 0ustar debiandebianPNG  IHDRw= pHYs  tIME !*RIDATHDžk]Gد뾒SI Q4R&J* E#/KEJ0⇀T-ږK)&JU4Vmhso{=}{$BhaYkZ[p1u]BϽpj_a󥫗ykGx!n*\|WW$5/@k1Ik܉oKn~?zd~ l3~XG9.Zi,)$8|ݻ~S^V"\?^ GqozffM 㡔B1EIdQg?svה}O}ز\FE-l{Z1Pd9y8h_[KM5{`y[҃_9}6l5Mhu V.RJX,<#]J)_Nz{vlg#9)Zkx^hq\ BiR`- V 6ز8u8I?ئVB ]\S(T5U,X+("ϫf$iN&թMn}Ǧ^o;븾ҠB*rM*SWYFIBVu/woa O-Zo2 `@4#qD<Y2 "K"xDq4 .8xhz]ߗJhpjEEUMU%k4%KѐѰOڛ$M7R|ѩ}^pk5=@QȰ<˪ i3{].Rf=x{\eO~cʫ?)̬PkN4Z8(R"%MGģ>+f>}Gv[6ǎϗn \RIGJ\ܾm~9׮bm|7;_:_陙{#}jow><wXQIENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/cyl16.png0000644000175000017500000000115511466133702022411 0ustar debiandebianPNG  IHDRa pHYs  tIME 3 IDAT8˭=kTAs~n$J?R!@KM%ڊ`XYؤBPPB Wݻ3sJa`{޶ۭ8N3s὇ /h--ټv@Po޼<9~\ 9^dK;?\7sKFP PZNLZ>n`0aRF eHX/ oY/VQAb|Cj #!gU ;up TF&Zb@TaANc`I89 "dYER1 !Y U1#$s?a k4 &hiIBP瑏b^oj}U@qDᜃsn;MҴ034̥ bBG/Qq6*&7Y6Ik ^Ag͆쯦~wQ^[LpS҅(âX/wW_:_ -IENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/labels16.png0000644000175000017500000000134611466133702023066 0ustar debiandebianPNG  IHDRa pHYs  tIME 2.wIDAT8˭MkTg993DH$QKPK#HRB ,]tEʅҥPAP0-Q7RWm⻙d3y;os?uWg7w(Ր"_Pշ w@?@C 4AٯOrN%>y$%oIdjzi${v,m;Ud֣[9[|JrgҤ} ^\ΓX*P$8LJ?>se@}ZWIǺTl&pm?r9n>Fcٿ;xȾnf\oÕ%&\Ũh7~TgFycۚt1>uCbCqfKcn;NIENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/mesh16.png0000644000175000017500000000127511466133702022561 0ustar debiandebianPNG  IHDRa pHYs  tIME 5\IDAT8In`7xi(G@b;66܂A`BB$%b;q<ſQ!! ѷyO}Ϋ .˗vmn?<ϕ CW8) \|#f>b0H8 JIJt8uzOa>jݺyל~[თilw6W\.4Q5(X{zO>A /ZjOϳu;Nj~\ѱ#8='iYY^P 53RfHf }[o5e=sT ]WUMff\|?C&Y0P{=#MZ@c(A4Qض(J ij cN8n?'ppМvBTX\R(eF^Wն0&1jUƲC`RPT*E yRdI`Ci'B,v!EYDzAFu@U~N)dC:C0T ]EfZ +2uGC STuq(Ȳ۞:vӤ0FCZ0U0&Mra JUBӤS*bpHIENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/labels.png0000644000175000017500000000272011466133702022714 0ustar debiandebianPNG  IHDRw= pHYs  tIME 'ioIDATHǕ]U;s̙ɴ?b7ĄD䂨1;&^b1Є5!"BPLK3ЙvΜ3kyŌ o/zz\>jdр" ȣUJY W4@2| J[~lHg6GT3T:IJ R[C|1OI.|Z]¬OXU_;*.TSLsd`٧˲sf{ `4&S8xƎXcW00|J6>JvbU-CEg^' uCPʙ=;n^x4Oe\^bn6YοĊf-kC S\zճOܗeWV@Pϰ[c qX!EXFUUFK/sqG%W/?-"D!ZP!f|0'WJ@Tf`SHHѹ"z,m-<~.'F@fb:PD!Ԝ3">6]LB vzڍ=ef'HP&N#߰6NRۻK4"x$H1UPAM;r ), PE3N@_tqQ)ܖ;v/O.-wFRF0Wg jԣLAI(PP$CDpt<~0n; dL|V 'ȚWu$!= Hb@-zֱw‹`b9Em,mpբjdU,/^Q5LdfZ d_bz7O?u o|6;隣aމP"xrO3{.U콣(JDDž1F8>0s܅ӫyy7p9kf1"} F߅T FHNQ՟dtSr%R?y;ۭ_V>{M9ECD5x*9H"  k͌lV^oNb#LQVBT G7o.&z׫u}QyyJf%#-Xt{/L}jjC?Yp?wmo[e?RٲXUfs_ņnj͝zwŃĖ'yV~(ޱ$IENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/cyl.png0000644000175000017500000000225211466133702022241 0ustar debiandebianPNG  IHDRw= pHYs  tIME %_IIDATHǍOUƿ٘d6bFAs ^rP@PT <( D h@BԍaC캳fv3;=ݯΌɃ^U}hBWv%M9Fݹq~q0 aEHLsk߉sgV|'_:|֯E_|FG6!D"k-%T3t"޵eo\s^c{~xdJklamdfd.Q 9Y&Q_|}gcS]1a5 ຑ@!DAB<ЃUMn#&@ X V(JlVy6pр(`J@8#%t^_X(Q$X/B:P@ !vNŁ uPQ]RK!P1TU_t$TTͥe,.4x!(BnD(B`BBSvBU{V.g}E)luaUB0,,!s. "`fXka,u4 k4𬅊@UD1lhwE!}?@Юj{] |@@0!c_핬Aavv<]h).sHI I>k-|߇Gdgz2Hnj E%n'R%@4qMdoDxۛ0w-LЎXN+IE9DQc TAUo<A$I`:ҒJ%axqv`Qe3,BBr~tfe̟|s{M>`sspN>\D7}X=yO/_tMU"<Ǹ01qO?[ ȑ'~YMG Hg]``:=ovdFf$'KolXGX 쯇?D5V]ԍuNWlH6( P$ JjbKiIvޛq{.k&7眜_#|YH~7+dgtu+yJ=5Y E:wS__w-ls<Ȼu5k > p?W.?ï_,,˙VC=U⾔d2!f?yǵi PpEn M-(r؎IΜ#o*heXyYUCTW'hlN$J0 # (݃O- P& \}wI%,̽eMdvv] ۲HGPr~LŻ:;{"a i~5\4&ka[_݂ Qy'):kxL&3v*])QVv{TM $j#+._SKMm3WX_NQxcX' lhhhA P<@A%\"TQIj-31vU-TpXOOW$ 9%>..qP|P.Lc;&?($=-yh$xx%OK,<嶶'jK}^ \/ʍ1ʶ[C;v|Y{s%~OOW__h@q\[{pO2V-IENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/geom16.png0000644000175000017500000000141311466133702022546 0ustar debiandebianPNG  IHDRa pHYs  tIME 9IDAT8˭;oU;ݝ}ڎIpbad)BHCPI砣 t)P E $*@ 9e>f̝ǝ{)"VJ8ৣs?FS$u:0Y[,Oݽݻ;e$[Q 8G^f8%YAoU](4*T/zG^ܽnx"" qCXKg<=b6gZo? GG_h x~Le*P8$³'Fŕl:P`s5UY3EU8pe!Nx9?x V tR$i.bpRSidHcqQ$Yr1?g/8Zm7iu3R)qk_8-2mD{VF?ٍ;מE(c|)A ;*n6} UDڡԜ:tn)UTV4c輠(5*)tI]&E@{.Z_X،lo6*T9Lujruqap^;z7NFO&TƠd~I n_q[gy]Nq7f+`8l%Is4:`wL-%WoopusO6h6ᛎ#UR IENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/lines16.png0000644000175000017500000000141311466133702022731 0ustar debiandebianPNG  IHDRa pHYs  tIME 9#|IDAT8˭;oU;ݝ}ڎIpbad)BHCPI砣 t)P E $*@ 9e>f̝ǝ{)"VJ8ৣs?FS$u:0Y[,Oݽݻ;e$[Q 8G^f8%YAoU](4*T/zG^ܽnx"" qCXKg<=b6gZo? GG_h x~Le*P8$³'Fŕl:P`s5UY3EU8pe!Nx9?x V tR$i.bpRSidHcqQ$Yr1?g/8Zm7iu3R)qk_8-2mD{VF?ٍ;מE(c|)A ;*n6} UDڡԜ:tn)UTV4c輠(5*)tI]&E@{.Z_X،lo6*T9Lujruqap^;z7NFO&TƠd~I n_q[gy]Nq7f+`8l%Is4:`wL-%WoopusO6h6ᛎ#UR IENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/mesh.png0000644000175000017500000000303211466133702022403 0ustar debiandebianPNG  IHDRw= pHYs  tIME - Y\wIDATHՖk?3;;ޝ}JZkW"ɲdI~ǐ7Ph)M-- 9CnH''; -+WZvGҾ$vf@ ]`a7RN=LO\V,{E`z4FcC'?>Y۩_Ng} >˸nޥ_Qf_ {^4N2++Wx}",+ffv_W7d9rxګoF"@IJlUe}9%Z!?R"[}[[yQ^Q4\-$3slmUN^.ho\xՌǓ㻻ۛGC] bZ)ÃK$.\8c}A =3[}NuSA'믿Day}|!CI+b[6o}W^y6k-D14 >}‹/\[[O'4-͛!; oAP.^;H!"%ݻP,T29}tzLOK4GGݾIēq\A%²18"ϑQ/!S(IgXKXYYL8C0XZ^'[ڤiHWa.biTU!85`\uhP"ƻݣ=$|_yoU[^Ddl{ƈz]Fvۤd\e=sQ"Y¡,Mp,j ύpvi;A($R9::fm}zT*$)L&I#e p)i*'#\!La # RA uqZMGQ .mR,ȪQp\@^KOl&}IQ"8G.fmm>&J( 錌B<IpnuqL4U0i+؎ IW=:2jVɓ|T&y]oy#$vI  (RHDDPsQB_! 3X֐Zm<8 ~D:a8G0 T* 9{R*c)\Gb'4pqaaEnwy4GU>xL`vLm[!lf!c鲺oЉ cj:E1CRa1^N` <,HQo$) J4MfgjJllL쳓 qu+bKYᅧ,GFIENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/lines.png0000644000175000017500000000212611466133702022564 0ustar debiandebianPNG  IHDRw= pHYs  tIME -|rIDATHǵMlTUy3tSmB I "0L"X>D5V]ԍuNWlH6( P$ JjbKiIvޛq{.k&7眜_#|YH~7+dgtu+yJ=5Y E:wS__w-ls<Ȼu5k > p?W.?ï_,,˙VC=U⾔d2!f?yǵi PpEn M-(r؎IΜ#o*heXyYUCTW'hlN$J0 # (݃O- P& \}wI%,̽eMdvv] ۲HGPr~LŻ:;{"a i~5\4&ka[_݂ Qy'):kxL&3v*])QVv{TM $j#+._SKMm3WX_NQxcX' lhhhA P<@A%\"TQIj-31vU-TpXOOW$ 9%>..qP|P.Lc;&?($=-yh$xx%OK,<嶶'jK}^ \/ʍ1ʶ[C;v|Y{s%~OOW__h@q\[{pO2V-IENDB`mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Icons/__init__.py0000644000175000017500000000000011466133702023042 0ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Insert2d.py0000644000175000017500000002734711253755024021752 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: Febuary 2006 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # # Revision: # ######################################################################### # # $Header$ # # $Id$ # import numpy.oldnumeric as Numeric from copy import deepcopy from opengltk.OpenGL import GL from DejaVu.Common2d3dObject import Common2d3dObject class Insert2d(Common2d3dObject): """Base class for 2d inserts that can be displayed in a camera """ keywords = Common2d3dObject.keywords + [ 'transparent', 'anchor', 'position', 'size', ] def __init__(self, name='insert2d', check=1, **kw): #print "Insert2d.__init__" self.anchor = [1, 0] # or 0 - left/top; .5 - center; 1 - right/bottom self.position = [1, 0] # or 0 - left/top; .5 - center; 1 - right/bottom self.size = [40, 30] # in pixels self.polygonContour = None # the list of 2d points (pixels coordinates from bottom left) # that defines the 2d polygon drawned by Draw() self.lastPickEventTime = 0 self.isMoving = None # tells what is the current behavior # the legend can be move (True) or resize (False) or nothing (None) apply( Common2d3dObject.__init__, (self, name, check), kw) self.initialAnchor = deepcopy(self.anchor) self.initialPosition = deepcopy(self.position) self.initialSize = deepcopy(self.size) def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ #print "Insert2d.Set" redoFlags = apply( Common2d3dObject.Set, (self, check, 0), kw) val = kw.pop( 'transparent', None) if not val is None: redoFlags |= self._setTransparent(val) anchor = kw.get( 'anchor') if anchor \ and (anchor[0] >= 0.) and (anchor[0] <= 1.) \ and (anchor[1] >= 0.) and (anchor[1] <= 1.): self.anchor = anchor redoFlags |= self._redoFlags['redoDisplayListFlag'] position = kw.get( 'position') if position \ and (position[0] >= 0.) and (position[0] <= 1.) \ and (position[1] >= 0.) and (position[1] <= 1.): self.position = position redoFlags |= self._redoFlags['redoDisplayListFlag'] size = kw.get( 'size') if size \ and (size[0] >= 0.) \ and (size[1] >= 0.): self.size = size redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def _setTransparent(self, val): #print "_setTransparent", val assert val in (False, True) self.transparent = val return self._redoFlags['redoDisplayListFlag'] | self._redoFlags['redoViewerDisplayListFlag'] def getState(self, full=1): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ state = Common2d3dObject.getState(self).copy() state.update( { 'transparent':self.transparent, 'anchor': self.anchor, 'position': self.position, 'size': self.size, } ) return state def setViewer(self, viewer, buildDisplayList): # could be renamed as 'onViewerAddition' #print "Insert2d.setViewer" Common2d3dObject.setViewer(self, viewer, buildDisplayList) self.viewer.AddPickingCallback(self.processHit_cb) def getTile(self): #print "Insert2d.getTile" # compute projection parameters tr = self.viewer.tileRenderCtx Left = 0 Right = tr.TileWidth #tr.CurrentTileWidth Bottom = 0 Top = tr.TileHeight #tr.CurrentTileHeight left = Left + (Right - Left) \ * (tr.CurrentColumn * tr.TileWidthNB - tr.TileBorder) / float(tr.ImageWidth) right = left + (Right - Left) * tr.TileWidth / float(tr.ImageWidth) bottom = Bottom + (Top - Bottom) \ * (tr.CurrentRow * tr.TileHeightNB - tr.TileBorder) / float(tr.ImageHeight) top = bottom + (Top - Bottom) * tr.TileHeight / float(tr.ImageHeight) tile = (left, right, bottom, top) #print "tile", tile return tile def Draw(self): """set the projection matrices, the subclass must call this in their Draw func, otherwise tile rendering and stereo won't work """ #print "Insert2d.Draw" GL.glMatrixMode(GL.GL_PROJECTION) if self.viewer.tileRender: tile = self.getTile() GL.glOrtho(float(tile[0]), float(tile[1]), float(tile[2]), float(tile[3]), -1, 1) else: GL.glOrtho(0, float(self.viewer.currentCamera.width), 0, float(self.viewer.currentCamera.height), -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) def pickDraw(self): """called by the picking process to operate the selection """ #print "Insert2d.pickDraw", self if self.polygonContour is not None: # we draw just flat quad of the insert2d GL.glMatrixMode(GL.GL_PROJECTION) GL.glPushMatrix() #GL.glLoadIdentity() GL.glLoadMatrixf(self.viewer.currentCamera.pickMatrix) GL.glOrtho(0, float(self.viewer.currentCamera.width), 0, float(self.viewer.currentCamera.height), -1, 1) GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPushMatrix() GL.glLoadIdentity() GL.glPolygonMode(GL.GL_FRONT, GL.GL_FILL) GL.glPushName(0) GL.glBegin(GL.GL_QUADS) GL.glVertex2fv(self.polygonContour[0]) GL.glVertex2fv(self.polygonContour[1]) GL.glVertex2fv(self.polygonContour[2]) GL.glVertex2fv(self.polygonContour[3]) GL.glEnd() GL.glPopName() GL.glMatrixMode(GL.GL_PROJECTION) GL.glPopMatrix() GL.glMatrixMode(GL.GL_MODELVIEW) GL.glPopMatrix() def setSize(self, event, redo=1): """the trackball transmit the translation info """ self.size[0] = event.x - self.coord2d[0] self.size[1] = self.coord2d[1] - event.y if self.size[0] < 1: self.size[0] = 1 if self.size[1] < 1: self.size[1] = 1 if self.size[0] > self.viewer.currentCamera.width: self.size[0] = self.viewer.currentCamera.width if self.size[1] > self.viewer.currentCamera.height: self.size[1] = self.viewer.currentCamera.height if self.viewer: self.viewer.objectsNeedingRedo[self] = None def setPosition(self, event, redo=1): """the trackball transmit the translation info """ #print "Insert2d.setPosition", event.x, event.y self.position = [ event.x / float(self.viewer.currentCamera.width), event.y / float(self.viewer.currentCamera.height) ] if self.position[0] < 0: self.position[0] = 0 elif self.position[0] > 1: self.position[0] = 1 if self.position[1] < 0: self.position[1] = 0 elif self.position[1] > 1: self.position[1] = 1 self.viewer.objectsNeedingRedo[self] = None def calculateAnchorAndPosition(self, event): insert2dTopLeftFromScreenTopleft0 = self.position[0] * self.viewer.currentCamera.width \ - self.anchor[0] * self.size[0] insert2dTopLeftFromScreenTopleft1 = self.position[1] * self.viewer.currentCamera.height \ - self.anchor[1] * self.size[1] #print "insert2dTopLeftFromScreenTopleft", insert2dTopLeftFromScreenTopleft0, insert2dTopLeftFromScreenTopleft1 self.anchor = [ (event.x - insert2dTopLeftFromScreenTopleft0) / float(self.size[0]), (event.y - insert2dTopLeftFromScreenTopleft1) / float(self.size[1]) ] #print "self.anchor", self.anchor self.position = [ event.x / float(self.viewer.currentCamera.width), event.y / float(self.viewer.currentCamera.height) ] def ResetPosition(self): self.anchor = deepcopy(self.initialAnchor) self.position = deepcopy(self.initialPosition) if self.viewer: self.viewer.objectsNeedingRedo[self] = None def ResetSize(self): #print "ResetSize", self.initialSize self.size = deepcopy(self.initialSize) if self.viewer: self.viewer.objectsNeedingRedo[self] = None def ResetTransformation(self): """Reset the tranformations """ self.ResetPosition() self.ResetSize() def respondToMouseMove(self, event, redo=1): """the trackball transmit the event info """ if self.isMoving is not None: if self.isMoving is True: self.setPosition(event) else: self.setSize(event) self.viewer.Redraw() def respondToDoubleClick(self, event): """to be overidden """ pass def processHit_cb(self, pick): #print "Insert2d.processHit_cb", self, (self.viewer==None) #print "pick",pick #print "pick.event",dir(pick) #print "pick.type",pick.type #print "pick.event",dir(pick.event) #print "pick.event",pick.event #print "pick.event.type",pick.event.type #print "pick.event.state",pick.event.state #print "pick.event.time",pick.event.time #print "pick.hits",pick.hits if ( len(pick.hits) == 1) and pick.hits.has_key(self): if self.viewer.currentObject != self: # if the only hit is the legend, # it becomes the current object self.viewer.SetCurrentObject(self) self.isMoving = True self.calculateAnchorAndPosition(pick.event) elif pick.event.time - self.lastPickEventTime < 200: #double click self.viewer.SetCurrentObject(self.viewer.rootObject) self.respondToDoubleClick(pick.event) elif pick.hits[self][0][0] == 1: # the click in inside the resize button #print "resize" self.isMoving = False elif pick.hits[self][0][0] == 0: # the click in inside the legend but outside # the resize button self.isMoving = True #print "pick.event", pick.event.x, pick.event.y self.calculateAnchorAndPosition(pick.event) #print "self.position", self.position if self.viewer: self.viewer.objectsNeedingRedo[self] = None elif self.viewer.currentObject == self: #print "the insert2d is selected, but picking is outside" self.isMoving = None self.viewer.SetCurrentObject(self.viewer.rootObject) self.lastPickEventTime = pick.event.time mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/SelectionGUI.py0000644000175000017500000001141711106400776022537 0ustar debiandebian######################################################################## # # Date: 2000 Author: Michel F. SANNER, Guillaume Vareille # # sanner@scripps.edu # vareille@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel Sanner and TSRI # # revision: # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/SelectionGUI.py,v 1.8 2008/11/11 22:06:54 vareille Exp $ # # $Id: SelectionGUI.py,v 1.8 2008/11/11 22:06:54 vareille Exp $ # import Tkinter import DejaVu import Slider from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from mglutil.util.callback import CallBackFunction from mglutil.util.colorUtil import TkColor class SelectionGUI: def __init__(self, master=None, viewerGui=None): if master is None: self.master = Tkinter.Toplevel() self.master.withdraw() self.master.title('Selection Settings') self.master.protocol('WM_DELETE_WINDOW', self.master.withdraw ) else: self.master = master self.mainFrame = Tkinter.Frame(self.master, relief='ridge', borderwidth=3) # CONTOUR WIDTH if DejaVu.enableSelectionContour is True: lLabel =Tkinter.Label(self.mainFrame, text='Contour width:') lLabel.grid(row=0, column=0, sticky='w') self.contourSizeSlider = Slider.Slider( self.mainFrame, minval=0, maxval = 10, immediate=1, incr=1, labelformat = '%d', cursortype='int' ) self.contourSizeSlider.frame.grid(row=0, column=1, columnspan=3) def setContourWidthSliderValue_cb(val): DejaVu.selectionContourSize = val viewerGui.viewer.Redraw() self.contourSizeSlider.AddCallback(setContourWidthSliderValue_cb) else: lLabel =Tkinter.Label(self.mainFrame, text='Contour selection is disabled') lLabel.grid(row=0, column=0, columnspan=3, sticky='w') # BACKGROUND COLOR lLabel =Tkinter.Label(self.mainFrame, text='Contour color:') lLabel.grid(row=1, column=0, sticky='w') lFunc = CallBackFunction(viewerGui.colorChooser.showColorChooser,'selection contour') self.contourColorButton = Tkinter.Button(self.mainFrame, #text='Contour color', width=7, background=TkColor(DejaVu.selectionContourColor), command=lFunc) self.contourColorButton.grid(row=1, column=1, columnspan=3) # PATTERN SIZE lLabel =Tkinter.Label(self.mainFrame, text='Pattern size:') lLabel.grid(row=2, column=0, sticky='w') def setPatternSizeSliderValue_cb(val): DejaVu.selectionPatternSize = val viewerGui.viewer.Redraw() self.patternSizeThumbwheel = ThumbWheel( self.mainFrame, width=70, height=16, type=int, value=DejaVu.selectionPatternSize, callback=setPatternSizeSliderValue_cb, continuous=True, oneTurn=10, wheelPad=2, min=0, max=50) self.patternSizeThumbwheel.grid(row=2, column=1, columnspan=3) self.mainFrame.pack(side='top') self.updateWidgets() def show(self, event=None): #print "showSpinGui", self if self.master.winfo_ismapped() == 0: self.master.deiconify() self.master.lift() def hide(self, event=None): #print "hideSpinGui", self if self.master.winfo_ismapped() == 1: self.master.withdraw() def toggle(self, event=None): #print "toggleSpinGui", self if self.master.winfo_ismapped() == 1: self.master.withdraw() else: self.master.deiconify() self.master.lift() def setWithWidgets(self): if DejaVu.enableSelectionContour is True: DejaVu.selectionContourSize = self.contourSizeSlider.Get() DejaVu.selectionPatternSize = self.patternSizeThumbwheel.Get() def updateWidgets(self): if DejaVu.enableSelectionContour is True: self.contourSizeSlider.Set(DejaVu.selectionContourSize) self.contourColorButton.configure(background=TkColor(DejaVu.selectionContourColor)) self.patternSizeThumbwheel.set(DejaVu.selectionPatternSize) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/0000755000175000017500000000000012146207760020774 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Fan3D.py0000644000175000017500000002102211173172165023274 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Fan3D.py,v 1.16 2009/04/20 22:17:25 vareille Exp $ # # import sys, os,math,types import numpy from Tkinter import Menubutton import unittest,numpy.oldnumeric as Numeric from DejaVu.Viewer import Viewer from time import sleep import Image from math import sqrt from DejaVu.Arcs3D import Fan3D class Fan3D__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = ['radii', 'angles', 'vectors'] all other keywords are handled by Geom.__init__ method """ #defaults def test_Fan3D_defaults(self): """defaults for radii, angles, vectors """ g = Fan3D() self.assertEqual(isinstance(g, Fan3D), True) #radii def test_Fan3D_radii(self): """radii 2 (default radii is 0.2) """ g = Fan3D(radii=2.) self.assertEqual(isinstance(g, Fan3D), True) #angles def test_Fan3D_angles(self): """angles 180., (default angles = (360.0,)) """ g = Fan3D(angles=180.0) self.assertEqual(isinstance(g, Fan3D), True) #vectors def test_Fan3D_angles(self): """vectors (.5,0,0) (default vectors is ((1.,0,0),)) """ g = Fan3D(vectors=(.5,0.,0.)) self.assertEqual(isinstance(g, Fan3D), True) class Fan3D_Set_Tests(unittest.TestCase): """ # doesnot override Geom.Set so just one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = Fan3D(name='test', angles=(30.)) def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Fan3D_Set_angles(self): """ Set angles by call to Set """ self.geom.Set(angles=180.) self.assertEqual(self.geom.angles, [180.]) def test_Fan3D_Set_radii(self): """ Set radii by call to Set """ self.geom.Set(radii=3.0) self.assertEqual(self.geom.radii, [3.0]) def test_Fan3D_Set_vectors(self): """ Set vectors by call to Set """ self.geom.Set(vectors=(1.0,1.0,0.0)) self.assertEqual(self.geom.vectors, [(1.0,1.0,0.0)]) def test_Fan3D_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) #INVALID INPUTS def test_Fan3D_Set_angles_invalid(self): """ Set inavlid angles by call to Set """ self.assertRaises(ValueError,self.geom.Set,angles="a") def test_Fan3D_Set_radii_invalid(self): """ Set invalid radii by call to Set """ self.assertRaises(ValueError,self.geom.Set,radii="a") def test_Fan3D_Set_vectors_invalid(self): """ Set invalid vectors by call to Set """ self.assertRaises(TypeError,self.geom.Set,vectors=1) def test_Fan3D_Set_vectors_string_invalid_input(self): """ Set invalid string vector input for Set """ self.assertRaises(AssertionError,self.geom.Set,vectors="a") #SETTING LIST OF INPUTS def test_Fan3D_Set_list_of_angles(self): """ Set list of angles by call to Set """ self.geom.Set(vertices =((0,0,0),(5.,0.,0.),(-5,0.0,0.))) self.geom.Set(angles=(180.,360.0,270.0)) self.assertEqual(self.geom.angles, [180.0,360.0,270.0]) def test_Fan3D_Set_list_of_radii(self): """ Set list of angles by call to Set """ self.geom.Set(vertices =((0,0,0),(5.,0.,0.),(-5,0.0,0.))) self.geom.Set(radii=(3.0,2.0,5.0)) self.assertEqual(self.geom.radii, [3.0,2.0,5.0]) def test_Fan3D_Set_list_of_vectors(self): """ Set list of angles by call to Set """ self.geom.Set(vertices =((0,0,0),(5.,0.,0.),(-5,0.0,0.))) self.geom.Set(vectors=((1.0,1.0,0.0),(0.0,1.0,0.0),(0.0,1.0,1.0))) self.assertEqual(self.geom.vectors, [((1.0,1.0,0.0),(0.0,1.0,0.0),(0.0,1.0,1.0))]) class Fan3D_Viewer_Tests(unittest.TestCase): """ tests for Fan3D in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.geom = Fan3D('arcs', vertices =((0,0,0),(5.,0.,0.)), vnormals=((0,0,-1),(0,1.,0)), materials=((.5,0,0),), radii=(1.0,2.0), angles=(360,180), vectors=((1,1,0),(1,0,0)), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.geom.Set(inheritCulling=0) self.geom.Set(culling=0) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGuiFan3D def test_Fan3D_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() #sleep(5) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] #sleep(5) self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Arcs 3D image def test_Fan3D_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #sleep(5) #check that the pixel is not black self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageFan3D.tif") im = Image.open("./saveimageFan3D.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum for v in d: self.assertTrue( max(v) < 1e-15 ) if __name__ == '__main__': test_cases = [ 'Fan3D__init__Tests', 'Fan3D_Set_Tests', 'Fan3D_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Spheres.py0000644000175000017500000002000411225234771024011 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Spheres.py,v 1.26 2009/07/09 00:29:45 vareille Exp $ # # import sys, os,math,types import numpy from Tkinter import Menubutton import unittest, numpy.oldnumeric as Numeric from math import sqrt from opengltk.OpenGL import GL from DejaVu.Viewer import Viewer from DejaVu.Spheres import Spheres,TriangulateIcos,TriangulateIcosByEdgeCenterPoint from time import sleep from DejaVu import viewerConst import Image class Spheres__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = ['centers', 'quality', 'radii', 'slices', 'shapes'] all other keywords are handled by Geom.__init__ method """ #defaults def test_Spheres_defaults(self): """defaults """ g = Spheres() self.assertEqual(isinstance(g, Spheres), True) #centers def test_Spheres_centers(self): """centers """ g = Spheres(centers=((0,0,0),(1,1,1))) self.assertEqual(isinstance(g, Spheres), True) #quality def test_Spheres_quality(self): """quality """ g = Spheres(quality=17) self.assertEqual(isinstance(g, Spheres), True) #radii def test_Spheres_radii(self): """radii 2 """ g = Spheres(radii=2.) self.assertEqual(isinstance(g, Spheres), True) #slices def test_Spheres_slices(self): """slices """ g = Spheres(slices=5) self.assertEqual(isinstance(g, Spheres), True) #stacks def test_Spheres_stacks(self): """stacks """ g = Spheres(stacks=5) self.assertEqual(isinstance(g, Spheres), True) class Spheres_Set_Tests(unittest.TestCase): """ # doesnot override Geom.Set so just one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = Spheres(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Spheres_Set_radii(self): """ test Setting radii """ self.geom.Set(centers=((1,1,1),(2,2,2),(3,3,3)), radii=(1,1,1,),) self.assertEqual(self.geom.vertexSet.vertices.array[0][0], 1) def test_Spheres_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) def test_Spheres_centers(self): """checks setting center of spheres """ self.geom.Set(centers = ((3,0,0),)) #self.assertEqual(self.geom.vertexSet.vertices.array[0],((3,0,0),)) self.assertTrue(numpy.alltrue(self.geom.vertexSet.vertices.array[0]==[3.,0.,0.])) def test_Spheres_centers_invalid(self): """invalid center of spheres """ self.assertRaises(AttributeError,self.geom.Set,centers=(0,0,) ) def test_Spheres_quality(self): """checks setting quality of spheres """ self.geom.Set(quality = 5) self.assertEqual(self.geom.quality,5) def test_Spheres_quality_invalid(self): """invalid input for slices """ self.geom.Set(quality= -100) self.assertNotEqual(self.geom.quality, -100) #self.assertRaises(AssertionError,sph.Set,slices= -100) def test_Spheres_radii(self): """checks setting radii of spheres """ self.geom.Set(radii = 3.0) self.assertEqual(self.geom.radius,3.0) class Spheres_Viewer_Tests(unittest.TestCase): """ tests for Spheres in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.geom = Spheres('spheres', vertices =((0,0,0),(5.,0.,0.)), materials=((.5,0,0),), radii=(5.0,), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGuiSpheres def test_Spheres_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=.25, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Arcs 3D image def test_Spheres_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageSpheres.tif") im = Image.open("./saveimageSpheres.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9 and v[0]>-1.e-9) self.assertTrue(v[1]<1.e-9 and v[1]>-1.e-9) self.assertTrue(v[2]<1.e-9 and v[2]>-1.e-9) if __name__ == '__main__': test_cases = [ 'Spheres__init__Tests', 'Spheres_Set_Tests', 'Spheres_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_memory.py0000755000175000017500000000234510177747401023727 0ustar debiandebianimport gc import unittest from DejaVu.Viewer import Viewer from time import sleep from Tkinter import Tk, Frame, Toplevel from DejaVu.Spheres import Spheres class memory_Tests(unittest.TestCase): """ tests for memory """ #def setUp(self): # self.root = Tk() # self.root.withdraw() # # def tearDown(self): # try: # self.root.destroy() # except: # pass def XXtest_creatingViewers100Time(self): """create a Viewer and destroy it 100 times""" #for i in range(100): # vi = Viewer(verbose=0) # vi.master.update() # vi.Exit() # gc.collect() self.assertEqual(1,1) def test_creatingViewers100TimeWithViewer(self): """create a Viewer and destroy it 100 times, when a Viewer already exists""" vi1 = Viewer(verbose=False) for i in range(10): vi = Viewer(verbose=0) vi.master.update() vi.Exit() gc.collect() vi1.Exit() gc.collect() self.assertEqual(1,1) if __name__ == '__main__': test_cases = [ 'memory_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Arrows.py0000644000175000017500000001420010651433502023651 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Arrows.py,v 1.11 2007/07/24 17:30:42 vareille Exp $ # # import unittest import sys, os,math from Tkinter import Menubutton import numpy.oldnumeric as Numeric, types from math import sqrt from DejaVu.Viewer import Viewer from DejaVu.Arrows import Arrows import Image class Arrows__init__Tests(unittest.TestCase): """ 'Arrows__init__Tests', """ #defaults def test_Arrows_defaults(self): """defaults for shape, etc """ g = Arrows() self.assertEqual(isinstance(g, Arrows), True) #shape def test_Arrows_shape(self): """shape (0,2), (default shape is (0,3)) """ g = Arrows(shape=(0,2)) self.assertEqual(isinstance(g, Arrows), True) class Arrows_Set_Tests(unittest.TestCase): """ # doesnot override Geom.Set so just one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = Arrows(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Arrows_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) class Arrows_Viewer_Tests(unittest.TestCase): """ tests for Arrows in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGui... def test_Arrows_inheritMaterial(self): """test image and changing its material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) arrows = Arrows("arrows", vertices=[[0,0,0],[10,0,0],[0,8,0]], faces=((0,1),(0,2)), materials=((1,0,0),), inheritLineWidth=0, inheritMaterial=0, lineWidth=10) self.vi.AddObject(arrows) self.vi.SetCurrentObject(arrows) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = arrows.getState()['inheritMaterial'] #print "now arrows.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Arcs 3D image def test_arrow_image(self): """test creation of valid image by writing/reading a tif file """ cam = self.vi.currentCamera arrows=Arrows("myarrows", vertices=[[0,0,0],[10,0,0],[0,8,0]], faces=((0,1),(0,2)), inheritLineWidth = False, lineWidth = 10) self.vi.AddObject(arrows) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = sqrt(total_pixels) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black ##print "buff_255[midpt][midpt][0]=", buff_255[midpt][midpt][0] # if sys.platform == 'win32': # self.assertEqual(buff_255[midpt][midpt+2][0]>0.1, True) # else: self.assertEqual(buff_255[midpt][midpt][0]>0.1, True) buff_255_sum=Numeric.add.reduce(buff_255) cam.SaveImage("./saveimagearrows.tif") im = Image.open("./saveimagearrows.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum=Numeric.add.reduce(narray_255) #print sum d=buff_255_sum-narray_255_sum #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) if __name__ == '__main__': test_cases = [ 'Arrows__init__Tests', 'Arrows_Set_Tests', 'Arrows_Viewer_Tests', ] unittest.main( argv=([__name__ , ] + test_cases) ) #unittest.main( argv=([__name__ , '-v'] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_MaterialEditor.py0000644000175000017500000000101710321523260025276 0ustar debiandebian """ do not add any dependancy on this file """ import unittest from opengltk.OpenGL import GL from DejaVu.Viewer import Viewer class MaterialEditor_BaseTests(unittest.TestCase): def test_MaterialEditorDependancies(self): vi = Viewer() mated = vi.materialEditor mated.show() obj = vi.currentObject mated.setObject(obj, GL.GL_FRONT) mated.defineMaterial(obj.materials[GL.GL_FRONT].prop, GL.GL_FRONT) assert mated if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Fog.py0000644000175000017500000002605310346114307023120 0ustar debiandebian# # # $Id: test_Fog.py,v 1.6 2005/12/08 20:34:15 annao Exp $ # # import unittest from opengltk.OpenGL import GL from DejaVu import Viewer class Fog_BaseTests(unittest.TestCase): """ setUp + tearDown form a fixture: working environment for the testing code """ def setUp(self): """ start Viewer """ if not hasattr(self, 'vi'): self.vi = Viewer(verbose=False) #self.vi.cameras[0].master.master.withdraw() self.fog = self.vi.currentCamera.fog self.orig_state = self.fog.getState() def tearDown(self): """ clean-up """ #print 'in fog tearDown' #apply(self.fog.Set, (), self.orig_state) try: self.vi.Exit() except: pass #self.vi.__del__() def test_SetColor_attr(self): """ Set color changes fog's color attribute """ self.fog.Set(color=(1,0,0)) col = self.fog.color self.assertEqual(col[0], 1.) self.assertEqual(col[1], 0.) self.assertEqual(col[2], 0.) def test_SetColor_GL(self): """ Set color changes GL_FOG_COLOR """ self.fog.Set(color=(1,0,0)) col = GL.glGetFloat(GL.GL_FOG_COLOR) self.assertEqual(col[0], 1.) self.assertEqual(col[1], 0.) self.assertEqual(col[2], 0.) def test_SetColor_state(self): """ Set color changes fog's state['color'] """ self.fog.Set(color=(1,0,0)) state = self.fog.getState() col = state['color'] self.assertEqual(col[0], 1.) self.assertEqual(col[1], 0.) self.assertEqual(col[2], 0.) def test_SetColor_bad_input(self): """ ValueError raised on bad input to Set color """ self.assertRaises(ValueError, self.fog.Set,color=(1,0)) def test_SetColor_empty_input(self): """ ValueError raised on empty input to Set color """ self.assertRaises(ValueError, self.fog.Set, color=()) def test_SetColor_too_much_input(self): """ ValueError raised on too_much input to Set color """ self.assertRaises(ValueError, self.fog.Set,color=(1,0,0,1,1)) def test_SetStart_attr(self): """ Set start changes fog's start attribute """ val = 15 self.fog.Set(start=val) self.assertEqual(self.fog.start, val) def test_SetStart_GL(self): """ Set start changes GL_FOG_START """ val = 15 self.fog.Set(start=val) start = GL.glGetFloat(GL.GL_FOG_START) self.assertEqual(start, val) def test_SetStart_state(self): """ Set start changes fog's state['start'] """ val = 15 self.fog.Set(start=val) state = self.fog.getState() start = state['start'] self.assertEqual(start, val) def test_SetStart_bad_input(self): """ ValueError raised on bad input to Set start """ self.assertRaises(AttributeError, self.fog.Set, start=100) def test_SetStart_empty_input(self): """ ValueError raised on empty input to Set start """ self.assertRaises(AttributeError, self.fog.Set, start='') def test_SetStart_too_much_input(self): """ ValueError raised on too_much input to Set start """ self.assertRaises(AttributeError, self.fog.Set,start=[1.,2.,3.,4.]) def test_SetEnd_attr(self): """ Set end changes fog's end attribute """ val = 30 self.fog.Set(end=val) self.assertEqual(self.fog.end, val) def test_SetEnd_GL(self): """ Set end changes GL_FOG_END """ val = 30 self.fog.Set(end=val) end = GL.glGetFloat(GL.GL_FOG_END) self.assertEqual(end, val) def test_SetEnd_state(self): """ Set end changes fog's state['end'] """ val = 30 self.fog.Set(end=val) state = self.fog.getState() end = state['end'] self.assertEqual(end, val) def xtest_SetEnd_bad_input(self): """ ValueError raised on bad input to Set end """ self.assertRaises(AttributeError, self.fog.Set, end=10) def xtest_SetEnd_empty_input(self): """ ValueError raised on empty input to Set end """ self.assertRaises(AttributeError, self.fog.Set, end='') def xtest_SetEnd_too_much_input(self): """ ValueError raised on too_much input to Set end """ self.assertRaises(AttributeError, self.fog.Set,end=[1.,2.,3.,4.]) def test_SetDensity_attr(self): """ Set density changes fog's density attribute """ val = 0.5 self.fog.Set(density=val) self.assertEqual(self.fog.density, val) def test_SetDensity_GL(self): """ Set density changes GL_FOG_DENSITY """ val = 0.5 self.fog.Set(density=val) density = GL.glGetFloat(GL.GL_FOG_DENSITY) self.assertEqual(density, val) def test_SetDensity_state(self): """ Set density changes fog's state['density'] """ val = 0.5 self.fog.Set(density=val) state = self.fog.getState() density = state['density'] self.assertEqual(density, val) def test_SetDensity_bad_input(self): """ AttributeError raised on bad input to Set density """ self.assertRaises(AttributeError, self.fog.Set, density=10) def test_SetDensity_empty_input(self): """ AttributeError raised on empty input to Set density """ self.assertRaises(AttributeError, self.fog.Set, density='') def test_SetDensity_too_much_input(self): """ AttributeError raised on too_much input to Set density """ self.assertRaises(AttributeError, self.fog.Set,density=[1.,2.,3.,4.]) #MODE #GL_EXP def test_EXP_SetMode_attr(self): """ Set mode GL_EXP changes fog's mode attribute """ val = GL.GL_EXP self.fog.Set(mode=val) self.assertEqual(self.fog.mode, val) def test_EXP_SetMode_GL(self): """ Set mode GL_EXP changes GL_FOG_MODE """ val = GL.GL_EXP self.fog.Set(mode=val) mode = GL.glGetInteger(GL.GL_FOG_MODE) self.assertEqual(mode, val) def test_EXP_SetMode_state(self): """ Set mode GL_EXP changes fog's state['mode'] ====================================================================== FAIL: Set mode changes fog's state['mode'] ---------------------------------------------------------------------- Traceback (most recent call last): File "test_Fog.py", line 261, in test_EXP_SetMode_state self.assertEqual(mode, val) File "/mgl/python/share//lib/python2.3/unittest.py", line 302, in failUnlessEqual raise self.failureException, \ AssertionError: 'GL_EXP' != 2048 """ val = GL.GL_EXP self.fog.Set(mode=val) state = self.fog.getState() mode = state['mode'] self.assertEqual(mode, "GL_EXP") #GL_EXP2 def test_EXP2_SetMode_attr(self): """ Set mode GL_EXP2 changes fog's mode attribute """ val = GL.GL_EXP2 self.fog.Set(mode=val) self.assertEqual(self.fog.mode, val) def test_EXP2_SetMode_GL(self): """ Set mode GL_EXP2 changes GL_FOG_MODE """ val = GL.GL_EXP2 self.fog.Set(mode=val) mode = GL.glGetInteger(GL.GL_FOG_MODE) self.assertEqual(mode, val) def test_EXP2_SetMode_state(self): """ Set mode GL_EXP2 changes fog's state['mode'] ====================================================================== FAIL: Set mode changes fog's state['mode'] ---------------------------------------------------------------------- Traceback (most recent call last): File "test_Fog.py", line 288, in test_EXP2_SetMode_state self.assertEqual(mode, val) File "/mgl/python/share//lib/python2.3/unittest.py", line 302, in failUnlessEqual raise self.failureException, \ AssertionError: 'GL_EXP2' != 2049 """ val = GL.GL_EXP2 self.fog.Set(mode=val) state = self.fog.getState() mode = state['mode'] self.assertEqual(mode, "GL_EXP2") #GL_LINEAR def test_LINEAR_SetMode_attr(self): """ Set mode GL_LINEAR changes fog's mode attribute """ val = GL.GL_LINEAR self.fog.Set(mode=val) self.assertEqual(self.fog.mode, val) def test_LINEAR_SetMode_GL(self): """ Set mode GL_LINEAR changes GL_FOG_MODE """ val = GL.GL_LINEAR self.fog.Set(mode=val) mode = GL.glGetInteger(GL.GL_FOG_MODE) self.assertEqual(mode, val) def test_LINEAR_SetMode_state(self): """ Set mode GL_LINEAR changes fog's state['mode'] ====================================================================== NB: all of these could be a bit better FAIL: Set mode changes fog's state['mode'] ---------------------------------------------------------------------- Traceback (most recent call last): File "test_Fog.py", line 316, in test_LINEAR_SetMode_state self.assertEqual(mode, val) File "/mgl/python/share//lib/python2.3/unittest.py", line 302, in failUnlessEqual raise self.failureException, \ AssertionError: 'GL_LINEAR' != 9729 """ val = GL.GL_LINEAR self.fog.Set(mode=val) state = self.fog.getState() mode = state['mode'] self.assertEqual(mode, 'GL_LINEAR') def test_SetMode_bad_input(self): """ AttributeError raised on bad input to Set mode """ self.assertRaises(AttributeError, self.fog.Set, mode="INVALID") def test_SetMode_empty_input(self): """ AttributeError raised on empty input to Set mode """ self.assertRaises(AttributeError, self.fog.Set, mode='') def test_SetMode_too_much_input(self): """ AttributeError raised on too_much input to Set mode """ self.assertRaises(AttributeError, self.fog.Set,mode=["INV","ALID"]) #ENABLE def test_SetEnabled_attr(self): """ Set enabled changes fog's enabled attribute """ val = 0 self.fog.Set(enabled=val) self.assertEqual(self.fog.enabled, val) def test_SetEnabled_GL(self): """ Set enabled changes GL_FOG """ val = 0 self.fog.Set(enabled=val) enabled = GL.glGetInteger(GL.GL_FOG) self.assertEqual(enabled, val) def test_SetEnabled_state(self): """ Set enabled changes fog's state['enabled'] """ val = 0 self.fog.Set(enabled=val) state = self.fog.getState() enabled = state['enabled'] self.assertEqual(enabled, 0) def test_SetEnabled_bad_input(self): """ ValueError raised on bad input to Set enabled """ self.assertRaises(ValueError, self.fog.Set, enabled=2) def test_SetEnabled_empty_input(self): """ ValueError raised on empty input to Set enabled """ self.assertRaises(ValueError, self.fog.Set, enabled='') if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/rgb256_map.py0000644000175000017500000003300010651433502023200 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by from DejaVu.colorMap import ColorMap from numpy.oldnumeric import array cm = ColorMap('rgb256') cfg = {'name': 'rgb256', 'ramp': array([[ 0. , 0. , 1. , 1. ], [ 0. , 0.015625, 1. , 1. ], [ 0. , 0.03125 , 1. , 1. ], [ 0. , 0.046875, 1. , 1. ], [ 0. , 0.0625 , 1. , 1. ], [ 0. , 0.078125, 1. , 1. ], [ 0. , 0.09375 , 1. , 1. ], [ 0. , 0.109375, 1. , 1. ], [ 0. , 0.125 , 1. , 1. ], [ 0. , 0.140625, 1. , 1. ], [ 0. , 0.15625 , 1. , 1. ], [ 0. , 0.171875, 1. , 1. ], [ 0. , 0.1875 , 1. , 1. ], [ 0. , 0.203125, 1. , 1. ], [ 0. , 0.21875 , 1. , 1. ], [ 0. , 0.234375, 1. , 1. ], [ 0. , 0.25 , 1. , 1. ], [ 0. , 0.265625, 1. , 1. ], [ 0. , 0.28125 , 1. , 1. ], [ 0. , 0.296875, 1. , 1. ], [ 0. , 0.3125 , 1. , 1. ], [ 0. , 0.328125, 1. , 1. ], [ 0. , 0.34375 , 1. , 1. ], [ 0. , 0.359375, 1. , 1. ], [ 0. , 0.375 , 1. , 1. ], [ 0. , 0.390625, 1. , 1. ], [ 0. , 0.40625 , 1. , 1. ], [ 0. , 0.421875, 1. , 1. ], [ 0. , 0.4375 , 1. , 1. ], [ 0. , 0.453125, 1. , 1. ], [ 0. , 0.46875 , 1. , 1. ], [ 0. , 0.484375, 1. , 1. ], [ 0. , 0.5 , 1. , 1. ], [ 0. , 0.515625, 1. , 1. ], [ 0. , 0.53125 , 1. , 1. ], [ 0. , 0.546875, 1. , 1. ], [ 0. , 0.5625 , 1. , 1. ], [ 0. , 0.578125, 1. , 1. ], [ 0. , 0.59375 , 1. , 1. ], [ 0. , 0.609375, 1. , 1. ], [ 0. , 0.625 , 1. , 1. ], [ 0. , 0.640625, 1. , 1. ], [ 0. , 0.65625 , 1. , 1. ], [ 0. , 0.671875, 1. , 1. ], [ 0. , 0.6875 , 1. , 1. ], [ 0. , 0.703125, 1. , 1. ], [ 0. , 0.71875 , 1. , 1. ], [ 0. , 0.734375, 1. , 1. ], [ 0. , 0.75 , 1. , 1. ], [ 0. , 0.765625, 1. , 1. ], [ 0. , 0.78125 , 1. , 1. ], [ 0. , 0.796875, 1. , 1. ], [ 0. , 0.8125 , 1. , 1. ], [ 0. , 0.828125, 1. , 1. ], [ 0. , 0.84375 , 1. , 1. ], [ 0. , 0.859375, 1. , 1. ], [ 0. , 0.875 , 1. , 1. ], [ 0. , 0.890625, 1. , 1. ], [ 0. , 0.90625 , 1. , 1. ], [ 0. , 0.921875, 1. , 1. ], [ 0. , 0.9375 , 1. , 1. ], [ 0. , 0.953125, 1. , 1. ], [ 0. , 0.96875 , 1. , 1. ], [ 0. , 0.984375, 1. , 1. ], [ 0. , 1. , 1. , 1. ], [ 0. , 1. , 0.984375, 1. ], [ 0. , 1. , 0.96875 , 1. ], [ 0. , 1. , 0.953125, 1. ], [ 0. , 1. , 0.9375 , 1. ], [ 0. , 1. , 0.921875, 1. ], [ 0. , 1. , 0.90625 , 1. ], [ 0. , 1. , 0.890625, 1. ], [ 0. , 1. , 0.875 , 1. ], [ 0. , 1. , 0.859375, 1. ], [ 0. , 1. , 0.84375 , 1. ], [ 0. , 1. , 0.828125, 1. ], [ 0. , 1. , 0.8125 , 1. ], [ 0. , 1. , 0.796875, 1. ], [ 0. , 1. , 0.78125 , 1. ], [ 0. , 1. , 0.765625, 1. ], [ 0. , 1. , 0.75 , 1. ], [ 0. , 1. , 0.734375, 1. ], [ 0. , 1. , 0.71875 , 1. ], [ 0. , 1. , 0.703125, 1. ], [ 0. , 1. , 0.6875 , 1. ], [ 0. , 1. , 0.671875, 1. ], [ 0. , 1. , 0.65625 , 1. ], [ 0. , 1. , 0.640625, 1. ], [ 0. , 1. , 0.625 , 1. ], [ 0. , 1. , 0.609375, 1. ], [ 0. , 1. , 0.59375 , 1. ], [ 0. , 1. , 0.578125, 1. ], [ 0. , 1. , 0.5625 , 1. ], [ 0. , 1. , 0.546875, 1. ], [ 0. , 1. , 0.53125 , 1. ], [ 0. , 1. , 0.515625, 1. ], [ 0. , 1. , 0.5 , 1. ], [ 0. , 1. , 0.484375, 1. ], [ 0. , 1. , 0.46875 , 1. ], [ 0. , 1. , 0.453125, 1. ], [ 0. , 1. , 0.4375 , 1. ], [ 0. , 1. , 0.421875, 1. ], [ 0. , 1. , 0.40625 , 1. ], [ 0. , 1. , 0.390625, 1. ], [ 0. , 1. , 0.375 , 1. ], [ 0. , 1. , 0.359375, 1. ], [ 0. , 1. , 0.34375 , 1. ], [ 0. , 1. , 0.328125, 1. ], [ 0. , 1. , 0.3125 , 1. ], [ 0. , 1. , 0.296875, 1. ], [ 0. , 1. , 0.28125 , 1. ], [ 0. , 1. , 0.265625, 1. ], [ 0. , 1. , 0.25 , 1. ], [ 0. , 1. , 0.234375, 1. ], [ 0. , 1. , 0.21875 , 1. ], [ 0. , 1. , 0.203125, 1. ], [ 0. , 1. , 0.1875 , 1. ], [ 0. , 1. , 0.171875, 1. ], [ 0. , 1. , 0.15625 , 1. ], [ 0. , 1. , 0.140625, 1. ], [ 0. , 1. , 0.125 , 1. ], [ 0. , 1. , 0.109375, 1. ], [ 0. , 1. , 0.09375 , 1. ], [ 0. , 1. , 0.078125, 1. ], [ 0. , 1. , 0.0625 , 1. ], [ 0. , 1. , 0.046875, 1. ], [ 0. , 1. , 0.03125 , 1. ], [ 0. , 1. , 0.015625, 1. ], [ 0. , 1. , 0. , 1. ], [ 0.015625, 1. , 0. , 1. ], [ 0.03125 , 1. , 0. , 1. ], [ 0.046875, 1. , 0. , 1. ], [ 0.0625 , 1. , 0. , 1. ], [ 0.078125, 1. , 0. , 1. ], [ 0.09375 , 1. , 0. , 1. ], [ 0.109375, 1. , 0. , 1. ], [ 0.125 , 1. , 0. , 1. ], [ 0.140625, 1. , 0. , 1. ], [ 0.15625 , 1. , 0. , 1. ], [ 0.171875, 1. , 0. , 1. ], [ 0.1875 , 1. , 0. , 1. ], [ 0.203125, 1. , 0. , 1. ], [ 0.21875 , 1. , 0. , 1. ], [ 0.234375, 1. , 0. , 1. ], [ 0.25 , 1. , 0. , 1. ], [ 0.265625, 1. , 0. , 1. ], [ 0.28125 , 1. , 0. , 1. ], [ 0.296875, 1. , 0. , 1. ], [ 0.3125 , 1. , 0. , 1. ], [ 0.328125, 1. , 0. , 1. ], [ 0.34375 , 1. , 0. , 1. ], [ 0.359375, 1. , 0. , 1. ], [ 0.375 , 1. , 0. , 1. ], [ 0.390625, 1. , 0. , 1. ], [ 0.40625 , 1. , 0. , 1. ], [ 0.421875, 1. , 0. , 1. ], [ 0.4375 , 1. , 0. , 1. ], [ 0.453125, 1. , 0. , 1. ], [ 0.46875 , 1. , 0. , 1. ], [ 0.484375, 1. , 0. , 1. ], [ 0.5 , 1. , 0. , 1. ], [ 0.515625, 1. , 0. , 1. ], [ 0.53125 , 1. , 0. , 1. ], [ 0.546875, 1. , 0. , 1. ], [ 0.5625 , 1. , 0. , 1. ], [ 0.578125, 1. , 0. , 1. ], [ 0.59375 , 1. , 0. , 1. ], [ 0.609375, 1. , 0. , 1. ], [ 0.625 , 1. , 0. , 1. ], [ 0.640625, 1. , 0. , 1. ], [ 0.65625 , 1. , 0. , 1. ], [ 0.671875, 1. , 0. , 1. ], [ 0.6875 , 1. , 0. , 1. ], [ 0.703125, 1. , 0. , 1. ], [ 0.71875 , 1. , 0. , 1. ], [ 0.734375, 1. , 0. , 1. ], [ 0.75 , 1. , 0. , 1. ], [ 0.765625, 1. , 0. , 1. ], [ 0.78125 , 1. , 0. , 1. ], [ 0.796875, 1. , 0. , 1. ], [ 0.8125 , 1. , 0. , 1. ], [ 0.828125, 1. , 0. , 1. ], [ 0.84375 , 1. , 0. , 1. ], [ 0.859375, 1. , 0. , 1. ], [ 0.875 , 1. , 0. , 1. ], [ 0.890625, 1. , 0. , 1. ], [ 0.90625 , 1. , 0. , 1. ], [ 0.921875, 1. , 0. , 1. ], [ 0.9375 , 1. , 0. , 1. ], [ 0.953125, 1. , 0. , 1. ], [ 0.96875 , 1. , 0. , 1. ], [ 0.984375, 1. , 0. , 1. ], [ 1. , 1. , 0. , 1. ], [ 1. , 0.984375, 0. , 1. ], [ 1. , 0.96875 , 0. , 1. ], [ 1. , 0.953125, 0. , 1. ], [ 1. , 0.9375 , 0. , 1. ], [ 1. , 0.921875, 0. , 1. ], [ 1. , 0.90625 , 0. , 1. ], [ 1. , 0.890625, 0. , 1. ], [ 1. , 0.875 , 0. , 1. ], [ 1. , 0.859375, 0. , 1. ], [ 1. , 0.84375 , 0. , 1. ], [ 1. , 0.828125, 0. , 1. ], [ 1. , 0.8125 , 0. , 1. ], [ 1. , 0.796875, 0. , 1. ], [ 1. , 0.78125 , 0. , 1. ], [ 1. , 0.765625, 0. , 1. ], [ 1. , 0.75 , 0. , 1. ], [ 1. , 0.734375, 0. , 1. ], [ 1. , 0.71875 , 0. , 1. ], [ 1. , 0.703125, 0. , 1. ], [ 1. , 0.6875 , 0. , 1. ], [ 1. , 0.671875, 0. , 1. ], [ 1. , 0.65625 , 0. , 1. ], [ 1. , 0.640625, 0. , 1. ], [ 1. , 0.625 , 0. , 1. ], [ 1. , 0.609375, 0. , 1. ], [ 1. , 0.59375 , 0. , 1. ], [ 1. , 0.578125, 0. , 1. ], [ 1. , 0.5625 , 0. , 1. ], [ 1. , 0.546875, 0. , 1. ], [ 1. , 0.53125 , 0. , 1. ], [ 1. , 0.515625, 0. , 1. ], [ 1. , 0.5 , 0. , 1. ], [ 1. , 0.484375, 0. , 1. ], [ 1. , 0.46875 , 0. , 1. ], [ 1. , 0.453125, 0. , 1. ], [ 1. , 0.4375 , 0. , 1. ], [ 1. , 0.421875, 0. , 1. ], [ 1. , 0.40625 , 0. , 1. ], [ 1. , 0.390625, 0. , 1. ], [ 1. , 0.375 , 0. , 1. ], [ 1. , 0.359375, 0. , 1. ], [ 1. , 0.34375 , 0. , 1. ], [ 1. , 0.328125, 0. , 1. ], [ 1. , 0.3125 , 0. , 1. ], [ 1. , 0.296875, 0. , 1. ], [ 1. , 0.28125 , 0. , 1. ], [ 1. , 0.265625, 0. , 1. ], [ 1. , 0.25 , 0. , 1. ], [ 1. , 0.234375, 0. , 1. ], [ 1. , 0.21875 , 0. , 1. ], [ 1. , 0.203125, 0. , 1. ], [ 1. , 0.1875 , 0. , 1. ], [ 1. , 0.171875, 0. , 1. ], [ 1. , 0.15625 , 0. , 1. ], [ 1. , 0.140625, 0. , 1. ], [ 1. , 0.125 , 0. , 1. ], [ 1. , 0.109375, 0. , 1. ], [ 1. , 0.09375 , 0. , 1. ], [ 1. , 0.078125, 0. , 1. ], [ 1. , 0.0625 , 0. , 1. ], [ 1. , 0.046875, 0. , 1. ], [ 1. , 0.03125 , 0. , 1. ], [ 1. , 0.015625, 0. , 1. ]],'f'), 'maxi': 10.0, 'mini': 0.0} apply( cm.configure, (), cfg) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_ColorWheel.py0000644000175000017500000001141510735276634024462 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_ColorWheel.py,v 1.5 2007/12/28 22:50:04 vareille Exp $ # # import Tkinter import numpy import numpy.oldnumeric as Numeric, math import DejaVu.colorTool import DejaVu.Slider from DejaVu.EventHandler import CallbackFunctions import unittest from DejaVu.ColorWheel import ColorWheel from DejaVu.colorTool import ToRGB,ToHSV def MyCallback(color): print color def MyCallback2(color): print 'hello' class ColorWheel_BaseTests(unittest.TestCase): def test_colorwheel_visible(self): """check that one colorwheel is visible after building 3 """ root = Tkinter.Tk() cw = ColorWheel(root) cw.AddCallback(MyCallback) cw1 = ColorWheel(root, immediate=0) cw1.AddCallback(MyCallback2) cw2 = ColorWheel(root, immediate=0) cw1.AddCallback(MyCallback) cw2.AddCallback(MyCallback2) root.wait_visibility(cw.canvas) root.wait_visibility(cw1.canvas) root.wait_visibility(cw2.canvas) self.assertEqual(cw.canvas.master.winfo_ismapped(),True) self.assertEqual(root.winfo_ismapped(),True) root.destroy() def test_colorwheel_add_remove_callback(self): root = Tkinter.Tk() cw = ColorWheel(root) cw.AddCallback(MyCallback) root.wait_visibility(cw.canvas) self.assertEqual(len(cw.callbacks),1) cw.RemoveCallback(MyCallback) self.assertEqual(len(cw.callbacks),0) root.destroy() def test_colorwheel_height(self): """check height of colorwheel """ root = Tkinter.Tk() cw = ColorWheel(root) cw.height = 120 cw.AddCallback(MyCallback) root.wait_visibility(cw.canvas) #apparently there is a 10 pixel border on each edge: self.assertEqual(cw.canvas.cget('height'), str(100)) root.destroy() def test_colorwheel_cursor(self): """tests color wheel,moving cursor """ root = Tkinter.Tk() cw = ColorWheel(root) old_x = cw.cursorX old_y = cw.cursorY cw._MoveCursor(25,25) new_x = cw.cursorX new_y = cw.cursorY root.wait_visibility(cw.canvas) self.assertEqual(old_x != new_x,True) self.assertEqual(old_y != new_y,True) root.destroy() def test_colorwheel_color_1(self): """test colorwheel,colors after moving cursor """ root = Tkinter.Tk() cw = ColorWheel(root) old_color = cw.hsvColor cw._MoveCursor(25,25) new_color = cw.hsvColor root.wait_visibility(cw.canvas) #self.assertEqual(old_color,new_color) self.assertTrue(numpy.alltrue(old_color==new_color)) cw.Set((1.0,0.0,0.0),mode = 'RGB') mycolor = ToRGB(cw.Get()) mycol =[] for i in range(0,4): mycol.append(round(mycolor[i])) self.assertEqual(mycol,[1.0,0.0,0.0,1.0]) root.destroy() def test_colorwheel_color_HSV(self): """test colorwheel,when mode is hsv """ root = Tkinter.Tk() cw = ColorWheel(root) cw.Set((1.0,0.0,0.0),mode = 'HSV') root.wait_visibility(cw.canvas) self.assertEqual(cw.hsvColor,[1.0, 0.0, 0.0, 1.0]) self.assertEqual(cw.cursorX,50) self.assertEqual(cw.cursorY,50) root.destroy() def test_colorwheel_color_RGB(self): """test colorwheel,when mode is rgb """ root = Tkinter.Tk() cw = ColorWheel(root) cw.Set((1.0,0.0,0.0),mode = 'RGB') root.wait_visibility(cw.canvas) self.assertEqual(cw.cursorX,100) self.assertEqual(cw.cursorY,50) self.assertEqual(cw.hsvColor[:3] != [1.0, 0.0, 0.0],True) root.destroy() def test_colorwheel_Wysiwyg(self): """test colorwheel,when Wysiwyg On """ root = Tkinter.Tk() cw = ColorWheel(root) cw.Set((1.0,0.0,0.0),mode = 'HSV') #when on wheel colors are recomputed cw.setWysiwyg(1) root.wait_visibility(cw.canvas) self.assertEqual(cw.hsvColor == [1.0, 0.0, 0.0, 1.0],True) cw.setWysiwyg(0) #root.wait_visibility(cw.canvas) self.assertEqual(cw.hsvColor[:3] != [1.0, 0.0, 0.0],True) root.destroy() def test_colorwheel_keyword_arguements(self): """tests setting keyword arguements in colorwheel """ root = Tkinter.Tk() cw = ColorWheel(root,circles = 20,stripes = 20,width =160,height =160) self.assertEqual(cw.circles,20) self.assertEqual(cw.width,160) self.assertEqual(cw.height,160) self.assertEqual(cw.stripes,20) root.destroy() if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_IndexedPolygons.py0000644000175000017500000002202410651433502025512 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # Id$ # # import unittest import sys, os from math import sqrt from Tkinter import Menubutton from opengltk.OpenGL import GL from geomutils.geomalgorithms import TriangleNormals import numpy.oldnumeric as Numeric from DejaVu.Viewer import Viewer from DejaVu.IndexedPolygons import IndexedPolygons import Image class IndexedPolygons__init__Tests(unittest.TestCase): """test keywords for __init__: no special keywords for this geometry all keywords are handled by Geom.__init__ method """ #defaults def test_IndexedPolygons_defaults(self): """defaults for vertices, faces etc """ g = IndexedPolygons() self.assertEqual(isinstance(g, IndexedPolygons), True) #vertices def test_IndexedPolygons_vertices(self): """vertices ((0,0,0,),(1,0,0)) """ g = IndexedPolygons(vertices=((0,0,0,),(1,0,0))) self.assertEqual(isinstance(g, IndexedPolygons), True) #faces without vertices def test_IndexedPolygons_faces_only(self): """faces alone won't do... """ self.assertRaises(ValueError, IndexedPolygons, faces=((0,1),)) #vertices and faces def test_IndexedPolygons_vertices_and_faces(self): """vertices and faces """ g = IndexedPolygons( vertices=((0,0,0,),(1,0,0)), faces=((0,1),)) self.assertEqual(isinstance(g, IndexedPolygons), True) #materials def test_IndexedPolygons_materials(self): """materials ((1,0,0),) """ g = IndexedPolygons(materials=((1,0,0),)) self.assertEqual(isinstance(g, IndexedPolygons), True) class IndexedPolygons_Set_Tests(unittest.TestCase): """ # doesnot override Geom.Set so just one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = IndexedPolygons(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_IndexedPolygons_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) def test_Indexedpolygon_fnormals(self): """checks number of fnormals???? """ points = [ [-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1], [-1, 1, -1], [-1, -1, -1] ] indices = [ [0, 1, 3, 2], [4, 5, 7, 6], [6, 7, 1, 0], [2, 3, 5, 4], [6, 0, 2, 4], [1, 7, 5, 3] ] polygon = IndexedPolygons("box", vertices=points, faces=indices, visible=1) self.assertEqual(len(polygon.faceSet.normals.GetProperty()),6) class IndexedPolygons_Viewer_Tests2(unittest.TestCase): """ check IndexedPolygons in Viewer """ def setUp(self): self.vi = Viewer(verbose=0) points = [ [-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1], [-1, 1, -1], [-1, -1, -1] ] indices = [ [0, 1, 3, 2], [4, 5, 7, 6], [6, 7, 1, 0], [2, 3, 5, 4], [6, 0, 2, 4], [1, 7, 5, 3] ] self.geom = IndexedPolygons("box", vertices=points, faces=indices, visible=1) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.Redraw() def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass def test_Indexedpolygon_fnormals(self): """checks number of fnormals """ points = [ [-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1], [-1, 1, -1], [-1, -1, -1] ] indices = [ [0, 1, 3, 2], [4, 5, 7, 6], [6, 7, 1, 0], [2, 3, 5, 4], [6, 0, 2, 4], [1, 7, 5, 3] ] polygon = IndexedPolygons("box", vertices=points, faces=indices, visible=1, replace=True) self.vi.AddObject(polygon) #self.vi.stopAutoRedraw() self.vi.Redraw() self.assertEqual(len(polygon.faceSet.normals.GetProperty()),6) class IndexedPolygons_Viewer_Tests(unittest.TestCase): """ tests for IndexedPolygons in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) # guillaume: the faces are not correct here, but the test is usefull # because it detects if the normal provided are really used # (if it tries to calculate ---> it fails because the faces are not correct) self.geom = IndexedPolygons('poly', vertices=((0,0,0),(5.,0.,0.),(7,2.5,0.),(5,5,0),(0,5,0)), vnormals=((1.0,0,0),(0,1.,0),(1.0,0,0),(0,1.,0),(1.0,0,0)), faces=((0,1),(1,2),(2,3),(3,4),(4,0)), materials=((.5,0,0),), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGuiIndexedPolygons def test_IndexedPolygons_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Arcs 3D image def test_IndexedPolygons_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageIndexedPolygons.tif") im = Image.open("./saveimageIndexedPolygons.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) if __name__ == '__main__': test_cases = [ 'IndexedPolygons__init__Tests', 'IndexedPolygons_Set_Tests', 'IndexedPolygons_Viewer_Tests2', 'IndexedPolygons_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_CrossSet.py0000644000175000017500000001470211226703712024152 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_CrossSet.py,v 1.12 2009/07/13 19:15:22 vareille Exp $ # # from Tkinter import Menubutton import unittest import numpy import numpy.oldnumeric as Numeric from DejaVu.Viewer import Viewer from time import sleep import Image from math import sqrt from DejaVu.Points import CrossSet class CrossSet__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = [ 'offset' ] all other keywords are handled by Geom.__init__ method """ #defaults def test_CrossSet_defaults(self): """defaults for shape, radius, angles """ g = CrossSet() self.assertEqual(isinstance(g, CrossSet), True) #offset def test_CrossSet_offset(self): """offset 1 (default offset is 0.3)) """ g = CrossSet(offset=1) self.assertEqual(isinstance(g, CrossSet), True) #vertices def test_CrossSet_radius(self): """vertices """ g = CrossSet(vertices=((0,0,0),(1,1,1))) self.assertEqual(isinstance(g, CrossSet), True) class CrossSet_Set_Tests(unittest.TestCase): """ # does override Geom.Set ??? one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = CrossSet(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_CrossSet_Set_vertices(self): """ test Setting vertices """ self.geom.Set(centers=((2,0,2),(0,2,2))) #self.assertEqual(self.geom.vertexSet.vertices.array[0],((2,0,2),(0,2,2))) self.assertTrue(numpy.alltrue(self.geom.vertexSet.vertices.array[0]==(2,0,2))) def test_CrossSet_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) class CrossSet_Viewer_Tests(unittest.TestCase): """ tests for CrossSet in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.geom = CrossSet('crossset', vertices =((0,0,0),(1.,0.,0.)), materials=((.5,0,0),), offset=3.0, inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGuiCrossSet def test_CrossSet_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() #sleep(5) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "2:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Arcs 3D image def test_CrossSet_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black #sleep(5) self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageCrossSet.tif") im = Image.open("./saveimageCrossSet.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) #import pdb;pdb.set_trace() #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9 and v[0]>-1.e-9) self.assertTrue(v[1]<1.e-9 and v[1]>-1.e-9) self.assertTrue(v[2]<1.e-9 and v[2]>-1.e-9) if __name__ == '__main__': test_cases = [ 'CrossSet__init__Tests', 'CrossSet_Set_Tests', 'CrossSet_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_ColorMap.py0000644000175000017500000002334010520470640024114 0ustar debiandebian######################################################################### # # Date: May 2003 Authors: Ruth Huey, Michel Sanner # # rhuey@scripps.edu # sanner@scripps.edu # # Copyright: Michel Sanner, Ruth Huey, and TSRI # ######################################################################### # # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Tests/test_ColorMap.py,v 1.15 2006/10/27 20:52:48 vareille Exp $ # # $Id: test_ColorMap.py,v 1.15 2006/10/27 20:52:48 vareille Exp $ # # # # import sys, Tkinter import unittest from mglutil.regression import testplus from DejaVu.colorTool import RGBRamp, RedWhiteBlueRamp from DejaVu.colorMapLegend import ColorMapLegend from DejaVu.colorMap import ColorMap from DejaVu.ColormapGui import ColorMapGUI from DejaVu.Viewer import Viewer from time import sleep #add methods to test configure + write methods when updated class ColorMapTest(unittest.TestCase): def setUp(self): self.root = Tkinter.Tk() self.root.withdraw() def tearDown(self): self.root.destroy() def test_constructor(self): # test if we can build a colormap with a ramp cmapgui = ColorMapGUI(name='test',ramp=RGBRamp(), mini=0, maxi=255) self.assertEqual(cmapgui.name, 'test') self.assertEqual(len(cmapgui.ramp),256) self.assertEqual(cmapgui.mini, 0.0) self.assertEqual(cmapgui.maxi, 255) self.assertEqual(len(cmapgui.history),1) self.assertEqual(cmapgui.currentOnStack, True) def test_constructorFromFile(self): # test if we can build basic cmap from file cmapgui = ColorMapGUI(name='second',filename='./Data/test_map.py') self.assertEqual(len(cmapgui.ramp), 5) self.assertEqual(cmapgui.mini, 0.0) self.assertEqual(cmapgui.maxi, 10.0) self.assertEqual(cmapgui.name, 'second') self.assertEqual(len(cmapgui.history),1) self.assertEqual(cmapgui.currentOnStack, True) def test_configureCmap(self): cmapgui = ColorMapGUI(name='test',ramp=RGBRamp()) cmapgui.configure(name='newRamp', mini=7, maxi=53, geoms={'g1':1}) self.assertEqual(cmapgui.mini, 7) self.assertEqual(cmapgui.maxi, 53) self.assertEqual(len(cmapgui.geoms), 1) self.assertEqual(len(cmapgui.history),1) cmapgui.configure(ramp=RedWhiteBlueRamp()) self.assertEqual(len(cmapgui.history),2) self.assertEqual(cmapgui.currentOnStack,True) self.assertEqual(cmapgui.mini, 7) self.assertEqual(cmapgui.maxi, 53) def test_pushRamp(self): #import pdb;pdb.set_trace() # test if we can build a very basic cmap and push the ramp cmapgui = ColorMapGUI(name='test', ramp=RGBRamp()) cmapgui.pushRamp() # Cannot push the ramp when already on the history stack self.assertEqual(len(cmapgui.history), 1) newRamp = RedWhiteBlueRamp() cmapgui.configure(ramp=newRamp, pushRamp=False) self.assertEqual(len(cmapgui.history), 1) self.assertEqual(cmapgui.currentOnStack, False) cmapgui.pushRamp() self.assertEqual(len(cmapgui.history), 2) self.assertEqual(cmapgui.currentOnStack, True) def test_popRamp(self): # Create an cmap with no ramp cmapgui = ColorMapGUI(name='test',ramp=None) self.assertEqual(len(cmapgui.history), 1) # call popRamp when len(history) is equal to 0 cmapgui.popRamp() self.assertEqual(len(cmapgui.history), 1) # fill in the history stack with 4 more entries: newRamp = RGBRamp() for x in xrange(4): cmapgui.configure(ramp=newRamp) self.assertEqual(len(cmapgui.history), 5) # Call popRamp with the default argument index=-1 cmapgui.popRamp() self.assertEqual(len(cmapgui.history), 4) self.assertEqual(cmapgui.currentOnStack, False) # Pop all the ramp from the history stack for x in xrange(4): cmapgui.popRamp() # The first entry of the history stack is never removed. self.assertEqual(len(cmapgui.history), 1) self.assertEqual(cmapgui.currentOnStack, True) # Test popRamp with various index # 1- (-len(cmap.history)) # fill in the history stack with 5 entries: for x in xrange(5): cmapgui.configure(ramp=newRamp) # 5 new entries plus the first entry self.assertEqual(len(cmapgui.history), 6) cmapgui.popRamp(-len(cmapgui.history)) self.assertEqual(len(cmapgui.history), 1) self.assertEqual(cmapgui.currentOnStack, True) # 2- negative index which doesn't exists # fill in the history stack with 5 entries: for x in xrange(5): cmapgui.configure(ramp=newRamp) # 5 new entries plus the first entry self.assertEqual(len(cmapgui.history), 6) cmapgui.popRamp(-len(cmapgui.history)-2) self.assertEqual(len(cmapgui.history), 1) self.assertEqual(cmapgui.currentOnStack, True) # 3- negative index in the list # fill in the history stack with 5 entries: for x in xrange(5): cmapgui.configure(ramp=newRamp) # 5 new entries plus the first entry self.assertEqual(len(cmapgui.history), 6) cmapgui.popRamp(-3) self.assertEqual(len(cmapgui.history), 3) # When popping a ramp from the history the new ramp # is not pushed back on the list except the first entry which # always stays on the history stack self.assertEqual(cmapgui.currentOnStack, False) def test_CmapWithLegend(self): cmapGui = ColorMapGUI(name='test', ramp=RGBRamp()) cmapGui.legend.Set( width=10, height=1, interp=1, ) cmapGui.configure(name='newRamp', mini=7, maxi=53, geoms={'g1':1}) self.assertEqual(cmapGui.mini, 7) self.assertEqual(cmapGui.maxi, 53) self.assertEqual(len(cmapGui.geoms), 1) self.assertEqual(cmapGui.legend.mini, 7) self.assertEqual(cmapGui.legend.maxi, 53) def test_asHSV(self): cmapGui = ColorMapGUI(name='test',ramp=RGBRamp()) hsv = cmapGui.asHSV() self.assertEqual(len(hsv), len(cmapGui.ramp)) #check that hsv[0]==ToHSV(cmap.ramp[0])?? def test_reset(self): rgbramp = RGBRamp() cmapGui = ColorMapGUI(name='rgb', ramp=rgbramp) self.assertEqual(cmapGui.history[0], cmapGui.ramp) self.assertEqual(len(cmapGui.history),1) self.assertEqual(cmapGui.currentOnStack, True) rwbramp = RedWhiteBlueRamp() cmapGui.configure(name='rwb', ramp=rwbramp) self.assertEqual(len(cmapGui.history), 2) self.assertEqual(cmapGui.currentOnStack, True) self.failUnless(cmapGui.history[0] != cmapGui.ramp) cmapGui.reset() rgb = map(lambda x: x[:3], cmapGui.ramp) self.assertEqual(rgb, rgbramp.tolist()) self.assertEqual(cmapGui.currentOnStack, True) self.assertEqual(len(cmapGui.history),1) # def test_resetComp(self): # # import pdb;pdb.set_trace() # # cmapgui = ColorMapGUI(name='rgb10', filename="Data/rgb10_map.py") # rgb10 = cmapgui.ramp[:] # c2 = ColorMap(name='rgb10T', filename='Data/rgb10_transparent_map.py') # rgb10T = c2.ramp[:] # cmapgui.configure(ramp=c2.ramp[:]) # self.assertEqual(len(cmapgui.history),2) # self.assertEqual(cmapgui.currentOnStack, True) # # reset the 'Hue' component # cmapgui.resetComp('Hue') # # allways keep the first entry # self.assertEqual(len(cmapgui.history),2) # self.assertEqual(cmapgui.currentOnStack, True) # # self.assertEqual(cmapgui.ramp, rgb10T) # # # reset the "Opa" component of the rgb10T # cmapgui.resetComp('Opa') # self.assertEqual(cmapgui.ramp, rgb10) # self.assertEqual(len(cmapgui.history),2) # self.assertEqual(cmapgui.currentOnStack, True) def test_getDescr(self): rgb = RGBRamp() cmap = ColorMap(name='test', ramp=rgb, mini=0, maxi=255) cfg = cmap.getDescr() self.assertEqual(cfg['name'], 'test') self.assertEqual(cfg['mini'], 0.0) self.assertEqual(cfg['maxi'], 255.0) self.assertEqual(cfg['ramp'], cmap.ramp) def test_read(self): rgb = RGBRamp() cmapgui = ColorMapGUI(name='test', ramp=rgb) r = map(lambda x:x[:3], cmapgui.ramp) self.assertEqual(r, rgb.tolist()) self.assertEqual(cmapgui.name, 'test') self.assertEqual(len(cmapgui.history), 1) #import pdb;pdb.set_trace() cmapgui.read("Data/rgb10_map.py") self.assertEqual(cmapgui.name, 'rgb10') self.failUnless( cmapgui.ramp != rgb.tolist()) self.assertEqual(len(cmapgui.history), 2) # self.assertEqual(len(cmapgui.history), 1) # self.assertEqual(cmapgui.ramp, cmapgui.history[0]) def test_write(self): cmap = ColorMap(name='test', ramp=RGBRamp()) cmap.write('/tmp/output_map.py') cmap2 = ColorMap(name='test', filename="/tmp/output_map.py") self.assertEqual(cmap2.ramp, cmap.ramp) self.assertEqual(cmap2.name, cmap.name) import os os.system("rm -f /tmp/output_map.py") ## harness = testplus.TestHarness( __name__, ## connect = setUp, ## funs = testplus.testcollect( globals()), ## disconnect = tearDown ## ) if __name__ == '__main__': unittest.main() ## testplus.chdir() ## print harness ## sys.exit( len( harness)) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Camera.py0000644000175000017500000005665212102056213023576 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Camera.py,v 1.59 2013/01/29 23:34:35 annao Exp $ # # import sys, os, math, types import numpy from Tkinter import Tk, Toplevel import unittest,numpy.oldnumeric as Numeric from opengltk.OpenGL import GL from DejaVu.Camera import Camera from DejaVu.Viewer import Viewer from DejaVu.Spheres import Spheres from opengltk.extent.utillib import glCleanRotMat from time import sleep from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.ViewerGUI import ViewerGUI from DejaVu import viewerConst,datamodel import Image from math import sqrt from mglutil.math.rotax import rotax class Camera_BaseTests(unittest.TestCase): """ setUp + tearDown form a fixture: working environment for the testing code """ def setUp(self): """ start Viewer """ if not hasattr(self, 'vi'): self.vi = Viewer(verbose=0) self.vi.currentCamera.Set(height=500, width=500) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass def test_SaveImage(self): """test save image """ cmd = "rm -f ./saveImage.tif" os.system(cmd) s1 = Spheres('sph', vertices = [[0,0,0], [3,0,0], [0,3,0], [0,0,3]]) self.vi.AddObject(s1) cam = self.vi.currentCamera cam.SaveImage("./saveImage.tif") self.vi.Exit() self.assertEqual( os.path.exists("./saveImage.tif"), True) def test_setCamera_width(self): """test camera width """ cam = self.vi.currentCamera # set the camera width cam.Set(width=150) self.assertEqual(cam.width, 150) # ask for the window size x,y,w,h = cam.getGeometry() # make sure the window actually has the right size self.assertEqual(w, 150) self.assertEqual(cam.__class__, Camera) # make sure the camera's state reflects the change newstate = cam.getState() self.assertEqual(newstate['width'], 150) self.vi.Exit() def test_setCamera_width_invalid_input(self): """test camera width negative input """ cam = self.vi.currentCamera self.assertRaises(AttributeError,cam.Set,width=-15) def test_setCamera_width_invalid_inputFloat(self): """test camera width float input """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.Set,width=450.) def test_setCamera_fov(self): """fov has to be <180,>0 """ cam = self.vi.currentCamera cam.Set(fov=120) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['fov'], 120) def test_setCamera_fov_invalid_input(self): """fov >180, invalid input """ cam = self.vi.currentCamera self.assertRaises(AttributeError,cam.Set,fov=190) def test_setCamera_rootx(self): """test camera rootx """ cam = self.vi.currentCamera cam.Set(rootx=220) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['rootx'], 220) def test_setCamera_rootx_negative(self): """test camera rootx invalid input """ cam = self.vi.currentCamera cam.Set(rootx=-100) self.assertEqual(cam.rootx, 0) def test_setCamera_height(self): """test camera height """ cam = self.vi.currentCamera # set the camera height cam.Set(height=150) self.assertEqual(cam.height, 150) # ask for the window size x,y,w,h = cam.getGeometry() # make sure the window actually has the right size self.assertEqual(h, 150) self.assertEqual(cam.__class__, Camera) # make sure the camera's state reflects the change newstate = cam.getState() self.assertEqual(newstate['height'], 150) self.vi.Exit() def test_setCamera_height_invalid_input(self): """test camera height invalid input """ cam = self.vi.currentCamera self.assertRaises(AttributeError,cam.Set,height=-400) def test_setCamera_height_invalid_inputFloat(self): """test camera height float input """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.Set,height=450.) def test_setCamera_rooty(self): """ test camera rooty """ cam = self.vi.currentCamera cam.Set(rooty=320) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['rooty'], 320) def test_setCamera_rooty_negative(self): """test camera rooty invalid input """ cam = self.vi.currentCamera cam.Set(rooty=-100) self.assertEqual(cam.rooty, 0) def test_setCamera_near(self): """test camera near """ cam = self.vi.currentCamera cam.Set(near=10) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['near'], 10) def test_setCamera_near_invalid_input(self): """ test near should be less than far """ cam = self.vi.currentCamera cam.Set(far=20) self.assertRaises(AttributeError,cam.Set,near = 40) def test_setCamera_far(self): """test camera far """ cam = self.vi.currentCamera cam.Set(far=20) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['far'], 20) def test_setCamera_far_invalid_input(self): """test far should be larger than near """ cam = self.vi.currentCamera cam.Set(near=10) self.assertRaises(AttributeError,cam.Set,far = 5) def test_setCamera_color(self): """ test camera color """ cam = self.vi.currentCamera cam.Set(color=(1.0,1.0,1.0,1.0)) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['color'],(1.0,1.0,1.0,1.0)) def test_setCamera_color_invalid(self): """ test camera color invalid input """ cam = self.vi.currentCamera rval = cam.Set(color = (1.0,1.0,1.0)) self.assertEqual(rval,None) def test_setCamera_antialiased(self): """test antialiased """ cam = self.vi.currentCamera cam.Set(antialiased=0) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['antialiased'],0) def test_setCamera_antialiased_invalid_input(self): """test antialiased invalid input """ cam = self.vi.currentCamera self.assertRaises(ValueError,cam.Set,antialiased='hai') def test_setCamera_boundingbox_NO(self): """test camera bounding box """ cam = self.vi.currentCamera cam.Set(boundingbox=0) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['boundingbox'],0) def test_setCamera_boundingbox_invalid_input(self): """test camera bounding box invalid input """ cam = self.vi.currentCamera self.assertRaises(ValueError,cam.Set,boundingbox='hai') def test_setCamera_projection_type(self): """test camera projection type """ cam = self.vi.currentCamera cam.Set(projectionType=1) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['projectionType'],1) def test_setCamera_projection_type_invalid(self): """test camera projection type invalid """ cam = self.vi.currentCamera rval = cam.Set(projectionType='hai') self.assertEqual(rval,None) def test_setCamera_contours(self): """test camera contours """ cam = self.vi.currentCamera cam.Set(contours=True) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['contours'], True, msg="Expecting cam.contours to be set to True") def test_setCamera_stereo_mode_side_by_side(self): """test camera stereoMode """ cam = self.vi.currentCamera cam.Set(stereoMode='SIDE_BY_SIDE_CROSS') newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['stereoMode'],'SIDE_BY_SIDE_CROSS') def test_setCamera_stereo_mode_side_by_side_invalid(self): """test camera stereoMode """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.Set,stereoMode='hai') def test_setCamera_side_by_side_rot_angle(self): """test camera sideBySideRotAngle """ cam = self.vi.currentCamera cam.Set(sideBySideRotAngle=5.) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['sideBySideRotAngle'],5.) def test_setCamera_side_by_side_rot_angle_invalid(self): """test camera sideBySideRotAngle,invalid input """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.Set,sideBySideRotAngle='hai') def test_setCamera_side_by_side_translation(self): """test camera sideBySideTranslation """ cam = self.vi.currentCamera cam.Set(sideBySideTranslation=3.) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['sideBySideTranslation'],3.) def test_setCamera_side_by_side_translation_invalid(self): """test camera sideBySideTranslation,invalid input """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.Set,sideBySideTranslation='hai') def test_setCamera_pivot(self): """test camera pivot """ cam = self.vi.currentCamera mat = Numeric.reshape(Numeric.array(Numeric.ones( (3,), 'f')), (3,)).astype('f') cam.SetPivot(mat) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['pivot'],[1.0,1.0,1.0]) def test_setCamera_pivot_invalid(self): """test camera pivot,invalid input """ cam = self.vi.currentCamera self.assertRaises(ValueError,cam.SetPivot,[1.0,1.0]) def test_setCamera_scale(self): """test camera scale """ cam = self.vi.currentCamera mat = Numeric.ones( (3,), 'f') cam.SetScale(mat) newstate = cam.getState() self.vi.Exit() self.assertEqual(newstate['scale'],[1.0,1.0,1.0]) def test_setCamera_scale(self): """test camera scale """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.SetScale,([1.0,1.0])) def test_setCamera_rotation(self): """test camera rotation """ cam = self.vi.currentCamera from DejaVu.IndexedPolylines import IndexedPolylines lines=IndexedPolylines('mylines',materials=((0,1,0),)) self.vi.AddObject(lines) lines.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),)) ## from mglutil.math.rotax import rotax ## import math ## matRot = rotax( (0,0,0), (0,0,1), math.pi/2.) ## cam.Set(rotation=matRot) ## self.vi.Redraw() ## newstate = cam.getState() ## self.vi.Exit() ## lTestedValues = [0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1] ## for i in range(16): ## self.assertTrue( newstate['rotation'][i] < lTestedValues[i] + 1.e9) ## self.assertTrue( newstate['rotation'][i] > lTestedValues[i] - 1.e9) lf1 = numpy.array([-20, 20, 0],'f') cam.Set(lookFrom = lf1) self.vi.Redraw() lf2 = cam.lookFrom self.assertTrue(numpy.alltrue(lf1==lf2), True) self.vi.Exit() ## def test_setCamera_rotation_invalid_input(self): ## """test camera rotation,invalid input ## """ ## cam = self.vi.currentCamera ## from DejaVu.IndexedPolylines import IndexedPolylines ## lines=IndexedPolylines('mylines',materials=((0,1,0),)) ## self.vi.AddObject(lines) ## lines.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),)) ## self.assertRaises(ValueError,cam.Set,rotation=[1.0,1.0]) def test_setCamera_lookat(self): """test camera look at """ cam = self.vi.currentCamera mat = Numeric.reshape(Numeric.array(Numeric.ones(3)), (3,)).astype('f') cam.Set(lookAt=mat) #self.assertEqual(cam.lookAt,mat) self.assertTrue(numpy.alltrue(cam.lookAt == mat)) self.vi.Exit() def test_setCamera_lookat_invalid(self): """test camera look at,invalid input """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.Set,lookAt = [1.0,1.0]) def test_setCamera_lookFrom(self): """test camera look from """ cam = self.vi.currentCamera mat = Numeric.reshape(Numeric.array(Numeric.ones(3)), (3,)).astype('f') cam.Set(lookFrom=mat) #self.assertEqual(cam.lookFrom,mat) self.assertTrue(numpy.alltrue(cam.lookFrom == mat)) self.vi.Exit() def test_setCamera_lookFrom_invalid(self): """test camera look from,invalid input """ cam = self.vi.currentCamera self.assertRaises(AssertionError,cam.Set,lookFrom = [1.0,1.0]) def test_setCamera_direction(self): """test camera direction """ cam = self.vi.currentCamera mat = Numeric.reshape(Numeric.array(Numeric.ones(3)), (3,)).astype('f') mat1 = Numeric.reshape(Numeric.array(Numeric.zeros(3)), (3,)).astype('f') cam.Set(lookAt=mat,lookFrom=mat1) #self.assertEqual(cam.direction,cam.lookAt - cam.lookFrom) self.assertTrue(numpy.alltrue(cam.direction == (cam.lookAt - cam.lookFrom))) self.vi.Exit() def test_setCamera_direction_invalid(self): """test camera direction,invalid input """ cam = self.vi.currentCamera self.assertRaises(ValueError,cam.Set,direction = [1.0,1.0]) def test_setCamera_translation(self): """test setCamera_translation """ cam = self.vi.currentCamera from DejaVu.IndexedPolylines import IndexedPolylines lines=IndexedPolylines('mylines',materials=((0,1,0),)) self.vi.AddObject(lines) lines.Set(vertices =[[1,0,1],[1,1,1]],faces=((0,1),)) #cam.Set(translation=Numeric.ones(3, 'f')) cam.SetTranslation(Numeric.ones(3, 'f')) self.vi.OneRedraw() self.vi.update() newstate = cam.getState() self.vi.Exit() #self.assertEqual(newstate['translation'],Numeric.ones(3)) for v in newstate['translation']: self.assertTrue(v < 1. + 1.e-9) self.assertTrue(v > 1. - 1.e-9) def test_setCamera_translation_invalid(self): """test camera translation,invalid input """ cam = self.vi.currentCamera from DejaVu.IndexedPolylines import IndexedPolylines lines=IndexedPolylines('mylines',materials=((0,1,0),)) self.vi.AddObject(lines) lines.Set(vertices =[[1,0,1],[1,1,1]],faces=((0,1),)) self.assertRaises(AttributeError,cam.SetTranslation,[1.0,1.0]) def test_setCamera_rotation_lines(self): """test camera set rotation """ #apply(self.vi.AddCamera, (self.master, None, Camera,), {}) cam = self.vi.currentCamera from DejaVu.IndexedPolylines import IndexedPolylines lines=IndexedPolylines('mylines',materials=((0,1,0),)) self.vi.AddObject(lines) lines.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),)) self.vi.OneRedraw() array1=cam.GrabFrontBufferAsArray() ## matRot = rotax( (0,0,0), (0,0,1), math.pi*.5) ## cam.Set(rotation=matRot) cam.Set(lookFrom = numpy.array([-20, 20, 0],'f')) self.vi.OneRedraw() array2=cam.GrabFrontBufferAsArray() array1.shape = (500, 500, 3) array2.shape = (500, 500, 3) #print "array1[249][250]", array1[249][250] #print "array1[250][251]", array1[250][251] #print "array2[249][250]", array2[249][250] #print "array2[250][251]", array2[250][251] d=array1-array2 error=Numeric.add.reduce(d) self.vi.Exit() #self.assertEqual(error!=0, True) self.assertEqual(error.max()>1.e-9, True) def test_setCamera_image(self): """test setCamera_image """ cam = self.vi.currentCamera from DejaVu.IndexedPolylines import IndexedPolylines lines=IndexedPolylines('mylines',materials=((0,1,0),)) self.vi.AddObject(lines) lines.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),)) self.vi.OneRedraw() cam.SaveImage("./saveimage1.tif") #matRot = rotax( (0,0,0), (0,0,1), math.pi*.5) #cam.Set(rotation=matRot) cam.Set(lookFrom = [-20, 20, 0]) self.vi.OneRedraw() cam.SaveImage("./saveimage2.tif") fptr=open("./saveimage1.tif") alllines=fptr.readlines() fptr1=open("./saveimage2.tif") alllines1=fptr1.readlines() self.vi.Exit() self.assertEqual(alllines==alllines1,False) #methods def test_orthogonal_to_perspective(self): """test_orthogonal_to_perspective """ cam = self.vi.currentCamera points = [ [-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1], [-1, 1, -1], [-1, -1, -1] ] indices = [ [0, 1, 3, 2], [4, 5, 7, 6], [6, 7, 1, 0], [2, 3, 5, 4], [6, 0, 2, 4], [1, 7, 5, 3] ] geomBox = IndexedPolygons("box", vertices=points, faces=indices, visible=1) self.vi.AddObject(geomBox) self.vi.OneRedraw() self.vi.update() #sleep(5) array1 = cam.GrabFrontBufferAsArray() sum1 = Numeric.add.reduce(array1) #print sum1 cam.Set(projectionType=1) #cam.OrthogonalToPerspective() self.vi.OneRedraw() self.vi.update() array2 = cam.GrabFrontBufferAsArray() sum2 = Numeric.add.reduce(array2) #print sum2 cam.Set(projectionType=0) #cam.PerspectiveToOrthogonal() self.vi.OneRedraw() self.vi.update() array3 = cam.GrabFrontBufferAsArray() sum3 = Numeric.add.reduce(array3) #print sum3 self.vi.Exit() self.assertEqual(sum1,sum3) def test_SaveImage(self): """test_Images """ cam = self.vi.currentCamera sph = Spheres("sp", centers=( (0,0,0),), radii = (1,),) self.vi.AddObject(sph) self.vi.OneRedraw() self.vi.update() import time time.sleep(1) buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = sqrt(total_pixels) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(buff_255[midpt][midpt][0]>0.1, True) buff_255_sum=Numeric.add.reduce(buff_255) cam.SaveImage("./saveimagesph.tif") im = Image.open("./saveimagesph.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum=Numeric.add.reduce(narray_255) #print sum d=buff_255_sum-narray_255_sum self.vi.Exit() #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) def test_DoPick(self): cam = self.vi.currentCamera cam.Redraw() sph = Spheres("sp", centers=( (0,0,0),), radii = (10,),) self.vi.AddObject(sph) pick = cam.DoPick(250,250) self.assertEqual(str(pick.hits),'{ sp with 1 vertices: [(0, [0, 0])]}') # def DrawPickingSphere(self): # cam = self.vi.currentCamera # from DejaVu.IndexedPolylines import IndexedPolylines # lines=IndexedPolylines('mylines',materials=((0,1,0),)) # self.vi.AddObject(lines) # lines.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),)) # p = cam.DoPick(250,250) # cam.DrawPickingSphere(p) # self.assertEqual(len(self.vi.pickVerticesSpheres.vertexSet),1) def test_CameraSize(self): import numpy.oldnumeric as Numeric from opengltk.OpenGL import GL from DejaVu import Viewer from DejaVu.Cylinders import CylinderArrows coordSyst = CylinderArrows('coordSystem', vertices=([0,0,0], [10,0,0],[0,10,0],[0,0,10]), faces = ([0,1], [0,2], [0,3]), materials = ((1.,0,0), (0,1,0), (0,0,1)), radii = 0.6, inheritMaterial=False, inheritCulling=False, backPolyMode=GL.GL_FILL, inheritBackPolyMode=False, quality=10) coordSyst.Set(culling=GL.GL_NONE) self.vi.AddObject(coordSyst, parent=self.vi.FindObjectByName('root')) c1 = self.vi.AddCamera() c0 = self.vi.cameras[0] c0.Activate() m0 = Numeric.array(GL.glGetDoublev(GL.GL_PROJECTION_MATRIX)).astype('f') c1.Activate() self.vi.update() m1 = Numeric.array(GL.glGetDoublev(GL.GL_PROJECTION_MATRIX)).astype('f') c1.Set(width=600) c1.Redraw() c1.Activate() self.vi.update() m11 = Numeric.array(GL.glGetDoublev(GL.GL_PROJECTION_MATRIX)).astype('f') c0.Activate() self.vi.update() #self.vi.DeleteCamera(c1) assert Numeric.sum(m1-m11)>0.0001 def test_CameraNpr(self): from opengltk.OpenGL import GL from DejaVu.Cylinders import CylinderArrows coordSyst = CylinderArrows('coordSystem', vertices=([0,0,0], [10,0,0],[0,10,0],[0,0,10]), faces = ([0,1], [0,2], [0,3]), materials = ((1.,0,0), (0,1,0), (0,0,1)), radii = 0.6, inheritMaterial=False, inheritCulling=False, backPolyMode=GL.GL_FILL, inheritBackPolyMode=False, quality=10) coordSyst.Set(culling=GL.GL_NONE) self.vi.AddObject(coordSyst, parent=self.vi.FindObjectByName('root')) self.vi.GUI.contourTk.set(True) self.vi.currentCamera.Set(contours=True, tagModified=False) self.vi.currentCamera.Redraw() self.vi.update() lArray=self.vi.currentCamera.GrabFrontBufferAsArray() lSum = numpy.add.reduce(lArray) print "lSum:", lSum lSumList = [180897624, #rapa 175905763, #austral 180891495, #jacob 180898731, #mslaptop4 175912068, #mslaptop1 ] self.assertTrue( lSum in lSumList, msg='test_CameraNpr lSum: %d'%lSum) if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/Data/0000755000175000017500000000000012146207760021645 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/Data/rgb10_transparent_map.py0000644000175000017500000005077410651433502026417 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by from DejaVu.colorMap import ColorMap from numpy.oldnumeric import array cm = ColorMap('cmap') cfg = {'mini': 0.0, 'maxi': 10.0, 'ramp': array([[ 4.58000024e-04, 0.00000000e+00, 2.29000002e-01, 1.00000000e+00], [ 4.68000013e-04, 0.00000000e+00, 2.33999997e-01, 1.00000000e+00], [ 4.80000017e-04, 0.00000000e+00, 2.39999995e-01, 1.00000000e+00], [ 4.80000017e-04, 0.00000000e+00, 2.39999995e-01, 1.00000000e+00], [ 4.92000021e-04, 0.00000000e+00, 2.46000007e-01, 1.00000000e+00], [ 5.02000039e-04, 0.00000000e+00, 2.50999987e-01, 1.00000000e+00], [ 5.14000014e-04, 0.00000000e+00, 2.56999999e-01, 1.00000000e+00], [ 5.14000014e-04, 0.00000000e+00, 2.56999999e-01, 1.00000000e+00], [ 5.26000047e-04, 0.00000000e+00, 2.63000011e-01, 1.00000000e+00], [ 5.38000022e-04, 0.00000000e+00, 2.68999994e-01, 1.00000000e+00], [ 5.38000022e-04, 0.00000000e+00, 2.68999994e-01, 1.00000000e+00], [ 5.48000040e-04, 0.00000000e+00, 2.73999989e-01, 1.00000000e+00], [ 5.60000015e-04, 0.00000000e+00, 2.80000001e-01, 1.00000000e+00], [ 5.60000015e-04, 0.00000000e+00, 2.80000001e-01, 1.00000000e+00], [ 5.72000048e-04, 0.00000000e+00, 2.86000013e-01, 1.00000000e+00], [ 5.72000048e-04, 0.00000000e+00, 2.86000013e-01, 1.00000000e+00], [ 5.82000008e-04, 0.00000000e+00, 2.91000009e-01, 1.00000000e+00], [ 5.82000008e-04, 0.00000000e+00, 2.91000009e-01, 1.00000000e+00], [ 5.94000041e-04, 0.00000000e+00, 2.96999991e-01, 1.00000000e+00], [ 5.94000041e-04, 0.00000000e+00, 2.96999991e-01, 1.00000000e+00], [ 6.06000016e-04, 0.00000000e+00, 3.03000003e-01, 1.00000000e+00], [ 6.06000016e-04, 0.00000000e+00, 3.03000003e-01, 1.00000000e+00], [ 6.18000049e-04, 0.00000000e+00, 3.08999985e-01, 1.00000000e+00], [ 6.28000009e-04, 0.00000000e+00, 3.14000010e-01, 1.00000000e+00], [ 6.40000042e-04, 0.00000000e+00, 3.19999993e-01, 1.00000000e+00], [ 0.00000000e+00, 1.44091994e-01, 3.26000005e-01, 1.00000000e+00], [ 0.00000000e+00, 1.46302000e-01, 3.31000000e-01, 1.00000000e+00], [ 0.00000000e+00, 1.46302000e-01, 3.31000000e-01, 1.00000000e+00], [ 0.00000000e+00, 1.46302000e-01, 3.31000000e-01, 1.00000000e+00], [ 0.00000000e+00, 1.48954004e-01, 3.37000012e-01, 1.00000000e+00], [ 0.00000000e+00, 1.48954004e-01, 3.37000012e-01, 1.00000000e+00], [ 0.00000000e+00, 1.48954004e-01, 3.37000012e-01, 1.00000000e+00], [ 0.00000000e+00, 1.51605994e-01, 3.42999995e-01, 1.00000000e+00], [ 0.00000000e+00, 1.51605994e-01, 3.42999995e-01, 1.00000000e+00], [ 0.00000000e+00, 1.54257998e-01, 3.49000007e-01, 1.00000000e+00], [ 0.00000000e+00, 1.54257998e-01, 3.49000007e-01, 1.00000000e+00], [ 0.00000000e+00, 1.56468004e-01, 3.54000002e-01, 1.00000000e+00], [ 0.00000000e+00, 1.56468004e-01, 3.54000002e-01, 1.00000000e+00], [ 0.00000000e+00, 1.59119993e-01, 3.60000014e-01, 1.00000000e+00], [ 0.00000000e+00, 1.59119993e-01, 3.60000014e-01, 1.00000000e+00], [ 0.00000000e+00, 1.61771998e-01, 3.65999997e-01, 1.00000000e+00], [ 0.00000000e+00, 1.61771998e-01, 3.65999997e-01, 1.00000000e+00], [ 0.00000000e+00, 1.63982004e-01, 3.70999992e-01, 1.00000000e+00], [ 0.00000000e+00, 1.63982004e-01, 3.70999992e-01, 1.00000000e+00], [ 0.00000000e+00, 1.66633993e-01, 3.77000004e-01, 1.00000000e+00], [ 0.00000000e+00, 1.66633993e-01, 3.77000004e-01, 1.00000000e+00], [ 0.00000000e+00, 1.69285998e-01, 3.82999986e-01, 1.00000000e+00], [ 0.00000000e+00, 1.69285998e-01, 3.82999986e-01, 1.00000000e+00], [ 0.00000000e+00, 1.71938002e-01, 3.88999999e-01, 1.00000000e+00], [ 0.00000000e+00, 1.71938002e-01, 3.88999999e-01, 1.00000000e+00], [ 0.00000000e+00, 1.74147993e-01, 3.93999994e-01, 1.00000000e+00], [ 0.00000000e+00, 3.51999998e-01, 4.00000006e-01, 1.00000000e+00], [ 0.00000000e+00, 3.51999998e-01, 4.00000006e-01, 1.00000000e+00], [ 0.00000000e+00, 3.57279986e-01, 4.05999988e-01, 1.00000000e+00], [ 0.00000000e+00, 3.61680001e-01, 4.11000013e-01, 1.00000000e+00], [ 0.00000000e+00, 3.61680001e-01, 4.11000013e-01, 1.00000000e+00], [ 0.00000000e+00, 3.61680001e-01, 4.11000013e-01, 1.00000000e+00], [ 0.00000000e+00, 3.66959989e-01, 4.16999996e-01, 1.00000000e+00], [ 0.00000000e+00, 3.66959989e-01, 4.16999996e-01, 1.00000000e+00], [ 0.00000000e+00, 3.66959989e-01, 4.16999996e-01, 1.00000000e+00], [ 0.00000000e+00, 3.72240007e-01, 4.23000008e-01, 1.00000000e+00], [ 0.00000000e+00, 3.72240007e-01, 4.23000008e-01, 1.00000000e+00], [ 0.00000000e+00, 3.77519995e-01, 4.28999990e-01, 1.00000000e+00], [ 0.00000000e+00, 3.77519995e-01, 4.28999990e-01, 1.00000000e+00], [ 0.00000000e+00, 3.77519995e-01, 4.28999990e-01, 1.00000000e+00], [ 0.00000000e+00, 3.81920010e-01, 4.33999985e-01, 1.00000000e+00], [ 0.00000000e+00, 3.81920010e-01, 4.33999985e-01, 1.00000000e+00], [ 0.00000000e+00, 3.81920010e-01, 4.33999985e-01, 1.00000000e+00], [ 0.00000000e+00, 3.87199998e-01, 4.39999998e-01, 1.00000000e+00], [ 0.00000000e+00, 3.87199998e-01, 4.39999998e-01, 1.00000000e+00], [ 0.00000000e+00, 3.92479986e-01, 4.46000010e-01, 1.00000000e+00], [ 0.00000000e+00, 3.92479986e-01, 4.46000010e-01, 1.00000000e+00], [ 0.00000000e+00, 3.96880001e-01, 4.51000005e-01, 1.00000000e+00], [ 0.00000000e+00, 3.96880001e-01, 4.51000005e-01, 1.00000000e+00], [ 0.00000000e+00, 4.02159989e-01, 4.56999987e-01, 1.00000000e+00], [ 0.00000000e+00, 4.07440007e-01, 4.63000000e-01, 1.00000000e+00], [ 0.00000000e+00, 4.63000000e-01, 3.15765977e-01, 1.00000000e+00], [ 0.00000000e+00, 4.69000012e-01, 3.19857985e-01, 1.00000000e+00], [ 0.00000000e+00, 4.74000007e-01, 3.23267996e-01, 1.00000000e+00], [ 0.00000000e+00, 4.74000007e-01, 3.23267996e-01, 1.00000000e+00], [ 0.00000000e+00, 4.74000007e-01, 3.23267996e-01, 1.00000000e+00], [ 0.00000000e+00, 4.79999989e-01, 3.27360004e-01, 1.00000000e+00], [ 0.00000000e+00, 4.79999989e-01, 3.27360004e-01, 1.00000000e+00], [ 0.00000000e+00, 4.79999989e-01, 3.27360004e-01, 1.00000000e+00], [ 0.00000000e+00, 4.86000001e-01, 3.31451982e-01, 1.00000000e+00], [ 0.00000000e+00, 4.90999997e-01, 3.34861994e-01, 1.00000000e+00], [ 0.00000000e+00, 4.97000009e-01, 3.38954002e-01, 1.00000000e+00], [ 0.00000000e+00, 5.03000021e-01, 3.43045980e-01, 1.00000000e+00], [ 0.00000000e+00, 5.09000003e-01, 3.47137988e-01, 1.00000000e+00], [ 0.00000000e+00, 5.09000003e-01, 3.47137988e-01, 1.00000000e+00], [ 0.00000000e+00, 5.13999999e-01, 3.50547999e-01, 1.00000000e+00], [ 0.00000000e+00, 5.13999999e-01, 3.50547999e-01, 1.00000000e+00], [ 0.00000000e+00, 5.19999981e-01, 3.54639977e-01, 1.00000000e+00], [ 0.00000000e+00, 5.19999981e-01, 3.54639977e-01, 1.00000000e+00], [ 0.00000000e+00, 5.26000023e-01, 3.58731985e-01, 1.00000000e+00], [ 0.00000000e+00, 5.31000018e-01, 3.62141997e-01, 1.00000000e+00], [ 0.00000000e+00, 5.31000018e-01, 3.62141997e-01, 1.00000000e+00], [ 0.00000000e+00, 5.37000000e-01, 3.66234004e-01, 1.00000000e+00], [ 0.00000000e+00, 5.37000000e-01, 3.66234004e-01, 1.00000000e+00], [ 0.00000000e+00, 5.42999983e-01, 3.70325983e-01, 1.00000000e+00], [ 0.00000000e+00, 5.49000025e-01, 3.74417961e-01, 1.00000000e+00], [ 0.00000000e+00, 5.54000020e-01, 3.77828002e-01, 1.00000000e+00], [ 0.00000000e+00, 5.60000002e-01, 1.33280009e-01, 1.00000000e+00], [ 0.00000000e+00, 5.65999985e-01, 1.34708002e-01, 1.00000000e+00], [ 0.00000000e+00, 5.70999980e-01, 1.35898009e-01, 1.00000000e+00], [ 0.00000000e+00, 5.70999980e-01, 1.35898009e-01, 1.00000000e+00], [ 0.00000000e+00, 5.77000022e-01, 1.37326002e-01, 1.00000000e+00], [ 0.00000000e+00, 5.83000004e-01, 1.38754010e-01, 1.00000000e+00], [ 0.00000000e+00, 5.83000004e-01, 1.38754010e-01, 1.00000000e+00], [ 0.00000000e+00, 5.88999987e-01, 1.40182003e-01, 1.00000000e+00], [ 0.00000000e+00, 5.93999982e-01, 1.41372010e-01, 1.00000000e+00], [ 0.00000000e+00, 5.93999982e-01, 1.41372010e-01, 1.00000000e+00], [ 0.00000000e+00, 5.93999982e-01, 1.41372010e-01, 1.00000000e+00], [ 0.00000000e+00, 6.00000024e-01, 1.42800003e-01, 1.00000000e+00], [ 0.00000000e+00, 6.00000024e-01, 1.42800003e-01, 1.00000000e+00], [ 0.00000000e+00, 6.00000024e-01, 1.42800003e-01, 1.00000000e+00], [ 0.00000000e+00, 6.06000006e-01, 1.44227996e-01, 1.00000000e+00], [ 0.00000000e+00, 6.11000001e-01, 1.45418003e-01, 1.00000000e+00], [ 0.00000000e+00, 6.16999984e-01, 1.46845996e-01, 1.00000000e+00], [ 0.00000000e+00, 6.23000026e-01, 1.48274004e-01, 1.00000000e+00], [ 0.00000000e+00, 6.29000008e-01, 1.49701998e-01, 1.00000000e+00], [ 0.00000000e+00, 6.29000008e-01, 1.49701998e-01, 1.00000000e+00], [ 0.00000000e+00, 6.34000003e-01, 1.50892004e-01, 1.00000000e+00], [ 0.00000000e+00, 6.39999986e-01, 1.52319998e-01, 1.00000000e+00], [ 0.00000000e+00, 6.39999986e-01, 1.52319998e-01, 1.00000000e+00], [ 0.00000000e+00, 6.46000028e-01, 1.53748006e-01, 1.00000000e+00], [ 0.00000000e+00, 6.51000023e-01, 1.54937997e-01, 1.00000000e+00], [ 0.00000000e+00, 6.51000023e-01, 1.54937997e-01, 1.00000000e+00], [ 1.31400004e-01, 6.57000005e-01, 0.00000000e+00, 1.00000000e+00], [ 1.32599995e-01, 6.62999988e-01, 0.00000000e+00, 1.00000000e+00], [ 1.32599995e-01, 6.62999988e-01, 0.00000000e+00, 1.00000000e+00], [ 1.33800000e-01, 6.69000030e-01, 0.00000000e+00, 1.00000000e+00], [ 1.34800002e-01, 6.74000025e-01, 0.00000000e+00, 1.00000000e+00], [ 1.34800002e-01, 6.74000025e-01, 0.00000000e+00, 1.00000000e+00], [ 1.36000007e-01, 6.80000007e-01, 0.00000000e+00, 1.00000000e+00], [ 1.36000007e-01, 6.80000007e-01, 0.00000000e+00, 1.00000000e+00], [ 1.37199998e-01, 6.85999990e-01, 0.00000000e+00, 1.00000000e+00], [ 1.38200000e-01, 6.90999985e-01, 0.00000000e+00, 1.00000000e+00], [ 1.38200000e-01, 6.90999985e-01, 0.00000000e+00, 1.00000000e+00], [ 1.39400005e-01, 6.97000027e-01, 0.00000000e+00, 1.00000000e+00], [ 1.40599996e-01, 7.03000009e-01, 0.00000000e+00, 1.00000000e+00], [ 1.41800001e-01, 7.08999991e-01, 0.00000000e+00, 1.00000000e+00], [ 1.42800003e-01, 7.13999987e-01, 0.00000000e+00, 1.00000000e+00], [ 1.44000009e-01, 7.20000029e-01, 0.00000000e+00, 1.00000000e+00], [ 1.45199999e-01, 7.26000011e-01, 0.00000000e+00, 1.00000000e+00], [ 1.45199999e-01, 7.26000011e-01, 0.00000000e+00, 1.00000000e+00], [ 1.45199999e-01, 7.26000011e-01, 0.00000000e+00, 1.00000000e+00], [ 1.46200001e-01, 7.31000006e-01, 0.00000000e+00, 1.00000000e+00], [ 1.46200001e-01, 7.31000006e-01, 0.00000000e+00, 1.00000000e+00], [ 1.46200001e-01, 7.31000006e-01, 0.00000000e+00, 1.00000000e+00], [ 1.47400007e-01, 7.36999989e-01, 0.00000000e+00, 1.00000000e+00], [ 1.48599997e-01, 7.42999971e-01, 0.00000000e+00, 1.00000000e+00], [ 1.49800003e-01, 7.49000013e-01, 0.00000000e+00, 1.00000000e+00], [ 4.81052011e-01, 7.54000008e-01, 0.00000000e+00, 1.00000000e+00], [ 4.84880000e-01, 7.59999990e-01, 0.00000000e+00, 1.00000000e+00], [ 4.84880000e-01, 7.59999990e-01, 0.00000000e+00, 1.00000000e+00], [ 4.88708049e-01, 7.65999973e-01, 0.00000000e+00, 1.00000000e+00], [ 4.88708019e-01, 7.65999973e-01, 0.00000000e+00, 1.00000000e+00], [ 4.91898000e-01, 7.71000028e-01, 0.00000000e+00, 1.00000000e+00], [ 4.95726019e-01, 7.77000010e-01, 0.00000000e+00, 1.00000000e+00], [ 4.95726019e-01, 7.77000010e-01, 0.00000000e+00, 1.00000000e+00], [ 4.99554008e-01, 7.82999992e-01, 0.00000000e+00, 1.00000000e+00], [ 5.03382027e-01, 7.88999975e-01, 0.00000000e+00, 1.00000000e+00], [ 5.03382027e-01, 7.88999975e-01, 0.00000000e+00, 1.00000000e+00], [ 5.06572008e-01, 7.94000030e-01, 0.00000000e+00, 1.00000000e+00], [ 5.06572008e-01, 7.94000030e-01, 0.00000000e+00, 1.00000000e+00], [ 5.10399997e-01, 8.00000012e-01, 0.00000000e+00, 1.00000000e+00], [ 5.14227986e-01, 8.05999994e-01, 0.00000000e+00, 1.00000000e+00], [ 5.14227986e-01, 8.05999994e-01, 0.00000000e+00, 1.00000000e+00], [ 5.17418027e-01, 8.10999990e-01, 0.00000000e+00, 1.00000000e+00], [ 5.21246016e-01, 8.16999972e-01, 0.00000000e+00, 1.00000000e+00], [ 5.21246016e-01, 8.16999972e-01, 0.00000000e+00, 1.00000000e+00], [ 5.25074005e-01, 8.23000014e-01, 0.00000000e+00, 1.00000000e+00], [ 5.28901994e-01, 8.28999996e-01, 0.00000000e+00, 1.00000000e+00], [ 5.32092035e-01, 8.33999991e-01, 0.00000000e+00, 1.00000000e+00], [ 5.35920024e-01, 8.39999974e-01, 0.00000000e+00, 1.00000000e+00], [ 5.39748013e-01, 8.46000016e-01, 0.00000000e+00, 1.00000000e+00], [ 5.39748013e-01, 8.46000016e-01, 0.00000000e+00, 1.00000000e+00], [ 5.42937994e-01, 8.51000011e-01, 0.00000000e+00, 1.00000000e+00], [ 8.51000011e-01, 7.81217992e-01, 0.00000000e+00, 1.00000000e+00], [ 8.56999993e-01, 7.86725998e-01, 0.00000000e+00, 1.00000000e+00], [ 8.56999993e-01, 7.86725998e-01, 0.00000000e+00, 1.00000000e+00], [ 8.62999976e-01, 7.92234004e-01, 0.00000000e+00, 1.00000000e+00], [ 8.62999976e-01, 7.92234004e-01, 0.00000000e+00, 1.00000000e+00], [ 8.69000018e-01, 7.97742009e-01, 0.00000000e+00, 1.00000000e+00], [ 8.69000018e-01, 7.97742009e-01, 0.00000000e+00, 1.00000000e+00], [ 8.74000013e-01, 8.02331984e-01, 0.00000000e+00, 1.00000000e+00], [ 8.79999995e-01, 8.07839990e-01, 0.00000000e+00, 1.00000000e+00], [ 8.85999978e-01, 8.13347995e-01, 0.00000000e+00, 1.00000000e+00], [ 8.90999973e-01, 8.17937970e-01, 0.00000000e+00, 1.00000000e+00], [ 8.97000015e-01, 8.23445976e-01, 0.00000000e+00, 1.00000000e+00], [ 8.97000015e-01, 8.23445976e-01, 0.00000000e+00, 1.00000000e+00], [ 9.02999997e-01, 8.28953981e-01, 0.00000000e+00, 1.00000000e+00], [ 9.02999997e-01, 8.28953981e-01, 0.00000000e+00, 1.00000000e+00], [ 9.02999997e-01, 8.28953981e-01, 0.00000000e+00, 1.00000000e+00], [ 9.02999997e-01, 8.28953981e-01, 0.00000000e+00, 1.00000000e+00], [ 9.08999979e-01, 8.34461987e-01, 0.00000000e+00, 1.00000000e+00], [ 9.08999979e-01, 8.34461987e-01, 0.00000000e+00, 1.00000000e+00], [ 9.13999975e-01, 8.39051962e-01, 0.00000000e+00, 1.00000000e+00], [ 9.13999975e-01, 8.39051962e-01, 0.00000000e+00, 1.00000000e+00], [ 9.20000017e-01, 8.44559968e-01, 0.00000000e+00, 1.00000000e+00], [ 9.25999999e-01, 8.50067973e-01, 0.00000000e+00, 1.00000000e+00], [ 9.25999999e-01, 8.50067973e-01, 0.00000000e+00, 1.00000000e+00], [ 9.30999994e-01, 8.54658008e-01, 0.00000000e+00, 1.00000000e+00], [ 9.30999994e-01, 4.46879983e-01, 0.00000000e+00, 1.00000000e+00], [ 9.30999994e-01, 4.46879983e-01, 0.00000000e+00, 1.00000000e+00], [ 9.36999977e-01, 4.49759990e-01, 0.00000000e+00, 1.00000000e+00], [ 9.43000019e-01, 4.52639997e-01, 0.00000000e+00, 1.00000000e+00], [ 9.43000019e-01, 4.52639997e-01, 0.00000000e+00, 1.00000000e+00], [ 9.43000019e-01, 4.52639997e-01, 0.00000000e+00, 1.00000000e+00], [ 9.49000001e-01, 4.55520004e-01, 0.00000000e+00, 1.00000000e+00], [ 9.49000001e-01, 4.55520004e-01, 0.00000000e+00, 1.00000000e+00], [ 9.53999996e-01, 4.57919985e-01, 0.00000000e+00, 1.00000000e+00], [ 9.53999996e-01, 4.57919985e-01, 0.00000000e+00, 1.00000000e+00], [ 9.59999979e-01, 4.60799992e-01, 0.00000000e+00, 1.00000000e+00], [ 9.59999979e-01, 4.60799992e-01, 0.00000000e+00, 1.00000000e+00], [ 9.59999979e-01, 4.60799992e-01, 0.00000000e+00, 1.00000000e+00], [ 9.66000021e-01, 4.63679999e-01, 0.00000000e+00, 1.00000000e+00], [ 9.71000016e-01, 4.66079980e-01, 0.00000000e+00, 1.00000000e+00], [ 9.71000016e-01, 4.66079980e-01, 0.00000000e+00, 1.00000000e+00], [ 9.76999998e-01, 4.68959987e-01, 0.00000000e+00, 1.00000000e+00], [ 9.82999980e-01, 4.71839994e-01, 0.00000000e+00, 1.00000000e+00], [ 9.82999980e-01, 4.71839994e-01, 0.00000000e+00, 1.00000000e+00], [ 9.89000022e-01, 4.74720001e-01, 0.00000000e+00, 1.00000000e+00], [ 9.94000018e-01, 4.77119982e-01, 0.00000000e+00, 1.00000000e+00], [ 9.94000018e-01, 4.77119982e-01, 0.00000000e+00, 1.00000000e+00], [ 9.94000018e-01, 4.77119982e-01, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.79999989e-01, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.79999989e-01, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.79999989e-01, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00], [ 1.00000000e+00, 4.19999994e-02, 0.00000000e+00, 1.00000000e+00]],'f'), 'name': 'cmap'} apply( cm.configure, (), cfg) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/Data/rgb128_map.py0000644000175000017500000000660410651433502024061 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by from DejaVu.colorMap import ColorMap from numpy.oldnumeric import array cm = ColorMap('rgb128') cfg = {'name': 'rgb128', 'ramp': [[0.0, 0.0, 1.0, 1.0], [0.0, 0.03125, 1.0, 1.0], [0.0, 0.0625, 1.0, 1.0], [0.0, 0.09375, 1.0, 1.0], [0.0, 0.125, 1.0, 1.0], [0.0, 0.15625, 1.0, 1.0], [0.0, 0.1875, 1.0, 1.0], [0.0, 0.21875, 1.0, 1.0], [0.0, 0.25, 1.0, 1.0], [0.0, 0.28125, 1.0, 1.0], [0.0, 0.3125, 1.0, 1.0], [0.0, 0.34375, 1.0, 1.0], [0.0, 0.375, 1.0, 1.0], [0.0, 0.40625, 1.0, 1.0], [0.0, 0.4375, 1.0, 1.0], [0.0, 0.46875, 1.0, 1.0], [0.0, 0.5, 1.0, 1.0], [0.0, 0.53125, 1.0, 1.0], [0.0, 0.5625, 1.0, 1.0], [0.0, 0.59375, 1.0, 1.0], [0.0, 0.625, 1.0, 1.0], [0.0, 0.65625, 1.0, 1.0], [0.0, 0.6875, 1.0, 1.0], [0.0, 0.71875, 1.0, 1.0], [0.0, 0.75, 1.0, 1.0], [0.0, 0.78125, 1.0, 1.0], [0.0, 0.8125, 1.0, 1.0], [0.0, 0.84375, 1.0, 1.0], [0.0, 0.875, 1.0, 1.0], [0.0, 0.90625, 1.0, 1.0], [0.0, 0.9375, 1.0, 1.0], [0.0, 0.96875, 1.0, 1.0], [0.0, 1.0, 1.0, 1.0], [0.0, 1.0, 0.96875, 1.0], [0.0, 1.0, 0.9375, 1.0], [0.0, 1.0, 0.90625, 1.0], [0.0, 1.0, 0.875, 1.0], [0.0, 1.0, 0.84375, 1.0], [0.0, 1.0, 0.8125, 1.0], [0.0, 1.0, 0.78125, 1.0], [0.0, 1.0, 0.75, 1.0], [0.0, 1.0, 0.71875, 1.0], [0.0, 1.0, 0.6875, 1.0], [0.0, 1.0, 0.65625, 1.0], [0.0, 1.0, 0.625, 1.0], [0.0, 1.0, 0.59375, 1.0], [0.0, 1.0, 0.5625, 1.0], [0.0, 1.0, 0.53125, 1.0], [0.0, 1.0, 0.5, 1.0], [0.0, 1.0, 0.46875, 1.0], [0.0, 1.0, 0.4375, 1.0], [0.0, 1.0, 0.40625, 1.0], [0.0, 1.0, 0.375, 1.0], [0.0, 1.0, 0.34375, 1.0], [0.0, 1.0, 0.3125, 1.0], [0.0, 1.0, 0.28125, 1.0], [0.0, 1.0, 0.25, 1.0], [0.0, 1.0, 0.21875, 1.0], [0.0, 1.0, 0.1875, 1.0], [0.0, 1.0, 0.15625, 1.0], [0.0, 1.0, 0.125, 1.0], [0.0, 1.0, 0.09375, 1.0], [0.0, 1.0, 0.0625, 1.0], [0.0, 1.0, 0.03125, 1.0], [0.0, 1.0, 0.0, 1.0], [0.03125, 1.0, 0.0, 1.0], [0.0625, 1.0, 0.0, 1.0], [0.09375, 1.0, 0.0, 1.0], [0.125, 1.0, 0.0, 1.0], [0.15625, 1.0, 0.0, 1.0], [0.1875, 1.0, 0.0, 1.0], [0.21875, 1.0, 0.0, 1.0], [0.25, 1.0, 0.0, 1.0], [0.28125, 1.0, 0.0, 1.0], [0.3125, 1.0, 0.0, 1.0], [0.34375, 1.0, 0.0, 1.0], [0.375, 1.0, 0.0, 1.0], [0.40625, 1.0, 0.0, 1.0], [0.4375, 1.0, 0.0, 1.0], [0.46875, 1.0, 0.0, 1.0], [0.5, 1.0, 0.0, 1.0], [0.53125, 1.0, 0.0, 1.0], [0.5625, 1.0, 0.0, 1.0], [0.59375, 1.0, 0.0, 1.0], [0.625, 1.0, 0.0, 1.0], [0.65625, 1.0, 0.0, 1.0], [0.6875, 1.0, 0.0, 1.0], [0.71875, 1.0, 0.0, 1.0], [0.75, 1.0, 0.0, 1.0], [0.78125, 1.0, 0.0, 1.0], [0.8125, 1.0, 0.0, 1.0], [0.84375, 1.0, 0.0, 1.0], [0.875, 1.0, 0.0, 1.0], [0.90625, 1.0, 0.0, 1.0], [0.9375, 1.0, 0.0, 1.0], [0.96875, 1.0, 0.0, 1.0], [1.0, 1.0, 0.0, 1.0], [1.0, 0.96875, 0.0, 1.0], [1.0, 0.9375, 0.0, 1.0], [1.0, 0.90625, 0.0, 1.0], [1.0, 0.875, 0.0, 1.0], [1.0, 0.84375, 0.0, 1.0], [1.0, 0.8125, 0.0, 1.0], [1.0, 0.78125, 0.0, 1.0], [1.0, 0.75, 0.0, 1.0], [1.0, 0.71875, 0.0, 1.0], [1.0, 0.6875, 0.0, 1.0], [1.0, 0.65625, 0.0, 1.0], [1.0, 0.625, 0.0, 1.0], [1.0, 0.59375, 0.0, 1.0], [1.0, 0.5625, 0.0, 1.0], [1.0, 0.53125, 0.0, 1.0], [1.0, 0.5, 0.0, 1.0], [1.0, 0.46875, 0.0, 1.0], [1.0, 0.4375, 0.0, 1.0], [1.0, 0.40625, 0.0, 1.0], [1.0, 0.375, 0.0, 1.0], [1.0, 0.34375, 0.0, 1.0], [1.0, 0.3125, 0.0, 1.0], [1.0, 0.28125, 0.0, 1.0], [1.0, 0.25, 0.0, 1.0], [1.0, 0.21875, 0.0, 1.0], [1.0, 0.1875, 0.0, 1.0], [1.0, 0.15625, 0.0, 1.0], [1.0, 0.125, 0.0, 1.0], [1.0, 0.09375, 0.0, 1.0], [1.0, 0.0625, 0.0, 1.0], [1.0, 0.03125, 0.0, 1.0]], 'maxi': 10.0, 'mini': 0.0} apply( cm.configure, (), cfg) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/Data/test_map.py0000644000175000017500000000052307723713122024032 0ustar debiandebianfrom DejaVu.colorMap import ColorMap cm = ColorMap('5val') cfg = {'legend': None, 'name': '5val', 'ramp': [[0.0, 0.0, 1.0, 1.0], [0.0, 0.80000001192092896, 1.0, 1.0], [0.0, 1.0, 0.40000000596046448, 1.0], [0.40000000596046448, 1.0, 0.0, 1.0], [1.0, 0.80000001192092896, 0.0, 1.0]], 'maxi': 10.0, 'mini': 0.0} apply( cm.configure, (), cfg) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/Data/rgb10_map.py0000644000175000017500000003677610651433502024004 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by from DejaVu.colorMap import ColorMap from numpy.oldnumeric import array cm = ColorMap('rgb10') cfg = {'name': 'rgb10', 'ramp': array([[ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0.002 , 0. , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.442 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 0.88 , 1. , 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.68199998, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0. , 1. , 0.23800001, 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.2 , 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 0.63800001, 1. , 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.91799998, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.47999999, 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ], [ 1. , 0.042 , 0. , 1. ]],'f'), 'maxi': 10.0, 'mini': 0.0} apply( cm.configure, (), cfg) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_ColorMapGUI.py0000644000175000017500000002027010443635174024471 0ustar debiandebian######################################################################### # # Date: May 2003 Authors: Ruth Huey, Michel Sanner # # rhuey@scripps.edu # sanner@scripps.edu # # Copyright: Michel Sanner, Ruth Huey, and TSRI # # revision: Guillaume Vareille # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Tests/test_ColorMapGUI.py,v 1.11 2006/06/13 22:21:48 vareille Exp $ # # $Id: test_ColorMapGUI.py,v 1.11 2006/06/13 22:21:48 vareille Exp $ # import sys, Tkinter import unittest from mglutil.regression import testplus from DejaVu.colorTool import RGBRamp, RedWhiteBlueRamp, RedWhiteRamp, \ WhiteBlueRamp from DejaVu.colorMap import ColorMap from DejaVu.ColormapGui import ColorMapGUI from DejaVu.Viewer import Viewer from time import sleep class ColorMapGUITest(unittest.TestCase): def setUp(self): self.root = Tkinter.Tk() self.root.withdraw() def pause(self,sleepTime=0.2): self.root.update() sleep(sleepTime) def tearDown(self): self.root.destroy() def test_constructor(self): # test if we can display a very basic cmg cmap = ColorMap(name='test', ramp=RGBRamp()) cmg = ColorMapGUI( cmap) self.pause() # Make sure that the Gui has been created properly. self.assertEqual(cmap.ramp, cmg.guiRamp) self.assertEqual(len(cmg.history), 1) self.assertEqual(cmg.cmapCurrent, True) def test_01_constructorWithViewer(self): # test building with a viewer cmap = ColorMap('test',ramp=RGBRamp()) vi = Viewer(verbose=False) cmg = ColorMapGUI( cmap, viewer=vi) self.pause() self.failUnless(cmg.ogl_cmw) vi.Exit() def test_constructorWidthOpt(self): # test setting canvas width cmap = ColorMap('test',ramp=RGBRamp()) cmg = ColorMapGUI( cmap, width=300) self.pause() self.assertEqual(cmg.xrange, 275) def test_constructorXoffsetOpt(self): # test setting xoffset cmap = ColorMap('test',ramp=RGBRamp()) cmg = ColorMapGUI( cmap, xoffset=5) self.pause() self.assertEqual( cmg.xrange, 195) def test_constructorHeightOpt(self): # test longer map cmap = ColorMap('test',ramp=RGBRamp(512)) cmg = ColorMapGUI(cmap) self.pause() self.assertEqual(cmg.lengthRamp, 512) def test_Dismiss_cb(self): # test destruction of Toplevel cmap = ColorMap('test',ramp=RGBRamp(512)) cmg = ColorMapGUI( cmap) self.pause() cmg.quit() assert cmg.master.winfo_exists()==0 def test_Update(self): cmap = ColorMap(name='test', ramp=RGBRamp()) cmg = ColorMapGUI(cmap, width=200) # update the ramp cmg.update(ramp=RedWhiteBlueRamp()) self.assertEqual(cmg.lengthRamp, len(cmg.guiRamp)) # the gui is not in a continuous mode.... self.assertEqual(cmg.cmapCurrent, False) self.assertEqual(len(cmg.history), 1) # update with longer ramp cmg.update(ramp=RedWhiteBlueRamp(512)) self.failUnless(cmg.lengthRamp==len(cmg.guiRamp)==512) # update mini, maxi values... cmg.update(mini=1.0, maxi=7.0) self.assertEqual(cmg.guiMini, 1.0) self.assertEqual(cmg.guiMaxi, 7.0) # update and configure the ramp # The gui is not continuous cmg.update(cfgCmap=True) self.assertEqual(cmg.cmapCurrent, False) self.assertEqual(len(cmg.history),1) cmg.continuousUpdate.set(1) cmg.update(cfgCmap=True) self.assertEqual(cmg.cmapCurrent, True) self.assertEqual(len(cmg.history),2) def test_stepBack_NoContinuous(self): cmap = ColorMap(name='test', ramp=RGBRamp()) cmg = ColorMapGUI(cmap, width=200) self.assertEqual(len(cmg.history), 1) self.assertEqual(cmg.cmapCurrent, True) # Step back with only one entry in the history list. cmg.stepBack_cb() self.assertEqual(len(cmg.history), 1) self.assertEqual(cmg.cmapCurrent, True) cmg.apply_cb() self.assertEqual(len(cmg.history), 1) self.assertEqual(cmg.cmapCurrent, True) # Change the ramp without pushing it onto the history list # then stepBack_cb cmg.update(ramp=RedWhiteBlueRamp()) self.assertEqual(len(cmg.history), 1) self.assertEqual(cmg.cmapCurrent, False) cmg.stepBack_cb() self.assertEqual(cmg.guiRamp, cmg.history[0]) self.assertEqual(cmg.cmapCurrent, False) cmg.apply_cb() self.assertEqual(len(cmg.history), 1) self.assertEqual(cmg.cmapCurrent, True) self.assertEqual(cmg.guiRamp, cmap.ramp) # Change the ramp twice and push them onto the history list # then stepBack_cb until the beginning of the history list. cmg.update(ramp=RedWhiteBlueRamp()) cmg.apply_cb() cmg.update(ramp=RedWhiteRamp()) cmg.apply_cb() self.assertEqual(len(cmg.history), 3) cmg.stepBack_cb() cmg.stepBack_cb() cmg.apply_cb() self.assertEqual(len(cmg.history), 1) self.assertEqual(cmg.cmapCurrent, True) # Change the ramp three times and push them onto the history list # then stepBack_cb until the beginning of the history list. cmg.update(ramp=RedWhiteBlueRamp()) cmg.apply_cb() cmg.update(ramp=RedWhiteRamp()) cmg.apply_cb() self.assertEqual(len(cmg.history), 3) cmg.update(ramp=WhiteBlueRamp()) cmg.apply_cb() self.assertEqual(len(cmg.history), 4) cmg.stepBack_cb() cmg.stepBack_cb() cmg.apply_cb() self.assertEqual(len(cmg.history), 2) self.assertEqual(cmg.cmapCurrent, True) def test_stepBack_Continuous(self): cmap = ColorMap('test', ramp=RGBRamp()) cmg = ColorMapGUI(cmap, width=200, continuous=1) newRamp = RGBRamp() for x in xrange(5): cmg.update(ramp=newRamp) self.assertEqual(len(cmg.history),6) self.assertEqual(cmg.cmapCurrent, True) # step back with a continuous colorMapGUI. cmg.stepBack_cb() self.assertEqual(len(cmg.history),5) self.assertEqual(cmg.cmapCurrent, True) cmg.stepBack_cb() self.assertEqual(len(cmg.history),4) self.assertEqual(cmg.cmapCurrent, True) cmg.stepBack_cb() self.assertEqual(len(cmg.history),3) self.assertEqual(cmg.cmapCurrent, True) cmg.stepBack_cb() self.assertEqual(len(cmg.history),2) self.assertEqual(cmg.cmapCurrent, True) cmg.stepBack_cb() self.assertEqual(len(cmg.history),1) self.assertEqual(cmg.cmapCurrent, True) cmg.stepBack_cb() self.assertEqual(len(cmg.history),1) self.assertEqual(cmg.cmapCurrent, True) def test_resetComp(self): cmap = ColorMap('test', ramp=RGBRamp()) cmg = ColorMapGUI(cmap, width=200, continuous=1) self.assertEqual(len(cmg.history), 1) ncm = ColorMap('rgb10', filename="Data/rgb10_map.py") rgb10 = ncm.ramp[:] ncm2 = ColorMap('rgb10T', filename='Data/rgb10_transparent_map.py') rgb10T = ncm2.ramp[:] cmg.update(ramp=rgb10T) self.assertEqual(len(cmg.history), 2) cmg.currentCanvasVar.set('Val') cmg.button_cb() # Reset the Opacity panel cmg.resetAll_cb #reset_cb() self.assertEqual(len(cmg.history), 2) def test_resetAll(self): cmap = ColorMap('test', ramp=RGBRamp()) rgb = cmap.ramp cmg = ColorMapGUI(cmap, width=200, continuous=1) self.assertEqual(len(cmg.history), 1) cmg.update(ramp=RedWhiteRamp()) cmg.update(ramp=RedWhiteBlueRamp()) self.assertEqual(len(cmg.history),3) cmg.resetAll_cb() self.assertEqual(len(cmg.history),1) self.assertEqual(cmg.guiRamp, rgb) if __name__ == '__main__': unittest.main() ## testplus.chdir() ## print harness ## sys.exit( len( harness)) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Cylinders.py0000644000175000017500000001752011173147112024337 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Cylinders.py,v 1.21 2009/04/20 19:34:34 vareille Exp $ # # import sys, os, math, types import numpy from math import sqrt from Tkinter import Tk, Toplevel, Menubutton import unittest,numpy.oldnumeric as Numeric from DejaVu.Viewer import Viewer from time import sleep from DejaVu.Cylinders import Cylinders import Image class Cylinders__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = [ 'radii', 'quality'] all other keywords are handled by Geom.__init__ method """ #defaults def test_Cylinders_defaults(self): """defaults for radii, quality etc """ g = Cylinders() self.assertEqual(isinstance(g, Cylinders), True) #radii def test_Cylinders_radii(self): """radii 2 (default radii is 0.2) """ g = Cylinders(radii=(2,)) self.assertEqual(isinstance(g, Cylinders), True) #quality def test_Cylinders_quality(self): """quality 15 (default quality is 3) """ g = Cylinders(quality=4) self.assertEqual(isinstance(g, Cylinders), True) class Cylinders_Set_Tests(unittest.TestCase): """ tests for Cylinders.Set method """ def setUp(self): """ create Cylinders geometry """ v = [[1.0,0,0],[2.0,0,0],[3.0,0,0]] f = [[0,1,2]] self.geom = Cylinders("cyl", vertices=v, faces=f) def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Cylinders_quality(self): """checks setting quality of cylinders """ self.geom.Set(quality=4) self.assertEqual(self.geom.quality,4) # def test_Cylinders_quality_invalid(self): # """invalid input for quality of cylinders # """ # self.assertRaises(TypeError,self.geom.Set, quality='hai') # # # def test_Cylinders_quality_bad_input(self): # """bad input for quality of cylinders # """ # self.assertRaises(TypeError,self.geom.Set, quality=[1,1]) def test_Cylinders_radii_asFloat(self): """checks setting radius of cylinders ???THIS APPARENTLY HAS NO EFFECT??? value remains the default!!! """ self.geom.Set(radii=3.0) self.assertEqual(self.geom.vertexSet.radii.array[0], 3.0) self.assertEqual(len(self.geom.vertexSet.radii.array), 1) def test_Cylinders_radii_asList(self): """checks setting radius of cylinders ???THIS APPARENTLY HAS NO EFFECT??? value remains the default!!! """ self.geom.Set(radii=[3.0]) self.assertEqual(self.geom.vertexSet.radii.array[0], 3.0) self.assertEqual(len(self.geom.vertexSet.radii.array), 1) def test_Cylinders_radii(self): """checks setting radii of cylinders """ self.geom.Set(radii=(3.0,)) self.assertEqual(self.geom.vertexSet.radii.array, (3.0,)) def xtest_Cylinders_radii_invalid(self): """invalid input for radii of cylinders ###### it seems that we have always been accepting this invalid data #### """ self.geom.Set(radii = (-10,)) self.assertNotEqual(self.geom.vertexSet.radii.array, (-10,)) def test_Cylinders_radii_invalid_too_much_float(self): """bad input, for radii of cylinders """ self.assertRaises(TypeError,self.geom.Set, radii='hai') class Cylinders_Viewer_Tests(unittest.TestCase): """ tests for Cylinders in Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(height=200,width=200,verbose = 0) v = [[-2.0,0,0],[2.0,0,0]] f = [[0,1]] self.geom = Cylinders("cyl", vertices=v, faces=f, materials=((.5,0,0),), quality=4, inheritLineWidth=0, lineWidth=10, inheritMaterial=False) # should be done vis geom.Set(radii=5.0) (ms) self.geom.Set(radii=5.0) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGui... def test_Cylinders_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() #sleep(5) buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.2, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__==Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu #import pdb;pdb.set_trace() inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) def test_Cylinders_Images(self): """tests storing and reading an image """ cam=self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #check that the pixel is not black self.assertEqual(buff_255[midpt][midpt][0]>0.1, True) buff_255_sum=Numeric.add.reduce(buff_255) #sleep(5) cam.SaveImage("./saveimagescyl.tif") im = Image.open("./saveimagescyl.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum=Numeric.add.reduce(narray_255) d=buff_255_sum-narray_255_sum #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) if __name__ == '__main__': test_cases = [ 'Cylinders__init__Tests', 'Cylinders_Set_Tests', 'Cylinders_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Axis.py0000644000175000017500000001203111330422250023271 0ustar debiandebianimport unittest import sys, os,math from Tkinter import Menubutton import numpy import numpy.oldnumeric as Numeric, types from math import sqrt from DejaVu.Viewer import Viewer from DejaVu.Arrows import Axis import Image from time import sleep class AxisTests(unittest.TestCase): def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.vi.cameras[0].Set(height=300, width=300) self.vi.Redraw() def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass def test_Set_name(self): """ test Setting name """ val = 'axis1' ax = Axis('axis', point=[0,0,0 ], unitVector=[1,0,0], length=20., radius=0.3) ax.Set(name=val) self.assertEqual(ax.name, val) def test_Set_length(self): ax = Axis('axis', point=[0,0,0 ], unitVector=[1,0,0], length=20., radius=0.3) self.vi.AddObject(ax) self.vi.Redraw() #sleep(5) val = 10 arr1 = ax.vertexSet.vertices.array ax.Set(length = val) self.vi.OneRedraw() self.assertEqual(ax.length, val) arr2 = ax.vertexSet.vertices.array self.assertEqual(numpy.alltrue(numpy.equal(arr1, arr2)), False) def test_Set_points(self): ax = Axis('axis', point=[0,0,0 ], unitVector=[1,0,0], length=20., radius=0.3) self.vi.AddObject(ax) self.vi.Redraw() #sleep(5) arr1 = ax.vertexSet.vertices.array ax.Set(point1 = [1,1,1]) arr2 = ax.vertexSet.vertices.array self.assertEqual(numpy.alltrue(numpy.equal(arr1, arr2)), False) ax.Set(point2 = [5,5,5]) self.vi.OneRedraw() arr3 = ax.vertexSet.vertices.array self.assertEqual(numpy.alltrue(numpy.equal(arr3, arr2)), False) def test_Set_materials(self): ax = Axis('axis', point=[0,0,0 ], unitVector=[0,1,0], length=20., radius=0.3, color='green') self.vi.AddObject(ax) self.vi.Redraw() #sleep(5) mat1 = numpy.array([[1,0,0,1],], 'f') ax.Set(materials=mat1, inheritMaterial=0) mat2 = ax.materials[1028].prop[1] self.assertEqual(numpy.alltrue(numpy.equal(mat1, mat2)), True) self.vi.OneRedraw() ax.Set(color = 'blue',inheritMaterial = 0) mat3 = numpy.array([[ 0., 0., 1., 1.]], 'f') self.assertEqual(numpy.alltrue(numpy.equal(mat3, ax.materials[1028].prop[1])), True) self.vi.OneRedraw() def test_Set_radius(self): ax = Axis('axis', point=[0,0,0 ], unitVector=[0,0,1], length=20., radius=0.3, color='magenta') self.vi.AddObject(ax) self.vi.Redraw() #sleep(5) val = 0.1 ax.Set(radius = val) self.vi.OneRedraw() self.assertEqual(abs(ax.vertexSet.radii.array[1] - val) < 0.001 , True) def test_image(self): """test creation of valid image by writing/reading a tif file """ cam = self.vi.currentCamera ax = Axis('axis', point=[0,0,0 ], unitVector=[1,1,1], length=20., radius=1,color='white') self.vi.AddObject(ax) self.vi.Redraw() from time import sleep #sleep(5) self.vi.update() ax.Set(radius =0.5) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = sqrt(total_pixels) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black #print "buff_255[midpt][midpt][0]=", buff_255[midpt][midpt][0] #sleep(5) # if sys.platform == 'win32': # self.assertEqual(buff_255[midpt][midpt+2][0]>0.1, True) # else: self.assertEqual(buff_255[midpt][midpt][0]>0.1, True) buff_255_sum=Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageax.tif") im = Image.open("./saveimageax.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum=Numeric.add.reduce(narray_255) #print sum d=buff_255_sum-narray_255_sum #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) if __name__ == '__main__': test_cases = [ 'test_Set_name', 'test_Set_length', 'test_Set_points', 'test_Set_materials', 'test_Set_radius', 'test_image' ] unittest.main( argv=([__name__ , ] + test_cases) ) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Geom.py0000644000175000017500000012515711247560133023304 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Geom.py,v 1.29 2009/09/02 21:15:07 vareille Exp $ # # import unittest import sys, os, math, Tkinter import numpy from opengltk.OpenGL import GL from geomutils.geomalgorithms import TriangleNormals import numpy.oldnumeric as Numeric, types from DejaVu.Geom import Geom from DejaVu.IndexedGeom import IndexedGeom #import Materials, viewerConst, datamodel, Clip from DejaVu.colorTool import OneColor from DejaVu.Transformable import Transformable from DejaVu.Displayable import Displayable from DejaVu.viewerFns import checkKeywords from DejaVu.Camera import Camera from DejaVu.Viewer import Viewer from DejaVu import viewerConst from DejaVu.ViewerGUI import ViewerGUI class Geom__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = ['protected', # 0/1 when set geometry cannot be deleted 'listed', # 0/1 when set geometry appears in object list 'vertices', 'shape'] all other keywords are handled by Set method """ def test_geom_not_protected(self): """default for protected False, (default listed is True) """ g = Geom() self.assertEqual(isinstance(g, Geom), True) def test_geom_protected(self): """protected True, (default listed is True) """ g = Geom(protected=True) self.assertEqual(isinstance(g, Geom), True) def test_geom_not_listed(self): """listed False, (default protected is False) """ g = Geom(listed=False) self.assertEqual(isinstance(g, Geom), True) def test_geom_listed(self): """listed False, protected is True """ g = Geom(listed=False, protected=True) self.assertEqual(isinstance(g, Geom), True) def test_geom_vertices(self): """vertices """ g = Geom(vertices=((0,0,0),)) self.assertEqual(isinstance(g, Geom), True) def test_geom_shape(self): """shape """ g = Geom(shape=(0,0)) self.assertEqual(isinstance(g, Geom), True) def test_geom_vertices_shape(self): """vertices and shape """ g = Geom(vertices=((0,0,0), (0,0,1),), shape=((0,0),)) self.assertEqual(isinstance(g, Geom), True) class Geom_Set_Tests(unittest.TestCase): """ keywords = ['protected', # 0/1 when set geometry cannot be deleted 'listed', # 0/1 when set geometry appears in object list 'tagModified', # use False to avoid toggling _modified 'vertices', 'vreshape', 'shape', 'texture', #not done 'textureCoords', #not done 'vnormals', 'materials', 'polyFace', 'matBind', 'propName', 'matName', 'matInd', 'rawMaterialB', 'rawMaterialF', 'matMask', 'transient', 'name', #'antialiased', 'lineWidth', 'pointWidth', 'lighting', 'visible', 'outline', 'stippleLines', 'stipplePolygons', 'culling', 'pickable', 'pickableVertices', 'scissor', 'scissorX', 'scissorY', 'scissorW', 'scissorH', 'scissorAspectRatio', 'opacity', 'depthMask', 'blendFunctions', 'instanceMatrices', 'inheritMaterial', 'inheritXform', 'inheritPointWidth', 'inheritLineWidth', 'inheritStippleLines', 'inheritStipplePolygons', 'inheritFrontPolyMode', 'inheritBackPolyMode', 'inheritShading', 'inheritCulling', 'transparent', # is also set when materials are defines 'immediateRendering', # set to 1 to avoid using dpyList 'frontPolyMode', 'backPolyMode', 'shading', 'rotation', 'translation', 'scale', 'pivot', ] """ def setUp(self): self.geom = Geom(name='baseTest') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass #protected def test_geom_protected_valid(self): """valid input for protected """ val = False self.geom.Set(protected=val) self.assertEqual(val, self.geom.getState()['protected']) def test_geom_protected_invalid(self): """invalid input for protected """ self.geom.Set(protected='hai') self.assertNotEqual(self.geom.protected, 'hai') #listed # def test_geom_cannot_set_listed(self): # """NB:CANNOT Set listed even with valid input 'False' # """ # self.geom.Set(listed=False) # newstate=self.geom.getState()['listed'] # self.assertEqual(newstate, True) def test_geom_listed_invalid(self): """invalid input for listed """ rval = self.geom.Set(listed = 'hai') self.assertNotEqual(self.geom.listed, 'hai') #tagModified def test_geom_tagModified_valid(self): """valid input for tagModified """ val = True self.geom.Set(tagModified=val) self.assertEqual(val, self.geom._modified) def test_geom_tagModified_invalid(self): """invalid input for tagModified """ self.assertRaises(AssertionError, self.geom.Set,tagModified = 'hai') #vertices def test_geom_vertices(self): """valid input for vertices """ val = ((0,0,0),(1,0,0),) self.geom.Set(vertices=val) flat = Numeric.array([0.,0.,0.,1.,0.,0.]) self.assertEqual(True , numpy.alltrue(flat == self.geom.vertexSet.vertices.array.ravel()) ) def test_geom_vertices_invalid(self): """invalid input for vertices """ self.assertRaises(ValueError, self.geom.Set, vertices = 'hai') ##vreshape # def test_geom_vreshape(self): # """valid input for vreshape # """ # val = ((0,0,0,1,0,0),) # reshape=True # self.geom.Set(vertices=val, reshape=reshape) # flat = Numeric.array([0.,0.,0.,1.,0.,0.]) # self.assertEqual(flat, self.geom.vertexSet.vertices.array.ravel()) # # def test_geom_vreshape_invalid(self): # """CANNOT FIND invalid input for vreshape # """ # self.geom.Set(vertices=((0,0,0),(1,0,0),), vreshape='False') # flat = Numeric.array([0.,0.,0.,1.,0.,0.]) # #print self.geom.vertexSet.vertices # self.assertEqual(flat, self.geom.vertexSet.vertices.array.ravel()) #shape def test_geom_shape(self): """valid input for shape """ val = ((0,0,0,1,0,0),) shape = (3,2) self.geom.Set(vertices=val, shape=shape) flat = Numeric.array([0.,0.,0.,1.,0.,0.]) #self.assertEqual(flat, self.geom.vertexSet.vertices.array.ravel()) self.assertEqual(True , numpy.alltrue(flat == self.geom.vertexSet.vertices.array.ravel()) ) # def test_geom_shape_invalid(self): # """CANNOT FIND invalid input for shape # """ # verts =((0,0,0),(1,0,0)) # self.geom.Set(vertices=verts, shape=5) # flat = Numeric.array([0.,0.,0.,1.,0.,0.]) # self.assertRaises(AttributeError, self.geom.Set,shape=5) #texture #textureCoords #vnormals #materials def test_geom_materials(self): """valid input for materials """ val = ((1,0,0),) self.geom.Set(materials=val) self.assertEqual(val, self.geom.materiasl) def test_geom_materials(self): """invalid input for materials """ self.assertRaises(ValueError, self.geom.Set, materials = 'hai') #polyFace #matBind #propName #matName #matInd #rawMaterial #matMask #transient #name def test_geom_name(self): """valid input for name """ self.geom.Set(name='test') newstate=self.geom.getState()['name'] self.assertEqual(newstate,'test') def xtest_geom_name_invalid(self): """invalid input for name ###### it seems that we have always been accepting this invalid data #### """ self.geom.Set(name = ' ') self.assertNotEqual(self.geom.name, ' ') ##antialiased # def test_geom_antialiased(self): # """valid input for antialiased # """ # self.geom.Set(antialiased=True) # newstate=self.geom.getState()['antialiased'] # self.assertEqual(newstate,True) # # # def test_geom_antialiased_invalid(self): # """invalid input for antialiased # """ # self.assertRaises(ValueError, self.geom.Set,antialiased='hai') #lineWidth def test_linewidth_invalid_input(self): """invalid input for lineWidth , """ self.assertRaises(AssertionError, self.geom.Set,lineWidth = -10) def test_linewidth(self): """valid input for lineWidth """ self.geom.Set(lineWidth = 1) newstate=self.geom.getState()['lineWidth'] self.assertEqual(newstate,1) def test_linewidth_bad_input(self): """badinput for lineWidth , """ self.assertRaises(AssertionError, self.geom.Set,lineWidth = 'hai') #pointWidth def test_pointwidth(self): """valid input for pointWidth """ self.geom.Set(pointWidth = 16) newstate=self.geom.getState()['pointWidth'] self.assertEqual(newstate,16) def test_pointwidth_invalid(self): """invalid input for pointWidth """ self.assertRaises(AssertionError, self.geom.Set,pointWidth = -1.0) def test_pointwidth_bad_input(self): """bad input for pointWidth """ self.assertRaises(AssertionError, self.geom.Set,pointWidth = 'hai') def test_pointwidth(self): """valid input for pointWidth """ self.geom.Set(pointWidth = 16) self.geom.Set(outline=False, backPolyMode=GL.GL_POINT) newstate = self.geom.getState()['pointWidth'] self.assertEqual(newstate,16) #lighting def test_lighting(self): """valid input for lighting """ self.geom.Set(lighting=True) newstate=self.geom.getState()['lighting'] self.assertEqual(newstate,True) def test_geom_lighting_invalid(self): """invalid input for lighting """ self.assertRaises(ValueError,self.geom.Set, lighting='hai') def test_geom_visible_invalid(self): """invalid input for lighting """ self.assertRaises(ValueError,self.geom.Set, lighting='hai') #visible def test_geom_visible(self): """valid input for visible """ self.geom.Set(visible=False) newstate=self.geom.getState()['visible'] self.assertEqual(newstate, False) #alternatively self.assertEqual(self.geom.visible, False) def test_geom_visible_invalid(self): """invalid input for visible """ self.assertRaises(ValueError, self.geom.Set, visible=[2,3,4]) #outline def test_outline(self): """valid input for outline """ self.geom.Set(outline=True) newstate=self.geom.getState()['outline'] self.assertEqual(newstate,(True,True)) def test_geom_outline_invalid(self): """invalid input for outline """ self.assertRaises(ValueError,self.geom.Set, outline='hai') #stippleLines def test_geom_stippleLines(self): """valid input for stippleLines """ self.geom.Set(stippleLines = True) newstate=self.geom.getState()['stippleLines'] self.assertEqual(newstate,True) def test_geom_stippleLines_invalid(self): """invalid input for stippleLines """ self.assertRaises(ValueError,self.geom.Set,stippleLines = 'hai') #stipplePolygons def test_geom_stipplePolygons(self): """valid input for stipplePolygons """ self.geom.Set(stipplePolygons = True) newstate=self.geom.getState()['stipplePolygons'] self.assertEqual(newstate,True) def test_geom_stipplePolygons_invalid(self): """invalid input for stipplePolygons """ self.assertRaises(ValueError, self.geom.Set,stipplePolygons = 'hai') #cull def test_geom_culling_none(self): """valid input for culling,none """ self.geom.Set(culling=GL.GL_NONE) newstate=self.geom.getState()['culling'] self.assertEqual(newstate,'none') def test_geom_culling_front(self): """valid input for culling,front """ self.geom.Set(culling=GL.GL_FRONT) newstate=self.geom.getState()['culling'] self.assertEqual(newstate,'front') def test_geom_culling_back(self): """valid input for culling,back """ self.geom.Set(culling=GL.GL_BACK) newstate=self.geom.getState()['culling'] self.assertEqual(newstate,'back') def test_geom_culling_front_back(self): """valid input for culling,front_back """ self.geom.Set(culling=GL.GL_FRONT_AND_BACK) newstate=self.geom.getState()['culling'] self.assertEqual(newstate,'front_and_back') def test_geom_culling_invalid(self): """invalid input for culling """ self.geom.culling=viewerConst.INHERIT self.assertRaises(AssertionError,self.geom.Set, culling='hai') #pickable def test_geom_pickable(self): """valid input for pickable """ self.geom.Set(pickable=0) newstate=self.geom.getState()['pickable'] self.assertEqual(newstate,0) def test_geom_pickable_invalid(self): """invalid input for pickable """ self.assertRaises(ValueError, self.geom.Set,pickable = 'hai') #pickableVertices def test_geom_pickableVertices(self): """valid input for pickableVertices """ self.geom.Set(pickableVertices = True) newstate=self.geom.getState()['pickableVertices'] self.assertEqual(newstate,True) def test_geom_pickableVertices_invalid(self): """invalid input for pickableVertices """ self.assertRaises(ValueError, self.geom.Set,pickableVertices = 'hai') #scissor def test_geom_scissor_invalid(self): """invalid input for scissor on/off not working,a box is displayed """ self.assertRaises(ValueError,self.geom.Set,scissor = 'hai') #scissorX def test_geom_scissorX(self): """valid input for scissorX """ self.geom.Set(scissorX = 1) newstate = self.geom.getState()['scissorX'] self.assertEqual(newstate,1) def test_geom_scissorX_invalid(self): """invalid input for scissorX """ self.assertRaises(ValueError, self.geom.Set,scissorX = 'hai') #scissorY def test_geom_scissorY(self): """valid input for scissorY """ self.geom.Set(scissorY = 1) newstate = self.geom.getState()['scissorY'] self.assertEqual(newstate,1) def test_geom_scissorY_invalid(self): """valid input for scissorY """ self.assertRaises(ValueError, self.geom.Set,scissorY = 'hai') #scissorW def test_geom_scissorW(self): """valid input for scissorW """ self.geom.Set(scissorW = 300) newstate = self.geom.getState()['scissorW'] self.assertEqual(newstate,300) def test_geom_scissorW_invalid(self): """invalid input for scissorW """ self.assertRaises(ValueError, self.geom.Set,scissorW = 'hai') #scissorH def test_geom_scissorH(self): """valid input for scissorH """ self.geom.Set(scissorH = 300) newstate = self.geom.getState()['scissorH'] self.assertEqual(newstate,300) def test_geom_scissorH_invalid(self): """invalid input for scissorH """ self.assertRaises(ValueError, self.geom.Set,scissorH = 'hai') #scissorAspectRatio def test_geom_scissorAspectRatio(self): """valid input for scissorAspectRatio """ self.geom.Set(scissorAspectRatio = 2.0) newstate = self.geom.getState()['scissorAspectRatio'] self.assertEqual(newstate,2.0) def test_geom_scissorAspectRatio_invalid(self): """invalid input for scissorAspectRatio """ self.assertRaises(ValueError, self.geom.Set,scissorAspectRatio = 'hai') #opacity # def test_geom_opacity(self): # """valid input for scissorAspectRatio # NOT AVAILABLE in STATE # """ # self.geom.Set(opacity = [.5, .5]) # ###THIS IS BURIED SOMEWHERE IN geom.materials[pf] # ###where pf is something like GL.GL_FRONT # print "\nopacity test not completed..." # ###self.assertEqual(self.geom.opacity,2.0) # # def test_geom_opacity_invalid(self): # """invalid input for opacity DOES NOT RAISE ERROR # """ # val = [.5,.5] # self.geom.Set(opacity=val) # print "\ninvalid opacity test not completed..." # ##self.assertEqual(self.geom.opacity, val) # #self.assertRaises(ValueError, self.geom.Set, opacity=[2,3,4]) #depthMask def test_geom_depthmask(self): """valid input for depthmask """ self.geom.Set(depthMask = 1) newstate=self.geom.getState()['depthMask'] self.assertEqual(newstate,1) def test_geom_depthmask_invalid(self): """invalid input for depthmask """ self.assertRaises(ValueError,self.geom.Set,depthMask = 'hai') #blendFunctions def test_geom_blend_func_zero(self): """valid input for blend func zero """ val1=GL.GL_ZERO val2=GL.GL_ZERO self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_ZERO','GL_ZERO')) def test_geom_blend_func_invalid(self): """invalid input for blend func """ self.assertRaises(AssertionError,self.geom.Set,blendFunctions = 'hai') def test_geom_blend_func_one(self): """valid input for blend func one """ val1=GL.GL_ONE val2=GL.GL_ONE self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_ONE','GL_ONE')) def test_geom_blend_func_color(self): """valid input for blend func color """ val1=GL.GL_DST_COLOR val2=GL.GL_SRC_COLOR self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_DST_COLOR','GL_SRC_COLOR')) def test_geom_blend_func_one_minus_color(self): """valid input for blend func one minus color """ val1=GL.GL_ONE_MINUS_DST_COLOR val2=GL.GL_ONE_MINUS_SRC_COLOR self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_ONE_MINUS_DST_COLOR','GL.GL_ONE_MINUS_SRC_COLOR')) def test_geom_blend_func_src_alpha(self): """valid input for blend func src_alpha """ val1=GL.GL_SRC_ALPHA val2=GL.GL_SRC_ALPHA self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_SRC_ALPHA','GL_SRC_ALPHA')) def test_geom_blend_func_dst_alpha(self): """valid input for blend func dst_alpha """ val1=GL.GL_DST_ALPHA val2=GL.GL_DST_ALPHA self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_DST_ALPHA','GL_DST_ALPHA')) def test_geom_blend_func_dst_one_minus_alpha(self): """valid input for blend func dst_one_minus_alpha """ val1=GL.GL_ONE_MINUS_DST_ALPHA val2=GL.GL_ONE_MINUS_DST_ALPHA self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_ONE_MINUS_DST_ALPHA','GL_ONE_MINUS_DST_ALPHA')) def test_geom_blend_func_src_one_minus_alpha(self): """valid input for blend func src_one_minus_alpha """ val1=GL.GL_ONE_MINUS_SRC_ALPHA val2=GL.GL_ONE_MINUS_SRC_ALPHA self.geom.Set(blendFunctions = (val1, val2)) newstate=self.geom.getState()['blendFunctions'] self.assertEqual(newstate,('GL_ONE_MINUS_SRC_ALPHA','GL_ONE_MINUS_SRC_ALPHA')) #instanceMatrices #inheritMaterial def xtest_geom_inheritMaterial_invalid(self): """invalid input for inheritMaterial ###### it seems that we have always been accepting this invalid data #### """ self.assertRaises(AssertionError,self.geom.Set, inheritMaterial = 'hai') #inheritXform def test_geom_inheritXform_invalid(self): """invalid input for inheritXform """ self.assertRaises(AssertionError,self.geom.Set, inheritXform = 'hai') #inheritPointWidth def test_geom_inheritPointWidth_invalid(self): """invalid input for inheritPointWidth """ self.assertRaises(AssertionError,self.geom.Set, inheritPointWidth = 'hai') #inheritLineWidth def test_geom_inheritLineWidth_invalid(self): """invalid input for inheritLineWidth """ self.assertRaises(AssertionError,self.geom.Set, inheritLineWidth = 'hai') #inheritStippleLines def test_geom_inheritStippleLines_invalid(self): """invalid input for inheritStippleLines """ self.assertRaises(AssertionError,self.geom.Set, inheritStippleLines = 'hai') #inheritStipplePolygons def test_geom_inheritStipplePolygons_invalid(self): """invalid input for inheritStipplePolygons """ self.assertRaises(AssertionError,self.geom.Set, inheritStipplePolygons = 'hai') #inheritBackPolyMode def test_geom_inheritBackPolyMode_invalid(self): """invalid input for inheritBackPolyMode """ self.assertRaises(AssertionError,self.geom.Set, inheritBackPolyMode= 'hai') #inheritShading def test_geom_inheritShading_invalid(self): """invalid input for inheritShading """ self.assertRaises(AssertionError,self.geom.Set, inheritShading= 'hai') #inheritFrontPolyMode def test_geom_inheritFrontPolyMode_invalid(self): """invalid input for inheritFrontPolyMode """ self.assertRaises(AssertionError,self.geom.Set, inheritFrontPolyMode= 'hai') #inheritCulling def test_geom_inheritCulling_invalid(self): """invalid input for inheritCulling """ self.assertRaises(AssertionError,self.geom.Set, inheritCulling= 'hai') def test_geom_culling_inherit(self): """valid input for culling, inherit """ self.geom.culling = viewerConst.INHERIT self.geom.Set(culling=self.geom.culling) newstate=self.geom.getState()['culling'] self.assertEqual(newstate,'inherit') #transparent def test_geom_transparent(self): """valid input for transparent """ self.geom.Set(transparent=True) newstate = self.geom.getState()['transparent'] self.assertEqual(newstate,True) def test_geom_transparent_invalid(self): """invalid input for transparent """ self.assertRaises(AssertionError, self.geom.Set,transparent = 'hai') #immediateRendering def test_geom_immediateRendering(self): """valid input for immediateRendering """ self.geom.Set(immediateRendering = True) newstate=self.geom.getState()['immediateRendering'] self.assertEqual(newstate,True) def test_geom_immediateRendering_invalid(self): """invalid input for immediateRendering """ self.assertRaises(AssertionError,self.geom.Set, immediateRendering = 'hai') #frontPolyMode def test_geom_front_polymode(self): """valid input for front_polymode """ self.geom.Set(frontPolyMode='fill') newstate=self.geom.getState()['frontPolyMode'] self.assertEqual(newstate,'fill') def test_geom_front_polymode_invalid(self): """invalid input for front_polymode """ self.assertRaises(KeyError,self.geom.Set, frontPolyMode = 'hai') #backPolyMode def test_geom_back_polymode(self): """valid input for back_polymode """ self.geom.Set(backPolyMode='line') newstate=self.geom.getState()['backPolyMode'] self.assertEqual(newstate,'line') def test_geom_back_polymode_invalid(self): """invalid input for back_polymode """ self.assertRaises(KeyError,self.geom.Set,backPolyMode = 'hai') #shading def test_geom_shading_mode(self): """valid input for shadingmode """ self.geom.Set(shading='smooth') newstate=self.geom.getState()['shading'] self.assertEqual(newstate,'smooth') def test_geom_shading_mode_invalid(self): """valid input for shadingmode """ self.assertRaises(KeyError, self.geom.Set,shading = 'hai') #rotation def test_rotation(self): """valid input for rotation """ old_state = self.geom.getState()['rotation'] from mglutil.math.rotax import rotax import math matRot = rotax( (0,0,0), (0,0,1), math.pi/2.) self.geom.Set(rotation=matRot) new_state = self.geom.getState()['rotation'] #hard to compare list with [4][4]array #self.assertEqual(new_state[0]-matRot[0][0] < .0000001, True) self.assertEqual(old_state!=new_state,True) def test_rotation_invalid(self): """invalid input for rotation invalid """ self.assertRaises(ValueError, self.geom.Set,rotation = 'hai') def test_rotation_invalid_array_shape(self): """invalid input,bad array shape for rotation """ self.assertRaises(ValueError, self.geom.Set,rotation = [1,1]) #translation def test_translation(self): """valid input for translation """ self.geom.Set(translation=numpy.ones(3,'f')) self.assertEqual(numpy.alltrue(self.geom.getState()['translation']==numpy.ones(3)),True) def test_translation_invalid(self): """invalid input for translation """ # self.geom.Set(translation = 'hai') # self.assertNotEqual(self.geom.translation, 'hai') self.assertRaises(ValueError, self.geom.Set, translation='hai') def test_translation_invalid_array_shape(self): """invalid input,bad array shape for translation """ self.assertRaises(ValueError, self.geom.Set,translation = [1,1]) #scale def test_scale(self): """valid input for scale """ self.geom.Set(scale=Numeric.ones(3)*2) self.assertEqual(numpy.alltrue(self.geom.getState()['scale']==Numeric.ones(3)*2),True) def test_scale_invalid(self): """invalid input for scale """ #self.geom.Set(scale = 'hai') self.assertRaises(ValueError, self.geom.Set, scale='hai') def test_scale_invalid_array_shape(self): """invalid input,bad array shape for scale """ self.assertRaises(ValueError, self.geom.Set,scale = [1,1]) #pivot def test_pivot(self): """valid input for pivot """ self.geom.Set(pivot=numpy.ones(3)*.5) self.assertEqual(True, numpy.alltrue(self.geom.getState()['pivot']==numpy.ones(3)*.5)) def test_pivot_invalid(self): """invalid input for pivot """ self.assertRaises(ValueError, self.geom.Set,pivot = 'hai') def test_pivot_invalid(self): """invalid input for pivot """ self.assertRaises(ValueError, self.geom.Set,pivot =[1,1]) ###class Geom_Method_Tests(Geom_Test): # """tests for methods of Geom class #getState #getGeomMaterialCode #getGeomClipPlanesCode #delete <-abstract method #getVertices #getVNormals #setViewer #getDepthMask #isTransparent #GetFrontPolyMode #GetShading #MaterialBindingMode #AddMaterial #SetMaterial #GetNormals #Add #SetForChildren #setTransparency #updateParentsForImmediateRendering #_Hide #_Remove #BoundingBox #DisplayFunction #Draw #RedoDisplayList #AddClipPlane #RemoveClipPlane #LastParentBeforeRoot #ApplyParentsTransform #TransformCoords #AllVisibleObjects #AllObjects #ObjSubTreeBB #ComputeBB #_DrawBox #DrawTreeBoundingBox #DrawBoundingBox #RenderMode #asIndexedPolygons #sortPoly #sortPoly_cb #getFaces #getFNormals #_FixedLengthFaces #_PrimitiveType #""" class Geom_Viewer_Tests(unittest.TestCase): """tests for geom.Set in viewer """ def setUp(self): self.vi = Viewer(verbose=0) self.geom = Geom(name='baseTest') self.vi.AddObject(self.geom) self.vi.currentObject = self.geom def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass def test_geom_protected(self): """valid input for protected 0/1 """ self.geom.Set(protected=True) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Tkinter.Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu protected_index = self.inheritF_menu.index('protected') self.inheritF_menu.invoke(protected_index) newstate=self.geom.getState()['protected'] self.assertEqual(newstate, False) # def test_geom_lighting(self): # """valid input for lighting # """ # self.geom.Set(lighting=False) # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__ == Tkinter.Menubutton \ # and c.configure('text')[-1] == ('Current', 'geom', 'properties'): # self.inheritF_menu = c.menu # lighting_index = self.inheritF_menu.index('lighting') # self.geom.viewer.SetCurrentObject(self.geom) # self.inheritF_menu.invoke(lighting_index) # newstate=self.geom.getState()['lighting'] # self.assertEqual(newstate,True) def test_geom_visible(self): """valid input for visible """ self.geom.Set(visible=0) newstate=self.geom.getState()['visible'] self.assertEqual(newstate,0) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Tkinter.Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu break visible_index = self.inheritF_menu.index('visible') self.inheritF_menu.invoke(visible_index) newstate=self.geom.getState()['visible'] self.assertEqual(newstate,1) def test_geom_outline_front_polymode(self): """valid input for outline """ self.vi.currentObject.frontPolyMode ='outlines' self.geom.Set(outline = 1.0) mode=viewerConst.INHERIT self.geom.Set(outline=True, frontPolyMode=GL.GL_FILL) newstate=self.geom.getState()['outline'] self.assertEqual(newstate,(True,True)) def test_geom_outline_back_polymode(self): """valid input for outline """ self.vi.currentObject.backPolyMode ='outlines' self.geom.Set(outline = 1.0) mode=viewerConst.INHERIT self.geom.Set(outline=True, backPolyMode=GL.GL_FILL) newstate=self.geom.getState()['outline'] self.assertEqual(newstate,(True,True)) def test_geom_scissor(self): """valid input for scissor on/off not working,a box is displayed """ self.geom.Set(scissor=True) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Tkinter.Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu scissor_index = self.inheritF_menu.index('scissor') self.inheritF_menu.invoke(scissor_index) newstate=self.geom.getState()['scissor'] self.assertEqual(newstate,True) def test_geom_inheritMaterial(self): """valid input for inheritMaterial """ for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Tkinter.Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate=self.geom.getState()['inheritMaterial'] self.assertEqual(newstate,True) def test_geom_inheritMaterial_red(self): """valid input for inheritMaterial set to red ,after toggle on inherits from parent """ self.geom.Set(materials=((1,0,0),)) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Tkinter.Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate=self.geom.getState()['inheritMaterial'] self.assertEqual(self.geom.materials==(1,0,0), False) def test_geom_inheritXform(self): """valid input for inheritXform """ for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Tkinter.Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritXform_index = self.inheritF_menu.index('inheritXform') self.inheritF_menu.invoke(inheritXform_index) newstate=self.geom.getState()['inheritXform'] self.assertEqual(newstate,True) # def test_geom_inheritPointWidth(self): # """valid input for inheritPointWidth # """ # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__ == Tkinter.Menubutton \ # and c.configure('text')[-1] == ('Current', 'geom', 'properties'): # self.inheritF_menu = c.menu # inheritPointWidth_index = self.inheritF_menu.index('inheritPointWidth') # self.inheritF_menu.invoke(inheritPointWidth_index) # newstate=self.geom.getState()['inheritPointWidth'] # self.assertEqual(newstate,True) # # # def test_geom_inheritLineWidth(self): # """valid input for inheritLineWidth # """ # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__ == Tkinter.Menubutton \ # and c.configure('text')[-1] == ('Current', 'geom', 'properties'): # self.inheritF_menu = c.menu # inheritLineWidth_index = self.inheritF_menu.index('inheritLineWidth') # self.inheritF_menu.invoke(inheritLineWidth_index) # newstate=self.geom.getState()['inheritLineWidth'] # self.assertEqual(newstate,True) # # # def test_geom_inheritStippleLines(self): # """valid input for inheritStippleLines # """ # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__ == Tkinter.Menubutton \ # and c.configure('text')[-1] == ('Current', 'geom', 'properties'): # self.inheritF_menu = c.menu # inheritStippleLines_index = self.inheritF_menu.index('inheritStippleLines') # self.inheritF_menu.invoke(inheritStippleLines_index) # newstate=self.geom.getState()['inheritStippleLines'] # self.assertEqual(newstate,True) # def test_geom_inheritStipplePolygons(self): # """valid input for inheritStipplePolygons # """ # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__ == Tkinter.Menubutton \ # and c.configure('text')[-1] == ('Current', 'geom', 'properties'): # self.inheritF_menu = c.menu # inheritStipplePolygons_index = self.inheritF_menu.index('inheritStipplePolygons') # self.inheritF_menu.invoke(inheritStipplePolygons_index) # newstate=self.geom.getState()['inheritStipplePolygons'] # self.assertEqual(newstate,True) # def test_geom_inheritFrontPolyMode(self): # """valid input for inheritFrontPolyMode # """ # self.geom.Set(inheritFrontPolyMode = True) # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__==Tkinter.Menubutton: # self.inheritF_menu = c.menu # inheritFrontPolyMode_index = self.inheritF_menu.index('inheritFrontPolyMode') # self.inheritF_menu.invoke(inheritFrontPolyMode_index) # newstate=self.geom.getState()['inheritFrontPolyMode'] # self.assertEqual(newstate,True) # def test_geom_inheritBacktPolyMode(self): # """valid input for inheritBackPolyMode # """ # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__==Tkinter.Menubutton: # self.inheritF_menu = c.menu # inheritBackPolyMode_index = self.inheritF_menu.index('inheritBackPolyMode') # self.inheritF_menu.invoke(inheritBackPolyMode_index) # newstate=self.geom.getState()['inheritBackPolyMode'] # self.assertEqual(newstate,True) # def test_geom_inheritShading(self): # """valid input for inheritShading # """ # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__==Tkinter.Menubutton: # self.inheritF_menu = c.menu # inheritShading_index = self.inheritF_menu.index('inheritShading') # self.inheritF_menu.invoke(inheritShading_index) # newstate=self.geom.getState()['inheritShading'] # self.assertEqual(newstate,True) # def test_geom_inheritCulling(self): # """valid input for inheritCulling # """ # self.geom.inheritCulling=True # for c in self.vi.GUI.inheritF.children.values(): # if c.__class__==Tkinter.Menubutton: # self.inheritF_menu = c.menu # inheritCulling_index = self.inheritF_menu.index('inheritCulling') # self.inheritF_menu.invoke(inheritCulling_index) # newstate=self.geom.getState()['inheritCulling'] # self.assertEqual(newstate,True) class IndexedGeom_Set_Tests(unittest.TestCase): """ keywords = Geom.keywords + [ 'type', 'faces', 'fnormals', 'freshape', ] """ def setUp(self): self.geom = IndexedGeom(name='indexed_baseTest') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass #type def test_IndexedGeom_types_invalid(self): """invalid input for types """ self.assertRaises(AttributeError, self.geom, primitiveType = 'hai') #GL_TRIANGLES, GL_QUADS... are the same as type????? def test_IndexedGeom_types_GL_TRIANGLES(self): """valid input GL_TRIANGLES """ self.geom.primitiveType=GL.GL_TRIANGLES self.assertEqual(self.geom.primitiveType,4) def test_IndexedGeom_types_GL_QUADS(self): """valid input GL_QUADS """ self.geom.primitiveType=GL.GL_QUADS self.assertEqual(self.geom.primitiveType, 7) def test_IndexedGeom_types_GL_POLYGONS(self): """valid input GL_POLYGONS """ self.geom.primitiveType=GL.GL_POLYGON self.assertEqual(self.geom.primitiveType,9) #faces def test_IndexedGeom_faces(self): """ test faces """ self.geom.Set(vertices =[[0,0,0],[1,0,0]], faces=((0,1),)) self.assertEqual(len(self.geom.faceSet.faces.array),1) def test_IndexedGeom_faces_invalid_not_sequence(self): """invalid input for faces, afces should be list of lists of integers """ self.assertRaises(TypeError,self.geom.Set,faces = 20) def test_IndexedGeom_faces_invalid_indices(self): """invalid input for faces, -20 not a good index """ self.assertRaises(ValueError,self.geom.Set,faces=[[-20,3,4]]) def test_IndexedGeom_faces_set(self): """valid input for faces """ self.geom.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),(1,0),)) self.assertEqual(len(self.geom.faceSet.faces.array),2) #fnormals def test_IndexedGeom_fnormals(self): """test fnormals """ self.geom.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),)) self.assertEqual(self.geom.faceSet.normals.GetProperty(),None) def test_IndexedGeom_fnormals_invalid(self): """invalid input fnormals """ self.geom.Set(vertices =[[0,0,0],[1,0,0]],faces=((0,1),)) self.assertRaises(ValueError, self.geom.Set,fnormals = 'hai') #normals def test_IndexedGeom_normals(self): """valid input for normals """ self.geom.faceSet.normals.SetValues([(0,1),(1,0)]) self.assertEqual(len(self.geom.faceSet.normals),2) #freshape !!!!!!NOT DONE!!!!!!! ###class IndexedGeom_Method_Tests(Geom_Test): ### """tests for methods of IndexedGeom class #methods: #getFaces #getFNormals #_FixedLengthFaces #_PrimitiveType #Add #Set #ComputeVertexNormals #ComputeFaceNormals #VertexNormalFunction #FaceNormalFunction #sortPoly #DisplayFunction #Draw #RedoDisplayList #removeDuplicatedVertices if __name__ == '__main__': test_cases = [ 'Geom__init__Tests', 'Geom_Set_Tests', 'Geom_Viewer_Tests', 'IndexedGeom_Set_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #remove the -v flag to make output cleaner #unittest.main( argv=([__name__ ,'-v'] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_ColorChooser.py0000644000175000017500000002044110735276634025017 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_ColorChooser.py,v 1.4 2007/12/28 22:50:04 vareille Exp $ # # import Tkinter import numpy import numpy.oldnumeric as Numeric import math import unittest from copy import deepcopy from DejaVu.ColorChooser import ColorChooser from DejaVu.colorTool import ToRGB,ToHSV def MyCallback(col): print 'col', col class ColorChooser_BaseTests(unittest.TestCase): def test_colorchooser_visible(self): """tests color chooser is visible """ root = Tkinter.Tk() cc = ColorChooser(root) cc.AddCallback(MyCallback) root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(cc.hsWheel.canvas.master.winfo_ismapped(),1) self.assertEqual(root.winfo_ismapped(),True) cc.RemoveCallback(MyCallback) root.destroy() def test_color_chooser_save(self): """tests colorchooser,save button """ root = Tkinter.Tk() cc = ColorChooser(root) cc.value.Set(0.75) cc.save.invoke() root.wait_visibility(cc.hsWheel.canvas) lColor = cc.hsWheel.Get() self.assertEqual(cc.savedHsvColor[0],lColor[0]) self.assertEqual(cc.savedHsvColor[1],lColor[1]) self.assertEqual(cc.savedHsvColor[2],lColor[2]) self.assertEqual(cc.value.val,0.75) root.destroy() def test_color_chooser_restore(self): """tests color chooser restore button(when invoked displays stored value as current one) """ root = Tkinter.Tk() cc = ColorChooser(root) #get color before setting value old_color = deepcopy(cc.hsWheel.Get()) #get cursor coords before setting value old_cursorx = cc.hsWheel.cursorX old_cursory = cc.hsWheel.cursorY #set value to 0.75 cc.value.Set(0.75) #invoke restore button cc.restore.invoke() #get color after setting value & invoking restore button new_color = cc.hsWheel.Get() #get cursor coords after setting value & invoking restore button new_cursorx = cc.hsWheel.cursorX new_cursory = cc.hsWheel.cursorY root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(cc.value.val,1.0) #colors,cursor,coords before,after setting values #invoking restore button shows previous values self.assertTrue(numpy.alltrue(old_color == new_color)) self.assertEqual(old_cursorx == new_cursorx,True) self.assertEqual(old_cursory == new_cursory,True) root.destroy() def test_color_chooser_swap(self): """tests color chooser ,swap button(when invoked shows stored value,invoked again shows current one) """ root = Tkinter.Tk() cc = ColorChooser(root) cc.value.Set(0.75) #get color before invoking swap button old_color = cc.hsWheel.Get() #get cursor coords before invoking swap button old_cursorx = cc.hsWheel.cursorX old_cursory = cc.hsWheel.cursorY #invoke swap button cc.swap.invoke() self.assertEqual(cc.value.val,1.0) #invoke swap button cc.swap.invoke() #get color after setting value & invoking swap button new_color = cc.hsWheel.Get() #get cursor coords after setting value & invoking swap button new_cursorx = cc.hsWheel.cursorX new_cursory = cc.hsWheel.cursorY root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(cc.value.val,0.75) #colors,cursor,coords before,after setting values #invoking swap button twice shows first value self.assertTrue(numpy.alltrue(old_color == new_color)) self.assertEqual(old_cursorx == new_cursorx,True) self.assertEqual(old_cursory == new_cursory,True) root.destroy() def test_colorchooser_cursor(self): """tests color chooser, moving cursor """ root = Tkinter.Tk() cc = ColorChooser(root) old_x = cc.hsWheel.cursorX old_y = cc.hsWheel.cursorY cc.hsWheel._MoveCursor(25,25) new_x = cc.hsWheel.cursorX new_y = cc.hsWheel.cursorY root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(old_x != new_x,True) self.assertEqual(old_y != new_y,True) root.destroy() def test_color_chooser_current(self): """tests color chooser ,current: checks back ground color of current changes when value is changed """ root = Tkinter.Tk() cc = ColorChooser(root) old_color = cc.currentColor.config()['background'][-1] cc.value.Set(0.75) new_color = cc.currentColor.config()['background'][-1] root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(old_color != new_color,True) root.destroy() def test_color_chooser_saved (self): """tests color chooser ,saved: checks back ground color of saved changes when value is changed """ root = Tkinter.Tk() cc = ColorChooser(root) old_color = cc.savedColor.config()['background'][-1] cc.value.Set(0.75) cc.save.invoke() new_color = cc.savedColor.config()['background'][-1] root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(old_color != new_color,True) root.destroy() def test_colorchooser_color_1(self): """tests colorchooser ,color wheel colors """ root = Tkinter.Tk() cc = ColorChooser(root) old_color = cc.hsWheel.hsvColor cc.hsWheel._MoveCursor(100,50) new_color = cc.hsWheel.hsvColor root.wait_visibility(cc.hsWheel.canvas) #self.assertEqual(old_color,new_color) self.assertTrue(numpy.alltrue(old_color==new_color)) cc.hsWheel.Set((1.0,0.0,0.0),mode = 'RGB') mycolor = ToRGB(cc.hsWheel.Get()) mycol = [] for i in range(0,len(mycolor)): mycol.append(round(mycolor[i])) self.assertEqual(mycol,[1.0, 0.0, 0.0, 1.0]) root.destroy() def test_colorchooser_color_HSV(self): """tests colorchooser ,color wheel hsvcolors """ root = Tkinter.Tk() cc = ColorChooser(root) cc.hsWheel.Set((1.0,0.0,0.0),mode = 'HSV') root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(cc.hsWheel.hsvColor,[1.0, 0.0, 0.0, 1.0]) self.assertEqual(cc.hsWheel.cursorX,50) self.assertEqual(cc.hsWheel.cursorY,50) root.destroy() def test_colorchooser_color_RGB(self): """tests colorchooser ,color wheel RGB colors """ root = Tkinter.Tk() cc = ColorChooser(root) cc.hsWheel.Set((1.0,0.0,0.0),mode = 'RGB') root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(cc.hsWheel.cursorX,100) self.assertEqual(cc.hsWheel.cursorY,50) self.assertEqual(cc.hsWheel.hsvColor[:3] != [1.0, 0.0, 0.0],True) root.destroy() def test_colorchooser_Wysiwyg(self): """tests colorchooser ,colorwheel setWysiwyg """ root = Tkinter.Tk() cc = ColorChooser(root) cc.hsWheel.Set((1.0,0.0,0.0),mode = 'HSV') #when On chooser colors are recomputed cc.hsWheel.setWysiwyg(1) root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(cc.hsWheel.hsvColor == [1.0, 0.0, 0.0, 1.0],True) cc.hsWheel.setWysiwyg(0) self.assertEqual(cc.hsWheel.hsvColor[:3] != [1.0, 0.0, 0.0],True) root.destroy() def test_colorchooser_value(self): """tests colorchooser,setting value """ root = Tkinter.Tk() cc = ColorChooser(root) cc.Set([0.5,0.5,0.]) self.assertEqual(cc.value.val,0.5) root.destroy() def test_color_add_remove_callback(self): """tests add,remove callback functions """ root = Tkinter.Tk() cc= ColorChooser(root) cc.hsWheel.AddCallback(MyCallback) root.wait_visibility(cc.hsWheel.canvas) self.assertEqual(len(cc.hsWheel.callbacks)>0,True) cc.hsWheel.RemoveCallback(MyCallback) cc.hsWheel.RemoveCallback(cc.UpdateCurrentColor) self.assertEqual(len(cc.hsWheel.callbacks),0) root.destroy() if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Ellipsoids.py0000644000175000017500000002376710651433502024525 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import sys, os,math,types,string from Tkinter import Menubutton import unittest from math import sqrt import numpy.oldnumeric as Numeric from DejaVu.Viewer import Viewer from DejaVu.Ellipsoids import Ellipsoids from string import split import Image class Ellipsoids__init__Tests(unittest.TestCase): """ tests for init: default values supplied for shape, slices, stacks, radius NB: if quality is supplied, it overrides default slices and stacks """ def test_defaults(self): """ test init with no parameters """ g = Ellipsoids() self.assertEqual(isinstance(g, Ellipsoids), True) def test_centers(self): """ test init with centers """ g = Ellipsoids(centers=[[1,1,1],[5,5,5]]) self.assertEqual(isinstance(g, Ellipsoids), True) def test_shape(self): """ test init with shape """ g = Ellipsoids(shape=(0,2)) self.assertEqual(isinstance(g, Ellipsoids), True) def test_quality(self): """ test init with quality """ g = Ellipsoids(quality=15) self.assertEqual(isinstance(g, Ellipsoids), True) class Ellipsoids_Set_Tests(unittest.TestCase): """ tests for Set: """ def setUp(self): """ setup Ellipsoid Geom """ rotcrn = Numeric.array( [[0.62831, -0.67899, -0.37974, 0],[0.36979, 0.69011, -0.62210, 0],[0.68446, 0.25045, 0.68468, 0],[0, 0, 0, 1]], 'f') transcrn = [9.26883, 9.78728, 6.96709] scalecrn = [8.0957, 11.7227, 16.2550] rotcv = Numeric.identity(4, 'f') transcv = [0.,0.,0.] scalecv = [7.8895, 5.5336, 3.3147] self.geom = Ellipsoids('ellipsoids1', centers=[transcv,transcrn],scaling = [scalecv, scalecrn],orientation = [rotcv, rotcrn],materials=[[1,0,0],[0,1,0]], inheritMaterial=0,quality=30) def tearDown(self): """ clean-up """ try: del(self.geom) except: pass #centers def test_Set_centers(self): """tests valid input for center """ self.geom.Set(centers = [[1,1,1],[5,5,5]]) self.assertEqual(split(str(self.geom.vertexSet.vertices.array),'\n'),['[[ 1. 1. 1.]', ' [ 5. 5. 5.]]']) def test_ellipsoids_center_invalid(self): """tests invalid input for center """ #self.assertRaises(AttributeError, self.geom.Set,centers ='hai') self.assertRaises(ValueError, self.geom.Set,centers ='hai') #quality AND #slices ??? def test_Set_quality(self): """ test Set with quality changes stacks """ val = 10 self.geom.Set(quality=val) self.assertEqual(self.geom.stacks, val) def test_ellipsoids_quality_slices(self): """tests valid input for quality """ self.geom.Set(quality = 10) self.assertEqual(self.geom.slices,10) def xtest_ellipsoids_quality_invalid(self): """tests invalid input for quality ###### it seems that we have always been accepting this invalid data #### """ self.geom.Set(quality ='hai') self.assertNotEqual(self.geom.slices, 'hai') self.assertNotEqual(self.geom.stacks, 'hai') #scaling def test_ellipsoids_scaling(self): """tests valid input for scaling """ self.geom.Set(scaling = [[8,8,8],[7.5,7.5,7.5]]) self.assertEqual(split(str(self.geom.scaling),'\n'),['[[ 8. 8. 8. ]', ' [ 7.5 7.5 7.5]]']) def test_ellipsoids_scaling_invalid(self): """tests invalid input for scaling """ # self.geom.Set(scaling ='hai') # self.assertNotEqual(self.geom.scaling, 'hai') self.assertRaises(ValueError, self.geom.Set,scaling ='hai') ##orientation # def test_ellipsoids_orientation(self): # """tests valid input for orientation # """ # a = Numeric.array( [[0.52831, -0.57899, -0.57974, 0],[0.56979, 0.89011, -0.42210, 0],[0.48446, 0.15045, 0.97, 0],[0, 0, 0, 1]], 'f') # b = Numeric.identity(4, 'f') # self.geom.Set(orientation = [b,a]) # result = [[[ 1. , 0. , 0. , 0. ], # [ 0. , 1. , 0. , 0. ], # [ 0. , 0. , 1. , 0. ], # [ 0. , 0. , 0. , 1. ]], # [[ 0.52831 , -0.57898998, -0.57973999, 0. ], # [ 0.56979001, 0.89011002, -0.42210001, 0. ], # [ 0.48446 , 0.15045001, 0.97000003, 0. ], # [ 0. , 0. , 0. , 1. ]]] # self.assertTrue(numpy.alltrue(self.geom.orientation==result)) def test_ellipsoids_orientation_invalid(self): """tests invalid input for orientation """ self.assertRaises(ValueError, self.geom.Set,orientation = 'hai') #stacks def test_ellipsoids_stacks(self): """tests valid input for stacks """ self.geom.Set(stacks = 25) self.assertEqual(self.geom.stacks,25) def xtest_ellipsoids_stacks_invalid(self): """tests invalid input for stacks ###### it seems that we have always been accepting this invalid data #### """ self.geom.Set(stacks = 'hai') self.assertNotEqual(self.geom.stacks, 'hai') class Ellipsoids_Viewer_Tests(unittest.TestCase): """ setUp + tearDown form a fixture: working environment for the testing code """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) rotcrn = Numeric.array( [[0.62831, -0.67899, -0.37974, 0],[0.36979, 0.69011, -0.62210, 0],[0.68446, 0.25045, 0.68468, 0],[0, 0, 0, 1]], 'f') transcrn = [9.26883, 9.78728, 6.96709] scalecrn = [8.0957, 11.7227, 16.2550] rotcv = Numeric.identity(4, 'f') transcv = [0.,0.,0.] scalecv = [7.8895, 5.5336, 3.3147] self.geom = Ellipsoids('ellipsoids', centers=[transcv,transcrn], scaling = [scalecv, scalecrn], orientation = [rotcv, rotcrn], materials=((1,0,0),), inheritMaterial=0, quality=30) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGui... def test_Ellipsoids_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt+1][midpt+1][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) def test_ellipsoids_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(round(buff_255[midpt][midpt][0],1)>0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageel.tif") im = Image.open("./saveimageel.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum=Numeric.add.reduce(narray_255) #print sum d=buff_255_sum-narray_255_sum #self.assertEqual(d,0) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) if __name__ == '__main__': test_cases = [ 'Ellipsoids__init__Tests', 'Ellipsoids_Set_Tests', 'Ellipsoids_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Viewer.py0000644000175000017500000002234110616454505023651 0ustar debiandebianimport sys from mglutil.regression import testplus import unittest from DejaVu.Geom import Geom from DejaVu.Points import Points from DejaVu.Viewer import Viewer from DejaVu.Polylines import Polylines class TestViewer(unittest.TestCase): def setUp(self): self.vi = Viewer(verbose = 0) def tearDown(self): self.vi.Exit() def test_AddObject(self): # MasterGeom1 mg = Geom('mol1', shape=(0,0), visible=1) wire = Geom('lines', shape=(0,0), visible=1) # lines: Bonded atoms are represented by IndexedPolyLines lcoords = [[[17.0, 14.0, 4.0], [17.0, 13.0, 4.0], [16.0, 13.0, 5.0], [15.0, 14.0, 6.0], [18.0, 13.0, 5.0], [19.0, 13.0, 4.0], [18.0, 12.0, 6.0], [15.0, 12.0, 5.0], [14.0,11.0, 6.0], [14.0, 11.0, 7.0], [15.0, 10.0, 7.0], [13.0, 11.0, 5.0], [13.0, 9.0, 5.0], [12.0, 11.0, 4.0], [13.0, 11.0, 8.0], [14.0, 11.0, 10.0], [12.0, 10.0, 10.0], [11.0, 11.0, 10.0], [14.0, 12.0, 11.0], [16.0, 12.0, 10.0], [12.0, 9.0, 11.0], [11.0, 9.0, 11.0]]] l = Polylines("bonded", vertices=lcoords, visible=1, pickableVertices=1, lineWidth=3, inheritMaterial=0, inheritLineWidth=0) # nobnds : Non Bonded atoms are represented by Points pcoords = [[11.0, 9.0, 13.0], [12.0, 8.0, 13.0], [10.0, 8.0, 11.0], [10.0, 8.0, 9.0], [10.0, 9.0, 14.0], [9.0, 9.0, 15.0], [9.0, 8.0, 16.0], [9.0, 8.0, 17.0], [8.0, 10.0, 15.0], [7.0, 10.0, 14.0], [8.0, 10.0, 13.0]] p = Points( "nobnds", shape=(0,3), pointWidth=6, visible=1,vertices = pcoords, inheritMaterial=0) # bondorder : Bond Order are represented by Indexed PolyLines b = Polylines('bondorder', visible=1, lineWidth=3, inheritMaterial=0) # MasterGeom2 mg2 =Geom('mol2', shape=(0,0), visible=1) wire2 = Geom('lines', shape=(0,0), visible=1) # lines: Bonded atoms are represented by IndexedPolyLines l2coords = [[[18.0, 14.0, 4.0], [18.0, 13.0, 4.0], [17.0, 13.0, 5.0], [16.0, 14.0, 6.0], [19.0, 13.0, 5.0], [20.0, 13.0, 4.0], [19.0, 12.0, 6.0], [16.0, 12.0, 5.0], [15.0,11.0, 6.0], [15.0, 11.0, 7.0], [16.0, 10.0, 7.0], [14.0, 11.0, 5.0], [14.0, 9.0, 5.0], [13.0, 11.0, 4.0], [14.0, 11.0, 8.0], [15.0, 11.0, 10.0], [13.0, 10.0, 10.0], [12.0, 11.0, 10.0], [15.0, 12.0, 11.0], [17.0, 12.0, 10.0], [13.0, 9.0, 11.0], [12.0, 9.0, 11.0]]] l2 = Polylines("bonded", vertices=l2coords, visible=1, pickableVertices=1, lineWidth=3, inheritMaterial=0, inheritLineWidth=0) # nobnds : Non Bonded atoms are represented by Points p2coords = [[12.0, 9.0, 13.0], [13.0, 8.0, 13.0], [11.0, 8.0, 11.0], [11.0, 8.0, 9.0], [11.0, 9.0, 14.0], [10.0, 9.0, 15.0], [10.0, 8.0, 16.0], [10.0, 8.0, 17.0], [9.0, 10.0, 15.0], [8.0, 10.0, 14.0], [9.0, 10.0, 13.0]] p2 = Points( "nobnds", shape=(0,3), pointWidth=6, visible=1,vertices = p2coords, inheritMaterial=0) # bondorder : Bond Order are represented by Indexed PolyLines b2 = Polylines('bondorder', visible=1, lineWidth=3, inheritMaterial=0) # Create a hierarchy of geometries. self.vi.AddObject(mg) wire.replace = True self.vi.AddObject(wire, parent=mg, redo=0) l.replace = True self.vi.AddObject(l, parent=wire, redo=0) p.replace = True self.vi.AddObject(p, parent=wire, redo=0) b.replace = True self.vi.AddObject(b, parent=wire, redo=0) self.vi.AddObject(mg2) wire2.replace = True self.vi.AddObject(wire2, parent=mg2, redo=0) l2.replace = True self.vi.AddObject(l2, parent=wire2, redo=0) p2.replace = True self.vi.AddObject(p2, parent=wire2, redo=0) b2.replace = True self.vi.AddObject(b2, parent=wire2, redo=0) # Make sure that each entry has been added to its proper place in the # object listbox. def test_DeleteObject(self): # MasterGeom1 mg = Geom('mol1', shape=(0,0), visible=1) wire = Geom('lines', shape=(0,0), visible=1) # lines: Bonded atoms are represented by IndexedPolyLines lcoords = [[[17.0, 14.0, 4.0], [17.0, 13.0, 4.0], [16.0, 13.0, 5.0], [15.0, 14.0, 6.0], [18.0, 13.0, 5.0], [19.0, 13.0, 4.0], [18.0, 12.0, 6.0], [15.0, 12.0, 5.0], [14.0,11.0, 6.0], [14.0, 11.0, 7.0], [15.0, 10.0, 7.0], [13.0, 11.0, 5.0], [13.0, 9.0, 5.0], [12.0, 11.0, 4.0], [13.0, 11.0, 8.0], [14.0, 11.0, 10.0], [12.0, 10.0, 10.0], [11.0, 11.0, 10.0], [14.0, 12.0, 11.0], [16.0, 12.0, 10.0], [12.0, 9.0, 11.0], [11.0, 9.0, 11.0]]] l = Polylines("bonded", vertices=lcoords, visible=1, pickableVertices=1, lineWidth=3, inheritMaterial=0, inheritLineWidth=0) # nobnds : Non Bonded atoms are represented by Points pcoords = [[11.0, 9.0, 13.0], [12.0, 8.0, 13.0], [10.0, 8.0, 11.0], [10.0, 8.0, 9.0], [10.0, 9.0, 14.0], [9.0, 9.0, 15.0], [9.0, 8.0, 16.0], [9.0, 8.0, 17.0], [8.0, 10.0, 15.0], [7.0, 10.0, 14.0], [8.0, 10.0, 13.0]] p = Points( "nobnds", shape=(0,3), pointWidth=6, visible=1,vertices = pcoords, inheritMaterial=0) # bondorder : Bond Order are represented by Indexed PolyLines b = Polylines('bondorder', visible=1, lineWidth=3, inheritMaterial=0) # MasterGeom2 mg2 =Geom('mol2', shape=(0,0), visible=1) wire2 = Geom('lines', shape=(0,0), visible=1) # lines: Bonded atoms are represented by IndexedPolyLines l2coords = [[[18.0, 14.0, 4.0], [18.0, 13.0, 4.0], [17.0, 13.0, 5.0], [16.0, 14.0, 6.0], [19.0, 13.0, 5.0], [20.0, 13.0, 4.0], [19.0, 12.0, 6.0], [16.0, 12.0, 5.0], [15.0,11.0, 6.0], [15.0, 11.0, 7.0], [16.0, 10.0, 7.0], [14.0, 11.0, 5.0], [14.0, 9.0, 5.0], [13.0, 11.0, 4.0], [14.0, 11.0, 8.0], [15.0, 11.0, 10.0], [13.0, 10.0, 10.0], [12.0, 11.0, 10.0], [15.0, 12.0, 11.0], [17.0, 12.0, 10.0], [13.0, 9.0, 11.0], [12.0, 9.0, 11.0]]] l2 = Polylines("bonded", vertices=l2coords, visible=1, pickableVertices=1, lineWidth=3, inheritMaterial=0, inheritLineWidth=0) # nobnds : Non Bonded atoms are represented by Points p2coords = [[12.0, 9.0, 13.0], [13.0, 8.0, 13.0], [11.0, 8.0, 11.0], [11.0, 8.0, 9.0], [11.0, 9.0, 14.0], [10.0, 9.0, 15.0], [10.0, 8.0, 16.0], [10.0, 8.0, 17.0], [9.0, 10.0, 15.0], [8.0, 10.0, 14.0], [9.0, 10.0, 13.0]] p2 = Points( "nobnds", shape=(0,3), pointWidth=6, visible=1,vertices = p2coords, inheritMaterial=0) # bondorder : Bond Order are represented by Indexed PolyLines b2 = Polylines('bondorder', visible=1, lineWidth=3, inheritMaterial=0) # Create a hierarchy of geometries. self.vi.AddObject(mg) wire.replace = True self.vi.AddObject(wire, parent=mg, redo=0) l.replace = True self.vi.AddObject(l, parent=wire, redo=0) p.replace = True self.vi.AddObject(p, parent=wire, redo=0) b.replace = True self.vi.AddObject(b, parent=wire, redo=0) self.vi.AddObject(mg2) wire2.replace = True self.vi.AddObject(wire2, parent=mg2, redo=0) l2.replace = True self.vi.AddObject(l2, parent=wire2, redo=0) p2.replace = True self.vi.AddObject(p2, parent=wire2, redo=0) b2.replace = True self.vi.AddObject(b2, parent=wire2, redo=0) # Make sure that each entry has been added to its proper place in the # object listbox. def test_AddObjectWhenExistsObjectWithSameName(self): from DejaVu import Viewer vi = Viewer() from DejaVu.IndexedPolygons import IndexedPolygons p1 = IndexedPolygons('foo', protected=True) vi.AddObject(p1) p2 = IndexedPolygons('foo', protected=True) try: vi.AddObject(p2) except RuntimeError: return raise RuntimeError('second geom with same name should not be \ added, a ValueError should have been raised') ## harness = testplus.TestHarness( __name__, ## connect = setUp, ## funs = testplus.testcollect( globals()), ## disconnect = tearDown ## ) ## if __name__ == '__main__': ## testplus.chdir() ## print harness ## sys.exit( len( harness)) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_basics.py0000644000175000017500000001023110651433502023640 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import sys from time import sleep import sys, os,math,types import unittest, numpy.oldnumeric as Numeric from DejaVu.Viewer import Viewer from time import sleep from Tkinter import Tk, Frame, Toplevel from DejaVu.Spheres import Spheres class basics_Tkinter_Viewer_Tests(unittest.TestCase): """ tests for Tkinter basics in DejaVu.Viewer """ def setUp(self): self.root = Tk() self.root.withdraw() def tearDown(self): try: self.root.destroy() except: pass def test_01_constructViewerWhenTkDefaultRootExists(self): """check creating viewer when Tkinter.root already exists """ # this test would fail if DejaVu.Viewer would try to create independent Tk # instances, because Pmw cannot handle several instances vi = Viewer(verbose=0) vi.Exit() self.assertEqual(1,1) def test_ViewerWithMaster(self): """create a viewer for a given master and destroy it""" master = Frame(self.root) master.pack() vi = Viewer(verbose=0, master=master) self.assertEqual( vi.master, master) vi.Exit() def test_ViewerWithFrameGuiMaster(self): """create a viewer with a frame to pack the GUI and destroy it""" master = Frame(self.root) master.pack() vi = Viewer(verbose=0, guiMaster=master) self.assertEqual(vi.master.master, self.root) self.assertEqual(vi.GUI.root, master) vi.Exit() def test_ViewerWithToplevelGuiMaster(self): """create a viewer with a frame to pack the GUI and destroy it""" master = Toplevel(self.root) vi = Viewer(verbose=0, guiMaster=master) self.assertEqual(vi.master.master.master, self.root) self.assertEqual(vi.GUI.root, master) vi.Exit() class basics_Viewer_Tests(unittest.TestCase): """ tests for basics in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass def test_deleteCamera(self): """ check viewer.deleteCamera """ self.vi.DeleteCamera(self.vi.cameras[0]) self.assertEqual(1,1) def test_deleteCamera2(self): """ check viewer.deleteCamera """ self.vi.AddCamera() self.vi.DeleteCamera(self.vi.cameras[1]) self.assertEqual(1,1) def test_TwoViewers1(self): """create 2 viewers and destroy them""" # this test makes sure that the GUI has different roots vi2 = Viewer(verbose=0) self.assertNotEqual( self.vi.master , vi2.master) #vi2.Exit() def test_2cameras(self): """display 4 spheres in 2 different cameras""" s1 = Spheres('sph', vertices = [[0,0,0], [3,0,0], [0,3,0], [0,0,3]]) self.vi.AddObject(s1) ## add a second camera self.vi.AddCamera() self.assertEqual(1,1) def test_multipleViewers(self): """create 3 independent viewers""" s1 = Spheres('sph', vertices = [[0,0,0], [3,0,0], [0,5,0], [0,0,3]], materials = ((1,0,0),), inheritMaterial=0) self.vi.AddObject(s1) vi2 = Viewer(verbose=0) s2 = Spheres('sph', vertices = [[0,0,0], [3,0,0], [0,3,0], [0,0,3]], materials = ((0,1,0),), inheritMaterial=0) vi2.AddObject(s2) vi3 = Viewer(verbose=0) s3 = Spheres('sph', vertices = [[0,0,0], [3,0,0], [0,3,0], [0,0,3]], materials = ((0,0,1),), inheritMaterial=0) vi3.AddObject(s3) vi2.Exit() vi3.Exit() if sys.platform == 'darwin': self.vi.currentCamera.Activate() # needed on our ppcdarwin7 self.assertEqual(1,1) if __name__ == '__main__': test_cases = [ 'basics_Tkinter_Viewer_Tests', 'basics_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_IndexedPolylines.py0000644000175000017500000001720110657070407025666 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_IndexedPolylines.py,v 1.14 2007/08/10 14:07:03 vareille Exp $ # # import unittest import numpy import sys, os from math import sqrt from Tkinter import Menubutton from opengltk.OpenGL import GL from geomutils.geomalgorithms import TriangleNormals import numpy.oldnumeric as Numeric, types from DejaVu.Viewer import Viewer from DejaVu.IndexedPolylines import IndexedPolylines import Image class IndexedPolylines__init__Tests(unittest.TestCase): """tests for IndexedPolylines.__init__ """ def setUp(self): """ create geom """ self.geom = IndexedPolylines(name='basic') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_basic(self): """sanity check """ self.assertEqual(1,1) def test_basic_init(self): """check object is created """ self.assertEqual(isinstance(self.geom, IndexedPolylines), True) class IndexedPolylines_Set_Tests(unittest.TestCase): """tests for Set, Add methods """ def setUp(self): """ #create geom """ self.geom = IndexedPolylines('geom',materials=((0,1,0),), vertices=((0,0,0),(1,0,0),(0,1,0)), faces=((0,1),(1,2))) def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_IndexedPolylines_faces(self): """check len(faces) """ self.assertEqual(len(self.geom.faceSet.faces.array), 2) def test_IndexedPolylines_faces_invalid_not_sequence(self): """invalid input for faces, faces should be list of lists of integers """ self.assertRaises(TypeError,self.geom.Set,faces = 20) def test_IndexedPolylines_faces_invalid(self): """invalid input for faces, -20 not a good index """ self.assertRaises(ValueError,self.geom.Set, faces = [[-20,3,4]]) def test_IndexedPolylines_faceSet_normals(self): """check len(faceSet.normals) """ self.assertEqual(len(self.geom.faceSet.normals), 0) def test_IndexedPolylines_primitiveType_GL_LINES(self): """check primitiveType, GL_LINES """ self.assertEqual(self.geom.primitiveType, GL.GL_LINES) def test_IndexedPolylines_linewidth(self): """valid input for lineWidth """ val = 3 self.geom.Set(lineWidth=val) newstate = self.geom.getState()['lineWidth'] self.assertEqual(self.geom.getState()['lineWidth'], val) def test_Add_vertices(self): """valid input for Add vertices """ old_len = len(self.geom.vertexSet.vertices.array) self.geom.Add(vertices=((2,0,0),(4,0,0), (6,0,0))) self.assertEqual(len(self.geom.vertexSet.vertices.array), old_len+3) class IndexedPolylines_Viewer_Tests(unittest.TestCase): """ tests for IndexedPolylines in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.geom = IndexedPolylines('test', vertices =((-1,0,0),(5.,0.,0.)), faces=((0,1),), materials=((.5,0,0),), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #IndexedPolylines test of setting properties via DejaVuGui... def test_IndexedPolylines_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #IndexedPolylines 3D image def test_IndexedPolylines_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimage....tif") im = Image.open("./saveimage....tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) # for v in d: # self.assertTrue(v[0]<1.e-9 and v[0]>-1.e-9) # self.assertTrue(v[1]<1.e-9 and v[1]>-1.e-9) # self.assertTrue(v[2]<1.e-9 and v[2]>-1.e-9) if __name__ == '__main__': test_cases = [ 'IndexedPolylines__init__Tests', 'IndexedPolylines_Set_Tests', 'IndexedPolylines_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #remove the -v flag to make output cleaner #unittest.main( argv=([__name__ ,'-v'] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_GridBox.py0000644000175000017500000001704310651433502023742 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_GridBox.py,v 1.12 2007/07/24 17:30:42 vareille Exp $ # # import unittest import sys, os,math import numpy.oldnumeric as Numeric from opengltk.OpenGL import GL #import Materials, viewerConst, datamodel, Clip from DejaVu.Viewer import Viewer from math import sqrt from DejaVu.Box import GridBox import Image from time import sleep from Tkinter import Menubutton #Grid Box class GridBox__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = [ 'npts', 'xnpts', 'ynpts', 'znpts', 'spacing', 'xspacing', 'yspacing', 'zspacing', ] all other keywords are handled by Geom.__init__ method """ #defaults def test_GridBox_defaults(self): """defaults """ g = GridBox() self.assertEqual(isinstance(g, GridBox), True) #npts def test_GridBox_shape(self): """npts default is 40 """ g = GridBox(npts=20) self.assertEqual(isinstance(g, GridBox), True) #xnpts def test_GridBox_shape(self): """xnpts default is 40 """ g = GridBox(xnpts=20) self.assertEqual(isinstance(g, GridBox), True) #ynpts def test_GridBox_shape(self): """ynpts default is 40 """ g = GridBox(ynpts=20) self.assertEqual(isinstance(g, GridBox), True) #znpts def test_GridBox_shape(self): """znpts default is 40 """ g = GridBox(znpts=20) self.assertEqual(isinstance(g, GridBox), True) #spacing def test_GridBox_shape(self): """spacing default is .375 """ g = GridBox(spacing=.20) self.assertEqual(isinstance(g, GridBox), True) #xspacing def test_GridBox_shape(self): """xspacing default is .375 """ g = GridBox(xspacing=.20) self.assertEqual(isinstance(g, GridBox), True) #yspacing def test_GridBox_shape(self): """yspacing default is .375 """ g = GridBox(yspacing=.20) self.assertEqual(isinstance(g, GridBox), True) #zspacing def test_GridBox_shape(self): """zspacing default is .375 """ g = GridBox(zspacing=.20) self.assertEqual(isinstance(g, GridBox), True) class GridBox_Set_Tests(unittest.TestCase): """ # does override Geom.Set ???? one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = GridBox(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_GridBox_Set_spacing(self): """ test Setting angles """ self.geom.Set(spacing=(.5,.375, .1)) self.assertEqual(self.geom.xspacing, .5) def test_GridBox_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) class GridBox_Viewer_Tests(unittest.TestCase): """ tests for GridBox in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) #put box with one corner on origin... self.geom = GridBox('gridbox', origin =(0,0,0), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.geom.frontPolyMode = GL.GL_LINE self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGuiGridBox def test_GridBox_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() #sleep(5) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Arcs 3D image def test_GridBox_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black #import pdb;pdb.set_trace() self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) #sleep(5) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageGridBox.tif") im = Image.open("./saveimageGridBox.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) if __name__ == '__main__': test_cases = [ 'GridBox__init__Tests', 'GridBox_Set_Tests', 'GridBox_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_DataOutput.py0000644000175000017500000001052111156264075024500 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import string, sys import numpy.oldnumeric as Numeric from mglutil.regression import testplus from DejaVu.DataOutput import OutputVRML2 from time import sleep from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.Viewer import Viewer from DejaVu.Texture import Texture from DejaVu.colorTool import RGBRamp def pause(sleepTime=0.4): sleep(sleepTime) #def setUp(): # pass def mapToTexture(ramp): return Numeric.array(Numeric.array(ramp)*255).astype('B') def buildVertToTexCoords(verts, texCoords): d = {} i = 0 for v in verts: d[str(v[0])+str(v[1])+str(v[2])] = texCoords[i] i = i + 1 return d def getTexCoords(vertices, lookup): tx = map(lambda v, l=lookup: l[str(v[0])+str(v[1])+str(v[2])], vertices) tx = Numeric.array(tx) tx.shape = (-1,1) return tx def test_getVRML2(): # first, lets test if we can create a vrml2 file vi = Viewer(verbose=False) points = [ [-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1], [-1, 1, -1], [-1, -1, -1] ] indices = [ [0, 1, 3, 2], [4, 5, 7, 6], [6, 7, 1, 0], [2, 3, 5, 4], [6, 0, 2, 4], [1, 7, 5, 3] ] geomBox = IndexedPolygons("box", vertices=points, faces=indices, visible=1) vi.AddObject(geomBox) V = OutputVRML2() vrml2 = V.getVRML2(vi.rootObject) assert len(vrml2) # now test the file Group = None children = None Transform = None Shape = None geometry=None IndexedFaceSet = None coord = None Coordinate = None point = None coordIndex = None # check that we have the following keywords for line in vrml2: for item in string.split(line): if item == 'Group': Group = 1 elif item == 'children' : children = 1 elif item == 'Transform': Transform = 1 elif item == 'Shape': Shape = 1 elif item == 'geometry': geometry = 1 elif item == 'IndexedFaceSet': IndexedFaceSet = 1 elif item == 'coord': coord = 1 elif item == 'Coordinate': Coordinate = 1 elif item == 'point': point = 1 elif item == 'coordIndex': coordIndex = 1 assert Group == 1 assert children == 1 assert Transform == 1 assert Shape == 1 assert geometry == 1 assert IndexedFaceSet == 1 assert coord == 1 assert Coordinate == 1 assert point == 1 assert coordIndex == 1 vi.Exit() def test_getVRML2withTexture(): vi = Viewer(verbose=False) points = [ [-1, 1, 1], [-1, -1, 1], [1, 1, 1], [1, -1, 1], [1, 1, -1], [1, -1, -1], [-1, 1, -1], [-1, -1, -1] ] indices = [ [0, 1, 3, 2], [4, 5, 7, 6], [6, 7, 1, 0], [2, 3, 5, 4], [6, 0, 2, 4], [1, 7, 5, 3] ] geomBox = IndexedPolygons("box", vertices=points, faces=indices, visible=1) # add texture to geom prop = Numeric.array(range(0,255,36)).astype('f') ramp = RGBRamp() tex = mapToTexture(ramp) t = Texture() t.Set(enable=1, image=tex) geomBox.Set(texture=t) lookup = buildVertToTexCoords(geomBox.vertexSet.vertices.array, prop) tx = getTexCoords(geomBox.vertexSet.vertices.array, lookup) geomBox.Set(textureCoords=tx) # create viewer, add object to viewer and get vrml2 vi.AddObject(geomBox) V = OutputVRML2() vrml2 = V.getVRML2(vi.rootObject) # check that we have the following keywords texture = None PixelTexture = None image = None texCoord =None TextureCoordinate = None for line in vrml2: for item in string.split(line): if item == 'texture': texture = 1 elif item == 'PixelTexture': PixelTexture = 1 elif item == 'image': image = 1 elif item == 'texCoord': texCoord = 1 elif item == 'TextureCoordinate': TextureCoordinate = 1 assert texture == 1 assert PixelTexture == 1 assert image == 1 assert texCoord == 1 assert TextureCoordinate == 1 vi.Exit() harness = testplus.TestHarness( __name__, #connect = setUp, funs = testplus.testcollect( globals()), ) if __name__ == '__main__': testplus.chdir() print harness sys.exit( len( harness)) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Light.py0000644000175000017500000010175012046002146023446 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # $Id: # import unittest from opengltk.OpenGL import GL from opengltk.exception import GLerror from opengltk.extent.utillib import glCleanRotMat import numpy.oldnumeric as Numeric from DejaVu import Viewer from DejaVu.Spheres import Spheres import math from mglutil.math.rotax import rotax from DejaVu.colorTool import OneColor from DejaVu.Transformable import Transformable class Light_BaseTests(unittest.TestCase): """ setUp + tearDown form a fixture: working environment for the testing code """ def setUp(self): """ start Viewer """ if not hasattr(self, 'vi'): self.vi = Viewer(verbose=False) #self.vi.cameras[0].master.master.withdraw() self.vi.master.update_idletasks() self.light = self.vi.currentLight self.orig_state = self.light.getState() def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #Name def test_Name(self): """ Name is light0 """ self.assertEqual(self.light.name, 'light 0') #end Name #AMBIENT def test_Set_ambient_attr(self): """ Set ambient changes light ambient attribute """ self.light.Set(ambient=(0.0,0.5,0.5,1.0)) ambi = self.light.ambient self.assertEqual(ambi[0], 0) self.assertEqual(round(ambi[1],1), 0.5) self.assertEqual(round(ambi[2],1), 0.5) self.assertEqual(round(ambi[3],1), 1.0) def test_Setambient_GL(self): """ Set ambient changes GL_AMBIENT """ self.light.Set(ambient=(0,0,0,0)) ambi= GL.glGetLightfv(self.light.num, GL.GL_AMBIENT) self.assertEqual(ambi[0],0) self.assertEqual(ambi[1], 0.) self.assertEqual(ambi[2], 0.) self.assertEqual(ambi[3], 0.) def test_Setambient_state(self): """ Set light changes light's state['ambient'] """ self.light.Set(ambient=(1,0,0,0)) state = self.light.getState() ambi = state['ambient'] self.assertEqual(round(ambi[0],1), 1.) self.assertEqual(ambi[1], 0.) self.assertEqual(ambi[2], 0.) self.assertEqual(ambi[3], 0.) def test_Setambient_bad_input(self): """ ValueError raised on bad input to Set ambient """ self.assertRaises(ValueError, self.light.Set ,ambient=(1,0)) def test_Setambient_empty_input(self): """ ValueError raised on empty input to Set ambient """ self.assertRaises(ValueError, self.light.Set, ambient=()) def test_Setambient_too_much_input(self): """ ValueError raised on too_much input to Set ambient """ self.assertRaises(ValueError, self.light.Set,ambient=(1,0,0,1,1)) #end AMBIENT #DIFFUSE def test_Set_diffuse_attr(self): """ Set diffuse changes light diffuse attribute """ self.light.Set(diffuse=(0.0,0.5,0.5,1.0)) diffuse = self.light.diffuse self.assertEqual(diffuse[0], 0) self.assertEqual(round(diffuse[1],1), 0.5) self.assertEqual(round(diffuse[2],1), 0.5) self.assertEqual(round(diffuse[3],1), 1.0) def test_Setdiffuse_GL(self): """ Set diffuse changes GL_DIFFUSE """ self.light.Set(diffuse=(1,0,0,0)) diffuse= GL.glGetLightfv(self.light.num, GL.GL_DIFFUSE) self.assertEqual(round(diffuse[0],1), 1.) self.assertEqual(diffuse[1], 0.) self.assertEqual(diffuse[2], 0.) self.assertEqual(diffuse[3], 0.) def test_Setdiffuse_state(self): """ Set light changes light's state['diffuse'] """ self.light.Set(diffuse=(1,0,0,0)) state = self.light.getState() diffuse = state['diffuse'] self.assertEqual(round(diffuse[0],1), 1.) self.assertEqual(diffuse[1], 0.) self.assertEqual(diffuse[2], 0.) self.assertEqual(diffuse[3], 0.) def test_Setdiffuse_bad_input(self): """ ValueError raised on bad input to Set diffuse """ self.assertRaises(ValueError, self.light.Set ,diffuse=(1,0)) def test_Setdiffuse_empty_input(self): """ ValueError raised on empty input to Set diffuse """ self.assertRaises(ValueError, self.light.Set, diffuse=()) def test_Setdiffuse_too_much_input(self): """ ValueError raised on too_much input to Set diffuse """ self.assertRaises(ValueError, self.light.Set,diffuse=(1,0,0,1,1)) #end DiFFUSE #SPECULAR def test_Set_specular_attr(self): """ Set specular changes light specular attribute """ self.light.Set(specular=(0.0,0.5,0.5,1.0)) specular = self.light.specular self.assertEqual(specular[0], 0) self.assertEqual(round(specular[1],1), 0.5) self.assertEqual(round(specular[2],1), 0.5) self.assertEqual(round(specular[3],1), 1.0) def test_Setspecular_GL(self): """ Set specular changes GL_SPECULAR """ self.light.Set(specular=(1,0,0,0)) specular= GL.glGetLightfv(self.light.num, GL.GL_SPECULAR) self.assertEqual(round(specular[0],1), 1.) self.assertEqual(specular[1], 0.) self.assertEqual(specular[2], 0.) self.assertEqual(specular[3], 0.) def test_Setspecular_state(self): """ Set light changes light's state['specular'] """ self.light.Set(specular=(1,0,0,0)) state = self.light.getState() specular = state['specular'] self.assertEqual(round(specular[0],1), 1.) self.assertEqual(specular[1], 0.) self.assertEqual(specular[2], 0.) self.assertEqual(specular[3], 0.) def test_Setspecular_bad_input(self): """ ValueError raised on bad input to Set specular """ self.assertRaises(ValueError, self.light.Set ,specular=(1,0)) def test_Setspecular_empty_input(self): """ ValueError raised on empty input to Set specular """ self.assertRaises(ValueError, self.light.Set, specular=()) def test_Setspecular_too_much_input(self): """ ValueError raised on too_much input to Set specular """ self.assertRaises(ValueError, self.light.Set,specular=(1,0,0,1,1)) # END SPECULAR #DIRECTION def test_Set_direction_attr(self): """ Set direction changes light direction attribute """ self.light.Set(direction=(1,1,1,0)) direction = self.light.direction self.assertEqual(direction[0], 1) self.assertEqual(round(direction[1],1), 1) self.assertEqual(round(direction[2],1), 1) self.assertEqual(round(direction[3],1), 0) def test_Setdirection_state(self): """ Set light changes light's state['direction'] """ self.light.Set(direction=(1,0,0,0)) state = self.light.getState() direction = state['direction'] self.assertEqual(round(direction[0],1), 1.) self.assertEqual(direction[1], 0.) self.assertEqual(direction[2], 0.) self.assertEqual(direction[3], 0.) def test_Setdirection_bad_input(self): """ AssertionError raised on bad input to Set direction """ self.assertRaises(AssertionError, self.light.Set ,direction=(1,0)) def test_Setdirection_empty_input(self): """ AssertionError raised on empty input to Set direction """ self.assertRaises(AssertionError, self.light.Set, direction=()) def test_Setdirection_too_much_input(self): """ AssertionError raised on too_much input to Set direction """ self.assertRaises(AssertionError, self.light.Set,direction=(1,0,0,1,1)) #END DIRECTION #POSITION def test_Set_position_attr(self): """ Set position changes light position attribute """ self.light.Set(position=(1,1,1,1)) position = self.light.position self.assertEqual(position[0], 1) self.assertEqual(round(position[1],1), 1) self.assertEqual(round(position[2],1), 1) self.assertEqual(round(position[3],1), 1) def test_Setposition_state(self): """ Set position changes light's state['position'] """ self.light.Set(position=(1,0,0,1)) state = self.light.getState() position = state['position'] self.assertEqual(round(position[0],1), 1.) self.assertEqual(position[1], 0.) self.assertEqual(position[2], 0.) self.assertEqual(position[3], 1.) def test_Setposition_bad_input(self): """ AssertionError raised on bad input to Set position """ self.assertRaises(AssertionError, self.light.Set ,position=(1,0)) def test_Setposition_empty_input(self): """ AssertionError raised on empty input to Set position """ self.assertRaises(AssertionError, self.light.Set, position=()) def test_Setposition_too_much_input(self): """ AssertionError raised on too_much input to Set position """ self.assertRaises(AssertionError, self.light.Set,position=(1,0,0,1,1)) #END POSITION #SPOT DIRECTION def test_Set_spotDirection_attr(self): """ Set spotDirection changes light spotDirection attribute """ self.light.Set(spotDirection=(1,1,-1,0)) spotDirection = self.light.spotDirection self.assertEqual(spotDirection[0], 1) self.assertEqual(round(spotDirection[1],1), 1) self.assertEqual(round(spotDirection[2],1), -1) self.assertEqual(round(spotDirection[3],1), 0) def test_SetspotDirection_state(self): """ Set light changes light's state['spotDirection'] """ self.light.Set(spotDirection=(1,0,0,0)) state = self.light.getState() spotDirection = state['spotDirection'] self.assertEqual(round(spotDirection[0],1), 1.) self.assertEqual(spotDirection[1], 0.) self.assertEqual(spotDirection[2], 0.) self.assertEqual(spotDirection[3], 0.) def test_SetspotDirection_bad_input(self): """ AssertionError raised on bad input to Set spotDirection """ self.assertRaises(AssertionError, self.light.Set ,spotDirection=(1,0)) def test_SetspotDirection_empty_input(self): """ AssertionError raised on empty input to Set spotDirection """ self.assertRaises(AssertionError, self.light.Set, spotDirection=()) def test_SetspotDirection_too_much_input(self): """ AssertionError raised on too_much input to Set spotDirection """ self.assertRaises(AssertionError, self.light.Set,spotDirection=(1,0,0,1,1)) #END SPOT DIRECTION #SPOT EXPONENT def test_Set_spotExponent_attr(self): """ Set spotExponent changes light spotExponent attribute """ self.light.Set(spotExponent=1.0) spotExponent = self.light.spotExponent self.assertEqual(spotExponent, 1.0) def test_SetspotExponent_state(self): """ Set light changes light's state['spotExponent'] """ self.light.Set(spotExponent=1.0) state = self.light.getState() spotExponent = state['spotExponent'] self.assertEqual(round(spotExponent,1), 1.0) def test_SetspotExponent_bad_input(self): """ ValueError raised on bad input to Set spotExponent """ self.assertRaises(ValueError, self.light.Set ,spotExponent='shkdj') def test_SetspotExponent_empty_input(self): """ ValueError raised on empty input to Set spotExponent """ self.assertRaises(ValueError, self.light.Set, spotExponent=' ') def test_SetspotExponent_too_much_input(self): """ ValueError raised on too_much input to Set spotExponent************** """ self.assertRaises(GLerror, self.light.Set,spotExponent=3265467) # END SPOT EXPONENT #SPOT CUT OFF def test_Set_spotCutoff_attr(self): """ Set spotCutoff changes light spotCutoff attribute """ self.light.Set(spotCutoff=180) spotCutoff = self.light.spotCutoff self.assertEqual(spotCutoff, 180) def test_SetspotCutoff_state(self): """ Set light changes light's state['spotCutoff'] """ self.light.Set(spotCutoff=180) state = self.light.getState() spotCutoff = state['spotCutoff'] self.assertEqual(round(spotCutoff,1), 180) def test_SetspotCutoff_bad_input(self): """ ValueError raised on bad input to Set spotCutoff """ self.assertRaises(ValueError, self.light.Set, spotCutoff='tuyu') def test_SetspotCutoff_empty_input(self): """ ValueError raised on empty input to Set spotCutoff """ self.assertRaises(ValueError, self.light.Set, spotCutoff=' ') def test_SetspotCutoff_too_much_input(self): """ ValueError raised on too_much input to Set spotCutoff """ self.assertRaises(ValueError, self.light.Set, spotCutoff=3265467) #end SPOT CUT OFF #CONSTANT ATTENUATION def test_Set_constantAttenuation_attr(self): """ Set constantAttenuation changes light constantAttenuation attribute """ self.light.Set(constantAttenuation=2.0) constantAttenuation = self.light.constantAttenuation self.assertEqual(constantAttenuation, 2.0) def test_SetconstantAttenuation_state(self): """ Set light changes light's state['constantAttenuation'] """ self.assertRaises(ValueError, self.light.Set,constantAttenuation=-2.0) def test_SetconstantAttenuation_bad_input(self): """ ValueError raised on bad input to Set constantAttenuation """ self.assertRaises(ValueError, self.light.Set ,constantAttenuation='hdi') def test_SetconstantAttenuation_empty_input(self): """ ValueError raised on empty input to Set constantAttenuation """ self.assertRaises(ValueError, self.light.Set, constantAttenuation=' ') #END CONSTANT ATTENUATION #LINEAR ATTENUATION def test_Set_linearAttenuation_attr(self): """ Set linearAttenuation changes light linearAttenuation attribute """ self.light.Set(linearAttenuation=2.0) linearAttenuation = self.light.linearAttenuation self.assertEqual(linearAttenuation, 2.0) def test_SetlinearAttenuation_state(self): """ Set light changes light's state['linearAttenuation'] """ self.assertRaises(ValueError, self.light.Set,linearAttenuation=-2.0) def test_SetlinearAttenuation_bad_input(self): """ ValueError raised on bad input to Set linearAttenuation """ self.assertRaises(ValueError, self.light.Set ,linearAttenuation='hdi') def test_SetlinearAttenuation_empty_input(self): """ ValueError raised on empty input to Set linearAttenuation """ self.assertRaises(ValueError, self.light.Set, linearAttenuation=' ') #END LINEAR ATTENUATION #QUADRATIC ATTENUATION def test_Set_quadraticAttenuation_attr(self): """ Set quadraticAttenuation changes light quadraticAttenuation attribute """ self.light.Set(quadraticAttenuation=2.0) quadraticAttenuation = self.light.quadraticAttenuation self.assertEqual(quadraticAttenuation, 2.0) def test_SetquadraticAttenuation_state(self): """ Set light changes light's state['quadraticAttenuation'] """ self.assertRaises(ValueError, self.light.Set,quadraticAttenuation=-2.0) def test_SetquadraticAttenuation_bad_input(self): """ ValueError raised on bad input to Set quadraticAttenuation """ self.assertRaises(ValueError, self.light.Set,quadraticAttenuation='hdi') def test_SetquadraticAttenuation_empty_input(self): """ ValueError raised on empty input to Set quadraticAttenuation """ self.assertRaises(ValueError, self.light.Set, quadraticAttenuation=' ') #END QUADRATIC ATTENUATION #POSITIONAL def test_Set_positional_attr(self): """ Set positional changes light positional attribute """ self.light.Set(position=[0,0,1,0]) positional = self.light.positional self.assertEqual(positional,True ) def test_Setpositional_state(self): """ Set light changes light's state['positional'] """ self.light.Set(position=[0,0,1,0]) state = self.light.getState() positional = state['positional'] self.assertEqual(positional, True) def test_Setpositional_bad_input(self): """ AttributeError raised on bad input to Set positional """ self.assertRaises(AttributeError, self.light.Set ,positional='hdi') def test_Setpositional_empty_input(self): """ AttributeError raised on empty input to Set positional """ self.assertRaises(AttributeError, self.light.Set, positional=' ') def test_Setpositional_invalid_input(self): """ AttributeError raised on invalid input to Set positional """ self.assertRaises(AttributeError, self.light.Set, positional=2.0) #END POSITIONAL #ENABLED def test_Set_enabled_attr(self): """ Set enabled changes light enabled attribute """ self.light.Set(enabled=False) enabled = self.light.enabled self.assertEqual(enabled,False ) def test_Setenabled_GL(self): """ Set enabled changes GL_LIGHTi """ self.light.Set(enabled=False) enabled= GL.glIsEnabled(self.light.num) self.assertEqual(enabled,False) def test_Setenabled_state(self): """ Set light changes light's state['enabled'] """ self.light.Set(enabled=False) state = self.light.getState() enabled = state['enabled'] self.assertEqual(round(enabled,1), False) def test_Setenabled_bad_input(self): """ AttributeError raised on bad input to Set enabled """ self.assertRaises(AttributeError, self.light.Set ,enabled='hdi') def test_Setenabled_empty_input(self): """ AttributeError raised on empty input to Set enabled """ self.assertRaises(AttributeError, self.light.Set, enabled=' ') #END ENABLED #VISIBLE def test_Set_visible_attr(self): """ Set visible changes light visible attribute """ self.light.Set(visible=True) visible = self.light.visible self.assertEqual(visible,True ) def test_Setvisible_state(self): """ Set light changes light's state['visible'] """ self.light.Set(visible=True) state = self.light.getState() visible = state['visible'] self.assertEqual(round(visible,1), True) def test_Setvisible_bad_input(self): """ AttributeError raised on bad input to Set visible """ self.assertRaises(AttributeError, self.light.Set ,visible=58768) def test_Setvisible_empty_input(self): """ AttributeError raised on empty input to Set visible """ self.assertRaises(AttributeError, self.light.Set, visible=' ') #END VISIBLE #LINE WIDTH def test_Set_lineWidth_attr(self): """ Set lineWidth changes light lineWidth attribute """ self.light.Set(lineWidth=4) lineWidth = self.light.lineWidth self.assertEqual(lineWidth,4 ) def test_SetlineWidth_state(self): """ Set light changes light's state['lineWidth'] """ self.light.Set(lineWidth=3) state = self.light.getState() lineWidth = state['lineWidth'] self.assertEqual(round(lineWidth,1), 3) def test_SetlineWidth_bad_input(self): """ ValueError raised on bad input to Set lineWidth """ self.assertRaises(ValueError, self.light.Set ,lineWidth='hdi') def test_SetlineWidth_bad_input1(self): """ AttributeError raised on bad input negative values to Set lineWidth """ self.assertRaises(AttributeError, self.light.Set ,lineWidth=-8) def test_SetlineWidth_empty_input(self): """ ValueError raised on empty input to Set lineWidth """ self.assertRaises(ValueError, self.light.Set, lineWidth=' ') #END LINE WIDTH #LENGTH def test_Set_length_attr(self): """ Set length changes light length attribute """ self.light.Set(length=4.0) length = self.light.length self.assertEqual(length,4.0 ) def test_Setlength_state(self): """ Set light changes light's state['length'] """ self.light.Set(length=3.0) state = self.light.getState() length = state['length'] self.assertEqual(round(length,1), 3.0) def test_Setlength_bad_input(self): """ ValueError raised on bad input negative values to Set length """ self.assertRaises(ValueError, self.light.Set ,length='hdi') def test_Setlength_bad_input1(self): """ AttributeError raised on bad input to Set length """ self.assertRaises(AttributeError, self.light.Set ,length=-8) def test_Setlength_empty_input(self): """ ValueAttributeError raised on empty input to Set length """ self.assertRaises(ValueError, self.light.Set, length=' ') #END LENGTH ##ANTIALIASED # def test_Set_antialiased_attr(self): # """ Set antialiased changes light antialiased attribute # """ # self.light.Set(antialiased=True) # antialiased = self.light.antialiased # self.assertEqual(antialiased,True) # # # def test_Setantialiased_state(self): # """ Set light changes light's state['antialiased'] # """ # self.light.Set(antialiased=True) # state = self.light.getState() # antialiased = state['antialiased'] # self.assertEqual(round(antialiased,1), True) # # # def test_Setantialiased_bad_input(self): # """ ValueError raised on bad input to Set antialiased # """ # self.assertRaises(ValueError, self.light.Set ,antialiased='hai') # # # def test_Setantialiased_empty_input(self): # """ ValueError raised on empty input to Set antialiased # """ # self.assertRaises(ValueError, self.light.Set, antialiased=' ') ##END ANTIALIASED #ROTATION def test_Set_rotation_attr(self): """ Set rotation changes light rotation attribute """ self.light.Set(rotation=[ 1., 2., 3., 4., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0.,1.]) rotation = self.light.rotation self.assertEqual(round(rotation[0],1), 1) self.assertEqual(round(rotation[1],1), 2) self.assertEqual(round(rotation[2],1), 3) self.assertEqual(round(rotation[3],1), 4) def test_Setrotation_state(self): """ Set light changes light's state['rotation'] """ self.light.Set(rotation=[ 1., 2., 3., 4., 0., 1., 0., 0., 0.,0., 1., 0., 0., 0., 0.,1.]) state = self.light.getState() rotation = state['rotation'] self.assertEqual(round(rotation[0],1), 1.) self.assertEqual(round(rotation[1],1), 2.) self.assertEqual(round(rotation[2],1), 3.) self.assertEqual(round(rotation[3],1), 4.) def test_Setrotation_bad_input(self): """ ValueError raised on bad input to Set rotation """ self.assertRaises(ValueError, self.light.Set ,rotation=[1,0]) def test_Setrotation_empty_input(self): """ ValueError raised on empty input to Set rotation """ self.assertRaises(ValueError, self.light.Set, rotation=[]) def test_Setrotation_string_input(self): """ ValueError raised on string input to Set rotation """ self.assertRaises(ValueError,self.light.Set,rotation=['a','c','b','n','s','j']) #END ROTATION #TRNSLATION def test_Set_translation_attr(self): """ Set translation changes light translation attribute """ self.light.Set(translation=[1,1,0]) translation = self.light.translation self.assertEqual(translation[0], 1) self.assertEqual(round(translation[1],1), 1) self.assertEqual(round(translation[2],1), 0) def test_Settranslation_state(self): """ Set light changes light's state['translation'] """ self.light.Set(translation=[1,0,0]) state = self.light.getState() translation = state['translation'] self.assertEqual(round(translation[0],1), 1.) self.assertEqual(translation[1], 0.) self.assertEqual(translation[2], 0.) def test_Settranslation_bad_input(self): """ ValueError raised on bad input to Set translation """ self.assertRaises(ValueError, self.light.Set ,translation=[1,0]) def test_Settranslation_empty_input(self): """ ValueError raised on empty input to Set translation """ self.assertRaises(ValueError, self.light.Set, translation=[]) def test_Settranslation_too_much_input(self): """ ValueError raised on too_much input to Set translation """ self.assertRaises(ValueError, self.light.Set,translation=[1,0,0,1,1]) #END TRANSLATION #SCALE def test_Set_scale_attr(self): """ Set scale changes light scale attribute """ self.light.Set(scale=[1,1,0]) scale = self.light.scale self.assertEqual(scale[0], 1) self.assertEqual(round(scale[1],1), 1) self.assertEqual(round(scale[2],1), 0) def test_Setscale_state(self): """ Set light changes light's state['scale'] """ self.light.Set(scale=[1,0,0]) state = self.light.getState() scale = state['scale'] self.assertEqual(round(scale[0],1), 1.) self.assertEqual(scale[1], 0.) self.assertEqual(scale[2], 0.) def test_Setscale_bad_input(self): """ ValueError raised on bad input to Set scale """ self.assertRaises(ValueError, self.light.Set ,scale=[1,0]) def test_Setscale_empty_input(self): """ ValueError raised on empty input to Set scale """ self.assertRaises(ValueError, self.light.Set, scale=[]) def test_Setscale_too_much_input(self): """ ValueError raised on too_much input to Set scale """ self.assertRaises(ValueError, self.light.Set,scale=[1,0,0,1,1]) #END SCALE #PIVOT def test_Set_pivot_attr(self): """ Set pivot changes light pivot attribute """ self.light.Set(pivot=[1,1,0]) pivot = self.light.pivot self.assertEqual(pivot[0], 1) self.assertEqual(round(pivot[1],1), 1) self.assertEqual(round(pivot[2],1), 0) def test_Setpivot_state(self): """ Set light changes light's state['pivot'] """ self.light.Set(pivot=[1,0,0]) state = self.light.getState() pivot = state['pivot'] self.assertEqual(round(pivot[0],1), 1.) self.assertEqual(pivot[1], 0.) self.assertEqual(pivot[2], 0.) def test_Setpivot_bad_input(self): """ ValueError raised on bad input to Set pivot """ self.assertRaises(ValueError, self.light.Set ,pivot=[1,0]) def test_Setpivot_empty_input(self): """ ValueError raised on empty input to Set pivot """ self.assertRaises(ValueError, self.light.Set, pivot=[]) def test_Setpivot_too_much_input(self): """ ValueError raised on too_much input to Set pivot """ self.assertRaises(ValueError, self.light.Set,pivot=[1,0,0,1,1]) #END PIVOT class LightModel_BaseTests(unittest.TestCase): """ setUp + tearDown form a fixture: working environment for the testing code """ def setUp(self): """ start Viewer """ if not hasattr(self, 'vi'): self.vi = Viewer(verbose=False) self.vi.master.update_idletasks() #self.vi.cameras[0].master.master.withdraw() self.lightModel = self.vi.lightModel self.orig_state = self.lightModel.getState() def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #AMBI def test_Set_ambi_attr(self): """ Set ambi changes light ambi attribute """ self.lightModel.Set(ambient=(0.0,0.5,0.5,1.0)) ambi = self.lightModel.ambient self.assertEqual(ambi[0], 0) self.assertEqual(round(ambi[1],1), 0.5) self.assertEqual(round(ambi[2],1), 0.5) self.assertEqual(round(ambi[3],1), 1.0) def test_Setambi_GL(self): """ Set ambi changes GL_AMBI """ self.lightModel.Set(ambient=(0.0,0.5,0.5,1.0)) ambi= GL.glGetFloatv(GL.GL_LIGHT_MODEL_AMBIENT) self.assertEqual(ambi[0],0.) self.assertEqual(round(ambi[1],1),0.5) self.assertEqual(round(ambi[2],1), 0.5) self.assertEqual(round(ambi[3],1), 1.0) def test_Setambi_state(self): """ Set light changes light's state['ambi'] """ self.lightModel.Set(ambient=(1,0,0,0)) state = self.lightModel.getState() ambi = state['ambient'] self.assertEqual(round(ambi[0],1), 1.) self.assertEqual(ambi[1], 0.) self.assertEqual(ambi[2], 0.) self.assertEqual(ambi[3], 0.) def test_Setambi_bad_input(self): """ ValueError raised on bad input to Set ambi """ self.assertRaises(ValueError, self.lightModel.Set ,ambient=(1,0)) def test_Setambi_empty_input(self): """ ValueError raised on empty input to Set ambi """ self.assertRaises(ValueError, self.lightModel.Set, ambient=()) def test_Setambi_too_much_input(self): """ ValueError raised on too_much input to Set ambi """ self.assertRaises(ValueError, self.lightModel.Set,ambient=(1,0,0,1,1)) #end AMBI #LOCAL VIEWER def test_Set_localViewer_attr(self): """ Set localViewer changes light localViewer attribute """ self.lightModel.Set(localViewer=True) localViewer = self.lightModel.localViewer self.assertEqual(localViewer,True ) def test_Set_localViewer_attr(self): """ Set localViewer changes light localViewer attribute """ self.lightModel.Set(localViewer=True) localViewer = self.lightModel.localViewer self.assertEqual(localViewer,True) def test_SetlocalViewer_GL(self): """ Set local viewer changes GL_AMBI """ self.lightModel.Set(localViewer=True) localViewer= GL.glGetBooleanv(GL.GL_LIGHT_MODEL_LOCAL_VIEWER) self.assertEqual(localViewer,True) def test_SetlocalViewer_state(self): """ Set light changes light's state['localViewer'] """ self.lightModel.Set(localViewer=True) state = self.lightModel.getState() localViewer = state['localViewer'] self.assertEqual(round(localViewer,1), True) def test_SetlocalViewer_bad_input(self): """ AttributeError raised on bad input to Set localViewer """ self.assertRaises(AttributeError, self.lightModel.Set ,localViewer='hdi') def test_SetlocalViewer_empty_input(self): """ AttributeError raised on empty input to Set localViewer """ self.assertRaises(AttributeError, self.lightModel.Set, localViewer=' ') #END LOCAL VIEWER #TWO SIDE def test_Set_twoSide_attr(self): """ Set twoSide changes light twoSide attribute """ self.lightModel.Set(twoSide=True) twoSide = self.lightModel.twoSide self.assertEqual(twoSide,True ) def test_Set_twoSide_attr(self): """ Set twoSide changes light twoSide attribute """ self.lightModel.Set(twoSide=True) twoSide = self.lightModel.twoSide self.assertEqual(twoSide,True) def test_SettwoSide_GL(self): """ Set two side changes GL_AMBI """ self.lightModel.Set(twoSide = True) twoSide= GL.glGetBooleanv(GL.GL_LIGHT_MODEL_TWO_SIDE) self.assertEqual(twoSide,True) def test_SettwoSide_state(self): """ Set light changes light's state['twoSide'] """ self.lightModel.Set(twoSide=True) state = self.lightModel.getState() twoSide = state['twoSide'] self.assertEqual(round(twoSide,1), True) def test_SettwoSide_bad_input(self): """ AttributeError raised on bad input to Set twoSide """ self.assertRaises(AttributeError, self.lightModel.Set ,twoSide='hdi') def test_SettwoSide_empty_input(self): """ AttributeError raised on empty input to Set twoSide """ self.assertRaises(AttributeError, self.lightModel.Set, twoSide=' ') if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Points.py0000644000175000017500000001423111330422250023645 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Points.py,v 1.10 2010/01/28 23:58:32 annao Exp $ # # import sys, os from Tkinter import Menubutton import unittest import numpy import numpy.oldnumeric as Numeric from opengltk.OpenGL import GL from DejaVu.Viewer import Viewer import Image from math import sqrt from DejaVu.Points import Points,CrossSet from time import sleep import Image from math import sqrt class Points__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = [ 'centers', ] all other keywords are handled by Geom.__init__ method """ #defaults def test_Points_defaults(self): """defaults """ g = Points() self.assertEqual(isinstance(g, Points), True) #centers def test_Points_shape(self): """centers ((0,0,0),(1,0,0)) """ g = Points(centers=((0,0,0),(1,0,0))) self.assertEqual(isinstance(g, Points), True) class Points_Set_Tests(unittest.TestCase): """ # does override Geom.Set why???? one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = Points(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Points_Set_centers(self): """ test Setting centers """ self.geom.Set(centers=((3,6,0,),(1,1,1),)) self.assertEqual(len(self.geom.vertexSet.vertices.array), 2) def test_Points_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) class Points_Viewer_Tests(unittest.TestCase): """ tests for Points in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.geom = Points('points', vertices =((0,0,0),(1.,0.,0.), (2,0,0)), materials=((.5,0,0),), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGuiPoints def test_Points_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() #sleep(5) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", midpt, buff_255[midpt][midpt] #sleep(5) self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.2, True) #Arcs 3D image def test_Points_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimagePoints.tif") im = Image.open("./saveimagePoints.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) # for v in d: # self.assertTrue(v[0]<1.e-9 and v[0]>-1.e-9) # self.assertTrue(v[1]<1.e-9 and v[1]>-1.e-9) # self.assertTrue(v[2]<1.e-9 and v[2]>-1.e-9) if __name__ == '__main__': test_cases = [ 'Points__init__Tests', 'Points_Set_Tests', 'Points_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Box.py0000644000175000017500000002060611226702334023134 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Box.py,v 1.14 2009/07/13 19:02:52 vareille Exp $ # # import unittest import sys, os import numpy import numpy.oldnumeric as Numeric import Image from math import sqrt from Tkinter import Menubutton from opengltk.OpenGL import GL from DejaVu.Viewer import Viewer from DejaVu.Box import Box #Box class Box__init__Tests(unittest.TestCase): """ 'Box__init__Tests', NOTE: cannot create box without any arguments! """ #defaults def test_Box_defaults(self): """can create box with defaults values """ g = Box() self.assertEqual(isinstance(g, Box), True) #origin def test_Box_origin(self): """origin (2,2,2), (default origin is (0,0,0)) box=Box("mybox",cornerPoints=((0,0,0),(5,5,0)), materials=((0,1,0),)) """ g = Box(origin=(2,2,2)) self.assertEqual(isinstance(g, Box), True) class Box_Set_Tests(unittest.TestCase): """ # doesnot override Geom.Set so just one test that baseclass Set is called adds these keywords to IndexedPolygon.keywords maxCube minCube vertices side xside yside zside center origin cornerPoints """ def setUp(self): """ create geom """ self.geom = Box(name='test', origin=(0,0,0)) def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Box_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) #maxCube def test_Box_Set_maxCube(self): """ test Setting maxCube """ val = 3 self.geom.Set(maxCube=val) self.assertEqual(self.geom.maxCube, val) #minCube def test_Box_Set_minCube(self): """ test Setting minCube """ val = 3 self.geom.Set(minCube=val) self.assertEqual(self.geom.minCube, val) #vertices def test_Box_Set_vertices(self): """ test Setting vertices """ val = ( ( 2., 2., 0.), ( 0., 2., 0.), ( 0., 0., 0.), ( 2., 0., 0.), ( 2., 2., 2.), ( 0., 2., 2.), ( 0., 0., 2.), ( 2., 0., 2.)) self.geom.Set(vertices=val) #self.assertEqual(self.geom.vertexSet.vertices.array[0], val[0]) self.assertTrue(numpy.alltrue(self.geom.vertexSet.vertices.array[0]==val[0])) #side def test_Box_Set_side(self): """ test Setting side """ val = 3 self.geom.Set(side=val) #side sets all 2 dimensions self.assertEqual(self.geom.xside, val) #xside def test_Box_Set_xside(self): """ test Setting xside """ val = 4 self.geom.Set(xside=val) self.assertEqual(self.geom.xside, val) #yside def test_Box_Set_yside(self): """ test Setting yside """ val = 5 self.geom.Set(yside=val) self.assertEqual(self.geom.yside, val) #zside def test_Box_Set_zside(self): """ test Setting zside """ val = 6 self.geom.Set(zside=val) self.assertEqual(self.geom.zside, val) #center def test_Box_Set_center(self): """ test Setting center """ val = (2,4,6) self.geom.Set(center=val) self.assertEqual(self.geom.center, val) #origin def test_Box_Set_origin(self): """ test Setting origin ONLY WORKS IF CENTER SPECIFIED (??) """ val = (-2,-2,-2) center = (0,0,0) self.geom.Set(origin=val, center=center) self.assertEqual(self.geom.vertexSet.vertices.array[0][0], -val[0]) #cornerPoints def test_Box_Set_cornerPoints(self): """ test Setting cornerPoints """ val = ((0,0,0),(10,10,10)) self.geom.Set(cornerPoints=val) self.assertEqual(self.geom.xside, 10) class Box_Viewer_Tests(unittest.TestCase): """ tests for Box in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.geom = box = Box("box",cornerPoints=((0,0,0),(5,5,0)),\ materials=((0,1,0),),\ inheritLineWidth=0,\ inheritMaterial=0,\ lineWidth=10) self.geom.frontPolyMode = GL.GL_LINE self.vi.AddObject(box) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(box) #self.vi.OneRedraw() def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGui... def test_Box_inheritMaterial(self): """tests changing box material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) box = self.geom self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = box.getState()['inheritMaterial'] #print "now box.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "2:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) def test_Box_image(self): """test image: changing its material by toggling inheritMaterial """ cam = self.vi.currentCamera cam.Set(height=200,width=200) box = self.geom self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() self.vi.startAutoRedraw() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = sqrt(total_pixels) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff#/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(buff_255[midpt][midpt][0]>0.1, True) buff_255_sum=Numeric.add.reduce(buff_255) cam.SaveImage("./saveimagebox.tif") im = Image.open("./saveimagebox.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray#/255. narray_255_sum=Numeric.add.reduce(narray_255) #print sum d=buff_255_sum-narray_255_sum #self.assertEqual(d,0) self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) #End Box if __name__ == '__main__': test_cases = [ 'Box__init__Tests', 'Box_Set_Tests', 'Box_Viewer_Tests', ] unittest.main( argv=([__name__ , ] + test_cases) ) #unittest.main( argv=([__name__ , '-v'] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Labels.py0000644000175000017500000001727611101715774023623 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Labels.py,v 1.21 2008/10/28 23:10:52 vareille Exp $ # # import sys, os,math,types from Tkinter import Menubutton import unittest,numpy.oldnumeric as Numeric from math import sqrt from opengltk.OpenGL import GL from DejaVu.Viewer import Viewer from time import sleep from DejaVu import viewerConst import Image from DejaVu.glfLabels import GlfLabels class Labels__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = [ 'labels', 'font', 'offset'] all other keywords are handled by Geom.__init__ method """ #defaults def test_Labels_defaults(self): """defaults for shape, radius, angles """ g = GlfLabels() self.assertEqual(isinstance(g, GlfLabels), True) #labels def test_Labels_labels(self): """labels ['TEST1'] """ g = GlfLabels(labels=("TEST",)) self.assertEqual(isinstance(g, GlfLabels), True) #font def test_Labels_radius(self): """font "glut9by15" """ g = GlfLabels(font="arial1.glf") self.assertEqual(isinstance(g, GlfLabels), True) #offset def test_Labels_offset(self): """offset """ g = GlfLabels(fontTranslation=(.1,.1,.1)) self.assertEqual(isinstance(g, GlfLabels), True) class Labels_Set_Tests(unittest.TestCase): """ # does not override Geom.Set so just one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = GlfLabels(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Labels_Set_font(self): """ test Setting font """ val = "arial1.glf" self.geom.Set(font=val) self.assertEqual(self.geom.font, val) def test_Labels_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) class Labels_Viewer_Tests(unittest.TestCase): """ tests for Labels in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) cam = self.cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vertices=((-3.7,0,0,),) #self.vertices=((-10,0,0,),) self.geom = GlfLabels(name='labels', shape=(0,3), inheritMaterial=0, materials = ((1,0,0),), visible=1, labels = ["XXXXX",], vertices=self.vertices, font="arial1.glf") self.vi.AddObject(self.geom) self.vi.update() self.cam.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) self.vi.OneRedraw() def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass def test_Labels_sanity(self): """ sanity check""" #print 4 cam = self.vi.currentCamera self.assertEqual(1,1) #one test of setting properties via DejaVuGuiLabels def test_Labels_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ #print 3 cam = self.vi.currentCamera self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] #this is trying to checkthat the label is red #self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "2:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Labels Image7 def test_Labels_image(self): """valid image..checked by writing/reading a tif file """ #print 2 cam = self.vi.currentCamera self.vi.update() #self.cam.DoPick(0.,0.) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 #print "total_pixels=", total_pixels effective_height = int(sqrt(total_pixels)) #print "effective_height=", effective_height midpt = int(effective_height/2) #print "midpt=", midpt buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #print " buff_255[midpt][midpt]=", buff_255[midpt][midpt] #check that the pixel is not black self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageLabels.tif") im = Image.open("./saveimageLabels.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) def test_Labels_Set(self): """valid image..checked by writing/reading a tif file """ #print 1 cam = self.vi.currentCamera try: self.geom.Set( inheritMaterial=0, materials = ((1,0,0),), visible=1, labels = ["lili", ], vertices=( (3.8, 0.2, 0.4), (3.8, 0.2, 0.4)), font="arial1.glf") self.vi.OneRedraw() except Exception, e: print "Exception", e self.assertEqual(1,0) if __name__ == '__main__': test_cases = [ 'Labels__init__Tests', 'Labels_Set_Tests', 'Labels_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main( argv=([__name__ , '-v'] + test_cases) ) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/__init__.py0000644000175000017500000000014710473163526023111 0ustar debiandebianignore = {'test_memory':['test_creatingViewers100Time'], #'test_dependencies' : [] } mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_triangleStrip.py0000644000175000017500000001744011473057650025245 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import numpy import sys, os,math,types from Tkinter import Menubutton import unittest, numpy.oldnumeric as Numeric from DejaVu.Viewer import Viewer from DejaVu.triangle_strip import Triangle_strip from time import sleep import Image from math import sqrt vert = [(0, 0, 0), (1, 0, 1), (1, 1, 0), (2, 0, -1), (2, 1, 0), (3, 0, 1), (3, 1, 0), (4, 0, -1), (4, 1, 0), (5, 0, 1), (5, 3, 0), (6, -2, 1)] v1 = Numeric.array(vert) v2 = v1 + 3.0 v3 = Numeric.concatenate( (v1,v2) ) colors = [(0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 0, 0), (0, 1, 0)] v4 = v2 + 3.0 v5 = Numeric.concatenate( (v3,v4) ) class Triangle_strip__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = ['stripBegin', 'stripEnd', 'fnormals'] all other keywords are handled by Geom.__init__ method """ #defaults def test_Triangle_strip_defaults(self): """defaults """ g = Triangle_strip() self.assertEqual(isinstance(g, Triangle_strip), True) #vertices def test_Triangle_strip_vertices(self): """vertices """ g = Triangle_strip(vertices = v1) self.assertEqual(isinstance(g, Triangle_strip), True) #stripBegin def test_Triangle_strip_stripBegin(self): """stripBegin """ g = Triangle_strip(vertices=v5, stripBegin=[0,12]) self.assertEqual(isinstance(g, Triangle_strip), True) #materials and colors def test_Triangle_strip_materials(self): """materials """ g = Triangle_strip(vertices = v3, stripBegin=[0,12,24], materials = colors+colors[0:8]) self.assertEqual(isinstance(g, Triangle_strip), True) class Triangle_strip_Set_Tests(unittest.TestCase): """ # doesnot override Geom.Set so just one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = Triangle_strip(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Triangle_strip_Set_vertices(self): """ test Setting angles """ self.geom.Set(vertices=v3, stripBegin=[0,12,24]) #self.assertEqual(self.geom.vertexSet.vertices.array[0], 0) self.assertTrue(numpy.alltrue(self.geom.vertexSet.vertices.array[0]==[0.,0.,0.])) def test_Triangle_strip_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) class Triangle_strip_Viewer_Tests(unittest.TestCase): """ tests for Triangle_strip in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) v = ((-1,1,0),(-1,-1,0), (1,1,0), (1,-1,0)) self.geom = Triangle_strip('triangle_strip', vertices=v, stripBegin=[0,4], materials=((1.,0,0),), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.vi.AddObject(self.geom) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(self.geom) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGuiTriangle_strip def test_Triangle_strip_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera width = height = 200 cam.Set(height=height,width=width) # turn lighting off so colors are pure #self.geom.Set(lighting=0) self.vi.OverAllLightingIsOn.set(0) self.vi.deleteOpenglListAndCallRedrawAndCallDisableGlLighting() self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() buff.shape = (height, width, 3) midx = width/2 midy = height/2 # assert middle picel is red #self.assertEqual(buff[midy][midx][0],255) # for some reason on some MacOS platforms the value of buff[midy][midx] is [248, 0,0]. self.assertTrue(buff[midy][midx][0] in [255, 248]) self.assertEqual(buff[midy][midx][1],0) self.assertEqual(buff[midy][midx][2],0) for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = self.geom.getState()['inheritMaterial'] #print "now self.geom.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() buff.shape = (height, width, 3) ## self.assertEqual(buff[midy][midx][0]==255, True) ## self.assertEqual(buff[midy][midx][1]==255, True) ## self.assertEqual(buff[midy][midx][2]==255, True) self.assertTrue(buff[midy][midx][0] in [255, 248]) self.assertTrue(buff[midy][midx][1] in [255, 248]) self.assertTrue(buff[midy][midx][2] in [255, 248]) #sleep(5) #Arcs 3D image def test_Triangle_strip_image(self): """valid image..checked by writing/reading a tif file """ cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #sleep(5) #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black # midpt+1 (instead of midpt) # because this was not working properly on some old sgi OGL card self.assertEqual(round(buff_255[midpt][midpt+1][0],1)>=0.1, True) buff_255_sum = Numeric.add.reduce(buff_255) cam.SaveImage("./saveimageTriangle_strip.tif") im = Image.open("./saveimageTriangle_strip.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum = Numeric.add.reduce(narray_255) #print sum d = buff_255_sum-narray_255_sum #self.assertEqual(d,0) for v in d: self.assertTrue(v[0]<1.e-9) self.assertTrue(v[1]<1.e-9) self.assertTrue(v[2]<1.e-9) self.assertTrue(v[0]>-1.e-9) self.assertTrue(v[1]>-1.e-9) self.assertTrue(v[2]>-1.e-9) if __name__ == '__main__': test_cases = [ 'Triangle_strip__init__Tests', 'Triangle_strip_Set_Tests', 'Triangle_strip_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_dependencies.py0000644000175000017500000000162711216031313025023 0ustar debiandebian# ################################################################# # Author: Sowjanya Karnati ################################################################# # #Purpose:To update dependencies list # # $Id: test_dependencies.py,v 1.5 2009/06/17 00:03:23 vareille Exp $ from mglutil.TestUtil.Tests.dependenciestest import DependencyTester import unittest,sys d = DependencyTester() result_expected =[] class test_dep(unittest.TestCase): def test_dep_1(self): import os if os.name != 'nt': #sys.platform !='win32': result = d.rundeptester('DejaVu') if result !=[]: print "\nThe Following Packages are not present in CRITICAL or NONCRITICAL DEPENDENCIES of DejaVu :\n %s" %result self.assertEqual(result,result_expected) else: self.assertEqual(result,result_expected) if __name__ == '__main__': unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Arcs3D.py0000644000175000017500000002067511330422250023461 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Arcs3D.py,v 1.19 2010/01/28 23:58:32 annao Exp $ # # import sys, os,math,types import numpy from Tkinter import Tk, Toplevel, Menubutton import unittest, numpy.oldnumeric as Numeric from opengltk.OpenGL import GL from DejaVu.Camera import Camera from DejaVu.Viewer import Viewer from DejaVu.Spheres import Spheres from opengltk.extent.utillib import glCleanRotMat from time import sleep from DejaVu.IndexedPolygons import IndexedPolygons from DejaVu.IndexedPolylines import IndexedPolylines from DejaVu.ViewerGUI import ViewerGUI from DejaVu import viewerConst,datamodel import Image from math import sqrt from DejaVu.Points import Points, CrossSet from DejaVu.Arcs3D import Arcs3D class Arcs3D__init__Tests(unittest.TestCase): """test keywords for __init__: keywords = [ 'shape', 'radii', 'angles'] all other keywords are handled by Geom.__init__ method """ #defaults def test_Arcs3D_defaults(self): """defaults for shape, radii, angles """ g = Arcs3D() self.assertEqual(isinstance(g, Arcs3D), True) #shape def test_Arcs3D_shape(self): """shape (0,2), (default shape is (0,3)) """ g = Arcs3D(shape=(0,2)) self.assertEqual(isinstance(g, Arcs3D), True) #radii def test_Arcs3D_radii(self): """radii 2 (default radii is 0.2) """ g = Arcs3D(radii=2.) self.assertEqual(isinstance(g, Arcs3D), True) #angles def test_Arcs3D_angles(self): """angles 180 (default angles is (360,)) """ g = Arcs3D(angles=180) self.assertEqual(isinstance(g, Arcs3D), True) class Arcs3D_Set_Tests(unittest.TestCase): """ # doesnot override Geom.Set so just one test that baseclass Set is called """ def setUp(self): """ create geom """ self.geom = Arcs3D(name='test') def tearDown(self): """ clean-up """ try: del(self.geom) except: pass def test_Arcs3D_Set_angles(self): """ test Setting angles """ self.geom.Set(angles=360) self.assertEqual(self.geom.angles[0], 360) def test_Arcs3D_Set_radii(self): """ Set radii by call to Set """ self.geom.Set(radii=3.0) self.assertEqual(self.geom.radii, [3.0]) def test_Arcs3D_Set_name(self): """ test Setting name """ val = 'new_name' self.geom.Set(name=val) self.assertEqual(self.geom.name, val) #INVALID INPUT def test_Arcs3D_Set_angles_invalid(self): """ Set inavlid angles by call to Set """ self.assertRaises(ValueError,self.geom.Set,angles="a") def test_Arcs3D_Set_radii_invalid(self): """ Set invalid radii by call to Set """ self.assertRaises(ValueError,self.geom.Set,radii="a") #SETTING LIST OF INPUTS def test_Arcs3D_Set_list_of_angles(self): """ Set list of angles by call to Set """ self.geom.Set(vertices =((0,0,0),(5.,0.,0.),(-5,0.0,0.))) self.geom.Set(angles=(180.,360.0,270.0)) self.assertEqual(self.geom.angles, [180.0,360.0,270.0]) def test_Arcs3D_Set_list_of_radii(self): """ Set list of radii by call to Set """ self.geom.Set(vertices =((0,0,0),(5.,0.,0.),(-5,0.0,0.))) self.geom.Set(radii=(3.0,2.0,5.0)) self.assertEqual(self.geom.radii, [3.0,2.0,5.0]) class Arcs3D_Viewer_Tests(unittest.TestCase): """ tests for Arcs3D in DejaVu.Viewer """ def setUp(self): """ start Viewer """ self.vi = Viewer(verbose = 0) self.geom = arc = Arcs3D('arcs', vertices =((0,0,0),(5.,0.,0.)), vnormals=((1.0,0,0),(0,1.,0)), materials=((.5,0,0),), radii=(1.0,2.0), angles=(360,180), inheritLineWidth=0, lineWidth=10, inheritMaterial=False) self.vi.AddObject(arc) self.vi.update() self.vi.currentCamera.DoPick(0.,0.) self.vi.SetCurrentObject(arc) def tearDown(self): """ clean-up """ try: self.vi.Exit() except: pass #one test of setting properties via DejaVuGui... def test_Arcs3D_inheritMaterial(self): """valid changing material by toggling inheritMaterial """ """ NOTE toggling is done by invoking a button in dejaVuGUI this test checks pixel in the middle of the scene when the object does not inheritMaterial and is colored RED vs after inheritMaterial is restored when the object is white (well grayish) """ cam = self.vi.currentCamera cam.Set(height=200,width=200) arc = self.geom self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "1:midpt=", buff_255[midpt][midpt] self.assertEqual(round(buff_255[midpt][midpt][1],1)<=0.1, True) self.vi.OneRedraw() self.vi.update() for c in self.vi.GUI.inheritF.children.values(): if c.__class__ == Menubutton \ and c.configure('text')[-1] == ('Current', 'geom', 'properties'): self.inheritF_menu = c.menu inheritMaterial_index = self.inheritF_menu.index('inheritMaterial') self.inheritF_menu.invoke(inheritMaterial_index) newstate = arc.getState()['inheritMaterial'] #print "now arc.inheritMaterial=", newstate self.assertEqual(newstate, 1) self.vi.OneRedraw() buff = cam.GrabFrontBufferAsArray() total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "midpt=", buff_255[midpt][midpt] if sys.platform == 'irix6': self.assertEqual( (round(buff_255[midpt-1][midpt-1][0],1)>=0.4) or \ (round(buff_255[midpt][midpt][0],1)>=0.4) , True) else: self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.4, True) #Arcs 3D image def test_Arcs3D_image(self): """valid image..checked by writing/reading a tif file """ arc = self.geom cam = self.vi.currentCamera cam.Set(height=200,width=200) self.vi.OneRedraw() self.vi.update() buff = cam.GrabFrontBufferAsArray() #print "max pixel= ", max(buff.ravel()) #sum_array=Numeric.add.reduce(buff) #on sgi, viewer is not 500x500 but 509 or 516 or? square total_pixels = len(buff)/3 effective_height = int(sqrt(total_pixels)) midpt = int(effective_height/2) buff.shape = (effective_height,effective_height,3) buff_255 = buff/255. #print "pixel at midpoint of buffer=", buff_255[midpt][midpt] #check that the pixel is not black if sys.platform == 'irix6': self.assertEqual( (round(buff_255[midpt-1][midpt-1][0],1)>=0.1) or \ (round(buff_255[midpt][midpt][0],1)>=0.1) , True) else: self.assertEqual(round(buff_255[midpt][midpt][0],1)>=0.1, True) buff_255_sum=Numeric.add.reduce(buff_255) cam.SaveImage("./saveimagearc.tif") im = Image.open("./saveimagearc.tif") im = im.tostring() narray = Numeric.fromstring(im,'B') #print narray.shape narray.shape = (effective_height,effective_height,3) narray_255 = narray/255. narray_255_sum=Numeric.add.reduce(narray_255) #print sum d=buff_255_sum-narray_255_sum self.assertTrue(d.ravel().max() < 1.e-9) #self.assertTrue(numpy.alltrue(d==[0.,0.,0.])) #for v in d: # self.assertTrue(v[0]<1.e-9) # self.assertTrue(v[1]<1.e-9) # self.assertTrue(v[2]<1.e-9) if __name__ == '__main__': test_cases = [ 'Arcs3D__init__Tests', 'Arcs3D_Set_Tests', 'Arcs3D_Viewer_Tests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Tests/test_Clip.py0000644000175000017500000003137111630013067023271 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by # # # $Id: test_Clip.py,v 1.27 2011/09/01 23:33:11 annao Exp $ # # import unittest import numpy.oldnumeric as Numeric import math import warnings import sys from mglutil.math.rotax import rotax from opengltk.OpenGL import GL from DejaVu import Viewer from DejaVu.Spheres import Spheres class Clip_BaseTests(unittest.TestCase): """ setUp + tearDown form a fixture: working environment for the testing code """ def setUp(self): """ start Viewer """ if not hasattr(self, 'vi'): self.vi = Viewer(verbose=False) self.vi.GUI.top.master.withdraw() #this is good also: #self.vi.cameras[0].master.master.lift() self.clip = self.vi.currentClip self.orig_state = self.clip.getState() def tearDown(self): """ clean-up """ #print 'in clip tearDown' #apply(self.clip.Set, (), self.orig_state) try: self.vi.Exit() except: pass #self.vi.__del__() #Name def test_Name(self): """ Name is ClipPlane0 """ self.assertEqual(self.clip.name, 'ClipPlane0') #end Name #COLOR def test_SetColor_attr(self): """ Set color changes clip's color attribute """ self.clip.Set(color=(1,0,0)) col = self.clip.color self.assertEqual(col[0], 1.) self.assertEqual(col[1], 0.) self.assertEqual(col[2], 0.) def test_SetColor_state(self): """ Set color changes clip's state['color'] """ self.clip.Set(color=(1,0,0)) state = self.clip.getState() col = state['color'] self.assertEqual(col[0], 1.) self.assertEqual(col[1], 0.) self.assertEqual(col[2], 0.) def test_SetColor_bad_input(self): """ ValueError raised on bad input to Set color """ self.assertRaises(ValueError, self.clip.Set,color=(1,0)) def test_SetColor_empty_input(self): """ ValueError raised on empty input to Set color """ self.assertRaises(ValueError, self.clip.Set, color=()) def test_SetColor_too_much_input(self): """ ValueError raised on too_much input to Set color """ self.assertRaises(ValueError, self.clip.Set,color=(1,0,0,1,1)) #end COLOR #ENABLE def test_Enabled_attr(self): """ Test clip's enabled attribute is False """ self.assertEqual(self.clip.enabled, False) def test_Enabled_GL_CLIP_PLANE0(self): """ Test enabled GL_CLIP_PLANE0 """ self.assertEqual(GL.glIsEnabled(GL.GL_CLIP_PLANE0), False) def test_SetEnabled_attr(self): """ Set enabled changes clip's enabled attribute """ val = True self.clip.Set(enabled=val) self.assertEqual(self.clip.enabled, val) def test_SetEnabled_state(self): """ Set enabled changes clip's state['enabled'] """ val = True self.clip.Set(enabled=val) state = self.clip.getState() enabled = state['enabled'] self.assertEqual(enabled, val) def test_SetEnabled_changes_GL_CLIP_PLANE0(self): """ Set enabled changes GL_CLIP_PLANE0 """ val = True self.clip.Set(enabled=val) self.assertEqual(GL.glIsEnabled(GL.GL_CLIP_PLANE0), val) def test_SetEnabled_bad_input(self): """ AttributeError raised on bad input to Set enabled """ self.assertRaises(AttributeError, self.clip.Set, enabled=2) def test_SetEnabled_empty_input(self): """ AttributeError raised on empty input to Set enabled """ self.assertRaises(AttributeError, self.clip.Set, enabled='') #end ENABLED #VISIBLE def test_Visible_attr(self): """ Test clip's visible attribute is False """ self.assertEqual(self.clip.visible, False) def test_SetVisible_attr(self): """ Set visible changes clip's visible attribute """ val = True self.clip.Set(visible=val) self.assertEqual(self.clip.visible, val) def test_SetVisible_state(self): """ Set visible changes clip's state['visible'] """ val = True self.clip.Set(visible=val) state = self.clip.getState() visible = state['visible'] self.assertEqual(visible, val) def test_SetVisible_bad_input(self): """ AttributeError raised on bad input to Set visible """ self.assertRaises(AttributeError, self.clip.Set, visible=2) def test_SetVisible_empty_input(self): """ AttributeError raised on empty input to Set visible """ self.assertRaises(AttributeError, self.clip.Set, visible='') #end VISIBLE #LINEWIDTH def test_LineWidth_attr(self): """ Test clip's lineWidth attribute is 2.0 """ self.assertEqual(self.clip.lineWidth, 2) def test_SetLineWidth_attr(self): """ Set lineWidth changes clip's lineWidth attribute """ val = 4 self.clip.Set(lineWidth=val) self.assertEqual(self.clip.lineWidth, val) def test_SetLineWidth_state(self): """ Set lineWidth changes clip's state['lineWidth'] """ val = 4 self.clip.Set(lineWidth=val) state = self.clip.getState() lineWidth = state['lineWidth'] self.assertEqual(lineWidth, val) #FIX THESE BY CHECKING INPUT IN CLIP.PY def test_SetLineWidth_bad_input(self): """ ValueError raised on bad input to Set lineWidth """ self.assertRaises(ValueError, self.clip.Set, lineWidth=-1) def test_SetLineWidth_bad_input2(self): """ ValueError raised on stringinput to Set lineWidth """ self.assertRaises(ValueError, self.clip.Set, lineWidth='a') def test_SetLineWidth_string_float_input(self): """ No ValueError raised on stringinput of a float to Set lineWidth """ #import pdb;pdb.set_trace() val = '1' self.clip.Set(lineWidth=val) self.assertEqual(self.clip.lineWidth, 1) #self.assertRaises(ValueError, self.clip.Set, lineWidth='-1.0') def test_SetLineWidth_empty_input(self): """ ValueError raised on empty input to Set lineWidth """ self.assertRaises(ValueError, self.clip.Set, lineWidth='') #end LINEWIDTH #INITIAL COEFFICIENTS def test_InitialCoefficients(self): """ Test clip's InitialCoefficients are (0,0,0,0) """ expectedVal = (0.,0.,0.,0) coefs = GL.glGetClipPlane(GL.GL_CLIP_PLANE0) for c,v in zip(coefs, expectedVal): self.assertEqual(c, v) #end INITIAL COEFFICIENTS class Clip_ObjectTests(unittest.TestCase): """ setUp + tearDown form a fixture: working environment for the testing code """ def setUp(self): """ start Viewer """ if not hasattr(self, 'vi'): self.vi = Viewer(verbose=False) #self.vi.GUI.top.master.withdraw() self.camera = self.vi.cameras[0] self.camera.master.master.lift() self.spheres = Spheres('test', centers=((-2.5,0,0),(4.5,0,0),), quality=15, radii=(2,4)) self.vi.AddObject(self.spheres) self.vi.Normalize_cb() self.vi.master.update() #self.vi.stopAutoRedraw() self.clip = self.vi.clipP[0] self.clip.Set(enabled=False) #self.spheres.AddClipPlane(self.clip) self.camera.Set(projectionType=self.vi.cameras[0].ORTHOGRAPHIC) self.camera.master.master.lift() self.vi.OneRedraw() def tearDown(self): """ clean-up """ #print 'in clip tearDown' #apply(self.clip.Set, (), self.orig_state) try: self.vi.Exit() delattr(self, 'vi') except: pass #self.vi.__del__() def test_setup_spheres_clips_right_sphere(self): """ check setup of spheres clip plane is working via zbuffer min NB: on sgi this may break if there are other windows open which overlap the camera's window """ width = self.camera.width height = self.camera.height zbuf = self.camera.GrabZBufferAsArray()#lock=False) import sys, os if sys.platform == "darwin" and os.uname()[-1] == "x86_64": if sum(zbuf) == 0: print "clipping plane on Darwin x86_64 does not affect Z buffer" return zbuf.shape = (width, height) self.camera.master.master.lift() self.vi.OneRedraw() #check that something is in the right half midway = int(self.camera.width/2.) #self.assertEqual(round(zbuf[:,midway:].min(),1)< .5, True) self.assertEqual(zbuf[:,midway:].min() < .6, True) self.spheres.AddClipPlane(self.clip) self.clip.Set(enabled=True) self.camera.master.master.lift() self.vi.OneRedraw() zbuf2 = self.camera.GrabZBufferAsArray()#lock=False) zbuf2.shape = (width, height) #self.assertEqual(round(min(min(zbuf2[:,midway:]))), 1.0) self.assertEqual(round(zbuf2[:,midway:].min()), 1.0) def test_translating_clip_removes_half_left_sphere(self): """ check translating clip plane is working via zbuffer min NB: on sgi this may break if there are other windows open which overlap the camera's window """ #self.clip.Set(translation=(-5, 0, 0)) self.spheres.AddClipPlane(self.clip) self.clip.Set(enabled=True) self.clip.Set(translation=(-2.5, 0, 0)) self.camera.master.master.lift() self.vi.update() midway = int(self.camera.width/2.) self.vi.OneRedraw() zbuf = self.camera.GrabZBufferAsArray()#lock=False) import sys, os if sys.platform == "darwin" and os.uname()[-1] == "x86_64": if sum(zbuf) == 0: print "clipping plane on Darwin x86_64 does not affect Z buffer" return zbuf.shape = (self.camera.width, self.camera.height) #self.assertEqual(round(min(min(zbuf[:,midway:]))), 1.0) self.assertEqual(round(zbuf[:,midway:].min()), 1.0) def test_rotating_clip_removes_top_half(self): """ check rotating clip plane is working via zbuffer min NB: on sgi this may break if there are other windows open which overlap the camera's window """ mat = rotax( (0,0,0), (0,0,1), math.pi/2.) self.spheres.AddClipPlane(self.clip) self.clip.Set(enabled=True) self.clip.Set(rotation=mat) self.camera.master.master.lift() self.vi.OneRedraw() zbuf = self.camera.GrabZBufferAsArray()#lock=False) import sys, os if sys.platform == "darwin" and os.uname()[-1] == "x86_64": if sum(zbuf) == 0: print "clipping plane on Darwin x86_64 does not affect Z buffer" return zbuf.shape = (self.camera.width, self.camera.height) # the array is flipped vertically compared tot he image # so we check the top half of the image by testing the # lower half of the array i.e. [midway:, :] midway = int(self.camera.height/2.) #self.assertEqual(round(min(min(zbuf[midway:, :]))), 1.0) self.assertEqual(round(zbuf[midway:, :].min()), 1.0) def test_translating_clip_removes_everything(self): """ check translating clip plane removes everything NB: on sgi this may break if there are other windows open which overlap the camera's window """ self.spheres.AddClipPlane(self.clip) self.clip.Set(enabled=True) self.clip.Set(translation=(-5, 0, 0)) self.camera.master.master.lift() self.vi.OneRedraw() zbuf = self.camera.GrabZBufferAsArray()#lock=False) import sys, os if sys.platform == "darwin" and os.uname()[-1] == "x86_64": if sum(zbuf) == 0: print "clipping plane on Darwin x86_64 does not affect Z buffer" return zbuf.shape = (self.camera.width, self.camera.height) if sys.platform == 'irix6': # on SGI octane 2 the opengl card has a bug: # the clipping plane doesn't affect the Z buffer !!! # so we just set a warning to pass the test anyway if min(min(zbuf)) != max(max(zbuf)): warnings.warn("clipping plane doesn't affect Z buffer") else: #self.assertEqual(min(min(zbuf)), max(max(zbuf))) self.assertEqual(zbuf.min(), zbuf.max()) if __name__ == '__main__': test_cases = [ 'Clip_BaseTests', 'Clip_ObjectTests', ] unittest.main( argv=([__name__ ,] + test_cases) ) #unittest.main() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Texture.py0000644000175000017500000003127211216516777021721 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Texture.py,v 1.28 2009/06/18 20:05:19 sargis Exp $ # # $Id: Texture.py,v 1.28 2009/06/18 20:05:19 sargis Exp $ # import sys, os import Image import numpy.oldnumeric as Numeric import warnings from opengltk.OpenGL import GL import viewerConst import math from colorTool import OneColor from Transformable import Transformable from Geom import Geom from viewerFns import checkKeywords, getkw class Texture(Transformable): """Base class for textures""" keywords = [ 'enable', 'wrapS', 'wrapT', 'magFilter', 'minFilter', 'genModS', 'genModT', 'genPlaneS', 'genPlaneT', 'planeS', 'planeT', 'level', 'auto', 'envMode', 'envColor', 'border', 'format', 'image', ] def __init__(self, check=1, viewer=None, **kw): if __debug__: if check: apply( checkKeywords, ('texture',self.keywords), kw) Transformable.__init__(self, viewer) self.objects = [] # will list the geometries to which this texture # is applied self.name = 'NoName' self.enabled = viewerConst.NO self.dim = GL.GL_TEXTURE_2D self.wrap = [GL.GL_REPEAT, ]*3 self.magFilter = GL.GL_NEAREST self.minFilter = GL.GL_NEAREST self.border = 0 self.genMod = [ GL.GL_OBJECT_LINEAR, GL.GL_OBJECT_LINEAR] self.genPlane = [ GL.GL_OBJECT_PLANE, GL.GL_OBJECT_PLANE] self.plane = [ [1.0, 0.0, 0.0, 0.0], # x=0 [0.0, 1.0, 0.0, 0.0] ] # y=0 self.image = None self.width = 0 self.height = 0 self.level = 0 self.format = GL.GL_RGB self.auto = 1 # automatic computation of texture indices self.envMode = GL.GL_MODULATE self.envColor = OneColor( (1.0, 1.0, 0.0, 0.0) ) # as we resize the texture to be of the power of two, # this allow to recompute texture coordinate after self.resizeRatio = (1, 1) apply( self.Set, (0,), kw) def Set(self, check=1, **kw): """Set various parameters for texture objects: - image=im set an image as the texture to be used. im can be either a Numeric array of bytes with shape (n x m x d) where d can be either 3 or 4. Im can also be a PIL Image object. If thes image is not of type 'RGB' or 'RGBA' it will be converted to 'RGB' if possible, else ... error ! "The set command will also pad the image to make sure that width and height are powers of 2." (has been tested for Image but not for Numeric array yet - guillaume) """ if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) val = getkw(kw, 'enable') if not val is None: assert val in (viewerConst.YES, viewerConst.NO), "enable can only be YES or NO" self.enabled = val val = getkw(kw, 'wrapS') if not val is None: assert val in (GL.GL_REPEAT, GL.GL_CLAMP) self.wrap[0] = val val = getkw(kw, 'wrapT') if not val is None: assert val in (GL.GL_REPEAT, GL.GL_CLAMP) self.wrap[1] = val val = getkw(kw, 'magFilter') if not val is None: assert val in (GL.GL_NEAREST, GL.GL_LINEAR) self.magFilter = val val = getkw(kw, 'minFilter') if not val is None: assert val in (GL.GL_NEAREST, GL.GL_LINEAR) self.minFilter = val val = getkw(kw, 'genModS') if not val is None: assert val in (GL.GL_OBJECT_LINEAR, GL.GL_EYE_LINEAR, GL.GL_SPHERE_MAP) self.genMod[0] = val val = getkw(kw, 'genModT') if not val is None: assert val in (GL.GL_OBJECT_LINEAR, GL.GL_EYE_LINEAR, GL.GL_SPHERE_MAP) self.genMod[1] = val val = getkw(kw, 'genPlaneS') if not val is None: assert val in (GL.GL_OBJECT_PLANE, GL.GL_EYE_PLANE) self.genPlane[0] = val val = getkw(kw, 'genPlaneT') if not val is None: assert val in (GL.GL_OBJECT_PLANE, GL.GL_EYE_PLANE) self.genPlane[1] = val val = getkw(kw, 'planeS') if not val is None: assert len(val)==4 and type(val[0])==type(0.0), "Plane has to be 4Float vector" self.plane[0] = val val = getkw(kw, 'planeT') if not val is None: assert len(val)==4 and type(val[0])==type(0.0), "Plane has to be 4Float vector" self.plane[1] = val val = getkw(kw, 'level') if not val is None: assert type(val)==type(0) and val >=0 self.level = val val = getkw(kw, 'auto') if not val is None: assert val in (viewerConst.YES,viewerConst.NO), "auto can only be YES or NO" self.auto = val val = getkw(kw, 'envMode') if not val is None: assert val in (GL.GL_MODULATE, GL.GL_REPLACE, GL.GL_DECAL, GL.GL_BLEND ), "envMode can only be GL_MODULATE, GL_DECAL, or GL_BLEND" self.envMode = val val = getkw(kw, 'envColor') if val: col = OneColor(val) if col: self.envColor = col b = getkw(kw, 'border') f = getkw(kw, 'format') im = getkw(kw, 'image') if im is not None: if isinstance(im, Image.Image): lImInstaceImage = True else: lImInstaceImage = False if lImInstaceImage is True: width = im.size[0] height = im.size[1] else: height = im.shape[0] width = im.shape[1] # find smallest power of 2 larger than image size dim1 = 1 dim2 = 1 while dim1 < width: dim1 = dim1 << 1 while dim2 < height: dim2 = dim2 << 1 self.resizeRatio = ( width / float(dim1), height / float(dim2) ) if os.name != 'nt': #sys.platform != 'win32': lMaxTextureSize = GL.glGetInteger(GL.GL_MAX_TEXTURE_SIZE) #print "width", width, height, dim1, dim2, lMaxTextureSize if (dim1 > lMaxTextureSize) or (dim2 > lMaxTextureSize): warnings.warn('texture map too big for this implementation of opengl %d'%lMaxTextureSize) if lImInstaceImage is True: if im.mode !='RGB' and im.mode !='RGBA': im = im.convert('RGB') im = im.transpose(Image.FLIP_TOP_BOTTOM) imstr = im.tostring() imarr = Numeric.fromstring( imstr, 'B') if im.mode=='RGB': imarr.shape = (height, width, 3) elif im.mode=='RGBA': imarr.shape = (height, width, 4) im = imarr if (dim1 != width) or (dim2 != height): if len(im.shape) == 3: newArray = Numeric.zeros( (dim2, dim1, len(im[0][0]) ) ) else: newArray = Numeric.zeros( (dim2, dim1 ) ) for i in range(height): for j in range(width): newArray[i][j] = im[i][j] im = newArray.astype('B') if b: assert type(b)==type(0) else: b = 0 self.border = b if f: assert f in (GL.GL_RGB, GL.GL_RGBA), "format can only be GL_RGB or GL_RGBA" assert type(im).__name__ == 'ndarray' assert im.dtype.char == 'B' if im.shape[-1] == 3: if f and f != GL.GL_RGB: raise ValueError("bad image format") self.format = GL.GL_RGB elif im.shape[-1] == 4: if f and f != GL.GL_RGBA: raise ValueError("bad image format") self.format = GL.GL_RGBA for o in self.objects: o.transparent=1 o.inheritMaterial=0 if self.viewer: self.viewer.objectsNeedingRedo[o] = None l = len(im.shape) if l==2: w=im.shape[0] - 2*b q, r = divmod(math.log(w)/math.log(2), 1) if r != 0.0: raise ValueError("Image width must be 2**m +2b") self.dim = GL.GL_TEXTURE_1D self.image = im self.width = im.shape[0] elif l==3: w=im.shape[0] - 2*b q, r = divmod(math.log(w)/math.log(2), 1) if r != 0.0: raise ValueError("Image width must be 2**m +2b") h=im.shape[1] -2*b q, r = divmod(math.log(h)/math.log(2), 1) if r != 0.0: raise ValueError("Image height must be 2**m +2b") self.dim = GL.GL_TEXTURE_2D self.image = im self.width = im.shape[1] self.height = im.shape[0] else: raise ValueError("Bad shape for image") if self.viewer: self.viewer.deleteOpenglList() self.viewer.Redraw() def getTextureCoordinatesAfterResizeRatio(self, textureCoordinates): """ to be called with textureCoordinates=geom.vertexSet.texCoords """ if self.resizeRatio == (1., 1.): return textureCoordinates.copy() lenTextureCoordinates = len(textureCoordinates) assert lenTextureCoordinates > 0 assert len(textureCoordinates[0]) == 2 newTextureCoordinates = [] for i in range(lenTextureCoordinates): newTextureCoordinates.append ( ( self.resizeRatio[0] * textureCoordinates[i][0], self.resizeRatio[1] * textureCoordinates[i][1] ) ) return newTextureCoordinates def MakeMatrix(self): """Build texture transformation matrix""" t = self GL.glMatrixMode(GL.GL_TEXTURE) GL.glLoadIdentity() GL.glTranslatef(float(t.translation[0]),float(t.translation[1]),float(t.translation[2])) GL.glMultMatrixf(t.rotation) GL.glScalef(float(t.scale[0]),float(t.scale[1]),float(t.scale[2])) GL.glMatrixMode(GL.GL_MODELVIEW) def dump(self): print '\nenabled: ', self.enabled, \ '\ndim: ', self.dim, \ '\nwrap: ', self.wrap, \ '\nmagFilter: ', self.magFilter, \ '\nminFilter: ', self.minFilter, \ '\nborder: ', self.border, \ '\ngenMod: ', self.genMod, \ '\ngenPlane: ', self.genPlane, \ '\nplane: ', self.plane, \ '\nimage: ', self.image.shape, \ '\nwidth: ', self.width, \ '\nheight: ', self.height, \ '\nlevel: ', self.level, \ '\nformat: ', self.format, \ '\nauto: ', self.auto, \ '\nenvMode: ', self.envMode, \ '\nenvColor: ', self.envColor def Setup(self): """Setup texture mapping""" t = self if not t.enabled: GL.glDisable(t.dim) return t.MakeMatrix() GL.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, t.envMode) if t.envMode==GL.GL_BLEND: GL.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_COLOR, t.envColor) GL.glTexParameterf(t.dim, GL.GL_TEXTURE_WRAP_S, t.wrap[0]) GL.glTexParameterf(t.dim, GL.GL_TEXTURE_MAG_FILTER, t.magFilter) GL.glTexParameterf(t.dim, GL.GL_TEXTURE_MIN_FILTER, t.minFilter) if t.auto: GL.glTexGeni(GL.GL_S, GL.GL_TEXTURE_GEN_MODE, t.genMod[0]) GL.glTexGenfv(GL.GL_S, t.genPlane[0], t.plane[0]) GL.glEnable(GL.GL_TEXTURE_GEN_S) else: GL.glDisable(GL.GL_TEXTURE_GEN_S) if t.dim==GL.GL_TEXTURE_1D: from opengltk.extent import _gllib _gllib.glTexImage1D(t.dim, t.level, t.format, t.width, 0, t.format, GL.GL_UNSIGNED_BYTE, t.image) elif t.dim==GL.GL_TEXTURE_2D: GL.glTexParameterf(t.dim, GL.GL_TEXTURE_WRAP_T, t.wrap[1]) from opengltk.extent import _gllib # directly call the C function to not have to transform the # t.image into a bufarray #print "t.width, t.height", t.width, t.height _gllib.glTexImage2D(t.dim, t.level, t.format, t.width, t.height, t.border!=0, t.format, GL.GL_UNSIGNED_BYTE, t.image) ## import bufarray ## bimage = bufarray.Bufarray(im, bufarray.ubyteCtype) ## GL.glTexImage2D(t.dim, t.level,GL.GL_UNSIGNED_BYTE, ## t.width, t.height, t.border!=0, t.format, ## bimage) ## GL.glTexImage2D(t.dim, t.level, t.format, ## t.width, t.height, t.border!=0, t.format, ## GL.GL_UNSIGNED_BYTE, t.image) if t.auto: GL.glTexGeni(GL.GL_T, GL.GL_TEXTURE_GEN_MODE, t.genMod[1]) GL.glTexGenfv(GL.GL_T, t.genPlane[1], t.plane[1]) GL.glEnable(GL.GL_TEXTURE_GEN_T) else: GL.glDisable(GL.GL_TEXTURE_GEN_T) GL.glEnable(t.dim) if __name__ == '__main__': t = Texture() import Image im = Image.open('lena.jpg') t.Set(enable=1, image=im) # if g is a DejaVu geometry #g.Set(texture=t) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/__init__.py0000644000175000017500000001474412044316514022010 0ustar debiandebian######################################################################## # # Date: 2000 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # ######################################################################### # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/__init__.py,v 1.70 2012/10/31 21:51:08 mgltools Exp $ # # $Id: __init__.py,v 1.70 2012/10/31 21:51:08 mgltools Exp $ # import os import sys import warnings # makes this directory the viewer package ## <<<<<<< __init__.py ## try: ## import OpenGL ## if not OpenGL._numeric: ## import sys ## print 'FATAL ERROR: DejaVu requires the OpenGL Package to be compiled \ ## with the the NUMERIC option turned on' ## sys.exit(1) ## except: ## import sys ## print 'FATAL ERROR: OpenGL Package not found' ## sys.exit(1) ## def loadTogl(master): ## # simulate the setting of TCLLIPATH ## import os, sys ## # Togl is expected to be in sys.exec_prefix/lib ## # build path to directory containing Togl ## pth = os.path.join(sys.exec_prefix, 'lib') ## ToglPath = os.path.join(sys.exec_prefix, pth) ## # get TCL interpreter auto_path variable ## tclpath = master.tk.globalgetvar('auto_path') ## # ToglPath not already in there, add it ## from string import split ## if ToglPath not in split(tclpath): ## tclpath = ToglPath + ' ' + tclpath ## master.tk.globalsetvar('auto_path', tclpath ) ## # load Togl extension into TCL interpreter ## master.tk.call('package', 'require', 'Togl') #======= ## try: ## from bufarray import bufarray_Numeric ## except ImportError: ## raise RuntimeError('FATAL ERROR: bufarray_Numeric not found') ## import bufarray_array ## from bufarray import bufarray_array try: from opengltk import OpenGL except ImportError: print 'FATAL ERROR: opengltk.OpenGL Package not found' raise RuntimeError('FATAL ERROR: opengltk.OpenGL Package not found') from Tkinter import _default_root, Tk def loadTogl(master): # simulate the setting of TCLLIPATH import sys, os from os import path # Togl is expected to be # build path to directory containing Togl from opengltk.OpenGL import Tk ToglPath = path.dirname(path.abspath(Tk.__file__)) # get TCL interpreter auto_path variable tclpath = master.tk.globalgetvar('auto_path') # ToglPath not already in there, add it from string import split if ToglPath not in tclpath: tclpath = (ToglPath,) + tclpath master.tk.globalsetvar('auto_path', tclpath ) # load Togl extension into TCL interpreter if os.name == 'nt': toglVersion = master.tk.call('package', 'require', 'Togl','1.7') else: toglVersion = master.tk.call('package', 'require', 'Togl','2.1') return toglVersion dejavurcText = """######################################################################## # # Date: Decembre 2006 Authors: Guillaume Vareille, Michel Sanner # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Guillaume Vareille, Michel Sanner and TSRI # # DejaVu Resource File # ######################################################################### # To customize DejaVu, you can modify the _dejavurc file: # unix: ~/.mgltools/[version number]/DejaVu/_dejavurc # windows: \Documents and Settings\(user name)\.mgltools\(version numer)\DejaVu\_dejavurc # DejaVu will generate it automatically if it doesn't exist. # Do not modify the original source file DejaVu/__init__.py ################################################################## preventIntelBug_BlackTriangles = None # True, False or None (will evaluate GL_VENDOR) preventIntelBug_WhiteTriangles = None # True, False or None (will evaluate GL_VENDOR) defaultSpinningMode = 0 # 0 - None , 1 - Spin , 2 - Bounce , 3 - Oscillate allowedAntiAliasInMotion = 0 # 0,2,3,4,8,15,24,66 #enableStereo = False # True, False defaultAntiAlias = None # None,0,2,3,4,8,15,24,66, None will decide if the graphic card is good enough enableSelectionContour = True # True, False selectionContourSize = 0 # 0 (= disabled), 1,2,3 ..... selectionContourColor = (0., 1., 1., .7) # (1., 0., 1., .7) selectionPatternSize = 6 # 0 .... 50 (0 = disabled) enableVertexArrayVBO = False enableVertexArrayNonVBO = False enableVertexArray = enableVertexArrayVBO or enableVertexArrayNonVBO def functionName0(level=1): # i.e. this func => level 0 (useless) # calling function => level 1 # one function up => level 2 assert level > 0 , level lsf = sys._getframe(level) functionname = lsf.f_code.co_name from os import sep filename = lsf.f_code.co_filename.split(sep)[-1] linenumber = lsf.f_lineno if True: #filename == 'MaterialEditor.py': print functionname, filename, linenumber """ def ensureDejaVuResourceFile(): """verify or generate _dejavurc file """ #print "ensureDejaVuResourceFile" #import pdb;pdb.set_trace() from mglutil.util.packageFilePath import getResourceFolderWithVersion rcFolder = getResourceFolderWithVersion() if rcFolder is None: return rcFolder += os.sep + 'DejaVu' if not os.path.isdir(rcFolder): try: os.mkdir(rcFolder) except: txt = "Cannot create the Resource Folder %s" %rcFolder warnings.warn(txt) return None rcFile = rcFolder + os.sep + '_dejavurc' if os.path.isfile(rcFile) is False: try: f = open(rcFile, "w") map( lambda x, f=f: f.write(x), dejavurcText ) f.close() except: txt = "can not create _dejavurc" warnings.warn(txt) return None return rcFile # after this we can access variables in _dejavurc with # from DejaVu import preventIntelBug_BlackTriangles rcFile = ensureDejaVuResourceFile() if rcFile is None: exec( dejavurcText ) else: execfile( rcFile ) from Viewer import Viewer from viewerConst import * CRITICAL_DEPENDENCIES = ['opengltk', 'numpy', 'mglutil','geomutils'] NONCRITICAL_DEPENDENCIES = ['PIL', 'numarray', 'Pmw', 'gle', 'UTpackages', 'NetworkEditor', 'symserv', 'Vision', 'Volume', 'QSlimLib', 'bhtree','pyglf', 'pymedia','Scenario2', 'SimPy', 'mslib', 'pytz', 'Pmv', 'bpy', 'BPyMesh', 'MolKit'] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cylinders.py0000644000175000017500000010626611266175254022217 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################ # # Author: Michel F. SANNER # # Revision: Guillaume Vareille # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Cylinders.py,v 1.81 2009/10/16 22:58:52 annao Exp $ # # $Id: Cylinders.py,v 1.81 2009/10/16 22:58:52 annao Exp $ # # TODO # 4 - include support for DIFFUSE_AND_AMBIENT # 6 - KNOWN BUG: color (0,0,0) per vertex does seem to work import numpy import numpy.oldnumeric as Numeric, math, sys from numpy.oldnumeric import array from opengltk.OpenGL import GL from opengltk.extent.utillib import solidCylinder import DejaVu from DejaVu.IndexedGeom import IndexedGeom import datamodel, viewerConst from viewerFns import checkKeywords from mglutil.math.rotax import rotax from colorTool import glMaterialWithCheck, resetMaterialMemory from Materials import Materials try: from opengltk.extent.utillib import glDrawCylinderSet except: glDrawCylinderSet = None class Cylinders(IndexedGeom): """Class for sets of cylinders """ keywords = IndexedGeom.keywords + [ 'radii', 'quality' ] def getState(self, full=False): state = IndexedGeom.getState(self, full) state['quality'] = self.quality if full: rad = self.vertexSet.radii.array if len(rad): state['radii'] = rad return state def __init__(self, name=None, check=1, **kw): if not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set self.culling = GL.GL_BACK self.inheritCulling = 0 self.frontPolyMode = GL.GL_FILL self.inheritFrontPolyMode = viewerConst.NO self.lighting = viewerConst.YES self.realFMat = Materials() # used in RedoDisplayList to build self.realBMat = Materials() # used in RedoDisplayList to build # material taking getFrom into account self.quality = None self.cyldraw = self.cyldrawWithSharpColorBoundaries apply( IndexedGeom.__init__, (self, name, check), kw) assert len(self.vertexSet.vertices.ashape)==2 if hasattr(self, 'oneRadius') is False: self.oneRadius = viewerConst.YES self.vertexSet.radii = datamodel.ScalarProperties( 'radii', [1.], datatype=viewerConst.FPRECISION) self._modified = False self.useGlDrawCylinderSet = 1 def Set(self, check=1, redo=1, updateOwnGui=True, **kw): """set data for this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ redoFlags = 0 # Exceptionnaly this has to be before the call to Geom.Set # because we want to override the treatment of it by Geom.Set invertNormals = kw.get('invertNormals') if invertNormals is not None: kw.pop('invertNormals') if self.invertNormals != invertNormals: self.invertNormals = invertNormals redoFlags |= self._redoFlags['redoDisplayListFlag'] redoFlags |= apply( IndexedGeom.Set, (self, check, 0), kw) rad = kw.get('radii') if rad is not None: redoFlags |= self._redoFlags['redoDisplayListFlag'] try: rad = float(rad) self.oneRadius = viewerConst.YES self.vertexSet.radii = datamodel.ScalarProperties('radii', [rad], datatype=viewerConst.FPRECISION) except: # it is not a number, so it has to be a sequence l = len(rad) import types if type(rad) == types.StringType: raise TypeError, "bad value for radii" elif l==len(self.vertexSet.vertices): self.oneRadius = viewerConst.NO self.vertexSet.radii = datamodel.ScalarProperties( 'radii', rad, datatype=viewerConst.FPRECISION) elif l in (1, 2): self.oneRadius = viewerConst.YES self.vertexSet.radii = datamodel.ScalarProperties( 'radii', [rad], datatype=viewerConst.FPRECISION) else: raise ValueError, "bad value for radii" v=kw.get('vertices') if rad is not None or v is not None and \ hasattr(self.vertexSet, 'radii'): self.vertexSet.radii.PropertyStatus(len(self.vertexSet)) if self.vertexSet.radii.status < viewerConst.COMPUTED: self.oneRadius = viewerConst.YES else: self.oneRadius = viewerConst.NO quality = kw.pop('quality', None) if quality is not None or self.quality not in [1,2,3,4,5]: if quality in [1,2,3,4,5]: self.quality = quality else: if len(self.vertexSet.vertices.array) < 500: self.quality = 5 elif len(self.vertexSet.vertices.array) < 5000: self.quality = 4 elif len(self.vertexSet.vertices.array) < 50000: self.quality = 3 elif len(self.vertexSet.vertices.array) < 100000: self.quality = 2 else: self.quality = 1 self.v, self.n = self._cylinderTemplate() redoFlags |= self._redoFlags['redoDisplayListFlag'] return self.redoNow(redo, updateOwnGui, redoFlags) def Draw(self): #print "Cylinders.Draw" #import traceback;traceback.print_stack() # for some reason if I do not set this always on MacOSX only the first # cylinder gets the right color if sys.platform=='darwin' \ or DejaVu.preventIntelBug_BlackTriangles is True: self.checkMat = False else: self.checkMat = True if len(self.vertexSet.vertices)==0 or len(self.faceSet.faces)==0: return if self.inheritMaterial: fp = None bp = None face = None else: mat = self.materials[GL.GL_FRONT] rmat = self.realFMat bind = [10,10,10,10] for pInd in range(4): bind[pInd], rmat.prop[pInd] = mat.GetProperty(pInd) if rmat.binding[pInd] == viewerConst.OVERALL: glMaterialWithCheck( GL.GL_FRONT, viewerConst.propConst[pInd], rmat.prop[pInd][0]) if pInd==1: GL.glColor4fv(rmat.prop[pInd][0]) pInd = 4 # FIXME mat.GetProperty does not handle shininess if rmat.binding[pInd] == viewerConst.OVERALL: glMaterialWithCheck( GL.GL_FRONT, viewerConst.propConst[pInd], rmat.prop[pInd][0]) rmat.prop[4] = mat.prop[4] rmat.prop[5] = mat.prop[5] rmat.binding[:4] = bind rmat.binding[4:] = rmat.binding[4:] fp = rmat # fp = self.materials[GL.GL_FRONT] if fp: if self.frontAndBack: face = GL.GL_FRONT_AND_BACK bp = None else: face = GL.GL_FRONT mat = self.materials[GL.GL_BACK] rmat = self.realBMat bind = [10,10,10,10] for pInd in range(4): bind[pInd], rmat.prop[pInd]=mat.GetProperty(pInd) if rmat.binding[pInd] == viewerConst.OVERALL: glMaterialWithCheck( GL.GL_BACK, viewerConst.propConst[pInd], rmat.prop[pInd][0]) rmat.prop[4] = mat.prop[4] rmat.prop[5] = mat.prop[5] rmat.binding[:4] = bind rmat.binding[4:] = rmat.binding[4:] bp = rmat c = self.vertexSet.vertices.array if glDrawCylinderSet: radii = self.vertexSet.radii.array fmat = None fbind = None bmat = None bbind = None if fp: fmat = fp.prop[0:5] fbind = fp.binding[0:5] if bp: bmat = bp.prop[0:5] bbind = bp.binding[0:5] highlight = None if len(self.highlight) > 0: highlight = self.highlight if self.getSharpColorBoundaries() in [True, 1]: return glDrawCylinderSet(c, self.faceSet.faces.array, radii, fmat, bmat, fbind, bbind, self.frontAndBack, self.quality, self.invertNormals, highlight=highlight, sharpColorBoundaries=1) else: v1 = self.v[:,0,:].astype("f") v2 = self.v[:,1,:].astype("f") return glDrawCylinderSet(c, self.faceSet.faces.array, radii, fmat, bmat, fbind, bbind, self.frontAndBack, self.quality, self.invertNormals, sharpColorBoundaries=0, npoly = self.npoly, vertx = v1, verty=v2, norms = self.n) if self.getSharpColorBoundaries() in [True, 1]: self.cyldraw = self.cyldrawWithSharpColorBoundaries else: self.cyldraw = self.cyldrawWithInterpolatedColors if self.oneRadius == viewerConst.NO: radii = self.vertexSet.radii.array else: radius = self.vertexSet.radii.array[0] pickName = 0 for i in xrange(len(self.faceSet.faces.array)): #print 'CYLINDERS', i, '********************************', for j in xrange(len(self.faceSet.faces.array[i])-1): vi1 = self.faceSet.faces.array[i][j] vi2 = self.faceSet.faces.array[i][j+1] if fp: fpp1 = [None,None,None,None,None] fpp2 = [None,None,None,None,None] for m in (0,1,2,3,4): if fp.binding[m] == viewerConst.PER_VERTEX: fpp1[m] = fp.prop[m][vi2] fpp1[m] = array(fpp1[m],copy=1) fpp2[m] = fp.prop[m][vi1] fpp2[m] = array(fpp2[m],copy=1) elif fp.binding[m] == viewerConst.PER_PART: fpp2[m] = fpp1[m] = fp.prop[m][i] fpp1[m] = array(fpp1[m],copy=1) fpp2[m] = array(fpp2[m],copy=1) else: fpp1 = fpp2 = None if bp and not self.frontAndBack: bpp1 = [None,None,None,None,None] bpp2 = [None,None,None,None,None] for m in (0,1,2,3,4): if bp.binding[m] == viewerConst.PER_VERTEX: bpp1[m] = bp.prop[m][vi2] bpp1[m] = array(bpp1[m],copy=1) bpp2[m] = bp.prop[m][vi1] bpp2[m] = array(bpp2[m],copy=1) elif bp.binding[m] == viewerConst.PER_PART: bpp2[m] = bpp1[m] = bp.prop[m][i] bpp1[m] = array(bpp1[m],copy=1) bpp2[m] = array(bpp2[m],copy=1) else: bpp1 = bpp2 = None GL.glPushName(pickName) if len(self.highlight) > 0: if self.oneRadius: self.cyldraw(c[vi1], c[vi2], radius, radius, fpp1, bpp1, fpp2, bpp2, face, highlightX=self.highlight[vi1], highlightY=self.highlight[vi2]) else: if vi1 < vi2: self.cyldraw(c[vi1], c[vi2], radii[vi2], radii[vi1], fpp1, bpp1, fpp2, bpp2, face, highlightX=self.highlight[vi1], highlightY=self.highlight[vi2]) else: self.cyldraw(c[vi1], c[vi2], radii[vi1], radii[vi2], fpp1, bpp1, fpp2, bpp2, face, highlightX=self.highlight[vi1], highlightY=self.highlight[vi2]) else: if self.oneRadius: self.cyldraw(c[vi1], c[vi2], radius, radius, fpp1, bpp1, fpp2, bpp2, face) else: if vi1 < vi2: self.cyldraw(c[vi1], c[vi2], radii[vi2], radii[vi1], fpp1, bpp1, fpp2, bpp2, face) else: self.cyldraw(c[vi1], c[vi2], radii[vi1], radii[vi2], fpp1, bpp1, fpp2, bpp2, face) GL.glPopName() pickName = pickName +1 #print 'CYLINDERS done' return 1 def cyldrawWithSharpColorBoundaries(self, x, y, radx, rady, colxf=None, colxb=None, colyf=None, colyb=None, face=None, highlightX=0, highlightY=0): # determine scale and rotation of template import math sz=0.0 for i in (0,1,2): sz=sz+(x[i]-y[i])*(x[i]-y[i]) if sz <= 0.0: return sz = math.sqrt(sz) sz2 = sz * .5 valueCos = (y[2]-x[2])/sz valueCos = min(valueCos, 1) valueCos = max(valueCos, -1) rx = -180.0*math.acos(valueCos)/math.pi dx = y[0]-x[0] dy = y[1]-x[1] if math.fabs(dx) < 0.00001 and math.fabs(dy) < 0.00001: rz = 0.0 else: rz = -180.0*math.atan2(dx,dy)/math.pi GL.glPushMatrix() GL.glTranslatef(float(x[0]),float(x[1]),float(x[2])) if rz<=180.0 and rz >=-180.0: GL.glRotatef(float(rz), 0., 0., 1.) GL.glRotatef(float(rx), 1., 0., 0.) if colyf: for m in (0,1,2,3,4): if colyf[m] is not None: glMaterialWithCheck( face, viewerConst.propConst[m], colyf[m], check=self.checkMat) if colyf[1] is not None: GL.glColor4fv(colyf[1]) if colyb and face!=GL.GL_FRONT_AND_BACK: for m in (0,1,2,3,4): if colyb[m] is not None: self.checkMat = 0 glMaterialWithCheck( GL.GL_BACK, viewerConst.propConst[m], colyb[m], check=self.checkMat) # this tests (colxf==colyf) self.checkMat = 1 idem = (highlightX == highlightY) if idem is True: if colxf is None: if colyf is not None: idem = False else: if colyf is None: idem = False else: lencol = len(colxf) if lencol != len(colyf): idem = False else: for i in range(lencol): if colxf[i] is not None: if bool(numpy.alltrue(colxf[i] == colyf[i])) is False: idem = False break if idem is True: if colxb is None: if colyb is not None: idem = False else: if colyb is None: idem = False else: lencol = len(colxb) if lencol != len(colyb): idem = False else: for i in range(lencol): if colxb[i] is not None: if bool(numpy.alltrue(colxb[i] == colyb[i])) is False: idem = False break quality = self.quality * 5 if idem is True: if highlightX != 0: GL.glStencilFunc(GL.GL_ALWAYS, 1, 1) solidCylinder(float(rady), float(radx), sz, quality, 1, self.invertNormals) GL.glStencilFunc(GL.GL_ALWAYS, 0, 1) else: solidCylinder(float(rady), float(radx), sz, quality, 1, self.invertNormals) else: midRadius = (radx + rady) * .5 if highlightX != 0: GL.glStencilFunc(GL.GL_ALWAYS, 1, 1) solidCylinder(midRadius, float(radx), sz2, quality, 1, self.invertNormals) GL.glStencilFunc(GL.GL_ALWAYS, 0, 1) else: solidCylinder(midRadius, float(radx), sz2, quality, 1, self.invertNormals) GL.glTranslatef(0, 0, float(sz2)) if colxf: for m in (0,1,2,3,4): if colxf[m] is not None: glMaterialWithCheck( face, viewerConst.propConst[m], colxf[m], check=self.checkMat ) if colxf[1] is not None: GL.glColor4fv(colxf[1]) if colxb and face!=GL.GL_FRONT_AND_BACK: for m in (0,1,2,3,4): if colxb[m] is not None: glMaterialWithCheck( GL.GL_BACK, viewerConst.propConst[m], colxb[m], check=self.checkMat ) if highlightY != 0: GL.glStencilFunc(GL.GL_ALWAYS, 1, 1) solidCylinder(float(rady), midRadius, sz2, quality, 1, self.invertNormals) GL.glStencilFunc(GL.GL_ALWAYS, 0, 1) else: solidCylinder(float(rady), midRadius, sz2, quality, 1, self.invertNormals) GL.glPopMatrix() def cyldrawWithInterpolatedColors(self, x, y, radx, rady, colxf=None, colxb=None, colyf=None, colyb=None, face=None, **kw): # draw a cylinder going from x to y with radii rx, and ry and materials # colxf and colxb for front and back mterial in x # colyf and colyb for front and back mterial in y # face can be GL_FRONT_AND_BACK or something else # determine scale and rotation of template import math sz=0.0 for i in (0,1,2): sz=sz+(x[i]-y[i])*(x[i]-y[i]) if sz <= 0.0: return sz = math.sqrt(sz) valueCos = (y[2]-x[2])/sz valueCos = min(valueCos, 1) valueCos = max(valueCos, -1) rx = -180.0*math.acos(valueCos)/math.pi dx = y[0]-x[0] dy = y[1]-x[1] if math.fabs(dx) < 0.00001 and math.fabs(dy) < 0.00001: rz = 0.0 else: rz = -180.0*math.atan2(dx,dy)/math.pi GL.glPushMatrix() GL.glTranslatef(float(x[0]),float(x[1]),float(x[2])) if rz<=180.0 and rz >=-180.0: GL.glRotatef(float(rz), 0., 0., 1.) GL.glRotatef(float(rx), 1., 0., 0.) # draw cylinder GL.glBegin(GL.GL_QUAD_STRIP) for i in range(self.npoly+1): if self.invertNormals: GL.glNormal3fv(-self.n[i]) else: GL.glNormal3fv(self.n[i]) if colxf: for m in (0,1,2,3,4): if colxf[m] is not None: #print "colxf[m]",type(colxf[m]) #print 'AAAAA', colxf[m] glMaterialWithCheck( face, viewerConst.propConst[m], colxf[m], check=self.checkMat ) if colxf[1] is not None: GL.glColor4fv(colxf[1]) if colxb and face!=GL.GL_FRONT_AND_BACK: for m in (0,1,2,3,4): if colxb[m] is not None: glMaterialWithCheck( GL.GL_BACK, viewerConst.propConst[m], colxb[m], check=self.checkMat ) vx = self.v[i][0] GL.glVertex3f(float(vx[0]*radx), float(vx[1]*radx), float(vx[2]*sz)) if colyf: for m in (0,1,2,3,4): if colyf[m] is not None: #print 'BBBBB', colyf[m] glMaterialWithCheck( face, viewerConst.propConst[m], colyf[m], check=self.checkMat ) if colyf[1] is not None: GL.glColor4fv(colyf[1]) if colyb and face!=GL.GL_FRONT_AND_BACK: for m in (0,1,2,3,4): if colyb[m] is not None: glMaterialWithCheck( GL.GL_BACK, viewerConst.propConst[m], colyb[m], check=self.checkMat ) vy = self.v[i][1] GL.glVertex3f(float(vy[0]*rady), float(vy[1]*rady), float(vy[2]*sz)) GL.glEnd() GL.glPopMatrix() def _cylinderTemplate(self): npoly = self.quality * 5 v = Numeric.zeros( ((npoly+1),2,3), 'f') n = Numeric.zeros( ((npoly+1),3), 'f') self.npoly = npoly a = -math.pi # starting angle d = 2*math.pi / npoly # increment for i in range(npoly+1): n[i][0] = v[i][0][0] = v[i][1][0] = math.cos(a) n[i][1] = v[i][0][1] = v[i][1][1] = math.sin(a) n[i][2] = v[i][1][2] = 0.0 v[i][0][2] = 1.0 a=a+d return v,n def _cylinderTemplateDaniel(self, quality=None): """ This template doesn't put the last point over the first point as done in the other template. In addition, it computes and returns face indices. I don't compute normals This template is used by asIndexedyPolygons()""" if quality is None: quality = self.quality * 5 import numpy.oldnumeric as Numeric, math v = Numeric.zeros( ((quality),2,3), 'f') n = Numeric.zeros( ((quality),3), 'f') f = [] a = -math.pi # starting angle d = 2*math.pi / quality # increment # compute vertices for i in range(quality): v[i][0][0] = v[i][1][0] = math.cos(a) v[i][0][1] = v[i][1][1] = math.sin(a) v[i][1][2] = 0.0 v[i][0][2] = 1.0 a=a+d lV = len(v) # compute template cylinder faces for i in range(lV-1): # cylinder body f.append([i, i+1, lV+i+1]) f.append([lV+i+1, lV+i, i]) f.append([lV-1, 0, lV]) #close last point to first f.append([lV-1, lV, lV+i+1]) for i in range(lV-2): # cylinder bottom cap f.append([0, i+2 ,i+1]) for i in range(lV-2): # cylinder top cap f.append([lV+i+1, lV+i+2, lV]) return v, f def asIndexedPolygons(self, run=1, quality=None, radius=None, **kw): """ run=0 returns 1 if this geom can be represented as an IndexedPolygon and None if not. run=1 returns the IndexedPolygon object.""" #print "Cylinders.asIndexedPolygons", quality if run==0: return 1 # yes, I can be represented as IndexedPolygons import numpy.oldnumeric as Numeric, math from mglutil.math.transformation import Transformation if quality in [1,2,3,4,5]: quality = quality elif quality < 0 and self.quality in [2,3,4,5]: quality = self.quality - 2 else: quality = self.quality - 1 quality *= 5 # make a copy of the cylinderTemplate tmpltVertices, tmpltFaces = self._cylinderTemplateDaniel(\ quality=quality) centers = self.vertexSet.vertices.array faces = self.faceSet.faces.array tmpltVertices = Numeric.array(tmpltVertices).astype('f') tmpltFaces = Numeric.array(tmpltFaces).astype('f') addToFaces = Numeric.ones((tmpltFaces.shape)) * 2*len(tmpltVertices) VV = [] # this list stores all vertices of all cylinders FF = [] # this list stores all faces of all cylinders # now loop over all cylinders in self for index in xrange(len(faces)): # tv temporarily stores the transformed unit cylinder vertices tv = tmpltVertices.__copy__() pt0 = centers[faces[index][0]] # bottom of cylinder pt1 = centers[faces[index][1]] # top of cylinder # get radius for cylinder if radius is not None: radx = rady = radius #override radii elif self.oneRadius: radx = rady = radius = self.vertexSet.radii.array[0] else: radx = self.vertexSet.radii.array[faces[index][1]] rady = self.vertexSet.radii.array[faces[index][0]] # determine scale and rotation of current cylinder sz=0.0 for nbr in (0,1,2): sz=sz+(pt0[nbr]-pt1[nbr])*(pt0[nbr]-pt1[nbr]) if sz <= 0.0: return sz = math.sqrt(sz) rx = -180.0*math.acos((pt1[2]-pt0[2])/sz)/math.pi dx = pt1[0]-pt0[0] dy = pt1[1]-pt0[1] if math.fabs(dx) < 0.00001 and math.fabs(dy) < 0.00001: rz = 0.0 else: rz = -180.0*math.atan2(dx,dy)/math.pi # prepare rotations matrices of current cylinder Rx = Transformation(quaternion=[1,0,0,rx]) if rz<=180.0 and rz >=-180.0: Rz = Transformation(quaternion=[0,0,1,rz]) R = Rz * Rx else: R = Rx r = R.getMatrix() k = 0 for v in tmpltVertices: # I DO NOT use Numeric.matrixmultiply # here, in order to gain significant speed v0x, v0y, v0z = v[0] # saves some lookups v1x, v1y, v1z = v[1] tv[k][0]=\ ([r[0][0]*v0x*radx+r[1][0]*v0y*radx+r[2][0]*v0z*sz+pt0[0], r[0][1]*v0x*radx+r[1][1]*v0y*radx+r[2][1]*v0z*sz+pt0[1], r[0][2]*v0x*radx+r[1][2]*v0y*radx+r[2][2]*v0z*sz+pt0[2]]) tv[k][1]=\ ([r[0][0]*v1x*rady+r[1][0]*v1y*rady+r[2][0]*v1z+pt0[0], r[0][1]*v1x*rady+r[1][1]*v1y*rady+r[2][1]*v1z+pt0[1], r[0][2]*v1x*rady+r[1][2]*v1y*rady+r[2][2]*v1z+pt0[2]]) k = k + 1 ctv = None ctv = Numeric.concatenate( (tv[:,1], tv[:,0] ) ) # now add the data to the big lists VV.extend(list(ctv)) FF.extend(list(tmpltFaces)) # increase face indices by lenght of vertices tmpltFaces = tmpltFaces + addToFaces VV = Numeric.array(VV).astype('f') FF = Numeric.array(FF).astype('f') # FIXME: should I compute normals? # now we can build the IndexedPolygon geom from DejaVu.IndexedPolygons import IndexedPolygons cylGeom = IndexedPolygons("cyl", vertices=VV, faces=FF, visible=1, invertNormals=self.invertNormals) # copy Cylinders materials into cylGeom matF = self.materials[GL.GL_FRONT] matB = self.materials[GL.GL_BACK] cylGeom.materials[GL.GL_FRONT].binding = matF.binding[:] cylGeom.materials[GL.GL_FRONT].prop = matF.prop[:] cylGeom.materials[GL.GL_BACK].binding = matB.binding[:] cylGeom.materials[GL.GL_BACK].prop = matB.prop[:] # if binding per vertex: if cylGeom.materials[GL.GL_FRONT].binding[1] == viewerConst.PER_VERTEX: newprop = [] props = cylGeom.materials[GL.GL_FRONT].prop[1] for i in xrange(len(faces)): for j in xrange(len(faces[i])-1): vi1 = self.faceSet.faces.array[i][j] vi2 = self.faceSet.faces.array[i][j+1] colx = props[vi2] coly = props[vi1] # add second color to first half of cyl vertices for k in range(len(tmpltVertices)): newprop.append(coly) # add first color to second half of cyl vertices for l in range(len(tmpltVertices)): newprop.append(colx) cylGeom.materials[GL.GL_FRONT].prop[1] = newprop # and finally... #print "Cylinders.asIndexedPolygons out", quality return cylGeom class CylinderArrows(Cylinders): """Class for sets of 3D arrows draw using cylinders""" keywords = Cylinders.keywords + [ 'headLength', 'headRadius', ] def __init__(self, name=None, check=1, **kw): if __debug__: if check: apply( checkKeywords, (name,self.keywords), kw) apply( Cylinders.__init__, (self, name, 0), kw) self.headLength = 1. self.headRadius = 2. def Draw(self): # for some reason, under Mac OS X, if I do not always set he material # only the first cylinder gets the right color (MS) if sys.platform=='darwin' \ or DejaVu.preventIntelBug_BlackTriangles is True: self.checkMat = False else: self.checkMat = True if len(self.vertexSet.vertices) == 0: return if self.inheritMaterial: fp = None bp = None face = None else: mat = self.materials[GL.GL_FRONT] rmat = self.realFMat bind = [10,10,10,10] for pInd in range(4): bind[pInd], rmat.prop[pInd] = mat.GetProperty(pInd) rmat.prop[4] = mat.prop[4] rmat.prop[5] = mat.prop[5] rmat.binding[:4] = bind rmat.binding[4:] = rmat.binding[4:] fp = rmat # fp = self.materials[GL.GL_FRONT] if fp: if self.frontAndBack: face = GL.GL_FRONT_AND_BACK bp = None else: face = GL.GL_FRONT mat = self.materials[GL.GL_BACK] rmat = self.realBMat bind = [10,10,10,10] for pInd in range(4): bind[pInd], rmat.prop[pInd]=mat.GetProperty(pInd) rmat.prop[4] = mat.prop[4] rmat.prop[5] = mat.prop[5] rmat.binding[:4] = bind rmat.binding[4:] = rmat.binding[4:] bp = rmat c = self.vertexSet.vertices.array if self.oneRadius == viewerConst.NO: radii = self.vertexSet.radii.array else: radius = self.vertexSet.radii.array[0] pickName = 0 for i in xrange(len(self.faceSet.faces.array)): #print 'CYLINDERS', i, '********************************' for j in xrange(len(self.faceSet.faces.array[i])-1): vi1 = self.faceSet.faces.array[i][j] vi2 = self.faceSet.faces.array[i][j+1] if fp: fpp1 = [None,None,None,None,None] fpp2 = [None,None,None,None,None] for m in (0,1,2,3,4): if fp.binding[m] == viewerConst.PER_VERTEX: fpp1[m] = fp.prop[m][vi2] fpp1[m] = array(fpp1[m],copy=1) fpp2[m] = fp.prop[m][vi1] fpp2[m] = array(fpp2[m],copy=1) elif fp.binding[m] == viewerConst.PER_PART: fpp2[m] = fpp1[m] = fp.prop[m][i] fpp1[m] = array(fpp1[m],copy=1) fpp2[m] = array(fpp2[m],copy=1) else: fpp1 = fpp2 = None if bp and not self.frontAndBack: bpp1 = [None,None,None,None,None] bpp2 = [None,None,None,None,None] for m in (0,1,2,3,4): if bp.binding[m] == viewerConst.PER_VERTEX: bpp1[m] = bp.prop[m][vi2] bpp1[m] = array(bpp1[m],copy=1) bpp2[m] = bp.prop[m][vi1] bpp2[m] = array(bpp2[m],copy=1) elif bp.binding[m] == viewerConst.PER_PART: bpp2[m] = bpp1[m] = bp.prop[m][i] bpp1[m] = array(bpp1[m],copy=1) bpp2[m] = array(bpp2[m],copy=1) else: bpp1 = bpp2 = None GL.glPushName(pickName) # compute point at base of cone vect = [c[vi2][0]-c[vi1][0], c[vi2][1]-c[vi1][1], c[vi2][2]-c[vi1][2]] norm = 1./math.sqrt(vect[0]*vect[0]+vect[1]*vect[1]+vect[2]*vect[2]) vect = [vect[0]*norm, vect[1]*norm, vect[2]*norm] headBase = [c[vi2][0]-self.headLength*vect[0], c[vi2][1]-self.headLength*vect[1], c[vi2][2]-self.headLength*vect[2]] if self.oneRadius: # cylinder self.cyldraw(c[vi1], headBase, radius, radius, fpp1, bpp1, fpp2, bpp2, face) # cone self.cyldraw(headBase, c[vi2], 0.0, radius*self.headRadius, fpp1, bpp1, fpp2, bpp2, face) else: if vi1 < vi2: self.cyldraw(c[vi1], c[vi2], radii[vi2], radii[vi1], fpp1, bpp1, fpp2, bpp2, face) else: self.cyldraw(c[vi1], c[vi2], radii[vi1], radii[vi2], fpp1, bpp1, fpp2, bpp2, face) GL.glPopName() pickName = pickName +1 #print 'CYLINDERS done' return 1 mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Materials.py0000644000175000017500000003316012024714164022164 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Materials.py,v 1.35 2012/09/14 20:49:56 sanner Exp $ # # $Id: Materials.py,v 1.35 2012/09/14 20:49:56 sanner Exp $ # import types from numpy.oldnumeric import array, ones, concatenate, minimum, maximum from opengltk.OpenGL import GL from DejaVu import materialsDef from DejaVu import viewerConst from DejaVu.viewerFns import checkKeywords, getkw propertyNum = { 'ambient':0, 'AMBIENT':0, 'ambi':0, 'AMBI':0, 'diffuse':1, 'DIFFUSE':1, 'diff':1, 'DIFF':1, 'emission':2, 'EMISSION':2, 'emis':2, 'EMIS':2, 'specular':3, 'SPECULAR':3, 'spec':3, 'SPEC':3, 'shininess':4, 'SHININESS':4, 'shini':4, 'SHINI':4, 'opacity':5, 'OPACITY':5, 'opac':5, 'OPAC':5, } class Materials: """Class for material and color properties of an object We have a Numeric array of RGBA values for the ambient, diffuse, emissive, andspecular component (in this order) and a list of values for shininess and opcaity. The list of opcaities will be placed as the 4th column in the diffuse component at rendering time. The constructor can be called either with no argument to get a default material, or with a property Name specifying a material table and an index into this table (i.e. tropical, 0).""" keywords = [ 'ambient', 'diffuse', 'emission', 'specular', 'shininess', 'opacity', 'binding', ] ambient = AMBIENT = ambi = AMBI = 0 diffuse = DIFFUSE = diff = DIFF = 1 emission = EMISSION = emis = EMIS = 2 specular = SPECUILAR = spec = SPEC = 3 shininess = SHININESS = shini = SHINI = 4 opacity = OPACITY = opac = OPAC = 5 def InitDefault(self): self.prop[self.ambi] = array( (( 0.1, 0.1, 0.1, 1.0 ), ), 'f' ) self.prop[self.diff] = array( (( 1.0, 1.0, 1.0, 1.0 ), ), 'f' ) self.prop[self.emis] = array( (( 0.0, 0.0, 0.0, 1.0 ), ), 'f' ) self.prop[self.spec] = array( (( 0.4, 0.4, 0.4, 1.0 ), ), 'f' ) self.prop[self.shini] = array( ( 75.0, ), 'f' ) self.prop[self.opac] = array( ( 1.0, ), 'f' ) self._modified = False def __init__(self, propName=None, propInd=None): """prop can be a string fro the properties library""" if propName is not None and propInd is not None: prop = getattr(materialsDef, propName)[propInd] self.prop = [0,0,0,0,0,0] for i in (0,1,2,3,4): self.prop[i] = array( prop[i], 'f' ) self.prop[5] = array( self.prop[1][:,3] ) else: self.prop = range(6) self.InitDefault() self.binding = [ viewerConst.OVERALL,]*6 # any of the AMBIENT, DIFFUSE, EMISSION, and SPECULAR property # can be obtained from another one of these properties by multiplying # the source property by a scaling factor going from ]0,1]. # self.getFrom is used by the GetProperty(). This list contains # for each property either None or a 2-tuple where the first entry # is the source property (string or int) and the second entry is a # scaling factor. # If the value is None, the requested property is obtained from its # own array of values (.prop[property]) # Else, it is obtained by multiplying the source propertys array # of values of the by the scaling factor. # for example, by default the ambient component is obtained by # multiplying the diffuse component by 0.2 the diffuse component. from DejaVu import preventIntelBug_WhiteTriangles if preventIntelBug_WhiteTriangles: self.getFrom = [ None, None, None, None,] else: # This line was causing diffuse to always be 60% of diffuse hence # preventing white color #self.getFrom = [ [self.diffuse, .6], [self.diffuse, .6], None, None,] self.getFrom = [ [self.diffuse, .6], None, None, None,] def GetProperty(self, prop): """return a given property and its binding while respecting the self.getFrom attribute. This is called by RedoDisplayList. prop can be a string, an integer, or an RGB tuple """ if type(prop) is types.StringType: prop = propertyNum[prop] assert prop < 4 if self.getFrom[prop] is None: return self.binding[prop], self.prop[prop] else: sourceProp, sca = self.getFrom[prop] if sourceProp is not None: if type(sourceProp) is types.StringType: origProp = self.prop[propertyNum[sourceProp]] else: origProp = self.prop[sourceProp] if type(sourceProp) is types.StringType: sourceProp = propertyNum[sourceProp] return self.binding[sourceProp], p elif type(sourceProp) is types.IntType: p = (self.prop[sourceProp]*sca).astype('f') if sourceProp==1: p[:,3] = origProp[:,3] # restore opacity try: if len(p)==len(self.prop[sourceProp]): return self.binding[sourceProp], p else: return 11, p except TypeError: return 10, p elif len(sourceProp) == 4: # single RGBA tuple try: # duplicate RGB to match length of sca vector sca = array(sca) sca.shape = (-1,1) p = array( ((sourceProp),)*len(sca) )*(sca) p[:, 3] = 1 return 11, p.astype('f') except TypeError: # sca is not a vector p = array( self.prop[sourceProp])*sca return 10, p.astype('f') else: sourceProp = array((1., 1., 0.), 'f') p = (self.prop[sourceProp]*sca).astype('f') return self.binding[sourceProp], p def fixOpacity(self): """This function should be called after all properties of a material have been updated. It will create the alpha chanel of the diffuse component from the opacity property. It will return 1 if there are alpha values < 1.0 or 0 else""" #print "fixOpacity" difflen = self.prop[self.diff].shape[0] opaclen = self.prop[self.opac].shape[0] if self.binding[self.opac] == viewerConst.PER_VERTEX and difflen == 1 and opaclen >1: # PER_VERTEX bindig && one color ( len(diffuse) == 1) && len(opacity vector) > 1: # create diffuse vector which length is equal to len(opacity). Set the alpha # chanel of this vector to the values from the opacity vector. opac = self.prop[self.opac] diff = ones( (opaclen,4), 'f') diff[:,:3] = self.prop[self.diff][0][:3] diff[:,3] = opac self.prop[self.diff] = diff elif self.binding[self.opac] == viewerConst.OVERALL or \ difflen!=opaclen: # OVERALL binding OR different length of diffuse and opacity vectors: # set the alpha channel of the diffuse component to the first value of # the opacity vector diff = self.prop[self.diff] opac = self.prop[self.opac][0] alpha = ones( (diff.shape[0]) )*float(opac) diff[:,3] = alpha.astype('f') else: self.prop[self.diff][:,3] = self.prop[self.opac][:] # raise ValueError("diffuse/opacity property shape mismatch") alphaMin = minimum.reduce( self.prop[self.opac] ) if alphaMin < 1.0: return 1 else: return 0 ## elif opaclen==1: # duplicate opac[0] ## ar = ones( (difflen,), 'f')*self.prop[self.opac][0] ## self.prop[self.diff][:,3] = ar.astype('f') ## elif difflen==1: # we have 1 rgb for diffuse but many opacities ## # so we duplicate diffuse[rgb][0] ## ar = ones( (opaclen,4), 'f') ## ar[:,3] = ar[:,3] * self.prop[self.diff][:,3] ## ar[:, 3] = self.prop[self.opac][:] ## self.prop[self.diff] = ar ## self.binding[self.diff] = viewerConst.PER_VERTEX ## else: ## if self.prop[self.diff].shape[1]==4: ## self.prop[self.opac] = self.prop[self.diff][:,3] ## else: ## self.prop[self.opac] = ones( (1,), 'f') ## self.binding[self.opac] = viewerConst.OVERALL ## #raise ValueError("diffuse/opacity property shape mismatch") ## alphaMin = minimum.reduce( self.prop[self.opac] ) ## if alphaMin < 1.0: return 1 ## else: return 0 def AddMaterial(self, values, prop=1): """Add materials to the current set""" assert prop in (0,1,2,3,4,5) values = array( values, 'f' ) if prop < self.shini: if values.shape[1] == 3: alpha = ones( (values.shape[0], 1), 'f' ) values = concatenate( (values, alpha), 1 ) self.prop[prop] = concatenate( (self.prop[prop], values) ) def SetMaterial(self, values, prop=1, tagModified=True): """Set the materials WARNING: when back face colors are set, two sided lighting has to be enabled we set RGB values for all properties except for shininess and opacity If an alpha value are specified they will be ignored Since IndexedGeomDSPL requires alpha values for all properties we set them automatically to 1.0 for all properties except for diffuse. The alpha channel of the diffuse component will be set later in fixOpacity which should be called after all properties of the material have been updated. """ if tagModified: self._modified = True if prop is None: prop = self.diff elif type(prop) is types.StringType: prop = getattr(self, prop) assert prop in (0,1,2,3,4,5) values = array( values, 'f' ) if prop < self.shini: assert len(values.shape)==2 and values.shape[1] in [3,4] alpha = ones( (values.shape[0], 1), 'f' ) values = concatenate( (values[:,:3], alpha), 1 ) else: if len(values.shape) != 1: values = array([values], 'f' ) self.prop[prop] = values def Set(self, check=1, **kw): tagModified = True val = getkw(kw, 'tagModified') if val is not None: tagModified = val assert tagModified in [True, False] self._modified = tagModified if __debug__: if check: apply( checkKeywords, ('Material',self.keywords), kw) val = getkw(kw, 'ambient') if not val is None: val = array(val).astype('f') self.prop[propertyNum['ambi']] = val val = getkw(kw, 'diffuse') if not val is None: val = array(val).astype('f') self.prop[propertyNum['diff']] = val val = getkw(kw, 'emission') if not val is None: val = array(val).astype('f') self.prop[propertyNum['emis']] = val val = getkw(kw, 'specular') if not val is None: val = array(val).astype('f') self.prop[propertyNum['spec']] = val val = getkw(kw, 'shininess') if not val is None: val = array(val).astype('f') self.prop[propertyNum['shini']] = val val = getkw(kw, 'opacity') if not val is None: val = array(val).astype('f') self.prop[propertyNum['opac']] = val val = getkw(kw, 'binding') if not val is None: val = array(val).astype('f') self.binding[:] = val[:] def getState(self, includeBinding=True): """return a dictionary describing this object's state This dictionary can be passed to the Set method to restore the object's state """ if includeBinding: return { 'ambient':self.prop[propertyNum['ambi']].tolist(), 'diffuse':self.prop[propertyNum['diff']].tolist(), 'emission':self.prop[propertyNum['emis']].tolist(), 'specular':self.prop[propertyNum['spec']].tolist(), 'shininess':self.prop[propertyNum['shini']].tolist(), 'opacity':self.prop[propertyNum['opac']].tolist(), 'binding': self.binding } else: lDict = {'binding': self.binding} if (self.binding[0] != viewerConst.PER_VERTEX) \ and (self.binding[0] != viewerConst.PER_PART): lDict['ambient'] = self.prop[propertyNum['ambi']].tolist() if (self.binding[1] != viewerConst.PER_VERTEX) \ and (self.binding[1] != viewerConst.PER_PART): lDict['diffuse'] = self.prop[propertyNum['diff']].tolist() lDict['opacity'] = self.prop[propertyNum['opac']].tolist() if (self.binding[2] != viewerConst.PER_VERTEX) \ and (self.binding[2] != viewerConst.PER_PART): lDict['emission'] = self.prop[propertyNum['emis']].tolist() if (self.binding[3] != viewerConst.PER_VERTEX) \ and (self.binding[3] != viewerConst.PER_PART): lDict['specular'] = self.prop[propertyNum['spec']].tolist() if (self.binding[4] != viewerConst.PER_VERTEX) \ and (self.binding[4] != viewerConst.PER_PART): lDict['shininess'] = self.prop[propertyNum['shini']].tolist() return lDict mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/capGeom.py0000644000175000017500000002705711354755047021640 0ustar debiandebianfrom time import time from mglutil.math.rotax import rotax, rotVectToVect import numpy def vdiff(p1, p2): # returns p1 - p2 x1,y1,z1 = p1 x2,y2,z2 = p2 return (x1-x2, y1-y2, z1-z2) from math import sqrt def vnorm(v1): x1,y1,z1 = v1 n = 1./sqrt(x1*x1 + y1*y1 + z1*z1) return (x1*n, y1*n, z1*n) def vlen(v1): x1,y1,z1 = v1 return sqrt(x1*x1 + y1*y1 + z1*z1) def dot(v1,v2): x1,y1,z1 = v1 x2,y2,z2 = v2 return (x1*x2) + (y1*y2) + (z1*z2) def lengthOfProjectedVects(v1, v2): """ return the length of the v1 projected onto v2 """ # v1.v2 = |v1|*|v2|*cos(angle) # |v1|*cos(angle) = (v1.v2) / |v2| x1,y1,z1 = v1 x2,y2,z2 = v2 nv2 = sqrt(x2*x2 + y2*y2 + z2*z2) s = ( (x1*x2) + (y1*y2) + (z1*z2) ) / nv2 vpx, vpy, vpz = s*x2, s*y2,s*z2 return sqrt(( vpx*vpx + vpy*vpy + vpz*vpz)) def area2(a,b,c): """ return 2 * area of triangle abc """ return (a[0]-c[0])*(b[1]-c[1]) - (a[1]-c[1])*(b[0]-c[0]) def insideTriangle(a, b, c, p): """ returns True if P lies within triangle A,B,C ABC is counterclockwise """ return area2(a,b,p)>=0 and area2(b,c,p)>=0 and area2(c,a,p)>=0 def triangulate(verts): tri = [] vertsInd = range(len(verts)) while len(vertsInd) > 2: triFound = False count = 0 while not triFound and count < len(vertsInd): count += 1 a, b, c = vertsInd[:3] ca = verts[a] cb = verts[b] cc = verts[c] if area2(ca, cb, cc) >= 0: for p in vertsInd[3:]: cp = verts[p] if insideTriangle(ca,cb,cc,cp): break else: tri.append( (a,c,b) ) vertsInd.remove(b) triFound = True vertsInd.append(vertsInd.pop(0)) if count == len(vertsInd): print "ERROR Not a simple polygon" return [] return tri from math import acos, pi def angleBetweenNormVecsRad(v1, v2): """return the angle between vetors v1 and v2. NOTE v1 and v2 have to be normalized""" # v1.v2 = |v1|*|v2|*cos(angle) # angle = acos( v1.v2 / |v1|*|v2|) x1,y1,z1 = v1 x2,y2,z2 = v2 return acos( (x1*x2) + (y1*y2) + (z1*z2) ) def angleBetweenVecsDeg(v1, v2): """ return the angle between vetors v1 and v2. """ # v1.v2 = |v1|*|v2|*cos(angle) # angle = acos( v1.v2 / |v1|*|v2|) x1,y1,z1 = v1 x2,y2,z2 = v2 n1 = vlen(v1) n2 = vlen(v2) arad = acos( (( x1*x2 ) + (y1*y2) + (z1*z2)) / (n1*n2) ) return 180 * arad /pi def ccw(poly): n = len(poly) k = poly.index(min(poly)) return area2(poly[k-1], poly[k], poly[(k+1)%n]) > 0 def capMesh(vertices, edges, faces, faceEdges, pp, pno, minDist=0.01): """ Finds the section mesh between a mesh and a plane vertices: mesh vertices edges: mesh edges as (v1,v2) faces: mesh faces faceEdges: pp: Vector - A point on the plane pno: Vector - The cutting plane's normal (normalized) minDist: useds to remove points to close in contour Returns: Mesh - the resulting mesh of the section if any or Boolean - False if no section exists """ from math import pi halfPi = pi*.5 ## ppx, ppy, ppz = pp ## pnox, pnoy, pnoz = pno ## t1 = time() ## vertsold = [] ## ed_xsect = {} ## pr1 = [] ## pr2 = [] ## ang1 = [] ## ang2 = [] ## for ednum, ed in enumerate(edges): ## # getting a vector from each edge vertices to a point on the plane ## v1 = vertices[ed[0]] ## co1 = vdiff( v1, pp) ## v2 = vertices[ed[1]] ## co2 = vdiff( v2, pp) ## # projecting them on the normal vector ## #proj1 = lengthOfProjectedVects(co1, pno) ## x1,y1,z1 = co1 ## x2,y2,z2 = pno ## s = ( (x1*x2) + (y1*y2) + (z1*z2) ) ## vpx, vpy, vpz = s*x2, s*y2,s*z2 ## proj1 = sqrt( (vpx*vpx + vpy*vpy + vpz*vpz) ) ## pr1.append(proj1) ## #proj2 = lengthOfProjectedVects(co2, pno) ## x1,y1,z1 = co2 ## s = ( (x1*x2) + (y1*y2) + (z1*z2) ) ## vpx, vpy, vpz = s*x2, s*y2,s*z2 ## proj2 = sqrt( (vpx*vpx + vpy*vpy + vpz*vpz) ) ## pr2.append(proj2) ## if (proj1 != 0): ## angle1 = angleBetweenVecsDeg(co1, pno) ## else: ## print '0 eangle1', ed ## angle1 = 0 ## if (proj2 != 0): ## angle2 = angleBetweenVecsDeg(co2, pno) ## else: ## angle2 = 0 ## print '0 eangle2', ed ## ang1.append(angle1) ## ang2.append(angle2) ## #Check to see if edge intersects. Also check if edge is coplanar to the ## #cutting plane (proj1=proj2=0) ## if ((proj1 == 0) or (proj2 == 0) or \ ## (angle1 > 90) != (angle2 > 90)) and \ ## (proj1+proj2 > 0) : ## #edge intersects. ## proj1 /= proj1+proj2 ## cox = (v2[0]-v1[0])*proj1 + v1[0] ## coy = (v2[1]-v1[1])*proj1 + v1[1] ## coz = (v2[2]-v1[2])*proj1 + v1[2] ## vertsold.append( (cox,coy,coz) ) ## #store a mapping between the new vertices and the mesh's edges ## ed_xsect[ednum] = len(ed_xsect) ## print ' time to compute contour', time()-t1, len(vertsold) t1 = time() edges = numpy.array(edges) nv1 = numpy.take(vertices, edges[:,0], axis=0) nv2 = numpy.take(vertices, edges[:,1], axis=0) nco1 = nv1-pp ns = numpy.sum( nco1*pno, 1 ) ns.shape = -1,1 nvp = pno*ns nproj1 = numpy.sqrt(numpy.sum( nvp*nvp, 1 )) nco2 = nv2-pp ns = numpy.sum( nco2*pno, 1 ) ns.shape = -1,1 nvp = pno*ns nproj2 = numpy.sqrt(numpy.sum( nvp*nvp, 1 )) lpno = vlen(pno) nlco1 = numpy.sqrt( numpy.sum( nv1*nv1, 1 ) ) denom = nlco1*lpno # what id denom is 0. i.e proj=0 arad1 = numpy.arccos( numpy.sum( nco1*pno, 1) / denom )# * 180 / pi nlco2 = numpy.sqrt( numpy.sum( nv2*nv2, 1 ) ) denom = nlco2*lpno # what id denom is 0. i.e proj=0 arad2 = numpy.arccos( numpy.sum( nco2*pno, 1) / denom )# * 180 / pi verts = [] contourVerts = {} for i in xrange(len(edges)): proj1 = nproj1[i] proj2 = nproj2[i] if ((proj1 == 0) or (proj2 == 0) or \ (arad1[i] > halfPi) != (arad2[i] > halfPi)) and \ (proj1+proj2 > 0) : #edge intersects. proj1 /= proj1+proj2 v1i, v2i = edges[i] v1 = vertices[v1i] v2 = vertices[v2i] cox = (v2[0]-v1[0])*proj1 + v1[0] coy = (v2[1]-v1[1])*proj1 + v1[1] coz = (v2[2]-v1[2])*proj1 + v1[2] verts.append( (cox,coy,coz) ) #store a mapping between the new vertices and the mesh's edges contourVerts[i] = len(contourVerts) print ' time to compute contour1', time()-t1, len(verts) if len(verts)==0: return [], [] # build list of edges in contour t1 = time() edgesS = [] vertToEdges = {} # used to find the 2 edges a vertex belong to nbe = 0 for fe in faceEdges: ps = [ contourVerts[key] for key in fe if key in contourVerts] if len(ps) == 2: v1,v2 = ps if v1 in vertToEdges: vertToEdges[v1].append(nbe) else: vertToEdges[v1] = [nbe] if v2 in vertToEdges: vertToEdges[v2].append(nbe) else: vertToEdges[v2] = [nbe] edgesS.append(tuple(ps)) nbe += 1 print ' time to compute edge list', time()-t1 # compute rotation matrix to cut plane into a Z plane rotMat = numpy.array( rotVectToVect(pno, (0,0,1)), 'f') vertsR = numpy.dot( verts, rotMat[:3, :3] ).tolist() # order vertices along contour t0 = time() edgeList = range(0,len(edgesS)) allFaces = [] allVertices = [] while len(edgeList): t1 = time() curE = edgeList[0] fstV, curV = edgesS[edgeList[0]] ovi = [fstV] ov = [vertsR[fstV]] ovnr = [verts[fstV]] edgeList.remove(curE) while curV != fstV: ovi.append(curV) ov.append(vertsR[curV]) ovnr.append(verts[curV]) length = 0 while length < minDist: nextEdge = vertToEdges[curV][0] if nextEdge==curE: nextEdge = vertToEdges[curV][1] curE = nextEdge edgeList.remove(curE) v2 = edgesS[curE][0] if v2==curV: v2=edgesS[curE][1] length = vlen(vdiff(vertsR[ovi[-1]], vertsR[v2])) curV = v2 if curV == fstV: break # make sure vertice are counter clockwise if not ccw(ov): print "reversing" ov.reverse() ovnr.reverse() print ' time to order pacth vertices', time()-t1 #print 'contour length', len(ovi), len(ov) # apply rotation to vertices #ovr = numpy.dot( ov, rotMat[:3, :3] ).tolist() #for v in ovr: # print v[2], #print #print ovi # triangulate t1 = time() facesS = triangulate(ov) print ' time to triangulate patch', time()-t1 allFaces.append(facesS) allVertices.append(ovnr) print ' time to triangulate all', time()-t0 return allVertices, allFaces if __name__ == '__main__': from DejaVu.IndexedPolygons import IndexedPolygonsFromFile geomS = IndexedPolygonsFromFile('cv', 'mesh') faces = geomS.getFaces() vertices = geomS.getVertices() vnormals = geomS.getVNormals() planePoint = (3.,0.,0.) planeNormal = (1.,0.,0.) vertsC, facesC = cap(vertices, faces, planePoint, planeNormal) from DejaVu import Viewer vi = Viewer() from DejaVu.IndexedPolygons import IndexedPolygons tet = IndexedPolygons('surfaceMesh', vertices=vertices, faces=faces, vnormals=vnormals, inheritFrontPolyMode=False, frontPolyMode='line', inheritCulling=0, culling='none', inheritShading=0, shading='flat', visible=0) vi.AddObject(tet) #from DejaVu.Spheres import Spheres #sectionVsph = Spheres('sectionV', vertices=vertsS, radii=(0.02,)) #vi.AddObject(sectionVsph) #from DejaVu.Points import Points #sectionVpts = Points('sectionV', vertices=allvertsS) #sectionVpts = Points('sectionV', vertices=[vertsS[14], vertsS[159], vertsS[158]]) #vi.AddObject(sectionVpts) #from DejaVu.IndexedPolylines import IndexedPolylines #line = IndexedPolylines( # 'sectionL', vertices=allvertsS, faces=edgesS, # inheritLinewidth=False, Linewidth=3, # inheritMaterial=False, materials=( (0,1,0), )) #vi.AddObject(line) #from DejaVu.Polylines import Polylines #line = Polylines( # 'contour', vertices=(vertsS[:5],), # inheritLinewidth=False, Linewidth=3, # inheritMaterial=False, materials=( (1,1,0), )) #vi.AddObject(line) i = 0 for v, f in zip(vertsC, facesC): cap = IndexedPolygons('cap%d'%i, vertices=v, faces=f, inheritFrontPolyMode=False, frontPolyMode='fill', inheritCulling=0, culling='none', inheritShading=0, shading='flat') vi.AddObject(cap) i += 1 mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Shapes.py0000644000175000017500000002342210651433501021463 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Sophie COON, Kevin CHAN, Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/Shapes.py,v 1.15 2007/07/24 17:30:41 vareille Exp $ # # $Id: Shapes.py,v 1.15 2007/07/24 17:30:41 vareille Exp $ # import numpy.oldnumeric as Numeric, math from opengltk.OpenGL import GL """ This module implements a set of Classes to describe 2D shape that can be used to perform an extrusion along a 3D path. """ class Shape2D: """ Shape2D is a base class describing a 2D shape. """ def __init__(self, contpts, contnorm, vertDup=0, firstDup=0): """ contpts : list of 3D coordinates of the control points describing the shape2D. contnorm : list of 3D vector specifying the normals at each vertex of the shape2D. vertDup : Flag specifying whether or not to duplicate each vertex and normal. firstDup : Flag specifying whether or not to duplicate the first first vertex. """ self.vertDup = vertDup self.firstDup = firstDup self.contpts = list(contpts) self.contnorm = list(contnorm) if vertDup: firstDupInd = 2 else: firstDupInd = 1 if firstDup: cont = self.contpts newcont = cont + cont[:firstDupInd] self.contpts = Numeric.array(newcont) contn = self.contnorm newcontn = contn + contn[:firstDupInd] self.contnorm = Numeric.array(newcontn) self.lenShape = len(self.contpts) def returnStringRepr(self): """ This method returns the string to be evaluated to create the object""" cname = self.__class__.__name__ before = 'from %s import %s'%(self.__module__, cname) st = "%s(%s,%s, vertDup=%s, firstDup=%s)"%(cname, self.contpts, self.contnorm, self.vertDup, self.firstDup) return before, st class Triangle2D(Shape2D): """ Class derived from Shape2D describing a Triangle.""" def __init__(self, side = 1.0, vertDup=0, firstDup = 0 ): self.side = side x = side/2 y1 = -side/(2*math.sqrt(3)) y2 = side/math.sqrt(3) if not vertDup: pts = ( (-x, y1, 1), (0, y2, 1), (x, y1, 1) ) norms = ((-math.sqrt(3)/2, -.5, 0), (0, 1, 0), (math.sqrt(3)/2, -.5, 0), ) else: pts = ( (-x, y1 , 1) , (-x, y1, 1), ( 0, y2 , 1) , ( 0, y2, 1), ( x, y1 , 1) , ( x, y1, 1) ) norms = ( (0, -2*x, 0), ( y1-y2, x , 0), ( y1-y2, x , 0),( y2-y1, x , 0), ( y2-y1, x , 0),(0, -2*x, 0),) Shape2D.__init__(self, pts, norms, vertDup=vertDup, firstDup=firstDup) def returnStringRepr(self): """ This method returns the string to be evaluated to create the object""" cname = self.__class__.__name__ before = 'from %s import %s'%(self.__module__, cname) st = "%s(side=%s, vertDup=%s, firstDup=%s)"%(cname, self.side, self.vertDup, self.firstDup) return before, st class Ellipse2D(Shape2D): """ Class derived from Shape2D describing a Ellipse """ def __init__(self, demiGrandAxis , demiSmallAxis, quality=12, vertDup=0, firstDup=0): """demiGrandAxis is 1/2 the width of the ellipse demiSmallAxis is 1/2 the height of the ellipse""" self.quality = quality self.demiGrandAxis = demiGrandAxis self.demiSmallAxis = demiSmallAxis circle = Numeric.zeros( (quality,3) ).astype('f') circleNormal = Numeric.zeros( (quality,3) ).astype('f') # when points are duplicated: # norm0 = (x(i-1)-xi,y(i-1)-y, z(i-1)-z(i)) cross (0,0,1) # norm1 = (0, 0, 1) cross (x(i+1)-xi,y(i+1)-y, z(i+1)-z(i)) # x = y1*z2 - y2*z2 # y = z1*x2 - z2*x1 # z = x1*y2 - x2*y1 for i in range( quality ): circle[i][0] = 2*demiGrandAxis*math.cos( i*2*math.pi/quality) circle[i][1] = -2*demiSmallAxis*math.sin( i*2*math.pi/quality) circle[i][2] = 1 circleNormal[i][0] = math.cos( i*2*math.pi/quality ) circleNormal[i][1] = -math.sin( i*2*math.pi/quality ) circleNormal[i][2] = 0 if vertDup: pts = Numeric.zeros( (quality*2, 3)) .astype('f') norm = Numeric.zeros( (quality*2, 3)) .astype('f') # index for pts and norm ptsInd = 0 for ind in range(quality): if ind == 0: prev = quality-1 next = ind+1 elif ind == quality-1: next = 0 prev = ind-1 else: next = ind + 1 prev = ind - 1 # Compute the Vprev vector and the Vnext vector Vprev = circle[prev]-circle[ind] Vnext = circle[next]-circle[ind] n0 = [ Vprev[1], -Vprev[0], 0 ] n1 = [-Vnext[1], Vnext[0], 0 ] norm[ptsInd], norm[ptsInd+1] = n0, n1 pts[ptsInd], pts[ptsInd+1] = circle[ind], circle[ind] ptsInd = ptsInd + 2 circle = pts circleNormal = norm Shape2D.__init__(self, circle, circleNormal, vertDup=vertDup, firstDup=firstDup) def returnStringRepr(self): """ This method returns the string to be evaluated to create the object""" cname = self.__class__.__name__ before = 'from %s import %s'%(self.__module__, cname) st = "%s(%s, %s, quality=%s, vertDup=%s, firstDup=%s)"%(cname, self.demiGrandAxis, self.demiSmallAxis, self.quality, self.vertDup, self.firstDup) return before, st class Circle2D(Ellipse2D): """ Class derived from Ellipse2D describing a Circle.""" def __init__(self, radius, quality=12, vertDup=0, firstDup=0): self.radius = radius Ellipse2D.__init__(self, radius, radius, quality=quality, firstDup=firstDup, vertDup=vertDup) def returnStringRepr(self): """ This method returns the string to be evaluated to create the object""" cname = self.__class__.__name__ before = 'from %s import %s'%(self.__module__, cname) st = "%s(%s, quality=%s, vertDup=%s, firstDup=%s)"%(cname, self.radius, self.quality, self.vertDup, self.firstDup) return before, st class Rectangle2D(Shape2D): """ Class derived from Shape2D describing a Rectangle """ def __init__(self, width, height, vertDup=0, firstDup=0): self.width = width self.height = height if not vertDup: pts = ( (-width, -height, 1), (-width, height, 1), (width, height, 1), (width, -height, 1) ) norms = ( (-1,-1,0), (-1,1,0), (1,1,0), (1,-1,0) ) else: pts = ( (-width, -height, 1), (-width, -height, 1), (-width, height, 1), (-width, height, 1), (width, height, 1), (width, height, 1), (width, -height, 1), (width, -height, 1) ) norms = ( (0,-1,0), (-1,0,0), (-1,0,0), (0,1,0), (0,1,0), (1,0,0), (1,0,0), (0,-1,0) ) Shape2D.__init__(self, pts, norms, vertDup=vertDup, firstDup=firstDup) def returnStringRepr(self): """ This method returns the string to be evaluated to create the object""" before = 'from %s import %s'%(self.__module__, self.__class__.__name__) st = "%s(%s, %s, vertDup=%s, firstDup=%s)"%(self.__class__.__name__, self.width, self.height, self.vertDup,self.firstDup) return before, st class Square2D(Rectangle2D): """ Class derived from Shape2D describing a Square """ def __init__(self, side, vertDup=0, firstDup=0): self.side = side Rectangle2D.__init__(self, side, side, vertDup=vertDup, firstDup=firstDup) def returnStringRepr(self): """ This method returns the string to be evaluated to create the object""" before = 'from %s import %s'%(self.__module__, self.__class__.__name__) st = "%s(%s, vertDup=%s, firstDup=%s)"%(self.__class__.__name__, self.side, self.vertDup, self.firstDup) return before, st mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/bitPatterns.py0000644000175000017500000001575510651433502022552 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/bitPatterns.py,v 1.4 2007/07/24 17:30:42 vareille Exp $ # # $Id: bitPatterns.py,v 1.4 2007/07/24 17:30:42 vareille Exp $ # import numpy.oldnumeric as Numeric #finest grain 50% solid: pat1 = Numeric.array(( 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55 ), 'B' ) pat2 = Numeric.array(( 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55, 0xAA, 0xAA, 0xAA, 0xAA ), 'B') #medium grained 25% solid: pat3 = Numeric.array(( 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00), 'B') pat4 = Numeric.array(( 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00), 'B') pat5 = Numeric.array(( 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xAA, 0xAA, 0xAA ),'B') pat6 = Numeric.array(( 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55), 'B') #these is 25% but adjacent pixels colored so looks striped pat7 = Numeric.array(( 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44, 0x88, 0x88, 0x88, 0x88, 0x44, 0x44, 0x44, 0x44), 'B') #12.5% faint staggered stripe pat8 = Numeric.array(( 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x00, 0x44, 0x44, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00), 'B') patternList=[pat1, pat2, pat3, pat4, pat5, pat6, pat7, pat8] mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/ViewerGUI.py0000644000175000017500000040063012100566317022051 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # # Revision: Guillaume Vareille # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/ViewerGUI.py,v 1.241 2013/01/25 20:36:31 sanner Exp $ # # $Id: ViewerGUI.py,v 1.241 2013/01/25 20:36:31 sanner Exp $ # import types, numpy from Tkinter import * import Tkinter import Pmw from opengltk.OpenGL import GL from Slider import Slider from ColorChooser import ColorChooser import string, os import viewerConst import jitter import colorTool import PropertyEditor import numpy.oldnumeric as Numeric from mglutil.util.callback import CallBackFunction from mglutil.util.colorUtil import TkColor from mglutil.gui.BasicWidgets.Tk.fileBrowsers import FileOpenBrowser, \ FileSaveBrowser from mglutil.gui.BasicWidgets.Tk.RelabelingCascadeMenu import RelabelingCascadeMenu import tkMessageBox from mglutil.gui.BasicWidgets.Tk.thumbwheel import ThumbWheel from DejaVu.Transformable import Transformable from DejaVu.IndexedGeom import IndexedGeom from DejaVu.Geom import Geom from DejaVu.SelectionGUI import SelectionGUI import DejaVu from DejaVu.Spheres import Spheres class TwoSlidersGUI(Frame): """Class for a gui with two sliders """ def mouseDown(self, event): # remember where the mouse went down self.draw.itemconfig(CURRENT, fill="red") self.draw.addtag('selected', 'withtag', CURRENT) self.lastx = event.x def mouseUp(self, event): # remember where the mouse went down self.draw.itemconfig("selected", fill="blue") self.draw.dtag("selected") def mouseMove(self, event): # whatever the mouse is over gets tagged as CURRENT for free by tk. t = event.widget.gettags(CURRENT) deltax = event.x - self.lastx if 'near' in t: newx = self.nearx+deltax if newx > self.left-6 and newx < self.farx: self.nearx = self.nearx + deltax self.near = self.cst1 * (self.nearx-self.left) self.draw.move(CURRENT, deltax, 0 ) self.lastx = self.nearx if self.near < self.far: self.viewer.currentCamera.Set(near=self.near) self.viewer.Redraw() elif 'far' in t: newx = self.farx+deltax if newx > self.nearx :#and newx < 191: self.farx = self.farx + deltax self.far = self.cst1 * (self.farx-self.left) self.draw.move(CURRENT, deltax, 0 ) self.lastx = self.farx if self.far > self.near: self.viewer.currentCamera.Set(far=self.far) self.viewer.Redraw() elif 'start' in t: newx = self.startx+deltax if newx > self.left-6 and newx < self.endx: self.startx = self.startx + deltax self.start = self.cst1 * (self.startx-self.left) self.draw.move(CURRENT, deltax, 0 ) self.lastx = self.startx if self.start < self.end: self.viewer.currentCamera.fog.Set(start=self.start) self.viewer.Redraw() elif 'end' in t: newx = self.endx+deltax if newx > self.startx :#and newx < 191: self.endx = self.endx + deltax self.end = self.cst1 * (self.endx-self.left) self.draw.move(CURRENT, deltax, 0 ) self.lastx = self.endx if self.end > self.start: self.viewer.currentCamera.fog.Set(end=self.end) self.viewer.Redraw() def createWidgets(self): self.draw = Canvas(self, width=300, height=30) self.draw.pack(expand=1, fill='x') self.left = 40 self.draw.create_line( 40, 15, 9999, 15, width=2) fnt='-*-helvetica-medium-r-narrow-*-*-120-*-*-*-*-*-*' self.draw.create_text( 16, 7, text='clipZ', font=fnt ) self.draw.create_text( 15, 22, text='Fog', font=fnt) self.nearC = self.draw.create_polygon( 1, 1, 10, 1, 5, 10, 1, 1, fill='blue', tag='near') self.farC = self.draw.create_polygon( 1, 1, 10, 1, 5, 10, 1, 1, fill='blue', tag='far') self.startC = self.draw.create_polygon( 1, 10, 5, 1, 10, 10, 1, 10, fill='blue', tag='start') self.endC = self.draw.create_polygon( 1, 10, 5, 1, 10, 10, 1, 10, fill='blue', tag='end') Widget.bind(self.draw, "<1>", self.mouseDown) Widget.bind(self.draw, "", self.mouseMove) Widget.bind(self.draw, "", self.mouseUp) def ComputeCst(self): self.cst = 155.0 / (self.max-self.min) self.cst1 = 1.0 / self.cst def GetX(self, val): """Compute the slider x offset in pixels for a given value""" return int( (self.left-5) + (val*self.cst) ) def Set(self, near, far, start, end): """Set the cursors """ if not near is None: if hasattr(self, 'nearx'): lPrev = self.nearx lYpos = 0 else: lPrev = 0 lYpos = 5 self.nearx = self.GetX(near) self.near = near self.draw.move( self.nearC, self.nearx - lPrev, lYpos) if not far is None: if hasattr(self, 'farx'): lPrev = self.farx lYpos = 0 else: lPrev = 0 lYpos = 5 self.farx = self.GetX(far) self.far = far self.draw.move( self.farC, self.farx - lPrev, lYpos) if not start is None: if hasattr(self, 'startx'): lPrev = self.startx lYpos = 0 else: lPrev = 0 lYpos = 15 self.startx = self.GetX(start) self.start = start self.draw.move( self.startC, self.startx - lPrev, lYpos) if not end is None: if hasattr(self, 'endx'): lPrev = self.endx lYpos = 0 else: lPrev = 0 lYpos = 15 self.endx = self.GetX(end) self.end = end self.draw.move( self.endC, self.endx - lPrev, lYpos) def __init__(self, viewer, master=None, min=0.0, max=100.0): Frame.__init__(self, master) Pack.config(self, expand=1, fill='x') self.max=max self.min=min self.viewer = viewer self.ComputeCst() self.createWidgets() if self.viewer: c = self.viewer.currentCamera f = self.viewer.currentCamera.fog self.Set(c.near, c.far, f.start, f.end) class ViewerGUI: def __init__(self, viewer, maxLights, maxClip, name='Viewer', nogui=0, master=None): if master is None: master = Toplevel() master.geometry('+80+180') master.title(name) self.root = master f = CallBackFunction(self.dialog) if isinstance(self.root,Toplevel): self.root.protocol('WM_DELETE_WINDOW', f) self.shown = True fnt = '-*-helvetica--r-narrow-*-*-140-*-*-*-*-*-*' self.viewer = viewer #self.addOcclusionCamera() self.top = Frame(self.root) # create menu bar self.mBar = Frame(self.top, relief=RAISED, borderwidth=2) self.mBar.pack(side=TOP, fill=X, expand=0) # FILE # create menu button self.menuFile = Menubutton(self.mBar, text='File', underline=0 ) self.menuFile.pack(side=LEFT, padx="1m") # create pull down menuand add entries self.menuFile.menu = Menu(self.menuFile) # File Browser obj self.openFileBrowser = FileOpenBrowser(#lastDir='.', filetypes=[('all', '*'), ('py', '*.py')], title='Choose File') self.saveFileBrowser = FileSaveBrowser(#lastDir='.', filetypes=[('all', '*'), ('py', '*.py')], title='Choose File') items = ["save Viewer's State", "Save Object's state", "save Viewer and Objects states", "restore state", 'Load Transformation', 'Save Transformation', 'Save Representations', 'Load Representations'] cmds = [self.saveViewerState_cb, self.saveObjectsStates_cb, self.saveViewerAndObjectsStates_cb, self.restoreState, self.loadTransformCurrentGeom, self.saveTransformCurrentGeom, self.saveReprToFile, self.loadReprFromFile] if not nogui: items.append('Exit') cmds.append(self.Exit_cb) for m in range(len(items)): self.menuFile.menu.add_command(label=items[m], underline=0, command = cmds[m] ) # attach pull down menu to button self.menuFile['menu'] = self.menuFile.menu # EDIT # create menu button self.menuEdit = Menubutton(self.mBar, text='Edit', underline=0 ) self.menuEdit.pack(side=LEFT, padx="1m") # create pull down menuand add entries self.menuEdit.menu = Menu(self.menuEdit) items = ('Apply Transformation', ) cmds = (self.applyTransformation_cb, ) for m in range(len(items)): self.menuEdit.menu.add_command(label=items[m], underline=0, command = cmds[m] ) # attach pull down menu to button self.menuEdit['menu'] = self.menuEdit.menu # PREF self.menuPref = Menubutton(self.mBar, text='Preferences', underline=0) self.menuPref.pack(side=LEFT) self.menuPref.menu = Menu(self.menuPref) items = (##'WYSIWIG Color Editor', 'Transf. Root Only', 'Show Picked Vertex', 'Display Value in the Object List', 'Display Quick Keys panel', ) cmds = (##self.Wysiwyg_cb, self.MoveRootOnly_cb, self.showPickedVertex_cb, self.displayValueInObjList_cb, self.showHideQuickKeys_cb, ) ##self.wysiwyg = IntVar() self.moveRootOnly = IntVar() self.showPickedVertex = IntVar() self.displayValueInObjList = IntVar() self.showHideQuickKeysVar = IntVar() vars = (##self.wysiwyg, self.moveRootOnly, self.showPickedVertex, \ self.displayValueInObjList, self.showHideQuickKeysVar, ) for m in range(len(items)): self.menuPref.menu.add_checkbutton(label=items[m], var = vars[m], command = cmds[m], onvalue=viewerConst.YES, offvalue=viewerConst.NO ) self.menuPref.menu.add_command(label='Add Quick Key', command=self.addQuickKey_cb) self.menuPref['menu'] = self.menuPref.menu # HELP self.menuHelp = Menubutton(self.mBar, text='Help', underline=0) self.menuHelp.pack(side=RIGHT) self.menuHelp.menu = Menu(self.menuHelp) self.menuHelp['menu'] = self.menuHelp.menu self.QuickKeysFrame = Tkinter.Toplevel(width=50, height=100) self.QuickKeysFrame.withdraw() self.QuickKeysFrame.title('Quick Keys') #self.QuickKeysFrame.forget() # # Radio button for transformation binding # self.Xform = viewer.Xform import Pmw self.sf = Pmw.ScrolledFrame(self.root,horizflex='expand',vertflex='expand') self.sframe = self.sf.interior() frame1 = Tkinter.Frame(self.sframe) self.XformRadio = Pmw.Group(frame1, tag_text="Mouse transforms:") w = self.XformRadio.interior() lFrameTransformButtons = Frame(w) Radiobutton(lFrameTransformButtons, text="Object", variable=self.Xform, command = self.TObject, value="Object", anchor=W, indicatoron=0, selectcolor="#c67171", activebackground="#28686b").pack(side=LEFT) Radiobutton(lFrameTransformButtons, text="Camera", variable=self.Xform, command = self.TCamera, value="Camera", anchor=W, indicatoron=0, selectcolor="#c67171", activebackground="#28686b").pack(side=LEFT) Radiobutton(lFrameTransformButtons, text="Clip", variable=self.Xform, command = self.TClip, value="Clip", anchor=W, indicatoron=0, selectcolor="#c67171", activebackground="#28686b").pack(side=LEFT) Radiobutton(lFrameTransformButtons, text="Light", variable=self.Xform, command = self.TLight, value="Light", anchor=W, indicatoron=0, selectcolor="#c67171", activebackground="#28686b").pack(side=LEFT) Radiobutton(lFrameTransformButtons, text="Texture", variable=self.Xform, command = self.TMap, value="Texture", anchor=W, indicatoron=0, selectcolor="#c67171", activebackground="#28686b").pack(side=LEFT) Radiobutton(lFrameTransformButtons, text="Scissor", variable=self.Xform, command = self.Scissor, value="Scissor", anchor=W, indicatoron=0, selectcolor="#c67171", activebackground="#28686b").pack(side=LEFT) lFrameTransformButtons.pack(side='top') #set mouse transformInfo lFrameTransformInfo = Frame(w) Label(lFrameTransformInfo, text='left').grid(row=0, column=0, sticky='w') Label(lFrameTransformInfo, text='middle').grid(row=0, column=1, sticky='w') Label(lFrameTransformInfo, text='right').grid(row=0, column=2, sticky='w') Label(lFrameTransformInfo, text=' ').grid(row=0, column=3, sticky='w') Label(lFrameTransformInfo, text='wheel').grid(row=0, column=4, sticky='w') Label(lFrameTransformInfo, text='zoom', relief='sunken', borderwidth=1, anchor='w').grid(row=1, column=4, sticky='w') self.transformInfo = {} for lButtonIndex in (1, 2, 3): self.transformInfo[lButtonIndex] = Tkinter.Label( lFrameTransformInfo, width=10, relief='sunken', borderwidth=1, anchor='w') self.transformInfo[lButtonIndex].grid(row=1, column=lButtonIndex-1, sticky='w') lFrameTransformInfo.pack(side='top') self.fillTransformInfo_cb(self.Xform.get()) #self.bindModifersToTransformInfo(master) for lCamera in self.viewer.cameras: self.bindModifersToTransformInfo(lCamera.master) # root only checkbutton # self.moveRootOnly = IntVar() Checkbutton(w, text='mouse transforms apply to "root" object only', variable=self.moveRootOnly, command=self.MoveRootOnly_cb).pack(side=TOP) ## if DejaVu.enableScenario: ## addScenarioButton = True ## if hasattr(self.viewer, "addScenarioButton"): ## addScenarioButton = self.viewer.addScenarioButton ## if addScenarioButton: ## from mglutil.util.packageFilePath import findFilePath ## icondir = findFilePath('32x32', 'scenario.Icons') ## PI = Tkinter.PhotoImage ## self.animatorIcon = PI(file=os.path.join(icondir, "scenario.gif")) ## icon = self.animatorIcon ## self.scenarioBt = Tkinter.Button( ## frame1, image=icon, width=icon.width(), height=icon.height(), ## command=self.startScenario) ## self.scenarioBt.pack(side='right', padx=2, pady=2, ipadx=2, ipady=2) frame1.pack(fill=X, pady=3) # # Object browser # self.ObjectList = Frame(self.sframe, borderwidth=2) scrollbar = Scrollbar(self.ObjectList, orient=VERTICAL) # # New Tree Object browser ( Class TreeView ) # self.ObjectListFrame = Frame(self.sframe, borderwidth=2, relief='ridge') from mglutil.gui.BasicWidgets.Tk.TreeWidget.tree import TreeView self.tvolist = TreeView(master=self.ObjectListFrame,displayValue=True) self.tvolist.setAction(event='select', function=self.setCurrentObjectFromTree_cb) self.tvolist.double1PickNode_Func_cb = self.toggleVisibility_cb # # Reset Normalize Center buttons # w = self.RNC = Frame(self.sframe, borderwidth=2) w1 = Frame(w, borderwidth=2) self.resetB = Button(w1, text='Reset') self.resetB.pack(side=LEFT, fill=Y, expand=1) self.normalizeB = Button(w1, text='Norm.') self.normalizeB.pack(side=LEFT, fill=Y, expand=1) self.centerB = Button(w1, text='Center') self.centerB.pack(side=LEFT, fill=Y, expand=1) self.deleteB = Button(w1, text='Delete') self.deleteB.pack(side=LEFT, fill=Y, expand=1) self.OwnGuiB = Button(w1, text='Settings') self.OwnGuiB.pack(side=LEFT, fill=Y, expand=1) w1.pack(fill=X) # # RADIO BUTTONS FOR PROPERTIES SUB PANELS # self.panel = StringVar() self.panel.set('Object') # self.PropRadio = Pmw.Group(self.sframe, tag_text='Show properties panel for:') # w = self.PropRadio.interior() # # Radiobutton(w, text='Object', var=self.panel, # command = self.PObject, value = 'Object', # indicatoron=0, selectcolor='#c67171', # activebackground='#28686b').pack(side=LEFT) # Radiobutton(w, text='Camera', var=self.panel, # command = self.PCamera, value = 'Camera', # indicatoron=0, selectcolor='#c67171', # activebackground='#28686b').pack(side=LEFT) # Radiobutton(w, text='Clip', var=self.panel, # command = self.PClip, value = 'Clip', # indicatoron=0, selectcolor='#c67171', # activebackground='#28686b').pack(side=LEFT) # Radiobutton(w, text='Light', var=self.panel, # command = self.PLight, value = 'Light', # indicatoron=0, selectcolor='#c67171', # activebackground='#28686b').pack(side=LEFT) def propertyRaiseCommand(arg): if arg == 'Object': self.PObject() elif arg == 'Camera': self.PCamera() elif arg == 'Clip': self.PClip() elif arg == 'Light': self.PLight() elif arg == 'Bookmarks': self.PViews() self.propertyNoteBook.setnaturalsize(pageNames=(arg,)) self.propertyNoteBook = Pmw.NoteBook(self.sframe, raisecommand=propertyRaiseCommand) lPropertyPage = {} lPropertyPage['Object'] = self.propertyNoteBook.add('Object') lPropertyPage['Camera'] = self.propertyNoteBook.add('Camera') lPropertyPage['Clip'] = self.propertyNoteBook.add('Clip') lPropertyPage['Light'] = self.propertyNoteBook.add('Light') lPropertyPage['Bookmarks'] = self.propertyNoteBook.add('Bookmarks') ################################## # OBJECT PROPERTIES FRAME ################################## self.ObjProp = Frame(lPropertyPage['Object'], relief=RIDGE, borderwidth=2) # INHERIT PROPERTIES self.inheritF = Frame(self.ObjProp) # create menu button fo inheriting properties self.inheritMenu_b = Menubutton(self.inheritF, text='Current geom properties', #underline=0, relief='raise', direction='right', ) self.inheritMenu_b.indices = [] def toggleMenu(event): if event.widget.menu.winfo_ismapped(): event.widget.menu.grab_set() self.inheritMenu_b.bind('', toggleMenu, '+') self.inheritMenu_b.pack(fill='x') self.inheritMenu_b.menu = Menu(self.inheritMenu_b) majorProp = [ 'protected', 'visible', ] moreProp = [ #'antialiased', 'disableTexture', 'faceNormals', 'invertNormals', 'scissor', 'vertexNormals', 'transparent', ] self.cascadeProp = [ 'lighting', 'sharpColorBoundaries', 'stippleLines', 'stipplePolygons', ] inheritProp = [ 'inheritMaterial', #'inheritStippleLines', #'inheritStipplePolygons', 'inheritXform', ] inheritProp2 = [ 'inheritPointWidth', 'inheritLineWidth', ] opacityProp = [ 'depthMask', ] self.inheritVar = {} for prop in majorProp: var = Tkinter.IntVar() self.inheritVar[prop] = var f = CallBackFunction(self.setInherit_cb, prop, var) self.inheritMenu_b.menu.add_checkbutton(label=prop, command=f, variable=var,) self.inheritMenu_b.menu.add_separator() for prop in inheritProp: var = Tkinter.IntVar() self.inheritVar[prop] = var f = CallBackFunction(self.setInherit_cb, prop, var) self.inheritMenu_b.menu.add_checkbutton(label=prop, command=f, variable=var,) self.inheritMenu_b.indices.append(self.inheritMenu_b.menu.index(prop)) for prop in inheritProp2: var = Tkinter.IntVar() self.inheritVar[prop] = var self.relabelingCascadeMenus = {} for prop in self.cascadeProp: lCascadeMenu = RelabelingCascadeMenu(label=prop, variable=Tkinter.IntVar(), master=self.inheritMenu_b.menu, tearoff=0) self.relabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) lFuncCall = CallBackFunction(self.setPropMode, lCascadeMenu.baseLabel, lCascadeMenu.cascadeVariable) lCascadeMenu.add_radiobutton( label='on', variable=lCascadeMenu.cascadeVariable, command=lFuncCall, value=1, underline=0) lCascadeMenu.add_radiobutton( label='off', variable=lCascadeMenu.cascadeVariable, command=lFuncCall, value=0, underline=0) lCascadeMenu.add_radiobutton( label='inherit', variable=lCascadeMenu.cascadeVariable, command=lFuncCall, value=viewerConst.INHERIT, underline=0) #lCascadeMenu.setWithoutCallbackFunction('inherit') # shading lCascadeMenu = RelabelingCascadeMenu(label='shading', variable=Tkinter.IntVar(), master=self.inheritMenu_b.menu, tearoff=0) self.relabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) lFuncCall = CallBackFunction(self.setPropMode, lCascadeMenu.baseLabel, lCascadeMenu.cascadeVariable) for lab, mode in viewerConst.SHADINGS.items(): lCascadeMenu.add_radiobutton(label=lab, variable=lCascadeMenu.cascadeVariable, command=lFuncCall, value=mode, ) # culling lCascadeMenu = RelabelingCascadeMenu(label='culling', variable=Tkinter.IntVar(), master=self.inheritMenu_b.menu, tearoff=0) self.relabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) lFuncCall = CallBackFunction(self.setPropMode, lCascadeMenu.baseLabel, lCascadeMenu.cascadeVariable) for lab, mode in zip(viewerConst.CULLINGS_keys, viewerConst.CULLINGS_values): lCascadeMenu.add_radiobutton(label=lab, variable=lCascadeMenu.cascadeVariable, command=lFuncCall, value=mode, ) # frontPolyMode self.frontPolyMode = Tkinter.IntVar() lCascadeMenu = RelabelingCascadeMenu(label='frontPolyMode', variable=self.frontPolyMode, master=self.inheritMenu_b.menu, tearoff=0) self.relabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) for lab, mode in zip(viewerConst.Front_POLYGON_MODES_keys, viewerConst.Front_POLYGON_MODES_values): if not self.viewer.hasOffsetExt: continue lCascadeMenu.add_radiobutton(label=lab, variable=lCascadeMenu.cascadeVariable, command=self.SetFrontPolyMode, value=mode, ) # backPolyMode lCascadeMenu = RelabelingCascadeMenu(label='backPolyMode', variable=Tkinter.IntVar(), master=self.inheritMenu_b.menu, tearoff=0) self.relabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) for lab, mode in zip(viewerConst.Back_POLYGON_MODES_keys, viewerConst.Back_POLYGON_MODES_values): if not self.viewer.hasOffsetExt: continue lCascadeMenu.add_radiobutton(label=lab, variable=lCascadeMenu.cascadeVariable, command=self.SetBackPolyMode, value=mode, ) # lineWidth lCascadeMenu = RelabelingCascadeMenu(label='lineWidth', variable=Tkinter.IntVar(), master=self.inheritMenu_b.menu, tearoff=0) self.relabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) def lineWidthFunc(): self.setPropMode( 'lineWidth', self.relabelingCascadeMenus['lineWidth'].cascadeVariable) value = self.relabelingCascadeMenus['lineWidth'].cascadeVariable.get() if value != viewerConst.INHERIT: self.lw.Set( value, update=False ) if self.inheritVar['inheritLineWidth'].get() != 0: self.inheritVar['inheritLineWidth'].set(0) else: self.inheritVar['inheritLineWidth'].set(1) for lIndex in range(1, 11): lCascadeMenu.add_radiobutton(label=' '+str(lIndex), variable=lCascadeMenu.cascadeVariable, command=lineWidthFunc, value=lIndex, ) lCascadeMenu.add_radiobutton( label='inherit', variable=lCascadeMenu.cascadeVariable, command=lineWidthFunc, value=viewerConst.INHERIT, ) # pointWidth lCascadeMenu = RelabelingCascadeMenu(label='pointWidth', variable=Tkinter.IntVar(), master=self.inheritMenu_b.menu, tearoff=0) self.relabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) def pointWidthFunc(): self.setPropMode( 'pointWidth', self.relabelingCascadeMenus['pointWidth'].cascadeVariable) value = self.relabelingCascadeMenus['pointWidth'].cascadeVariable.get() if value != viewerConst.INHERIT: self.pw.Set( value, update=False ) self.inheritVar['inheritPointWidth'].set(0) else: self.inheritVar['inheritPointWidth'].set(1) for lIndex in range(1, 11): lCascadeMenu.add_radiobutton(label=' '+str(lIndex), variable=lCascadeMenu.cascadeVariable, command=pointWidthFunc, value=lIndex, ) lCascadeMenu.add_radiobutton( label='inherit', variable=lCascadeMenu.cascadeVariable, command=pointWidthFunc, value=viewerConst.INHERIT, ) self.inheritMenu_b.menu.add_separator() for prop in moreProp: var = Tkinter.IntVar() self.inheritVar[prop] = var f = CallBackFunction(self.setInherit_cb, prop, var) self.inheritMenu_b.menu.add_checkbutton(label=prop, command=f, variable=var,) for prop in opacityProp: var = Tkinter.IntVar() self.inheritVar[prop] = var f = CallBackFunction(self.setInherit_cb, prop, var) self.inheritMenu_b.menu.add_checkbutton(label=prop, command=f, variable=var,) self.opacityRelabelingCascadeMenus = {} self.srcBFtk = IntVar() lCascadeMenu = RelabelingCascadeMenu(label='srcBF', variable=self.srcBFtk, master=self.inheritMenu_b.menu, tearoff=0) self.opacityRelabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) for lab, mode in viewerConst.srcBFnames.items(): lCascadeMenu.add_radiobutton( label=lab, variable=lCascadeMenu.cascadeVariable, command=self.SetBF, value=mode, underline=0) self.dstBFtk = IntVar() lCascadeMenu = RelabelingCascadeMenu(label='dstBF', variable=self.dstBFtk, master=self.inheritMenu_b.menu, tearoff=0) self.opacityRelabelingCascadeMenus[lCascadeMenu.baseLabel] = lCascadeMenu self.inheritMenu_b.menu.add_cascade(label=lCascadeMenu.baseLabel, menu=lCascadeMenu) dstBFnames = [ 'GL.GL_ZERO', 'GL.GL_ONE', 'GL.GL_SRC_COLOR', 'GL.GL_ONE_MINUS_SRC_COLOR', 'GL.GL_SRC_ALPHA', 'GL.GL_ONE_MINUS_SRC_ALPHA', 'GL.GL_DST_ALPHA', 'GL.GL_ONE_MINUS_DST_ALPHA' ] for dstBFname in dstBFnames: lCascadeMenu.add_radiobutton( label=dstBFname, variable=lCascadeMenu.cascadeVariable, command=self.SetBF, value=eval(dstBFname), underline=0) self.inheritMenu_b['menu'] = self.inheritMenu_b.menu otherProp = [ 'inheritBackPolyMode', 'inheritCulling', 'inheritFrontPolyMode', 'inheritLighting', 'inheritShading', 'inheritSharpColorBoundaries', 'inheritStippleLines', 'inheritStipplePolygons', ] self.cascadeProp += ['shading', 'culling', 'lineWidth', 'pointWidth'] lChidrenInheritProp1 = inheritProp \ + self.cascadeProp lChidrenInheritProp2 = moreProp \ + opacityProp #+ inheritProp2#+ otherProp +#majorProp lChidrenInheritProp = lChidrenInheritProp1 + lChidrenInheritProp2 self.cInheritMenu_b = Menubutton(self.inheritF, text='Propagate property', relief='raise', #direction='right', ) self.cInheritMenu_b.bind('', toggleMenu, '+') self.cInheritMenu_b.pack(fill='x') self.cInheritMenu_b.menu = Menu(self.cInheritMenu_b, tearoff=0) self.cInheritMenu_b['menu'] = self.cInheritMenu_b.menu lCascade = ( Tkinter.Menu(self.cInheritMenu_b.menu, tearoff=1), Tkinter.Menu(self.cInheritMenu_b.menu, tearoff=1) ) self.cInheritMenu_b.menu.add_cascade(label='to direct children only', menu=lCascade[0]) self.cInheritMenu_b.menu.add_cascade(label='to children recursively', menu=lCascade[1]) for lRecursive in (0,1): for prop in inheritProp: f = CallBackFunction(self.setChildProp_cb, prop, lRecursive) lCascade[lRecursive].add_command(label=prop, command=f) for prop in self.cascadeProp: f = CallBackFunction(self.setChildInheritProp_cb, prop, lRecursive) lCascade[lRecursive].add_command(label=prop, command=f) lCascade[lRecursive].add_separator() for prop in lChidrenInheritProp2: f = CallBackFunction(self.setChildProp_cb, prop, lRecursive) lCascade[lRecursive].add_command(label=prop, command=f) # spin settings self.spinMenuButton = Button( self.inheritF, text='Spin settings', #underline=0, relief='raise', command=self.viewer.currentCamera.trackball.toggleSpinGui, ) self.spinMenuButton.pack(fill='x') self.inheritF.pack(fill='x') # outline mesh properties self.outlineMeshButtonInitialized = False self.outlineMeshButton = Button( self.inheritF, text='Outline-Mesh Properties', relief='raise', command=self.outlineMeshProp_cb, ) self.outlineMeshButton.pack(fill='x') # strokes properties self.strokesButtonInitialized = False self.strokesButton = Button( self.inheritF, text='Strokes', relief='raise', command=self.strokesProp_cb, ) self.strokesButton.pack(fill='x') self.objectInheritButtons = {} # EDIT OBJECT MATERIAL self.objMatEdTk = IntVar() self.objMatEdTk.set(0) f = Frame(self.ObjProp) Label(f, text='Material:').grid(row=0, column=0, sticky='w') self.MatEdB1 = Button(f, text='Front', command=self.ObjMatEdFront_cb, ) self.MatEdB1.grid(row=0, column=2) self.MatEdB2 = Button(f, text='Back', command=self.ObjMatEdBack_cb, ) self.MatEdB2.grid(row=0, column=3) #self.inheritVar['inheritMaterial'] = Tkinter.IntVar() lFunc = CallBackFunction(self.setInherit_cb, 'inheritMaterial', self.inheritVar['inheritMaterial']) lCheckbutton = Checkbutton(f, text='inherit', variable=self.inheritVar['inheritMaterial'], command=lFunc, #indicatoron=0, ) lCheckbutton.grid(row=0, column=4) self.objectInheritButtons['inheritMaterial'] = lCheckbutton # LINE WIDTH Label(f, text='Line width:').grid(row=1, column=0, sticky='w') self.lw = Slider(f, minval=1, maxval = 10, immediate=1, incr=1, labelformat = '%d', cursortype='int', ) self.lw.frame.grid(row=1, column=1, columnspan=3) def inheritLineWidthFunc(): if self.inheritVar['inheritLineWidth'].get(): self.relabelingCascadeMenus['lineWidth'].setWithCallbackFunction( viewerConst.INHERIT) else: self.relabelingCascadeMenus['lineWidth'].setWithCallbackFunction( self.lw.Get() ) lCheckbutton = Checkbutton(f, text='inherit', variable=self.inheritVar['inheritLineWidth'], command=inheritLineWidthFunc, ) lCheckbutton.grid(row=1, column=4) self.objectInheritButtons['inheritLineWidth'] = lCheckbutton def CurrentObjectLineWidth(val): self.relabelingCascadeMenus['lineWidth'].setWithCallbackFunction(val) self.lw.AddCallback(CurrentObjectLineWidth) # POINT WIDTH Label(f, text='Point width:').grid(row=2, column=0, sticky='w') self.pw = Slider(f, minval=1, maxval = 10, immediate=1, incr=1, labelformat = '%d', cursortype='int', ) self.pw.frame.grid(row=2, column=1, columnspan=3) def inheritPointWidthFunc(): if self.inheritVar['inheritPointWidth'].get(): self.relabelingCascadeMenus['pointWidth'].setWithCallbackFunction( viewerConst.INHERIT) else: self.relabelingCascadeMenus['pointWidth'].setWithCallbackFunction( self.pw.Get() ) lCheckbutton = Checkbutton(f, text='inherit', variable=self.inheritVar['inheritPointWidth'], command=inheritPointWidthFunc, ) lCheckbutton.grid(row=2, column=4) self.objectInheritButtons['inheritPointWidth'] = lCheckbutton def CurrentObjectPointWidth(val): self.relabelingCascadeMenus['pointWidth'].setWithCallbackFunction(val) self.pw.AddCallback(CurrentObjectPointWidth) self.polyModeMenus = [] # FRONT AND BACK POLYGONS MODE #self.polyMode = Frame(self.ObjProp) Label(f, text='Polygon mode:').grid(row=3, column=0, sticky='w') #self.frontPolyMode = IntVar() #self.backPolyMode = IntVar() Radio_b1 = Menubutton(f, text='Front', #underline=0, relief='raised', padx=5, ) Radio_b1.grid(row=3, column=1) Radio_b1.menu = Menu(Radio_b1) self.polyModeMenus.append(Radio_b1) Radio_b2 = Menubutton(f, text='Back', #underline=0, relief='raised', padx=5, ) Radio_b2.grid(row=3, column=2) Radio_b2.menu = Menu(Radio_b2) self.polyModeMenus.append(Radio_b2) labels = viewerConst.Front_POLYGON_MODES_keys[:] modes = viewerConst.Front_POLYGON_MODES_values[:] for label,mode in zip(labels,modes): Radio_b1.menu.add_radiobutton( label=label, var=self.relabelingCascadeMenus['frontPolyMode'].cascadeVariable, value=mode, command=self.relabelingCascadeMenus['frontPolyMode'].setWithCallbackFunction) Radio_b1['menu'] = Radio_b1.menu labels = viewerConst.Back_POLYGON_MODES_keys[:] modes = viewerConst.Back_POLYGON_MODES_values[:] for label,mode in zip(labels,modes): Radio_b2.menu.add_radiobutton( label=label, var=self.relabelingCascadeMenus['backPolyMode'].cascadeVariable, value=mode, command=self.relabelingCascadeMenus['backPolyMode'].setWithCallbackFunction) Radio_b2['menu'] = Radio_b2.menu # Culling Radio_b3 = Menubutton(f, text='culling', relief='raised') Radio_b3.grid(row=3, column=3) Radio_b3.menu = Menu(Radio_b3) for lab, mode in zip(viewerConst.CULLINGS_keys, viewerConst.CULLINGS_values): Radio_b3.menu.add_radiobutton( label=lab, var=self.relabelingCascadeMenus['culling'].cascadeVariable, value=mode, command=self.relabelingCascadeMenus['culling'].setWithCallbackFunction, ) Radio_b3['menu'] = Radio_b3.menu self.polyModeMenus.append(Radio_b3) #self.zsortFrame = Frame(self.ObjProp) b = Label(f, text='Transparency order:') b.grid(row=4, column=0, columnspan=2, sticky='w') # sort polygons along z direction b = Button(f, text='Zsort', command=self.zSortPoly) b.grid(row=4, column=2) # sort polygons along -z direction b = Button(f, text='-Zsort', command=self.minuszSortPoly) b.grid(row=4, column=3) f.pack(fill='x', expand=1) # b = Button(self.ObjProp, text='Read Object', command=self.read) # b.pack(fill=X, expand=1) # b = Button(self.ObjProp, text='Write Object', command=self.write) # b.pack(fill=X, expand=1) # b = Button(self.ObjProp, text='Edit Prop.', command=self.ObjectProp) # b.pack(fill=X, expand=1) ################################## # CAMERA PROPERTIES PANEL ################################## self.CameraProp = Frame(lPropertyPage['Camera'], relief=RIDGE, borderwidth=2) self.drawSceneBB = IntVar() Radiobutton_button = Menubutton(self.CameraProp, text='Bounding Box', #underline=0, relief='raised') Radiobutton_button.bind('', toggleMenu, '+') Radiobutton_button.pack(fill=X, padx=5) # the primary pulldown bbmodes = ('NO', 'ONLY', 'WITHOBJECT') Radiobutton_button.menu = Menu(Radiobutton_button) for v in (0,1,2): Radiobutton_button.menu.add_radiobutton(label=bbmodes[v], var=self.drawSceneBB, value = viewerConst.BB_MODES[v], command = self.DrawSceneBB_cb) Radiobutton_button['menu'] = Radiobutton_button.menu # COLOR CHOOSER def setSelectionContourColor_cb(color): DejaVu.selectionContourColor = color self.selectionGUI.contourColorButton.configure(background=TkColor(DejaVu.selectionContourColor)) self.viewer.Redraw() lTargetDict = { 'ambient light': (self.viewer.lightModel.ambient[:3], 'RGB', self.viewer.LMColor ), 'background': (self.viewer.currentCamera.backgroundColor[:3], 'RGB', self.viewer.CurrentCameraBackgroundColor ), 'selection contour': (DejaVu.selectionContourColor, 'RGB', setSelectionContourColor_cb ), } for i in range(maxClip): lTargetText = 'clip %d'%(i+1) lTargetDict[lTargetText] = (self.viewer.clipP[i].color[:3], 'RGB', self.viewer.clipP[i].setColor, ) for i in range(maxLights): ii = i + 1 lTargetText = 'light %d - ambient'%ii lTargetDict[lTargetText] = (self.viewer.lights[i].ambient[:3], 'RGB', self.viewer.lights[i].setAmbient, ) lTargetText = 'light %d - diffuse'%ii lTargetDict[lTargetText] = (self.viewer.lights[i].diffuse[:3], 'RGB', self.viewer.lights[i].setDiffuse, ) lTargetText = 'light %d - specular'%ii lTargetDict[lTargetText] = (self.viewer.lights[i].specular[:3], 'RGB', self.viewer.lights[i].setSpecular, ) lTopColorChooser = Tkinter.Toplevel() self.colorChooser = ColorChooser(master=lTopColorChooser, targetDict=lTargetDict, targetKey='background', ) lTopColorChooser.withdraw() # BACKGROUND COLOR lFunc = CallBackFunction(self.colorChooser.showColorChooser,'background') b = Button(self.CameraProp, text='Background Color', command=lFunc, ) b.pack(fill=X, padx=5) # AUTODEPTHCUE b = Button(self.CameraProp, text='Auto Depthcue', command=self.AutoDepthcue).pack(fill=X, padx=5) # add a button for video recorder # check if the camera is recordable: try: from DejaVu.Camera import RecordableCamera isrecordable = True except: isrecordable = False if isrecordable: camera = self.viewer.currentCamera if isinstance(camera, RecordableCamera): b = Button(self.CameraProp, text='Video Recorder', command = self.CameraVideoRecorder_cb) b.pack(fill=X, padx=5) if not hasattr(camera, "videoRecorder"): camera.videoRecorder = None # PROJECTION TYPE self.projType = IntVar() Radiobutton_button = Menubutton(self.CameraProp, text='Projection', underline=0, relief='raised') Radiobutton_button.bind('', toggleMenu, '+') Radiobutton_button.pack(fill=X, padx=5) # the primary pulldown Radiobutton_button.menu = Menu(Radiobutton_button) for v,s in {0:'Perspective', 1:'Orthographic'}.items(): Radiobutton_button.menu.add_radiobutton(label=s, var=self.projType, value = v, command = self.SetProjection) self.projType.set(self.viewer.currentCamera.projectionType) Radiobutton_button['menu'] = Radiobutton_button.menu # ANTIALIASED self.nbJitter = IntVar() self.nbJitter.set(self.viewer.currentCamera.antiAliased) Radiobutton_button = Menubutton(self.CameraProp, text='Scene Antialiasing', underline=0, relief='raised') Radiobutton_button.bind('', toggleMenu, '+') Radiobutton_button.pack(fill=X, padx=5) # the primary pulldown Radiobutton_button.menu = Menu(Radiobutton_button) for v in jitter.jitterList: Radiobutton_button.menu.add_radiobutton(label=str(v), var=self.nbJitter, value = v, command = self.SetJitter) Radiobutton_button['menu'] = Radiobutton_button.menu #NPR OUTLINES Checkbutton_button = Menubutton(self.CameraProp, text='Cartoon Outlines', underline=0, relief='raised') Checkbutton_button.bind('', toggleMenu, '+') Checkbutton_button.pack(fill=X, padx=5) self.contourTk = viewer.contourTk Checkbutton_button.menu=Menu(Checkbutton_button) # CONTOUR Checkbutton_button.menu.add_checkbutton(label='On', var = self.contourTk, command=self.toggleOutline) #SET NPR PARAMETERS Checkbutton_button.menu.add_command( label='Edit Parameters', command=self.showCurveTool) Checkbutton_button['menu'] = Checkbutton_button.menu #GraphToolWidget from mglutil.gui.BasicWidgets.Tk.graphtool import GraphApp self.GraphToolpanel=Tkinter.Toplevel() self.GraphToolpanel.title("GraphTool") self.GraphToolpanel.withdraw() self.GraphToolpanel.protocol('WM_DELETE_WINDOW', self.GraphToolpanel.withdraw) f1 = Tkinter.Frame(self.GraphToolpanel) f1.pack(side='top', fill='both', expand=1) self.curvetool=GraphApp(f1,callback=self.continuousRamp) self.curvetool.defaultcurve_cb() self.d1scalewheel=self.curvetool.d1scalewheel self.d1scalewheel.set(self.viewer.currentCamera.d1scale) self.d1scalewheel.callbacks.AddCallback(self.setNPR_cb) #=============================================================================== # Screen Space Ambient Occlusion #=============================================================================== Checkbutton_button = Menubutton(self.CameraProp, text='Screen Space Ambient Occlusion', underline=0, relief='raised') Checkbutton_button.bind('', toggleMenu, '+') Checkbutton_button.pack(fill=X, padx=5) self.ssaoTk = BooleanVar() self.ssaoTk.set(self.viewer.currentCamera.ssao) Checkbutton_button.menu=Menu(Checkbutton_button) # TOGGLE Checkbutton_button.menu.add_checkbutton(label='On', var = self.ssaoTk, command=self.toggleSSAO) #SET SSAO PARAMETERS Checkbutton_button.menu.add_command( label='Edit Parameters', command=self.showSSAOTool) Checkbutton_button['menu'] = Checkbutton_button.menu # occlusion cam GUI ## b = Button(self.CameraProp, ## text='Ambient Occlusion', ## underline=0, ## command=self.showOcclusionCamGUI) ## b.pack(fill=X, padx=5) # SelectionGui self.selectionGUI = SelectionGUI(viewerGui=self) b = Button(self.CameraProp, text='Selection Settings', underline=0, command=self.selectionGUI.toggle) b.pack(fill=X, padx=5) # DEPTHCUE self.depthcued = IntVar() b = Checkbutton(self.CameraProp, text='Depthcueing', variable=self.depthcued, command=self.ToggleDepth, onvalue=viewerConst.YES, offvalue=viewerConst.NO).pack(fill=X, padx=5) self.depthcued.set(1) # THUMBNAIL self.drawThumbnail = IntVar() b = Checkbutton(self.CameraProp, text='Thumbnail', variable=self.drawThumbnail, command=self.ToggleThumbnail, onvalue=viewerConst.YES, offvalue=viewerConst.NO).pack(fill=X, padx=5) ##SET OVER ALL LIGHTING b=Checkbutton(self.CameraProp,text='Overall Lighting', variable = self.viewer.OverAllLightingIsOn, command = self.viewer.deleteOpenglListAndCallRedrawAndCallDisableGlLighting ) b.pack(fill=X, padx=5) # NEAR/FAR DEPTCUEING SLIDER self.NearFarFog = TwoSlidersGUI(viewer, self.CameraProp) ################################# # Light properties frame ################################## self.LightProp = Frame(lPropertyPage['Light'], relief=RIDGE, borderwidth=2) ################################### #LIGHT MODEL lmframe = Frame(self.LightProp, relief=RIDGE, borderwidth=2) self.localViewer = IntVar() self.localViewer.set(self.viewer.lightModel.localViewer is True) b = Checkbutton(lmframe, text='Local Viewer', width=10, variable=self.localViewer, command=self.ToggleLocalViewer, onvalue=viewerConst.YES, offvalue=viewerConst.NO).grid(row=0, column=0) self.twoSide = IntVar() self.twoSide.set(self.viewer.lightModel.twoSide is True) b = Checkbutton(lmframe, text='Two Side', width=7, variable=self.twoSide, command=self.ToggleTwoSide, onvalue=viewerConst.YES, offvalue=viewerConst.NO).grid(row=0, column=1) lFunc = CallBackFunction(self.colorChooser.showColorChooser,'light 1 - diffuse') b = Button(lmframe, text='Light Colors', command=lFunc, ) b.grid(row=1, column=0, columnspan=4) #self.lightModelColor = IntVar() ################################### #LIGHT Sources lsframe = Frame(self.LightProp, relief=RIDGE, borderwidth=2) self.CurrentLight = IntVar() self.CurrentLight.set( 1 ) f1 = Frame(lsframe, borderwidth=0) self.lightSourceOnOffCheckButtons = [] b = Checkbutton(f1, text='1 \'key\'', variable=self.CurrentLight, onvalue=1, offvalue=0, command=self.LightSelect) self.lightSourceOnOffCheckButtons.append(b) b.grid(row=0, column=0) b = Checkbutton(f1, text='2 \'fill\'', variable=self.CurrentLight, onvalue=2, offvalue=0, command=self.LightSelect) self.lightSourceOnOffCheckButtons.append(b) b.grid(row=0, column=1) b = Checkbutton(f1, text='3 \'reflective\'', variable=self.CurrentLight, onvalue=3, offvalue=0, command=self.LightSelect) self.lightSourceOnOffCheckButtons.append(b) b.grid(row=0, column=2) f12 = Frame(lsframe, borderwidth=0) for i in range(3, maxLights): b = Checkbutton(f12, text=str(i+1), variable=self.CurrentLight, onvalue=i+1, offvalue=0, command=self.LightSelect) self.lightSourceOnOffCheckButtons.append(b) b.grid(row=1, column=i-3) self.lightOnOff = IntVar() self.lightOnOff.set(1) f2 = Frame(lsframe, borderwidth=0) self.lightOnOffButton = Checkbutton(f2, text='Light On', variable = self.lightOnOff, command = self.LightOnOff, width=14, onvalue=viewerConst.YES, offvalue=viewerConst.NO) self.lightOnOffButton.pack() self.showLight = IntVar() b = Checkbutton(f2, text='Show Lights', command = self.LightShow, variable=self.showLight, width=14, onvalue=viewerConst.YES, offvalue=viewerConst.NO) b.pack() self.lightColor = IntVar() # f3 = Frame(lsframe, borderwidth=2) # self.LightType = StringVar() # self.LightType.set('Directional') # Radiobutton(f3, text="Directional", # command = self.LightDirectional, value = 'Directional', # variable = self.LightType, # indicatoron=0, selectcolor="#c67171", # activebackground="#28686b").pack(fill=X) # Radiobutton(f3, text="Positional", # command = self.LightPositional, value = 'Positional', # variable = self.LightType, # indicatoron=0, selectcolor="#c67171", # activebackground="#28686b").pack(fill=X) # Radiobutton(f3, text="Spot", # command = self.LightSpot, value = 'Spot', # variable = self.LightType, # indicatoron=0, selectcolor="#c67171", # activebackground="#28686b").pack(fill=X) f1.pack(fill=X, pady = 3, expand = 1) f12.pack(fill=X, pady = 3, expand = 1) f2.pack(fill=X, pady = 3, expand = 1) lmframe.pack(fill=X, pady = 3, expand = 1) lsframe.pack(fill=X, pady = 3, expand = 1) # f3.pack(fill=X, expand = 1) ################################# # CLIPPING PLANES PANEL ################################## self.ClipProp = Frame(lPropertyPage['Clip'], relief=RIDGE, borderwidth=2) self.CurrentClip = IntVar() self.CurrentClip.set( 1 ) f1 = Frame(self.ClipProp, borderwidth=0) lab = ('on', 'side', 'clip\nchildren', 'display', 'capGL', 'capMesh', 'current') lenlab = len(lab) lenlabm1 = lenlab - 1 for i in range(lenlab): Label(f1, text=lab[i]).grid(row=0, column=i+1) self.clipvar = [ ] self.clipw = [ ] funcs = (self.ClipOnOff, self.ClipSide, self.ClipInherit, self.ClipVisible, self.ClipCap, self.ClipCapMesh) for i in range(1, maxClip+1): l = [] self.clipvar.append(l) lw = [] self.clipw.append(lw) w = Label(f1, text=str(i)) w.grid(row=i+1, column=0) for j in range(lenlabm1): v = IntVar() l.append(v) w = Checkbutton(f1, variable=v, onvalue=i, offvalue=0, state=DISABLED, command=funcs[j]) w.grid(row=i+1, column=j+1) lw.append(w) Radiobutton(f1, variable=self.CurrentClip, value=i, command=self.ClipSelect).grid(row=i+1, column=lenlab) for i in range(lenlabm1): self.clipw[0][i].configure(state=NORMAL) f2 = Frame(self.ClipProp, borderwidth=0) lFunc = CallBackFunction(self.colorChooser.showColorChooser,'clip 1') b = Button(f2, text='Clip plane colors', command=lFunc, ) b.pack() # self.clipColor = IntVar() # self.editClipCol = Checkbutton(f2, text='Edit ClipPlane Color', # width=16, # variable=self.clipColor, # command = self.ClipColorButton_cb, # onvalue=viewerConst.YES, # offvalue=viewerConst.NO) # self.editClipCol.pack() f1.pack(fill=X, pady = 3, expand = 1) f2.pack(fill=X, pady = 3, expand = 1) self.top.pack(fill=BOTH) self.XformRadio.pack(fill='x', padx=2, pady=2, ipadx=2, ipady=2) #self.ObjectList.pack(fill=BOTH, expand=1,padx=2, pady=2) self.ObjectListFrame.pack(fill=BOTH, expand=1,padx=2, pady=2) self.RNC.pack(padx=2, pady=2, ipadx=2, ipady=2) self.ObjProp.pack(fill='x', ipadx=2, ipady=2, padx=2, pady=2) self.propertyNoteBook.setnaturalsize(pageNames=lPropertyPage.keys()) self.propertyNoteBook.pack(padx=2, pady=2, ipadx=2, ipady=2, fill='x') self.CurrentPropPanel = self.ObjProp ################################# # OBJECT MATERIAL PANNEL ################################## # NEW TOPLEVEL ## self.colorRoot = Toplevel() ## self.colorRoot.title("Object Material") ## self.colorTop=Frame(self.colorRoot) # MATERIAL EDITOR # self.materialEditor = PropertyEditor.MaterialEditor( # self.sframe, # self.colorChooser, # ) # LIGHT COLOR EDITOR # self.lightColorEditor = PropertyEditor.LightColorEditor( # self.sframe, # self.colorChooser, # ) self.sf.interior().pack(fill = 'both', expand = 1) self.sf.reposition() self.sf.pack(fill = 'both', expand = 1) ###################################################################### ###################### Bookmarks pane ################################ ###################################################################### self.BookmarksProp = Frame(lPropertyPage['Bookmarks'], relief=RIDGE, borderwidth=2) self.createBookmarkPane(self.BookmarksProp) def strokesProp_cb(self, event=None): self.viewer.currentObject.applyStrokes(strength=2) # modified Stefano def _setOMP(self, attr, obj, val=None): if attr=='lighting': val = self.lightOutlineMesh.get() elif attr=='color': obj._setTransparent('implicit') d = {attr:val} #print 'setting outline', obj.fullName, attr, val obj.outline.Set(**d) self.viewer.Redraw() def outlineMeshProp_cb(self, event=None, geometry=None): if geometry is None: obj = self.viewer.currentObject else: obj = geometry if not hasattr(obj, 'outline'): return if not self.outlineMeshButtonInitialized: frame = self.outlineMeshPanel = Tkinter.Toplevel() frame.geometry("+%d+%d"%frame.winfo_pointerxy()) frame.protocol('WM_DELETE_WINDOW', frame.withdraw) lFuncCall = CallBackFunction(self._setOMP, 'factor', obj) self.ompfactortw = ThumbWheel( frame, width=70, height=16, type=float, value=obj.outline.factor, callback=lFuncCall, continuous=True, oneTurn=10., wheelPad=2, min=0.1, labCfg = {'text': 'factor:', 'side':'top'}) self.ompfactortw.grid(column=0, row=0) lFuncCall = CallBackFunction(self._setOMP, 'unit', obj) self.ompunittw = ThumbWheel( frame, width=70, height=16, type=float, value=obj.outline.unit, callback=lFuncCall, continuous=True, oneTurn=10., wheelPad=2, min=0.1, labCfg = {'text': 'unit:', 'side':'top'}) self.ompunittw.grid(column=1, row=0) lFuncCall = CallBackFunction(self._setOMP, 'lineWidth', obj) self.omplwtw = ThumbWheel( frame, width=70, height=16, type=int, value=obj.outline.lineWidth, callback=lFuncCall, continuous=True, oneTurn=10., wheelPad=2, min=1, labCfg = {'text':'line width:', 'side':'top'}) self.omplwtw.grid(column=2, row=0) lFuncCall = CallBackFunction(self._setOMP, 'lighting', obj) self.lightOutlineMesh = IntVar() self.omplightingb = Checkbutton( frame, text='lighting', variable=self.lightOutlineMesh, command=lFuncCall, ) self.omplightingb.grid(column=3, row=0) cc = self.ompcolorchooser = ColorChooser( frame, gridCfg={'column':0, 'row':1, 'columnspan':4}) lFuncCall = CallBackFunction(self._setOMP, 'color', obj) cc.Set(obj.outline.color, 'RGB', run=False) cc.AddCallback(lFuncCall) frame.title('outline-mesh properties for '+obj.fullName) self.outlineMeshButtonInitialized = True else: frame = self.outlineMeshPanel frame.deiconify() frame.geometry("+%d+%d"%frame.winfo_pointerxy()) self.updateOMPgui(obj) def updateOMPgui(self, obj=None): if self.outlineMeshButtonInitialized: if obj is None: obj = self.viewer.currentObject if self.outlineMeshPanel.winfo_ismapped(): if not hasattr(obj, 'outline'): self.outlineMeshPanel.withdraw() return else: self.outlineMeshPanel.title('outline-mesh properties for '+obj.fullName) self.ompfactortw.set(obj.outline.factor, update=0) self.ompunittw.set(obj.outline.unit, update=0) self.omplwtw.set(obj.outline.lineWidth, update=0) self.lightOutlineMesh.set(obj.outline.lighting) self.ompcolorchooser.Set(obj.outline.color, run=False) def createBookmarkPane(self, master): self.masterFrame = master self.allRepr = 0 # repr counter used to name representations by default self.reprMem = {} w = self.reprContainer = Pmw.Group(master, tag_pyclass = Tkinter.Button, tag_text='Save representation') w.configure(tag_command = self.addRepr) w.pack(fill = 'both', expand = 1, padx = 6, pady = 6) self.viewsBalloon = Pmw.Balloon(self.root) self.reprMenu = Tkinter.Menu(self.root, title = "Representation") self.reprMenu.add_command(label="Rename repr") self.reprMenu.add_command(label="Remove repr") self.reprMenu.add_command(label="Dismiss") def addOrient(self, event=None): name = 'orient%d'% self.allOrients self.allOrients = self.allOrients + 1 c = self.viewer.currentCamera mini, maxi = self.viewer.rootObject.ComputeBB(self.viewer.currentCamera) lBox = maxi - mini lHalfObject = max(lBox)/2. if lHalfObject == 0.: lHalfObject = 1. import math from scenario.interpolators import matToQuaternion, quatToMatrix dist = lHalfObject / math.tan(c.fovyNeutral/2*math.pi/180.0) lookFrom = c.nearDefault+dist+lHalfObject self.orients[name] = { 'quat' : matToQuaternion(self.viewer.rootObject.rotation), 'trans' : self.viewer.rootObject.translation[:], 'scale' : self.viewer.rootObject.scale[:], 'pivot' : self.viewer.rootObject.pivot, 'fovy' : c.fovy, 'lfrom' : lookFrom, 'near': c.near, 'far': c.far, 'start':c.fog.start, 'end': c.fog.end } #positionNames = positions.keys() #positionNames.sort() #positionList.setlist(positionNames) #self.addOrientScenario(name) orient = self.orients[name] self.orientsDirectors[name] = self.createOrientScenario(name, orient) self.addOrientButton(name) def getButtonIcon(self): import Image, ImageChops, ImageTk c = self.viewer.currentCamera im = c.GrabFrontBuffer() def autocrop(im, bgcolor): if im.mode != "RGB": im = im.convert("RGB") bg = Image.new("RGB", im.size, bgcolor) diff = ImageChops.difference(im, bg) bbox = diff.getbbox() if bbox: return im.crop(bbox) return None # no contents imc = autocrop(im, tuple([int(round(x*255)) for x in c.backgroundColor[:3]])) if imc is None: imc = im ims = imc.resize((50, 50), Image.ANTIALIAS) return ImageTk.PhotoImage(ims), ims def saveRepr(self): statesMem = {} for g in self.viewer.rootObject.AllObjects(): if not g.visible: state = {'visible':0} else: state = g.getState(full=1) del state['rotation'] del state['translation'] del state['scale'] del state['pivot'] del state['name'] statesMem[g.fullName] = state return statesMem def restoreRepr(self, name, button = None): mem = self.reprMem[name] for g in self.viewer.rootObject.AllObjects(): if not mem.has_key(g.fullName): g.visible = 0 else: #print g.fullName tmp = mem[g.fullName].copy() mat = tmp.pop('rawMaterialF', None) if mat: g.materials[GL.GL_FRONT].Set(**mat) mat = tmp.pop('rawMaterialB', None) if mat: g.materials[GL.GL_BACK].Set(**mat) g.Set( **tmp ) if button: if not hasattr(button, "photo"): #print "updating image for button %s" % name self.viewer.master.master.lift() self.viewer.OneRedraw() photo, ims = self.getButtonIcon() button.configure(compound='left', image = photo, text = "", width=photo.width(), height = photo.height()) button.photo = photo def removeRepr(self, name): reprB = None frame = self.reprContainer.interior() for b in frame.grid_slaves(): if hasattr(b, "name"): if b.name == name: reprB = b break if reprB: reprB.destroy() buttons = frame.grid_slaves() buttons.reverse() for i, b in enumerate(buttons): b.grid(row=1+ i/5, column= i%5, sticky='w') self.propertyNoteBook.setnaturalsize(pageNames=('Bookmarks',)) self.reprMem.pop(name) def renameRepr(self, name): from tkSimpleDialog import askstring newname = askstring("Rename repr %s"%name, "Enter new name:", initialvalue = name, parent = self.reprContainer.interior()) if newname != None and newname != name: if self.reprMem.has_key(newname): from tkMessageBox import showwarning showwarning("Warning", "Representation name %s already exists"%newname, parent = self.root) return #find cooresponding button, rename it and update the bindings: for b in self.reprContainer.interior().grid_slaves(): if hasattr(b, "name"): if b.name == name: b.name = newname b.configure(command = CallBackFunction( self.restoreRepr, newname)) b.bind('', CallBackFunction( self.showReprMenu_cb, newname)) self.viewsBalloon.bind(b, newname) repr = self.reprMem.pop(name) self.reprMem[newname] = repr break def showReprMenu_cb(self, name, event = None): entry = self.reprMenu.index("Rename repr") self.reprMenu.entryconfigure( entry, command = CallBackFunction(self.renameRepr, name)) entry = self.reprMenu.index("Remove repr") self.reprMenu.entryconfigure( entry, command = CallBackFunction(self.removeRepr, name)) self.reprMenu.post(event.x_root, event.y_root) def addRepr(self, event=None): name = 'repr%d'% self.allRepr self.allRepr += 1 self.reprMem[name] = self.saveRepr() self.addReprButton(name) def addReprButton(self, name, icon = True): if self.allRepr == 0: self.viewsBalloon.bind(self.reprContainer._ring, "Right click on image\nto display its menu") master = self.reprContainer.interior() if icon == True: photo, ims = self.getButtonIcon() b = Tkinter.Button(master=master ,compound='left', image=photo) b.photo = photo else: b = Tkinter.Button(master=master , text=name, width = 4, height = 3, wraplength=50) self.viewsBalloon.bind(b, name) b.name = name b.configure(command = CallBackFunction( self.restoreRepr, name, b)) b.grid(row=1+(len(self.reprMem)-1)/5, column=(len(self.reprMem)-1)%5, sticky='w') self.propertyNoteBook.setnaturalsize(pageNames=('Bookmarks',)) self.sframe.pack() b.bind('', CallBackFunction( self.showReprMenu_cb, name)) def saveReprToFile(self, file = None): if len(self.reprMem) == 0: from tkMessageBox import showwarning showwarning("Warning", "There are no representations in Bookmarks to save", parent=self.root) return if file is None: oldtypes = self.saveFileBrowser.filetypes self.saveFileBrowser.filetypes = [('', '*_repr.db'), ('all', '*')] file = self.getSaveFileName() self.saveFileBrowser.filetypes = oldtypes if file: import shelve f = shelve.open(file) if len(f.keys()): f.clear() for name in self.reprMem.keys(): f[name] = self.reprMem[name] f.close() def loadReprFromFile(self, file = None): if file is None: oldtypes = self.openFileBrowser.filetypes self.openFileBrowser.filetypes = [('', '*_repr.db'), ('all', '*.py')] file = self.getLoadFileName() self.openFileBrowser.filetypes = oldtypes if file: import shelve newrepr = shelve.open(file) action = "ADD" if len(self.reprMem): # ask the user if he wants to add or replace the representations: dialog = Pmw.Dialog(self.root, title = "Representations", buttons = ('ADD', 'REPLACE', 'Cancel'), defaultbutton = 'ADD') dialog.withdraw() label = Tkinter.Label(dialog.interior(), text = "Would you like to ADD file representaions\n or REPLACE existing ones?", pady = 10) label.pack(expand = 1, fill = 'both', padx = 4, pady = 4) action = dialog.activate(geometry = '+%d+%d' % (self.root.winfo_x()+100, self.root.winfo_y()+200)) if action == "Cancel": return elif action == "REPLACE": # remove all existing representations for b in self.reprContainer.interior().grid_slaves(): b.destroy() self.reprMem = {} nrepr = self.allRepr self.viewer.master.master.lift() #add new repr for i, name in enumerate(newrepr.keys()): newname = name # if saved representation has "custom" name, # check if that name already exists in Representations: if not name.startswith("repr"): if self.reprMem.has_key(name): # name exists -> create newname by adding an # integer to the name count = 0 for k in self.reprMem.keys(): if k.startswith(name): count = count +1 newname = name+"_"+str(count) else: newname = 'repr%d'% (nrepr + i) self.reprMem[newname] = newrepr[name] # ?how can we create an image button of the saved repr? # display that view and "take picture" of it? -> #self.restoreRepr(newname) #This could be very slow self.addReprButton(newname, icon = False) self.allRepr = self.allRepr + 1 newrepr.close() def bindModifersToTransformInfo(self, master): #print "bindModifersToTransformInfo", master if master is not None: lKeys = ('Alt_L','Alt_R','Control_L','Control_R','Meta_L','Meta_R','Shift_L','Shift_R') for lKey in lKeys: master.bind(''%lKey, self.fillTransformInfo_cb) master.bind(''%lKey, self.fillTransformInfo_cb) if hasattr(master, 'master'): self.bindModifersToTransformInfo(master.master) def fillTransformInfo_cb(self, event=None): #print "fillTransformInfo_cb", event, dir(event) if isinstance(event, Tkinter.Event) and (event.type == '2'): lEvent = event.keysym elif type(event) == types.StringType: lEvent = event else: lEvent = 'None' if lEvent.startswith('Alt'): lModifier = 'Alt' elif lEvent.startswith('Shift'): lModifier = 'Shift' elif lEvent.startswith('Control'): lModifier = 'Control' elif lEvent.startswith('Meta'): lModifier = 'Meta' else: lModifier = 'None' for lButtonIndex in (1, 2, 3): lText=self.viewer.currentCamera.mouseButtonActions[self.Xform.get()][lButtonIndex][lModifier] if lText == 'None': lText = '' self.transformInfo[lButtonIndex].configure(text=lText) ## def addOcclusionCamera(self): ## from DejaVu.Camera import OcclusionCamera ## root = Tkinter.Toplevel() ## root.withdraw() ## root.protocol('WM_DELETE_WINDOW', self.hideOcclusionCamGUI) ## self.occlusionCamRoot = root ## self.occlusionCamera = OcclusionCamera(root, self.viewer, ## width=50, height=50) ## def hideOcclusionCamGUI(self, *dummy): ## self.occlusionCamRoot.withdraw() ## def showOcclusionCamGUI(self, *dummy): ## self.occlusionCamera.listGeoms() ## if self.occlusionCamRoot.winfo_ismapped() == 0: ## self.occlusionCamRoot.deiconify() ## self.occlusionCamRoot.lift() ## def startScenario(self, event=None): ## if not hasattr(self.viewer, 'director'): ## from scenarioInterface import DejaVuScenario ## from scenario.director import Director ## director = self.viewer.director = Director() ## scenario = DejaVuScenario(self.viewer, director) ## director.addScenario("DejaVuScenario", scenario) ## else: ## scenario = self.viewer.director.scenarios["DejaVuScenario"] ## scenario.start() def dialog(self): # t="Do you Wish to Quit?" # from SimpleDialog import SimpleDialog # d = SimpleDialog(self.root, text=t, # buttons=["Quit","Cancel"], # default=0, title="Quit?") # ok=d.go() ok = tkMessageBox.askokcancel("Quit?","Do you Wish to Quit?") if ok: self.quit_cb() else: return def quit_cb(self): self.root.master.destroy() def setCurrentObjectFromTree_cb(self, treeNode): if treeNode.object: self.viewer.SetCurrentObject(treeNode.object) def toggleVisibility_cb(self, treeNode): geom = treeNode.object if geom: geom.Set(visible=not geom.visible) def withdraw(self): if self.shown: self.root.withdraw() self.shown = False def deiconify(self): if not self.shown: self.root.deiconify() self.shown = True def Exit(self): # kept for backwards compatibility self.viewer.Exit() def Exit_cb(self, event=None): self.Exit() ## def Wysiwyg_cb(self): ## self.colorChooser.Wysiwyg(self.wysiwyg.get()) def MoveRootOnly_cb(self): self.viewer.TransformRootOnly( self.moveRootOnly.get() ) def showPickedVertex_cb(self): self.viewer.showPickedVertex = self.showPickedVertex.get() def displayValueInObjList_cb(self): v = self.displayValueInObjList.get() self.tvolist.displayValueInTree(v) def showHideQuickKeys_cb(self): if self.showHideQuickKeysVar.get(): self.QuickKeysFrame.deiconify() else: self.QuickKeysFrame.withdraw() def addQuickKey_cb(self): viewer = self.viewer camera = viewer.currentCamera # find what the trackball is bound to xform = self.Xform.get() # find the currentObject if xform=="Object" or xform=="Texture" or xform=="Scissor": obj = viewer.currentObject elif xform=="Camera": obj = viewer.currentCamera elif xform=="Clip": obj = viewer.currentClip elif xform=="Light": obj = viewer.currentLight else: raise RuntimeError("bad value for xform", xform) # find value of rootOnly rootOnly= self.moveRootOnly.get() cb = CallBackFunction( self.quickKey_cb, xform, obj, rootOnly ) if xform=="Object": if rootOnly or obj==viewer.rootObject: label = "Xform Scene" else: label = "Xform "+obj.fullName elif xform=="Clip" or xform=="Light": label = "Xform "+xform+str(obj.num) elif xform=="Camera": label = "Xform Camera" elif xform=="Texture" or xform=="Scissor": label = "Xform %s %s"%(xform, obj.fullName) # create a button and add it to the Quick Keys panel button = Tkinter.Button(self.QuickKeysFrame, text=label, command=cb) button.pack(side='top', expand=1, fill='y') def quickKey_cb(self, xform, obj, rootOnly): if xform=="Object": self.viewer.SetCurrentObject(obj) self.viewer.TransformRootOnly(rootOnly) self.TObject() elif xform=="Camera": self.viewer.SetCurrentCamera(obj) self.TCamera() elif xform=="Clip": self.viewer.SetCurrentClip(obj) self.TClip() elif xform=="Light": self.viewer.SetCurrentLight(obj) self.TLight() elif xform=="Texture": self.viewer.SetCurrentObject(obj) self.viewer.SetCurrentTexture(obj) self.TMap() elif xform=="Scissor": self.viewer.SetCurrentObject(obj) self.Scissor() def bindResetButton(self, func): self.resetB.configure(command=func) def bindNormalizeButton(self, func): self.normalizeB.configure(command=func) def bindCenterButton(self, func): self.centerB.configure(command=func) def bindDeleteButton(self, func): self.deleteB.configure(command=func) def bindOwnGuiButton(self, func): self.OwnGuiB.configure(command=func) def enableResetButton(self, val): self.resetB.configure(state = val) def enableNormalizeButton(self, val): self.normalizeB.configure(state = val) def enableCenterButton(self, val): self.centerB.configure(state = val) def enableDeleteButton(self, val): self.deleteB.configure(state = val) def enableOwnGuiButton(self, val): self.OwnGuiB.configure(state = val) def countParents(self, object): c = 0 while object.parent: c = c+1 object = object.parent return c def lstripChar(self, name, char): n = string.count(name,'~') return n, name[ n : ] def objectByName(self, name): ol = self.viewer.rootObject.AllObjects() n, name = self.lstripChar(name, '~') for o in ol: if o.name==name: return o return None """ def objectIndex(self, object): # object is a geometry and we find this object's index in the list of # names displayed in te widget. If the ibecjt is not shown we # return -1 l = self.olist.get(0, 'end') for i in range(len(l)): indent, n = self.lstripChar(l[i], '~') if n==object.name: break if i==len(l): return -1 else: return i def countDecendentsInWidget(self, object): # object is a geometry, we count and return the number of # decendents shown in widget ind = self.objectIndex(object) allNames = self.olist.get(0, 'end') nbTild = string.count(allNames[ind],'~')+1 # count children in widget nbChildren = 0 for i in range(ind+1, len(allNames)): nbt = string.count(allNames[i],'~') if nbt >= nbTild: nbChildren = nbChildren + 1 else: break return nbChildren # NOT USED def countChildrenInWidget(self, object): # object is a geoemtry, we count and return the number of # children of object shown in widget ind = self.objectIndex(object) allNames = self.olist.get(0, 'end') nbTild = string.count(allNames[ind],'~')+1 # count children in widget nbChildren = 0 for i in range(ind+1, len(allNames)): nbt = string.count(allNames[i],'~') if nbt == nbTild: nbChildren = nbChildren + 1 else: break return nbChildren def getObjectIndexInList(self, object): # object is a geometry and we find this object's index in the list of # names displayed in the widget. If the object is not shown we # return -1 l = list(self.olist.get(0, 'end')) ofn = object.fullName.split('|') ofn = map(lambda x: ofn.index(x)*'~'+x, ofn) findex=0 for name in ofn: en = enumerate(l) for ind, lname in en: if name==lname: findex = ind + findex l = l[ind:] break if findex == len(self.olist.get(0, 'end')): return -1 else: return findex def expand(self, object): # object is a geometry if object.isExpandedInObjectList: return object.isExpandedInObjectList = 1 geoms = object.children ind = self.objectIndex(object) + 1 c = self.countParents(object) + 1 prefix = '~'*c for i in range(len(geoms)): g = geoms[i] if g==object: continue if not g.listed: continue self.olist.insert(ind, prefix + g.name) ind = ind + 1 def collapse(self, object): # object is a geometry, we recursively collapse the sub-tree object.isExpandedInObjectList = 0 # delete the names from the bject list widget nbChildren = self.countDecendentsInWidget(object) ind = self.objectIndex(object) + 1 for i in range(ind, ind+nbChildren): self.olist.delete(ind) # toggle isExpandedInObjectList for all descendents for child in object.AllObjects(): if child.listed: child.isExpandedInObjectList = 0 def getFullName(self, ind): # strip the leading ~ allNames = self.olist.get(0, 'end') nbTild = string.count(allNames[ind],'~') fullName = allNames[ind][nbTild:] for i in range(ind-1, -1, -1): nbt, name = self.lstripChar(allNames[i], '~') if nbt >= nbTild: continue nbTild = nbt fullName = name + '|' + fullName return fullName def toggleExpansion(self, event): # get a 0-based index into list of names o = self.olist.nearest(event.y) fullName = self.getFullName(o) #obj = self.objectByName(self.olist.get(o)) obj = self.viewer.FindObjectByName(fullName) if obj: childGeoms = obj.AllObjects() if len(childGeoms)==1: # this geoemtry has no children return else: # this geometry has children if obj.isExpandedInObjectList: self.collapse(obj) else: self.expand(obj) def select(self, event): # get a 0-based index into list of names o = self.olist.nearest(event.y) fullName = self.getFullName(o) #obj = self.objectByName(self.olist.get(o)) obj = self.viewer.FindObjectByName(fullName) if obj: # SetCurrentObject is called by BindTrackballToObject # self.viewer.SetCurrentObject(obj) self.viewer.BindTrackballToObject(obj) self.viewer.currentTransfMode = 'Object' """ def renameObject(self, obj, name): if not obj.listed: return treeNode = self.tvolist.objToNode[obj] treeNode.rename(name) def addObject(self, obj, parent): """adds object and its children recursively to the treewidget""" if not obj.listed: return if not parent: #self.olist.insert('end', obj.name) self.tvolist.addNode(parent=None, name=obj.name, object=obj) #self.olist.select_set(0,0) else: self.tvolist.addNode(parent=self.tvolist.objToNode[parent], name=obj.name, object=obj) # recursively add the subtree under obj for child in obj.children: self.addObject( child, obj) # if not parent.isExpandedInObjectList: # return # return here.. the following lines should be removed #i = self.objectIndex(parent) # Get the index of the parent in the list to insert the # child after it, # i = self.getObjectIndexInList(parent) #if i==-1: # return #c = self.countParents(obj) # prefix = '~'*c #name = prefix + obj.name # now we need to skip all children already there # l = self.olist.get(0, 'end') # while 1: # i = i + 1 # if i==len(l): break # if self.olist.get(i)[:c]!=prefix: break #self.olist.insert(i, name) def deleteObject(self, obj): if not obj.listed: return # Get the index of the object in the list to # delete it. #i = self.getObjectIndexInList(obj) #self.olist.delete(i) self.tvolist.deleteNode(self.tvolist.objToNode[obj]) def SetCurrentObject(self, obj): #print "SetCurrentObject" #Update GUI for current object #if obj.listed: # names = string.split(obj.fullName, '|') # top = self.viewer.topObjects # l = self.olist.get(0, END) # i = 0 # for name in l: # if names[0]==l[i]: # break # i = i + 1 # for name in names[1:]: # while (i0 and i==len(l): # return # cl = self.olist.curselection() # if len(cl): # self.olist.select_clear(cl) # self.olist.select_set(i,i) # self.olist.see(i) #else: # cl = self.olist.curselection() # if len(cl): self.olist.select_clear(cl) lIsInstanceTransformable = isinstance(obj, Transformable) # Set the Node corresponding to 'obj' be selected p=self.viewer.currentObject try: node = self.tvolist.objToNode[p] except KeyError: self.viewer.currentObject = self.viewer.rootObject node = self.tvolist.objToNode[self.viewer.currentObject] if self.tvolist.current_selected != node: #print "trying to select", node.name , "over :", \ # self.tvolist.current_selected self.tvolist.Select(node) # update the object properties panel for prop, var in self.inheritVar.items(): if hasattr(obj,prop): if (obj is self.viewer.rootObject) \ and (prop.startswith('inherit')): var.set(False) else: propVal = getattr(obj, prop) var.set(propVal) elif prop == 'disableTexture': if hasattr(obj, 'texture') and obj.texture: var.set(not obj.texture.enabled) else: var.set(False) # # update the children properties panel # self.initChildPropPanel(self.viewer.currentObject) #self.showObject.set(obj.visible) mated = self.viewer.materialEditor val = self.objMatEdTk.get() if lIsInstanceTransformable \ and obj.inheritMaterial \ and obj != self.viewer.rootObject: mated.dismiss() self.objMatEdTk.set(0) self.MatEdB1.configure(state='disabled') self.MatEdB2.configure(state='disabled') else: self.MatEdB1.configure(state='normal') self.MatEdB2.configure(state='normal') if val==1: mated.setObject(obj, GL.GL_FRONT) elif val==2: mated.setObject(obj, GL.GL_BACK) for cp in self.viewer.clipP: self.UpdateGuiCP(cp, obj) ## if obj.pickableVertices == viewerConst.YES: ## self.pickableVertices.set(1) ## else: self.pickableVertices.set(0) ## if obj.antialiased == viewerConst.YES: ## self.antialiasedLines.set(1) ## else: self.antialiasedLines.set(0) ## self.scissortk.set( obj.scissor) # self.depthMasktk.set( obj.depthMask ) if lIsInstanceTransformable: self.lw.Set(obj.lineWidth, update=0) self.pw.Set(obj.pointWidth, update=0) ## self.opacw.Set(obj.materials[GL.GL_FRONT].prop[1][0][3], update=0) lCascadeMenu = self.opacityRelabelingCascadeMenus['srcBF'] lCascadeMenu.setWithoutCallbackFunction( obj.srcBlendFunc ) lCascadeMenu = self.opacityRelabelingCascadeMenus['dstBF'] lCascadeMenu.setWithoutCallbackFunction( obj.dstBlendFunc ) lCascadeMenu = self.relabelingCascadeMenus['frontPolyMode'] if (obj is not self.viewer.rootObject) \ and (obj.inheritFrontPolyMode is True): lCascadeMenu.setWithoutCallbackFunction(viewerConst.INHERIT) elif obj.drawOutline[0]: lCascadeMenu.setWithoutCallbackFunction(viewerConst.OUTLINED) else: lCascadeMenu.setWithoutCallbackFunction(obj.frontPolyMode) lCascadeMenu = self.relabelingCascadeMenus['backPolyMode'] if obj.frontAndBack: lCascadeMenu.setWithoutCallbackFunction(GL.GL_FRONT_AND_BACK) elif (obj is not self.viewer.rootObject) \ and (obj.inheritBackPolyMode is True): lCascadeMenu.setWithoutCallbackFunction(viewerConst.INHERIT) elif obj.drawOutline[1]: lCascadeMenu.setWithoutCallbackFunction(viewerConst.OUTLINED) else: lCascadeMenu.setWithoutCallbackFunction(obj.backPolyMode) for prop in self.cascadeProp: lCascadeMenu = self.relabelingCascadeMenus[prop] inheritProp = 'inherit' + prop[0].upper() + prop[1:] if (obj is not self.viewer.rootObject) \ and (getattr(obj, inheritProp) is True): lCascadeMenu.setWithoutCallbackFunction(viewerConst.INHERIT) else: lCascadeMenu.setWithoutCallbackFunction( getattr(obj, prop) ) if len(obj.children) == 0: self.menuEdit.menu.entryconfig('Apply Transformation', state='normal') else: self.menuEdit.menu.entryconfig('Apply Transformation', state='disabled') if obj == self.viewer.rootObject: for lButton in self.objectInheritButtons.values(): lButton.configure(state='disabled') for lIndex in self.inheritMenu_b.indices: self.inheritMenu_b.menu.entryconfigure(lIndex, state='disabled') for lCascadeMenu in self.relabelingCascadeMenus.values(): lCascadeMenu.entryconfigure('inherit', state='disabled') for lPolyModeMenu in self.polyModeMenus: lPolyModeMenu.menu.entryconfigure('inherit', state='disabled') else: for lButton in self.objectInheritButtons.values(): lButton.configure(state='normal') for lIndex in self.inheritMenu_b.indices: self.inheritMenu_b.menu.entryconfigure(lIndex, state='normal') for lCascadeMenu in self.relabelingCascadeMenus.values(): lCascadeMenu.entryconfigure('inherit', state='normal') for lPolyModeMenu in self.polyModeMenus: lPolyModeMenu.menu.entryconfigure('inherit', state='normal') self.updateOMPgui() def read(self): print 'read' def write(self): print 'write' def delete(self): print 'delete' def ObjectProp(self): print 'ObjProp' ## can't get gluProject to work properly ! ## v = obj.vertexSet.vertices.array ## mini = Numeric.minimum.reduce(v) ## mini = obj.Project(mini) ## print 'mini:', mini ## maxi = Numeric.maximum.reduce(v) ## maxi = obj.Project(maxi) ## print 'maxi:', maxi ## diffX = (maxi[0]-mini[0])*0.25 ## diffY = (maxi[1]-mini[1])*0.25 ## obj.Set( scissor = self.scissortk.get(), ## scissorX = mini[0]+diffX, scissorY = mini[0]+diffY, ## scissorW = mini[1]+(2*diffX), scissorH = mini[1]+(2*diffY) ) def zSortPoly(self): obj = self.viewer.currentObject if isinstance(obj, IndexedGeom): # or isinstance(obj, Spheres): obj.sortPoly() self.viewer.Redraw() def minuszSortPoly(self): obj = self.viewer.currentObject if isinstance(obj, IndexedGeom): # or isinstance(obj, Spheres): obj.sortPoly(order=1) self.viewer.Redraw() def SetBF(self): obj = self.viewer.currentObject if isinstance(obj, IndexedGeom): obj.Set( blendFunctions=(self.srcBFtk.get(), self.dstBFtk.get()) ) self.viewer.Redraw() def setChildProp_cb(self, propname, recursive): #print "setChildProp_cb", propname obj = self.viewer.currentObject if propname == 'scissor' : obj.SetForChildren( scissor=obj.scissor, scissorX=obj.scissorX, scissorY=obj.scissorY, scissorW=obj.scissorW, scissorH=obj.scissorH ) elif hasattr(obj, propname): propval = getattr(obj, propname) apply( obj.SetForChildren, (recursive,), {propname:propval}) self.viewer.deleteOpenglList() self.viewer.Redraw() def setChildInheritProp_cb(self, propname, recursive): #print "setChildInheritProp_cb", propname obj = self.viewer.currentObject if isinstance(obj, Geom): inheritPropName = 'inherit' + propname[0].upper() + propname[1:] #print "inheritPropName", inheritPropName inheritPropVal = getattr(obj, inheritPropName) apply( obj.SetForChildren, (recursive,), {inheritPropName:inheritPropVal}) propVal = getattr(obj, propname) apply( obj.SetForChildren, (recursive,), {propname:propVal}) self.viewer.deleteOpenglList() self.viewer.Redraw() def setInherit_cb(self, propname, variable): #print "setInherit_cb", propname, variable.get() # 1- Get a handle to the current object. obj = self.viewer.currentObject # 2- Get the propname and the property value propval = variable.get() # 3- props that dont need to call obj.set if propname == 'disableTexture': if hasattr(obj, 'texture') and obj.texture: obj.texture.Set(enable=not propval) elif propname == 'vertexNormals': if propval: obj.addVertexNormalsGeom() else: obj.removeVertexNormalsGeom() elif propname == 'faceNormals': if propval: obj.addFaceNormalsGeom() else: obj.removeFaceNormalsGeom() else: # 4- Set the propname of the current object to the given value apply(obj.Set, (), {propname:propval}) if propname=='scissor': if propval: self.viewer.currentScissor=obj else: self.viewer.currentScissor=None # 5- If inheritMaterial needs to do some other stuff. if propname == "inheritMaterial": if propval: # and obj != self.viewer.rootObject: self.viewer.materialEditor.dismiss() self.objMatEdTk.set(0) self.MatEdB1.configure(state='disabled') self.MatEdB2.configure(state='disabled') else: self.MatEdB1.configure(state='normal') self.MatEdB2.configure(state='normal') elif propname == 'scissor': if propval: c = self.viewer.currentCamera w = c.width/4 h = c.height/4 obj.Set( scissor = propval, scissorX = w, scissorY = h, scissorW = 2*w, scissorH = 2*h ) else: obj.Set( scissor = propval) elif propname == 'invertNormals': if propval: obj.invertNormals = True else: obj.invertNormals = False # 6- Calls the redodisplaylist of the viewer and trigger a redraw self.viewer.deleteOpenglList() self.viewer.Redraw() def ObjMatEdFront_cb(self): """start material editor define the diffuse component of the current object""" self.objMatEdTk.set(1) face = GL.GL_FRONT self.viewer.materialEditor.root.title('Front Material Editor') mated = self.viewer.materialEditor mated.show() obj = self.viewer.currentObject mated.setObject(obj, face) #mated.defineMaterial(obj.materials[face].prop, face) def ObjMatEdBack_cb(self): """start material editor define the diffuse component of the current object""" self.objMatEdTk.set(2) face = GL.GL_BACK self.viewer.materialEditor.root.title('Back Material Editor') mated = self.viewer.materialEditor mated.show() obj = self.viewer.currentObject mated.setObject(obj, face) #mated.defineMaterial(obj.materials[face].prop, face) def ObjectDelete(self): """Remove current Object from viewer and make its parent current""" obj = self.viewer.currentObject if obj == self.viewer.rootObject: p = obj else: p = obj.parent self.viewer.RemoveObject(obj) self.viewer.SetCurrentObject(p) def SetFrontPolyMode(self): """Modify the current Object's frontPolyMode""" obj = self.viewer.currentObject if isinstance(obj, Geom): obj.SetFrontPolyMode( self.relabelingCascadeMenus['frontPolyMode'].cascadeVariable.get() ) self.viewer.Redraw() def SetBackPolyMode(self): """Modify the current Object's frontPolyMode""" obj = self.viewer.currentObject if isinstance(obj, Geom): lValue = self.relabelingCascadeMenus['backPolyMode'].cascadeVariable.get() if lValue == GL.GL_FRONT_AND_BACK: obj.frontAndBack = viewerConst.YES obj.SetBackPolyMode( self.relabelingCascadeMenus['frontPolyMode'].cascadeVariable.get() ) else: obj.frontAndBack = viewerConst.NO obj.SetBackPolyMode( lValue ) self.viewer.Redraw() def setPropMode(self, prop, val): """Modify the current Object's prop mode to val """ #print "setPropMode", prop, val.get() obj = self.viewer.currentObject if isinstance(obj, Geom): val = val.get() kw = {} inheritProp = 'inherit' + prop[0].upper() + prop[1:] #print "inheritProp", inheritProp if val == viewerConst.INHERIT: kw[inheritProp] = True else: kw[inheritProp] = False kw[prop] = val obj.Set(**kw) #print prop, getattr(obj, inheritProp), getattr(obj, prop) def reset(self, event): print 'reset' def normalize(self, event): print 'normalize' def center(self, event): print 'center' def TObject(self): self.viewer.BindTrackballToObject(self.viewer.currentObject) def TCamera(self): self.viewer.BindTrackballToCamera(self.viewer.currentCamera) def TClip(self): self.viewer.BindTrackballToClip(self.viewer.currentClip) def TLight(self): self.viewer.BindTrackballToLight(self.viewer.currentLight) def TMap(self): self.viewer.BindTrackballToTexture(self.viewer.currentObject) def Scissor(self): self.viewer.BindTrackballToScissor(self.viewer.currentObject) def PObject(self): """Make the object panel visible""" if hasattr(self, 'CurrentPropPanel') and self.CurrentPropPanel != self.ObjProp: self.CurrentPropPanel.forget() self.CurrentPropPanel = self.ObjProp self.ObjProp.pack(fill=X, expand=1) self.sframe.forget() self.sframe.pack() def PCamera(self): """Make the camera panel visible""" if self.CurrentPropPanel != self.CameraProp: self.CurrentPropPanel.forget() self.CurrentPropPanel = self.CameraProp self.CameraProp.pack(fill=X, ipadx=5, ipady=3, expand=1) self.sframe.forget() self.sframe.pack() def PLight(self): """Make the light panel visible""" if self.CurrentPropPanel != self.LightProp: self.CurrentPropPanel.forget() self.CurrentPropPanel = self.LightProp self.LightProp.pack(fill=X, expand=1) self.sframe.forget() self.sframe.pack() def PClip(self): """Make the clipping planes panel visible""" if self.CurrentPropPanel != self.ClipProp: self.CurrentPropPanel.forget() self.CurrentPropPanel = self.ClipProp self.ClipProp.pack(fill=X, expand=1) self.sframe.forget() self.sframe.pack() def PViews(self): """Make the views planes panel visible""" if self.CurrentPropPanel != self.BookmarksProp: self.CurrentPropPanel.forget() self.CurrentPropPanel = self.BookmarksProp self.BookmarksProp.pack(fill=X, expand=1) self.sframe.forget() self.sframe.pack() def DrawSceneBB_cb(self): """Toggles depthcueing""" camera = self.viewer.currentCamera camera.Set(boundingbox=self.drawSceneBB.get()) self.viewer.Redraw() def ToggleDepth(self): """Toggles depthcueing """ #print "ToggleDepth" camera = self.viewer.currentCamera camera.fog.Set(enabled=self.depthcued.get()) self.viewer.Redraw() def ToggleThumbnail(self): """Toggles drawing thumbnail""" camera = self.viewer.currentCamera camera.Set(drawThumbnail=self.drawThumbnail.get()) self.viewer.Redraw() def showCurveTool(self, event=None): if self.GraphToolpanel.winfo_ismapped()==0: self.GraphToolpanel.deiconify() self.GraphToolpanel.lift() def showSSAOTool(self,event=None): #should show some windowswith ssa optio...and pass the option #pass camera = self.viewer.currentCamera if not hasattr(self,"ssao_options_w"): self.ssao_options_w = Toplevel(self.root) self.ssao_options_w.title("SSAO") #should put here preset, quality ? scale ? #pull-down menu with preset #need an advanced button that will show the advance oiption -> collapsable ? self.ssao_options_w_widget ={} Label(self.ssao_options_w, text="Screen Space Ambient Occlusion").grid(row=0, column=0, columnspan = 2,sticky='w') r=1 #order? for k in camera.SSAO_OPTIONS_ORDER: elem = camera.SSAO_OPTIONS[k] Label(self.ssao_options_w, text=k).grid(row=r, column=0, sticky='w') def updateSSAO_OPTIONS_cb(*args,**kw): self.viewer.Redraw() if k in ["do_noise","only_ssao","use_mask_depth","show_mask_depth", "fog","use_fog","only_depth","mix_depth","negative"]: pw = Tkinter.IntVar() w = Tkinter.Checkbutton(self.ssao_options_w, var=pw,command=updateSSAO_OPTIONS_cb) w.grid(row=r, column=1, columnspan=3) pw.set(camera.SSAO_OPTIONS[k][0]) else : pw = ThumbWheel(self.ssao_options_w, showLabel=1, width=60, height=16, type=elem[3], value=elem[0], callback=updateSSAO_OPTIONS_cb, continuous=True, oneTurn=10.,min=elem[1], wheelPad=2, #labCfg = {'text':'fog end:', 'side':'left'} ) pw.grid(row=r, column=1, columnspan=3) camera.SSAO_OPTIONS[k].append(pw) self.ssao_options_w_widget[k] = pw r+=1 self.ssao_options_w.protocol('WM_DELETE_WINDOW', self.ssao_options_w.withdraw) else : for k in camera.SSAO_OPTIONS: elem = camera.SSAO_OPTIONS[k] self.ssao_options_w_widget[k].set(elem[0]) if len(elem) < 5 : camera.SSAO_OPTIONS[k].append(self.ssao_options_w_widget[k]) self.ssao_options_w.deiconify() def toggleSSAO(self, event=None): camera = self.viewer.currentCamera camera.ssao = self.ssaoTk.get() self.viewer.Redraw() def showHistogram(self): camera = self.viewer.currentCamera im=camera.GrabZBuffer() from PIL import Image #print im.getbands() self.curvetool.histvalues=im.histogram() self.curvetool.drawHistogram() def continuousRamp(self, event=None): camera = self.viewer.currentCamera camera.Set(d1ramp=self.curvetool.get()) self.viewer.Redraw() if self.GraphToolpanel.winfo_ismapped()==1: self.showHistogram() def setNPR_cb(self,event=None): camera = self.viewer.currentCamera camera.Set(d1scale= self.d1scalewheel.get()) self.viewer.Redraw() def toggleOutline(self, event=None): camera = self.viewer.currentCamera camera.Set(contours=self.contourTk.get()) self.viewer.Redraw() def AutoDepthcue(self): """set depthcueing using bounding box """ #print "ViewerGUI.AutoDepthcue" vi = self.viewer vi.currentCamera.AutoDepthCue() vi.Redraw() def SetProjection(self): """Set jitter values for scene anti aliasing""" camera = self.viewer.currentCamera camera.Set(projectionType=self.projType.get()) self.viewer.Redraw() def SetJitter(self): """Set jitter values for scene anti aliasing""" camera = self.viewer.currentCamera camera.Set(antialiased=self.nbJitter.get()) self.viewer.Redraw() def CameraVideoRecorder_cb(self): """Show video recorder GUI.""" camera = self.viewer.currentCamera if camera.videoRecorder: st = camera.videoRecorder.form.root.winfo_ismapped() if st: camera.videoRecorder.close_cb() else: camera.videoRecorder.buildForm() else: filename = "out.mpg" from DejaVu.videoRecorder import Recorder root = camera.master.master.master camera.videoRecorder = Recorder(root, filetypes=[("MPG", ".mpg")], fileName = filename, camera=camera) def SetCurrentCamera(self): """Update GUI for current camera """ c = self.viewer.currentCamera f = self.viewer.currentCamera.fog self.NearFarFog.Set(c.near, c.far, f.start, f.end) if f.enabled: self.depthcued.set(1) else: self.depthcued.set(0) self.projType.set(self.viewer.currentCamera.projectionType) def ToggleLocalViewer(self): """turn local viewer mode on and off""" lm = self.viewer.lightModel lm.Set(localViewer = self.localViewer.get()) self.viewer.Redraw() def ToggleTwoSide(self): """Turn two side polgon on and off""" lm = self.viewer.lightModel lm.Set(twoSide = self.twoSide.get()) self.viewer.Redraw() def LightSelect(self): """Set current Light""" v = self.viewer l = v.lights[self.CurrentLight.get()-1] v.SetCurrentLight( l ) def SetCurrentLight(self, obj): """Update GUI for current light""" v = self.viewer l = v.lights[self.CurrentLight.get()-1] self.lightOnOff.set(l.enabled) self.showLight.set(l.visible) def LightOnOff(self): """turn current light on and off""" v = self.viewer l = v.lights[self.CurrentLight.get()-1] l.Set(enabled=self.lightOnOff.get()) v.Redraw() def LightShow(self): """Mke light source visible""" self.viewer.currentLight.Set(visible=self.showLight.get()) self.viewer.Redraw() def LightDirectional(self): print 'LightDirectional' def LightPositional(self): print 'LightPositional' def LightSpot(self): print 'LightSpot' ################################### # CLIP ################################### def UpdateGuiCP(self, cp, obj): """Update the Clip panel buttons for cp""" if isinstance(obj, Transformable) is False: return v = self.viewer cpn = cp.num clipI = cp in obj.clipPI clip = cp in obj.clipP self.clipvar[cpn][0].set( (clipI or clip) ) # on/off side = max(0, v.currentObject.clipSide[cpn]) self.clipvar[cpn][1].set( side ) # side self.clipvar[cpn][2].set( clipI ) # inherit self.clipvar[cpn][3].set( cp.visible ) # visible if v.currentObject.cap: self.clipvar[cpn][4].set( 1 ) # capped GL else: self.clipvar[cpn][4].set( 0 ) # not capped GL if v.currentObject.capMesh: self.clipvar[cpn][5].set( 1 ) # capped Mesh else: self.clipvar[cpn][5].set( 0 ) # not capped Mesh def SetCurrentClip(self, oldcp): """Update GUI for current Cliping plane""" v = self.viewer cp = v.currentClip self.UpdateGuiCP(cp, v.currentObject) for i in range(6): self.clipw[oldcp.num][i].configure(state=DISABLED) self.clipw[cp.num][i].configure(state=NORMAL) self.CurrentClip.set( cp.num+1 ) def centerClipPlane(self, obj, cp, inh): # compute center of clipped object center = None if inh: # inherited verts = [0,0,0] i = 0 for g in obj.AllObjects(): ve = g.getVertices() if len(ve): verts += numpy.sum(ve, 0)/len(ve) i += 1 center = verts/i else: ve = obj.getVertices() if len(ve): center = numpy.sum(ve, 0)/len(ve) # center clipping plane if center is not None: cp.Set(translation=center) def ClipOnOff(self): """Add this clipping plane to the current object and make it current""" v = self.viewer cp = v.currentClip cpn = cp.num on = self.clipvar[cpn][0].get() obj = self.viewer.currentObject if on: if obj.culling!=GL.GL_NONE or obj.inheritCulling: obj.Set(culling='none', inheritCulling=False, setCurrent=False) if self.clipvar[cpn][1].get(): side=1 else: side = -1 if self.clipvar[cpn][2].get(): inh = True else: inh = False #if self.clipvar[cpn][3].get(): cp.visible=1 #else: cp.visible = 0 # show the plane by default self.clipvar[cpn][3].set(1) cp.visible=1 obj.AddClipPlane( cp, side, inh ) self.centerClipPlane(obj, cp, inh) else: obj.RemoveClipPlane( cp ) if obj != self.viewer.rootObject: self.viewer.objectsNeedingRedo[obj] = None v.Redraw() def ClipSide(self): v = self.viewer cp = v.currentClip obj = self.viewer.currentObject if self.clipvar[cp.num][1].get(): v.currentObject.clipSide[cp.num] = 1 else: v.currentObject.clipSide[cp.num] = -1 if obj != self.viewer.rootObject: self.viewer.objectsNeedingRedo[obj] = None v.Redraw() def ClipInherit(self): v = self.viewer cp = v.currentClip obj = self.viewer.currentObject inh = self.clipvar[cp.num][2].get() if inh: if cp in v.currentObject.clipPI: return if cp in v.currentObject.clipP: obj.clipPI.append(cp) obj.clipP.remove(cp) else: if cp in v.currentObject.clipP: return if cp in v.currentObject.clipPI: obj.clipP.append(cp) obj.clipPI.remove(cp) if obj != self.viewer.rootObject: self.viewer.objectsNeedingRedo[obj] = None self.centerClipPlane(obj, cp, inh) v.Redraw() def ClipVisible(self): v = self.viewer cp = v.currentClip val = self.clipvar[cp.num][3].get() cp.Set(visible= (val!=0)) obj = self.viewer.currentObject if obj != self.viewer.rootObject: self.viewer.objectsNeedingRedo[obj] = None v.Redraw() def ClipCapMesh(self): cp = vi.currentClip obj = vi.currentObject obnOff = self.clipvar[cp.num][5].get() cp.ClipCapMesh(obj, onOff) def ClipCap(self): v = self.viewer cp = v.currentClip obj = self.viewer.currentObject val = self.clipvar[cp.num][4].get() if val: obj.cap = GL.GL_CLIP_PLANE0 + cp.num obj.immediateRendering = 1 else: obj.cap = None obj.immediateRendering = 0 if obj != self.viewer.rootObject: self.viewer.objectsNeedingRedo[obj] = None v.Redraw() def ClipSelect(self): """Set current Clipping plane""" v = self.viewer if v.currentClip: cpn = v.currentClip.num for i in range(6): self.clipw[cpn][i].configure(state=DISABLED) cp = v.clipP[self.CurrentClip.get()-1] v.SetCurrentClip( cp ) def saveViewerState_cb(self, event=None): filename = self.getSaveFileName() if filename: self.viewer.saveViewerState(filename) def saveObjectsStates_cb(self, event=None): filename = self.getSaveFileName() if filename: self.viewer.saveObjectsStates(filename) def saveViewerAndObjectsStates_cb(self, event=None): filename = self.getSaveFileName() if filename: self.viewer.saveViewerAndObjectsStates(filename) def restoreState(self, event=None): filename = self.getLoadFileName() if filename: execfile(filename, {'vi':self.viewer, 'mode':'both'}) self.viewer.Redraw() # added by D. Stoffler, TSRI, Jul 2003 def saveTransformCurrentGeom(self, event=None, askGUI=1): geom = self.viewer.currentObject if askGUI: yesno = tkMessageBox.askokcancel('Saving Transformation', 'Saving matrix for geom "%s"?'%geom.name) if not yesno: return filename = self.getSaveFileName() if filename: self.saveTransformation(filename, geom) def loadTransformCurrentGeom(self, event=None, askGUI=1): geom = self.viewer.currentObject if askGUI: yesno = tkMessageBox.askokcancel('Restoring Transformation', 'Apply matrix on geom "%s"?'%geom.name) if not yesno: return filename = self.getLoadFileName() if filename: self.loadTransformation(filename, geom) def getSaveFileName(self, event=None): file = self.saveFileBrowser.get() return file def getLoadFileName(self, event=None): file = self.openFileBrowser.get() return file def saveTransformation(self, filename, geom): if filename: # FIXME won't work with instance matrices data = geom.GetMatrix(geom) # in relation to root, if called # without arguments, it also adds root transformation data = Numeric.reshape(data, (4,4)) self.lastDir = os.path.split(filename)[0] f = open(filename, 'w') f.writelines('# File saved by DejaVu. Do not modify!\n') f.writelines('import numpy.oldnumeric as Numeric\n') f.writelines('trans = Numeric.array(%s)\n'%list(geom.translation)) f.writelines('rot = Numeric.array(%s).astype("f")\n'%list( geom.rotation)) f.writelines('scale = Numeric.array(%s)\n'%list(geom.scale)) f.close() def loadTransformation(self, filename, geom): if filename: mydict = {} self.lastDir = os.path.split(filename)[0] execfile(filename, globals(), mydict) old = 0 if geom.viewer.redirectTransformToRoot == 1: old = 1 geom.viewer.TransformRootOnly(0) geom.FrameTransform() geom.translation = mydict['trans'] geom.rotation = mydict['rot'] geom.scale = mydict['scale'] geom.viewer.deleteOpenglList() geom.viewer.Redraw() if old == 1: geom.viewer.TransformRootOnly(1) def applyTransformation_cb(self, event=None, askGUI=1): """Apply the current transformation to the coordinates of the currently selected geometry in the viewer.""" geom = self.viewer.currentObject if askGUI: yesno = tkMessageBox.askokcancel('Apply Transformation', 'Apply current transformation on "%s"?'%geom.name) if not yesno: return # build Transformation matrix for geom only # FIXME won't work with instance matrices mat = geom.GetMatrix(root=geom) def applyMat(mat, pt): ptx = mat[0][0]*pt[0]+mat[0][1]*pt[1]+mat[0][2]*pt[2]+mat[0][3] pty = mat[1][0]*pt[0]+mat[1][1]*pt[1]+mat[1][2]*pt[2]+mat[1][3] ptz = mat[2][0]*pt[0]+mat[2][1]*pt[1]+mat[2][2]*pt[2]+mat[2][3] return (ptx, pty, ptz) # compute new coordinates newPts = [] for p in geom.vertexSet.vertices.array: newPts.append( applyMat(mat, p) ) # apply to vertex Set geom.Set(vertices=newPts) geom.ResetTransformation() geom.RedoDisplayList() mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/IndexedGeom.py0000644000175000017500000011301711535247403022436 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by ######################################################################## # # Date: 2000 Authors: Michel F. SANNER, Daniel Stoffler, Guillaume Vareille # # vareille@scripps.edu # sanner@scripps.edu # # The Scripps Research Institute (TSRI) # Molecular Graphics Lab # La Jolla, CA 92037, USA # # Copyright: Michel F. SANNER, Daniel Stoffler, Guillaume Vareille and TSRI # ######################################################################### # # $Header$ # # $Id$ # import numpy.oldnumeric as Numeric import warnings from opengltk.OpenGL import GL from opengltk.extent import _gllib from opengltk.extent.utillib import glDrawIndexedGeom from geomutils.geomalgorithms import TriangleNormals import DejaVu from DejaVu.datamodel import FaceSet from DejaVu.viewerFns import checkKeywords from DejaVu import viewerConst from DejaVu.Geom import Geom class IndexedGeom(Geom): """Geometry specified by a VertexSet and a FaceSet """ keywords = Geom.keywords + [ 'type', 'faces', 'fnormals', 'freshape', ] def __init__(self, name=None, check=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #self.outlList = GL.glGenLists(1) self.numOfHighlightedIndex = 0 if not kw.get('shape'): kw['shape'] = (0,3) # default shape for sphere set self.faceSet = FaceSet( shape= (0,0) ) apply( Geom.__init__, (self, name, check), kw) self._modified = False def getState(self, full=False): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() state = Geom.getState(self, full) if full: state['faces'] = self.getFaces() state['fnormals'] = self.getFNormals() return state def getFaces(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns a handle to the faces array""" if len(self.faceSet.faces.array)== 0: return [] return self.faceSet.faces.array def getFNormals(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """returns a handle to the face normals""" if self.faceSet.normals.status == viewerConst.NONE: self.faceSet.normals.GetProperty() if len(self.faceSet.normals.array) == 0: return [] return self.faceSet.normals.array def splitFacesOnHighlightedVertices(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "splitFacesOnHighlightedVertices", self.name if len(self.highlight) > 0: lFacesWithHighlightedVertices = [] lFacesWithoutHighlightedVertices = [] for face in self.faceSet.faces.array: for lVertexIndex in face: if self.highlight[lVertexIndex]: lFacesWithHighlightedVertices.append(face) break else: # we didn't break lFacesWithoutHighlightedVertices.append(face) lFaces = lFacesWithHighlightedVertices + lFacesWithoutHighlightedVertices self.numOfHighlightedIndex = len(lFacesWithHighlightedVertices) self.faceSet.faces.SetValues(lFaces) else: self.numOfHighlightedIndex = 0 def removeFacesWithoutHighlightedVertices(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() if self.numOfHighlightedIndex > 0: self.Set(faces=self.faceSet.faces.array[:self.numOfHighlightedIndex]) # def removeFacesWithoutHighlightedVertices(self): # if len(self.highlight) > 0: # lFacesWithHighlightedVertices = [] # for face in self.faceSet.faces.array: # for lVertexIndex in face: # if self.highlight[lVertexIndex]: # lFacesWithHighlightedVertices.append(face) # break # self.Set(faces=lFacesWithHighlightedVertices) def _FixedLengthFaces(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """sets self.fixedLength to the number of vertices perface if all faces have the same number of vertices, else self.fixedLength=0. Check if there are negative indices finishing faces lists""" ind = self.faceSet.faces.array min = Numeric.minimum.reduce( Numeric.minimum.reduce (ind) ) if min > -1 and ind.shape[1] < 5: self.fixedLength = ind.shape[1] else: self.fixedLength = False def _PrimitiveType(self, type=None): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the geometric primitives type for indexed geometries Type can be: None, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP GL_TRIANGLES, GL_QUADS, GL_POLYGON, GL_TRIANGLE_FAN """ #print "IndexedGeom._PrimitiveType", self, type # # - GL_POINTS, GL_TRIANGLE_STRIP and GL_QUAD_STRIP are not # considered because they are not indexed geometries # # - GL_LINES, GL_TRIANGLES, GL_QUADS, are NOT pickable but fast # # - GL_LINE_STRIP, GL_LINE_LOOPS, GL_POLYGON, GL_TRIANGLE_FAN # return per primitive picking info # assert type in viewerConst.PRIMITIVES+(None,) if len(self.faceSet)==0: return self._FixedLengthFaces() old = self.primitiveType # no type has been given # so use the most efficient primitive if type is None: if not self.pickableVertices: if self.fixedLength==2: self.primitiveType = GL.GL_LINES elif self.fixedLength==3: self.primitiveType = GL.GL_TRIANGLES elif self.fixedLength==4: self.primitiveType = GL.GL_QUADS else: self.primitiveType = GL.GL_POLYGON self.pickableVertices = True # it will pickable else: if self.fixedLength==2: # MS DEC 02: we make it a line strip so the display list # build by the *DSPL function will let pick parts self.primitiveType = GL.GL_LINE_STRIP elif self.fixedLength==3: self.primitiveType = GL.GL_TRIANGLES elif self.fixedLength==4: self.primitiveType = GL.GL_QUADS else: self.primitiveType = GL.GL_POLYGON else: # type has been provided if type == GL.GL_LINES: if self.fixedLength==2: self.primitiveType = GL.GL_LINES self.pickableVertices = False else: raise AttributeError('Bad faces for GL.GL_LINES') elif type == GL.GL_TRIANGLES: if self.fixedLength==3: self.primitiveType = GL.GL_TRIANGLES self.pickableVertices = False else: raise AttributeError('Bad faces for GL.GL_TRIANGLES') elif type == GL.GL_QUADS: if self.fixedLength==4: self.primitiveType = GL.GL_QUADS self.pickableVertices = False else: raise AttributeError('Bad faces for GL.GL_QUADS') elif type == GL.GL_TRIANGLE_FAN: self.primitiveType = GL.GL_QUADS self.pickableVertices = True else: self.primitiveType = type self.pickableVertices = True if old != self.primitiveType: self.redoDspLst = 1 def Add(self, check=1, redo=1, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """add faces (polygon or lines) to this object """ #print "IndexedGeom.Add" if __debug__: if check: apply( checkKeywords, (self.name,self.keywords), kw) t = kw.get( 'type') f = kw.get( 'faces') fn = kw.get( 'fnormals') if f is not None and len(f): self.redoDspLst = 1 self.faceSet.faces.AddValues( f ) if fn is not None and len(fn): self.redoDspLst = 1 self.faceSet.faces.AddValues(fn) Geom.Add(self, check=0, redo=0, vertices = kw.get( 'vertices'), vnormals = kw.get( 'vnormals'), materials = kw.get( 'materials'), polyFace = kw.get( 'polyFace'), matBind = kw.get( 'matBind'), propName = kw.get( 'propName') ) if f is not None: pf = kw.get( 'polyFace') pn = kw.get( 'propName') mbm = kw.get( 'matBind') self._PrimitiveType(t) self.MaterialBindingMode(pn, face=pf, mode=mbm) if f is not None or fn is not None: if self.shading==GL.GL_FLAT: self.GetNormals() if self.viewer and redo: if self.redoDspLst: self.viewer.objectsNeedingRedo[self] = None # self.RedoDisplayList() def Set(self, check=1, redo=1, updateOwnGui=True, **kw): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """set data for this object: add faces (polygon or lines) to this object check=1 : verify that all the keywords present can be handle by this func redo=1 : append self to viewer.objectsNeedingRedo updateOwnGui=True : allow to update owngui at the end this func """ #print "IndexedPolygons.Set" #import pdb; pdb.set_trace() redoFlags = 0 # Exceptionnaly this has to be before the call to Geom.Set # because we want to override the treatment of it by Geom.Set invertNormals = kw.get('invertNormals') if invertNormals is not None: kw.pop('invertNormals') if self.invertNormals != invertNormals: self.invertNormals = invertNormals redoFlags |= self._redoFlags['redoDisplayListFlag'] if hasattr(self, 'vertexArrayFlag') \ and self.vertexArrayFlag is True \ and len(self.vertexSet.normals.array) > 0: if self.invertNormals: lnormals = -self.vertexSet.normals.array else: lnormals = self.vertexSet.normals.array if hasattr(DejaVu, 'enableVBO') and DejaVu.enableVBO is True: from opengltk.extent import _glextlib _glextlib.glBindBufferARB(_glextlib.GL_ARRAY_BUFFER_ARB, int(self.vertexArrayFlagBufferList[1])) _glextlib.glBufferDataARB(_glextlib.GL_ARRAY_BUFFER_ARB, 4*len(self.vertexSet.normals.array)*len(self.vertexSet.normals.array[0]), lnormals, _glextlib.GL_STATIC_DRAW_ARB) _gllib.glNormalPointer(GL.GL_FLOAT, 0, 0) elif DejaVu.enableVertexArray is True: _gllib.glNormalPointer(GL.GL_FLOAT, 0, lnormals) # Exceptionnaly this has to be before the call to Geom.Set # because we want to complete the treatment of it by Geom.Set highlight = kw.get('highlight', None) redoFlags |= apply( Geom.Set, (self, check, 0), kw) if kw.has_key('faces'): self.numOfHighlightedIndex = 0 self.faceSet.faces.SetValues( [] ) if hasattr(self, 'edges'): del self.edges if hasattr(self, 'faceEdges'): del self.faceEdges t = kw.get( 'type') f = kw.get( 'faces') reshape = kw.get( 'freshape') fn = kw.get( 'fnormals') if not f is None: try: len(f) except TypeError: raise TypeError ("faces should be sequences of integers") if len(f)==1 and len(f[0])==0: # handle [[]] f = [] ind = Numeric.array(f) if len(ind.ravel()) > 0: m = Numeric.minimum.reduce(ind) if m.size > 1: m = min(m) m = max(0, m) if ( m < 0 ): raise ValueError ("vertex index %d out of range" % m) m = Numeric.maximum.reduce(ind) if m.size > 1: m = max(m) if ( m >= len(self.vertexSet) ): raise ValueError ("vertex index %d out of range, max %d" % (m, len(self.vertexSet)-1) ) redoFlags |= self._redoFlags['redoDisplayListFlag'] self.faceSet.faces.SetValues( f, reshape) assert len(self.faceSet.faces.ashape)==2 if highlight is not None: #len(self.highlight) > 0: # the rest of the treatment was done in Geom.Set self.splitFacesOnHighlightedVertices() if not fn is None: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.faceSet.normals.SetValues(fn) if not f is None or t or kw.get( 'pickableVertices'): pf = kw.get( 'polyFace') pn = kw.get( 'propName') mbm = kw.get( 'matBind') self._PrimitiveType(t) self.MaterialBindingMode(pn, face=pf, mode=mbm) if f is not None or fn is not None: if self.shading==GL.GL_FLAT: redoFlags |= self._redoFlags['redoDisplayListFlag'] self.faceSet.normals.PropertyStatus(len(self.faceSet)) if self.lighting: self.GetNormals() if self.faceSet.normals.status < 24: if self.lighting: self.GetNormals() if (f is not None or highlight is not None) and \ hasattr(DejaVu, 'enableVBO') and \ DejaVu.enableVBO is True and \ self.vertexArrayFlag is True and \ hasattr(self, 'faceSet') and \ len(self.faceSet.faces.array) > 0: # faces #print "contiguous", self.faceSet.faces.array.flags.contiguous #if self.faceSet.faces.array.flags.contiguous is False: # self.faceSet.faces.array = numpy.array(self.faceSet.faces.array,copy=1) from opengltk.extent import _glextlib _glextlib.glBindBufferARB(_glextlib.GL_ELEMENT_ARRAY_BUFFER, int(self.vertexArrayFlagBufferList[2])) _glextlib.glBufferDataARB(_glextlib.GL_ELEMENT_ARRAY_BUFFER, 4*len(self.faceSet.faces.array)*len(self.faceSet.faces.array[0]), self.faceSet.faces.array, _glextlib.GL_STATIC_DRAW_ARB) _glextlib.glBindBufferARB(_glextlib.GL_ELEMENT_ARRAY_BUFFER, 0) return self.redoNow(redo, updateOwnGui, redoFlags) def ComputeVertexNormals(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Compute the vertex normals""" v = self.vertexSet.vertices.array f = self.faceSet.faces.array if len(v) > 2 and len(f) > 1: return TriangleNormals( v, f[:,:3], 'PER_VERTEX') else: return None def ComputeFaceNormals(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Compute the face normals""" v = self.vertexSet.vertices.array f = self.faceSet.faces.array if len(v) > 2 and len(f) > 0: return TriangleNormals( v, f[:,:3], 'PER_FACE') else: return None def VertexNormalFunction(self, func=None, args=()): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the function used to compute vertices normals""" if func is None: return self.vertexSet.normals.Compute assert callable(func) self.vertexSet.normals.ComputeFunction( func, args ) def FaceNormalFunction(self, func=None, args=()): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """Set the function used to compute faces normal""" if func is None: return self.faceSet.normals.Compute assert callable(func) self.faceSet.normals.ComputeFunction( func, args ) def DisplayFunction(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """display a set of indexed geometric primitives""" if self.dpyList: # print "DisplayFunction", self.dpyList, self.fullName lDrawOutline = (self.getDrawOutlineMode('front'), self.getDrawOutlineMode('back')) if (lDrawOutline[0] or lDrawOutline[1]) and self.viewer.hasOffsetExt: outl = self.outline if self.GetPolyMode('front') == GL.GL_FILL \ or self.GetPolyMode('back') == GL.GL_FILL: mode = GL.GL_POLYGON_OFFSET_FILL GL.glEnable(mode) self.viewer.polyOffset( outl.factor, outl.unit) Geom.DisplayFunction(self) GL.glDisable(mode) GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE) if not outl.colorAsMaterial: if outl.lighting: GL.glMaterialfv( GL.GL_FRONT_AND_BACK, GL.GL_EMISSION, outl.color ) else: GL.glDisable(GL.GL_LIGHTING) GL.glColor4fv (outl.color) GL.glLineWidth(outl.lineWidth) if lDrawOutline[0] is False or lDrawOutline[1] is False: GL.glEnable(GL.GL_CULL_FACE) if lDrawOutline[0]: GL.glCullFace(GL.GL_BACK) elif lDrawOutline[1]: GL.glCullFace(GL.GL_FRONT) else: GL.glDisable(GL.GL_CULL_FACE) if outl.dpyList: currentcontext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') if currentcontext != outl.dpyList[1]: warnings.warn("""DisplayFunction failed because the current context is the wrong one""") #print "currentcontext != outl.dpyList[1]", currentcontext, outl.dpyList[1] else: #print '#%d'%outl.dpyList[0], currentcontext, "glCallList IndexedGeom" GL.glCallList(outl.dpyList[0]) GL.glEnable(GL.GL_CULL_FACE) GL.glEnable(GL.GL_LIGHTING) else: Geom.DisplayFunction(self) else: Geom.DisplayFunction(self) def Draw(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ draw geom """ #print "IndexedGeom.Draw", self.name if self.vertexArrayFlag is True \ and DejaVu.enableVertexArray is True: if not (hasattr(self.vertexSet, "texCoords") \ and self.vertexSet.texCoords.status >= viewerConst.COMPUTED): return self.drawVertexArray() if len(self.faceSet) and len(self.vertexSet): if self.materials[GL.GL_FRONT] and \ not self.inheritMaterial: mat = self.materials[GL.GL_FRONT] fpProp = [] fpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) fpProp.append(p) fpBind.append(b) fpProp.append(mat.prop[4]) fpBind.append(mat.binding[4]) else: fpProp = None fpBind = None if self.materials[GL.GL_BACK] and \ not self.inheritMaterial: mat = self.materials[GL.GL_BACK] bpProp = [] bpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) bpProp.append(p) bpBind.append(b) bpProp.append(mat.prop[4]) bpBind.append(mat.binding[4]) else: bpProp = None bpBind = None texCoords = None if hasattr(self.vertexSet, "texCoords"): if self.vertexSet.texCoords.status >= viewerConst.COMPUTED: texCoords = self.vertexSet.texCoords.array if self.lighting and self.normals is not None: if self.invertNormals: norms = - self.normals else: norms = self.normals else: norms = None from DejaVu import preventIntelBug_BlackTriangles if preventIntelBug_BlackTriangles: preventIntelBug = 1 else: preventIntelBug = 0 lsharpColorBoundaries = self.getSharpColorBoundaries() if self.disableStencil is True: GL.glDisable(GL.GL_STENCIL_TEST) status = glDrawIndexedGeom( self.primitiveType, self.vertexSet.vertices.array, self.faceSet.faces.array, norms, texCoords, fpProp, bpProp, fpBind, bpBind, self.frontAndBack, 1, lsharpColorBoundaries, preventIntelBug, highlight=self.highlight, ) if self.disableStencil is True: GL.glEnable(GL.GL_STENCIL_TEST) return status def drawVertexArray(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() """ drawVertexArray """ #print "drawVertexArray", self.name if hasattr(self, 'faceSet') and len(self.faceSet.faces.array) > 0: # vertices GL.glEnableClientState(GL.GL_VERTEX_ARRAY) # normals if len(self.vertexSet.normals.array) > 0: GL.glEnableClientState(GL.GL_NORMAL_ARRAY) # colors if hasattr(self, 'colorPointerIsOn') and self.colorPointerIsOn is True: GL.glEnableClientState(GL.GL_COLOR_ARRAY) from DejaVu import preventIntelBug_WhiteTriangles if preventIntelBug_WhiteTriangles: GL.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_DIFFUSE) else: GL.glColorMaterial(GL.GL_FRONT_AND_BACK, GL.GL_AMBIENT_AND_DIFFUSE) GL.glEnable( GL.GL_COLOR_MATERIAL ) if DejaVu.enableVBO is True: from opengltk.extent import _glextlib # vertices _glextlib.glBindBufferARB(_glextlib.GL_ARRAY_BUFFER_ARB, int(self.vertexArrayFlagBufferList[0])) _gllib.glVertexPointer(len(self.vertexSet.vertices.array[0]), GL.GL_FLOAT, 0, 0) # normals if len(self.vertexSet.normals.array) > 0: _glextlib.glBindBufferARB(_glextlib.GL_ARRAY_BUFFER_ARB, int(self.vertexArrayFlagBufferList[1])) _gllib.glNormalPointer(GL.GL_FLOAT, 0, 0) # colors if hasattr(self, 'colorPointerIsOn') and self.colorPointerIsOn is True: _glextlib.glBindBufferARB(_glextlib.GL_ARRAY_BUFFER_ARB, int(self.vertexArrayFlagBufferList[3])) _gllib.glColorPointer(4, GL.GL_FLOAT, 0, 0) else: # vertices _gllib.glVertexPointer(len(self.vertexSet.vertices.array[0]), GL.GL_FLOAT, 0, self.vertexSet.vertices.array) # normals if len(self.vertexSet.normals.array) > 0: _gllib.glNormalPointer(GL.GL_FLOAT, 0, self.vertexSet.normals.array) # colors if hasattr(self, 'colorPointerIsOn') and self.colorPointerIsOn is True: _gllib.glColorPointer(4, GL.GL_FLOAT, 0, self.colorArray) # Draw faces if self.primitiveType == GL.GL_LINE_STRIP: lPrimitiveType = GL.GL_LINES elif self.primitiveType == GL.GL_TRIANGLES: #print "triangles' length:", len(self.faceSet.faces.array[0]) lPrimitiveType = GL.GL_TRIANGLES elif self.primitiveType == GL.GL_QUADS: #print "quads' length:", len(self.faceSet.faces.array[0]) lPrimitiveType = GL.GL_QUADS else: #print "what's that ?" , self.primitiveType lPrimitiveType = self.primitiveType lNumOfNonHighlightedIndices = len(self.faceSet.faces.array) - self.numOfHighlightedIndex if DejaVu.enableVBO is True: _glextlib.glBindBufferARB(_glextlib.GL_ELEMENT_ARRAY_BUFFER, int(self.vertexArrayFlagBufferList[2])) #this protect from unexplained segfault if self.disableStencil is False and self.numOfHighlightedIndex > 0: # highlighted GL.glStencilFunc(GL.GL_ALWAYS, 1, 1) _gllib.glDrawElements(lPrimitiveType, self.numOfHighlightedIndex*len(self.faceSet.faces.array[0]), GL.GL_UNSIGNED_INT, 0 ) GL.glStencilFunc(GL.GL_ALWAYS, 0, 1) # non highlighted _gllib.glDrawElements(lPrimitiveType, lNumOfNonHighlightedIndices * len(self.faceSet.faces.array[0]), GL.GL_UNSIGNED_INT, self.numOfHighlightedIndex * len(self.faceSet.faces.array[0]) * 4 ) else: _gllib.glDrawElements(lPrimitiveType, len(self.faceSet.faces.array)*len(self.faceSet.faces.array[0]), GL.GL_UNSIGNED_INT, 0 ) _glextlib.glBindBufferARB(_glextlib.GL_ELEMENT_ARRAY_BUFFER, 0 ) #this protect from unexplained segfault else: if self.disableStencil is False and self.numOfHighlightedIndex > 0: # highlighted GL.glStencilFunc(GL.GL_ALWAYS, 1, 1) _gllib.glDrawElements(lPrimitiveType, self.numOfHighlightedIndex*len(self.faceSet.faces.array[0]), GL.GL_UNSIGNED_INT, self.faceSet.faces.array ) GL.glStencilFunc(GL.GL_ALWAYS, 0, 1) # non highlighted _gllib.glDrawElements(lPrimitiveType, lNumOfNonHighlightedIndices * len(self.faceSet.faces.array[0]), GL.GL_UNSIGNED_INT, self.faceSet.faces.array[self.numOfHighlightedIndex: ] ) else: _gllib.glDrawElements(lPrimitiveType, len(self.faceSet.faces.array)*len(self.faceSet.faces.array[0]), GL.GL_UNSIGNED_INT, self.faceSet.faces.array ) if hasattr(self, 'colorPointerIsOn') and self.colorPointerIsOn is True: GL.glDisable( GL.GL_COLOR_MATERIAL ) GL.glDisableClientState(GL.GL_COLOR_ARRAY) if len(self.vertexSet.normals.array) > 0: GL.glDisableClientState(GL.GL_NORMAL_ARRAY) GL.glDisableClientState(GL.GL_VERTEX_ARRAY) return 1 def RedoDisplayList(self): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "IndexedGeom.RedoDisplayList", self.name ## if __debug__: ## print 'IndexedGeom RedoDisplayList for', self.fullName Geom.RedoDisplayList(self) if len(self.faceSet) and len(self.vertexSet) \ and ( self.primitiveType == GL.GL_TRIANGLES \ or self.primitiveType == GL.GL_QUADS \ or self.primitiveType == GL.GL_POLYGON): # we always build this, that way we don't have to built on demand outl = self.outline if outl.colorAsMaterial: if self.materials[GL.GL_FRONT] and \ not self.inheritMaterial: mat = self.materials[GL.GL_FRONT] fpProp = [] fpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) fpProp.append(p) fpBind.append(b) fpProp.append(mat.prop[4]) fpBind.append(mat.binding[4]) else: fpProp = None fpBind = None if self.materials[GL.GL_BACK] and \ not self.inheritMaterial: mat = self.materials[GL.GL_BACK] bpProp = [] bpBind = [] for propInd in range(4): b, p = mat.GetProperty(propInd) bpProp.append(p) bpBind.append(b) bpProp.append(mat.prop[4]) bpBind.append(mat.binding[4]) else: bpProp = None bpBind = None else: fpProp = bpProp = fpBind = bpBind = None texCoords = None if outl.lighting: norms = self.normals else: norms = None # WARNING: if texture, fpProp, bpProp, fpBind, bpBind, # are not passed (either None or arrays) we get a segmentation # fault if the surface has many colors (i.e. color MSMS by atom # type and dispaly outline seg faults) # calling with too many arguments segaults too # just add None, None, None, None, after the line with colors if hasattr(outl, 'dpyList') and outl.dpyList is not None: lNewList = outl.dpyList[0] else: lNewList = GL.glGenLists(1) self.viewer.deleteOpenglList() #print "lNewList IndexedGeom.RedoDisplayList", lNewList, self.name lCurrentContext = self.viewer.currentCamera.tk.call(self.viewer.currentCamera._w, 'contexttag') outl.dpyList = ( lNewList, lCurrentContext) GL.glNewList(outl.dpyList[0], GL.GL_COMPILE) #print '+%d'%outl.dpyList[0], lCurrentContext, "glNewList IndexedGeom" status=glDrawIndexedGeom( GL.GL_TRIANGLES, self.vertexSet.vertices.array, self.faceSet.faces.array, norms, texCoords, fpProp, bpProp, fpBind, bpBind, self.frontAndBack, 1) # 1 means use diffuse component if no lighting #print '*%d'%GL.glGetIntegerv(GL.GL_LIST_INDEX), "glEndList IndexedGeom" GL.glEndList() if not status: #print '-%d'%outl.dpyList[0], "glDeleteLists IndexedGeom" GL.glDeleteLists(outl.dpyList[0], 1) outl.dpyList = None def _setTransparent(self, val): if __debug__: if hasattr(DejaVu, 'functionName'): DejaVu.functionName() #print "IndexedGeom._setTransparent", self.name, val t1 = self.materials[GL.GL_FRONT].fixOpacity() t2 = self.materials[GL.GL_BACK].fixOpacity() lDetectedTransparency = t1 or t2 if val == 'implicit': val = lDetectedTransparency \ or ( (self.getDrawOutlineMode('front') is True or \ self.getDrawOutlineMode('back') is True) and self.outline.color[3]<1.0) if val is True: val = 1 elif val is False: val = 0 assert val in [0,1], "only 0 or 1 are possible" self.transparent = val if self.viewer: if val in (1, True): for c in self.viewer.cameras: c.addButtonUpCB(self.sortPoly_cb) else: for c in self.viewer.cameras: if self.sortPoly_cb in c.onButtonUpCBlist: c.delButtonUpCB(self.sortPoly_cb) return self._redoFlags['redoDisplayListFlag'] | self._redoFlags['redoViewerDisplayListFlag'] # if container we force rebuilding main dpyList def buildEdgeList(self): """ builds and returns a list of edges at pairs of vertex indices also return a dict with key face and value list of edge indices """ edges = [] edgeKey = {} en = 0 faces = self.getFaces() for f in faces: s1,s2,s3 = f if s1

Example 1: Getting started

In the following we will assume that you have are running Python1.5.2 and that you can import OpenGL (which implies Tkinter), the Numeric extension and also DejaVu, the viewer module itself. The word xxx-"object" refers to an instance of the class xxx.  For the code for this example, see Example1.py.

Let's first import the viewer module from the DejaVu application

>>> from DejaVu import Viewer
All right, so let's instantiate our first viewer:
>>> MyViewer = Viewer()
This command creates a viewer with a first camera (3D window) that was created with double buffering and a z-buffer by default. A viewer can have several cameras allowing the user to look at the scene from several view points.
It is a good idea to use a non trivial name for the viewer (not v since you are very likely to use v to refer to a list of vertices in which case you would loose the handle to your viewer). Of course you can use a simpler alias if you do not want to type in the viewer's whole name:
>>> v1 = MyViewer
After issuing this command you should have the following windows on your screen:
The viewer's GUI, and the first camera called camera 0.

The GUI presents a row of buttons under Transform which allow the user to direct transformations to the current Object, the current Camera, the current Clipping plane, the current Light or the current Texture. Normally  "Object" is selected (I call transformation a rotation, translation or scale operation). This means that the callback functions of the camera's trackball are bound to the functions transforming the current object's position.
Below this set of  buttons we have the object list that currently contains only one object called "root".  root  is highlighted which means it is the current object. This "root" object is protected against deletion and is a place holder for the world transformation. All objects added to this viewer will be children of "root" or one of its children and they all will inherit root's transformation matrix. 3D transformation inheritance makes all children of the current object undergo the same transformations as the current object.  This can be changed programmatically.(see Reference Manual)

Now let's display a bunch of lines. To do this we need 3D coordinates:

>>> coords = [ [0.,0.,0.], [1.,1.,0.], [0.,1.,0.], [1.,0.,0.] ]
an array of indices telling which vertices are to be connected by lines:
(each entry represents a line between two points whose indices in the coords array are given)

>>> indices = [[0,1], [2,3],[0,2],[2,1],[1,3],[3,0]]

Alternatively, the lines could be specified where each list represents a line through the points whose indices are given. The value -1 terminates the line. The first two entries draw the diagonals and the third the box itself:

>>> indices = [[0,1, -1, 0,0], [2,3,-1,0,0], [0,2,1,3,0]]
and an optional array of materials. Here the tuples represent RGB values:
>>> materials = ( (1.,1.,1.,1.), (1.,0.,0.,1.), (0.,1.,0.,1.), (0.,0.,1.,1.) )
We create a geometry object of type IndexedPolylines:
>>> from DejaVu import IndexedPolylines
>>> cross = IndexedPolylines.IndexedPolylines('MyFirstObject')
We add the vertices, lines and materials to that object:
>>> cross.Set(vertices=coords, faces=indices, materials = materials )
and we add the geometry to the viewer:
>>> MyViewer.AddObject(cross)
to see the object, we need to redraw the scene:
>>> MyViewer.Redraw()
Now the object listbox should have one more line "~MyFirstObject". The ~ is used to visualize the hierarchy. By default, AddObject makes the new object the child of root.  This can be changed programmatically (see Reference Manual). In the camera you should see a square with four vertices colored white, red, green and blue. You can use the mouse to transform this object:
Mouse default bindings
Middle-button rotation
Right-button XY-translation
Shift + Middle-button scale
Shift + Right-button Z-translation

Because of the perspective, the Z-translation looks like a scaling operation, but it is not. You can tell the difference by doing a Z-translation away from you. You will see the object fade in the fog ...!

Now try to hit the Reset button in the GUI. The object should return to its initial position. What you do here is to reset the current object's transformation matrix.(See Reference Manual for more details.)

If you hit the Normalize button, the square will be scaled to fill out the camera. What happens here is that the bounding box of the scene is computed and then the root object is transformed to fit the bounding box into the camera.

Notice that when you rotate, the square rotates about its lower left corner (the white vertex). Try hitting the Center button and do a rotation. The object now rotates about its center. What happens here is that the center of the scene's bounding box is computed and this point is set as the current object's rotation center. You can set the rotation center of the current object by picking on any vertex in the scene while holding down the Shift key.
 

Shift + Left-button set rotation center to picked vertex
The Reset, Normalize and Center functions are also bound by default to the 'r', 'n' and 'c' keyboard keys (also to the 'R', 'N' and 'C' keys).

Up to now the current object was always the "root". Therefore, all transformations were applied to "root" and the square moved because it is a child of root and thus inherits its transformations.

You can change the current object either by selecting its name in the object list or by picking its graphical representation with the mouse in the camera. Picking in the camera not on an object makes the root the current object. (Also, an object can be made the current object programmatically which is described in the Reference Manual.)
 

Left-button selection picking
Using the left mouse button you can select an object (i.e. make it the current object). Try picking on the square. If picking was successful, the Object browser in the GUI should now highlight the object "~cross". Any rotation, translation or scale operation will now apply to this object and its children but won't affect its siblings.

The Properties Panel appears below the Reset, Norm. and Center buttons.  This part of the GUI allows the user to interactively change the properties of the current object, camera, any Clipping planes and any of the lights present.  Selecting Object, Camera, Clip or Light button causes the appropriate submenu to be displayed at the bottom of the GUI.

By default, the Object submenu is displayed. The Object submenu has 3 checkbuttons: Show Object lets you display or hide the current object,( it has no effect if the current object is root) and the Edit Object Material button lets you change the color, value and surface properties of the current object.

Set the current object to "~MyFirstObject" and toggle the Show Object checkbutton.  The box should appear and disappear in the Camera 0.

Click on the Edit Object Material checkbutton.  Controls are displayed which allow you to change the color, value and other properties of the materials used to display the current object, "~MyFirstObject."   (Example Two below shows you more about changing the materials of the current object.)
Click on this button again to close this portion of the GUI.  (It is not possible to change the properties of the root's materials)

Next is the Delete Object button.  If you press this button, the current object will be deleted and removed from the viewer.  Try it.  The box should disappear from Camera 0. To restore it, you must again add it to your viewer.

>>> MyViewer.AddObject(cross)

to see the object, we need to redraw the scene:

>>> MyViewer.Redraw()

The LineWidth and PointWidth Sliders allow you to change these properties of the current object if it is possible.
Make "~MyFirstObject" the current object and try dragging the small blue triangle above the slider. You should see the line widths change in Camera 0.

The last four buttons allow you to make choices about how the Front and Back views of the current object are displayed,  what kind of shading is used and what kind of culling is done on it.  These are illustrated with the third example below.

Up to now we have transformed geometries, but you can also transform the camera position or the clipping planes.
Let's first name a clipping plane:
NOTE:You must make ~MyFirstObject the current object by selecting it in the ViewerGUI or by clicking and you should increase the size of "cross" with Shift-Middle Mouse Button before starting this section.
 

>>> cl = MyViewer.clipP[0]
This a handle to the first clipping plane. By default this plane has equation x=0. The number of clipping planes available depends on your hardware. The OpenGL specifications speak about 6 or more such planes. When a viewer gets instantiated, it finds out how many such planes your OpenGL implementation provides and creates an array of clipping planes for the viewer (MyViewer.clipP).

Now we can add this clipping plane to our object, meaning this object will be clipped by the plane .  MAKE cross the current object for the next section, either by selecting in the ViewerGUI or by clicking on it in the camera. (HINT: you may want to increase the size of "cross" with Shift-Middle Mouse Button before starting this section)

>>> cross.AddClipPlane(cl)
To activate and display this plane,  select the Clip button in the Properties Panel.  This will show the Clip Properties submenu.  Click on row 1 button under on heading. This makes this clipping plane interact with the current object, cross.  To display the clipping plane, click on row 1 button under the disp. (display)  heading.  Notice that as you translate the square, it gets clipped when it moves into the left half of the camera.  If you toggle the button in row 1 under the side heading, this will change.  You can add other clipping planes using this submenu.  First, be sure that ~MyFirstObject is the current object.  Then clipping planes are made to slice it by turning on the buttons in the first column.  The side buttons toggle which part of the clipped object is displayed.
#Make the clipping plane visible
>>> cl.Set(visible=1)
# translate it to the right
>>> cl.ConcatTranslation( (0.5, 0., 0.) )
 

When you bind clipping planes to an object, you can specify whether or not it should clip this object's children using the inh buttons.

We can now transform the clipping plane either by picking on it (left mouse button) or by selection (Transform Clip) in the GUI.
As you rotate the plane you will see that is is actually a square with diagonals. Translations are always done perpendicular to the clipping plane. Scale only changes the geometry representing the clipping plane which is infinite .  Of course, the plane can be made invisible by toggling the disp button. The reset button in the GUI will reset the clipping plane's transformation if the Clip button under Transform is on.

Note that when you move the "root" object or the "~MyFirstObject" object, the clipping plane doesn't move. this is because it doesn't inherit transformations. If you want to look at how it clips your geometry from somewhere else you'll have to transform the camera's position. You can do this either by double clicking (left mouse button) on the camera's background or by selecting "Transform Camera" in the GUI.
 
 

Double Left-button transform camera
 Now when you rotate the relative position of the plane, the object doesn't change. You look at it from somewhere else.
 
  mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/images_fm.jpg0000644000175000017500000017064210504574206024703 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( uf:\kgnkx 6X(fMNk+ ]{t?QiJ[>[ܲ<^7ż w[{W奉TX(!98Ӌ?6?} ^:A_{2|Υ"xnx8ocJ?*n(ۃqvlYgA lv~&'-eA%x0qӓ_{1rC|Dxp;>7Ooo#\#c ϥ샮=`k}/dq_F/|Υ"xnx8ocJ']?XYgA lčh>gd9|Υ"xnx8ocJ']?XYgA lčh>gd9|Υ"xnx8ocJ']?XYgA lčh>gd9|Υ"xnx8ocJ']?XYgA lčh>gd9|Υ"xnx8ocJlu3|5nys'G@N N>R1+~$l~DuǬ~= #c ϥ샮=`kR̭ʗatF!5mR`[q ^IGS']?XYgA lčh>geF\/9N"xnx8ocJ']?XYgA lčh>gf_3o/}vG҆-wm}+~$l~DuǬ~= #c ϥ샮=`k>_3o/}vG҆-wm}+~$l~DuǬ~= #c ϥ샮=`k>_3o/}vG҆-wm}+{o$m#Ϣ*dqa!ّ&0q]z6Oq}×ɭx9#!mn pGOo/}vGҹqgc 3h_/1.3L9e}/dq_F 9|Υ"xnx8ocJS;2=:B京3kp'j[ rčh>geמ[YY%&6fxSH;80>}v?m^^4[[X^?3I`V'z ax$c^%K[R$֝Š(EPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^WA:תWE?OTs1Ư~ӌZ\^^#%/2:0=;9&qg8Gק?xI7mk*H mN8n|G*_)gvӮP:vp+Nſy ݭ7q޹|D̊E6#X5-M|,2͖$dtJnAER(((((qܜv53J~szұs&'?=CS?N\_i$18V`zp3m(rg 4~"M%Q.$zqy`[7?m_ }ne>WAxt`[p:-nF<р?Ym?t]/W(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQE-[؅Gvr({g=֫H?"^]}GZ?ßꃪ9+Fϥfk# CLF#9vy x~K8L}=_"g?xE)x~K8L}=F.8r_ˌ. :tޛmpqFFA9ar#0_[J$`RUmS`J|=*{ hǰ]Nqwᡜ~C!Nqwᡜ~C=exA[m4u'#G`9cC9{'鏸CC9{'鏸{(qg|!㓜]hg=/d1|!㓜]hg=/d1mm{ky}Z|yrhǰ]Nqwᡜ~C!Nqwᡜ~C={8 >.43q{>.43q{罢gvpG99߆sN:q|99߆sN:q|Q.?~5{BJ8{υuss,kOl{縢gvpG99߆sN:q|;++\h7c?!ΐPLαTH,>ց4M;%C2*FnUb@$v`J={I/4pdž""P/d']'~kg83xL==iR5,YU$rE>$B8x͚FWxdI:uɡO/--JVY&eB~(’9퐹SA^ycρc>RcG"qI 31/nAHǀ:0K-ke2EVC ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( @ȵ׿CQֽRă/P8-u=Gu#9~:ǁz}OCxW3_"g?xՅ? rvSk1$u?K^,ab~1sz$'"V~"ڻP)#,H1<`t A^eiQ-sӥv'j@ 8g5zexDMʭ? XlnHjr~\B]9*2c qJ۠5Zvu a u]cmˌdnuΰA{{=DsN؝'d*(q -&PmgK+KȎ ;Kڬ#eݗjJK y.]X`WB4]ʝnᑮu bX4tFr!f<~R#iw^Yry ev0?(`:{Ys;ZGlg*Tb( *V&Du KL×Db ~fs_Gӭt f$r»vadVp3TX٤ eN0%rrC¿hѮ`*0v'PHלU_%{d8kKfd仁AsW#JV׾r1ihn&ɺ:!Rs}hsnu6f<5C厅DGc~q[ΣTEpמXX_Լ~>R-KQZ6rOrW e:T#b=̤ #؏#hΥ =kg$c^%K[CWN{=:˱"52#[?۶Qu]5^+ZEfnGE۶QuY{^?tVg]qQg¹^ښu14mCźcmaw=8U]K\~KjS yY =WKυ_/O _V>[skAGUGE8yYms&sP:T18SG?fVٌuCEˣmp҉DN:܀@bbxe<JP>[skAuEE(yYcF<[yn>V}W~sӎEUԵ.1tzZߕ ?+8O#êΣ^Ѽ9 >+YgUu#gУutIoplqk1*(%r 7 V+Ji%+}GEI=ԟZ~-iL0G+;dsVVxP" j=O'kQυ_QjVDүF Rڶs. @7[A+(gxj}9M5ދmnfQυ_5>n`"P4S6=խ&KEm1G98WOۿw|{=kC/O _G^>99NMܼF*nV٭4n#..ၼ-?|-% U1yTE(ͻKMs1uWռ]ݤ4ah%etzZߕ ?+rO>خ_弭{_Z֬3*3? GQY»?|-zZߕ % ࣈrsVekk{mCaop6m1An8 FhIα-6vibr!zƟe KHBU%~7>ez1?A'zv aJP%);ݫ|uV^!txHXx~Uwr؋lQ8Fҷ|-G^_ 'ٳ2׭Kxt`[p:-nMxKwBUz?W~s5{m߉2tfms}$u[6Zׅ[WH =t8޶hTdn_SBTI]K_4kmdrcX1WE]fCc'%if3A[޶hBj-9kLFU#8J+uyknrVjR[_xbKa2 - mIڏU(|1yDЉ ڤ6]UrO>خ_弭{е Oھ#1[- N\-Z J|{wf3rƥG*rN2G}kU9RSTTaRR$\VhAXm#} yN܂ڹ7zƤ]米vy[sd궚Tp$ 旻m9OOi=[d78(m$#pێ;|1xʒb[g'6E\3ں(NݻaM7]񖳥k7V nۘ|' #jt-FUѭntݺ\L19=;֍rEZgJ0%+]ݻٻk']n4OP-mqOӵhDa4rUlFsWOsмeͽ߄/%ݺRS HcެxZGmcR&Hg$nxzꨥ>[skȧ:j-15l7D\1A>w0ܪ;V7&Z$ٟ_gn_f|x9eE7Y.b#^&OQEhqQ@Q@Q@Q@Q@y_^p?Zߋz^^WA:֑?TQ_?3KSǧ1<^~ן{jŸ† (AEPEPEPEP&!I?޹0?Jqk-e3jf#ߵ kA1#,IH'm2r}N PKXO :ki,B gLAWF18-2KJTXm_byZ8䌑qPԚQ,wok+1^H<&hFeo9\Yoiv 8e0b^@섨,.ขhnX< >b'Ҁ8n/ʷ\G7fCdsfSˑUFAsbmȈ8W^(-m.k]6 ɷy@$9; 鶗x&ڣBo&7EϰvQ pir]Cu6y1W% xа026d<W^Vm[Bk?$qؑBZ&#,sF;'}MOEfj^ 4)srhH77L9*?Q;%q3=k8J/&TUߗEQҿ'ghҿ'gj=_q#zNNj+̽EQҿ'ghҿ'gh5z^mi_4mi_4{os,^njpSsề&W[ɸ}1ϣޱVd!8iP¸χ7xVǡRNA?AJy~8zQHǀ:0K-kZ'ASht'E(5H' +g=:w'Mz5=JַiYӿ)?ƏH? Y{^?tV|z4ZQnP'<Ш%XӜ>%`*H +#'.dfՐ.s;RE+,nA&FmoJzeO:i*Ԍeu'ʽt3zŏv&}LIwn;7 2vOn6d6VhS%[mFAcʍE7^}zv\&ogsw56V(2FJןf6̆@pWp#/cXZh?VeίxnWt[i'*T0G3-V~1) 8$@xC+yYn"iHJ.rHPH9>a&dG ^I86$sDWS Q@Q@y_^p?Zߋz^^WA:֑?TQ_?3KSǧ1<^~θu5=A!|$OPrEhgfajxf?<~O\"ԋ:ʐ7#]+XS|潯5،$0vߑN]7!ygngvqcUhޛS6r$.ݏjܭqyJAg""Z<Y'|pWf~Ώy^ꨗ:<(7-kd guuC,A1;^Q'$Ϲ(?:?R{`Ɛv4;Ȓ]:$Ie #F=a"BZmsǕZ԰ִmVNkkU-+pGoϵ?kFa<̯moл, UR Ӂ^-\ϩ MJ9x|ʱ1Ÿ0e$G'ZM}S^_koN<5u?A|{C5}Cŗִ(qa,QZ V-%a1ćw۴F@ϟE5 w>4gƱk *R#&>wP\U*zH .>kgR{{[u+kxdJXR%G=N)h/gYJT*(]F]:6{|t rW0zuܷ|1m89͚"oc +8VHzocK Hqd lYsA =.i8vߵV$`,@>^ZM?wyQHq^i&s2G46!C+ڕ xt8W-Y^jnҮg,leyDu0>c@,Sh^˴V \b3, 6#$EZ_NUSt+Ӿujpi\Qث:4RjZFj[+\8'<{W I^3g`ڔXIך"җPMUP[[Cڣ̥2H; rr_PѼiqe|ϲ6>^,vf<:PgϟE5KVVthi[$θG_O Z:-EcVT?.NXv&y hn&l:!Rsey2H?tuMφ_^}o&>w'tGG\nun?Lsu~ Feax$c^%K[_ `+!Q@Q@~0_ YEIbn : t5 T6U.g]v`)yNs-饊8$m/ŝq(B)Y6%ҵM*}/SsG֫*#( q8#p}:!楢ᗷoMiF%Wv Ԍ'תuKkf4ҫ/=KE'qv>}E]Yo<ۇI N35?u]wWiwq%&@@,0I8観 ekwNҪm}ziv].H>m`i*%g ld=bh7";m>h^+UnF,۽cpz` Q+Y~=/f*Zߧ7 ojlZZM/QKe$rJge#q ܿud^ H?m\.ÜYpŲ~\muPZ߿V~U\V}z.49;DOi.YzWƮgP.7^G=KCuq[Rm"7}2#Ȫx^)gD%Y[TPT/G*Zsn 'ӷ<<'˴wm'ӷ<<'˴wmB}HEh.- &mC 6 tҶvzf8(KN`XI9*ZuaxkBKgh%~awn O$ O5DtM;T6'y{z}6Vg~vڎQEnus8)GKSߡl~D-s#Dz^MͰ۝&ǥ(LB=-=!)$ O t Ět27$V*Ž@[MgkN8"/Z$ݓ0)*RIWo$aiq77x< [x/TUil(݀qucupztN+\[CsFN9&/ZلԋJQjheGr+)ã[LҴlnZGIfw.8;#1YöZV[;]^24,Htd:Y7~m}gn3>V1sU#ҤQO|76lwnsلԍIO2CI,.ɫ X@O\dʗ2z"FZҵ6:ԪA:8#]k5N(hƍ ս\Z\E<DհppGAR_ѯnWwGf=4q*Sw^z4QE30((((( ޸;$y>dӴ68;vK/MѭO؆&r~ޭ O`+:us- ,]ObrO T,~!xζK#_\[ۤ̓t)o$)LsZy;W~+F< |`gxS]NnnH^ַ<ݻΧ{%csim@iXZevv~[ǝldy9=IuQ>e'VH*sq[&ݗ< [we%Dcr}8 FP+gҧJTeRmӱi~Fk?Y  $rOp(<=6rҪ  8wE3/i}t6Fk}?b˕zX3=̷xH4woy;W~j(ٚ\6JKl{8+F< |`gxSPxV-_Vi/Fʻ䕵TyԌyUdהuӄ^h _YBnjK{y/i>B̏mOIIWRoaЭޡ}pmz(M?XŶm 1 `q}1SMBWͫ$LOi55R&@#?.1Ԏ&ci\\پuo{H$:d"Q?eЫ&wLF>qcG"#[Q^4%6]4/:5uX M"%a3 #RRkѴ-7oi}˽,@zT1/nAN*䖷dEt*(pkuUIs=~M3LѴ,!mb[$I'5³?f_.(t$K@ӔNm_׹SS,:[ |Yq7#Agh|?xz]xlsTqb:[Sp|jDq5MҌڋ]=g/TD[t‚N0Rjލi{M.n?ۜj8-bSvzv9_K<,%;YNAluZo,TD W{&3 &hSVIXsbg5RU$ww^Ѽ~ټ| u gQN\8 @+e rXkU=.mw{vSL,m:+ |X7I'IMdi捨ay7Qgc62<#5QM.mW5W}EUQ@Q@Q@Q@Q@y_^p?Zߋz^^WA:֑?TPOXWןt-%`l5H#y~bBr8ҳ|!=`zy\zs!<^~%_JAW۵{;Oo/?_my?h۷-94i'4B+->9`~Φ;9*6G#z+"6W)d쥶IX*L@-r>T\(,Z5)ISmd4kR£j?eh״( ?='״^?_&*?^?_&{OxY?3ڲ{OxY??ej (£j?eh״( ?='״^?_&*?^?_&{OxY?3ڲ{OxY??ej (£j?eh״( ?='״uޢZjYLcUj^?V| d6sDZo L rsnේ?$O8vwZV_UMcɌΞbc`plGx: 2M}tk qsề&W[ɸ}1ϣJx$c^%K[xt`[p:-nMd-(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQE~$zk9=GuT+ 9Q֭|PuC|!=`zy\zs!<^~%_Jgq̇=ykC+ ֢*QEQEQEQEQEQEQEQEQEQEQEj^?UZg/Ũ'C^aYW* K²"P=E/\Dnun?Lsoȣ_k 2M}ίTw=3#,tZݬ/x ãIJہ~kvk^!lQEd0(((((((((((((((+ 9QֽRă/X8,?K}GZOA gq̇=ykC+ǧ2b_/i(osZ(QEQEQEQEQEQEQEQEQEQEQEU?x-Uj՟ AzeE\z/ @tk qsề&W[ɸ}1ϣ"ma"n|7p:cy79~: Qx ãIJہ~kv1/nAYz̅QEŠ(((((((((((((((ă/X8,?K}GZJ`ȳ.qj?OT7ǧ2b_/_OXWןv?ұj(AEPEPEPEPEPEPEPT Y-Or倍 q7TҠM̪{!^:z?a!R-!pyOه$ͩY[0ps)VԒvVM54:*Mٿ?mVN^Z?e*Mٿ?mQj]9h3?6fɶ7Eww_^V\ZmUMټ},xZwZ?d:/ X6o&3Iv R y*`u>皷m=/?6o*R!Gܿv"ma"n|7p:cy79~4yk>w_{w{=+h_ro+utLcB21n??۳yg"wwL~GFok7ytvS׿,]ֺ~[Esq3aC# p=ϼ%nc4.ޝ$`eU$HKq m.N`QRm$7Vh yqF2rvMt}9Eg{K>ysd`ୣ?WueoF\n$We~}Bo/;;>Ɂ~vl3ݼWK#mg~'3ˎ15[witˈ{n|ywK_\h<(((((+ 9QֽRă/X8,?K}GZOA gq̇=ykC+ǧ2b_/i(osZ(QEQEQEQEQEQEQEQEQEQEQEU?x-Uj՟ AzeE\z/ @tk qsề&W[ɸ}1ϣ"ma"n|7p:cy79~: Qx ãIJہ~kv1/nAYz̅QEŠ(((ѭn5Iu4KXc ןLТ3ogquk( ((((((((((+H?"s=uT+ 9Q֭|PuC|!=`zy\zs!<^~%_Jgq̇=ykC+ ֢*QEQEQEQEQEQEQEQEQEQEQEj^?UZg/Ũ'C^aYW* K²"P=E/\Dnun?Lsoȣ_k 2M}ίTw=3#,tZݬ/x ãIJہ~kvk^!lQEd0(((((((((((((((+ 9QֽRă/X8,?K}GZOA gq̇=ykC+ǧ2b_/i(osZ(QEQEQEQEQEQEQEQEQEQEQEU?x-Uj՟ AzeE\z/ @tk qsề&W[ɸ}1ϣ"ma"n|7p:cy79~: Qx ãIJہ~kv1/nAYz̅QEŠ(((((((((((((((ă/X8,?K}GZJ`ȳ.qj?OT7ǧ2b_/_OXWןv?ұj(AEPEPEPEPEPEPEPEPEPEPEPVUV\Z2t?_Ar Կ+/*SQ5Mφ_^}o&>v:_ц+я~> %Gs<1/nAHǀ:0K-ke2EVC ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( `ȳ.qk+H?"s=u_?TPOXWןv?ұ|!=`zy\zs!<^~%_JƟ†5Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@ZVYqjV_U+=;J7S{YvNgϧ(H@tk qsề&W[ɸ}1ϣ"ma"n|7p:cy79~: Qx ãIJہ~kv1/nAYz̅QEŠ(((((((((((((((ă/X8,?K}GZJ`ȳ.qj?OT7ǧ2b_/_OXWןv?ұj(AEPEPEPEPEPEPEPEPEPEPEPVUV\Z1|.Ϋn#ܭ?ڮjzV2L,mOy@sc<kKvD8eA>puMym VPOQ' y$,mFXFPwt~~לMφ_^}o&>z:&WMφ_^}o&>gW*;xt`[p:-nF<р?Ym?t]5/W (QEQEQEQEQEQEQEQEQEQEQEQEQEQEQExJSxv+{xK vEbyݜ|WN _\GAHmH=cGוEu{J1۷;=F^M,ʿc]W\0̇g$xMƙ{t2CHC3lAU<!=`zy\zs!<^~+nIRU9Rn6NׯNzGY-E]D8q\-?yj?* x|-wggKZB5rForu)9'浗/^w#)wvfxA" 85GAo]$c@0]k?ZB48Ϛ®Qp6ߛOߩaZ]hF #jHl^̑"%E !{KAt$fRe v'E|=|bxĠHG<輋_F"?-`_m'nmoo|] 4D{gEa|S;hdhQH8WaZB4y5,NTI5qyEc,d)fg`3^H{Vf.Y!ev$HaKs{ ޺kxI4($4Q(4&\k[M4>&}_߳E83+`Դ ȡIAKɥ;׍\K" zynun?Lsuc;v8OfMݴѾ%hމ]4i1N`F%Gj-f5hڲmb8$uSHǀ:0K-kfK-t&\<4%kkMtzy.OϞ~/l+}}E$ P[$܎>S[4V 5wkRS&s^;i}xR9cLp Z׽_m'nmoo׉lU}c'P ؞>a\_Bӵ+5gFIRA_CK$SU%)n/ek|gl9_07ٿ3ƹ]?⾅V0j+- ?NkFn֕BW %RmZ߃cxĶ^cy"a(- G)ߵ˳3v1?5QNBC88>澟uS~%n4k (Щܡ2#t:o TIR mY@ 6S:޴hI*\2Ӽ%Ou'ڷN6rº*(Qg-{%[ )ƓP깵o^ӧN;oi-_!7;ccXڇ} NԮfZ[i)%I~WwE')kTkYJTsmqo~Ol߳fc8=׏jRXG,p.~a]UMJ5((IJ +kQVsQ@Q@Q@Q@Q@y_^p?Y~_&8+>e;LN1x ,uVCnp5WJOA_OXWן{ !=`zy\zs!<^~+* ܵ5ViUVSҠYk8Y .%XԶ XpzYX>:ɳ9vFPI{Ʋ#S[傱giچ}egmh/h9B*v H3!;j+όRyʧOmj["F}$A#h&<=_ǭqoy"k=e"ymw(;Wm:ƥoj5-5&KOV*cڧ'pD sa:_ֺ Am{ky}Z|yrƧi:ud6ZhgUut-KU[sX_+)p!{^wuW ksUGkhp" rÃ&xt u_iz5ݤS!C2 d2hF5W+F5W(Z>|:?ιYa螂٥E+qdc4k_OqͲx]l } Z%.t)ٓO1(c0)xQF.^݉H#GBv9`_vCv@WZ>^QAOĢ&kfd>CnRX0+ fx/MӧuK73vr@f+2pB5z=YktM7P{ m/$x\,l9tF*`8+M?kVM?X%Ԣ-[C<ޒxq9䢺кpsi_sề&W[ɸ}1ϣ,/IkXQ-._1DS8緮jptՒ7@Mw.32~`9Ѵy5J).5c|1/nA| 7BbB;X'U)6Î`?{Ua9J-4tq_iY~@;ӿ=G޿~]޿Ӣ`E( <#8 mI}[Eyν*C?$Q !`봃WKZ v14f;urč גx>^W#[[~%m^ߙ]d[W]oh%S"[L_[ۤA4$RX(ev[1i}|f8zckaI'+jsT)f(s(+|MRhB\1.Sm\{:?0~$zg9]:(>H:gq̇=yǰ?ǧ2²ZG#Uj[ifV`߫&(~@OO\ok+Eٱ[/$95_?m?ɴ ֬ ?m?§S4]䴷m6;ƀ5.oCAx+rҶ>v)d8 An2F}>z ynun?Lsu6Ndž, I }XGpcI4F0\I8 #,tZݮP%lQEf0((ASi/"C60A(Ҡg;'fЎ0A`ЊEi}ލ#ZRI?hb{]Nk//I>%OL1 (Vky5 rO$APF2I8[ߛ4kߛ[[=X<5okyI5dIIF7`3G?۵.ǝ7*IR# G'v9MoQMbjWO]? :?=_ܥl e8 EqYzywjo0G鎼訍YY>5EZ/_'b {V 4l e\pz2@,H"yd>_nE_j6iO,þ𭎡p~Omot9*-Sv}su43mR 1^8랆qV'[8cq,ڷ7^SIn%NŌ'8xb=$R1qM@+r_Yk_/W_&{7'Us< p1Z68|˫}e} M^ԓz2e'~1l|92z[%Ì[ '<v4 [ٯ/ͼlϘ- ;''mQCU{_,]i&of>Jtç܋f ͆XxSN Jk#Ps, p,U< ``Z}w?W7;@n.5 FbG`1*Rp'MnQED2Zu-`+30(f`0q8Fyǚ5(.ZDH:$ \A'ue+ 9Qֈ҇GWױt #iz֧,o!hX199^kC|ws]$@$S&x3BzCxVO cߝ#/Am|=bLRe `8V-í"[$4Ӛ먫tiֈTU: )nN.qqpB2J˛>M;3GM#hn:S1񮆊=9V|oS!k:څޢ˷p@ { -KO墋v%ŎX8w5E-XUb+Rn1k+/?^xo_f^OtV)v1aqqZuGY?4=CR߱IqۿbpquN)*c8Τqy?#A֋维y3JF C_%HP0 =+FM9<7O@ 90#{|?q^k[AӴXIRr@p+SO#Jm,rqLΖ1.flݲN[m [ b}CGΗg?~z_{o>zCMAO1S*R?>f6ͻnݹϗڹ?xz+L*q]2:[X|vˁ:m1l6pp } g[MRW׆BQ"RzN@@YsDBVml*9&iͥ-u;K Z]]i e 3&h>|=|vW#b"[iH s/S/JC}<~﹜zt椏SQN][,eE㒹0zA˝E v"^3|C!k:څޢ˷p@ { -KO墋v%ŎX8w5E-XUb+Rn1k+/?^xo_f^OtV)v1aqqZtQ4Krf8ӌMW9#C[-,[-*ryC 4}7}|iFwc9g(Ti%K1JJoh[kl?iGo_wyҜm1Ukơ%ʉ\p鞘?uu }]#1qk@cg;Ѿ\;?پͻ#vݻsc8z֑c}ow U TguQ*P[ asiK3/^m|CbrLPb Gpxמ[VeRLMARԈ tzynun?LsUPBo:-?W|)"=pk׆+cc,E$bg`[$>QQ$c^%K[Zy-nxD,<N |(еJkEep PXqtWvYgk PVf#*G8~Q+fQeu3UNNyɪht/7}RvՖD*w)S(= Z)n߲}k˿g3ns?QBMG-Y*U"S|D_g;o_&[7wcQYMƩws~Ϸr"T(TwʊnhZu}5ޢ8I(,I8t溯kG?_}~F6g8qVF#v㭘bk(ƤQ4ZCw$D*JFp8ľVs lGpxlBME-f8#VsnQ9_ xJ% J{(_]ixY.oyX@jʓQK嶅,:j3-5hnҐXb8u'sM;is~j";ʊn8D},߿yŠ(@(((((+ 9QֽRă/X8,?K}GZOA gq̇=yǰ?ǧ2±Š( ׬_2Z?oFKSPEPEPX,[A4|葢gcI=bǵƕiè,w3wy567lqҹtx%Ѧ->[y$L`u2",N2+&{,>do pR北0>ZY7!T7X7݌^=3[K2n{YL2g+֧ M!Ԥ_Ky36m* Uإ,ŎO$kPnkoܴ:ͅE vFZc|9–9ΊKM%^ ag2sٵO7@1lZYko͡- :7#P3q;C@Q@ hig"zP?P%*G!s9V>]ZfMSY9Cs J4? fK 3FH\2<{ka}7;oyo:#dK &z^lUsڗw99h3Gc6f$ҭ/0 (Eww_iTmQm=/?6o*R!Gܿ̽^y7>ez1?AdK khJHkJ3898rMgQRGѿg$c^%K[CF: %Ƞ*zg=u]S{WJ|O_EfaYmG7]VQYZw-r3N³ڏ n??綣.R!GܿӢb(5,U(,ŎuaõAi^q]A$P %U#xog')(|R/K ahBkymNҊwK.MFl2)d(I_5huwA&dơ(ыAۻo0+E'.G-}:].뱴rt篧K}vOIԵX4#}-S` 9#)&3[-Є+ st-4m|p?#thhLA@s9>g0M'ʹM%ՖQ")r6%R[Uo2c~VK]NG6Ֆ].P9nrօyn/5Mbf^=P@*Knp1֙[/ݎ"k|tXN9-T8˚_[6sʡ5&=c(/ _5R}Fm*gO@/iu0[MSasG2ۛϯ)C2GQE@QEQEQEWEu{^^WAs>Z'3BzCxW әzaXPEU>!" 8ʴmJj\K Z};D" ܂8MۑvWibO&Qs+H󃹐y#x.Nx3MSogKjBηP5Or ;z5IWKml=F~ֱ vq魫"NRMqNe0Adb-~6 S-Mz+=j9t2!I"L#[}¹*=+Vx.ͤ)$pafʹ|<5+{mŵ*ь/ȋ8%3:t}v% nje0[ReCA`v@69 ^(gLtuIp$Fj(HC c'x|(qőYkXy,>nFdp{_^U4o\RK ŴH# *2LU(oyf]寄&\p2~ovu=h]_tywOӶwOv]~w??>gݻYkmv}mg Y_ UKyb9<{W9;@Q\K{32]'>J`h ~]6'ݕH\g=jKqaYn.6#K@G0yuZ$:)AH*"8o%dۿuOh:Mglr6}%qcG3LHǀ:0K-k #,tZݮŗ[QY (((*ASi/"C60A*Q*$f (/HKki'͖yʗclVJrIlSb➏p*H ( ( ( ( ( ( ( ( `ȳ.qkVk"fh:`oF'<\'5 3 Si^xt)Xi'q< NENQ*tey_OXWן{ <q>%Fc<wɮ[ֵm28l7{D<ްX| _˛?U Qլ^{Od("[$`ܨ? ļ.m}q^ ԧ)UWÀp~zպII؊%J)sGz?D)n58-3=Vڬ:*uͼA3r捎Wl++HKhzRn<0R1׽Dd KJt龗 C쪴0poY ߫&(~@OOzZҵ=>5[xN@#I(׵O7a̱[ǀrF!<OC#;6m߉s?m?ɴ ]}oVy >E[hFCH+>(/*ۦևZ )= yv"IR\ޏ{?_6K nM1BzT*qY~"53{ѷ^NTWWVg+B?'XjZwom30SusInΧeo ?ȣPAG؉Vt\WF:{E_̾e>}knݷ;:g9\퟉ux%nrȨҲc։Um~YI/w}R޿#< 2M}w0ܪ;RU"ԩB~ju4W x]ԮFq3.wٻ玟].EE/{mS3F4kmdrcX1WE]fCc'%if3A[ޅZ.KeS.SRK[{Ӳ4W+j%/4 rXQy䞽-gJn,­V"^>?|-[*ek~W(U(^> Epŧd+)ZU㾀2-FAwҍ7Vj עh.ꈺk32I?zZߕ O46XHɼiܣ#J t'̨Ɓ..%%fT^9+s=jxtм6R(fBIVwGb r.e=sjl.0E#H)s0-*0,\͵[ ԭMM؛u1R߼M} i쿲+ek~W+vkcb2y^G~ˍ~yv3QdMF&xuE@ۺTqV8N/O _UctcL{|QxP>aϸo[X5y~̂=eȋ9ˎ?՝MҺMe|83g+`AގJHlm*Ƥ`6B=hJ ke"d,apAv !f­@?+ek~W*S/O _G^>­@?+ek~W*^49.gUU [ &wLF>qcG;~?q^)+я~> %Gs<1/nAHǀ:0K-ke2EVC ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( `ȳ.qk+H?"s=u_?TPOXWןz!6Xd3BzCx z%i(orj(AEPEPUOY[?# p@$y͊(mj++6v,-У<Q@6ެLJ%o9$hܪI瓛_?c'n[۳ӷN*GB͞k^~ݾof皻&c/7\w/4xǕ7oZ6rw*yb<%߽ԚrOs;,G%đrF% 6.VI-'i>l{![iywuIm݀HEEb7t#c٥5 ؑ7͓rh_IcV>M[5 L}7 H,0I5EQEQEQEQECo?k7>ez1?AMφ_^}o&>gW*;xt`[p:-nF<р?Ym?t]5/W (QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWEu{^^WAs>Z'3BzCx z%Wǧ2M/-cOC{QEb ( ( (/`njWive2@݅8 ~Ivj܇,IR? {GF~~7_*&|';Ws|s}i~umNh.m# JjC) ol,n,̷2Fa29ο!=Zޱt~64hdUP񸟼XwuOڽXD7Z-ВqċAS[uY[vMKm"LKʂh UmAچgO]I0Wbsu>أqK{k5 溂ZzG*y#u1Ϝ*rI_jp*14bl.]nA r Ђ*gӬ-!ѮMB2o=ԯy1đpUFy%ƫ\/̦W`͌ !v $n;Rܛi- ;yfM؝Ȍw@*Hؼdb?u_FJ[dWkke$ J?sXs&YoĶ;*Y$"TmOݱy /.,,ۅYQĩ#(10f ' g:خ0_l2 7hu{Sf7F)`cf<b !  KEφ`u Jm%ܓW- Hj,"Ҵ=:v,UT('s@(((߭}\׮ n|7p:cy79~s_W5낛 2M}ίTw=3#,tZݬ/x ãIJہ~kvk^!lQEd0(((((((((((((((+ 9QֽRă/X8,?K}GZOA gq̇=yǪ?oFK\?'O+Nd?=Q׬_2ZƟ†&*QEUWYCcNg;[ߺERoetخ$!jYe)m,8z; ޏ%:jj_zwiWpH*܍֮i4KM].TJf\U3vֱinym{~\Svĸ >,ό&|9Hη:Z\ ]b8V LU^G<wTW;PH)Һ*((߭}\׮ n|7p:cy79~s_W5낛 2M}ίTw=3#,tZݬ/x ãIJہ~kvk^!lQEd0(((((((((((((((+ 9QֽRă/X8,?K}GZOA gq̇=yǪ?oFK\?'O+Nd?=Q׬_2ZƟ†&*QEI_5T;(;TpqڱgDj(g&k++:nCjޕnMim4F14Vwjv4NȴG!RTd)?U=Xj3Nm[K'#VB(e8\sҺ(VͧmQEdd"Nx`NyV8i:\[2 )dҒUѹ )aXۺ*(|5yt1F;PJQA4 QRϼ.m|ĖvMDA uP;.Ī-{veKqsfI1MdBX`.Ot .+i _IsZb#Mi0F1Eb\{ϷQnKrpq,m^|; Y;c>"NXG(d3gcsnwA|}q2ۦ>[X,"ܘb\/$ڹuk]~kO0v4ndʲ9fSG@֚[[j=Alw LM)Jeހ1k>}6{ Y!KKGWgCId]~\]eˡ$bkԹhkR+ k`rDu'PE5#A,pɪGip4;w zU(I$EsqrKEj( ߭}\׮ n|7p:cy79~s_W5낛 2M}ίTw=3#,tZݬ/x ãIJہ~kvk^!lQEd0((j7izubr2}9'=HwդvZ%ÄAxr)H$浅 W7U^ uXѼC\<6[K` 8U8p8Zo?~wmǗwNJH_帥i+iWKUkMFP+{ʯ=3CUCVɩ;tq4=iFIK'hU]5謍c_MͰ_.zTC\CN/#3Asd*AU#=IG.+7-YE-5ʻ}ESVeR#1+2僂~ c}_/>q׏C5Қ270\D幍0m:B=*kZTKzy_^p?Y~_kꃪ әzT&_OXWןz!6Xd? MEU(pm`.#GϟE4j'U ^}SGk>Z(ןk>ϟE5jz军go\\I%ͳMPYO9=F"]: Om5RI&F%% (ʖeu[*HSϟE4yMrs{9M}֖\$RD&5G * EO v{7nM}S\tV.H%i$y$(hff;@$^cZńj$ #"2 ={ǟk>ϟE5%u.Y[N\vd;\pGMInۀ7U_FP[k,*$H AZ\S ϵ?h"~gT:4V0 m{ʧwP |]B(}nbxd nl|ǁ@/k>ϟE5iRjvVY,ѵѽ14Όc8nl-Z"<_Ȧ@_ȦSP[R;u-|,X$OY60k@4]iqҮYA  t1Lr ^H29^9?tW\q؈*^Xxu?w=?6fɶ7W}_yfA[~v^Mm#Ib1Wq''IBs_W5낛 2M}ΥzEkog{ 2[,w"cSzVcq_x ãIJہ~kvk֨)=+Zٙg=taYmG7]iY{jb󿽙VQGcq֝{jo{b(5,U(,Ŏ=teүm.]V饏 l"` 'NG+\`U210 [h%͍i}𱀶n۝͎åAjQۨUYe$gtp3]jZz䎨fm+5IzV]:q}`Ԇ]Dh 7rj|Cᛍ8mW_-CEp3g׊*)|׷[mQ˛kW=mkzs^0I?^K.g Hpy" 6Q]AaKCk;IfGf0Bnez1?A_zgF<р?Ym?tX^ Fet,_B(aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^WAs>zy_^p?Y~_kꃪ әzT&_OXWןz!6Xd? MEU(((((s^&<.lLPǟaG%zKŚh^BYfXo-G}FrG{W}<W0wu%)=((((((((mzwLF>qcG;~?q^)+я~> %Gs<1/nAHǀ:0K-ke2EVC ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( `ȳ.qk+H?k:եOA gq̇=yǪ?oFK\?'O+Nd?=Q׬_2ZƟ†2 xgOG7!{mPpPv F:֙u656W&h يH*OI {Vux'lIhVq͆T{lD%bcMM H&0-ϸ2e70hHq}sJw=<.$uP`p14u}]yo4V0cKydcܥ3wLfUU F*Xг\($n9bnjrv Uy`HV {Y%OvB쫧AiXBi%/$yeTTݮ02+_ EeHxH@01ba  #U p1&]Gd;f4۝;Ɂ_,e{.rjϯAq^tD0He7Fjl״2K DDj`-t[2_j-l1'L.JaceOz5֡k~PЈ2<1׍e ]fjZD~VoH2 FG3EjTmjEi5ۮ1 %8{*ג:P YҮ*a# |?U\Gs_]HWLmGQXc^e o+Ӥo`2˸5~˪6=ݲ#kNenrJ`  ]Xa凋d/D܃?I~0_eG,aʷi\۬SHIU`ɞq lW1G ?I~0_e]/+R_?WWmEq?K *?cԗUQ@O,aʏX%vP ?I~0_e]/+{/}/AJc'FrOuPEP6nFpSsề&W[ɸ}1ϣ[ѯ\nun?Lsu~ Feax$c^%K[_ `+!Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@y_^p?Zߋz^^WA:֑?TPOXWןz!6Xd3BzCx z%)(orj(AEPEPEPEP-|,hzݔ3®,_k^ d&f4dx'T|3ՕUͲv|m M;cQծf+y6ro0f-3.n(n|1O\نQvTJ  WSuYt$2Ğpz0޻e"mk;oJ[7h((((((߭}\׮ n|7p:cy79~s_W5낛 2M}ίTw=3#,tZݬ/x ãIJہ~kvk^!lQEd0(((((((((((((((+ ]{t?Qk+H?"^]}GZ?ßꃪ әzT&_OXWןz!6Xd? p7m⥛ۓʢOD ;NNrvG5.zS[ͳ9gzò]Z^ +Eq8 89S MFuĀɄP-´s=Y~-Ju:PHRSTV2 'Hm~U;7A1Y><>17kZ:?p:yLqH$/kl,l>E`ic-`l mYKY^E <2 jޫز26tWi!ԼY ,F/y>GvPIIJ XA r܌Ocg<`AfT` WI^ߍFL䶆e庅E=KeqE^߭}\׮ n|7p:cy79~s_W5낛 2M}ίTw=3#,tZݬ/x ãIJہ~kvk^!lQEd0(((((((((((((((+ ]{t?Qk+H?"^]}GZ?ßꃪ әzT&_OXWןz!6Xd? MEU(((?G٧2&_O*^H+1sC8 6,0D/љ؜nI=c?G٧2&=i{I}>?5_y鸾Fz2F, w0bU9 >?5\gҐ&` g< €3}j-zTBK_:E HXP0{Ia>.5 gym$,|ӈٙe)u<﯍\5ц3ɵQFI$lwnFpSsề&W[ɸ}1ϣJx$c^%K[xt`[p:-nMd-(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQE~$zk~.>zy/mƘ\\[}]pAZ<!=`zy\zs!<^~bђ+R y_{'\=9=Q׬_2ZŸ†&*QEQE\h"X1g@.17?/?qkwj2XCi/# @f&@x`F>l6Tm/%R9*; X->SmuKm.]bvX≕` 3moZ-.[;.X|=N' R8_ñ aW\ V+mFѧ;EcmB`)`NF:',./Q/cFr!9ʨP; NDӣiʬqBw>=S~W~cj:s=h_&PQU0A֚.(8Q' ?+B/ &V0ϸ ny`\]2z@.aW\ ?+BW.d" nMŒycY>V'q ׼T|ڄV>Le$Ff t^*VpN=4cA]s*ņM"ϨLm:8',./Q/cFr!9ʨQ v}{<||+n84;Y^y%EH&0B2NOTfcG3%eJIX   @KEPEPEP6nFpSsề&W[ɸ}1ϣ[ѯ\2%}[jWBI7pwǰza |#x$c^%K[xt`[p:-nMd(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQE~$zk~.>zy_^p?ZߋzZGsPuC|!=`zy\zs!<^~bђ+ әzX&gh(~?4}'jEEKi猟ɣ?@QR'h4O\V^.Zٵ(ОQA#]D&keg> RX2FE$k?qWϗ{?'&hԟkVKΧA@Q(KnDe!I}EhJI;Ƒ6Q&¶.+0dݼ5 Wޥsn;Ѱr2Eڥ+ktȡ؋8/RsZ^ 6G{d(a-\WHӦѮM3Q/q*D\)Q=?CNԟk^^[MKN]7Q};RYcʶvy܅!p4o4wQ I2Af9bap{0dzԟRkƀ1/#_޿꿳|ߧ5KVKΧA@Q(KnDe!I}EtړXC5Z+wލx< +$FTcYD @X02qC)sj^ԭ;"b.NNrIj}ɽK+|۷VX1hR'h4OTTfx|>?4/٧2&OqcG3LHǀ:0K-k #,tZݮŗ[QY (((((((((((((((+H?"^]}GZJ3~!$ ګL v4c̀V 2a$⿮:i}Kq=iN~xy ;sV..5+ >6}F8faim:{|Y3C| vu{hgօEe5gc?z==n30m6Oݷ?[۳k0G>< ,O+|z9'~:.X^a|c?z==4ݝ{^?s,?im:{|Y3Gο X^a|c?z==4ݝ{^?s,?im:{|Y3Gο X^a|c?z==4ݝ{^?s,?im:{|Y3Gο X^a|c?z==4ݝ{^?s,?im:{|Y3Gο X^a|c?z==4ݝ{^?s,?im:{|Y3Gο X^a|c?z==4ݝ{^?s,?|> 3IDrjG,D1g}÷)SU]v!?kK?1g/@?~zǰǾ. ִG=ϱ#XfnU*w囦qW۳k0G>NN)c g/@?~zǰǾ Oo[nν|ß9_4ݝ{^?s,?OAu?kK?1g/@?~zǰǾ7۳k0G>7 -g^׾aa/}hOAu?kK?1g/@?~zǰǾ7۳k0G>7 -g^׾aa/}hOAu?kK?1g/@?~zǰǾ7۳k0G>7 -g^׾aa/}hOAu?kK?1g/@?~zǰǾ7۳k0G>7 -g^׾aa/}hOAujvȂD?/)?;pO_xEsD&DPj( !=s֡o[nν|ß9_?_c.;bum!sM@;h9ϻm>t3GXLj,*|Nxno[nν|ß9_ ೱӵZK{K*S Æ<擠ގk ]#,tZݯ2IxK]oA%4&],ɹ"Evp^U)ָ(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example2b.jpg0000644000175000017500000003454010504574206024627 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?McPMf++(䅎$` 0yXE0{s] <Ҹݗsi_>UVmhn5 H_Lÿ amY %{4ln-܍AϹ XB^'Xd&4d:8=amY (NwgPy($! {@6?';s|P_m?F-rxmn;l$`$wݜ{犅Od;Er # /< OZDw=zn~9oamY2bM [ś 6X$#$f_Ysm5٣ Xx=?vdi7s,v%FITw??:֑YWZ{ `,^$nAxdL$c,8$wug6Ol5 ג4^#}}bukqjVfl2NNwuyyƛ'Y}~G׀^q_TϷ3FE7jWKڢRQ$8ǮI5V×K[Mۧ#߭@|o/8d/_O4=>꘏Oo[RĖvs"Kyr GC6):Dw[TB4=>6Olp#}¶Mʛg*)$țʂI c&ep[D.ec*p;uyyƛ'Y}~G׀^q_TϷ2x~ǨX,%\K2; B6 @$c$x]5q6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcEq6OlM,}?#!>ogcNlvbn??ˏzW|o/8d/_O"x墰{tf/9,U{A=;1yuXA|֏ (H7G _i֛${@n4=>6Olp#}>;Χ(_? x~> N}?ל.q=p^;Oje6P#,a87GLAsJ /Fp=Xz?@Tl,Gۘ%{e}ո,>r{v1;o#p>y-u0Hr }kּw̎zßq=EE{j_\yGڮ?缿٨vmSK/hU5r3~q=jfU=Oy/ڮ?缿٣W_TQʻ%U4}{}9W`?jf\yQQG*ڧ?W_/j*(]Tg{}>q=EE{j_\yGڮ?缿٨vmSK/hU5r3~q=jfU=Oy/ڮ?缿٣W_TQʻ%U4}{}9W`?jf\yQQG*ڧ?W_/j*(]Tg{}>q=EE{j_\yGڮ?缿٨vmSK/hU5r3~q=jfU=Oy/ڮ?缿٣W_TQʻ%U5 ImvBI%{H?>/q륰ǯ!=rIJ6:RWE :=mzà+S :^|$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW|/]-=yL|Kzl1x`C(?W~h|{#>ǿ0_ ;#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_9_=mzà( :8|9}sϫAusFu;G=~׿}_ 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z8ckԾqǮ9C}Wǿ0_ <{#>329~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_E :=mzà+C :^|$EEVQEQEQEQEQEQEQEQEQEQEQEQWfY 22WYⲽ?KJ+?̺B=ZC4QeHIU*3N(c ( ( ( ( ( ( ( ( ( /q륰ǯ!=ש|/]-=yLs*/a6=OxF}aoZgyds{> :#p>y}]v?5'"*(8Š(((((((((((#n1I:Lkgj*6H#!B DۓPb=O8Nr#^-[[z2$ʊc.x:N-RӸQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_9_=mzà( :8|9}sϫAusFu;G=~׿}_ 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@-nȞm"'Bf8>AK'kdg˓Ϩ# PA,[yA5f#Y$/<q8?^Iќ=4T)=Jwg-p2T;Q Wjs*rq (EPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_E :=mzà+C :^|$EEVQEQEQEQEQEQEQEQEQEQEQECpá? FE<+0O?~G~E( A#Vь((((((((((+ԾqǮ>[^C=t<{0~_N4r=Xz?@QA Sthq_sW<>w̎zß329~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPn)n0qoJge{m)d{G]G%;d^x}AG"IcrN=۷Q␣0qY59{ jp/ }l[{UӒH))\G+F{$gQWҳw0j6QEEQ@Q@Q@Q@Q@Q@Q@Q@Q@z8ckԾqǮ9C}Wǿ0_ <{#>329~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPS"IcrN=۷Q[Pw:$ i_o|ϧ4_FHQ~?Ԓ,i^FquJ|ϓo0)QEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_9_=mzà( :8|9}sϫAusFu;G=~׿}_ 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z8ckԾqǮ9C}Wǿ0_ <{#>329~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_E :=mzà+C :^|$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW|/]-=yL|Kzl1x`C(?W~h|{#>ǿ0_ ;#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_9_=mzà( :8|9}sϫAusFu;G=~׿}_ 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z8ckԾqǮ9C}Wǿ0_ <{#>329~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_E :=mzà+C :^|$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW|/]-=yL|Kzl1x`C(?W~h|{#>ǿ0_ ;#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_9_=mzà( :8|9}sϫAusFu;G=~׿}_ 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z8ckԾqǮ9C}Wǿ0_ <{#>329~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_E :=mzà+C?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~ "fҝC2B>F~=+9|Q;(xF}aoS|Eq$7e-(n`G$_Ìb;o#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_9_=mzà( :8M6s̐MmPBx{dXւO$:C*#3=܅IPuKz =CNzM'2?8I8I^T9I~}???/ϧ'{(_r!ËџOeOQAqz3qIL)N|s~?OAA/_OO(QB?:4g'@=&{RR%_>Q_}?/Ft3i=闱=ENzM'2?:K=T9I~}??D>_~^g{/czËџOeOQJuKz |s~?OAG}~u/8I8I^?:4?/ϧ'R%e~_!qz3qIL(?/Ft3i=闱=E)/_OO(:K=!ܿCg'@=&{P~^g{/czS_>PuKz =CNzM'2?8I8I^T9I~}???/ϧ'{(_r!ËџOeOQAqz3qIL)N|s~?OAA/_OO(QB?:4g'@=&{RR%_>Q_}?/Ft3i=闱=ENzM'2?:K=T9I~}??D>_~^g{/czËџOeOQJuKz |s~?OAG}~u/8I8I^?:4?/ϧ'R%e~_!qz3qIL(?/Ft3i=闱=E)/_OO(:K=!ܿCg'@=&{P~^g{/czS_>PuKz =CNzM'2?8I8I^T9I~}???/ϧ'{(_r!ËџOeOQAqz3qIL)N|s~?OAA/_OO(QB?:4g'@=&{RR%_>Q_}?/Ft3i=闱=ENzM'2?:K=T9I~}??D>_~^g{/czËџOeOQJuKz |s~?OAG}~u/{Hq,lzP~^g{/czo.$|[ yV/_OO(QB?:4/ xfwkD֍nm3t= b689T9I~}???/ϧ'8tL =_9=mzà*UI%ma85g)mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/annObj_PropPanel.jpg0000644000175000017500000013371310504574206026141 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222," }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( +oxbH'ѹ5e`pTr=?M'CFZ*5p+ ѢQ hz?7M'CFG&EWѽE`o?4^?7 /\_UƧ.+ ѢQ hz?5?toQX?O?/*M'CFG z4hqTo?4^=Op]V&E ѢQj+ޢ7 /\_UO?/*cS_F hz?4hqT{7M'CFG&EWѽE`o?4^?7 /\_UƧ.+ ѢQ hz?5?toQX?O?/*M'CFG z4hqTo?4^=Op]V&E ѢQj+ޢڮ[fk{ 9dU`*J38rj ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (s,_>(B$ ,]l`%($;j+/9Ex] ڿQrb5ڿQrb5ڿQrb5ڿQrb]j_lZ Y?R Bd#;N5kNn} io+"J *tAs87 lj+/9YZ-R+;;2Y!N?!Pcxw-V{ŢtIFe ̹W0prb}ei.еKf<1:?pTBɏI㞕U|q\1 uIqP7pC 9_667NW_rӕa+Khr=ͼZA,'#.J pFg(ӭ/{/eI} #$@ /ӕ_}|),2(t2AAڿQrb5ڿQrb5ڿQ~cVcۜSڦnZRQEk6M?OQtuk6M?OQLc[c?.ca}z_X ^g~HAETQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE3s?z~7}"nu:\?8O?OSg1AER x] x] O@ocFѿ/a)4oWWѢo J7?%?Ƌ+hT˩}Fi[;R9՘Z_fx|`[>o5nWl. n-㕌bA nWZ0YΞ+/Y1o-H<:?l'h4O#,uо/4Eol&ѭt;}:&WYy`cV;՛D < ѷ / O6o5ΐ5Ŭn؋g, <'h4OhS/\Φ%P4ʓ!2TpH@<;$?:E7]K.K2#&bb7`a#X%u ;)4fx|Gyg*M|"H pNOAj4Oi猟ɠ ]C,N M/٧2&"]kĶ+IXP#:gi猟ɦFled${Zѕ8:{P(Ny9mŇTl-aIO9qkNU?ew\sg0R kç<&. GtOJ.ZRaQqii&u\A_2)?M+?kUOa0K`6L )tH59ۦM6?{k{}GQ2tQD,;/4ɴL=v'<nGEs n1a>OuZMG伅G_޿ ["2D*ۉx~=jz(]<3Mͮ4H3Dq!93 7zUӭT*H,A#g<8ͿZNlۜn>Yic5MK+{1bsA^|MJkJ][՝Ovs8Kod3YĶ6M.Zy: nj j/L -s%Y\ .2FH푍[o o-&K760RN2g,K:ܓ<9yo}4J֙A!V;zvov.kVo[YE|OO?!U+╺wKȭCwb֟6uyM A=T&񰶹x&]bd @B! x|;-{\ /ͻ:d樏̖ۦu;TH9U @(I)=ogaSjV_=;MsiV:[[ũۙC8cS].s"3O#Ӛяþ]Ɓ/ڳ ŏ/ng=55fN1[u 9 g'K[iwN]2I[Me뭹^okS7V[I9ҭZbqe[m ko˹zXǸVm'ڃ$ѫlX -G8Zͧj]_o$#PmevIOk-[_йT8ZEӭt 4fn.lRs^FGu22^3O* ZZ+[]yeq2<1R o3,Zm5kkdq{v ӌA'ɼG5A&IR2s sG˽4 U00k4%dvL,;muw$q2ʤ'8YI@9$sr2= v A.wB/4ˁsui%q&r)#qk‘cU2uj<ϼw5/xnkMOz ;fibX[cgNpq֧%O5Xa"pCcdTo@VͰ9۞}{<6=3[%PFcF$3( eѾo. =$JOˣxH䴵UQ ?w}zl"́9/< Ne|4_j[i݅Q\QEQE3s?z~7}"nu:\?8O?OSg1AER x] ׌[1iIsu9`NY胀NP0Ij_7Nk%3볥s#H6R${=cykyIzaٳRs9ڧ=I,gYO4n)1Wb3«  vxb}7UDM%sʒ@"[,[Ynn]Bsa*{EA|E],G/ӎz5"}:};4wF@/Ua/$.9BF7S J>_ G-4;>n5Ao&CQ+PTˮ?T[hfx%m0FIgD*V'⺻?T5Q@siousiou-X ^:B1,!שY_QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQXzό4%}y1"$TҔUiJJ'+ٹ`yrx=? >^g}q3X֮v N_>N3ϦG=4 Ԑ#F ;*T4޷0Sq[7(KĚ6}Qy7FMV~ɨ|n[c~3n[/^ۑwmBx] 5x.;M:n.Q sG>-jJJC!մӨGpmBU|.s{TBNT"r4k6{C*Kp#W \a py0Eqr$d5Pմ.gͰyZm dwQxC n;.^O(HGc5r>nܮv7GLw1;gq}mBmjim`'-18=ꦟi:OkQ[au b9=9öA&y6(n.Xdp~N}r[ת4?gD*Jwm?yvgݜv}4 ek,ӹsi7pJ0mG}P3"QC?%Ek6}[y_M/Lg;FhڷMnscw}4]soa御Zr>NvKC?%W5 9-em9Q*;homq SIcW 2.m1>v8#qB[OP8*Q{6.3j/V j0r$}C?%fi_۪ռ4 G֜DRHܜp䞽%RM*NQJrN[]5Nk=f4E9@̣GFP K=sPVӕ(\?ңFvѕ̺x嘀:w5&-KX.Ǖy<#1{X[x,R9sok;۽}FmEⷊmB{N[$Ϸ4?gDm'TiuJ+l>n,G8=5BxvH$/7m PA+(`3rr[;TTFOO~ٳ͟|7< {M.fF_% (H[Ԙkʛ7~AZjg*.RHUH [ѵ7owͱ 8zB[OPiQ}lh\? Y^Oiql 9򝬧d.:ӳ|Oc1Ju0i9t;wLχ5F+ Gκ;ȑsI߉yڷgywݷ㨣Ak 1:r{+; j+'D6??*F3nwgx 5OSχ4mF[ Gɺȑ)A.keQT̷Vw_-SL:+ Ys  suԹ؞DO%@ 78ޤ ^HAN՝AZjg*.RHUH [ѵ7owͱ 8zB[OPiQ}lh\'>Nyݷnv+2rjЫF.7髅QTdQEQEQEQEQEFEҵeԪC#'Ri=ʄx3}b8D7+.C89Eҭ`3qLBVHUepHkv''O3}W'tGGNN2Vq,dc.+lٝtJstZiVgoo7cp9jU`v} W>u;Mq+cs rH+Ci)lAS m郓Qʷ:Qrv^e-"RXee@Tpj՝B+hn#pYP8&*ZXj9;2eP:p*-NId70,Bx OZ_ZmS߽!|=cѡbd/^Y]#E_*C77j<9{Bwbµ%Q/3T4]:|;4\Y[۴rV`m6P5ݫi,K-ֱ! UQ ׹5E/M7UKMlZFA$BTdNQvFX6/]eCKmSM6脔*Ye@Uo' NUUfJO];K>g,6goG}&%Mz, ZkwmMFqa6f 9TO#5XX"\ x/"H_ @%NU{=y9_Ck6i[HcGW4 `0޶vv, ?? N3P跏j,kn)(@6Ll0yc?붗sj"D%qر8"NQQK#3z'__]zXխS?5 K[Ғ[tx#fC0 ߯jiivFk-6+8 lh-Wiae^:BU[ 6-6l"dH˕e#rOtM,c;r~ Ǘ{K+륯zUt๛iM)Gjՙ6N8،$GUsӏ\RAxSKx"`95iֺnlic"f'i9@hg@H(BnM@ȇ*Üq3O8vKVdSSY7S^k'}3VWwF}ggcnY?saIwC+MJ'Rf[k,3r+cVݼ)~ܓ3^P81YZ$ћGJv[V<ʴ}y xҹcE%+5d[EMrΤZ[Y/i6-,tlER$R\l'5-֋[k*ɵr0eөwLu+/Wã2 BA8bv98\fMԼg~ٹ/| `@8j5I?V_z:P P֌wNsϤ6$WZ$GNzu͕<)=vTvQY`%F1w:gpvmRU %Ko/ ?/eizixm"Z͂>4V_~ NMU|{4Zy~vm-It;,CcH:'`jeBa&m "8 78$BPkN갌jIEug^rR$*nw϶dX}|&skF*Kc)T'p)QEQEQEQEQEQExt?<<~q B?::ٹ`yrx=? >y2H?ttY}5QHAEPEPL#Et%Xd(GUy$yd.,zCVcfi猟ɠ e^BGqȡFpy149 Ȭ!QU$=*B  4FFEޛgqn%3]ji8awmUdeМ.oCp8Yc9R;u" Kh$D!lr6( :~gnge4 gqeXqao 8mU`0O֍0MN P̊цX *>Ҁ#im eb BSEQEQEQEC7~95ۦM6?{k{}GQ7~95ۦM6?{k{}GQ2ٍn__Ŏ8q}{~c?.ca}z굟OE!QPEEos = gle888#ދ{.Yh[;d)Z ūl6]m:d1䌩##ڋkx-avC rN RG3s;r@sivv][+,-60 s$r#':(DT_i_eF377c3iIh &&>\l3dwh@[Sm.dZ8JIt^HPg(ߕER$(((((((((`yrx=? >y2H?tus?z~7} c?.ca}z굜iu^B_F[;n# 2dwTQX;_C'ks_HӿjMJ[ ZllV$$7CwN$QGnHm?w~lsNg"g<ϳ~{9eRV3m]-4v֖3UmWINO뉡< t_.tr.^wnp1uZjg8գenB_f#tI7;IṸ72vɔ`s?Lw:}Cigi,1$Mg_Fta;e𵌱8=JN4g{4gIuq}v~H4Z9ao6 9ڧzxKcto^3=t?8ϷЯҡ?tml$|Tw?O#͞N8_szX5􆗾k˗m /uONk춻Km78]iW7-3i۰j$`B_Up8B{;c$Hn :E'Ӿʭk;3JŌ%[89oZޭ0mXLf$m9<ĒǒIɪ5XU7m+Bi6ߢ*ZKJ֮K\\-- [\FTsqQGuY%ooulw ・g"g<ϳ~{9#Za< 7sE9b =כcy!o݆춼Zqek xT/l#d>~%{wKzn %̤F"?*ڻI$g<`1|v鮋N9 P|vKMtW[&QEppQEQEQEQEQEQEQEQEQE3s?z~7} hTYL1 sӒ<EErp;@ҵmfɤgi$mN*3n}}x<MuޤmHc2 n+ x\dz%I~ωV&=ARX|mXǦ][VKl ixy))lL̻9h S{ g7> x-徕`a$YURÖG{e_KY{$l΋2"LN"v q@;+nm\kzdOT13)^&3M_hﹱkXfVI_C|۔v۔o[]]?㱛ɼ.ULm;*$rT޲gn*Kyw 4o> (TV9r\/coa4ztO%+)0XrTgR\:oۿ6NjRM#FBfQ*CPڊbFw⹲yl,M*RPYYy;)z$WۭYe[2܅ vU3^&}wc|PҥuкIv)4m$GB@|Z:Svt>syn4lIy#F.b!HͰcsߞk {QFg~ BnUct{_?T|WlV?rqe"g\p#n}4Fjk|~s=s.F Q-~F0}r*qCT~?l/_]?>=yØťդ@j mYLG##'5t=Z[.~?iPZDE&Lc,5=`՝w00z^wy/o6qzVՔR&6^q\z2͡Dl=gc ȋ#vFW A뻒Fg]cGyulJ_,XI#8#>c=I`i;}{Rh򶗟~hU_'ΓkYM ƸO 6qR_hirinq,KlA. c g>X =俫9M%E vz%xZ[NIo&=>DiK .@ +~<9$$youuOC`Rhxۘ9oWHs cj7VQKgH۸eyGq:~"dBI (1urᙳHԯ.,K o݄7+&8nz Ǧ}qZ/n}?jy[wեw%纾}kfm2)fS$~frvy"h &ԯew't. 18ͬ'#/xG^M%QwUbki46cD d^}VŶ oDŽ;1PpG8jLXUkN诇^EL7l? #֞6_/6&4[zzgw.cvpc=iYHXfsws6mgk]@?7 | = 4iɟS^)`E VQ$Sk}AT5%ӯ}_ݣӹ\!,kNY"#n!n:x8u^eJQEb`QEQEQEQEQEQEQEQExt?<<~q B?::ٹ`yrx=? >y2H?ttY}5QHAEPU5ѠV$QP@rI?[3,˘u{u}1yCA03մhoإYa۽9E#p#( ^1By u{JH.R0Nb8]I歪޳ieXC LP7 A'?1l.:Z(b[j724) r7ڊ 85 WX^kgS5,BY8,Nv#8$J(_ Xזerp4Vϸ2r.iswr]Eyu{:{';vU!ٍ.y5@8. u]R>\ ,x@b.rub]|[U H-溙 [u2P6,=-FM1'm5ieId)%r$cV_ XKiaueth(HN8g|9#[P;>SRfu+x58^[[9MRUiA}ׅ- mBmڣLQ΁UdRpO(? 2]ꚕsɒUL.W(3? a/ # `Ϝ>Q\Q@Fy%ƫ\/̦W`͌ !v $n;((os8k XM>m~vos8k XM>m~eܿ|q!vU/_]?>=k>B ( q:lW=>.3,*'݌u)-p*rcsST'-ԛնVN{+ymȞ%d\ 008&_-ĉCmaцzRG4]ȡ!/1̏BcՎ:Mk+GKǶ]1QOE.g{9{܁/v0]G<'4+B m-rg&1@15=9ܭc_/~1ןO$q*+UCSdV߁QG)XTS@NtN:sW(-?i;w nV#qBZ%%+u"y`;8-Ԏ*z(qs˹, +ơTdz)6ۻm)((((((((`yrx=? >y2H?tus?z~7} wngAiy!mo54E *$I4lk\Tt-4e{iq4L")lYXm<0];RP>wNӵLXMb^]Cn6AʌmMBsW5ϬgL`'I]1?)2s3@lkG?Z(?vv6g&a!I?u_ր5.- 3N?2qSV8~4U=[x5G Z8,F!7J קtU+vƏ+vƣW^?&??󆰵tmo4%4whR!c1cb꺕(ӦKf,.ʤ+mvyșPgkZ|q!vU?u]:[[Bɪ4eTܾLC#8#>Ǔֻ?H? Z΍]=ײziPZ_e0K pG~EOX4ӳ2qqvaEyͷ5tu ۜ/"wOۅ\OQ׎qں:ڢds7-9 c񞺸 Wo#Y3rwܬ;=O7;c+! 9n3NkKX/o^ mkUAY<ns隇 W' k6Xs@$G-9T~,yP>r)RBlrqڒnܬ7e}hX^7Pr<[egy,"(mյ0gN;A]RRqFʟΧI=i H=#$mtWőGk ;FggiPU$8ghy~!}}tW= ]EwҳM6zcxrxKvvI :\n1O.8RDpu+9~&Wmk ζ?=֡y.<I5MkdOo1B|P1$T*)ԇVu{~:+ŶWBmo\ۘ᜞T+9~U[+SNjXH([Au_̯buQES+}cLбe Snukk=F;;4&7NrLcg jM=-^?FuDBX0̛Gb0F09 u⧇ry2H?ttY}5QHAEPoou|ݦ$$ {Y۟ @VOB?PO.a.SNfg$(fBMQ{-gVuH-,'x-{d;o)7c POn+Sso Ԥњܵ؍ɰ.߾>fk-S==NeVV]p3ОsZVzwEH4 m-Evh%LxzVw!ui.K(6-ڮ8ڍGr\|t۟ GB?]>{=CNm7&RRh ɖH :H9Zk6:YysciE;o0 V2~A&<Vz???^9vTYdVT;kWf2Iڪ7bOi ]qJK]݌P܌WAPOn+SfZi&k+y[R|%2^Ywb}ӝ_izt!?b-'-Ɗ;cr4jףsZZVz???^5'\ohVz{{&5qwq,84FȪVVLZ+dޘt()֩OFԱhɫ (1!?l?mOx~=ݛ?l?mOx~=lƷ//_]?>=p n1a>OuZϧ(=B=FMssCIʆۓ`0x;VW4間 ̒Nn ear95Q]0BY%]ݽNCHߛ-f}wy۷z~5MgD(mUa1 *@ F9綢{ku{]&յYn.&.(2*}3-g]AK8n!u 񷳞y8hf^i]{.Y[ ; {U۶10In|=ڕqa$ʹ3 #8>XSNr]{U)Ik~Yk.sd7jYX/,AcO[M"kk4ZX#(Up}\Gl5ƪOmc9xݤm&jp\Ŭ5c<8  As2z.5vHӣG0c?($YVNm;zjכޫn5oMYOVF{y"RǀYHm+?ڡT iLw%r1t'򮪊Ξ"tX[x{Y=J7L9`keq41ݻN3=iGoFm3^vcݼsל񮾊j֖~^M~Yft̏ SӮ^72J0@j+f:(H #b&:[o8/3<5%X,1%dOUoIj/'0M<뗕 y~j+X$1J[_9<$Ou:RX]wÇ#n1A5K Ry\3ad cR:QOBqjb{_ӷOIF xbU@8QEqNM8'')9>ER$((((`yrx=? >y2H?tus?z~7} k}^wܢ-cFNA8OY^zy2^GEdxs^OIx@;*tӡ46ӣVVe۴ಀYCci`#)PJ:!OV]㿗Т ][cQIIjx|Imogw +DdcR?\\7W6ׄMi[iޢ\[LQR +:1e#pldzoi_iى.wMrAl I>;+ "wӲn-ygwN` gM,5tvVFF;XA{Tʌrȕ 9%tW/Q\ٵ%/.8޻%e:Wwg+jĚFyƥC$96z]\%jm5JR5hXY҈ՄK#XF2[r 9SA}[OӯK[kiX:W-RApĒ( /n@7?۷ ok8TF38rAۂEiyIGoʹC/N1V׮(V/ZG_-<(! 1e# 9#$'W2ЩJ+5hF׷uEV&EPEPEPEPEPλC˓g>+A>v''O3}7'tGGNg0艫Vs Bt0ԑoU{AιGmUN6gw[|e" AP3A@UԵXMN_jQZy+e,+Qk**uk<DeUubc.6}t_A|#">J'#öj)t.nZF)E4!w|8f o8 [{SrԶ)nE29 ` cpW:}FH.n$<;<.vyc r9dMVQ,tK#iY6$1.>qV$5}h V>Ts׷m͖:ޝko)J-dߟtJۓl/V #nZI1؂$I{%@Sj3xVHcKtMJ B.W195j[jS[{sds%MYw1ws b*rtݮ~M'$9y?IsD+POқa?߳~|*O$9y?IsD+PvP 7jo<]M'Z(?O?WmEq?xV ?&AQ@O$9y?IsD+PvP 7j𦿉b\܂ٮڊ_\4e;~D}~uխmCJ\ NW< dO= k8tӵh%2eg嶶齮yΓ}fHCC֙Ws޷!4]>HU@ 3]US0QkW4VNRK[}|>얺/KU>HG^NIUOT?ٻoߜx^E7s__7o6߯v}G/Ӯ6j6VhTdg`dC@8TcXP[VFN/ =2zwtRYT>ЖiYKw+9ҵIlyGRDO5X2rF{g8$s]o-[N&8r(d{+T\+i+~H筋XJ+dQEsEPEPEPEPEPMλC˓g>A>v''O3}7'tGGUStDU[NJgof$cR'b9<{Qaj4u* *O8#z-QLhxIQV][IǠ>(% Ynaw˴e=q0Z dE wH< Tљ-.aARaVR==Ht/ "d, ;#E29%E#WR2##>3?%ɞPNѼI%\}snkAyƱO vn 9W_Erz?bi}>ѳfͿW7|EW-sXނ5]*+Y)%n9ݞ0k[XVu*ce8*F6dӡ]y(&28}GP')C ZwW&ZK ?I{,(68@_ΓmG ;crZKn[(@ Kp1oG1wDH.tۛH%p)WP@8/av^\#8k)#o1! 椽:兽~խdnR @2S.2 ;le7vT!)F 3=D J U NVS9 |Wax_Nu)6Ŭaџ/rߺ^=5?0 [K>3?>!׵i_ksfB86H+OV_$9y?¶0 G&h'}aR_xV ?&A ?8a~_̰1c{qmm-}K>0ϩ/۽sws\9R'#r#X^ -bgO2k[n@8IPq4[ėVmP]k_dzHo]9Ǔ'x񧎍)QP,mY!fe/o<G$9y?¦ҼSiguym{}oIou4_CDV4Pv >f?'S  5Ա?_s~3}KbM'Z(?O?V&hAMRϹ}?_ #o<G$9y?º?R icV[i^pp=EZ%AY'5&AM'Z+?O?S_Ğ86Fx0 ! dWqE.滬S] 3};i] <8 灓 硢gn֝:vDFT|79E[H$ 909hYxsRIdVL_۷&U%B}Ĺ< ], +ơTdzM_]_[49$m.]y?#NcÚxC |س$1X{1?.kcs$ 45.]nmgsF`hoB$]ʼ@pxOMBL۳G5 hJJc?uzO5QGR先UXZo_Yyj[,&|Ba# ҨZagM{],Йs8Uii.ҫfZO8{OxWvOk=M'<;sp2kƾ"Uݿ!inޞn( ( ( ( ([=~ fbs2"$鵆X ;1В4,2(t2AAsVnnKVM3gcUX*KTMmz&Ӵk;-Z4٥LhFHWdttk PfMya<X3vuyylO.ᶶa,QƠd_HmT:GK \J"I+ޟGVw?Em?g~݄%Q-cpx b=)_T5_֏mWXf_??|W+O_-uUә;3꾡EW Q@Q@ ak6M?OQn ak6M?OQLc[qa?,~a}z_Xk 7c^n#!QYQ\>k%Ai:"j(((_ _WWAjQK?mZ&T:m坶4?366dLw1g0m;uO{fҪH! */ 1,pIcfO4ߌ䭦g7o+ d/6qcib`xz|/u%.53KyG6`ylu<Tl 9Z&dJ{(,T1EQcI1h]ֺmnn"VI2rw09#'=.?|y.&IxeWy}Sku$$C :| c@O$2x K+X㶍-TF Tm8H-0yҴQ$=YՎ9'AGK00', i-ڃp1q]>"maR3]];3n%, tsX0I8QͲ弴v&l#NKe{"/ƿyivקןe˿͜vNEx1JQDm7WDңUO ʁG~igA YtM6K{}LOiHь N:-}XEe65ZA;hI _{+Y#d*9/@^K=kR=d/o._AjiC,ha1z`sלSdDʲ;Yp###"nɾgvr^`~-*-;J!P3m5ᾃKtd%׶;5[PC!ݵ=biK2wHܜr:NO_gZ5e.U9:m~Wi5sR:mf~i4+|!ɭzi* |q{K*f@/5*Mo} ˇ@@&$Q 0C4yΙ*~뺜 W͞#W꺒A`ֺn·xy# s9< 3iM[M6ߕVw~Mfm?\m.wy7)>okRwڤz|6-"Koڄ}ߐ7'y2H?tu璢 z&U]f;@L=;OnjUOOaQE QEQEZX=6n#oPtvI3F1Vuux{E[dUVkNHeH ;P ֔JѥӣQT!D"wRpGVa~_2UfV$MJP{(=GMȠR ڹ~*]:[Ub+n /vmrq]_8ؾ?A'2U |KnGcv>ͻ?yvݼUo5fI.m?d[y-pQb%1>ޥ*٣G1 _ ȭ ?/~OZzg-u9];RS!cS%[n7!*X`O񅮣6jQAes4!c*;6UJFृ?ql_uܚ>3E/BV, N_ ?Uu#F躋]M%Q]H O6GX/sqdkb?sA'2Uoe^ڲ^A#< ӏ#` Y6v⤃ yKc$lQI$XG3;Qkb?S_ ?U*xtut֤VS?_V> KXƳXbR>&O mܜ:xSMUӵ+x58B9M8bU#p ?ql_u? iPtɿ1՛F(שּׂ!U79rps8=0Z3ivW3B9£eTdn X0 0h@Vn5NGR{QEffQEQEC7~95ۦM6?{k{}GQ7~95(oA##lƷ4>qa?,~a}zH1X2]mSu( 8<+cmYX-5V_62X E;gel0k{ng搑z{`Su}^=R#H[!i]8P0['#OԯtkۏX`e1+05|CJ\ڽRzg|[6wJmեԹiPkzTuȐͷsF@a 1{-t-5[F7}mh5mjE7Xx2 @$F1<~'yQmcVF]{iS^T& L5"}_q,-#Zc2Y2eq@ lJԴC\X2V,Tu 6ב,QHUYF3@M\msM]2 GJֳLXpT ų1hon9K&VռrS%X0VN8H,6 +Qp*-'t= iڥn\,+,|0t g4c%0.wܖ8(Sm$~DX&u74x\[O 6Caqg]HJy9WI"6kYV&E,df8 4;[qf;κ&g$s3EI/48eT+.Q S`*Y-ꥲJab@pP7qJ|%ij=ǤGKvk0 +wrG#鎞M[KNin:ɺ.b^:eG\M";4c>͹є4xF67wl6n#׎.|s|֖sEܺӮ6iwip=&WqN Yִ[پ5-j cZе?~1׶sVi}n^v>Z K-}vӧbEp6,/-,c #vG%$Qm&spXj`9<*1e#|ʶ2!%G'UOOaP?/XTRT?mG4}?T?mG4}?uuW/ΗlLdϸ9F[. ܁rm^NA=P,b%I-Y?ۗ_cX?ƀ1t9R%\j|^dA369$}o·6 .]W1$cB\@ܺK4n]ϥ `𮳧DhDm.k"H CwJ.qZ6zY:t3eX693j_\C {QK,p=9?AL,זqW 586U.^{i~\^ J }#g' HN9q~wTº^X] .ydO7Qr "mۙ r},ku>?5jH4uOKhE3\;)[{I.Z)F !YT\Tvɯ^ܭ1ZIۨB!w{Qu>?5h2Zgmrsx~ו*7"Q!uׄGy- YL&Mlo/tۗ_cX?Ə˯@`ṅv2wya>:}cxAҼ)jB_H m~gqMu>?5hܺK4hz^-nt6B&I|&m܊Ung9:Vٲ)x'p'ܺK5yX?m77/ˎ]LTp򼠥l05?]]?Ogml!cQmG5ok_W|-n>Vn}?/XTGe7U+? o7GϕmG4}?#0EJYuOf>\jny?Ue}[*GlI-`'+z6abNXE*2bpN:ʱtmo&U#gƪ̓Ԛvzسؿpo&g#99^~@;1Ë |q!f cUJ[.~?Ajo7Xf2 z׌TQX7ws&{Wmu.;V٭fo, 09''㚭[k~!h|v X`&Kʮ@ sꨮbWʯY}:ጔ9*r뭿 gS/d>'D34v\ 2?/uz{qEhJ?5YX3t{MwN áhN% \ߧfiEcv#б{l $d'qBN U!W{P]YZ_"0ۂMp~M5~?Ѡc6:V{]Ih|pn5{EFTB p ppuK?E<]`gxfy{f;{h- X-W;cB-)<l*f_Iv˖u[A"eʶv '#Z?6oo?Ls]<}W.k-VvYiKݷ&j^*o-[#Lw=H=d^\ɥIc4Xs5鸒Rܒp$r@nQSS9ٵ$E\}J&Zm~+ p37/:TW~՛N1ou#\X yAwV05YdӲЮN&֥u7_`2;~c }IExsRoaP/p0 c9vTV.ߏt_q̫F\/._#.EiRIMM+`VVV:-^oi`|QM"F͹b?:|~?1HGr( ڡQ!ȤW1L}adV˶ /^~ql]zdi$JY'‡<_O"cOAuآ~ql]z-*_t[#o0k^?y>E=OEV hZiͬ-K;Wj 3һc9,$sFN#Rʭ̝E=vQ~ql]z{?‡<_O"<_]++mWL?GE=vQP'#?Q }?=<_bE=vQ~ql]z{?‡<_O"cOAuآ~ql]z-*_t[#o0k^?y>E=O9C{xG(q( 52*TA_C'}f6asyq=qU\dV]FVw/$ +0 +ɶWO~ѹl/--vx6NJOͧ K,HRbRv'2GROR#X o-4CўYZ-4W_}uVE߈`KnݙaXFHh>#-08mcV3F@3'X,=Wm?XZ֎~3^ z j`Ml'_WcּW+4(zXu k{럱F#,d9?/UHO?-$c23*2Y o Y;rufxkg[4[bG_'לrp #~.MӖt彟e H=>j8J[× yN+ʾ XbwTT񅌷Qַn$k9FHc\d VQQЈ+<.CE`XMv,ϖ<8oX@2=kvm.'8Ny_OLXJە`q A[7aҵ-E0&U *yq[N VѩM^j?/AEVfaEPEPEPEPEPEPEPEPEPEPEPEPEPYA) (#E2bz*RQV_!VPM.Ifg]QyAGUEWܿȯo._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._fe{Q-w5ZtQe/o._Akk-OTcSEf̛9 _,SJttvgR;*p8z*:+;,Ƽmzwieoϵy3;v^sƋo CNim~Rf \0Xw}?*wv/;KgJ_j m" ʩICp1 w:>Ozu߅.]CMxF݋ݳ$3*m \q]m?^{_5{4V9O][խʥT: =<ڡ?mpWo-ޫ !׃}@>vQ mX!C1oߕVgѡ7N)6 QugEo筿{_EL1u`Q4թǕ.۫oOn&`UF0qNps[9i-P&,UKa=3]}_]̥[د}U &š~a]Bho efR =:|/mE\Dꤥ|UJ)R_ (9(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/shadeMenu.jpg0000644000175000017500000000660710504574206024664 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222ak" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ˈL(gůREv4_}?N})喡{$E<$UAO?\+xr/"s<0ǾPOh]_tG,^C2MRU؃P.L&p>%\d ᴷ'm5ihGrR\=A'*ΐ:gnU p .O?.:?¼ŵ]WUR}SʼT u(*FmNCX2amSR.6Re܈7Fcc}".!l[{y ${۠>%[-2]x졌 ";}}~~JA GQ-ͪ;@M,Op.FPMrYkπR]P<)d:d0mpAE j#E `@j[hs*E z#UESI=뚵-~ Rq9cKy++0j"&#~I,1wfv'$G$41\$Ē"xC+ ڀ1yҿ{mknaIHfEdY ʬA \aO((TwצWMM.w`\嗉ou),7cӶ{g|Kn;Hb'[^ppyNMfr6ٿeb_Sq>5a)9%c+YΖ"4붍- E+HB۟1A'OG,QK4I,W o[[x}&wPcst-nz%`mT]$G 28UŚTВo#O g-6Qv,4zrs0O-}K֊okr|ȺXQLlʗcISewq%ekp#y:(f)=OX\XX^M2CrwƥA`' RY7&F.o FJ۟1#G<؆MJM^Cë́ `<˞?v1zg^g^k+O wЍz~S$XV'l~^xi$hf=K礗fٽ3QnEr>1W/ul֒])nX/P}'ʳmK'Kބ+Vl +5E< A,VAbԓ^s lgivWW*dHG_75KC]#~SC:֩%ŝWr64d#H?Ho۷#P>3MnZܗR[mR@ _b7\ ^q .? ItokZe3T72Cj"HfM@ܬ@8FNk%#BُR4@u8اî ItoKC j+']#~(ZHG$G7 ֯3?/{]B5KCTQ3We8A$֊(((((((mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Index.html0000644000175000017500000000442410504574206024201 0ustar debiandebian

Table of Contents

Key Concepts:

Tutorial  
  mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/frontMenu.jpg0000644000175000017500000000613710504574206024726 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222^d" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?kKeu#k_y}%7rpNy"5.MZim0dW*!K'YvCh dqxFU+:7ڥʃ2Ķ }y~ʒNdFFdNzE[_Y^]hViD'MQ L`/ pAY:TrN} vY#-iO `u?SZ:?4}'j*(V$JaL3 S? @%o F#(fVnVnw3U' ,Oc{Iff~=};+XdY"we7gR2jz|eiSh,r,N?wG#2%FJ4t<ӛo:v]4d,qR *y!Wm(%r=YW!+ۋk{ hnV q2÷HuIyaX-PH8 C9#@!-xzTvssjKi5s 8c2ׂzQEB5xB5xH:w6]NC~IWmc?$(((Bj(Bj(yFcہ\zIyjmn-o=GKXj[hر¶UZItI`Al~{{*ZWnxuٜv9( E36,@kM\ZIpڕus#+y6m!qր իؾ8Ӵ~W=<1_g[۶B(Y29ǯQ@Q@Q@O/pQG/pQ@xj,. H Fp9AHstUu׼IgW;:mEryP;AxǨ"!PF>qUgžtHMV%dya_NA9&O7_TctNK4ٮ[d?!{T8yZڕoYj $%Pʛvctcp<*OLtu|G&:W { i'lX6FXv1:玕jLtu|G&:W1U_*:+O7_TcBj*C_$,Bs{Emgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Example3.py0000644000175000017500000000761410651433503024275 0ustar debiandebian## Automatically adapted for numpy.oldnumeric Jul 23, 2007 by import os, sys; sys.path.insert(0, '.') #Example Three: a simple surface and its normals #This example starts by importing the function which we will use to read #in a precalculated msms surface from the files 'surface.vertices' and 'surface.triangles': from DejaVu.doc.Tutorial.simple import readSurface lDataDir = 'DejaVu'+os.sep+'Tutorial'+os.sep #The function readSurface returns v, a list of vertices and t a list of triangles v,t = readSurface (lDataDir+'surface') #We make a numeric array out of the vertices so we can easily separate #vertices and normals import numpy.oldnumeric as Numeric vn = Numeric.array(v) # get a viewer: from DejaVu import Viewer vi = Viewer() # add the surface to the viewer from DejaVu.IndexedPolygons import IndexedPolygons srf = IndexedPolygons('myFirstSurface', vertices = vn[:,:3], vnormals = vn[:,3:6],faces = t) vi.AddObject(srf) #The surface composed of triangles should appear in camera 0 #The buttons at the bottom of the Viewer GUI let you change this display. #First make "~myFirstSurface" the current object. Then, click on the #Front button. A drop-down menu appears with 4 radiobuttons: inherit, #point, line or fill. Try changing the surface to Fill. While #it is shown in this representation, experiment with the Shading menu. #The Culling menu allows you to select which side of the surface is hidden #(culled). Try rotating the object while the front is culled. #Notice that if Front_and_Back is culled the object disappears! #To see the effects of selecting "INHERIT" for the Front representation, #make "root" the current object and change its representation from line #to fill or to point. #Notice what the surface looks like if Culling is set to None: If the #Front and Back representations are both set to Line you see all the triangles #in both the front and back. If you now change the Back representation #to Fill, you will see the Front triangles on top of the Back shaded areas. #Experiment with changing culling. #To make this example a little more interesting, we will add lines to #represent the normals to each vertex , spheres to mark the center of each #face and lines representing the normal to the center of each face: #To add the normals to each vertex (each point in pts which is a copy of vn): from DejaVu.Polylines import Polylines pts = vn.__copy__() vn[:,3:6] = vn[:,:3]+vn[:,3:6] pts = Numeric.reshape( vn, (-1,2,3) ) p = Polylines('normals', vertices = pts) vi.AddObject(p) #srf.addVertexNormalsGeom() #To add the face centers (by computing the center of gravity of each triangle): from DejaVu.Spheres import Spheres pts = Numeric.take(vn[:,:3], t) cg = Numeric.sum(pts, 1)/3.0 s = Spheres('faceCenters', centers=cg, radii=0.1 ) vi.AddObject(s) #To add the normals to the triangles placed on the face centers we just computed: #This is done by calculating the normals to the triangles: #from OpenGL import GL from geomutils.geomalgorithms import TriangleNormals vc = vn[:,:3].__copy__() #nf = GL.glTriangleNormals(vc, t, 'PER_FACE' ) nf = TriangleNormals(vc, t, 'PER_FACE' ) #Then by drawing lines from the center of the triangles to these points: pts = Numeric.concatenate( (cg, cg+nf), 1 ) pts = Numeric.reshape(pts, (-1,2,3)) pf = Polylines('faceNormals', vertices = pts) vi.AddObject(pf) #'normals' and 'faceNormals' have been show in the viewer as a #collection of lines. 'faceCenters' has been added to the viewer and appears #as a collection of spheres marking the centers of the triangles making #up the surface. (NB:You may need to do a "Reset" if you transformed the #surface in the viewer before these additions.) As discussed above, transformations #are directed to the current object so that it is possible to transform #'normals', 'faceNormals', or 'faceCenters' independently of #'myFirstSurface.' If 'root' is the current object, everything #in the viewer is transformed together. print "end of Example3"mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example3d.jpg0000644000175000017500000007562110504574206024637 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?lY<nCuq72YgOY]˯$/ukX;ޛ7cTw\~2zFׂA-簶 [h觹ɏ‡g%N3i{/_ljp34YzEu@k9Q$WsK4R4Bcm@͓qQrM4F"40Pˌ~_Sp34YzhH1gۯ=aӬglE nFOs{aqT8Ɯ7V8*qcN|uzgU [_u62h,~n88QTlM<Ѭkyn1*"upy>}P?[9"_}CakxgE9m2׿A$FgHH} W"խcݯ-H#[rGs֦RQօ 3#ÿU$Ѵ եkyT$ ~ǏC4~{|Oڕ.0A\8skWg1gۯ=5> SO1Q>\xSb2P/(P?Gi:M-_^4{X+_z3vwPݭtyU .FqO\n<7 ѹio[I 0.z0 Hc&zau![qOhWgiq;~xAʍ>>U=CN}Y繴X"㏔+)Ԇ?imǪ?xRk~k~_z:l0:yS {/H0fmcK&:XD9$u9a؎sƏC4~{_EyN1Kn=Wװ}M:M-_^4{X+_z3(3)Ԇ?imǪ?xRk~k~_zec:M-_^4C4~{bP}LxRk~Hc&za=C/WC4~{_EyN1Kn=Wװ}M:M-_^4{X+_z3(3)Ԇ?imǪ?xRk~k~_zec:M-_^4C4~{bP}LxRk~Hc&za=C/WC4~{_g&A}&^!MByF#)Ԇ?imǪ?ouBOK&!L:hWgks}y#}8Zө+k$$gvNL b0omԁr9c\~>y?^mρm>.f^1}rҳ W~hǢ+C(((((((((((((((((((((((+COK gֆίv`?Ϡ 9>y>}QIϮy8+Lo\72߯kc(+Qys/>y?Yهw4cEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEǥsCOK gW;0^gZ^H(?$(?$ג?'ӏ 5 9>y>}Vo"5ۏ3s/sy?^j%..^̼wCOVsu/QEhrQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@hi{\CYNף!'>ג?'ӏ 5 9>y>}Vm"-?G72?>y?^l qp1:?A:yg?'^ޯяEV QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVϭ ?=/5_z?ɟAks}y#}8\\hq`+1^;} rҽvcvyw2?Lsk8xm0}z(9(((*ͅЂ೻$j:zj+-=Pi.&DaO9ۂYpeU9=9$h/C4̲rKgy .3Vgj@{EvfM[s!.Q{2 M댷=EcQ[K [`+rx(((( ?=/5Zz^?k: ـ:>?$ג?'ӏ 0Ho[`>qy~uJ|[0~pqxG<_\?_1袊 ( ( (m l xlۑ1Ezs]5mgytMqT0ڣ#K:zVo(-0#$C *)qh rNrOA.[no.IX'6kVŦ:"Xp&RFVa sg' _eKĬO$HIWBjPe#~hMŴ<ɓӟS Wvv7~jkZ_9RKۣ#smF1U5=>k[٦@a#Iz` l8#np׶]͵r$:SnwVc&VPWtC(Vq 6QZT:Z~:F> Bmah ڴ2@~meT%6F0v%k(* -qĄ dPEPEPEPEPEPEPE5.|Ǡy> >(eE o$I'aE+nsb>AªqG@5K}5ҴwF_Ia 8$OovD̀@) = i#k=hD,CE:mg܌)mypZ[u BSv?u]ZI-6mBgͻ~OZpjzw1ͨ$gIPsbmʖ۸K%eej%@I?18ߎ1XZC8hmlƙ]\_%͔żW, :?Q@tUKqǖek23Ig`NI KYuY?|L3(pH`w.2Č74DՆdS^9s' `r:VƓXij\FդQIYG!~n,2iX2Ym  Ȃiצ_i7Kϧ^*?29#v.}mŻR 9sN!YYT2(((4}hi{\'fL \\^H+Cķkp \1ϣAOW۶[s/skuaݪ߲яEUEPEP[DmV-T:>XTa{:6lҮBG$[GͿ~Y")/59& h۾~AКw=,2ʦ$aZӛv;88;8$|^r-=owITrzN#F!),Q󃁹 RqgWS:Q}O k_}pc P05s}:Y xfQ y%@RIg{+k=>Py#v7WKi,/xh3)nG`NCG!ۂx9mF"h р#`x{9K&jHtK(7υ^N_Ojݼ]I!uU fvI܊ T*FA"ޙ^hŌQiwjt?|CBK&Us1E[ q+Jٚ o=vD`2rZMq-hii vt Fv1!8McZjzV-6TXMn6ȸWLs"Ɲ#T7my`|<[ zH 7=6Uji1Hڣ>6g} i_X]3uyk 6Ȑ)IvX`K>t,6y1Uq8I~Ys, 絙He\nI35wY[Y ¤xQ_m¬nrAtoxb-VV>\$>H!$o "0Tƛ@Q@Q@V @DHcm 78A<&2^j[EͳcsԌ sN+}>S6w7'U/ߌλ\=28"Cmpqrf݆(N>RB>lɷ𾑧2^F Vj]bFxweݡq*i Dg n+;AN3+CRJIDv8b6# tnn hU777/`w)'v@75;hXQDvN%ga\ ;WͽDP]mrZ/N9BTܒv2wsծml-ndٝnP8t+l ƣIDJKzFyN9j@;@v[{t5` Ib31iM+jg$H$ݾXi}t5+T@#V@i#?.pNXH6m2P" wM֭oO.'gSG`SjFK)q[ΰb9toyǵmzOi= A$m!EќksP[GWKox\gp)c&n–U1jmBTSǟ=0_\_ڌi,Ikt%q|2VŐH йo4結߾%%8hC!.$=Gyu o42'\f{ : Fݦvg=<{y^K.1mM𠏘1!ydeh|w#ާl'*͕^&i3ǩX[K=A+? Ry, ((+COK gֆίv`?Ϡ 9>y>}QIϮy8K~| o_7z>N} rҽvыؓn.31ϣEOVsuᕰWяEV QEQEVY%bA?~5SY̶LEr\9H5(['x`8-ĖF>qL0I ˫ѽͰM*ܱ:1vLP̆HNb8FOT @1OԡH TA ĐF)Š$e/!coC:c gH.mVB ڎIa,<;Af$-"x#x FͭsDhޡi$Ƥ9Cm7+Et'N{|Op񋘙HnH,ɒU m̚my-B\dBvȽۜ6V-" ұ[ALӰ KrqǨ#e%ΓC1 }Bd1#6/o'ٰI.d> 15,k`FX?ƫiΟgj7w}h`[GX` *q'.j-ˈAUU@̀ۜ:tf3d+r}܌$df`Fv-wW}6v2!ʝ2fRɂ2[HX\Z,1Ϋ͛HwY=e^2H0)z'uvIH"Tgˑ_\ڢɨ3` n3*0\dv9]햗5S!Ԉf'espI9`p3a̿3Z8ڼ#&9 9cn4.,&Na"F8T]A\0|.$[V'X@7L0 1ggc7i7vЋdB\D嘒wy#`=մ-S-2#HOz`djáI>,YE Hw\.W*r@f9FEK wr&^f;w `c':6&XHvE0Taq?Vs#EZߩвG0Gqt{"k ͢n`u*1$OcIbKa,Hb99 :L YV#,# pB*ы._F[{`й ;.Ϳ$Gp2s@ m.$c|TH3p;gF[U ") 6 tQy-4ygPb!` l{oJrI$Ҋ])'ٌ5ч9•S@$`kv# |͓.@!KNKq׬cԮ58&Zȯq ݃W<)NAaSTxQ7)VG 1Q̘cUNbMN.6j'33"J Q*Xd|n_[hgdhK䃁XP@A4I:){3U'V'Ld je`q%lmldv#>1MN{/C\$wr m$|R1HxWѥ$Xo,X( w.)T0|Gm.cv(:  gz-7_s8Y4OsfL?dbNw*uO՚HV[Jc(q ms@wEPEPZz^?k>4u~u&}IϮysBN}sϯ$Otaڏ-:\\ cney?^oAG^2߯k8xozF=QZEPEPEPin#{Q0FU>CH㟼zVv6ﳎp{ Pvm6?l-P ʤLUlt_#O!q,Xnv f2๻fڒ\J`#ysIrFE7JE|aFG8>^ vQ՞I0Vb`n tcbv7(%RUrItuP]r2A o K%A"m<|hݷU#mZڍKMWLi ]7 8PMcAg%ɃG9$G˖\a s7*n^k Ҥxcnդ{`*:s ‹Xi=ɍ@ 70gʂ  [H}w3gt~NdnAV;cIRd fW1yܧahxSNk Y%.szp*HIA*/ 8;.Zu ɷ;6%% RYXE hVQeSsۊuki5);}Nx&h.X͸d)I^AVӷ1t܄(e$<~VcL k!$x#,mʪ$F>mIҵ#8$WF g i &X]:t$`E9"xw0PPcpNG,.מ$*I5S-رp7ΌAlɭLZ$]͝3~YP2mZeWNK0Gnq39Zʼ[*xeG$̘`1h9l#g0y]iP[Z}~7 Ɔ$FvK(puֵ6I_<@eT~0J2 ֵ[iv9lrX<^Uam2.} 9ʲyl!l$g$̱.rr$v*TŶmSO$ٛyVBw1Rp;Л-2³\a ́=aPNA0N]TqM,2C:y-M 6WhլŌf zrǏpMuzTqYᧂ5I ĩܭ3`}b.!LN:_YڲI,"9(7(Mr`sבPRԢE$J@6VUgȡ?6 kiWo!=>;`,ۄPĀ4os+>]h8Ly +dW9_Ecum   28H,ORLjT+o0ʹ0l=yE#K)*Jaǡ)QEVϭ ?=/5_z?ɟAks}y#}8\\hqv۾.^1}rҽzԖ%y?h~uJN7_E(@((]cnqd-8wX1;qb6:`Z[y:Kl_( Tw0}W[ fבu 6gP]@2zFRi$B`'$I$յfÑA,W  p7+D1$s5GV*pr!Ⱦ`)y@ +X w3\:368u0 O|  Y61FJn ꣃ`[wqm$9&m>| Qf#DcʡnK)`pY)%}^^P}ؐ2̛ `4s=Ojnb,n!bJTl 6 9u(n-)5~b{3@.O@7tD&BFI#'J<s(e#O AujlU6 pw>{[L]ؼŌr~`+:R+mjȷ?ohfUpz SCixՠ̷VeʪhP76<2pG ~hvEK86!@Uؒ;$DetԿ()4A"0X!%b +\mYn59 m4*p3 r1} HMg[ť\X3sĶ߅-ԓ[{h>.÷ۮtcֵ'%yҳQ:@-j<6s쏅};!\;@0l&lJ-4BҸ'(w3(ʡ:< b6}*X䐬pVmZ e` CFN[225,01!\3rߜFN2U `6X g.R&Xݵ(Ğ%w nėWsjW2HԂUFvIPsȗHeZY-y';Lx7WZLmAf""+8ĮxOLd`.%K# N*CO'ypR,>HtVTWN<V4Q԰OI#I=TŶOIr1+*n~Brzds-r.$F1q04X &}3m+Sst9s@B4J#FEk͝V@WA9<5S-ƭg6o?P ;3:5q>#Ckb9X1^$~%UekYZFRGN~;@$0x~YğhhȨ^9#β<1q$.$n. -Hzߐ.2n$ 5MEn."N'1!bd%KՒ2[`\ct 41%wp.OXc$pr/[8,614p2 |*;:~%Y$=ƷcTO<) IVf9?$ג?'ӏ 0ۄ~p~COWZ7,..ɹ~uJN7_E(@(((Z[UӉ%YGOT'<7tk#!%>Y3tܸZZ//*zGb@ my­Cb5HG'7A!$Y@LHBN;#ʼH @ebx# W4MR9좋ʕ;Nw"H9Ԧ+ &AI,A,@ {moQR#!s Q`uo1.!pMCg5Gkq4N !62e{.I@6S bB ؖg1BB#+mI8fF3$d~ɯŠfHʮZ#el($'Xl/MĒHWnqop@KLso2ƭb0w%r[-?L; m.,(xߌ1VεKQZf ˎ(-3ֹYoLi , [twvMǘ,;m̩Un܀gO4W -h6#iB19c19nnvl& 4nݫTc眜2{72O(q\eD`I݌q2dCH ȫ X7$n8_}5.-0DXRU1)$²[MIR`DF0|y`'1:nyJ4XX(SBMLTfEŲ3;ϒC v i9-X ]6d![5RJJ9UUWn2I 3 ԓ%xL$r,? L@ Aڪp7QHsY#A_$L,G8 6HMeK *o&w/ bi,Owz3DO s#[l Xdi#9vng# 1X(Xo>Hv 0?y [(s#ܴ)dUMb$mv 0 H @pErkH+f;2xP7 lc$W7 5a&q@{-kUv7Yytd\(#U&]D%h| 2sdз+$22?T p ]2)]SH+!ʹ19 BA ‘Hp8`c[x Wc/|8,p|k>ymY Ibps9݁Yz&b[GHGO@~R]JBep-#N 9brgYtLikgs/xLH #Q4;;vcL@mT{p0G roPt}bF:&8 +uPUۍ9 (b&x#2q鴆z &Itٝ- 3}gګJ ɨ#IW[uP>^z}eܪc*XHOTaHq[66Y #,p$v?7 . ܐDѬd ˎD!ʃ$g9jڭn"{ɎTJ.27}0T 8ݼsF/p8>0 pu5>pC+d囯|=h[Yeyn \"f-1C{r #!w9cڙEQEQEQEǥsCOK gW;0^gZ^H(?$.e_)dtV2m ' 4ۛ \ܣ@3=3`78jǖKhWg *O?^T%$ =.1皩9ռ46nCp ʐ0='fsHg^5*jN#GYNoec+bvWo|I9#(-Sr~fy,0er2j-j~%a#SP!UU*X#p[PxX譭pB͎^]_y [q H.UHր-q4f \xpg+krWu8bkd : 8iBCP)7NkK,ͻ@9lpYH xn"Gm@Z=7 %1lq$>jY6i tob?Lj6Xzڠ:d0$v8V}΂=o7 3>ag9Stq3}Eo m˸rNbI+CõK`$\\1ϣCOWۨ_[-Žne=9~5JN3яEV QEQEQEQEQEQE,77w]W?K??ƪ@z^39&HIJLl9=q;uu}>SsKw[#+G{͑yn]:xx9 _iu˧M/p| @]IPW'=OUPcټG{t/&B7 4-*^M u˚$mh,L`+ѳm_4cI#*Kx(sۣTZ˫fJvpUbu_v22A U=_M{f'd!, A1 Si-ͻ\D&1%p@I7}KJ˩ޘnFU "˞Ts$Pz`o!Ͳ8@9*ۆ8yukkQ8Y)U@8g&m5촍,)^6J߼|{֕Xi$1I ăԆW_+#_Niq0vG g\KbK%O40H̢&6a:~Hϳӥ{8Xf`ΩIz]CC 2h 0RN8FT+L9&AݟRuZB\4u~u&}IϮysBN}sϯ$Ota.۩ss(~}rҽz۟ۀ|\ ̼c?A:yg?'^ޯяEV QEQEQEQEQEQEQEQE[;!x2l ~R79qƅq}G{o&YKnyڍ*Hg==]ozfHV Ī<ïn#֗xX.U o@UnJ홋J f2 ZLp1i e\4,(Bg!HyKǼf;;Q ;M.zgq V걖5_+ẖ v <ق 9lh;\3c˓h\} xG'dw B_,ʤes# !ڌVo{k!P ̲M )#i9'-3K'[A y%]Z\Xgc2mfW9$ /ҋZ{W\Ay`29]m>d$]ōMMvRSr %K.w0mrhcBO. wsō[-OTD]X(WQ-ב[XB]@~P FJ6fGz\T!bFUEjڐP!6Lu2Qד$jPӵ *ea .CY0hjmP.Zb9?$ג?'ӏ 02|l%pz~EOWُFs̿?AZyg?'fޯяEVQEQEQEQEQEQEQEQEWkz`B\ bPg *h/̑Q9j}鑎 \׶A4p)Wn*8y~G:ЃM/m,lyjE(w+nT!;@E  k#1ͻقwS9PM $S;wv99бN-.# IjW@vۺ~1<S@ iImHݱrM2 ( ( ( ( ( ( ( ( CYǥsG3-sBN}sϯ$Otks}y#}83[ne_!'+׭y%?.=3s/9G<_\?_1袊 ( ( ( ( ( ( ( ( 4)M'Tǖ#XַlIQԀC.q i, @9;QY.f,0#!cvCcp?03aNj\U`ګGN NWiẞ2Y8SpgHO%\)$(b Gԁ]7-vUQ*b~]žSZI6-M~L'Q=‹̼{y$F; h0l,T݌{5-Ē?NU0A#%Hm0HȬm.yZx Hbery;GsڮnIJ#&UBt)@_9$Ke@t`y'VFz/?yfM|'d\\9v \<=9'YiYc}*7+ qy>}QIϮy8;`mtsӿCOW[m> _G<_\?_1袊 ( ( ( ( ( ( ( ( o.[,b2?8o >q-sfu<;>uPH=Y$S&~q$ Hk6/2ߍ ) yF?jk7\&`0y;g;sqy \bKf%bF$Mn{`1\d0n5}nm -&bv,2' k6iskdF`\nG288;_|0~w'?w$) lTӭ #*^9K 2 j]6i"Re.9R]mn/3G_󓴐TO ǀ iDcMNp `-/H*@r 3뺶2 E<2O#V h\ 3ԜM?ZbGMҼqD `(9 W9yWN(j*= Xx?7DEru{UL(Ŵ6(yO8Q(((((((((4}hi{\'fL \\^H+CķmM9G<_\?^xH\f^;q!'+9q:}z(9((((((((( }"ybF$\QuymI^A fh t$r{;Jъ4\^Y4èͻ=jY3:+T$Nݸlg vo".2A27-N3l/NUs<@cBQU*((((((((((+COK gֆίv`?Ϡ 9>y>}QIϮy8;omHr99~uJ``̼~?Nq!'+9q:}z(9(((((((((((((((((((((((4}hi{\'fL \\^H+Că_72߯k붃S..cG<_\?i4cEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEǥsCOK gW;0^gZ^H(?$y>}QZhrI{H#v@+Cķkp \1ϣAOW۶[s/sI,φ|JΣׄxz-l4bQRxK|>q<% _2aj+~q<% ee=Oq/n?焿_̻"-4}xK|9p5?TTe G2Ƨ򿸊_[/h]WQRxK|>q<% ˸{**_ Gn?焿wcS_EEK[/h-4s.j+~q<% ee=Oq/n?焿_̻"-4}xK|9p5?TTe G2Ƨ򿸊_[/h]WQRxK|>q<% ˸{**_ Gn?焿wcS_EEK[/h-4s.j+~q<% ee=Oq/n?焿_̻"-4}xK|9p5?TTe G2Ƨ򿸊_[/h]WQRxK|>q<% ˸{**_ Gn?焿wcS_EZz^?jn?焿QI&cpx5VN 9ɴ=\\^H+Sӣ[#Tqe݌9$.nurBL_zQI-tN&ht%?^q$֕Tnb$qg=x(pkG{$>V+yZ <)2X=xhg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?g޴:ggg޴:gg{8v?xCq,>_zxCq,>_zQG`#~?&փO*B@~C׉ Rr\JvpF3,{8v?ht%?^'îZ gY^ (`xG7.̪Wp_`*smgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example1b.jpg0000644000175000017500000003412010504574206024620 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?'tHk 18i<$s;~= i,BMCϫ I:.u N9-`_Fkx=[,t3 %C(*s%:ucW?ҤOizڽO07|"Grx94sG8Ӽ=qX=}Ѩ:焎qx{{zgWP5}@c*N1?~^>D(Isg\4sb|u_lj#i8Ŭ^H,}cUӨ4'02bDjvsι#i8Ŭ^sG8Ӽ=qX=}ѫzd8uyfV.p;78xAx,SC2޽?|9ƝsZU힍A<$s;~=42š4b˂9rZxKdR*U|tqϩ|9ƝsZU힍A<$s;~=_xSuZI2IbBkRvVQ\XEF!s\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^տP]˹P~5-J Nx㸑U_8\@8îxHw1k:Wz52}gSC,k}w(+m#  t]X8Sd֡.[qǠhY|VЦ3$op-Hu|H9#bi ~[=Nl?lI-;~1'߯_Cw47eocϫmG.Fc8a_a|e?\U$FdDksyf& g#Q=s~c^^R]rٍ 8# ڮwX2sks54KoI8AʓI>.Fc8a_a|(lg9?1 #iҴ.ܓJyqvMgX\M3 ҜP8 GEMч=}=h?鱜z0篿Ǿ9m'P@?by]N *[295kI q1XP= ݳtcg63F|]qÞɋLq]6䅮 m 3ZgQ[ZEDžP8 t(lg9?1EMч=}=˩ MoM[iAU( IⷅvEp9v3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F|]qÞQ=s~cVv3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F|]qÞQ=s~cVv3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F|]qÞQ=s~cVv3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F|]qÞQ=s~cVv3ǣz{>.Fc8a_a|hj:]=3:ή1\q',/a,,1?1Ӓ4u/hRW/ELp#xge[k6h9cw$hɷ~Nqo)0}GZ>.Fc8a_a|6_hG0Өs< ӹX:+:Z+k|NW@vG t?SX'W3K?1 Z#p>y}].*U5z4ԣN$[ظ_?.?ƳPevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_ϢevkjS\]$NlֽWsxL;4NB/ /IO/ퟚcv5Z\*Gw$fx?^y~.oν|9}sϫAusFu_d䈨 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (-F|xK{g=7B~?׶xo~Oy>lϑ#p>y}]ׯ?^y~.oΏy$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEoM_5:_8_ϯ3?7F|xK{g^|$fx?^y~.oν|9}sϫAusFtϐ?5'"*(8Š(((((((((((((((((((((((( zo"l}}OM_5:_8_ϯ3?6v?5'#3|9}sϫAusFu;G=~׿}_ 7^|?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[!{g$'zo"l}}#?;G=~׿}_ 7_29~\G]ѿH(0((((((((((((((((((((((((ޛ!k<7ǀty'q<_|g~o!{g$'͟H29~\G]ѿz_sW<> kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@E#^<?=x!k<7ǀty'q<_|g~lkOFg_sW<>w̎zßGcs_3 :?QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP7B~?׶xo~Oy>l'B/ /IO/ퟛ?y;ds{> :#p>y}]/>@䈨 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (-F|xK{g=7B~?׶xo~Oy>lϑ#p>y}]ׯ?^y~.oΏy$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEoM_5:_8_ϯ3?7F|xK{g^|$fx?^y~.oν|9}sϫAusFtϐ?5'"*(8Š((((((((((({ 6eQF2j͎siYf8r7[\bʥʓw:ObQZPӕM.FrmE??$2H-yQyO$3 N38MMkjtK:kȧEUQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@E#^<?=x!k<7ǀty'q<_|g~lkOFg_sW<>w̎zßRǑ1~lU [i//o$mg[j,XrpZ!gvL7BK2OA! K3%ȞTlԥ"DN cwLq@ ԜohdnĦe(#BMlϑ#p>y}]ׯ?^y~.oΏy$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEoM_5:_8_ϯ3?7F|xK{g^|$fx?^y~.oν|9}sϫAusFtϐ?5'"*(8Š(((((((((((((((((((((((( zo"l}}OM_5:_8_ϯ3?6v?5'#3|9}sϫAusFu;G=~׿}_ 7^|?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[!{g$'zo"l}}#?;G=~׿}_ 7_29~\G]ѿH(0((((((((((((((((((((((((ޛ!k<7ǀty'q<_|g~o!{g$'͟H29~\G]ѿz_sW<> kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@E#^<?=x!k<7ǀty'q<_|g~lkOFg_sW<>w̎zßGcs_3 :?QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP7B~?׶xo~Oy>l'B/ /IO/ퟛ?y;ds{> :#p>y}]/>@䈨 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (-F|xK{g=7B~?׶xo~Oy>lϑ#p>y}]ׯ?^y~.oΏy$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEoM_5:_8_ϯ3?7F|xK{g^|$fx?^y~.oν|9}sϫAusFtϐ?5'"*(8Š(((((((((((((((((((((((( zo"l}}OM_5:_8_ϯ3?6v?5'#3|9}sϫAusFu;G=~׿}_ 7^|?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE[!{g$'zo"l}}#?>7;r `Kd@?8,1oν|9}sϫAusFtϐ?5'"*(8Š(((((((((((((((((((((((( zo"lݵǁ4wq} duRϗFN=23zo"l}}#?;G=~׿}_ 7teo[ϲ&a1$v;=ǀ?8릞:_sl))]"ʌ{:{_GQ^<nq]4e?Y߈{,7Ȩ]8 㮚xM}}[FqM9eyVQuO?鯹A+s:駎G'4~!?O"tx *03i5?<nq]4do=~? TW[FqM?8릞:_sl<+s:駎G T`gtOk#퓚}Xo'Q^<nq]4d8 㮚xM}}sO ?*+G?8릞:_slVQuO?鯹NiCaEEzT`gtOk#x *03i5?>߈{,7Ȩ]8 㮚xM}}[FqM9eyVQuO?鯹A+s:駎G'4~!?O"tx *03i5?<nq]4do=~? TW[FqM?8릞:_sl<+s:駎G T`gtOk#퓚}Xo'Q^<nq]4d8 㮚xM}}sO ?*+G?8릞:_slVQuO?鯹NiCaEEzT`gtOk#x *03i5?>߈{,7Ȩ]8 㮚xM}}[FqM9eyVQuO?鯹A+s:駎G'4~!?O"tx *03i5?<nq]4do=~? TW[FqM?8릞:_sl<+s:駎G T`gtOk#퓚}Xo'Q^<nq]4e-w?T quldo=~? tW¿$N!ڲȄ駕`?}}+s:駎G'4~!?O-!{g$'͊<nq]4gK힗ѹhK2qzc9s4:ҥ 9_[nG>$#wlO=\c1q~B+Cq_8LOoa WVEcFەx QE@!K'YvCh dqxFU+:7ڥʃ2Ķ }y~ʒNdFFdNzE[_Y^]hViD'MQ L`/ pAY:TrN} vY#-iO `u?SZ:?4}'j*(>>46 $!Uf$D?**??e]#R@~JA GQ-ͪ;MRgv ,Ni { Ho3,pqר#E+hQ~X#{~` #&jQu6X w" {r3(bTd`3@gL39hi<#FAB `⧒xH&2QW#ϡ>q6`ʇx!;{dg]nHgUHAT=8 rxTSFDY{֬P$K3EbY$ܓXv~-ּܤ|_(J T#8 ^+g!vG+gUt6"mȈ8W^(#(W$Fʠl8P3Gg<64Z;g0Pv3/=x'O@Q@1=,Z(_?-m=F7+V$pg?^m-B V:sP?)^M,+Tu?Z"XiUY+7ƥ=6ַ)fLIE(WeScʌQ@ yo%H>%Q)U*M[He/ < m5Y;\#ݶ%s?ʹkA`e^2GOg!ՇN%)TtCNK+sqovRy:;g"kQK }I5T&Ӯ-u$mJ:LJ68Axʞ}-[ŸS+pW.@U rqͭ_RWvY$BE7cWk Bps钾n.κJDJCdc =Ecjom)*Q+=Qݼw:+p@Մ̓l,-ې3 qF<ǥtKE{~T-4J/ALo`ᶠuc޹;G[F3mA-9: )]2`ro@izt*yvtW;m]M8Gڵ{J'4u+lx#T+{vHXK&G=sѢ(((><ǥtKEG=-$X] rn#PcC??ŘRāgD>X`ݎ5 SšniI[ZDLO,+rI'ıcQվO@O 4.7ViI'Q$}69g z蓮琻VVa./Nd$e@Ep:l2E*ZH%DEuRr 6 8S]cjV,䘠GHql4-IMKxI0FF:,cMirB2BTXf|wcjXAum%$[`\Fm̪Gp;žRmjK >wڑIkV| #>]Equ jR_^L#1 3TcjKאI9-_,M,<}B$7\w'9 TVjRa|$f+`$O&)b!# ld+{vEsѠ(_?-|yK/k w Y31i6M(_oƏM(_oƏM(_oƏM(_oƏM(_oƏM(3êki>V62QEmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/camera0.jpg0000644000175000017500000002520410504574206024255 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?ݿߋ5+-r=>-Cgˀ6T`+8GWG!x"texo!#MGYح-E蘀v{;nEvs~!Ʊ${0Fydc'<vͫ4wr#x"/Ns}3Zx-i9.UZ< e!;F3^jS^.R[ȠN?ⳄxM=}S^:OslEOab0|Jq#Oi#g*{fJ(,FN?ⳄxM=}S^:OslEх)Vp?駹@|Jq#Oi#(0>%8pU4?N?ⳄxM=}%{F#ħY? t>)Vp?駹dh`+8GWG >%8pU4?̔QXg*{dħY? t>ْ= S^:Osl+8GWG8>4gth^)d n%%Ԁpzpz+&ml=Rk.i`?/I(;[ RS^:Osl+8GWG>hDŽ<1<6!e jx;`r(Uw [E;b;B[8H5 C)Vp?駹@|Jq#Oi#>SFpьC%ĥ-J+yixROim:$)>SʀhC)Vp?駹s.GX=ϏaGO dy|U3#}3JInK:(mi^L+/Q%~lV~[ڷ`,Gς: 3҄|Jq#Oi#g*{fJ+?hb0|Jq#Oi#g*{fJ(,FN?ⳄxM=}S^:OslEх)Vp?駹@|Jq#Oi#(0>%8pU4?N?ⳄxM=}%{F#ħY? t>)Vp?駹dh`+8GWG >%8pU4?̔QXg*{dħY? t>ْ= S^:Osljư*[E\_{fZSa98c(,(>%1ATYc/`8L>%8pU4?sasYCߧ=;>,n<-p<& Cx\dr1-lGY$r][.X"cgcy*ֱJ^Dӭe m.48=e>ٻ_~\0M?7mG;ĖzƧKYDӮ$ :\n@Os5f'd0޼ll 9V $~8£vabcn81n}Rwj!t^,`YC<'|oj0g=}=fyXo*11Q'5܋?RӓvGbJ4:5_ǨA r02_AxïpɨW{`}p?^qȿ#4l\r/?g- ?Q=y?18a8G^z{.?Ə틏EL7>3Fu篿ǾQ=y?1ظ_?.?Əe.߈ra|oj0g=}=|g'_a|x"qȿ#4{)vC ?Q=y?18a8G^z{.?Ə틏EKo'|g'_a|ƣ z:~c'qȿ#4l\r/]=8a8G^z{>75N3מ?틏Eb~GhR&~? ƣ z:~cqqljl\r/܋?Go90?Ol>75N3מ>3Fu篿Ǿ3Fu篿ǾQ=y?1ظ_?.?Əe.߈ra|oj0g=}=|g'_a|x"qȿ#4{)vC ?Q=y?18a8G^z{.?Ə틏EKo'|g'_a|ƣ z:~c'qȿ#4l\r/]=8a8G^z{>75N3מ?틏Eb~GhR&~? ƣ z:~cqqljl\r/܋?Go90?Ol>75N3מ>3Fu篿Ǿ3Fu篿ǾQ=y?1ظ_?.?Əe.߈ra|oj0g=}=|g'_a|x"qȿ#4{)vC ?Q=y?18a8G^z{.?Ə틏EKo'|g'_a|6_ 9 Cp{IvCm vSԼa ؼ.1mYޥO!:s*Y`$KHm`>Vy' G`b09خx$ColѪvhU(ST9[mnoFKoi%y%]-R (8((((((((((((((((((((((( mν/G]?%qm-ν/G]?%qm#?Ke2_?dI+( ^aEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE-}]ץ+?My}]ץ+?Mc?v~LoFKoi%y%b?Kl( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (%:Et4:Etg?/ɖ-}\WW[$$ G)z?ͅQ[AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPt_^Ȯ6斿t_^Ȯ6?G%2ſ/JJ2_?RA/G+c(((((((((((((((((((((((>W&޼>W&ޱ;cĿ&[#%sI^I^oFK[16QElqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?z^"JDךZ?z^"JD3GldI++-}\WQKy#Š( ((((((((((((((((((((((([_/KWO \zK_/KWO \zoi%y%zſ/JJ)o QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEKkpEuz?a+o^ikpEuz?a+oXt_-[$$[#%sI^IE-R (8((((((((((((((((((((((( mν/G]?%qm-ν/G]?%qm#?Ke2_?dI+( ^aEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE-}]ץ+?My}]ץ+?Mc?v~LoFKoi%y%b?Kl( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (%:Et4:Etg?/ɖ-}\WW[$$ G)z?ͅQ[AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPt_^Ȯ6斿t_^Ȯ6?G%2ſ/JJ2_?RA/G+c(((((((((((((((((((((((>W&޼>W&ޱ;cĿ&[#%sI^I^oFK[16QElqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?z^"JDךZ?z^"JD3GldI++-}\WQKy#Š( ((((((((((((((((((((((([_/KWO \zK_/KWO \zoi%y%zſ/JJ)o QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEKkpEuz?a+o^ikpEuz?a+oXt_-[$$[#%sI^IE-R (8((((((((((((((((((((((( mν/G]?%qm-ν/G]?%qm#?Ke2_?dI+( ^aEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE-}]ץ+?My}]ץ+?Mc?v~LoFKoi%y%b?Kl( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (%:Et4:Etg?/ɖ-}\WW[$$ G)z?ͅQ[AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPt_^Ȯ6斿t_^Ȯ6?G%2ſ/JJ2_?RA/G+c(((((((((((((((((((((((>W&޼>W&ޱ;cĿ&[#%sI^I^oFK[16QElqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?z^"JDךZ?z^"JD3GldI++-}\WQKy#Š( ((((((((((((((((((((((([_/KWO \zK_/KWO \zoi%y%zŠT#9%rrO00J)o QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEKkpEuz?a+o^ikpEu;0Cms{#?Ke2_?CQ=ٴo8F{kg8<F@Mw%*a.VeKP$}]YQ]_!5WKVvqԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥQ]_!5WKQWgԥ?z^"JD9hW KWWecyaᨒPuKZ6+[8#>՛4nanIxRi,sbh)HH3ORMPh(((((((((((((((((((((rHhݔW*q#mPEPmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example2c.jpg0000644000175000017500000003464310504574206024634 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?y.s  2P:rI.={?]\LCN>[v\ sSYuU}Lvs:IJtusg^=3?w8ˇaWEkc*ǩ_}wIi1K32g OW?z)C>SS܇}!yqno5GRMY33HO}@?]\LCN>:~KN3/r􇟻}t hlg;Ynwn`m뜂ǜc _cӌV EPgEq /N@':~KN3/r􇟻}tusg^=3?w8ˌk?y >숪 vP2O|taⸯnC I .WhQps0Sk?]\LCN>:~KN3/r􇟻}E/&.[bP/E8zg~q^q{Ϥ<.-@S܇}!yp?]\LCN>P/E8zg~q^q{Ϥ<.-@S܇}!yp?]\LCN>P/E8zg~q^q{Ϥ<.-@S܇}!yp?]\LCN>P/E8zg~q^q{Ϥ<.-@S܇}!yp?]\LCN>P/E8zg~q^q{Ϥ<.-@S܇}!yp?]\LCN>P/E8zg~q^q{Ϥ<.-@S܇}!yp?]\LCN>P/E8zg~q^q{Ϥ<.-@S܇}!yp?]\LCN>P/E8zg~q:n>ӣ%!"y^q}Wi˷oˏZt~_H/E8zg~q^q{Ϥ<.wXO\ѐ(U,m\zWko"yX}B ?(^xaOW?z)C>SdEtt->I47w$$P^q{Ϥ<.,iܛFdkHcqi2\g9iw4ҶLBJ0`çpksÇ:s=?׎:L v=6ȼ}@Q.Ǧ +v\ s]׆vKT K4vEP%2On* U5nKie) }>ߙl[^2G>ڰ-=\clC6tSWhFWWÚ|:;ao$(vnSW<] ~=?? ;]O{xa{Xw4#;şC ]AO`r8\v1sW<ggv1sW<ggp#78^<7̋ul-O5P±<`A$w-e Xx!vzZ.Ն?qnq瞟`.Ն?qnq瞟`f߄[kT;[`63,٫:fyZͪ.Y-H`NFrKwdxVŹǫz3xVŹǫz3øg5&ofXFsR3\J9ZH?C7\>a[z>>=;~'gᏳ%m4}ĩv;rzJ+.Ն?qnq瞟`.Ն?qnq瞟`gyEpcڰ-=\clڰ-=\cl?( xVŹǫz3xVŹǫz3øgj8sO}}j8sO}}{XwO31Xcyϱ϶Xcyϱ϶kFwW<] ~=??<] ~=??a??Nja[z>>a[z>>=;~'Q\v1sW<ggv1sW<ggp#;+.Ն?qnq瞟`.Ն?qnq瞟`gyEpcڰ-=\clڰ-=\cl?( xVŹǫz3xVŹǫz3øgj8sO}}j8sO}}{XwO31Xcyϱ϶Xcyϱ϶kFwW<] ~=??<] ~=??a??Nja[z>>a[z>>=;~'Q\v1sW<ggv1sW<ggp#;up;#ڰ-=\cl"qSxJ}p:t0F0(9Ƨ7sO\玽N~z*U29S?ʫ8ovUv/( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /<@}#ӉzsOױ|;Q>N?#ӟsƾge/jO5Oc`|t)zlOx8329S?ʫ|js~9̤xǠ?ݩ (8Š(((((((((((((((((((((((Hqy_xGoϧKڧS|S#%>"qGd^?>+C|js~9̤xǠ_߱s)=s:9=99|kvRv_v=6ȼ}@Q.Ǧ ;߱s)=s:9;^Gvq8E:8Ƨ7sO\玽N~z*U29S?ʫ8ovUv/( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /<@}#ӉzsOױ|;Q>N?#ӟsƾge/jO5Oc`|t)zlOx8329S?ʫ|js~9̤xǠ?ݩ (8Š(((((((((((ޒK1uk2Ơ\FNZ3wPOK?cU9^R32Tv8#N1e3QVTnŠ(0(((((((((bw;~}8G?t{ÿ >=99|kvRv_v=6ȼ}@Q.Ǧ ;߱s)=s:9=99|kvRv_v=6ȼ}@Q.Ǧ ;߱s)=s:94XRCGjPYGC?tӽHlZm&|Ms/ YR:8?%UFs8Ur_ S]$N(,]|r'm.<؉qЃ,2p} A.>ϲHͶ>Tc8Aܓ÷J "1VF H4}t͈v8A զ4dӑפ<&gѬ:*b4 CpC$H=@aЌbF [JKltJqR(eQ@Q@Q@Q@Q@Q@Q@Q@Q@{ÿ >=9kؾߟN'9_3OXFK}>E:v=6ȼ}@VsIשןAU59cRzF0H.SUsJt|JdHuQ*d}Jw"IŴŠ(FrGĖr 0NJ2G$2R$Y`A6#=F$uKPNFzt?. gjZz#>t "1VF*GPGcM QEQEQEQEQEQEQEQEQEQEW|;Q>N?#ӟ|vHqyӜ5;)Tyd^?>(Oc`|thqNo9zyxU^S9e's^?^=VqO_QEQEQEQEQEQEQEQEQ@=J ;O5O%O|r!Z7c֮ՆQrGgthedb0GQI\rqEQH 5HCCk2zgt"la?%QVd`YNAnTF^00?qN tZ1.澹7 B*( V$dUESQEQEQEQEQEQEQEQEQEW|;Q>N?#ӟ|vHqyӜ5;)Tyd^?>(Oc`|thqNo9zyxU^S9e's^?^=VqO_QEQEQEQEQEQEQEQEQEN^QW?U{z;܆5{~_?/ME%Q@lDK*App oC~^50eYNA)Z$Aen= :X("LD㞨}=03KGה4ri 2E4Ĥr }*(J$''QL(((((((((bw;~}8G?t{ÿ >=99|kvRv_v=6ȼ}@Q.Ǧ ;߱s)=s:9Sh͂.4;fI9hĽx8=ІUg@;NKIK(WF]F+"V@5-լk,~c|w`BWSQ|or*Q~Nj_ItGIy@"qGd^?>+C|js~9̤xǠ_߱s)=s:9=99|kvRv_v=6ȼ}@Q.Ǧ ;߱s)=s:9;^Gvq8E:8Ƨ7sO\玽N~z*U29S?ʫ8ovUv/( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /<@}#ӉzsOױ|;Q>N?#ӟsƾge/jO5Oc`|t)zlOx8329S?ʫ|js~9̤xǠ?ݩ (8Š(((((((((((((((((((((((Hqy_xGoϧKڧS|S#%>"qGd^?>+C|js~9̤xǠ_߱s)=s:9=99|kvRv_v=6ȼ}@Q.Ǧ ;߱s)=s:9;^Gvq8E:8Ƨ7sO\玽N~z*U29S?ʫ8ovUv/( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /<@}#ӉzsOױ|;Q>N?#ӟsƾge/jO5Oc`|t)zlOx8329S?ʫ|js~9̤xǠ?ݩ (8Š(((((((((((((((((((((((Hqy_xGoϧKڧS|S#%>"qGd^?>+C|js~9̤xǠ_߱s)=s:9=99|kvRv_v=6ȼ}@Q.Ǧ ;߱s)=s:9;^Gvq8E:8Ƨ7sO\玽N~z*T zUdAVVfrJ+Wڟ@+C(((((((((((((((((((((((+ؾߟN'>;^8_Id8[nxﳂA=;uy_ݪz=99|kvRv_v=6ȼ}@Q.Ǧ =gXz.%pf88lx<e[FqMa=\c1q~B=\c1q~Bӌ:)ҏ,%dzHT`gtOk#핋0M+D#EeiʦT{طkGq_8LOoa i zmC,F#9KC'#VQuO?鯹A+s:駎G>la=\c1q~B=\c1q~BevzHT`gtOk#x *03i5?ϛqq{(v OG?8릞:_slVQuO?鯹|xWttxWttChb<nq]4d8 㮚xM}}z/c㧷z/c㧷C+s:駎G T`gtOk#6#1|0=(#1|0=(Pg[FqM?8릞:_sl18?!@18?!G`;=$x *03i5?<nq]4g͇q_8LOoa q_8LOoa =;'#VQuO?鯹A+s:駎G>la=\c1q~B=\c1q~BevzHT`gtOk#x *03i5?ϛqq{(v OG?8릞:_slVQuO?鯹|xWttxWttChb<nq]4d8 㮚xM}}z/c㧷z/c㧷C+s:駎G T`gtOk#6#1|0=(#1|0=(Pg[FqM?8릞:_sl18?!@18?!G`;=$x *03i5?<nq]4g͇q_8LOoa q_8LOoa =;'#VQuO?鯹A+s:駎G>la=\c1q~B=\c1q~BevzHT`gtOk#x *03i5?ϛqq{(v OG?8릞:_slVQuO?鯹|xWttxWttChb<nq]4d8 㮚xM}}z/c㧷z/c㧷C+s:駎G T`gtOk#6#1|0=(#1|0=(PgG%̞#5f8W’{ T`gtOk#>0ז#Qqo扶Ls8⫏q{(v OG?8릞:_slx{FnXf1l|:zqq8#:c9]xFK}>E:.nf  *smgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Example4.html0000644000175000017500000000424210504574206024607 0ustar debiandebian  
 

Example Four:  Callbacks and the event Manager

This example illustrates the event Manager property of the camera.
 

First get a handle to the event manager:

>>> ehm=MyViewer.cameras[0].eventManager

The eventManager is a property of an individual camera.  You can get a complete listing off all the callback functions bound to keys strokes existing in the event Manager at any time:

>>> ehm.ListBindings()

or the list of all callbacks bound to any specific key stroke:

>>> ehm.ListBindings('<Button-1>')
 

Predefined callback functions can be added to specific key strokes in the camera:

>>> def mycallback1(event):
...     print 'mycallback1 Event at %d %d' % (event.x, event.y)
 
>>> def mycallback2(event):
...     print 'mycallback2 Event at %d %d' % (event.x, event.y)

>>> ehm.AddCallback("<F1>", mycallback1)

Note that the callback function must have 'event' as its parameter and the key stroke must occur with the cursor over the camera.  AddCallback adds this callback to whatever else may have been previously bound to this keystroke. Another function, SetCallback, replaces the previously bound funtions with the new one.  It returns a list of the previous callbacks which can be stored and restored.

>>> funcList = ehm.SetCallback("<F1>", mycallback2)
 

Now, funcList is a list of what was previously bound to <F1>:
 
>>> funcList

[<function mycallback1 at 102d1788>]
 

and mycallback2 is bound to F1.  mycallback1 could be restored as follows:

>>>  ehm.SetCallback("<F1>", funcList)

Callback functions can be removed:

>>>  ehm.RemoveCallback("<F1>", funcList)
 

 
  mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example2f.jpg0000644000175000017500000004067610504574206024642 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?'tHk 18i<$s;~= i,BMCϫ I:.u N9-`_Fkx=[,t3 %C(*s%:ucW?ҤOizڽO07|"Grx94sG8Ӽ=qX=}Ѩ:焎qx{{zgWP5}@c*N1?~^>D(Isg\4sb|u_lj#i8Ŭ^H,}cUӨ4'02bDjvsι#i8Ŭ^sG8Ӽ=qX=}ѫzd8uyfV.p;78xAx,SC2޽?|9ƝsZU힍A<$s;~=42š4b˂9rZxKdR*U|tqϩ|9ƝsZU힍A<$s;~=_xSuZI2IbBkRvVQ\XEF!s\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?OjTc}Mr\4sb|u_lj#i8Ŭ^ _PJu?O/MVc"^4Jr>u瞼8:焎qx{{zgPu N9-`_FjTc}MW?ҤOhV|sL:8A 7gS?t\4sb|u_ljmAR-q)~ϰg~{wϮ: %I%TycT{fs~fsG8Ӽ=qX=}Ѫqf>,;,mJ:g;F )5?xEkN -X1R F~MĬ.K=͟BIӬgEҬK4 1"o⊚xJV@P+y;g9sG;j,6E+VPr$1^kOPtMr]G5i HǀZQpI `=wQ=s~c{u/|UmI5Y&l8D'YHpjg63FíW.mpװf-\cp=N:=6 6s\ako`3ryQ=s~cv3ǣz{>k{ZG; 7$ fRA@YCF~~4!?‘+>.Fc8a_a|(lg9?1~I?ط^lSwB,>J MZt\Em9 TqHwl=XEMч=}=h?鱜z0篿Ǿ2b'WME.y!ko<+);f2pc9g ֯YEVֆx|cqT.3>*v3ǣz{>.Fc8a_a|eB[VwFF%F Aj ;kx]Ds05|]qÞQ=s~cVv3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F|]qÞQ=s~cVv3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F|]qÞQ=s~cVv3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F|]qÞQ=s~cVv3ǣz{>.Fc8a_a|nQXg(lg9?1EMч=}=Eah?鱜z0篿Ǿg63F:ɳ 4h.?X'(lg9?1!n,m Pq@S8MYHHEv`*lnkX}:'n\g63F|]qÞް_X;o?w5njsxD-I4!u$sq0g`I_;_f)>ffcpq>F-kh:H:u#ӟO܍FKK,Y3`zǾ:j70tw=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ__2xIAxO~/q륰ǯ!= F3q5kaꪒGW/3켓hbȗq&@Vy}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_4}ĭo>^[?tžV/w_-:829~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_ENxJV@Q<[%o+yw+CO#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_4}ĭo>^[?tžV/w_-:829~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_ENxJV@Q<[%o+yw+CO#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEUdLrd9pJe)s!:*YH\*\G8#; 51Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z8ckԾqǮ9C}9q+y[sϗDo9o1 :^|$EEVQEQEQEQEQEQEQEQEQZi-"AV?'6V7xiV|_eՇv?ء[}gk;K87q88a0ʺ{WHf= > tQRy}۷NuUn楺]3PtW[F=G쯢ʽgqu6OKma\+ eO44QE ( ( ( ( ( ( ( ( ( /q륰ǯ!=ש|/]-=yLs*/sžV/w_-:q+y[sϗZbx?^y~.oν|9}sϫAusFuH(0((((((((1#Sч }z?mն8# sIlAq~ UJ>}5"8rVROT{xt-^M~#X1AQ\ʁ ?Nu AAJI&mڏj֗,E.M$ "ާSImżSזk|$IFy(I=A -F 2כ?r)Ӄjj]?Gس,Bᰣ\ɏ=uX r 0Ѓ{*r'8QN__nGpuHE:H) 8|#{iQEQEQEQEQEQEQEQEQEQEW|/]-=yL|Kzl1x`C(?W~hӞ-<{mO[|| |9}sϫAusFu;G=~׿}_ 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@!x&ldIrGPNGpKyZ)Wk|:9pEGVb%mI۱w w[_B ;6 ʭ-QWf##I!Gaަ>O6\yXdAx_"Vk: Ɯ/$x iGu׷9M({s5;O7mϕ(:?FG A5#I}Fr2oˋ;4CHC"aS;G>NQ<P+`H`rR ӭ$t=̷0 ^T4QYQE(((((((((+ԾqǮ>[^C=t<{0~_N4i[|| '}ĭo>^[?thqds{> :#p>y}]v?5'"*(8Š(((((((( q3i1.I AR_>T#I;9CvYM+`bN?e~@\e$*'8ϲHͶ>Tc8Au^&*u+e8#pA+WQEwuĚm] K!Vdٶ~=ǧ T{jZM-B(0(((((((((R_![ z=?Cmz8c9|Q;(ѧ<[%o+yw(-<{m'_sW<>w̎zßW*l#8>'* p#'42VSAfn'kQKm! z} jٻ(wki~:ʷ*dBʣ/wev8^hQYNA@AhH6HN#V2>[j}VJ8-o/Ё؀E"xE b:j_Ʃݜea~믨9pAMqyuw73M;|-jjԕ{jQE1Q@Q@Q@Q@Q@Q@Q@Q@Q@z8ckԾqǮ9C}9q+y[sϗDo9o1 :^|$EEVQEQEQEQEQEQEQEQEmtEBZznb6:N%ًD7xЅeV[eQ;+{t EA  2F㲻0Zz2H5{Fb ܺv_KIs5v+=B$YNAeh = 6[eYL2Np< ?)ML5NWSo g??F_%P @_'j_C>ԟU[0KwZ3y4F#CLzQ@(((((((((Kzl1x`C_ 8Ka_CǿzD Fo9oxJV@V;G=~׿}_ 7_29~\G]ѿg/>Gcs_"+C((((((((*²ܨF *$X#ۡo[4Mo PO:;z/HYJF4,\]P/AQU+S|ϓo0)QEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_4}ĭo>^[?tžV/w_-:829~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_ENxJV@Q<[%o+yw+CO#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_4}ĭo>^[?tžV/w_-:829~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_ENxJV@Q<[%o+yw+CO#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_4}ĭo>^[?tžV/w_-:829~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_ENxJV@Q<[%o+yw+CO#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_4}ĭo>^[?tžV/w_-:829~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_ENxJV@Q<[%o+yw+CO#p>y}]ׯ?^y~.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8Ka_Cǿz-R_![ z=?C/'eU_4}ĭo>^[?tžV/w_-:829~\G]ѿz_sW<>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C=t<{0~/q륰ǯ!=rvP_ENxJV@Q<[%o+yw+CO#p>y}]׮x\co6fE||wQw_7toYϑ䈨 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /q륰ǯ!=ר1&.Jp 29 sӞ=C(?W~hԞ-<{m/ueg:1%Nf6Othq;G=~׿}_ 7_29~\G]ѿg/>Gcs_"+C(((((((((((((((((((((((+ԾqǮ>[^C=t<{0~_N4i[|| '}ĭo>^[?thqD@AH=x翫䑜Xqc/[RY$ŬBG?9C5/k/G!(sճw^нx߸=[=wu ׃ٿaϨKQf@moe+o;~lן/^w.9V]ykBo}n??s33R62[߸=[=wu ׁ(sճw^нx=f[ Կ Ej__"w.9V]ykBo;~lן/^f>?9C5/k/G!(sճw^нx߸=[=wu ׃ٿaϨKQf@moe+o;~lן/^w.9V]ykBo}n??s33R62[߸=[=wu ׁ(sճw^нx=f[ Կ Ej__"w.9V]ykBo;~lן/^f>?9C5/k/G!(sճw^нx߸=[=wu ׃ٿaϨKQf@moe+o;~lן/^w.9V]ykBo}n??s33R62[߸=[=wu ׁ(sճw^нx=f[ Կ Ej__"w.9V]ykBo;~lן/^f>?9C5/k/G!(sճw^нx߸=[=wu ׃ٿaϨKQf@moe+o;~lן/^w.9V]ykBo}n??s33R62[߸=[=wu ׁ(sճw^нx=f[ Կ Ej__"w.9V]ykBo;~lן/^f>?9C5/k/G!(sճw^нx߸=[=wu ׃ٿaϨKQf@moe+o;~lן/^w.9V]ykBo}n??s33R62[߸=[=wu ׁ(sճw^нx=f[ Կ Ej__"w.9V]ykBo;~lן/^f>?9C5/k/G!(sճw^нx߸=[=wu ׃ٿaϨKQf@moe+o;~lן/^w.9V]ykBo}n??s33R62[h-5>縔's듞o;~lן/^f>?9C5/k/]'P'k6A-0I,.XI}Cwn9뻯?^ Gv\sb-J _{žV/w_-:Y

Tutorial:

In the following we will assume that you have are running Python1.5.2b1 and that your PYTHONPATH is set such that you can import OpenGL (which implies Tkinter), the Numeric extension and also the viewer module itself. I will also use the word xxx-"object" to refer to an instance of the class xxx.
 

Example 1: Getting started

Let's first import the viewer module from the DejaVu application
>>> from DejaVu import Viewer
All right, so let's instantiate our first viewer:
>>> MyViewer = Viewer()
This command creates a viewer with a first camera (3D window) that was created with double buffering and a z-buffer by default. A viewer can have several cameras allowing the user to look at the scene from several view points.
It is a good idea to use a non trivial name for the viewer (not v since you are very likely to use v to refer to a list of vertices in which case you would loose the handle to your viewer). Of course you can use a simpler alias if you do not want to type in the viewer's whole name:
>>> v1 = MyViewer
After issuing this command you should have the following windows on your screen:
The viewer's GUI, and the first camera called camera 0.

The GUI presents a row of buttons under Transform which allow the user to direct transformations to the current Object, the current Camera, the current Clipping plane, the current Light or the current Texture. Normally  "Object" is selected (I call transformation a rotation, translation or scale operation). This means that the callback functions of the camera's trackball are bound to the functions transforming the current object's position.
Below this set of  buttons we have the object list that currently contains only one object called "root".  root  is highlighted which means it is the current object. This "root" object is protected against deletion and is a place holder for the world transformation. All objects added to this viewer will be children of "root" or one of its children and they all will inherit root's transformation matrix. 3D transformation inheritance makes all children of the current object undergo the same transformations as the current object.  This can be changed programmatically.(see Reference Manual)

Now let's display a bunch of lines. To do this we need 3D coordinates:

>>> coords = [ [0,0,0], [1,1,0], [0,1,0], [1,0,0] ]
an array of indices telling which vertices are to be connected by lines:
(each entry represents a line between two points whose indices in the coords array are given)

>>> indices = [[0,1], [2,3],[0,2],[2,1],[1,3],[3,0]]

Alternatively, the lines could be specified where each list represents a line through the points whose indices are given. The value -1 terminates the line. The first two entries draw the diagonals and the third the box itself:

>>> indices = [[0,1, -1, 0,0], [2,3,-1,0,0], [0,2,1,3,0]]
and an optional array of materials. Here the tuples represent RGB values:
>>> materials = ( (1.,1.,1.,1.), (1.,0.,0.,1.), (0.,1.,0.,1.), (0.,0.,1.,1.) )
We create a geometry object of type IndexedPolylines:
>>> from DejaVu import IndexedPolylines
>>> cross = IndexedPolylines.IndexedPolylines('MyFirstObject')
We add the vertices, lines and materials to that object:
>>> cross.Set(vertices=coords, faces=indices, materials = materials )
and we add the geometry to the viewer:
>>> MyViewer.AddObject(cross)
to see the new object, we redraw the scene:
>>> MyViewer.Redraw()
Now the object listbox should have one more line "~MyFirstObject". The ~ is used to visualize the hierarchy. By default, AddObject makes the new object the child of root.  This can be changed programmatically (see Reference Manual). In the camera you should see a square with four vertices colored white, red, green and blue. You can use the mouse to transform this object:
Mouse default bindings
Middle-button rotation
Right-button XY-translation
Shift + Middle-button scale
Shift + Right-button Z-translation

Because of the perspective, the Z-translation looks like a scaling operation, but it is not. You can tell the difference by doing a Z-translation away from you. You will see the object fade in the fog ...!

Now try to hit the Reset button in the GUI. The object should return to its initial position. What you do here is to reset the current object's transformation matrix.(See Reference Manual for more details.)

If you hit the Normalize button, the square will be scaled to fill out the camera. What happens here is that the bounding box of the scene is computed and then the root object is transformed to fit the bounding box into the camera.

Notice that when you rotate, the square rotates about its lower left corner (the white vertex). Try hitting the Center button and do a rotation. The object now rotates about its center. What happens here is that the center of the scene's bounding box is computed and this point is set as the current object's rotation center. You can set the rotation center of the current object by picking on any vertex in the scene while holding down the Shift key.
 

Shift + Left-button set rotation center to picked vertex
The Reset, Normalize and Center functions are also bound by default to the 'r', 'n' and 'c' keyboard keys (also to the 'R', 'N' and 'C' keys).

Up to now the current object was always the "root". Therefore, all transformations were applied to "root" and the square moved because it is a child of root and thus inherits its transformations.

You can change the current object either by selecting its name in the object list or by picking its graphical representation with the mouse in the camera. Picking in the camera not on an object makes the root the current object. (Also, an object can be made the current object programmatically which is described in the Reference Manual.)
 

Left-button selection picking
Using the left mouse button you can select an object (i.e. make it the current object). Try picking on the square. If picking was successful, the Object browser in the GUI should now highlight the object "~cross". Any rotation, translation or scale operation will now apply to this object and its children but won't affect its siblings.

The Properties Panel appears below the Reset, Norm. and Center buttons.  This part of the GUI allows the user to interactively change the properties of the current object, camera, any Clipping planes and any of the lights present.  Selecting Object, Camera, Clip or Light button causes the appropriate submenu to be displayed at the bottom of the GUI.

By default, the Object submenu is displayed. The Object submenu has 3 checkbuttons: Show Object lets you display or hide the current object,( it has no effect if the current object is root) and the Edit Object Material button lets you change the color, value and surface properties of the current object.

Set the current object to "~MyFirstObject" and toggle the Show Object checkbutton.  The box should appear and disappear in the Camera 0.

Click on the Edit Object Material checkbutton.  Controls are displayed which allow you to change the color, value and other properties of the materials used to display the current object, "~MyFirstObject."   (Example Two below shows you more about changing the materials of the current object.)
Click on this button again to close this portion of the GUI.  (It is not possible to change the properties of the root's materials)

Next is the Delete Object button.  If you press this button, the current object will be deleted and removed from the viewer.  Try it.  The box should disappear from Camera 0. To restore it, you must again add it to your viewer.

>>> MyViewer.AddObject(cross)

to see the new object, we redraw the scene:
>>> MyViewer.Redraw()

The LineWidth and PointWidth Sliders allow you to change these properties of the current object if it is possible.
Make "~MyFirstObject" the current object and try dragging the small blue triangle above the slider. You should see the line widths change in Camera 0.

The last four buttons allow you to make choices about how the Front and Back views of the current object are displayed,  what kind of shading is used and what kind of culling is done on it.  These are illustrated with the third example below.

Up to now we have transformed geometries, but you can also transform the camera position or the clipping planes.
Let's first name a clipping plane:

>>> cl = MyViewer.clipP[0]
This a handle to the first clipping plane. By default this plane has equation x=0. The number of clipping planes available depends on your hardware. The OpenGL specifications speak about 6 or more such planes. When a viewer gets instantiated, it finds out how many such planes your OpenGL implementation provides and creates an array of clipping planes for the viewer (MyViewer.clipP).

Now we can add this clipping plane to our object, meaning this object will be clipped by the plane . (HINT: you may want to increase the size of "cross" with Shift-Middle Mouse Button before starting this section)

>>> cross.AddClipPlane(cl)
To display the plane,  select the Clip button in the Properties Panel.  This will show the Clip Properties submenu.  Click on row 1 button under the disp. (display)  heading.  Notice that as you translate the square, it gets clipped when it moves into the left half of the camera.  If you toggle the button in row 1 under the side heading, this will change.  You can add other clipping planes using this submenu.  First, be sure that ~MyFirstObject is the current object.  Then clipping planes are made to slice it by turning on the buttons in the first column.  The side buttons toggle which part of the clipped object is displayed.

When you bind clipping planes to an object, you can specify whether or not it should clip this object's children using the inh buttons.

We can now transform the clipping plane either by picking on it (left mouse button) or by selection (Transform Clip) in the GUI.
As you rotate the plane you will see that is is actually a square with diagonals. Translations are always done perpendicular to the clipping plane. Scale only changes the geometry representing the clipping plane which is infinite .  Of course, the plane can be made invisible by toggling the disp button. The reset button in the GUI will reset the clipping plane's transformation if the Clip button under Transform is on.

Note that when you move the "root" object or the "~MyFirstObject" object, the clipping plane doesn't move. this is because it doesn't inherit transformations. If you want to look at how it clips your geometry from somewhere else you'll have to transform the camera's position. You can do this either by double clicking (left mouse button) on the camera's background or by selecting "Transform Camera" in the GUI.
 
 

Double Left-button transform camera
 Now when you rotate the relative position of the plane, the object doesn't change. You look at it from somewhere else.

Finally, we can add a second camera:

>>> c2 = MyViewer.AddCamera()
As you move the mouse from one camera to the other, notice that the cameras maintain their own transformation mode. The first camera should be in Transform Camera mode while the second one appears in the default Transform object mode.
Try some transformations in each window.

Also notice that camera 0 has a red border, meaning that it is the current camera. If you pick (left mouse button) in camera 1, it will become the current camera.
 

Example Two:  Changing materials

Start this example by making a collection of points, v:
>>>  v = ( (0.,0.,0.),  (1.,0.,0.),
      (0.,1.,0.),  (1.,1.,0.),
      (0.,2.,0.),  (1.,2.,0.),
      (0.,3.,0.),  (1.,3.,0.),
      (0.,4.,0.),  (1.,4.,0.),
      (0.,5.,0.),  (1.,5.,0.),
      (0.,6.,0.),  (1.,6.,0.))
 
 

and defining some colors:
>>> RED =   (1., 0., 0.)
>>> GREEN = (0., 1., 0.)
>>> BLUE =  (0., 0., 1.)

and collections of colors:
>>> col = ( RED, RED, RED, GREEN, GREEN, GREEN, BLUE, BLUE, BLUE, RED, GREEN, BLUE, RED, GREEN )

>>> col2 = ( RED, RED, RED, RED, RED, RED, RED, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN)

Define a list to specify the faces of the lines we make later:
>>> ind = (range(14),)

Start up a viewer :

>>> from DejaVu import Viewer
>>> vi = Viewer()

and make a line:

>>> from DejaVu.IndexedPolylines import IndexedPolylines
>>> p = IndexedPolylines('testColor', vertices = v, faces = ind, materials = col)

and add it to the viewer:
>>> vi.AddObject(p)

to see the new object, we redraw the scene:
>>> vi.Redraw()

and make another line:
>>> p2 = IndexedPolylines('testColor2', vertices = v, faces = ind,materials = col2)

and add it to the viewer:

>>> vi.AddObject(p2)

to see the new object, we redraw the scene:
>>> vi.Redraw()

With these two objects in the viewer, try changing the current object and transforming it.

Add another line:
>>> norm = ((1.0, 0., 0.0 ),) * 14
>>> pn = IndexedPolylines('testMaterial', vertices = v, faces = ind,
                      materials = col, vnormals = norm)
>>> vi.AddObject(pn)

to see the new object, we redraw the scene:
>>> vi.Redraw()

Add another line:
>>> pn2col = IndexedPolylines('testMaterial2', vertices = v, faces = ind,
                          materials = col2,
                          vnormals = norm)
>>> vi.AddObject(pn2col)

to see the new object, we redraw the scene:
>>> vi.Redraw()

Finally, try making some rows of spheres colored differently:
>>> from DejaVu.Spheres import Spheres
>>> s1 = Spheres('test', centers = v, radii = (0.4,), materials = col)
>>> vi.AddObject(s1)

to see the new object, we redraw the scene:
>>> vi.Redraw()

>>> s2 = Spheres('test', centers = v, radii = (0.4,), materials = col2)
>>> vi.AddObject(s2)

to see the new object, we redraw the scene:
>>> vi.Redraw()
 
 

Example Three:  a simple surface and its normals

This example starts by importing the function which we will use to read in a precalculated msms surface from the files 'surface.vertices' and 'surface.triangles':

>>> from tutorialFunctions import readSurface

The function readSurface returns v, a list of vertices and t a list of triangles
>>>  v,t = readSurface ('surface')

We make a numeric array out of the vertices so we can easily separate vertices and normals

>>> import Numeric
>>> vn = Numeric.array(v)

We get a viewer:

>>> from DejaVu import Viewer
>>> vi = Viewer()

We add the surface to the viewer
>>> from DejaVu.IndexedPolygons import IndexedPolygons
>>> srf = IndexedPolygons('myFirstSurface', vertices = vn[:,:3], faces = t)
>>> vi.AddObject(srf)

to see the new object, we redraw the scene:
>>> vi.Redraw()

The surface composed of triangles should appear in camera 0.   The buttons at the bottom of the Viewer GUI let you change this display.  First make "~myFirstSurface" the current object.  Then, click on the Front button.  A drop-down menu appears with 4 radiobuttons: inherit, point, line or fill.  Try changing the surface to Fill.  While it is shown in this representation, experiment with the Shading menu.  The Culling menu allows you to select which side of the surface is hidden (culled).  Try rotating the object while the front is culled.  Notice that if Front_and_Back is culled the object disappears!
To see the effects of selecting "INHERIT" for the Front representation, make "root" the current object and change its representation from line to fill or to point.
Notice what the surface looks like if Culling is set to None: If the Front and Back representations are both set to Line you see all the triangles in both the front and back.  If you now change the Back representation to Fill, you will see the Front triangles on top of the Back shaded areas. Experiment with changing culling.

To make this example a little more interesting, we will add lines to represent the normals to each vertex , spheres to mark the center of each face and lines representing the normal to the center of each face:

To add the normals to each vertex (each point in pts which is a copy of vn):
>>> from DejaVu.Polylines import Polylines
>>> pts = vn.__copy__()
>>> vn[:,3:6] = vn[:,:3]+vn[:,3:6]
>>> pts = Numeric.reshape( vn, (-1,2,3) )
>>> p = Polylines('normals', vertices = pts)
>>> vi.AddObject(p)
to see the new object, we redraw the scene:
>>> vi.Redraw()

To add the face centers (by computing the center of gravity of each triangle):
>>> from DejaVu.Spheres import Spheres
>>> pts = Numeric.take(vn[:,:3], t)
>>> cg = Numeric.sum(pts, 1)/3.0
>>> s = Spheres('faceCenters', centers=cg, radii=0.1 )
>>> vi.AddObject(s)
to see the new object, we redraw the scene:
>>> vi.Redraw()

To add the normals to the triangles placed on the face centers we just computed:
This is done by calculating the normals to the triangles:
>>> from OpenGL import GL
>>> vc = vn[:,:3].__copy__()
>>> nf = GL.glTriangleNormals(vc, t, 'PER_FACE' )

Then by drawing lines from the center of the triangles to these points:
>>> pts = Numeric.concatenate( (cg, cg+nf), 1 )
>>> pts  = Numeric.reshape(pts, (-1,2,3))
>>> pf = Polylines('faceNormals', vertices = pts)
>>> vi.AddObject(pf)
to see the new object, we redraw the scene:
>>> vi.Redraw()

 'normals' and 'faceNormals' have been show in the viewer as a collection of lines. 'faceCenters' has been added to the viewer and appears as a collection of spheres marking the centers of the triangles making up the surface. (NB:You may need to do a "Reset" if you transformed the surface in the viewer before these additions.) As discussed above, transformations are directed to the current object so that it is possible to transform 'normals',  'faceNormals', or 'faceCenters' independently of  'myFirstSurface.'  If 'root' is the current object,  everything in the viewer is transformed together.
 

Example Four:  Callbacks and the event Manager

This example illustrates the event Manager property of the camera.
 

First get a handle to the event manager:

>>> ehm=MyViewer.cameras[0].eventManager

The eventManager is a property of an individual camera.  You can get a complete listing off all the callback functions bound to keys strokes existing in the event Manager at any time:

>>> ehm.ListBindings()

or the list of all callbacks bound to any specific key stroke:

>>> ehm.ListBindings('<Button-1>')
 

Predefined callback functions can be added to specific key strokes in the camera:

>>> def mycallback1(event):
...     print 'mycallback1 Event at %d %d' % (event.x, event.y)

>>> def mycallback2(event):
...     print 'mycallback2 Event at %d %d' % (event.x, event.y)

>>> ehm.AddCallback("<F1>", mycallback1)

Note that the callback function must have 'event' as its parameter and the key stroke must occur with the cursor over the camera.  AddCallback adds this callback to whatever else may have been previously bound to this keystroke. Another function, SetCallback, replaces the previously bound funtions with the new one.  It returns a list of the previous callbacks which can be stored and restored.

>>> funcList = ehm.SetCallback("<F1>", mycallback2)
 

Now, funcList is a list:

>>> funcList
[<function mycallback1 at 10345b68>]

and mycallback2 is bound to F1.  mycallback1 could be restored as follows:

>>>  ehm.SetCallback("<F1>", funcList)

Callback functions can be removed:

>>>  ehm.RemoveCallback("<F1>", funcList)
 
 
 
  mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/GU.jpg0000644000175000017500000011065210504574206023262 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?O,|]Oidye"Ky!30I'dg[94 szzga? t&z 붿dIU[{{3vԴp[94 szzgbૻлnqn=qr5;я5ZY-e{=SS;瀞V0iX {Oo85Okq뎿U힍'uUn9{iWwkh]j~6B2uO=?ѭǮ:Wz6n=q}ѱwk_ij_y ok|m!wHը|Ys =0ٺF.Y7+*v7\ ~9Ɵz[\u_ll[94 szzgcī7Z>ѻ2{hī7Z>ѻ2{iszd~9Ɵz[\u_ll[94 szzgcīqt2E$θ sh*ݺ% *2(]u\g#,s'[94 szzg`:߁qk~=F?5;я4s<~9Ɵz[\u_ll[94 szzgcCz1~Pǝo85Okq뎿U힍~9Ɵz[\u_llvSH~??_S@F?8n=q}Ѱo85Okq뎿U힍jw[hC9BuO=?ѭǮ:Wz6n=q}ѱ Nc!}MSH~??_SG?Xηsi5_FuO=?ѭǮ:Wz6;ތ?ojw[h ys?\F^si5_F`5;я4􍨆LB ׾=뜊B uO=?ѭǮ:Wz6n=q}ѱ Nc!}MSH~??_SG?XWS7]5fcX`y`UN8tv3枻Gi#'(k)ӻĚ1\/߫5d~eo%D$k3pu^>Z]/ Ia$@y[ui^9j n࣮^=?Q 9͚ Ԗ&KO{AP7dJXUxZƣ z:~c763nY]q?1Ӓz1O>oLA}zFi%}gQ%ż!c, sTxu5 luc<=qqtehVCaj71CiMO @$pUNs׎3mjNS)]Iz0 2gQ=y?18a8G^z{.h7l= ]=:Mp|إ9sTC-׳nmt0KΤm 䌁V|oj0g=}=|g'_a|`|v:TtP<:jhEfFK}ɮдX㴶KĀ$ƹgn |dp1Uύ>3Fu篿ǾQ=y?1@hx8a8G^z{>75N3מWwGCEsƣ z:~cqq\qq|oj0g=}=rtt4W<|oj0g=}=|g'_a|] |g'_a|ƣ z:~c+GCEsƣ z:~cqq,Wo?w=8a8G^z{-eF)mЄD$: J/YY@pNKx٥M:`3czc~!f p|CQ=y?18a8G^z{ഭkcYnKߍ޲'_YWu_'x@K뛃@Y<`y,|n:5&Ip̚3S+0@pG:NiΫğ+j7k'>^.vArS{i ʍnR#;2?!%𭅍wf9a;mn[zF6g7|U9iO^sOq)RxeI|z ڟ‰{s+ý-ĠӠGB|=;o/."tI0w?{Ķ>_n_^4cau=h]_ts^,N\G{holh]_t_Ukŗik~mpT|ܐ@@/GQu=v'Uh|B ҭ4/nY#ѾUD uGknouYnnO۬H w8̣Umu?_GGW& `i Q"#C"H+m\b-i0];RP>w3嬳3@$x,mp5kNosk5o=xppH +s\߉|y3.O`G|fa]f}ǿU/궜-)sמy0M? w?{Ķ>_n_^W?{Ķ>_n_^k]<2]!X*`dd Tݍ*#&DֲY#%o5cPq3P]KtKȥ݅źlx݀g@ aN?%?!Q .? µ$<u+XZ>{{M@-ʬAH!g=.c.ZO 3"V$INv8]?$G7 ?%?!P7}kCW`|={N֎gLerjd305>agZ\[5MyңNt* 8lmItoKCQwf᣶,R%` 'xaxgǞLc?qItokڏ?%D?)i=Y|U9iO^sOq(ss_^zu8•47sAH}~zl@d-,nĒ;:W?{Ķ>_n_^&l3{ћX"]6 _ fŻiݷL*hNs.ȭ+ p' @:<zf?' OKkweդɖ8e;SXĈ_C k:zڮlӽBUxj8dvhO;\忊NDMJo%Ρ.`A' WH=rO}>lM҃$41b, #pHGXZt9'MI=*SE*Q?yʴUͿo(U|6ϕ*Igsniy=^߽4My]1nv>O6ͿO"Ceꈍ`p%+#]N8V(B=}b_ovc?8[αvA"6H\'ĩ [8 sOOqZjKh>d.ZM)<SI*KUO ^Yh#NR&e"܁th]Q?yhm.]>i/kh.i0i.%I]8Q̐x{VjW7NcoA7c[E/O6*3sLuNd?L< qunsGg\3S30=4ss_^zu8”|_9m9ZSׯ=:aJ n9lפ }p~/m\W;qK` Sx[o m#j_ĉox~ sExΗs0LmF-&M{7??eT#dmW[T 72AkvangݒTȍޭ^ෆF/tt3 `#.Nv%:tȖΙ=Z[XKes;̋p]ќs>p.]3vۗNU]+YCbp-p )gGŸQ{vϿXBJyVax&X[34+N]P0Zȳ𞨞{5(c<븒"D= 0"ְڳBg6k wH^6 l?*p[9oZNԭ'%3f)'*/,ֈ4H61*`͎³|1tw1~eRF$ڻᶍSCAውWpJ-m:w[W߸ʉH 'b@Ulom_̷'py^{O}(aSJ1lU&x$+/QѴs C‚ U<1qZ,/tif kʷ Ϙye HxVݿ ϬiM3$B$[^X<>)p0J[?Ҭ꺵]olΎcxPġ$Cqtizޝuulo5ъ4*mF3qۜ2^/6k_ c(pʤh, .yW-4FgGX/'OZ+[[]09t=xߟҨxwO7~ǥomۿc2qtY׭5OI-6 ;"y#hKa"X-$y`S &U=  KM ~vkp PM̠8q5xFOY:u{]$#̊®H%ēmbڭWp`xd'3$a.[923(X մĚQ_Ah~'5DZO,FdY2 d4{7IZ%d.lU!9Ax[6,m ܢWhFq&Npdc׵ %ȷ[m|ڀܘf9t0k@5sLuNd?օ gg\3S30=4ss_^zu8”|_9m9ZSׯ=:aJ n9lפ }p~VO`]BhQ!eP37gLqK` S\Cn8v 3vUڳEKe綗_SO_Wbˡm/C4}C_j?ƏM?XKYIi-:+"y{t)?44jiki29+I_2(Ə/eZ?ښ?44/eG} ?M?ښϲ_G4g/ /_ i}S`3Fd_QQgi4+MŎ5 _SO_@_2(Ə/eZ?ښ?44V ?OYy{ی*9l&ɹرƣ>ÁW44jikh;>YeeC,2kGSO_G?ƀ3eQZRKyay%`߾z SO_G?ƀ3eQ_2(ƴ44jikh;>YeeC,2kGSO_G?ƀ3eQ_2(Ƶ>gkݷ1z?44Z ;OiWgn6$sI3.7hEgo<1q˥DZFu[Ns9NR:9Jz^z})SOC{?-zOۮ{7\sAH}~w/SOv6kQE!EPEPEPEPEPEPEPEPEPEPEPEP ݿ5r>|:}3W.o #vm]fxfΡ'\{kLݡY$sI3.O`G|_9m9ZSׯ=:aJ>/궜-)sמy0M? w?{Ķ>_n_]0qK` S M=٭EVQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@x>?_v˟ꟈ?o\?΀3uA g:c?q1#vm]fxfΡ'\{i=|U9iO^sOq(ss_^zu8•47sAH}~w/\?-zOۮ{74cfQZQEQEQEQEQEQEQEQEQEQEQEQEA}3W.o~ ݿ5r>|:7hEgo<1q˥DZFuA g:c?qxwVӜ=zzӯ=>ΫirҞ~=yמx TP{qK` S pW?{Ķ>_n_]0ݍQEjHQEQEQEQEQEQEQEQEQEQEQEQE?o\?Ω>?_v˟8ݡY$sI3.7hEgo<1q˥DZFu[Ns9NR:9Jz^z})SOC{?-zOۮ{7\sAH}~w/SOv6kQE!EPEPEPEPEPEPEPEPEPEPEPEP ݿ5r>|:}3W.o #vm]fxfΡ'\{kLݡY$sI3.O`G|_9m9ZSׯ=:aJ>/궜-)sמy0M? w?{Ķ>_n_]0qK` S M=٭EVQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@x>?_v˟ꟈ?o\?΀3uA g:c?q1#vm]fxfΡ'\{i=|U9iO^sOq(ss_^zu8•47sAH}~w/\?-zOۮ{74cfQZQEQEQEQEQEQEQEQEQEQEQEQEA}3W.o~ ݿ5r>|:7hEgo<1q˥DZFuA g:c?qxwVӜ=zzӯ=>ΫirҞ~=yמx TP{qK` S pW?{Ķ>_n_]0ݍQEjHQEQEQEQEQEQEQEQEQEQEQEQE?o\?γO'$ܹgԷVW;県q4ݡY$sI3.tO{˴Wt@HU*O9|H3Pg].=4ss_^zu8”|_9m9ZSׯ=:aJ n9lפ }p~sa 㟇=z@ ol{bCr9$8'%8 W3A g:c?qxwVӜ=zzӯ=>ΫirҞ~=yמx TP{qK` Su?{Ķ>_n_^SOv6"+eIIe8ZAi猟ɣ?GgF=fx|>?4}'hLOi猟ɣ?GgF=fx|i@ oiɧ}'jmFvvts~ i猟ɣ?GgF=fx|>?4}'hLOi猟ɣ?GgF=fx|Co2L29$LONs9M= m{.'PC$)鐤Ӿ?52;Ǧe8P'h4Oi猟ɣ3i?GgFO?4}'h4Oi猟ɣ3i?GgFOΫirҞ~=yמx TP{qK` Su?{Ķ>_n_^SOv6j:V_I*ןQj_wpdk#&ɝ#QdrBEzezWٴԆtGB7#G,8Rp׭g?.l`oa|JF8T[`g /w%Mucd87^WYh:Lu`ϲx5XV.ہ N;G_ƫZX%D0,pݠ{yt?{Pd! 17kR񅮙u{iڔ۸! fڥY+mR Z>szݴOvkNx$|ǜz`0uO]\ڍZWXd[N-Xv>b@TnL3+-kSsy$8ٳn =۷f5*UrK?o@+GJIH.nn0dPQ"klg߬J[x]'%Lǁ\=82}x4.cx&dM)Q#(O[R^:ABͷkeAV*FUK=^x+qi4l[P̠p+sSa,#C' ŤxXLDA4Y曢Kb<66Jf#qN0ֵd t -U_ -U }CXmuY!g$31A!(dkWRXjM1Hȶ>c+F_6jIuKRIsyvvD_,kn>PA;o j7iWWi&ʉVVRIb(lly =4J{x!$I7ef#TI*+mSYҠEI2xdDB ea˂@bhWVWDG[f#K$DSymH$gZ}gwdFnDہr ~a@StJ }Ch-P̻w($U \M~;,o $.QS 3†,1$x*X;]hwZzKxm' {s6}\;' c9.a./Nd$e@EhO_f'_/3@ՁA g:c?q 3BN1t?{<;ΫirҞ~=yמx Q|U9iO^sOq*i(os%^)u:ˎ~=[\/߯S Ϟ(o8\=j:{Kk qo h2 b\s5$_ښ?44ek~W(P_SO_G^>?|-ښ?44ek~W(P_xA209`S+4vCE2*##q@jikh/υ_/O _@?ƏM?zZߕ ?+jikh/υ_/O _@?Ƴuk[Ӓ ea}*8Ҵ+أ( T~kmJgg`;}?SO_SOmQqrQ"z?AT?zZߕ ?44jikhQυ_SO_G?Ə?|-zZߕ ?44jikhQυ_SO_U<5"C5o/O _V"8cƃ>/궜-)sמy0M? w?{Ķ>_n_^^YqK` Su4caEVX^I:[JpA ~OW/E/o5Cz>OW/SQ@6_*TP?g }U5Tg3.ƪѱ\32>vXdP"_JFA7 4^9lsihv翦8)if6(lD׷w_`]|NU32T?=_lUg ?m?yi.7}qBk=\]mO-7nod9b}6_*WixVkqxʵeIL-;x _wMq3QU46.cQP*бdbYp Tŀ;h)^T&"`6B=jOWz7f]صeͷ*7>pEO1Z+MCjhЀr0Z1X*46_*Ujښ ߛ4+eXYu c$@6_*TP?g }U5e;+fno7,V2Al ժi $c<WvZDb΁\c$1JTݤf- }-.%"wQoC^f($|ʖEO?39Dt/O?l濕[omyyoteW-jW򷼲29!L I]<;@":l_|7<<ӤX>[#Y^fP#Hd,9VK*q`V<}+ maO}yO!K$ME<q&DA1O47Am n؛{.+VTR28Av3వKkdgĒrX1$NI$I5=ZAvOwEcB lMΗ* pB)PqsR;@h_?OUo?Oԯl4>k/$sۓQ^njMEPX$sI3.߬ xc9$Kc'#þ/궜-)sמy0u[Ns9NR†;ێ~=[\/߯S,%^)u:{+RHo}^趯!ՋI\ $.uF8U&b~׿ Y[Wͥuԥ$ŸyZΦn ^MioZym㸑Xlo`n$zcg-ƜшpEug#d d`fo]r.K5d$꣜g^&! {kx#˄e<' vahekح뺌[hQDBirT; 62< ZX! Wo}7 ۏ w4ڭQUd+qI)k#S+i~ Em&exo2EۍRs9k_a_cDS; h’ZzA9"綥,Y7HLo@Q(4uybȪ?&7q?x N[{^ӿ<ͱ]NmC3O-~ҦnWaӬhiSY cRNk?ڞviX'A1r߽n=ji:U֣sw.{-ofLsJ(ː']WT}K[ml:~)LYZ_x8Ud6:\CsIyŽͪ]|"E!Ԏ*2+h49"ա aXmpbH@*rO> ZkTEOFʿ+'r)0` WkK6*YadU(\l N+cOˌ` .6n!,q)g`>Xn C-+֍X=꘢hd;0d+(ms{ ŵ.cy7STg0G9۞YN'C*n'xĩs򌊩:ch:X-:P1tc `략a4S{}=؞..1J$>;W,{uz__Dqȱ|G&TcvpzpAXCo+'XSF|\Ztvmܺqk?D g<ν[/4g@HdAp "*FS wΕ7==ln&9ym-˪ FBCdx{nN2:^-^w*c2J<("Ȑ"+nlWԣ AWt+ <(*i/-M zI,lZP69cp7`uן'tGG\ֳ[W6fڤtݻb*rk?::(/궜-)sמy0M? w?{Ķ>_n_^^YqK` SKZNXlRFq*iP?'7ޱy?jHHXƃ/%Ԕ i$QNPIbB9'$I4zf?'i=?Q^voc3{Ҳ<|/zυf?'7ޱy?A.y>?r;;Li!,IV3{ћX˧OwʷX˧OyhO;@ȶGrW"P:3˧OyhO;@>˧OwʷX˧OyhO;@>˧O%y򣳺 ȬIÓOj7ޱy?hj*zf?' ă7u 8#Z%mmY$>\N>Gl\Y$sI3.O`G|_9m9ZSׯ=:aJ>/궜-)sמy0M? w?{Ķ>_n_^{ Ey?-zOۮצ2fmSOv6MEVQ@Q@WӮtN3"U{m:(xTg$(dίnvڟMzN&myinmPw Ϡ%&I<@20Wlkccgp3nF3rGEyyk=i}+5`T$2ƤyԨ TjƭIt֡Q{ 1A.Srޥ'Lٖ5uY+pe᛫{/]W}N(&Vm1bvXt'>ovϷgg#{fݟ߻nsڧOk_ kymx<,71hF A M)RAQuA{>a%]]/r$nQ#GZhTTj1 ruC*dm zQcZ /z28<}=tϱE ]N+KET)hTд{nʆ3(I"'*_a1ȸ,p7Pmz25 oQ-mn|.l'/%Ӭd2 SPv(*Tp-'޳gm݈涸FV+RN&{gwq%՘nnm$FoPdN||s;u[מ2,liZhIIh$ƛ ]N5ӵ(-3Ws+b˹C2UܠY?r7-0I3$Jpd`vu4Eb_xB_oŲ~b_OAH3VŰ`)--u%Fp%~eTI-4X-.[;.X|=N' R8GpԶljcP>'대oX-R+;;2Y!N?!PcxOm=*)u"2E:Ȏ+%瑐 J+Ovg LOoz<\xd9T-5rN̷k2$R`4"6P$|6%x<訢(((륧}-cxfΡ'\{kf륧}-cxfΡ'\{i=|U9iO^sOq(ss_^zu8•47sAH}~zm/oW?{Ķ>_n_^{ EM=5QZQEQEQEMi*Ap%OCOҰ??^ E$:rѸݕq>cڱAa\ 0R6^m] ۵BXWYEr~ ئcfUs,7Eb{"3' %q@L2Bo> ji6]ql`km`F [k:]6mZHpw(9'=>Q[9_O丷6vۻBq;%aÖViqK9 M7Ģ5.Xܷ 3Lٮ|g ܍Z .By,+ eqCb1@l"Z*" )p#9W[9?qc H 3 Hu]kH.X6fpubQ`RrGA[=*uOi~wm+y(`[bA )KR-8nU> cv7qV,'HC}msuW$cF"$H>]p_hluk\Oi\ClupNX4E[gi-…Lܡh s>;+W2ܧf^[*\F  '-KXN&C:E_A z:_iz}IʿV` \=kned7!4u .aT0Tp Yrv1^@Q@Q@to xc9$Kclto xc9$Kc'#þ/궜-)sמy0u[Ns9NR†;ێ~=[\/߯Mezڼ㟇=z@ o}^趩&+RB( v]Ku>O6*VO6Ϳ UͿo(ko(<Udӭb]vǺF(~` Fn#88OͿo(ko(<EZ<>O6*VO6Ϳ UͿo(ko*+ⴷy-(YPTQEQECuH3Pg].=5uH3Pg].=4ss_^zu8”|_9m9ZSׯ=:aJ n9lפ }p~6A7j+~=[\/߯Mezڦl(I (-A7_UjuuV ( IJn}s%߳uk-s"I#$+nS4Q!2]iv M!f8ݐ@uPAy1BQmrx;ןTּI,6_-kcGVhDl+&Bwcg!OkF?5U72(FNv3&'$m0=NzO;tDԾmA:Dj\}}G1I&+![i$ ]jͨlֱ4ufF"d'pF1dSE:TC2FRU؃\Esj~&I=<ʎ@| ww_[v6lx.;="iJfyO2(=gI$(ȿukVO_b5(륧}-cxfΡ'\{kf륧}-cxfΡ'\{i=|U9iO^sOq(ss_^zu8•47sAH}~zm/oW?{Ķ>_n_^{ EM=5QZQEZ%~?+GZ/3"EPEP7]-?kă7u 8#[7]-?kă7u 8#I:9Jz^z})GVӜ=zzӯ=>㟇=z@ o}^趯2%^)u_׬-iɨKu+ gQY.`lsjy=p>Zh\ű}?l>1W+*r̀Ό,dە.bGlmF +$p>a +]ecUMJXcR0}x2^|]?M ~LΤUvsiqհppGEMT2FҭtEb5qՎ'$rIS|t4^aETQEQEQEQEQEQE KO*Z 3BN1t?KO*Z 3BN1t?{<;ΫirҞ~=yמx Q|U9iO^sOq*i(os%^)u_׬-̮9lפ }p~6A7j{j?Ebi\6wpc`MH`s`ԓ-n?--3niV;c,^Zy\owJꖗqZ Dm#bmLNvoRTP5m"]GU7](9,-XioKM=触C[:[kvQ[FwH`Cnq8jIXk3%TsmаY%TP6X+cnl>?hO40ܼB ymceA +O; zKlq[B<Ҭv|[\!ZC|\4ۘR[s>ۢ_B]zKhf]>X"$IAa-TU` qz`{wԍOok3Yz)##j ڔM*-]ۅD`Sy|-etĆdVEܪ UF@ѯHXkdpsc=ZѢ(]7Zm%ZHr6'#PkBMMyok6ʨ8=x?S :$0DD1h7Tj\G?'cUW-QښD-p ;y<ױaka*׫6k} ))$QEQ@Q@Q@Q@Q@to xc9$Kclto xc9$Kc'#þ/궜-)sמy0u[Ns9NR†;ێ~=[\/߯Mezڼ㟇=z@ o}^趩2YeJ=xhE;IsPjš喇\^KhR50PHdEEjI߬ڵޡiixm]&%mdɊC6WR[]/.i Bgg卾ٵ(Ҵ~.0tѦe')*q R}Ǘ4:+DʑF XVH0{(lux-*]md.>h9HH)uӯⴏ]I lS *5.` w*wTP!getػ_5 16f>wCz袀1Y 2I Il|gWzncH>0yW KX{3Z-2Xn]9<㡦Yᦣ>o;]7$B HWQSmRi"89q A %qsX1Hl0DXei hkGKH|8*9deB;3<( ^L"o޵9leF;[dqZ @?s4W2絕'iw.d(Y$1 o ɹ?Qx7?]¢7n.T^MmEq? @?suQ@O*/&Eo]vP-|9𦃪CiWy.OJʕ<3ОECuH3Pg].=5uH3Pg].=4ss_^zu8”|_9m9ZSׯ=:aJ n9lפ }p~6A7j+~=[\/߯Mezڦl(I ( ( (-[,^Dp7ϟE4A7_\gE4[bYms#K$F*UasPgϟE4yMrIiooy9/i@2˽F-pFsK0w}H<߷ۻϵ?j9sOȥ7rF v]|ajn#SjKjͧa#Fm,XA7\Zd7vOi"]@?x68 4[=imXŨX!@]!cvq隱m6w_Z6p^M͸&NN'$dWV_W9A|Wn0KoO5s218:gހ:?Mt37Aq}{ghOjk>!avZ&j7 "kj"܊[l`@0;p@z{]6K=;RvZ$!%;e7ml)r<_Ȧjڜ~=v*΀m +c$33k;RĊKW˸3;M Kd.ZK"CEPEPEPEP7]-?kă7u 8#[7]-?kă7u 8#I:9Jz^z})GVӜ=zzӯ=>㟇=z@ o}^趯2%^)u_׬-iɨԐ(('rqT_@uuqXdd&#WїY6A 8溹ӧXP,bE^$k+!'# j垯n&K{kkg[i` Y뎼/^i_h̞wݍÚr:1r:t8|sW[5neQey2m/ͻzUxx AzeEs{N{ ҶCGo""QAn8}/3j .s ͞Ic?v!tm378@U崚̒Y׹!(((?TA g:c?q?TA g:c?qxwVӜ=zzӯ=>ΫirҞ~=yמx TPl^O}Cbʍ(y$ uNXz/oW?{Ķ>_n_^{ EM=5QZQEQEZ՗Yp,׷ l@yiB"YA'5g/ūŃ 9//X!]9G, 珛mIiiIbHXW xMČn 5\y=4Γ_؀D`vL36S5ö'MKU6XAl2M$ͻb0@7>c7.81wpGS^5YFCjtK<9HT a;ʮ V FO-X=ɕx.Ir pĜ>> +X=hjڗڣ@ܓĂFq@4y|:?G?Ծ(}ZN./m>`l㜌P8|S\Oq_YX$7XA3G휍88جHIOft`MFᕀ]m8sB__}!]sG=*hb.m*-K) Lԯ1& +Nxex~BtÎ l#ֆ}?4 1Z1]H$n`N0"T:ۤ"E#Py$b]7EPEPEP7]-?kă7u 8#[7]-?kă7u 8#I/6Q w 3FYշGۮO ΫirҞ~=yמx TP{qK` S鷿 Y[WI?4u*(c}F5bxw#?i+?uG$ &oivm8b0c^$o?Du/?u=Khح|'^o|cl=k\Iy/w˕ӣ[XʲBgcWv ꧟:z4\TP3WH$L1]hBzӐzmq],8to-Dy4.ydi$wrYMHORNhAecoU% ]xG86_6fo$۾cm*W-R= A\:z4\tEEUEDJX㢞Tv=1O+yco~{͞q~@_G:zp-ٮu$mѭӬeY!3+ 7y'G:+Xt`9YzK#7_O_p:*+?uG/궜-)sמy0M?ܷobKӬr X·tzg80Fw=wࢡ\wsz_׆\|\I1 {Fw{zQG$B컩|cg[v\rՏ~|`E=NzkE o<]xgw-9sw_?^ (]|`E=Nzk#;nySkQG$Bgw-9sw_?^sz_ׂ9"`#;nySk7[s~Qsz_ׁ0Fw=wࢎH7[s~ 39rD.0Fw=wo<]x(!v 39|`E=NzkE o<]xgw-9sw_?^ (]|`E=Nzk#;nySkQG$Bgw-9sw_?^sz_ׂ9"dۇ!Hp'*[G qP7[s~QȂgw-9sw_?^sz_ׂ9"g?ch˖ߎKmCz*Lmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Example2.html0000644000175000017500000001001610504574206024601 0ustar debiandebian

Example Two:  Changing materials

For the code for this example, see Example2.py
Start this example by making a collection of points, v:
>>>  v = ( (0.,0.,0.),  (1.,0.,0.),
      (0.,1.,0.),  (1.,1.,0.),
      (0.,2.,0.),  (1.,2.,0.),
      (0.,3.,0.),  (1.,3.,0.),
      (0.,4.,0.),  (1.,4.,0.),
      (0.,5.,0.),  (1.,5.,0.),
      (0.,6.,0.),  (1.,6.,0.))
 
 

and defining some colors:
>>> RED =   (1., 0., 0.)
>>> GREEN = (0., 1., 0.)
>>> BLUE =  (0., 0., 1.)

and collections of colors:
>>> col = ( RED, RED, RED, GREEN, GREEN, GREEN, BLUE, BLUE, BLUE, RED, GREEN, BLUE, RED, GREEN )

>>> col2 = ( RED, RED, RED, RED, RED, RED, RED, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN)

Define a list to specify the faces of the lines we make later:
>>> ind = (range(14),)

Start up a viewer :

>>> from DejaVu import Viewer
>>> vi = Viewer()

and make a line:

>>> from DejaVu.IndexedPolylines import IndexedPolylines
>>> p = IndexedPolylines('testColor', vertices = v, faces = ind, materials = col)

and add it to the viewer:
>>> vi.AddObject(p)

to see the new object, we have to redraw the scene:
>>> vi.Redraw()
 
 


 

and make another line:
>>> p2 = IndexedPolylines('testColor2', vertices = v, faces = ind,materials = col2)

and add it to the viewer:

>>> vi.AddObject(p2)

to see the new object, we have to redraw the scene:
>>> vi.Redraw()
 

With these two objects in the viewer, try changing the current object and transforming it.


Add another line:
>>> norm = ((1.0, 0., 0.0 ),) * 14
>>> pn = IndexedPolylines('testMaterial', vertices = v, faces = ind,
                      materials = col, vnormals = norm)
>>> vi.AddObject(pn)

to see the new object, we have to redraw the scene:
>>> vi.Redraw()
 

Add another line:
>>> pn2col = IndexedPolylines('testMaterial2', vertices = v, faces =ind,
    materials =col2,vnormals = norm)

>>> vi.AddObject(pn2col)
to see the new object, we have to redraw the scene:
>>> vi.Redraw()

Finally, try making some rows of spheres colored differently:
>>> from DejaVu.Spheres import Spheres
>>> s1 = Spheres('test', centers = v, radii = (0.4,), materials = col, quality=15)
>>> vi.AddObject(s1)
to see the new object, we have to redraw the scene:
>>> vi.Redraw()

Add another set of spheres, colored differently with default quality.
>>> s2 = Spheres('test7', centers = v, radii = (0.4,), materials = col2)
>>> vi.AddObject(s2)
to see the new object, we have to redraw the scene:
>>> vi.Redraw()


 
  mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/snap.jpg0000644000175000017500000011467710504574206023723 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?u#,;GӠ/H秹$zgY:8ߧusqLϧXg?Oq*j;&pmsp1$dzgY:8ߧus^W5)flgzDZͱs:H1a?VgDe_#1GCU8]|QN^ 7 c>`u}1뭟 dg?0D~}VTծvL 8ǹc^I fFtDP1{ch .q3quϢqN>>#[?a>8v!ϕ}"M8W6[Kw(9ܮ( >QAK怼|G5ˌî}qW!@Fs.3N>\[ FLmU+9g$}Ҹ8" /LF1x^zp=(.뭟 dg?0D~}|G5ˌî}qW4.Qc`ʳE fL ueۭض F@ w|s.뭟 dg?0D~}|G5ˌî}qW4o[.l#)&ܱ粀8 MYM!Y-nܴl@mp@$Ew=u\fs}ӏ3quϢqN>u&c1+JM 1>#[?a>8Ac x1=(314cA_zS jͩZ˥jr3 ';fC=u\fs}ӏ_36Lp_!o#}^X#V-K0̧y*l=u\fs}ӏ?$DG"dX%Ab.K.i55DcǕ1e!YvwYxnYf|l.d\ Pq AI (]ImW/(x~B%3Oޠ[z'BW=olk|=;Ī3EROM$%Gy6ju [Kzz y eW>Bt9=N:ԼoasM7,ĩhdsbRA(N_ 3?NLlMiA%CpNqذ˜Aq~gӘUgqm$+?~g991^Ưu^?>:t߈l/?6?>6 `=GNG7Z Vsߑ:@LAU,߻oo}9kMBo}:Gk<JnԚϟFfTd7m $:['Ӟ |ae {}?3|ae {}?3s_qZF~,vmuŲetiҋy#oц!nRA$1^18mϧ!8mϧ+'/1E+nAT%F1i_˨i^tV-\YM@UA'iQ9L|ae {}?3|ae {}?35"ӷk6F"p8>?JXaSIr".Ē\}Ҳό,߻oo}9,߻oo}9j$¯訮t˜Aq~gӐ˜Aq~gӚ UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UWΟYs.=vOrYs.=vOr{j̃UW?O\W.^Þ''Z揌,߻oo}9t77S7BX' /ZVj_qٽ%~VUJ`z`j6h;ȉ;#SA z|ae {}?3|ae {}?3i^*ܯ:[ۯ68&zKY2Q˸J2N^O9zjv`)ٝ (݀F}3:UWr^?)Ģ?=4YsS^߾o~CI[M;!Ԡ*fC9X˨E(pt }=1Ǣt%/q 1$+А=8 8%eWv7&c8]:d{zd嚕 >(0s^K>aQL?ty6i\5!'('vrd_WGGUJ+?g[GQw=R=;w=i]otTgG{-i]otWU(ð}o?WGGUJ(p[GQw=R=;w=i]otTgG{-i]otWU(ð}o?WGGUJ(p[GQw=R=;w=i]otTgG{-i]otWU(ð}o?WGGUJ(p[GQw=R=;w=i]otTgG{-i]otWU(ð}o?WGGUJ(p[GQw=R=;w=i]otTgG{-i]otWU(ð}o?WGGUJ(p[GQw=R=;w=i]otTgG{-i]otWU(ð}o?W]'YҞVR?W']G-NF%LfTtgɵ-t'6[Re+cN:ˏDJOޠ[z'BWUo#K>aQL?ty6i\5: ;ľGk3Q_⇣}cQEIQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEx;B_bW/]G-NF%Dz/(pt }=1Ǣt%8:~>~:+|G v7<v|'Ӭ*3'&??fgQ'o}:£=2~mc>j+PCگS>(9B((((((((((((((((((((((([KJw ĨOTv`eA8NOޠ[z'BWEoǃ4N/uF{}3d}s׬~:?zEn?Lq ]#; ;ľGk3^K>aQL?ty6i\5(z?W?ETEPEPEPE1j>5(f0x\\d *TQEQEQEQEQEQEQEQEQEQEQEQEQEQOm x-ta zt+|h6m"E7Fx's73"Z)XfPGX&ƫ#E 4nW$\dQjR Qfm$򍋻Ih}ާ {Hu![4y.(?xlS;`x}<=;y~-.u1r,d;3>:v_?:/?zEn?Lq GA8NGh_ gɵO?Yxf%No %ׇoZHϴhg*%G(yWwj-%ݴI%p0nj39*`ep榺x~{"K&(FT1B&Wbm%vw(*L62`K:!=i,9ͦp1ȁJ RxKn`l$C&0p80R4,oEսϔyr_b yq<(*/~{KeG h!}3BV0(YXz3(clIs3|df Rs'Y&HR4&Q03\kon_OIiX*LBW#S㎇5GYk9 \mϰ?/R Lm{n,-BB=HS>#5C/qU3@tZ+].kٙKUCb:#JcdY(dbLh7.274:#sccmۉ " c xX%G#}pGCC@ҤI<͖yF| 0 ]IFNoG/FM+w ٚ\ 8AK}AMWP"F\H"%܅<1PWFY[R9FU/| 8I?KO)\M)W3\h' c7nmǪ\\NDX»I䜒I<cIFE5tzƤn+|-Xko&2=4n6E+BaK! 1}rWN0hjCEPEP]G-NF%rx;B_bTO;0{2Oޠ[z'BQCPc=+pcQ'o}:£=2~mc>ku<v|'Ӭ*3'&??fG?ݪ3袊(|22-:yR#،dMGè[i@ AH䨠SӼ+Wݩ9-1J]q #GT7eu_:9ԜgwHǯ=/-`5~WnN I89>񤼍X.fhD#B Ps|քRleB}vq9Ʀ3ZL0}? N:-FdHa}<;~cTk$EP2GCӟYv>\O |{P3s-0lpp??KW~/y߾i^̗:G*U@|3ViduCl3SWn Gx9s x6o Aߟs;tlfUp6ǎNv))߭i_aRokY/XfiIGBs֙sKs,+RD8A>n?"VTw>Ts4շ3qj_er;{ʍbHVUYeorۂ"ҮQNx\/Rsi%́-_άIWۏ0*CKu?7${彀+#.˦HvpR,0K-KS;|   ~c4ks{,<3YxoO?vU&u/.mۅN ,"i.R['1"*t[>˫;yK[6<,;8fE~lyi @r'YVΛmSUºhhW-rsl }x~"70i^©"к;đ |0q&^u+G%۪Ҡ(#+Н ^.:Bo8X^ݞ&Wb`q6`3egwsyn-)4ҩtȪIF>`!_i![ hx젚MNIbŀ%`b2w+MZ+!cCrD)-E !q0YJ̰^kȌ$Y@S` ƒѤ#w'ov95w~e ۊ$`pR4>f9={` 5}k[PȨcJ7múA? .[aR#y),w;zc҃*^j טP-evu%Lq'(ϙ?#<_kk՝\4Ӣv0`Igi [j{qs#IBcLQG@=+Sb( <!m/v1+'o}=Qكt_8:~>~:?zEn?Lq ]#; ;ľGk3^K>aQL?ty6i\5(z?W?ETEPE#S˙ 9fʉť2eTBA#޻m#W I'0)6퓃ɧ \GQ0^Q`0RwtqEx2լ廾hʹm-<05HT$c’N}zKd ޛgx4*J"!QI6s!JSi!ӴɄ2Aus67AOM\#rlYKq/q߂0p6cr~l"-/b[(Q!ԂEYdm7U>̤hQt*NE8!Ť-Wi mm"@q0ѻ9bj[pȋ1sA 3 z/ VxܧA3_x%mhHN[\r˃qnۡ[Eu6a /Gҧ畼pnr?֭^ZbTL,"E#G T)v؄I =N8ibeWr0@W;TP=Hh@<ˈ;r2~p*Av&"ql $#^F1D@SV-;O5~M1lRv_oB1ǯcIP.Iu3j.g(W+7OoRhjmuyQmQ¹'9R )jQ bPym1/&zrj.I$մgc1%(@L*@rD @|G +2Qʩ;sy%$ƫsr$mx>dW<6YmMvqp"pOOGnR|.2mWg? Gy|IYVX$F : ;TP\Ȗ2>\R"d8 {hrN)lqyLPVjvp\VVf\1$r[ϙ%'c[7%  @T8u7+ f ú\ 'ْLҥ1KA0RXf9;B|w4V$X-l ^AI]~aN[Mm|頔_M":ȇMX ]6ʒi 2#2t )-7:ywmh ?0,2rcNvN*X6VC̚m$#DGS0ۣm+$itY!2y.9xJ9b7CGdӼքꈥU&b|髲ve'-"$P$;gumíî^mp["ډT#%@ʱz|Ky b8 I}Wl. m`ֻmV9] RLfp23߅i{i^=LxFose[%H*nVSz\\b08XV6 e n ]x\m=.[ڭޏ#.$9/)_;)bQQЧg?EH`H$$c>([KJw ĨOTv`eA8NOޠ[z'BWEoǃ4N/uF{}3d}s׬Y|$=IP/?Ѡ9[#y_#YU9i%i%ͯM h%%Ye2m`'&m7(zTLEb`!cn"H oc'=p;U# dLa' 2}j@eC#:E8.>r{t;}c.FIje;iDDF%I#$#5Z͹h 'ː vY>EG %d26x#L.G9ж$ůG$v\!8\IQ9T:)KNOoٛfEqޒt=n-I5R|vϵ6FH@m|FSݳ3Xo bZF`r#dSu}22î၎{Ŷ, &VL'əsݏn$2O?(i7_MI]>灦!c۰9"ar]/l+#>apx`Hj .ZQ$hʍQ`6}pe>dWi3F=ya'mCNY|w{x.q|n >I?.$=nHՏ+ lc\A>9*'o\c%&'U6Tڿ#3''Y_ۡzR.~[$:6U10GLiopsw̫B;W$:QBkZddVR("F9R{u+w}t$gf*NO:[k!"n*/’Y~8H8ǥRH>df9w6kFw'd@(A'm)x):#CRDdgy<ѳ[=MkqdRP# 8VUk纺tmʂ'#$np16)桊72A1;B`3fg.{B Č`L4y<6 ]͂6d`pmݐ}vߚtJ&/Pv^0Snꢖx|+c4eNF'!v+H-<Nvku<v|'Ӭ*3'&??fG?ݪ3袊(*Ս7ssY(]K9|?8Uj톗qyD?h =<\~4_l,s}kok*mRM`pEwZG~'um^VCImI1DmI92p%W'kpvRF$I<9W>bʂ8=ׅT?8vV|˕qm0\\aF{gN3YV0z9f9<UcZ]WY@InJ63x; ˎT97(so6B7p ?^roo"l,v609/HIҺXGk+uG-3&<B9 r90!|xF@yHSɌ'n7(Lgʙ'v/bD6Kp9%O^yR}Fil$R3 rzޱI;c:`;I+CL-b\qp'grei+Śι#lT A ;@#fcֿe{E8038!`c_dII.FFʘaGF݌! yBDF<sӓֵ*ڵib;+y![& ` ۔pI}|1).}LeG< 0-Ux 劥q+\LiIP $}j'<~ )K[⸅Beb0ۉ(pt }=1Ǣt%tVo 5эAH$Tne'jF6:a[b htcYvʻjuڅޥ,6zr*6,S`p:⤹MϸRۥsQ[mYz:1R;us'2ˀJ:0AAj H²D^W A ;gϡ>^]cPYсg>h6p}#ֳʜe6SVc޲-AVffwaxZ Q5K6#>| ,''b!}Rɉ$M# _ܜnj{qFB@9ntEl^ ֚Dgv hA*r$su[T?k.㸱*+%# 9*28(IkqʜnymF9&I2j|| H2#}1SZ [+t^--,2kc=x<QҫǦkܡ!U7@wu8\2vsF85bZ vtV$Rzmԭ^[(. EY  wqL>y5R1ݐX8TgtLNԻڬ$9$5>-F7I#,k1IHI"[h\mۀ0Hwag[^P~bU_X[$:ٮwG@qӨ >.5s%!c'nyX>ZlRvfg*71{)!Q:ʊY-#鞙r*toMcr/'!'Qq5 UB2ŏa;G3ZhBpjr{Ԍd9\<q#1HIuI |/a9w62FAϲxZ#.s 7|tg# e8 84֚סrukwea~믨<APl}"c &2Wo=ۖgH/yOqОp|>eOӬ\-JH py$Q߆N~dpTTw" !J#8cb`c {r@$ ujaVld۴:dQ72[737Pq==p daKvBͽүGi%|ˬA7rq.xM+<+*[FőZ09c ;6޵5f(^`oH822G˻Y^%ػ{[a{3pP|m4=˨t5А^C6W2sVVF]b}IZX`ܱDJ?~ NV6!v*d$mj^^FW#C(,$SYRkN-CW<|yXɭ M2K>7Q#ݑ~Y$K,%r?#?_ʛ- 0Y3eFdP b72||2d?ϥ_i}F8"gePbx]nR] %s4% |W3 FcX<5yKXDGAN$kZ],"vardIO qp7ȓUhNo_-Q7L;pM\M\WJN vUgYqCqҨC"졷6w^Gss('jvdhr&KگsX<Y :CpO!?wde`8 #}d)&s#88OBv|E-Fs,}=sH[0S*1|㎇s G0 hI&I#%@d޹GƗZ$MG#, t`ҝ9KdkJ:{[n<6hg )1؀v6@5CR4kY D,2,LB, JVZoꖒ:NmI*lC( prAu ۄmbP"+{.,hD;DnUgzthhPT˩Z'<*>pZ@cgvwR@陭k/ Wi1Tkk¬4cSx0API$ee{wq$x@FfL0T }}.::%fՈ'',I;wok$Rݘ0HV(('oz<!m/v1*'=~GECPc=(A1VЕ[8cK>aQL?ty6i\5: ;ľGk3Q_⇣}cQEIQEQEQSZ[!6KK3mTdzI 2OF#HK318ԓ]$춚Eͪ\HAܜV$rPF0]Wð\Z[=̋fpCyR \q'i!R#6jo[@ ͼr@ڙj*SU#ҍXdU.d!e)-3͎mhldidpV[xU]0pngQ_]iS奅lq4m"AttW)y:)htABNOp01ԧ*oSŭJtMVկ闭R+y" cnFX/sq=?v/ 6(ҿocW!XoOhHd 2 sR۹bF9֮w/ߙ![/;H)#c2Fn:ÑaA7+"Y5+"HU^tee?'9`H$ƌZ$@Jrx b̰I?yw(Q!cp5 `r6y# OѤB*r*~C#M̛PC[q $3"($]q`f߹İ/k} 2/ ]#'V#OprH )QƩ, u=Y;ynC48e,,Ls\F,(P'旈dq8 s>ćKKyc{|J"aK1"C$V"uf p fRO2K\y@ \LU`):VqU>lMjKjdn*nF d\y9q\ZKxܬ$xǙg)UyE_e$&_Mr\8531ȁN$`e Еu4l/-.h}!m $s:5ޥnķEe;q8$ֵ K̻L0r%2Nv),9 $SS*mZs&O6m>I,rs_@[wh|<ДܹFG=fc>ƣ$1Q y@y'gdcd̻IVM_ȿid+#d9I[q 򪲂sec[ $̺1`1G:9Rveٚ[*32XY%XѰ$prz4k6x&ʭI$y)x2} k;hCHû!xÅ8 Jʮ7!#H~Zsi!0pկRz}%70DGH3v^*\V幦I4"v$@-r@*=: [NtNBXD K%6 0y|i/q5խ7T7EW L~:?zEn?Lq ]#; ;ľGk3^K>aQL?ty6i\5(z?W?ETEPEPEPw_tEXc{-N~_1Ux {6Sn%/Fd {p8]Յ m zNPJ,eNʜr%rzď}]yl _Wv71i,O=4˕C#CЁ* AgiZyVaH)*2|&@u9ZƕyoȸbH"N32"HB8cLxjVM0[e3e} gRxzo[n۞wgui-BL$4Syq:Ylyʀc2֧;Z8Ufd2J櫨 m |FZ>[8&0ňD$ 051?ؾY-eV[fVK*pkU`ƴ[4l#Egv Vhs]Ðx GspZnY\#9}Fz{2ZMiuD׮y"ܫv X}KajK}a$"KxPsq$ʸ!P=rJԖ{X-wD yQqz85}wkmC"O,1A%6ztIiunU\ztaӑ֣U 6c{^I'ܱlS:xp:Vqvؤ[nM˄a.z.0~f=.nv"%?GCzmH;K/}L񞜏Q˻xͬR#x >NP)8e*ÆV0=9:;kfa$1{V,8~B,MF4a8cvb=HcU]F xKp9  ǯ(Pc3u?%1Ɛf}_xu絼r*$V #c'phJ|00PDg?N⻅jFfeeJYay]Z~!o-4WB_DFEbC"cЩ 6 ;ԺZyoba ֣{Tq~40I(8`7˰>@Pxn{fӮ 1^^XG|LWvn"dH6Re@ vxO ؽɧiUo]A,q c ?6}q\5ƦRD۬U+ q҅?=Rx,²"=* ǜGyiu*˧xvK{U #\ہ mr>H8 OܥN[_ͤrTĩ]<{rFp:<41G #23W1pOvbx +U%#ėlP\y5eAusVMaX[ kGfV3ed7}ՌK&U XbK:$Q;c.ʤӡ]EVS}ONx r.+eVl2؅gnr"Wܻ铎ETbp r~UŕY7.v2q޷"(ԥ0U\F8>P#wԬh.5jkT?l`ϛoܬ.89ƫȾb#w/huKpJ@bFѼ0ziQ5thOg5ԣYt~mHuA{G!PTab|Hdl:6;K.naaծV#vAS,4'g,xL(>a巶񵠛MK]zF1U0$BN໇9W_ou;,$G+.'eI @褒=hEY m؀܏qvG7(ʜd %IB ْd:Mc`_k`7FxelgKq<#,]v,ORM2Š(((((([KJw ĨOTv`eA8NOޠ[z'BWEoǃ4N/uF{}3d}s׬[e.CLggN9#{4i8(×ZC$ g*7F́ yy FPKUy"B8AUh ((((((([KJw ĨOTv`eA8NOޠ[z'BWEoǃ4N/uF{}3d}s׬dEG'$۔Y躧yl.ϴdd+yfPXzd' xχυ`օ˥^nFJrTmPA~o3Q[MpYD1R O*61z$M-O<,1wس3I=I4(((((((([KJw ĨOTv`eA8NOޠ[z'BWEoǃ4N/uF{}3d}s׬&cM/NL꫑[o&il|U+h.Lnwŵ7$s sj!}BZ,mfEsٷ>p 38EĊ烏sVM{VH.s9'X9;I|U{kA i0)dH\A^owd5;ۏzGּ]6[4h3 n@-Oק=x䖳Z24K`L]?0] ږhYF>vnNcO㊵A%sbZ^Io2maGB<G #׎ic}5;c ܨRR$nqgޤ!-.FI8xI# Is?ɞd ݔ\c'j̷/nakZ^pI*lx@axRNr:uMx,VzDq?h7:36=X{yUWk=v[IW JeT*,08`A,b\TWdg X*n’=L=?gSt՜%:4ӡqdLD=XuAVLKq<#,]v,ORM2 ( ( ( ( ( ( ( ( <!m/v1+'o}=Qكt_8:~>~:?zEn?Lq ]#; ;ľGk3^K>aQL?ty6i\5(z?W?ETEPEPEPEPEPEPEPEPҬNc#l}Oi_jZ|FiJfAu:2²6 "f~Uɭ :\wj, 8,(0`s"+8^o &Mw*$c#* kWiKhJyLC`s>rI\I%C7O,VћXiwy0gZH,@Fp- k_\H,Z܃Yrۿ=Upһpyհm}KufQD#IۛjïJ$@5u$vKۛ=O+B`FIH;n|idp:y5x9n86td4RZH>t8a0{ r/6pCq `rUEgտGHS"O%e^^0W< cb#$z!u8,nDS$WnXZ̿dP8 $FP2jf\]҈FB>0ܧA᱋ ]A/Dje?<b19uixy4TPuGP_spy(Ŷ=L߷ x,[lL.Tc ]1Eψq $&#նݐ_/ހ;HQĺ$mD`̃r 9ORIVbZħpc$R(s4  QB%uXw©u'-I{ڋYڗn H4|c~讦{czlXhtyM)*  /^jޢxCTBE%3(L>䌞G|qp[!(;"#v]ѥ(?Oq<NsA_,407X%Rn7 CUf@Ѥ fhCDhgep)FyTh:l=)nx6VrF \D Td;Ҵ HcX ԅ\2 ( ( ( ( ( ( ( ( ( <!m/v1+'o}=Qكt_8:~>~:?zEn?Lq ]#; ;ľGk3^K>aQL?ty6i\5(z?W?ETEPEPEPEPEPEPEPEPEPEPY<<PbHUTsS(45Oz ܳpg,3TibI9U V :62(((((((((((+w Į^[KJGfy_|P +qzcDJ>(pt }=1Ǣt%tVoj+PCگS>(9B((((((((((((((((((((((([KJw ĨOTv`eA8N~'w2dUU&@67)QwoW8cK>aQL?ty6i\5: ;ľGk3S_⇣}cQEIQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEx;B_bW/]G-NF%Dz/(pt }=1Ǣt%8:~>~:+|G v:Ki)! ?$h'3F%c&g{7}*x---V+kxQ9*Ktpji2N'uzTOX\D#oae#Ay.s7Zߑg??]:{{xx7] >=}A/f]GEX\D#oae#Ay.s7Zߑ%\_j\ç%I#n ќz\>?9FA~C'>?氹ΈF33i~G҃X\D#oae#TϏNѐu|zsӯOcK}vasg9g?氹ΈF33i~Gҩޜ t?! _oq|Ɨ0? .:!s{-Jasg9g?S>?9FA~C!2N=/a$\?5tB11O[>:!s{-J|zsӯCӟd.}={_H(~k c9L _oq|??]:{{4gQp<9sxs-?oP~k c9?9FA~C'>?氹ΈF33i~G҃X\D#oae#TϏNѐu|zsӯOcK}vasg9g?氹ΈF33i~Gҩޜ t?! _oq|Ɨ0? .:!s{-Jasg9g?S>?9FA~C!2N=/a$\?5tB11O[>:!s{-J|zsӯCӟd.}={_H(~k c9L _oq|??]:{{4gQp<9sxs-?oP~k c9?9FA~C'>?氹ΈF33i~G҃X\D#oae#TϏNѐu|zsӯOcK}vasg9g?氹ΈF33i~Gҩޜ t?! _oq|Ɨ0? .:!s{-Jasg9g?S>?9FA~C!2N=/a$\?5tB11O[>:!s{-J|zsӯCӟd.}={_H(~k c9L _oq|??]:{{4gQp<9sxs-?oP~k c93Z>GC{ ҳ]B O5|zsӯCӟd.}=+ߙUJ1WV%CPc=+ּK6nK [wrUT8#mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example2h.jpg0000644000175000017500000004163110504574206024634 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?Y1xb }6g̒kT&@2dOݠ5 gNm`OtUQ%q__ :ú$qO"!-? sCӼ=3X==i>h1]r97뎫]Y9Cz l΢#v2p;秷g3mmbnZ(Q%y ˸q^{kΝ1힟F]lڶm72)b=3":s'9~OA@<$1;c9=>VxHc:wskz}:tK-RI;ITAǷM%Ėj$Yy F cۏA@<$1;c9=>VxHc:wskz}:nBpl(_pqq\鸑\¤CnjUUlFNA0ύsCӼ=3X==h焆3x{g6{gѺ{A'EFUEY @uW1)$6"8  =`kΝ1힟F@<$1;c9=>Vo^閫!ieA 1) H<ǰNwhn- oބ:0psیA xHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzPu}@*Ns9qxHc:wskz}:\tql7O|uZIzRkIt)|HnGqOAXkΝ1힟F@<$1;c9=>V?Rs'_P9J?_?FmS3M4x˷PF8nSW6_^t"g!M3ߣ~l~!Y.FzTMo[Mb;K:LDFP?p005 gNm`OtUkΝ1힟F[QANmyK6xT,O=Sj0 sU:  Fi1 ir/̫>8'VŎt۞ILܢ.[s[~1p1swGKk1h; i%h chuzqt[j6rY,.n3y%t orc3nB,ZlTf)R;Q7 eHRNF:Z)lc>8#IH]>Yqˎqׯzet Yc60va~Gtç#=ח J dp:RxCYs1 d"秦HOS}XqG J,]3ES@VID; q';ys<^NVlb"k2"[961Vt?<]3Î>Γ6!p/$eL %q_G)+3e]>sfE*qS}XqG .#k/7#> L)*'8ϽI[^S'2eT* 62Oh鱌㧿A61Vt?<]3Î>S}XqG Vvqϫ:{d.N?caOslnQXc)lc>8#xE8MgՇ=}Eah鱌㧿A61Vt?<]3Î>S}XqG Vvqϫ:{d.N?caOslnQXc)lc>8#xE8MgՇ=}Eah鱌㧿A61Vt?<]3Î>S}XqG Vvqϫ:{d.N?caOslnQXc)lc>8#xE8MgՇ=}Eah鱌㧿A61Vt?<]3Î>S}XqG Vvqϫ:{d.N?caOslnQXc)lc>8#xE8MgՇ=}Nm Ӿl?{ɹG|61Vt?̖>-Fg;j1GBRĿLtaN?0$NHG#z\_B[{v(m+ 䞠^))lc>8#xE8MgՇ=}gvo5?X1;fwPR}}OCϭ-W_ү[=k7*Q H φMq\vb ^+X}lb㧿kykRWw72Ip\,2Λsߡ T_`{KVTi$@H< "BQn7mٹq~uk-&Z͝ҽbAius/ӟG<_\?;p5%NI~hqȿ#4l\r/gGahb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_ v~b cֆt&2JjgUnK143&%^gvc6C@3+((jsKn|\ @̼w?A:yzπxune_"'+9q:}z(9(((((((((((((((((((((((4}hi{\'fL=^On_E9n{>$=2r.ې 72?Lsk붘>}qӛx~ȵJN2яEV QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVϭ ?=/5_z?ɞc6C@3+(:m~פgۦWQZepRE tӿAOWȇlE雙xӾ:?AZyg?'^ޯяEV QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVϭ ?=/5_z?ɞc6C@3+(:m~פgۦWQZef< nqq\f^?>y?^jKxq}=?A:yg?'^L=_E(@((((((((((((((((((((((( ?=/5Zz^?k: ـ:=k:m~פgۦWQGŎt۞ILܢ8˰#^n8} rҽ~ߟ[c&c72ct~5Jq:}z( ( ( ( ( ( ( ( ( ( ( ( *՝aƻ bXwU9S@pV[擱J51]/adhUiqp)(((((((((+COK gֆίv`?ZΛsߡ Qc6C@3+(2 [|\`}rҽzv:qc\t8xk}^/QEhrQ@Q@Q@Q@Q@Q@Q@Q@n-dVYcȩ Pӕ<?2J+;QJj{4"H2 Jcʮ 1$ {;ktr0OJԕwR.2F֧i(VLte@VE| AVMjX6+RV8>&Ak ۾QoLdt`B+Y-% ]w"ٔpG VQM;8$eE;F]H*pAeoB̠(#(kۨ!bkiۍZzge4Z7WK u ,.>ٵSy8}JVΕy%x1d0R?`{nʢ2RqEUQEQEQEQEQEQEQEQEQEǥsCOK gW;0^g|XM {t(Λsߡ Vr؇-Q򛋌@ne_Ny?^lCx܎A2?>y?Y׆w4cEQEQEQEQEQEQEQEQE9?iџJ{ 8K0 zGgNZqBI-IU2W)*;;3 DUg*A2@m.Ԭۿ#kW(K$5d}^)tM$F*ר iͨCN4x"~>`CH9#bK{TE pn{ǧC#^)QDb0TƹcN/I^iBNҽכnV]@#O'9ѷ[@AKnV]@#[ uDTUPx h㟽u\+НƝŠ(0((((((((( ?=/5Zz^?k: ـ:=k:m~פgۦWQGŎt۞ILܢ8˖۫..ɹy?^oρ_랾 rҳ W~hǢ+C((((((((d,YYv/HP@ ۠AqlYoЁ؂j ( 67u? F[$r*caq˪4̕#@9b'6xP(Z8!Cې"I!%$F HAi}R3INƏӿco-|9.!LC?zo[ ~\Β8.QKO "û(| XڤחFO^[~%> #uyIJBl#=?)8/ LrCfӤ$vV%[\1CqW{ynLRFZƤB OSuALI-K`)QEQEQEQEQEQEQEQEQEǥsCOK gW;0^g|XM {t(Λsߡ Vv x׭̣~5J<Z㧟8[x~?AZyg?'^[Uy/QEhrQ@Q@Q@Q@Q@Q@Q@Q@E3 eSӂ=Cuu\v!5^1_+58r N.dyu,f9.ft=U AkK,/0ܻ[cm8#8][SE/i%$r(RXD`pTƯIzOqn(ɑaݔt>\t֏Sh8}<B "^}._k/z)_"/su+ZA òI+cT1s2G?댼GeYѿ߹V[%1 %?ԗSg. t_G<_\?^|\ ~rҢN/_E(9B(((((((( arā< X@vA*Kʒc}ocۡXe"%Z@Sh@xGNtxhVGRU#"hVSƮaOA#sJʭYOޗN/֔{_l3y{|M8ϸ#&o} LHQp<"[8\sn}k /pI]ymP[Kpdzb*tE?~ch:0qRȆhF}_&9ҋ[ky&yaid2hQE )&(HQEQEQEQEQEQEQEQEQEVϭ ?=/5_z?ɞc6C@3+(:m~פgۦWQZeA$=2r>,s}zH{=e~]*~p72Lskۏmhne_!'+9q:}z(9(((((((( ᳺR[M**宛[γ[8ŻA 0A Qo/rgv?БD{Y[|Mϱ#\O T~ݿ]Kj:VgR]:0Y&=0[Ǩ{3cQREXby ID}s 4Zܗ?F_UMe/.ZN&2wЃQU/f1Ӑ>WR+{>kӽޟכ( ((k{;/Rľz@>@jQimGO"20ebAn tv8Z5H֐*3 FՈ &ObQE QE1Q@Q@Q@Q@Q@Q@Q@hi{\CYNף_9n{>$=2r>,s}zH{=e~]n\y?^j?ℶ\\9?A:yg?'^ޯяEV QEQEQEQEQEQEQEQEQEQEQEQEQER20e$09Ag[VVOPq\^lv13C}ImܨgR];utsz[AETQEQEQEQEQEQEQEVϭ ?=/5_z?ɞc6C@3+(:m~פgۦWQZen| o?.172qNrҽ`}?AyD8X_jF=QVrQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@I 2zQȥhC械#vp?JnUi_vG4*M &qT??zeoR |}UJTŠ(HQEQEQEQEQEQEQEVϭ ?=/5_z?ɞc6C@3+(:m~פgۦWQZe~| ooI̿^ rҽAius/ӟG<_\?ՅvQEYQEQEQEQEQEQEQEQEQEQEQEQEQE*:8%B(Uc9햿o?[ѣr0E63[ %fQc{ZRŠ(((((((( ?=/5Zz^?k: ـ:=k:m~פgۦWQGŎt۞ILܢ8˖> ~COWٜ ׏o8\f^;}-rҳW~hǢ+C(((((((((((((*l쿟׬p[Ot-g%cB^*>@K-%+vRIo.A$,{"$K`)QEQEQEQEQEQEQEǥsCOK gW;0^g|XM {t(Λsߡ Vv܆5p77>cG<_\?]#~EOVsuᕰ}z(9(((((((((((((3(6l:GpGw%.91Q=ŪIaA##;k]P*Фeg&3=TCصZ'p)(((((((+COK gֆίv`?ZΛsߡ Qc6C@3+(2?[":  '+m?Cc"m̼w-rҳ W~hǢ+C(((((((((((((uRYi%N<-#*2zJLRb'XAVze %{QL(((((((4}hi{\'fL=^On_E9n{>$=2r.[7[v[:729~uJR[ێ[__!'+9q:a/QEhrQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@AϽ_"QJ)4\7gxnyRG?_bPRr(dQ@Q@Q@Q@Q@Q@Q@hi{\CYNף_9n{>$=2r>,s}zH{=e~]<q^?Lskc7AOTOՅv4cEg(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEVϭ ?=/5_z?ɞc6C@3+(:m~פgۦWQZebh9?A:yz%us(~!'+9q:[v_1袊 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( CYǥsG3־,s}zH{=e~|XM {t+ClCܨM72߯G<_\?X{|0[\yCq&Fwws }rҳ W~hǢ+C(((((((((((((((((((((((+COK gֆίv`?ZΛsߡ Tu hc3A&@:d_88۫..ɹy?^oρ_랾 rҳ W~hǢ+C(((((((((((((((((((((((+COK gֆίv`?ZΛsߡ Qc6C@3+(2 ( [F;jn;]_fKpyv5KNҬfdI|%y_#>)WĚ7]6oO㾜rw/料_33R62[Lje3cO??,>%hnUA%gLy?)wfI~?pj__"C5/k/^w]B$Km*Y@AϨsV?k[2h dNS辜cXm_33R62[NJuKn>Pq: ?N\&L1:G?r{'݃AoN?7!KWvariT'A辜bXohC33R62[+`MH'g_N_1\|zNcg}9=x%wN?7!KWrar{'݋?8oC5/k/G!mn^k8~?pj__"C5/k/]x]4@ap6?NZ|M@m2:eG??'v%ݔ![? Կ Ew he@\N8>|I˸+gz|}ӓ>oMoN/!KWt~9Oޜ8oC5/k/G!x]\Į*z|2.O㾜#̸ܻr1z|Oשϸ~?pj__"C5/k/]$yΙp<:qqӐ[if3ӌlwҏdXo]33R62[.Vm6v;, ӎ|O-o]%c :nU'}}zgf@moe*Eoo:Ck !k}>SGmv:uz|/\%wS:gA{&lk05"ӯr=^On_EaxMg]%:LR f?>Jۖ]mOmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example3e.jpg0000644000175000017500000011536710504574206024642 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?5|=\3BRYb~Ib sCӼ=3X==k{\Kc{=e~]TIOJf'<$1;c9=>VTmC"9$N:\u}@*Nsֵ{fir$#=#oA@2.L)q{oV5 gNm`OtU}R'>(`G'z÷L E.{o$1`rs۩=9xHc:wskz}:\tql7O|uZ#46\E&wȒU8 n=4xk%u;^Uv)=>5 gNm`OtUkΝ1힟F[αw (%wN#S4-ڪG5 gNm`OtUkΝ1힟FZ׾+RMvHO-#$n'8V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'˩bbB`w``p r\tql7O|uZ!ͬn_P9J?_?T=rMDMc sȀ |@ƹ!ͬnZڄ1ĥE =;d]$0ݝcV'!z݇X<$1;c9=>VYjH&-I8'2V5 ozu1gOӏAO^u3M!͹PMzǣw@i吸:ur_SY|V<ݘm&?5Uψ1>.gۦWVmuK=q#E~3A*;:U}Ʃc{mm K!?qV29g!d|^Tm!;FQJr*W$5 sq~ñS}XqG 4I=NQ fE1Vlc 'ӯoY๷g5"Ё\ 8><]3Î>S}XqG i3_y{#ҽJyVqclMqՍ;LmDK"Ul|]p[)lc>8#xE8MgՇ=}ok?~>:\E#E!PO9)F'q;Y3@Z}|l9UU 8#xE8MgՇ=}VYsZmng{[#gBBG NH޶4mܢNjS}XqG vqϫ:{dr.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7(161Vt?<]3Î>ܢNjS}XqG vqϫ:{dr.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7(161Vt?<]3Î>ܢNjS}XqG vqϫ:{dr.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7(161Vt?<]3Î>ܢNjS}XqG vqϫ:{dr.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7) kw n|~?GS}XqG2YE IQy"~2?<7BqI3G(g;HX`8AӴ#c HY$u|Q61Vt?<]3Î>ް\Gn\Þ''ZӿV1U[?yspk3%=9=w=̓i%F9W;QAp9>5?@5C.7Oujuo%3*u6Q #==w<9}c/|9oiw)#fH3 V_/UO7fqy}("wLeҲAPI2TFڽ͌gvnRE=>y2XlgۦWW_BTgh֩K M/ɒl\r/܋?YU{(v2;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#5?^3X1>ljtc`sc2cQ(F-4qU¤jJhmCZ-j#SuY|V<ݘm&?<LV>z%?lɗףc=2rOR~LEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW{ĺ10n91{1 ߇%юqqq#gSxO_UnSهf~bcJ(e[vaGҊ-|AcѱOn_^'B_ ψ<{}z63++/K!YϑؿʔQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@wz%?lɗףc=2rOR~LEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW{ĺ10n91{1 ߇%юqqq#gSxO_UnSهf~bcJ(e[vaGҊ-|AcѱOn_^'B_ ψ<{}z63++/K!YϑؿʔQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@wz%?lɗףc=2rOR~LEVQEQEQEQEkM-%[ap, EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP]Ã88eָ*~xF9 9?s/|>Mva>; V_/UO7fqy}(UnSهf~bcJ+C/F{=e~x! +> eLܯԿ!/g/>Gbs_*QEQEQEQOxe#y#tYW|e뒹 ><%4Wz\H:|E\?tM~9Hۺqb ZUK2*ܨ%42$KxJ8 ЃL\ysϔ&I+&60b X@ %޳<"G|*zɑ@tQVtNve]G wc¨h;KIR72I'I8N'K(1o,>G,K u:Zt )_7$Q5ͬ f 2D].@+nwĞ#gnm,qoiw41~ Hh譝oA>sUcPEPEPEPEPEPEPEPEP4뻇EpPѠb GHUBt5hsiH#<ϦLi{x*G5Rpvs72ؼ"FGYI2JS>;UZ鯿W?٬/I2ޫLA:h;Pga9 /iPWoYH ze41CsI7P+*| <54wGTWeQy!i'9)lq4QEQEQEQE88.ss~^}kljtc`sc2cY>fe[vaGҊ5Y|V<ݘm&?8_y2XlgۦWW_B&^+^{t=KBVv/7%2QZaEPSEgu51[M%:UBV= < jkKnRJ 0A9Ak==Bn4X#2L@`Bd#s-pWǻ5Vdc| (%Rx{Rx: %RUpxij~t4ۀ4rbF `PRI"?p*Ul%S 0[rx8vji|>:%͘ՙ,1 ZԴ]][c&w\8 "}n$:=4Y.^hq+#]++ ://_B nf3,av9r_ጀ V*j> u/L4 :Ey.eGlI~T%H&%iƛV;+[1AbXT'lW7L>HpFhie>D&ω UPdmf,r@7yu4աVxH(,K]O(IRypWEҭAk-45G911+rLJ.A=1FJ#dauv4( ( ( ( ( (RXoO*y@'pdTclHXeMUu `O= PEi P4̓ @n zFC!;K;^3љKK w% b(:T#5)KhׯgÝzf]RN#m 6|0e\^ 8!Fki\$G1NVlP! w}bmWI]-Ca坡I)# GDfmiڴBy VQJFIbUYw Ҵ ?Ot+gick-X٠(Iv.cppeLiRqVo\wV*X06Ck%kGr̔Nx<x<eîkԒI"!QTCӑk5MB [Ȇurx!0v\ S Jgm?/ [Evׄk\.drlڪW\;`*3/@Q@Q@Q@wz%?lɗףc=2rOR~LEVQE5\t1p9Ҵ^=ޙ/Rd\Ec=I27 Q@?]\.UC,.FR1x8Lt}>Dܣ$#?+$cNWR@룾{_ªEG)zDԓJL ɿ'ggx֯nRX+Uc"Py7g1x~-gWa'9R233+y㼂KPdSUw~{PͿ(Yq,˝0 "qp*/#h.eqb4,_h1I+r^ @sTn9J𽠴Daf!BQ~S%[ǟLk wP*1) b:q%{䙦OY+NK #bN;wTrZ^lo% {is78;weB Sy .ōɧÛ0[#wr}FĶEAR x1 #uEu64wxdF 'G8-j[}ޡ/Aemv8PT䂼RIcԭ%g7GI,IF@B$$O wmJc"U ) O?V.}io,{M# +DG?ixFko Ũ*(+ŀr/#@Z} p˘7l`6ߛ ExbTY(;Q+Ï(R.$G$!q}@-Vj9Kꎰ }Ao%A =xv.3.n 8;؂@P'f[-Σ},qqqo>cn!fb#ieƨfֺ<3k:jvmU$y c6NhZ KLZu@8v< #s2HV ![CL1ᘵf#Z=Ƀ <#xG3tz]}?T71Cpwσ6X@9[;?+6AF%BeU=⡯Y4YɴN xd@\Fr7R$Tmli#g@а 227 ˽TVg_dשe?>z{XBЮ\:,Ar{pBǂuhCɨv1G9c+b8wOl%DeRR_)d3P\n Y@1f[ړ$ͤ]^[1&$>dsFy)&ݤ01Mۏ jKpv#-&'v牑p(%T|}Nt`{1<˷WG+&F8e'soK)82kX=ՎϊV78*618@A#|qozXmZg ΣsmO,<(mO s͞ڄhHD wGK<9q~W6$^c13Hg8.1`*X-P{kkǹlU*h`.NJ2Hg'nq 8 ˧h'|iϝqbP΍$eC#3b\ o:bH"O1E#oLU;z S1!w,֚pHͲ[wVrUJ,] +/Sok5iR_.'UX#'n ;]qlb#L[[-f Vlb&1"ѻ),[<:i7m`XfwX9\2xקxJSQ>u}`) j.oG\ ;{iONLUU7pBn +¶sv7lXݦg,*<0´Q:MQE88.ss~^}kljtc`sc2cY>fe[vaGҊ5Y|V<ݘm&?8_y2XlgۦWW_B&^+^{t=KBVv/7%2QZaEPSYȑ^#mDYYpo<;?wizf>Mgi* #8^wc'6o8[0P0, q#dXC_i?jK*ɁQecp=2hmjP&YcE[م'^80<2mY4k"-gHĀp+;H@6;ĝB0`s'wZUd\i7YHq֡ԮzKk!)9ORN9+f=S@]Nq:hJ܂A+'c8z4sbo2FF7#^e[认YBiRw*|eKdl翂ifZGP_$nOE[K*h>KƩ!oݳs@x^ClݭKf!s&@DU6^^k=Rxby嬂N$! dc#r8}%4Z/=-|37Vf`RRB9fsV.&mFHς Q@<{=F|j]t,hS~U;B]'DҬ=2Nqjn@S*d(z֊Gݛ%Զ߸);6ʠF4AZV*mcaՒRLnDfVbv쵍 ;* :_צ(ZRHy\}u%rPݎ~pg,mhǹY,pXr0[0nMGő-%TGsuW!v %,mA$0_d\< T;-Im&9UʜeܗmoIK{43pö@ P ӢcPKTu ;S@Ga댜,g ℘Q+|  +5 ZK.oqsIrZy Q6v=qTzEӭo⌝ڋ""=πİ@)>ɦi}\HYw:%z8mتzvwK{tIl99䨎mNcRfF%X U^qP GSi'W~WFBHI?X۴^hvV;"'ˌmڡK`U ;kzƸMXap0 #K[TS: Ν93Cm5xWMђĀv#G8}o- 3"{^O1HIYW6u9k9`tkc*ܩL9WW6$lКu)GtiIiU*=2Og &&XV<&am*gR3OsjO-Ō%hdwaE9;@vB cCSe@282*ڝ$'Qr."v $ 9''$ӜD}|wrt5GX縍cvϐ0$t{a^Z1\9dR""Ҵ [W]d4WQ]Iˊm4;d˫U_`<r33YӢm˅XrD ø q0*;4R]BI1ǻsO<"`Fb[x+(8O݌pg^ ƚ-ʱY-FAgfx͂20+pq]7̽?]Ã88eֳ}N'W/Ga)3n?11|jzy0wۏL#Ehq eLܯԿ!/{gLV>z%?_oKeJ(8Š()-t+A4<|9/9Fq pxF#;|%8mgՏwEt{Xo H-v&T] (YHT40__,һ%T̲EyŶBFEFZýc+)8#9=niַ qk ;I ;[aĬc8~p5iimri me{b~n3pj:D?yjO$z *y ]f&ҵW%Qݮu%r倫܊IN Hia_"ȕO*{wS,Qh p%SԺ̗ZRi怫1( [sᗖ,iNaզyQi QBؐ*pXk5Vk#s 714/ɌA䗏a-6ݨYy3*p g&ϊ-m/'Ԍ0LCHG` VP ~)=g_4_aC,.ČWd[|v䙆5?|h.'ʗ }2taE2i4h5;R6Wd C0A `Ox2ٮuyg0kNcGTbR\`Ar[H[TFe"-n~G'b?yl]; $Nlfe|ˍf:d⎣cu{uKQm" #cY5RS1e[/SE *4dm$hDnFr p8 gP]rn chf7 $gc'y3(ҒT琊HGԯ-' 'jܬ\1?yJ;Whxu-.9O}F4b~o-U7[nܑrH=[#cY)dȆF9 p+]$ַM\_qVf]eIe3)נ<)="O,֍p:|bA2q'<zkQOde%di3&B9)[[+#,m$H¬^5$b7@1U!yV2?<契Ϲ Imq0v|A4\y $=@Mpv=s-` XlŽy!^F> YY4{:.n'开F@H?h9C7ox~h\,vr^},lN:c86H;xgE(p7cnc<6o/, pof6( `c;T.x}UK< !I<~bpp-?Om_,43K"'Ġy`9Nm5tFm 󥉊ɰ#P;KC.5}Qom՗H"\- +> ᳟4Z!' (̭\q0X/?w}8R.Ybp;61ףd fe[vaGҊ5Y|V<ݘm&?8_y2XlgۦWW_B&^+^{t=KBVv/7%2QZaEPEP5+p۫qu ~Q70Zu.\7Yy~L֐Qr. ;esobR[$vFIHCA! sgI./_R쐗lvTT>U`JVj%b)*7<? 6gqiٶCl.7iY\YOk !D6W ɼ9E+y5m>#hL kɑ Gˌ)l0Dlla_mLKI`X2|{rrQ[y"%Op,wۋgv aWeJt}.8絔GwrG"I[( e\1,l5K+HYlԆ2Th>K COVa TH}J励?ci.bH$ťsDiR,rUla۴53$dIS%9=>N?"V?KpKTtmyqvone/8\s9MiI$A)yfVVq#?P{ݴ#cc.}F[F\$gsD˵W'y=Bk[F1ڗs2/ #4@ݻPEvL{ .u;]FJc?\Hr̬Wp#wF8**}JXX[]Ds]q8YYӺ2ndړ>i.--n&7( s$Q>eѐ8NBAOj6Z-1Dц ".b\mpG]̲ϡM,7ZjWq3O(J$|+R"3Ry*5)Ѥ$ҸZ$ ώ5L4:Im#Ċ0b71ۃ*Ú [ka?# gͅ07?. [ys5ω|Cw\ k!o;IS8i fA>MB.׻<,0v_rIm}p 8Yw) `>eF6I  Ll7@\| ˹lIob(/s!݂Cs[PEuhCVEREU P vh˙f)qiv#Q,RݐGMU#Yӳc`B. aUl.uo *гq<1qi42#v+aYSQ}ߛ#Qj Ћb'7Ơ2t9HKeyC{wk4+2 2T$ԷV:%S!X#ʤs* ,J Q^.RHڄ(csNzoX/ +B 'T*0pOksjbgD#~Xr>\Ft뉥 GO% ʗ,zXk:F'Ǐc X$.֩vTK3FYw(?*)GV\Ḯ"J+*W˻B ;. VT&=p9T>PV;\לqs\ҩ[ve3U8 26 >Pw :im6IJwͥVK.wX"Gn[YhVSAmm Vd !`0B@BvKJZH']FC$g`\ v{oʱ^ 8dK'PpK@ VKa6ZIq D`<(C*BOPFŜ&96+y<퓲ɒć1AS6/բc*uQ:>tb|gdgHm4.N}!HWgN~E.1Rp9ּ?%D|=si++%iƓ2ʲp g~j4|&C:DXWp̫ w eP]Ã88eָ*~xF9 9?s/|>Mva>; V_/UO7fqy}(UnSهf~bcJ+C/F{=e~x! +> eLܯԿ!/g/>Gbs_*QEQEQE>96#e`r#kڶ:u^MG V@q>O#Kk;in;" `dO?iMսhݠ$ʟ/;1#?GEx(K]=n7Gy-\sN0GCqkVRؑ]F,lAQ OzpI}P#=wHKmoIAcaJ淴?wr^[!C1,I0#vrTf0>2]7 oI1fLgl0wNQM[b0b*s@9@'%m&{wjEC`Ѵ%Q*)TWSgv0Wvt:5}6Mf|)S pB %@-ì}U6[yNLc̑.G,eOnuu<^ iPqrp\ԮoYl-o%m[H6ύY~c\jxMwUG̘ \n?6@9kQtLj]d|3z 6 [a²Mmslo~BG# k%r7˜tvǾ3A_-MpGƌX8C\v7 gT}Qro+,l8,죂= ;zh{wkv Ga"H4hd)]1#uF9{n^51 ( _ZȱMir35H<v@dRM\x[-Q[Y  R̅bLjZ\r-F clYNZFX`vW.v4Bh4#;imI3؈bɁ x;KM=ŵ܋q\ڑcHO ,zfjw\4 d6[1+kA[eф'X-/_,6~x#H`< "DOgf ;*ոQ1M犴..搹88ɠWViA;": t 6r1ڿ*qN3c\V\ +NH@Pgw" tSL=&qŲu+Y -,j `9>X Ԝng ZWz9KcmQl#-bT|JN,SEĸG`Y%G?3uX3סO$vpikRN2;%"btR2Bk]{{{փ@c,$28;,J<(faH t+GB*!e6JTv,](]Oi fKDBir>9$s|<>M,F&Wr=xg= &Xfc?\1r֒jGӚiR.. Eܡ F3Զ0}5> $p[cDwU;eqQ4q*Dd06Xc򎋴OpٖSAkkx?! یpsXE)q J& 2`7vdarը0YZg-ݫK>d`8;\8?6#ƣ,9n8S  vP}+k{ZdA=<ڥ'94cM%{i41|*@AnOZF'k#6ipЌz?ZjviŚO1mb<sbq1Gea,_$R޴(W $q K H`mɂ5{m%&s4 `8 }3Ҭ[[ĐG7ږZ;YmsLW DUmk IU^D  sw4aV"Y˅3p8ӁIОxo^K#,Y@ p= #۲Y~eq)lyB[@=n42]J\ #$d3)eP=ĉ5_Qrm XG?dtٹ@ 0@'o 7;I/h1۸,Ks3HF8%zG4c x$*,'\^j~5@S H@>wVSp8\mZ6NWBEIѭhX Im9' kv֚r:B%>fJʺWBYhdO!c˲|ÐFKER:qZIse~+KNYN1|P~ dz]*Ap/Fi$%8` E?]whЇ2Gԩo -ܞFdmoK{(my|28V{嬓Lê,.Ir\|S &]DmOҽ58I&xin8>b VFl zDTsɕH!$[y5]4oYZC!]"p8)>r ( ~xF9 9?s/|>W{ĺ10n91{1oS jzy0wۏL#E^rn?6QZe<{}z63++/K!^/F{=e~x! +?y;R(0(Il d(b $! @mݻ=(=1>ZK IJٙ9(_d5;TKqA8;A6h^|7k:IbGBsxxU4^IQ< iC2BY&#}.muK;K\;r3@&uc M?6cqxria/.K.T,{+Kq qIVE korAGp2Nҭ IkF%QyķZw3pC6HkKqIu#JKeiZAǰ+0'皉lnti"YcHl+nc-@p>l8غCZ'폥_@r%u%+mi)Y.Vdls.Bp.Nԍp@H oHKu Hv', vj]yP[0BCK N$N})חZE I!l;6@RHqw<>AiӿDdMd:rrZi Rծ1o 'Vhcp3r+MMcֶRF̓O,.HU_bóJ Ƥ"Hn.RB it8R>tG#?9ny8 28ʶҵ #h}6o0(6uʶlrNa\è@l%ce²LʻW~Q%xі 2fL˺-W\\h>lJ$@%&YaUU\Ά0K)FV0z/ZգIDXHg :fpH{5u/J52&xfGE#kRI MR-ŊHQ$PP,4x|:.]5;dwmqySP}"+ deIg*9oGc;˅qG 5!˱ Al j1GI()avmrR /2`{d䕣q8_G2vZi,Ƕfh2Z\EZ =;OSIr&>dL7; r2aֵXu Ӱ,ibC( @m[>}Vmf9I"@r ar %m#G cs Ucn8-WmV$X_I2#mp98#+ۉ&.`P5A#>lp ( )5HddYbcŚV1"6~#~ ܍/;KtbTż&8C1Ȁ8=R1W%\mι~ͤm-))*ddiUlaPH*՟"ķkox#F$+# w({LM>X $K,IGMj嶑2ds QBӅE>DyܑfTs=łiwt,1H=;MSE۝FKt G K?F?tMgR%]^R,ΑG 2P|` iu<<٦iɣy 4~Zn|9STi ܷEČ'θٞ@@-~bs| %'_tm1b$ mbH*O~PMՠDЕq%@$qWUw6X2+XK4t pA`sqvv+2)I|D{B@Er݈m \ۜ88%{q@V yW:q$pI$ϵWk{h÷Rh>@2:y75{u-lGXRȹօ:V5xN1Rr ʚF]O@ :|e~NT,g'kַ>:e⑁f[8O =9{ۗk9$mՕ)u9۴nO!sMܩIrd +v9&-Z6\A!vx 0 p 2pFMU(+pq]7̽?]Ã88eֳ}N'W/Ga)3n?11|jzy0wۏL#Ehq eLܯԿ!/{gLV>z%?_oKeJ(8Š(((4ߛbe IBzcF0mc*ɜ=$%p\?6÷;2|nvjigt%XILo,2QX615 ('pB/Q::.ew[`ngrv)ڪ$ÁԜ~qI{%̫p""M2e` o=kԬٴ(%ـg;D ˻;rsG=oZCDj0 uv6|eͩ7-z4%لъrcm .S}rGd4 尠y->vf)bX4!I]9瞝kFHż2;UNA^e pŖpA8e^8'v9(8閚w,Lc:.ONxz{ ZfU:jP Xoc'Ju+X5 /'C`68ڒ Cʺ{y72Eo# wdaHmǟ[-RjP2)攴l Tm,@ &DՒ"9s1pwu; F{la HDF8P2ǩn~bv/#m T@`Xvs(Q&A# 0yXKIUc,fUr[9!FH$$nݽ&g_. 1$~l  ]2|= ( ( ~xF9 9?s/|>W{ĺ10n91{1oS jzy0wۏL#E^rn?6QZe<{}z63++/K!^/F{=e~x! +?y;R(0(((Zh6#j.-l [ae'[G dElgQW<&1zήu=܃vqW'ԧ5y' 6+Fb %O͸mgiܙYQ%L-]on.羹{+'`6?#U(.co_Gzs @YEY9?+mag#-M?vZx]`_*\Gq1.rmY4\2O?:t|Ao7iپrxIq8Х𦙧__ZqX=F#ˋRZ10&]P`2uEfQ]*\d2*' ֯4Vtt˛J]R2Ճ_##O)$զ- *!(QeJT6?,4 g.#c`~buoo%CrSRkK 떐1B!2ɱ FpJqw6̬佩$@0ڣ6- 67S\E4PҢKҡs`1%4iqKwZr2yV ĊB]-b3CADf~`F:[]^YdضړMjy T1$`IH>+ BQW,ǒ# |e͏8Ce)0t6? }'kihtfV;쑱8=XTQEQEQEQEQEW{ĺ10n91{1 ߇%юqqq#gSxO_UnSهf~bcJ(e[vaGҊ-|AcѱOn_^'B_ ψ<{}z63++/K!YϑؿʔQEhqQ@Q@Q@Q@ھ.R4U$D푐='cEQEEfq+դHKct~U;)A^HK׺{&TE^&U>h X'|¢;?kٚڵm^>l ?;*Z[+h)Pz3s-&յ; w]Kcd.[s|5 UKhݦVuM;\M7Ò[Maioq,17;e3"PɰfgأOq#qWr3mrWd_XUarF`I2ef9'aui:q26p\$ñ%˸ ~emk9 , 000b4TKu2mXO:Ik喘9-Z5Cpa9L&rUɊM )qpbd2 |)b'.kwukGQ"ݲ@00K {˃63My)8Yĭ(F8ܸd>\Bm8[Hv;LmV%-Z\@d3铀ORI`ɴf5x #ӠX0m; 9U /=̨7 *2 MK-5[Yt Rq2*mv-3]g{haA2EpC)VpAph>&s%dki~׍XqP2 EQEQEQEQEQEQE88.ss~^}kljtc`sc2cY>fe[vaGҊ5Y|V<ݘm&?8_y2XlgۦWW_B&^+^{t=KBVv/7%2QZaEPEPEPEPEPEPEP[?-_d42/oᲳlg;>f1ڙR @:ouB8MB ;e Hc[K܋NKx&x1sF2cXN rxHº嬍&˦i]֪B(P2cihL^ e^rmwd wkL1BBKBm8A[6ZmZ[^==-XQǢCEQEQEQEQEQEQEQE88.ss~^}kljtc`sc2cY>fe[vaGҊ5Y|V<ݘm&?8_y2XlgۦWW_B&^+^{t=KBVv/7%2QZaEPEPEPEPEPEPEPᕠ9!h0ԐsʐA`a&宯!OHe!:l|]ODLVQ{a++$` U`H >ıI:W7XeL"#bʿF=͎e^_)B ַö\bUsc%d^&In4;f][Nir5$rQ-Cm g(Ap*rF͠,g&YiYPz `c5.--+yPFE;: HĨ݃n~ɨ66H.,.DkKki -2K㌚k.u 4,ɌX;e9\7lIRH!̅ ŃI;84erc# RPH*ZLח2K-78gFq$Mdx_IWHa[y Urj.ʕ$n#;ZvKӒt0@}nXC~F4ocƺ-R}WV7BWry_-e'GRQ`@IPssN{61GnVgv>syd(waȮCQY缛.r5bɠ :m?Y?,o+CʰM'fƣc5:I'x.mFAAA3Ko{뗸}2p ((( ( ( ( ( ( ( ( ~xF9 9?s/|>W{ĺ10n91{1oS jzy0wۏL#E^rn?6QZe<{}z63++/K!^/F{=e~x! +?y;R(0((((((((-t+A5֡$jS`p<{ruwI.m.TX@DQ.u:*"]"sG'Vٸ7!󐧧} KmfX2T$n>y* F.uR.qCQ|?gC*zF xhƗVF1!3Lm:䁗^y,ָ*GR3)HOl .Vcs)=>{e!mB2O"Z5_igKK6Kh-E $ n3GeNjmʹ?gӌf A5*Hr͹l~.E-BabUvho 1U(ݚ|Oq0]=Dyr>t5-.V xZ|b|93Ovi"L/A[,rdkh{[J Y0\`| 79MLIr~%ibl!f=Ƕy8>Iַe{Gua4+nBn0r(J~`>$ۃRӭM1fH)!$ڡ$d+ɔ*,[}kPӦya51'_xA4mW 9K9i12asl!A&}đRc|8r0ʑӆ9􅈪FrLtbSM渕+a![96v]|%w%m4777ZeˤDiIXRqDK|e#{0^((((((((((߇%юqqq#pU88.ss~^}k:|54v^rn?6QF/ܧ|͸<>Vk&^+^{t=KBW|AcѱOn_^'B_ ^|Ŀ&T+C((((((((+uMKFKw3_Q\^<7-EQEu YA\}lج)IRAq7bԵ?Ja=Vp2FN3W?[>AZ>1%6`3޵uI^*C326pFlcՕeƑ̄|qNxf ["6wϷN3`%0Hܹݱ3á)cZ]Bi&$. L3WRFUw+Xu„B18l $V-xlİ F<ƫWZ\<ۮؕ \v@Q@Q@Q@Q@Q@Q@Q@Q@Q@wz%?lɗףc=2rOR~LEVQEQEQEQEQEQEQEQEQEQEV.Fyr]2'jN'ڳ(((((((((((((߇%юqqq#pU88.ss~^}k:|54v^rn?6QF/ܧ|͸<>Vk&^+^{t=KBWxݮ伲kWefҤ?)'8O_B#/ɕ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ~xF9 9?s/|>W{ĺ10n91{1oS jzy0wۏL#Ei\̳.4JHA2;}T~@QZe<{}z63++/K!^/F{=e~x! +?y;R(0(((((((((((((((((((((((ljtc`sc2c\wQ)3n?11|^]L[,XB=8q++gq3J6\ԏ?8=uXAc x1zTJwK4If@moe(3R62bqM 1(( ( +/dM[xngYFa<v$[?xi=-'#־WiutW) 8=xi=-'#e}WErxi=-'# 8=]޿.utW) 8=xi=-'#e}WErxi=-'# 8=]޿.utW) 8=xi=-'#e}WErxi=-'# 8=]޿.utW) 8=xi=-'#e}WErxi=-'# 8=]޿.utW) 8=xi=-'#e}WErxi=-'# 8=]޿.utW) 8=xi=-'#e}WErxi=-'# 8=]޿.utW) 8=xi=-'#e}WErxi=-'# 8=]޿.utW) 8=R񖽧gM m՟L`$}h2as/kucwfؤsUD}(}cv\]Š(EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPQE}EPEPkn}_{F{uez]y6xg^[ץөzDQE! Fdxu$px)]%0/}^趩.ߘ?]%0񺚊˺7GuA n!!/B_|K~`tyw_,s{ nmmvgs3L{Q.1K5.d쑬q RQP8 yw_!/-nO?yۻm k#Z=4Wm=A+GYm Nᐠ!/B_./s%aI,ƨF4%}/\`(#v5KwK]yae k)fH E apuA n.ߘ?qskam2fqH;BWhN0ľ?k@3Ǩ}GϏ D@1 `X ˺7GuA nhZ%\[\,H;dܩ9*r8Ѡ|K~`tyw_j(.ߘ?]%0񺚊˺7LPelZ@!U=zPnjMEPX$81Iq.߬_x$8Kq'#OCh_UWv!/MAw*ZHH(((kd0@8m &ݑ-􉧴\I]ǹH^3(GkNKJ='U(3 (.`8a\nF '$Id4vDQE!Q@TW7ZZs;l2;`('ښM!۲%|3 eH8>- 4QU-mlm%6hs ZCVmn-$(gNy9gzɰe#sN1C%/_z($(ךKe/OfJ ŤZ0hqI* G`W|ѳ s9]abZ(!EPEPQE}EPEPkn}_{F{uez]y6xg^[ץөzDQE!2fmST7 Y[V ; lyd U"?ȵhkȵh-!E-VQtH"Gf<}= maEC%Y=h*;n5OP26`Gs+g?KmA*6bOs O"?ȵh>o?hg?w~ٻnqڪgK5Kb%WӿGWlV?rQX{Yy}o._Q_F㕉_hFkf?n} d~>I̜nG$/"6qBJV0'6鲽k5eBou9[|5q5VwK$;odNrvT7} Gb匋 $lV0Oq*Z$8C`GqG7c GgE>zMN_'3*9;vvWӶL875Hb./4>$WOo xW'wޭ&XKP{Y<g |1 =R#6R}p;*tcteO&8N*hW/a=9Tmmm}J؏zÄINg=}4ڴwO!yY dO5?f_jcF/7v3*46)be*G s91B:鮚95 8k릶9˅Zzi0nLzc&/uqs{e'|ZG#%bKh^(Q F `tz``~TVdR}sqiSScG]z8TŚ Ww2]߄\+,x:SM'#qpoK<*Ejmnp݁<*?vD{6R]Aeoę*D퓓NO4玄˭̩4MǗ[Zwۓ]8Fk~=B H O}z?S%0 5hb L {ף-^=[BR.טFH~Busf % ޛA%M4^z},ʛSJKm,htVHMϩ/mw`\0H`"gK UM:j=ncWz {01} lv0GӬ^ k+s Kvs rr'҅۶׽-eIMICK^z[Es~>XHYn3Be}1G\_QSmm{p3@^k)?39;I<Czǥ0)ɏyL%X{}+^;["۩Ido KN35G)XTS@NtN:sR+@- l`"1!1EST❒kKWAQTI5t8}?Uu5y3w]%#@7ăUooAOaۨUރi^t< c-B[+D{Ķn]0a5h;b]6Ac(voKh 2mv-8nR653+ KŶA F g?&x={c}_3>3ӏYLEh岵qb·/*J (C (>((õѷM/Lǽģ=2v.]tP<{J3ۯO-k=OW (o}^趪,QX\iEVhQb#6/}^趧xLMR#<Ʊ |ȝOU,eO0<@?g}Z㷼Y-vl[J%!g]A'5;o>܈/4gh2-\$ p:]&omA.Y` &-ɵݻXI`y+FHS_^_cwdWi$) #]I0O c玕vm)5-CVgkm۬[UN;#Q?7"/=ˏ%ԒL 0Hβm+$ 5kMP1Ҥ-Z`ٴgϵs==f:[:ufW3fm𫃐\GSH]V}bqh6HLJ'`s>f I'm^^qWvMYA.Co5>ZjymW?^~{u^rm. {1%!;|lz,G@ A<̒20q\ڣg99^y2H?tu.:dQEjyX$81Iq.߬_x$8Kq'#OCh_UWv!/MAw*ZHH(((((((((((((((((((袊(_U(|1yDЉ ڤ6S9+|>"~Κ/ͤyƺ6xg^[ץטZU*os(da_kiq$%H݁:ےzŠ#DiKZZ r}R_fGeEr#=ƉoLڗw17\Nxs~3iNݾ{[397D0=zHruVXW^~Iv ikiU@IF {kj3 & :W7Lfkأ۶x_*3V_m=E#%IN8ޅV-)ƤmW]̛_s/kuoo% ,+v$0רkZލEP(ذ华8N*qr[/&:v"HҒ\ޏ杗̛_s/k/.o䷺4Xg0$6(9ڏxFQeTH(5f||fsnz`zG}Jŗ'.cx{xK~.?=<%?Mbk>65Y(#Wʃ!#jѵo.54M۠&rDjFRq[JkM.Wkj'uEt8lpZ/k2!a*k}M/en"{bϖ!xQUF;Pc@SpغNKzϲ ?M[cFgw,J%F$kZލEP(ذ华8NG.o䷺4Xg0$6(9ڟeЅUŠA;{_3QF9PI#o WFSҡY7nW b93ӽ5R.N+s::Ƽ{j+F`x8ơ'9\{+2!qa7.mf:tʇ-4K䟧n*%O&kW/Q!4'eEOMOп6=?a.u_^1y|rrل7p}L)֭on68VҴh8-]e)eT\UGϭӹQ\Ck~u;6y{Uz`zwZΕYZxBP-nb/b28$h(ta*΂Kjۧ[ۯsۯ .<d{g%Ka~9l q߽sJoj6M2F}@,su(u~L)؊{?z=>zwtV7uMHT n8z׊]sR\K O9mAo(O^:RL0UEIr5|KWCԣB$3[jH7<׽hkY4.oVc|`;U:vT/P (.W^Ep=Jj7C3Ɠ}H 1kѸsO>_}b~xQ: T\?4h7B񖳪6W~vKL)#9HzOu`.o;~#w·\N*q,ʃKۯ[ۧs xQ׾Ivl~;Y+Y[v_kA8dpI{PAG؉Vt\WF:{j7o{w˧.ra޸X~!TTJ"}|Q(A+GE~o]\:+;]n4OP-mqOӵsWY\_jaI`r@{*^X*iJWlw$vTW+_j/5H!TFGZs}Oʳsʯӵ \zUEWir5 +Y3 mٿo=qW-Z6QEYQEQEQEQEQEQE|EPQEQExv6xg^[Sq\6xg^[SqNz}r("Hw+ gMu<4Yqj?{\A4h2VVR2NA @+(WL9F /_u_۪ۢ3|e6ykyc+.8qHḨxmmZmOڟ/ҧT=疶QW.n8ꨶb]֤/̲qnq _SHSQn,RB=.FHy>??jԽO.&W;QFI;Qiy--EH:9F2WcerɦxIۤ݉%$=ԓ 8ƥ_i:|wk]/fg1\EYTf!=n5k4 >>kcsktfUG*Q31ZEu;;Z[=>C2(P̧oߴlvFǪY[궧X Q`Zk2-*Uu*B~nGcj4̉y_Yc׹ %˓h|۸qI!\ X5[}3Dwgo٬1V^>ҼC{Mdx,3 S0y֥qt|?𖠒i b4B&.{* D61.{]qWl~"Bx=ʵ(((((((((((((((((((((F63}Jn+F63}Jn)=OW.QE6Xh%yr r=29Fȏ5E2(R(E 9 hڬ>X^LIql0\΢0XRhbEjm6"1I>9"4鵉a}B%[p:#t$~_M˟3z(]l̢cP*'!7A@Y3XTLQ 9u-}-n"%tSo@M>KY9gi_lM;an3պdETK*vbG= ܑ@>k^Oxݽ6ti7O'j(8j. e}8'wV`?CLT=,֪[h]ֺmnn"VI2rw09#'=Aiy--EH:9F2PyekZ76MtlPVm[Bk?$qؑRE4SxeI3!d`@e%XqA4]IugĒ,p*I%3oSEM}ky66(d''s2sް5^ømKc3q ^`-aOj=~q]B4U_hkFxG{hVWvGQjg+G'>95 sqoyZ#|B]θldSI9~F:s):qĿJ?ο:? lz ˼We\!t[YōL73no"@F01ӯ8gGNեJq[.{(:Ӣڥ/Tf6rޤ\xVNG_ =+mp`|K(^=x }CAܙ[0Bd^I}9x|2W-]:2x\jm]RۚnzubŨio{ 2HN2y,[ĉyc%u"SkZ&xz U֣-Q_1`ܜqRaj*ҵy(o w2+Q?>&AFJ uٽKU$o{V{^)jM ~nR4m0B;(I*kv)t%D8b>mÎ Q4-2HFU3қhzsCzX'ӿOzgEbfu{* Q65gVzMޡukDɍ?ɹWHc5N0éo,2_5¼Y1Kp0xQY藚u "\YxfXᴞFzU? W6>-mpw rr}+Ukv5J,0uת^[7egn[_16>ŭvԘ}π Cr'gi_+wIG+3H[Z׉|=}/j8,3~UJ/O{讗cR4.[|ԳcM#RK{KՒI @$` Pr; Kϩҵҳ.ݧKF@9?Y)>;7oCs4/jQi:,kvDʤO 灷 i Rj3Wy+Q`ԚMJ{Ejf[oXܭɨ'cъA5yM"\ުNcb.aFHGQ+ \igfIw1Բ?6b 9m2^Ě-Yj ͷRR$d:\ha\Rr]==M!8EJ]ގ7{%z7V{:tAwc}}1NĚDoWةFJ?0 qKU{/P9>Y_V"`os^]pwu#BI6ݒQ꺥[>3VMh SZ].gg}A=ǏgDlmLE6ieUc,+9Fq|WxUmၮ,3lHJ|̭و+=^%/ha[cRr'嚗C\Wv[^oO.ڐXU{)-+կm]OiwIoou*K1_U oX\;nKe`3Hei$g45a `#$U `G`KTSϵ}voއkIap'?} (ז6$!khm! sx;*+tPIO nB𪤱AWzz%=- #2`80@Ƙ/-d͖+c,,ʧv57Wio>nnoFsrhmiSm8^YD,66!/AijyсLc/FOnޒ>oaqH0yq>9# ]Kcը\Mr)*0݌QE]6]VٙU u۳^((õѷM/Lǽģ=2v?'wқ5ѷM/Lǽģ=2v?'wқu?Sc苔QE!Q@KmP?EJQ) ?7&1/S,$3JzsW,mLVh[qak1- i6g2-ºss?l5 [f\dM<]#RY72F m6Zm/0,3p8)4ZttzEX[d;q\`s=(U]b{5K"ܝL e$Iaq,ypG,M)!3xQV:eAcmHv0O, gt4ກ,mwDffb1#=h-~ Rq9cKy++0j"&"{xVԁ䀶L#Qy~q 0u41\$Ē"xC+ ڣ[+UBTLXcl!x٣.։A21ʀͅǪY[궧X Q`Zk2-*Uu*B~nkZ`J7ڔKs\ĒJtbpnߴ cѴSkiۙD(TO0C` nTׁSek?[C'mF3z>c@~2 MO,@,1]D8A ~h~y?gǗvێ1J: KMMsV@ʤ{{PT:ۤ"E#Py$b ZKm)",BbPh3 fA`q5'l:j6Krt2XƇ݅wz~k?f|Xo߻gy@ CHfRYS̊9bOE9'I`+hcJ]ǩgO@Q@Q@r~&8OqBa1]er~&8OqBa1I>D61.{]qWl~"Bx=ʵ(((4jW6y~nѿns=qqRM6mlQE!Q@Q@CglvggGSpđDTQtv)6} s\QE"B(( o3Ȇ82> V8OKE;wkQHAEPEPEPQ}}ɏ<7h߷9۞8h[ 6"慱92REv]QE!EW+_j/5H!TF몢idoNCv_ZU*os(dGSD3K$ycT}PpWmg=%ק yo#7(d`N񌛙pzʊѓMewҕz0:JR{;m;'m7}vczTxR> [Ngsg0?:?=_lUg 5ޏ~s5{m߉jZQOW/GePNZSH4R^Zۺ:wk|kq,s?7ja̱^πrF356_*Q>[sk@{Obs/Aլ^{mSOd("|wrGV-牵{k" [Ngsg0?:?=_lUg \Ӱ{z>%wߵ~'/MkokWGlm|<`j%QẸMJY7nKٷ&rGP3ӽ]?=_lUg 1nW]z3BݵC[_^ۏ&^Y.ktԯ%n#s=;U߳Qz# ӕb0\(z|Ꚏ ƉY&{q0:}{YtJ50Xg9#o~OW/GerO)pβmK~̽VyM>E[FrGX& #"ʷpug }T&JZƤ*)->w߳RGټm۶g\OW/\ω7'<8Y]ce6,sԓuR5y_5pp^NZ>]u_^1y|rrل7p}L)֭on68VҳD61.{]i8ME'-l켅,FU9 xQ׾Ivl~;Y+Y[v_kA8dpI{WeECmͯ}8::)mo{ØZׅ[WH =t8޹?Zkm75x#yܾ 9p:Cݭ/PǟwYi徶1Kzlw6:D0w( +q;wU뚔XLymbyEze~m; UMN_w9_U(|1yDЉ ڤ6Z>ou6K"}.U ;Ux䎝fe~m;tU5I)55kzմ>n"g'Bdb3Uq|j'>7y}3(dy_j&IFt/k:oew > wn’3:Q~ V7~q+u](OraeQQJ+xV{{|-G^_ 'ٳ2׭g2tfms}$u]8O#êΣ^Ѽ9j7o{w˧.ra޸X~!TUtQ(MF$W_c;]n4OP-mqOӵsWY\_jaI`r@{eER&z0(Nմ이S/]RMmI#o^f\d'Yb WHڶhF\ӰNEST]7-g?D//fgckpWJ>[ow((((((((袊(tmo =@q(n?Lݮ tmo =@q(n?Lݮ O"QHAEPTu{4.kYnXW;]G }hs>Eg+o1$g{W­%+o^FV 9=n2x}sEg-wҰdY&<e[ 9bM֒>DOZE-S._?sQ$-P'[jiioi|1o""y'֬oɨktcy Ci9^9(^Y౸7 4Po  2x˱!Ogyٮ UPߗrꛯ;tu9/"ү$ӢIkx^@h< >=jV,w[O'cc((%#b@9?%H.IzVB?+ص U"rC[>}5O"V`i%P"NNscNWImn7e\`zOq8ÉURh:m+O8kz~y_lݻf gX)%216mugyG-HlNH''jiioi|1o""y'֠^^uikNܖbQ?/ɨktcy Ci9^9+SSUү4d 0VR eZ[Z[ٓO4W$ӴoA<) EjPxOW73ڸH-THn ( ( Lq9ÇbLq9Çb|=]m cc]ʻ*~D61.{]kSuQEQ@TW7ZZs;l2;`('ښM!۲%<]m/s˧j6j#hacAČLjR7iURՂjlE-ھYq0OE[8J咳 *kRh`'sASEji_cFUZrGS9[SI-/QU>k<ߦ%S EjhTڍH÷rc 1;99%JnjZ>V\! ' I+Xn`m̂Dl# T^m hB ( ( *k}g#kQQY(49EJ(P8"iX({BM rvDVTzēvb/ENIx ka2 FTU*sċ)Y"Z+SY}uXߏq _6B!4wOc7dN1Ͼ2x_:/굿VFWv#*FAk&vf-4Š( ( (>((õѷM/Lǽģ=2v?'wқ5ѷM/Lǽģ=2v?'wқu?Sc苔QE!Q@Tֱ,)OCEZAvlb-VtmAlG8gh~#r]4Rյ4*N}~u0V0P 69 p3'hU-S._?sQ$-P'@EQuPԼ7v\y{إgqTky}Q?0Cg]Luu*A\amSZijܤlH=>'<Ve{jPN[hr `9?Y!4Yo/lⷆ,diL*bdU\dmPY}6n~/g1m;sgVlI)/ƀ*QL$-P'jk:Fj^W;i.syE8˕ܨKJH.4lIy#F.b!HͰcsߞk_Fz쯎e╻$wbsQN1\%(Z#|B]θldSI9~F:s+O)1\s8{+֕}U^]ܿ$:{8&FmCh0zu5z>D61.{]iR[.o._fyt=GGNէEGܿ=/kӿ\KɡM40=0Yjz*eQYDʬ% /Z4im1Sy`B';Tgr"y{k; uk2P] ͸ 䑻,Fco /kCڒk;3o#,@wxd.~nkGuk_~=_K9r{u[t-P;2ڛk2pG889-Ϳ\Z_5ޖ{ַ-IF2Iz]<Ŵ.V\;<{m]MHI'$wy!k~\?ֻaM@uTTKܣ+=忙)M=gY})ltq٬FK'fcX֋BJ/ `x:,bٕKwߨ#GUҴH4.{4 62p:)rk[oGVU,ҜbַM/IEekM.(( (<;]tP<{J3ۯO-kBw?)]tP<{J3ۯO-kBw?)S=_>ERQET֒Y $=*('sZHt;h卣q*|ǵi@wڝ򴙯%WdImm ݹ9 qO,%Ҽ9Ӳ4֖@섕,8ȭ(-KSKK{Hy =?c}MC\Ӥ[R7{M[Pva.SNfg$(fBMgi\\kWCGK"A "qqqQ@ZJ\ d$"'?j׭j(3Imn7e\`,4tΟs)]%`zӆF9Ԣ R!mupbDEOOR@?iP4ErsVmuy3y[I+TlF #Erkuc+59}Fh6!f`Y[yg-(((O)1\s8{+O)1\s8{)=п6=?a7Ch_UV7^QYQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQ@EQEۦp&zQz~o]Mpۦp&zQz~o]M:ǩ1E((((+z(WĝQ}(WvGAEyFjae-qqNRV`9z̑2IJ'h6ees i;UKH >ҳg m^;8b,jMrgo v %M]S=9ỷMt6M'%.l ;w|OHKK]>IWW&ޤ vLlR_*@_Ec*4KAUfUV!XIXr8ݞqWZ\v_%\miD,"+vߘ;:*+|U}~$Z'lo*,yF@VUr < Iܸj;C}?*j:Kpg{ez|/à.5Y475CK(:j2wgJj߳_GgmK_r{ w_z2GgmRu/QT|W|-n>Vne//{ w_z2r~&8OqBa1[n>VnI{ An0 TAmh}xRtenz0T%}ΧCh_UWwc]tZY8:2y-!Fr0֝r{m/SGݼQ-''4K>N5_y&!cy)1W#w\柳zG3譢ӻ;j+b%ѵ u;X[YA{q;u;~MN寔xgrۺUnJ<_;^Ŭnj{uu B)w\Ziw 85zŅώ.m&hfUUuں w ϩw^(ܼyNY8| ήOK/E+|/ln<H4߰o:ng{݁rR8! q,H5vh֦V9{nh&,Z)D,Rpd8ڐg|'ӎA,I" RA5`6y'{^Yc06Qm(<ࢊ(((((( (>((õѷM/Lǽģ=2v?'wқ5ѷM/Lǽģ=2v?'wқu?Sc苔QE!Q@Q@Q@gLzͼVH|vҴ(i6>[^>[ʲwT3I43bFiP]JӪ7sJ?&ԴF϶Hlom# ʘϚx+\ү4_$yVr|}ѕ x1Ί 3ze4\WY{ͷӨ?1Ce$Kwשj$ܫ(`Xmx+GP0w :DgXYaoꥁfjxڌ7S@Cdcr݀@$(eӼ9i>o/vw~_L{PEPEPEPEP\Zּ#&+L-(` F9\nysQZST.h~ڎ*sdеhK\YɌfPo q5 hC[)Xf F_qOEg.(( (<;]tP<{J3ۯO-kBw?)]tP<{J3ۯO-kBw?)S=_>ERQEQEQEziV[tJIJdԥ^[/.S0Kn'?ڬ%XR5LX#JggkQog@i+v6 Mp]#C}JxtLx 12< fT{=Fͯ/.lز0ـu* AyZ é3i|Fˆ$.Y(0I%MΟ=w->]Feg"76' @,e-cAKFEz%Hco0LbUr@*@?0kSXZ;/X: cz#=}o˩OꩩOked͆bY JZ>\p`ԠD|H HGiZU;Ci@*9TIY̙zsx$Tz_tF ehm6Qi3.ZM^ZE) a8 97Kmx%$Msva=_?y?W,O|kJ_kJ_W=vGkJ_kJ_Qz]9+ |CY]Xo tgwIA @I`nsv>95 sq&[g*?F5}2=wnd|ʛȄnFA;~GgNzc&Ǡ?vUGOM˯j?Fg$zt O=:w'֝ A;jF[;n# 2dwTTdAP^\%Dn;Iv5=Esmf̒/1 y6\eOb;4Ƀ8]-ҭ5GW5Tyf y*;3|Ik[&Zk;}^X䕮b"N1yl?ŖHe\wlӌrۏ yo]yV|n^+Tikm=bp4ӵv6Kmlm'|Hm//!kYHħ͎N*bR-<ĵt r7W ) w*wyy5Z|0U\923NŜd-nZ#p9ċMF+h-%@vqďk5,2]-2qWiwO/Kkqk g ̙ͭ*7$_Umw</o>mE9o5c$W[[dE\|062rs(Yh? !BdPNG|A H.ݛ9: oڟ$o/ ݎ,OTBrvMt^*u0'Qm]zzve=Xp 3ry~t "*_:F,Bކڦд+sn 39<}8vEK]Oe֖LESw9◻uߢ]oCJ).[|ZNW+Gnl$Q 2LsuYAMum̷91d^vu}iv2jH,0bfPCk\=ޝ a#s1j2­l}%oîe ࣪KoR᳷5ǎ!:X}DBXBF309:Sž#CF o-OHn Rr>MmYx~Oՙ,nܖgRň9q89&{mZ[j-ki(/$>%,A';N؁T9Z2KEn謹MiJ$/>V?g&/3V7w)ݕ8SvVz.&:v>$UI"{OJto_dn߳?/Qbx~;-2M$ڡ[X7F)WN(JƜ~a(Ҟyԩ/KzC%x/'XpT'|[X(cc*)F쐸}t:'K&/cXFse@$ߜ<'}sq%DX@*D@# cХ8iY;H~ѝjX5#NM'wCWMvSsqB9=Z%Y '<tN'in|w`)(袊(tmo =@q(n?Lݮ [KԚO~lcq(;9 t>SqNzD\)(((-k~bk ±)@v^$Xh \_0^˪Gs; X[R(&Y mFɂ-Bd`X;OE 9Yڦ4S%A@;~Nb, *+@KKZEZE,!(; 0H@<54SҼ5 I R{6(CG:E{"[qPJV!ع,3"/LZ{Gs9*pkBo5~fX4t;`e2BH\H㉯R][rimwsoekiGo!Wpz'a~ߢۛ[m M{|Xq"䧗#n!US[4g{ 5,IĐ IdRcrѷ z([JUL:'ٴ_K$dO50YV|֏5ksJԮ4~9 ;PHݦԼiPM##!s#PGj#3RiRKuy os4H? G$zt O5ziYӿ)?Ư[wm4sB$lN9^IeJDQP^\%Dn;Iv5)]؈\[iV險Jf洇!:X}DBXBF309:< DOS-?z4Y jz./&8/Yd6eFONO;ie>i\إ漌de^g)aj)oo?1 uz^[ \;ynl]߂t8eRTUTƙxymJF `GTpuZztJ޺ MۥמVm_ެ 0d~p8!R12*懪]iLk8(es(etst"%5g<%XEKE_Z+dwl4˃mkw%320'=u|dKt p숫&qNNqޞc)OK傫Ju4.Wc/ s\s0wtc޵WCiqϦ݋Kk8X.ʯ2+J3JmhM:K^EZI֯'W9%k%@9Ӂ wƗ>/֬fCy1BA'[A#olҞ U2RJ/[EpQ@Q@Q@Q@Q@Q@Q@QEQ@Q@mg=%ק!;Wmg=%קG4w^u~eA  hgqg ښ#,Ӵ'8U}SKl:kx&ūL4mD!ִeA  hm,*? kViukh;so<DE eA  hˤiPpl 0T**k:l:X7s.%iwvpkg_ƏBno<+=vsj%?.ͬLS|Apѝ9k{šUGeE`-O 1zl!cQmG4v] xeXCld!Cbs#c6 *yt߱IH JVm1\2u{_ƏBùȺQ_-O,*#y~[Fdb"NI,3<7]_i8FL NT),NӓmG4}?9xVm&+o:~p UC1!F̿*I+oF4=?M|߱Gomۿb2qtXm,*?_ƀ&m,*?_ƀ$tI#hUt`C+ b+&O -{vDJ ^oLp:Z_mG4}?֔TIjXoQP?/XTYW'c|.9?=}?/)DѸpW<:_Ɠ|=]m cc]ʻ*~D61.{]kSuQEQ@Esmf̒/1 y6\eOb;i 6[nZ Y"sݲKN3Ny̶^;mfK+w%Աb>evIޢxg[6V},kZ{ZVt#g|wqc';"#2Ŭ}V{Mgiʜ8CE%e|RrY迫s>[E&yp.n6dN$UX$ux#5,fUa 3!Nz[֏k#+]9gKoY%aq$,N}li֟]3[T JEDjzSR/.9m8嵄3vwf IfLIb_qZ67w]}ͻ7su:*4ԞUL]j93__gW?<7?|Ͼ}m>.e[*Ngx3ܒq^Em }Dܥ~~v:)u7~yno蝴9 yo]yV|nZ1 XvE*0ݗ8r8:V/U~mK9匭(E(`((((((( (>((KYn෋tjUxq/$s~Oݭ. VYBٹa9ey\աIn%1G};;c1IsQ·*-k;pR)-]/Pg> :cA/P;Ok[Qk]&ci<-!7 CS>*s@cL=?Tς3kFdwҙZf9$- 3Qk]>*s@cL=?Tς3kF[ZNffFIV3giױZ| u^5 ߏhooTZ_v4{7& 2OA/P;Oh>*s@cL=?oVEuo3G+{~?ֺӷٿ_7ђ|U z_{#AV3giױk·*-k;?[:ɿ.Pg> :cA/P;Ok[Qk] ߏhoMAtdj9^1&v{|U z_{#ZZNfVEuo3Gοo $Tς3kFPg> :cooTZ_v4·*-k;=u]'Z| u^4j9^1&v{ַ+{~?ֺӷQk]>*s@cL=?Tς3kF[ZNffFIV3giױZ| u^5 ߏhooTZ_v4{7& 2OA/P;Oh>*s@cL=?oVEuo3G+{~?ֺӷٿ_7ђ|U z_{#AV3giױk{tx!$Z zI ߏi7& 2OA/P;Oj櫭kx~NOYe > 9|WK ߏhooTZ_v4mDWl~"Bx=ʱ9 ZAѹ7KsqmF0ڶiͦջ%$( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (>(( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (>(( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (>(mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/tutorialFunctions.py0000644000175000017500000000124510504574206026350 0ustar debiandebiandef readSurface( name ): """Read the files 'name'.vertices and 'name'.triangles and returns lists of 6-floats for vertices x,y,z,nx,ny,nz and a list of 3-ints for triangles""" import string f = open( name+'.vertices' ) vdata = f.readlines() f.close() vdata = map( string.split, vdata ) vdata = map( lambda x: (float(x[0]), float(x[1]), float(x[2]), float(x[3]), float(x[4]), float(x[5])), vdata ) f = open( name+'.triangles' ) tdata = f.readlines() f.close() tdata = map( string.split, tdata ) tdata = map( lambda x: (int(x[0]), int(x[1]), int(x[2])), tdata ) return vdata, tdata mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/KeyConcepts.html0000644000175000017500000004417510504574206025370 0ustar debiandebian KeyConcepts

Keys Concepts from the DejaVu Package:

INDEX: This document reviews a few of the basic concepts of the DejaVu package.

1 - The Viewer Class

The Viewer-object is probably the most "sophisticated" object in DejaVu. In fact it is a fully functional visualization application providing control over a  fair number of rendering parameters such as, depth cueing, rendering modes (points, lines, polygons), shading modes (flat, gouraud), multiple light sources, arbitrary clipping planes etc, geometris to visualize can be handed to a viewer object to be displayed and transformed. The Viewer-object also has default mouse bindings for the trackball object which allow the user not only to rotate, translate, or scale the scene, or individual geometries, but also to rotate and translate the camera position (i.e. the viewer's position), the positions of the light sources, or the positions of the clipping planes. The "mouse binding buttons" in the GUI  bind the mouse to the current object, camera, or light actually transformed when mouse motion generates 3D transformations.
DejaVu was built around the idea that one should be able to instantiate a viewer and hand it objects that would actually know how to render themselves. All geometry classes included in DejaVu (polygon, polylines, spheres, labels etc...) inherit from the Geom base class and implement their own displayFunction method that gets called by the Viewer each time the object has to be drawn. This means that anyone can create objects that suitable to be passed to a Viewer instance (as long as they inherit from the Geom class).
Being heavily influenced by the AVS (Advanced Visualization System) architecture (as well as by my numerous previous viewing programs) I decided that geometries inside a Viewer would build a tree-like structure in which 3D transformations (rotation, translation, scale) are inherited by children objects. I also played with the idea of inheritance of rendering properties, even though that is only partially implemented.

2 - Current object, camera, light, clipping plane:

As people started to use the Viewer (initially only made of a Camera), they quickly requested a GUI that would let them modify properties of the objects in the Viewer at the click of a button. This was done in a quick and dirty way (creating all kinds of problems!). Anyway, since the GUI allows modifications of the properties of the geometries, cameras, light sources and clipping planes, the Viewer has to have a  current-object, current-camera, current-light, and current clipping-plane which will undergo the changes initialed using the GUI. Pointers to the current items (object, camera, clipping plane and light) are available as members of the viewer object.

Current object:

The current-object can be selected in the GUI by right-clicking on its name in the object listbox. Another way to select an geometry (i.e. an object) is to right click on its geometry. The name of the current object is highlighted in the GUI. The viewer instance also has a member called currentObject pointing to that object. This handle can be used to set the current-object programmatically.  To select the root object, click on the background.

Current camera:

This concept is only meaningful when multiple cameras are used, else the default camera is always the current one. The current-camera is the one that has a red outline. To select a camera to be the current one, right-click on its background. NOTE: right-clicking on the background of the current camera means something different: it means make the root object the current object.
 

Current clipping plane:

The Viewer supports arbitrary clipping planes. Their number depends on your OpenGL implementation.  Clipping planes are activated on a per-object basis. They can be inherited by children, i.e. turning on the first clipping plane while Object A is the current object will activate this clipping plane for Object A only.  The current clipping plane can be selected either using the clipping plane property panel in the GUI or by right-clicking on the geometry representing a clipping plane in a  camera (if it is visible). The current clipping plane can be determined by looking at the clipping plane property panel or by examining the Viewer's member called currentClip that points to that clipping plane.
 

Current light:

An instance of a viewer contains a light-model object that provides an interface to the OpenGL Lighting Model.  It also maintains a list of independent light source objects. Currently only directional light-sources are supported.  The current-light can be selected either using the light property panel in the GUI or by right-clicking on the geometry representing a light source (if it is visible). The current light can be determined by looking at the light property panel or by examining the Viewer's member called currentLight that points to that light source object.

3 - Transformations, Inheritance and Root Object:

As I said before, the geometries are organized in a tree-like structure. There is a special object called the Root Object which is always present, cannot be deleted and is the parent of all other geometries in the viewer. Every node in that tree (i.e. every geometry) stores its own transformations (i.e. rotation, translation, scale, pivot point). It is important to understand that the transformations assigned to a given node are applied to all the children of that node. This is called the transformation inheritance. Since every geometry in the scene has to be a descendant of the 'root' object, root becomes naturally a place holder for the "world's transformation". In other words, applying a rotation to the root object is the same as rotating the whole scene.
By default, mouse click-and-drag actions will generate 3D transformations (see Mouse Default Bindings ). These transformations are always applied to the current object (that is if the trackball is currently bound to transform geometries see "mouse binding buttons"). By selecting another object than root you can alter this object's transformation. When doing this, sibling nodes of the currently selected one are NOT transformed. Finally, right below the object list box you can see a group of three buttons called reset, normalize and center. These buttons always apply to the current object and have the following functions:

Reset:

This button resets the transformation of the current object. Its rotation becomes identity, its translation the vector (0.,0.,0.) and its scale the vector (1.,1.,1.). Nothing changes for parent nodes of children, they all keep their own transformations untouched.

Normalize:

I would advise using this only on the root object. However, applied to another currentObject, this is what should happen. This function translates and scales the bounding box of the geometries in the sub tree rooted at the current object in such a way that the bounding box roughly fills the Camera. When applied to root, this gives you a nice view of the whole scene.  When applied to another object in the scene, its bounding box should fill the camera.

Center:

This button sets the center of rotation of the current object to the center of gravity of all the vertices found in that geometry and all its children. For instance, when applied to the root it sets the center of rotation of the "world" to be the center of gravity of the scene.

4 - Generating Transformations with the Mouse

Mouse default bindings
Middle-button rotation
Right-button XY-translation
Shift + Middle-button scale
Shift + Right-button Z-translation

Because of the perspective, the Z-translation looks like a scaling operation, but it is not. You can tell
the difference by doing a Z-translation away from you. You will see the object fade in the fog ...!

You can set the rotation center of the current object by picking on any vertex in the scene while
holding down the Shift key.
 
 

Shift + Left-button set rotation center to picked vertex

5 - GUI overview:


 First of all the GUI shown here is optional. A Viewer can be instantiated without a GUI and its cameras can actually even be embedded inside other Tk widgets. The Default GUI is essentially separated in 3 parts: the mouse binding buttons at he top, the object list box in the center and the property panels at the bottom.

    Mouse Binding Buttons:

    The GUI presents a row of buttons under Transform which allow the user to direct transformations to the current Object, the current Camera, the current Clipping plane, the current Light or the current Texture. Normally  "Object" is selected (I call transformation a rotation, translation or scale operation). This means that the callback functions of the camera's trackball are bound to the functions transforming the current object's position. Some of these functions can also be achieved by clicking actions inside Cameras.
     

    Object List Box:

    This widget shows the tree-like structure of geometries present in a Viewer. Children are indented using the a number of '~' symbols showing their distance to the root object. The '~' symbol is not part of the object's name. Names have to be unique and if a same name is given to two different geometries, the Viewer will concatenate a '.x' where x is an integer to the object name to make the name unique.
    When an object is added to a Viewer its parent can be specified. If omitted, 'root' is assumed to be the parent.

    Property panels:

    There is a property panel for the current object, camera as well as for clipping planes and light sources. Only one of these panels is visible at a time. The one shown is selected using the buttons in the "Properties Panel Menu" box.

    Object property panel

    The drawing mode menu for front-facing polygons lets you choose inherit, in which case the polygons are drawn in the same mode as their parent, or as points, lines or with a filled representation.  There may also be an outline mode which appears only if your OpenGL provides the OffsetPolygon extension.

    The drawing mode menu for back-facing polygons adds the possibility of the back polygons being represented with the same mode selected for the front.

    The shading mode menu selections are for the current object to be shaded with an inherited shading mode, with flat shading which shades the entire polygon with one color, with smooth shading which uses gourot shading or not at all.

     

    The culling mode menu selections are to select which polygons to be culled in the same mode as in the current object's parent, to do no culling, to cull the back-facing polygons, to cull the front-facing polygons or to cull all of them (which makes the object disappear!)

    Camera property panel

    (1) The bounding box of the current object by default is not shown.  You can use this menu to show the bounding box alone or with the current object.  This bounding box has the special property that it remains orthogonal to the axes of the viewer even if the object it bounds is rotated.  If the current object is root, the bounding box encompasses all of the objects in the scene.
    (2) In auto spin mode the object continues its motion after the mouse button has been released.  This motion continues until the next mouse button click.
    (3) Scene antialiasing uses the standard OpenGl scene jittering to achieve antialiasing.  You can select how much jittering is done from these values: 0, 2, 3, 4, 8, 15, 24 and 66.
    (4) This displays the color editor which allows you to modify the background color of the current camera.
    (5) The line represents the z-axis with the Viewer at the left and infinity at the right. The triangles may be dragged any where in this range. The left blue triangle on the top of the line sets the position of the near clipping plane while the top right blue triangle sets the position of the far clipping plane.  By changing the positions of these two triangles, you can display selected sections along the z-axis.  The bottom left triangle represents the plane along the z-axis where fog starts and the bottom right triangle the plane for 100% fog.  Linear fog is implemented between these two.
     

    Clipping plane property panel


    (1) The number of lights  depends on your OpenGL implementation.
    (2)  The on button lets the user turn on or off the current clipping plane on a per object basis.  If it is on, the current plane will clip the current object, hiding one side.  The side button lets you toggle which side of the current object, as divided by the current clipping plane, is hidden.  The inh button sets whether the children of the current object will inherit the type of clipping performed by the current clipping plane.  The disp button lets you toggle whether the current clipping plane is displayed in the scene.  The radiobuttons under current let you select the current clipping plane.
     

    Light property panel


     

    (1) The default OpenGL Lighting Model (see OpenGL Programming Guide ,M. Woo, J. Neider and T. Davis, Reading, MA: Addison-Wesley Developers Press,  1997. pages 193-195) is based on three concepts: global ambient light, whether the viewpoint position is local to the scene or infinite distance away and whether lighting calculations should be done differently for front and back faces of objects.  The default ambient light can be changed with the color editor. The location of the viewpoint affects how the highlights on objects are calculated.  The Viewer uses the infinite distance viewpoint by default  but this can be changed to use a local viewer. The Viewer uses front face lighting calculations as the default.  It is slower to calculate lighting for both sides of the polygons, but this may be useful in special cases.
    (2) These buttons allow the selection of the current light.  Currently only directional light sources are supported.  The bottom three buttons always apply to the currently selected light. The Light On button toggles the light on and off.  Show Lights button toggles whether a line is drawn in the Camera showing the direction of the current light. Edit Light Color displays a color editor which can be used to change the color of the current light.

mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/cullingMenu.jpg0000644000175000017500000001201110504574206025217 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222w" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?iRyd @GS}ekmQ{52Qy o'#'1=4[g]Gou _Ѐ 幂9IaCԌPe+88ƣiut0wO69J*+^ aӼ Ȫ۹U}*O 8U?.?on~Il<|0>]o?`k|`lO>C|^NNX`Ph]_tG-K $MdGPGz4r;{ϰmͭHٝ`齷|&<s;4ڌW]9wLcDF*H݂O Bz*kBz(к EZк ?.:?ª@.:? P Bz*kBz(к EZк +?YRb#H# WVB@*s`aX>+Eٱ[/$95u xeu[{OX)X^ OS[P[m6s5B(2/@; BɭxM oɜ\gA8ߜH$֍QEQEQEQEQEQEW)_q-uux\@2=CN}.Q#头 8p+|꺞7݈zRy9=zghdt$05#[eD|=X4T1)SqNf| e,h'n@X"MٟRԬn-*N.PtpĀ Dk` IaJ77'ʹѯՔoQ\M)r4O :y0,|)8`XxCxLL#?tt,H/# Q^[[_F veCA`v@<Vie[Nou gG'e ʉ$8b}}3WM'5\K}K+L3+ R 1T [_מc6tIG˿kd#brgsTf>Jɵ ^#g9[[h-6,/"HJ 6hX_Ũ@F42J?3қ6ou.mվB??ΒIo嶌 '`{kH|nvbc`X̚|=5bu+ۈ)o.wQ݆p{wt4ҍ]s](GqFmQݷ.'i`K+tyikIm2-ϚR\3!U8ݜgoKErf::bYKJKDacʶ7:v7xV+̬EʫmGwuP? *t'z]H%ZVSb VPEPEPEPEPEP\)_q-t֣3$!X_#g5 u%Oq=w[>BP#7''a67񤩜,,# M~]+ÚMii, Rʅ8#.&Pcgy 1&wʪvxSMÚ:&ao}un8!w8'N(=u_C=vVA)W8,*>r1UF*du9++iklk@p鸉3p]xjNX.|?_%&Ucps H-U$k5̓¯dc#`;`s|_uKm [S,Qąm^Z7zƹyIqlgiՆ<>r1WJ/,5M*i]|q<۸I9t+\ |6֖oSD3 #bʱmO{PSu{{\[PȎT!JV_f6;_]AGSǪ??]D.7 YQ!S(9%'nwCujW]Zt!?i;F[Uf':ŷx'PԮ]NK]IR#dCādB7de Z>ӮMNXʱ I#<[cUd>Rgiz5SN߬i[y7r&vLKzVՒ}5-.Vki 9Iɐlc8njښ\7m)ܓCw*1Ivdpk"5]7Y:]\ Hqxc #rZn r$2Jy;I Lg&*z军go\\I%ͳMPYO9=U][\\ &вGz ,"X *?ikyiW۳6l VĬ8V6Goi4Sh|w]Ar3Ċ%HdoX*avj[xaqEr]qWv+ŽcEܯ!wvw7񶒖pFrO:I#vdvOWE׮7J{x7Aq} ʃz+9.3 ¯W'hW>6iv-Up309qOˏkSƿm?Zs4LQ.w 3ln`eW}QE7?x+Q _O:@{=4TT gq3a2dDJTr9˖N=Ms3!iz[t¡rl9l 7ɖnc}+u+OO^Xb]W=-[ui߽{VzÞ95@w%\88'cHԝezԝez)1 KlFp(HZ 2n+E9@$ XQ3 FZ6p *)EDj3?()Ҕ@C[H|)N ʨ^UrzgIJ)akqjzC#ceB8Nչ\D+Wk"gtψ&|ip,{O@?}u,{O@?}ucn+iJӽ;9J4me{\㥵Yx}~ \t?. g Ua̬Va\Pcz&cUoT9p  ď<}g׬Nf9FėĬ?Vϩ;7_;7_=KiaW?[f8RqxV_TzWZVkJzY2+j)>Q3??d]n)ت䬦c6ǘ|M,{O@?}u,{O@?}ue+JQiZS,ow\]OFxA=\<ϟY>Ǻ:񻽾)RwioRwio6US]ڃJsh{~ݨ,~7oW{ T1\ f|xc[[$tܴ<׬ς%DOlƕ/;7_;7_*LQQ?2e8wiJQ{֞SNl "L<^u4XqWEK. `2q^;7_;7_ &XKo}h(ԧ_ssJwPs)N1H>f'壩\bX.:Pm.~\,Ny)RwioRwio5 ~[߿nޫ3߿~Pw+am[&>p%1Lu}Pr{sfQϢXΔϩ;7_;7_ HR8RJIiߵk۽m~ų4o\]xWUJh+9IrDr'L`yxÍȝox.N&}qW'=\DP,{O@?}u,{O@?}uҝ(SDkߵt{Af;zpnJ!Z~Pf#3#3\[$tܴ<׬ς%DOlƕ/;7_;7_*LQQ?2e+E)zǗVl "0SJyC޽~+.T2Z\L`')?۪:,@l5O>}JG_#?N=MsN=Msɖ7Z 5u)GWҝ(SǬs$2<|Z'߫Jw gղJ-:Vc<G)RwioRwio5 ~ҵ{Vf~ǫ ve~J:큂bl{.~ B6-6}-ʞKTˆzGЀڶLG3bS35;!HDQTOHL 'zY~~&'zY~~&樂46zune)_'.Z֞׵y01Uƙrl+[oǿJ׿{|D&<xG8)i/g!x눑>'ύ"_RwioRwio?y2erd,uե)J|۞]OշIl{eWk^:Þ9ڬV!܄:WW_h:c=]&4}Iޖ_nx}Iޖ_nx*9Jޔ%Vo*yȵY):̶]u~Ŵzq$x(~\G:*SG˞?HԝezԝezRRkޕzWyRPz;J`&Km~+Z~>VHb9f"?u@[] a$^>sDդ?N=MsN=Msǽ1Q.wnؘ= f`c"^~^ "|_n;7_;7_zZq$u+}ݫucT,ˊeԺZҿ!&&uq&% f#31DIDG dnXXAh~N\ ' G.t8&nB[C5Qz| KEJnu*sَtm,ʚ`H1 "JnHj0T{8an/1]T£;Ys}ܰD4b+%-3~s%n;37I.9v\/unl+P_T!$Pa!T2f{rШ JbdG8ٸqy;Y~R\ޯsmR0w cT3ǟX5M5QGW0k {;unwU-F}AO@GU^[U4L//n95]PAQ/||f2y|rVo d;-+YLDrg[\jSI$`F cDqvݢI fQ9eA"ڲEؿO!s]%:Gyv}Q`Ef/+^/AURA6;]k4{msClP z|^6[nJ⡄%pʒ`ըצy1et}K.} ~_fzSXM6_ MrCK>_᨝^mkf|U67 .hRkUSJ_5j^Sd<1of&hتv򦍣||̔pSd_- tzV2}ϳ]B>6[nJ⡄%pʒ`ըצ},Śc-~hDQlɨ)[d(Hܺg% gyx i2 @IIjdukB .yX9"}̎e*rTWiL~igŧҟ;_l~/a믔=SGUW?/jpx(/S 7&Crq]NZbk,TE3^l6>ԼHSxl"f1dom*h1ϏS G^E=3fW2tp{Qm7vW^й EGғV8,_7 E*?χג 'JoIl $]#|/̎Zb HD,@ǚdYW"2;ky9%?>"4֥h>HP;xl,f/tm> T)h8zfX?3U*Ý{fc=yxgَf?֭@a P}8ZI}4ryc7 \sWw=#>y.ڴI^\}XY[A%߆.֋^.O+Jud`~eR[rn4k-k ԕFD ##Vs]?5GyydK Bg/nJшlZJj_UPU--[_z=tq:BzƸw&IFbqX26ᆑ 犏@Z'JK`L}=;SySn]%`zf=ȑ`ꎟyǞf|qM 1bd syk㖌b1 EFTYhYV<X '^O=+L,TzTyTt~ jv[V8;O*ulM)3O1<[9(9xpX;-@b88YW:3#8njx.hݢb3ܸ:k4C"# !֑W|jU_5.t-轅~ƙd;9d݉!3חRb:6kܵUPz--K2TZ5L@"Bb"8&"~Q1È2Y 7G%N劷Ƀq %0f-.(yΫ_~fhZIuerl bep.F"'q! 66!}hb 7D~`"5mK9Ϋ2c2̉#Ÿ ]?5z\iΐ'n7s]ŒQV.1_S:$`Vc|dWDIinpnxw_RiSE|L:V=!O_\<|Zr+82a'6%'˔Av (_7[[[~zv|||{r$N]4eY(>uQre1u;-p8zTX.ERw!H.]F2g9~~R9};fYzdn=_w9[]._i*8ٌHq(8jYl:(^NۮUY<{0|q?~~RFZ-Y#Lu{^51k7)mn5zQ UuUz*?Fs\w7uW;߿۷T!JXc#">_?5BF/ߴwBmeװDD2E1O}j*re͓8N^ݾX+$sFKf"&|u7%39\n `?D,)bqڞMrScbV XIIDQfB*Y/V`M΃)3,ș2<)~W֔ B Z2{w5y%hڸۆFkPΉzr+82a'6%'˔Av PL:\W}=+_}SҟjWۿ#`v*]J|nw{ݹ;?h1Fs4XVN>- .Sw9C1_ sgǝ~x+,JҔJR6Ɠn.S؇;=09Ri3TYЋKٸ#7,8sG/y%L{~~9sPx xb|OG ~O!qlѶ0P6jhD\O|jK% Qv E{$좆COAgF>] _A/AVcLf2kZ[}Y^S7?Nq{v’)+`&~|DsG)ڛ+o\+6O|a<ƩtZkZiZ[װ5n+Z麷Wkν5`A{:0e\rr'îr8˻MV]eWňv\QUzW$p&Mi+Z•{vicM:̘Q0FD313~:ܻ1]U2BM5kԢX0B`>||ub]K> dn:}k.h~N7I֓GI߭eO9ֲiM XRr?'Y>?5EVʟl6wkA[FrEA5#BRr7&cňe"F1 |ln *_6 &D1pNLTI2BɳT*Cc F9jvΰṚLP^DfP,C5}ߣ˂?Ò`$f&'LO1?í#R0%E k(3Tƨ?I&mJ9W!Q¬FZ5ul !Р@F#)Q p@Fʰ,CIM:{lt%g% u6M(u>>w{G%X} 0Dt0,>&cw$pa=#/χ>WXѳhi>} V]~nO}oǬGL3^0[M&g{Ms69mHuc[6:<ۛ-õ0Mqyer[pK _ymjF|"F/$0c[\9\{5|7k{'ƚFm9:[IZt&#[Ic8z #I0B=F !34Z𤡬vtet~ڻV| IQ1ߏYr`zGp{KI[MY>f}Jo_IPcC#EZr$ B| MHʐJ$R w-ms.Yr"`EʮD9 U'*~DUʑzTRflUȝV+3Ly͏}l%KVi|5~熘9\_Ԓ+]yBMhJM /Oi(b%s=M&qM n >OrL/Ӈ>4gÙVVc;3&ժG@+ZZԸILj̓%.i߇iii'_]>ӟ]^‡-oh==QvR읰e;׷zּm}4s>=]:l]jإrRJJRO WÍ5}9M9O&%9Vi#dB$o()hYW`Ε##ܟeL! 5/k6*(]5ݒGrqhZQD@&FkF`Is$n:H,p0vg!Ss/ZVp8 !d{⑓(R0%1%1N{ 9φ/tb6@ܸ)Ф9vޱ`\rPJTj,|TY-d@JpF](9"bu'ДRFY7Jc&2[U?2D'm0O<[땆$L݂&ÎN ,6 a$22Y]rP4TЮ ypG1~_.65Iyl'#*Bf켮=It/i<ȷuwnݫڽJ^=߿۷漺Rf:vlʘfȇ'TdD8>>m;h{m{;XCrۃ rV(DwNNbmOC$_I%5>9Ql y6f&C\D]x G{55cfL}pe%> s% Of}ػvS[$T+Òn+e>YZʊѰ+|uL_c|lr4HR1":R"UXtbY@,`" =~u#Qmȫ-W֟PWO"S+1^R42= 6[汘]YĘ\M*XDqvsLJ%aMbOvJkJֵ c o AW31G<7enL(QU*֮!çDm[[U&XdKD,JLJwSnM-]3jT"9+$ќ rk?zQWSҲ9fHc4>D>XF? &e,kM HNi*n| KdTqjKdQ`xHQxyDDX@]%=eS/_ |lΛg)NZ5jv}wM=IḷR7WUXU/$-%4%+]O5\s~ھ F{5˘lO_ɩ+ U\VY+p,iÍ c8bf"k1I,1$T9]@\ GSWlgtػl4ap=z:oXSѭL _*8KԻ۩Z}|~+•}ե{{Wnk;$G:h% `H ~}*lh}!3\QiͧV5^ xaAY+ԕ̳dYr61nIN9l!f *VBH^Hn THg uq @|B35wChVHu2Y Ԯ[W%3ף[62VCXWu+6ز- dIt뾉.ڐe7µ=-{}U.Z~?9>$щ hUk甩LiO8P~6|ZGڼKg"LL5rG ߀ }pu 'K^ wm ,,omm&ǐ#k·:Fbn&˜M0z%P#,$FԷK%qI4#x1]ԑcn*j8LFpL4ys[[:}ưr5FQ9row[ 5 E8 6;1f]o sV03Jn(D\"%a  Ǐ\ & rLؚqbuShXa\KNUޫPz@,2yŚPJ_Z]6 Vz3q|)ִpzŠ>ȷ 2Š$ E$,`DGJ'>uRi>2Ug51hdHwfFzdAR2gq1&E/qQS&^ ;{Ioctm^V]${4D`.z.D-Hע'f^Fw@n#ፊr93`]Xsc!fݣhY-ŭpr)1Z`g=Y͑@ՐC'#S:ϼe,hzQ`t̙!h~k=- Lp4 jk#F$ Դ-)*]yzgcuÒ:6:yRfy~N{">>QxpA1jge6B-Z6ЄZΚ#"m~ֺ&INTV3ײSJ{3& '/N|_GSTWm|+_\?;8؇&AOׯCۆZ^{8 [/ f)5 b3 ͗)mk! φc\())p1Jc>O^Ru&o8??GG3\ަlO 2b~;?SVk췴G-dj+؏ưuЁ=D&*'1FyAl6핾B쇰k|HᲉdOp`[~׶{xLzl7$b'KCaHCyu) H2Qި+^d^BP7:?K]:{|bw]wBMUv8b/YCs׌KzY;l$_Va|.}PRѰ[mm60s!b`aQY%*h{ak9\UƐC\,6m!ZzH\r o9f_k7sTߙҕHK ZNHdc*߰ꗓj- @o.(r5HS2%Hvn2i Pm%\'<:ͶSBLi}H5 1Lhwa5boB] DWFP=u r$:ʣJ Tݵ@wF,'U+Ż-bHg Z}9K:D]^;i%)S`* hdNBٳkcHLTtVIyi2{Gn|jYK(戆AOMM&t؍rCEnDR1b3so7Z@mvʪM=U#LR:lLqȱJ'KI4'J13ƥ FMcꮿ(; 8k=(G#7 'Yc# zw>x~Gܾ>%=G[F7>B2PǺu];22q#X`!@4 ZϷ[D. Tһ] ٿ^w}S{S67Gv:2ܝmٸI{[Zř#04n:;}zU\^hzmP,j?7K˴һ uׁkw"MȾl&Hڝ 81  XlA3eu3JLseXye rˑfDLr ˋJyF1~l灷]7Ű: #uNz5rhA'})tݭDM|Mx$Mz;5sMOaM>dM\LqbeogxCJ:$/ w5wro3<e֠ԡ%m "rM1M^i,ÝKM7L'M8gQb-c+ZU -IV>dxz6*b~8XTV<3I}`÷|>oo="|5ڈ1a2[k|@0\2g̤ ZJp141H VekvCJLUo_ɼiÇhÇhÇhUӖ1ygx` 㲖[^7oƔ{v;|>oNsLw?7QFKrYuԹvWm}ӵ{ҽW~:j PT@T+,%P2XP2ۂff[~ܿºl%h,\6kJGh!QEpV"\dʞո)_^wYR\O0lCdH@3=\uG0Q=× ][pAz1ֻIea20d e\^}u0,hf,Ǚ3AYpy҃8ƛ#tdx3_z2 M|ntu'7&Io$ Q`CVY) N:k 8@U·;xɅeRVw~s>!?zI2XTuɌԡa`bE*=NbN;Z)6lRlaM RsI,SdͱmlݵcZ-ޑnLt>ed} 0>y,OEuhw(lм30f_ܩ!߾CUCBl}EzT؆'rOfɆOvZP*>PBi/AA)fH-rc̫7G9"_/ ^1$(iZɩc1M'"G\0!pwgB(O8Jxwۿ.v2j˅安&A  8 %v@Egs'1ψySu|L`C5sRN~ d<魘 uȎh5/{E⛄ǃ1c,.Q!v*9%zǁ4>긩Nי;~k{fM 2#z\cADٮ Lc:_w_÷Җ!iS!6?JZz$xuodjedB;XmJG>Y5[mOh`OU:a2˕ٷo4%-+Ԣ$PfTժ2E(#~$0P-![ƒ:aBAtDgFRƞ{k<2գH>;ώZAїU ő8HY8XeJXEs;`^1 {㎩LpSDlz/WNU6j[λ;Jg FT,%juCŮE1kBG8!@$Z^h=[%Tp °IKē0(||jD .I-lr͢m6Ha\aBsu̬‹ޞ>w+Rm6*#{ʚ0F, )^Z7kq뼊f*E\oQaݥ`cKZ&҇ ,VB/@%tnmyK 9BYW09ol.)z PFg̻&%SJ5e=J=n xa(A"FdmcK%TFRkUf)fTY)b{]=_xZU&`D${kM>==Oon{d]bkՏVwc_8֦)Kw@#َt18![attdPxSk Z׉&K:EUWo[J]/; $d7`EMH^UU%CjL X׋Dfe`lw8X,#D@DIRMNU5j6;6ZH+=Zɗ[VjG208K2E An49pr}\fU3,iS1:mȏv׭[kqi/ZlmzZ'A4memqn9P+. YjwN?~?w"d zq\ üXPbш~Uwu#r +VJr }S}ivH+{<&CU8bC2rL$I.,.4|=xR@,#Ȅ*+qurK'Qel%_|yXrI`Kr([ k4_;3kY͏q!mr+_´ZO9SB˫ߝ#Xà% 8OZVї)}LŃgqIH^TVRY(ǗD+Ǎ XRϴr?'Y_Z˩gÓHdZ^5p\[4M2e۩αϾ+OO^Xr%W=-1ҟ?jVi^[G=t-)lցhw9FanJD- ݃5QU|ڣhW[Jc.tKd29/M Bfr >W^g>|dM~0*TB/*_Ȳrޏ]1O2Ԍ\5y|f; EHXctAVRϩ])Jֵǥ;S宻Hkޔqi]{LBwS$5 ֊lNݬORt)ެUgK^ӷ|zҽ\z#]oz|U){F:Rtsk)ֺ:EՍ-߇y85ٰ7"wm -R \[WQ=lMe6d^\ DDH<ω~qlT6fNS)sN1lr\0Yj:GQN4t ܒL?3Jm?ֶ(ZbޒP-^y VwUz7:b| ;um]Rjz͵D>)ՔE^_MGI%9 GWkF_ܥJӿN@ZLP,#LD֔JWƔ?'0jۈbm|f5c揭n>Msp⪫8hi54>Nj-=&?# 1zEfnd$NBz:FY+b0ȠGs~^*pb54q3s-?oMUhwNyDDIg5/@G(T*8q1ٕؒxZ@Uwn? W{~_)pսS̈́L3nc6o3d¯L΃) rș:\88}#URA-wl-f/MǙܕP T)}zf8?1V4b뜶6W [n8SQfW,z*o6Fck?^JjR}ԥ)o+ZW}??E޴~>>~´y|=#2 fhَ7l 6:;ӄ򈨴bi0jky>RucmpפVwMdv>_ym&OM1HP^"x>Ígۢ>w&lq\1M1'稇'~gV[\M_Xo}$񧏅kUحе<{w?YM34X ƨvuԺmqIEŵxE- TIz |מXBe\؍#.Bu-wl"f/]ǙuNXѴc}7%FzftHd3VD VPp=@ɑ\OP2SϞ~zlnY[UQ¤ƂJ>q|F8ZBd0;!R2B߉&՗%r(i\"RpuFx3U0ZW'~ ޾+ӣkaߛ->W'~<'On5ovDAk_#tkҕ*}R>z*#er_lW:MWk%%^*b#kzbd~_~Fl뙯Rc䶝[xn_kuԌÿj1E||{|?{dZ5ۚ3>q>*ݷfh:آX{6躩}P1mw8KU^e$/RLyi"yU BX6PK^RucepפVwdv>OwolȁEv-a(.cÝ[l[)dK1kZS1MiѺkʟf0_Gu٣6xxҕNW^߮i޿/z9e#|b53ZmR m$ o%)RY%^yb oɖsb4ڷ uԶS8wfm;lycFэl̓qUy!ZۖjU,ZY.C$1:>"gƧH9튮Yy]=Xups)zkG0be[>VV,*1H h+:7a;<=H-TzLe2ZYKqw%T6 m` yA.AXkx:L‡~0ƝBY73- iv}vκУm)XCN(ӅTFA7'Q[i\$ޥ'`e+|Geke=읬{Fl5o VNyNMNWDl*nh:e{1rsP>2N*k|+%ُTwrG m[\:[) D^36ꝶ_|OݧOýiιqS||>Ϗ"3) av}]u!VۜRgGzx^U \/ ^zo;\էQkkDUklS7d))>V2@C]1KZA<㎑(=WeXKse34_ѯh 'dɶ#1ջR)ZV}ե{ҿbuJV뭶jVm+Z}⫯K_UYD+[l:ב!6픐䪗)AB,%U-sr煷4q ~[(U<[G m[d:[) D^36ꝶ:*ն^Yb tח ǟ<㘈i%]ڿե+Jִi۷n?/_7NkJw=kZ)!AZd̶IJm*by3k«u gh#H̷tz/ƹkM:CB@a:9ԭqxe+_wVwҕJ׊NwW7ݛ#oqw-ݚ[m¶Ҵǽ+߿nMo-W5tcፗ]؇z31߯\c'V?2s$PZ1]ezQSzWeR+T;YsmU$Ua88)hT3XNLQ2b'2/=BC}|L56etV-ްS1eY)Ol3ςcNJCm+U=w\[e+֔OukO~) UͧZ5)K1J⃷?5KyFydK Bg5niUvATTa}}WeƔ B 2W5%hʸFkPΉXQ}X6O* eT&P\&dVЃ'1L9 ՚fnɒlw֔jvkRvSἯ'I;?z֞}}yIq>^_1KoKAyyj;Co:x hHΉbu8fSңkWڕKi5){߷d!?.q&c*g?_<=ms< W ~1dLy\Osf#&,|tee]e{Ҵ~Nխ;WvKrTwef*޵kZw;Sv3Z1xƊ"ƍ-+4-ˈvD20 u$]Z*<@*U>ZY2ȳmORދ96n5!絓\Oi k^UoUJшlP}Z?=VNVK]KZ0r+x  ƕU+f`j=a 3)0<\G-"fu[[/cJֿ?s.۷~ߵ>^v'E%c~Kޙ+[ڴڴJzWʮ*ٰ4okZW-31vƊ*lFhj"S Vd`f]Y=@=8U>bY2b ّE!CBTiLA)|xH#nZgaőF<:c٧!v]*>~ZTX^ 7˖kkO{9Y):rږǖ˯+N?=.4t!rD9߯AHNڢ>]Fg9~~R9};fYzd'µO\Z3+g{q唦nq˴LY2+x PtOTT.NI#^ꈖaP~Ȗ2BY̎ceX͈Eáe㩑L~<[NN?zRG9v[Zwk{w}zϟq.^Z54_'Zص\y 3}nWU{U_WWw?.;r~;c}Y^Rvi_×*\Kp7D\I~=1ΰ^=wXu6hAfŪVɇH+Ar%%"DDy< y5"ʶS~޾4zx5m׽+߽.ߔ_zTVMjWJwKi5iJVYZvVH9hQ*`8h،е^Hڭ7ԑd #$ҋW|jT˚H+g~)/?A)}<ǟ^u?,,6K'uY PZ_.L"xxTwy*`˖kVbL6lVMe6”WƜBΓ*S;09Ri;PYЋKٸ7,8TK'U>e&G>z~jҝ!HACFOc\n滏$18lWpHj 犏WDEi| Y~~`>9fG<'HU]8srLb+~Mɋ{e=0 \s6oZm+Zz)O)JSWR)<ҞzKiJ֕Zv^zYq.;]ɾۭد9L?SZ>W7ٰ}+V{wKy}ƒbf8[::F g鬆FՊއ.ݧ {<9nԥiZW)^׽+JҴ4EAA+r[oz|%>^?;q[[e>~ӵ;_WmԐEJ{>4P0!m+S5>}d3ys9B rupfY*dxS+ [aNc<|ΣWm u(]OUvD]+Aǧ(=e* .ŒNE=n??nu-nJw~JR|K& Qv D$좆COAgF>] _A/B|+1R Ɏܸb&n}|;{ dnGI߭eO9ֲiM XRϛ{*n3J_{ _u|ڷZֵvN;}:PWS-2}[n*t_gk쿵i}wi^X_0i?k}/M8pM8pM8pM8pMLkZZG]E)S&_' i)uVҗ`z>R~Ǐ)?D2Tw֊!b MTZ \br[ d3IdXQ#$8K"Ngb#?/}Ezz=P* +Ϧc펞G(6܅e]6@aӏMJbk'A3 _ kH69 eKz6AHL& V]wct&?kh"xO,9 t##&I cjMl4"E7ٳIDP Qt׮MגʛHC:=7ɱ CyY$蹰Im&JA3Iu(Y 14~G͐dX# zɛdQr4|:NG@9>n4߈%Vz#Q7gUʤiQȋ3ҹ{{E">nT%vtVKvz$@GX?XwFEȝd&&S6 iLkG$2qD-C䨾y7\@bO6z6s/f zӷ4"3u SDl&` >Zw I&h.$mVۑBQ3;i?% aJt j3đ} F;rAtLhF+rcpLrCB]p`chuW(whu&pFP|#0GQ r8Jb=.vGBm<(8`uǤh;)#6BFuaGpu:Xf]wF:n^Շ '= zE۞cR=p s4N}Z&dYKzͶ̘whi3K^ORaz̊6;{\ݔN: /3 PLuy=d&[=@%ggU . ڱ &4e27KqnqcL"bNvRm:%J>+ľuanlݡ5&b`,pܖhBˇdg9p!qk\:ۀHV]$k [;|eо[65m}b8Xe+^m8^lU6@V??MM#?u-q4rry,$e![aPE.ԍv ]1p ^h l)dP\ZYВI Y2E3fNL9/ꇟzilB"[ikc 38UƤZ1ҶDɐ{>6% BV> Bsۉu9uI82Ռx"b}Ѫ^]Z'ۖգJYӱ]=>&*P҈ ]gVVBL<|AC^Hr%:_BHp7ըGW 3gu2;>Ы61>|x6⸼.\E؍QGŕDKE2>Z1 T.ā, ܏߀/fIR\.lǺ!1܈`DDI|>5‡K9ۇpnRY-rvl"WK9 c򆇇~}f~ 0 =_?>W$a%|H4#7&/K{=|4<8|H4#7&/KiGoL_㹓Oc4{#q7ho?Uh)ZϢýiMy٪xSZ޴J֝~=l{Ž̭v]~Z\}iKJZy>%_z]O_5 fSb*Eqp!I.o/Y|MLxuGw0"D7fVwE-i=xȲ!U_=%0j31m1ꉫk jlJsy8Oo(_3%"N~SHζnl5)LZRmkZԥ+r% ӴjUKrX+6k4& Z٭֦v )'"„}?ii6MS"M*.q|" T{U:eđLxHT`Xj| ş6>"3Ű xB\4d\9&HEK,vI :,c+,vcq)y;uZѤ6v -3N¬u mSth‡s+<ǧ}{$i\B8kfd)5{ cI1T “_נbJtp7x3a /gc-dG עKR+[O!\O2#]E)ΡpSr+9)k:V-rHGCلDDLȧZѥZ=[cCxjn:~yPnJ^$"rFĪ 8mcN+Y i)N50Zi:MۨbڼRhP@>7FLs#eAd~Xbp7&{3d 1i1hV} /}^8JBh9#fj/r,U\ZEZ6&4M(0"(o?)!bvpEbl&-I\̈́ 晓vC.Bٷo!"Iy!f`5(i,fGeX| +d 'qГTz&NGvucIƅ}}` i(@4ח@K*Tk%~諔/_zѹiAl$dAAB-w֥w NhYzóv)2=! E#݆/8 Ljqתl%eŧrCvqS#봲ئg|!a!!D36f"O:L W&\G,P1YEэKr,CV"̳jlfZs)n4ňwh=zrX>שUVrQ}[¨s;ة]/W#Hk~ŭ/۲B2Y/͠D7 tYv֘Yp+.) 2NAq0gq#*uTu~2ۧpIH35XȍLe82ȳ jSzvS~ޝ~>~o58pƚ8pƚ8pƚ8pƚ8pƚ8pƚ@:}k.h~N7XRϴr?'Yh;io:<t]4 7c?iֲYnG#qF)\={ʭie,W>t+|Yږ?vsՋYu,@7#u (uAd%oOW֑JV֖[u:ҕkڴa4Ç_8q8qO|GOZpƚ8v_>Fv=fHk*,ndaR{eQ},1[*V8Xr˅fn$Mx9mkL P@{u",uŊׯ\1ȓZNU'GrDS>Z|owo |?|>s\m)WSC;MLh\u]m4e!4NۮIc0Gn̮H!!H9F\ OI*F*(:h'Rda$^65D.mjgܐkXu˛E6@WÞ1c9gcjK-i?.?OG)-{T'7 :Rv }#ː.^{J]`\nh#<$JHJF,GRi2|v7olTz1jou՝8|\R ֤?-VWES6mζ;9옺[ kcw>)ZW>~ߧWŇv3Ltl=q)1Q)#Yր9U dnzKTa BP9YYWfV&^3ˈ |S%KZxBkR&!dvv?vx`p:*P t*=->49ۨl= aZY&K}4[aG[cC{\hQqb͝7ӭ= Imڲ'SȧYYGPu3n&7 uI@;W ǖpۙZiA#wx;;zm#tl?VʛpNH|iD.6X'vBu(:-^6>RCMm_JsjD7SMǢ, ߥdp4r̳/Җn4En:u:ւج6F"yWP; fU .V:fP#m'Y O[fNiDZ[]cm˴'HC\"[Z#la)Vb f莦.RIO%+3ےfH]{B$Cl lB$㩪-df$yHoݱsBp?kVd[7CxUwE!3d|%ya*kfذZ ?MnÑtrJ?'cÑH(s\$bx48NG l,Mmܼj)G@wK$=n, NIq ~;][DkkX@"Ǐ'M֏H۞Ŗ2-RɔL#" f|lj5/Nm˰%Y,u,Ut.&csb"fgw7|dȶ[2L:90UoGm% 8Vxª]d,}3˧O&3raԕ~{wIB 9.(9>}z+?ۖ iB-ⱷXM ! :)M+ٟģr0>7/1?Fay?<ڿ̝L?ն_|W7/1?Fax|o_cf;m_O̝L?ն_|"OW睛>n@<؟[+,L뭾ܕwgʲmҴmխi^nbu;nG5+p}( R+,>Da"IQAˬCō] C~J)j^Ժ݉.jی=`!/k4lbt^X@xXbzL?//"gbfI6mS!s,[8Ҵ>Oqu[+:ӉOvO?~\wpwqmkaekܺkl80B埍*ϡ^AVBw# 2E#*d\XW{K(Y4mzzfy'y1j+E8n-[baB地  "4ے)u+_Jw>A]qս jYJZ\n&[٥ddK㈠W*R+ ֛a?KH}Kdȡ*B/#62*u+r̩jI6"2\՜g iinVyr:jݒO ϐ8Q ԙQ@ a 1 Bgu%ft07 Ɩ3"NAC$I}ɯȑ1쭟G߿߿&;+J_}]mk)Zӽ~rR28HEmWpmXtI6nʨ pp ܥЇeY*|$4pr3ϯ-E[{FYYX1u4_e7*2C]F:LFۑ!GfE%i|N*"*/`2BLJT]""Ψ9's>6xES9QF2,ڤWbHiHw-c[[-vDVC;sJҵjR+Znsu &u (a(\KPKNMTn)CrH,x@ZA!?Z9h|ƻI{Wo-Lx2=,'cZ A=GߨW-K., sٓ;Uc!\iubAa"L1 '3z. vh4IrW_rkc$xa۝ {n5 #z0DQ~{lu\[]@ZXu&w,87 9$FoCwG,V}jQV,ѹ(#B^c/Zس# %<@􌖷9_EwV.v*b,aWi+X8PS{@c &C!7/e_Nmݼ+KWiZtځL9uYF0ҙ$L$%t5أV̙K&zHS%D@}J-¼d9ifq qz2da*T5\~ y ʔrJMe'1`J=HCݗ_Cpм'a\˻lSM12ꈁ){ յnfA#Vdmck~΃Uuu#z˳|U;RnmݫڽJ^w ՞ڋn DCp_9a"i˕h*s QG7>t oY%uG{EkƻPZ: .)Osy[dyl;"yhK)miRCKTIsh]5އDLƳc,x|B|\`Gk،._`n?Gc+je<8s0uqlw 潊;M;tWԸݥLóQŘ4>^ 2D95&B¨nA<WSDNvUuY!=CnsHs jq{QպЧa4F-\OPGi3tZ?H]pK;HK00R d`R5}uy($zSl'X}ZCA۪\{UI2aWÔt)$kNqz ZdѰ2"͑)!%Iz '!b,id2d.:$Fm]Nj6ĮC"p ʽE,O`DB4)9,1Pb3#/NŅ\ ,, " Ps:ܧ..t25V75Y 5Qot8Qsk;Ҿ.v߿Ϫ_ek[iuRV4{ӚJ($uf˩5X>j;GʝQ{!cFMA{S~arbU(L X|ۅ^%V컦аAZKq Z؉κ2)Je b?lXҴǯx17JM01L.ᤊND8ޒ8$n5[z[_#%}1' u.F,ycsdټC*iI+֭R kQUz+|Yr0WZHnK< bddDNc0-0Xl>f^d1.bk \]YTj6G'Ou>_ʄԞ<@s.Zđ%d37s$7q 8 y|7Y@vaDͽKhur_Wr20Q"%OMP #;],B-" \<\Qc#ḳ0O gi `xsh*$62ecx:ێG&rɥخJXb [M  *'Oe f.[gNnD:g-s+H55`ƛ8͏@}<Ԟz`Hf 5p_xՋ0ٚlv+ÒrfLwnnLwV֭5-[mg74 0-VdR-p J00@(H䩐@:4Ït'Qr[%,BRf<H"s"$f&nl50`ĹXxg%%XsOauR+Ҧr[;:{1crY.|m;u|{R/i C'Jm\Hm.EL+f▄0v/5$FMդ3㗋d c7gZ,ʥ JuS`v5A)d*ҕj.nQ2&VHQR -^cyh;|;cN'.8G;'w؏:#zoaz2}=ez񦐻BtWXɒ+Aː^nGԦ$y<߯ؾ=YH ,HM.>rf7 *G'"Z 蹗%x4/6nNdvUÍ56[-[mg74- -VhR-p ŧH00@$P@:4x0Ë'#ȳd6]/,ymIf.IFETT%WQK2[VՃ!&'*ۘ FՊvTBjUCc<BC11LO^9 K$| UɜA!8%TD`Γ 2TĂCƧF5ԨEZȮRT XOQL u̔g33cqd󹬦_"R{%~lZV*Hi " )"8ÇgGjŏw?pÎ͏XwSXkꔭ%{R.]zٮ{xR+_=9ZK|imimRִU<;p}$g_÷~ݹL]`R]uoi_**"ٻɥ{Sӵ-֝޽1101sLjղpMaDL'dj|N/wg%x2h/kN e1!;=Vc$gG~%VTNuD-$U'D |,Utɓ'vU gu˲˒qmuZ"K1!`2#yƲԱj)^]Q.ʘ&*GↃ%r?GxҒH!kbXqs >[#_Q"lʙha &Eң zӨnp ,ej礵 IGqɏ BAY,f *-U%kZ&@5m0@k@ &ds:*P1?zL.-R&XЕa7,ǒD5*dFeρ|" seV˾4%@!f PX؍)(,9Ķv+]Rĉ%+6?jJZV<%(.QcT&g [5A)*Sʭҟ?zvpS{w{Nݼ|~1Iu͓ sK() YDS+QLfyޫo;[Jcפ!}2v]rDm#UqɌ/($8.ya^k}lbWD\б+Q%RkLg$(>bI֐BdƖn%d\d^p%m8/Lq*kWʕ}0ؕr²a)uj]N7sUiozzTX #pPb]18?"܂Z\WFe$dCnMk|;$XxB(3" S ܯХAj|,ү]rMMԷ!QĒ Z7?١gp+`Ka:V8Wkui޴> X@u׬v雬lǾ09c9D.{߇op"7.PP)Vb MBTTJͅ"zOLY FI.r"XU!e[dHV6C~εɍB3$HQW#qm! z6DWguJTZ|{xs[{VRM{w?s*j!F$$~szC"+`ȕڃȟRg$'LƮ=Ϻ+؎N*#udd&Ey ]9";g?8̓4.SapK]RAXj`-ʩ3w$%2Fkr X]0YA1)>@)q^ԫN86Q--lENmB1U.`Kq!HY~}=?8·OyX.\:9)Dxx"~qlBܙtWytb뗐%r+ouR"3",(ޏ]jۄ[žsI+?S9ɟ=۩ B:4eRGԚ!P#<ϭ7aQ'= &A:缒$_HN:^dɜTԥm^[ӽ=?8RkҞxWÌ05=p%}'/sc-fÖ"gu!{n[vf&%La 7}MUJwi$ eWxvn<*D,PtrhpLkϟ.կoj{S>{9NK_uiZV!5̔G"< }">\Giry\fǼܱzԀ9c9.Inv4s筶u|92eF憉dWrFDM.0Ifa 1:ʠBA݅r4qeAʥ c G#0Q11Ls:8 FRm`c]]`ئу;Rނ(ǷxsG1<1bU]CqI\hȨ:K`fʱġ>سaɏ&;o[n[NZx槏.0(!1b`&<ư9WarmSVR,[q !(( ]XRϴr?'Y>z}K)mV J]J֟#{J]\L|}t]4 7c?@:Nk.hN4ՋYu,@7#uoVp+)_&ǮeJw,,vZֵά_Z˩gIe֟ݎw -;UUjv_XQD"Gu݃uDW/]>WH"2¾C|3_l } K񦴛;3FA~ ,fXR|rv:u >OjVG6ѧ1 ϟvJÇh.pk6sH'fnR*L@vZ8}^FR*Y3^1)r2F2Y H&~EQ#3>&&'IW]請Sn`.ĢM&i5Ǒ['(jskwXpLhA\I[mq/Fd69ⲶmNV+pWT%\A:BrYCm c}!$ Q)1  @!,jĝ>,xqe8V_wsݿZ@kT{sIOg^yL:?~zF{OnmoC6a2lecߌLXz\2kj0&S0>_f݆;>"ٟaύtדe??WEmk~klOgZ[34dzO#ۿ7+"ٟaχgiCÏgc2OUiw%UnǗJ޶ڞjWңl|&D)U2k}? ez{82dec{MP{qa ""-pkTw&\_yaJ)Sݚʣ>Jַf[ :J{g;/rjfWcg\$^CrDDfWm|UrFQģt۱rhSyxr`Q)R!Ur'O/;+h0ɓ9Ɋ R8[|XcTIՕYx5 pWvVHjkvvh^%ZuBhw*&l:)(=Bi !ɚ"?3rRF!/ LW^?LMc|jr钀سWt})AߏH.K6]zbu!*^$LCrmY/rm7ӸRe;HFrRVK؞շۆ]+mZy9qrHuP*-Xz\[pQ__%h`v%3K B}vu>5X6N H Qkh¦PE%3*/YrlI]#^bsD222,5Tg&C[FUNƪ ޼eưۦh8M$gbRBWVkLԸjw%cE$ƶ[5+˒z6ڕۭ *@#f[~JQVDiޣɿ&KɾjukJk*U1'Ԟ8(2dzFBacs3:1N7c傸MlSH2) x9v?TT:^'LyOf,tgظa*< ĝuiY2//HW%'ǎqٽ4 {&mEXq-\ֽnQĒ1N  $pg:mM6@8*nPaB ^$*HF:,Kis(Ó*{ umR)Ky㌣TALLV+E`qhy/×"6(ES~lǒ0uջDZ"*8A^l[@#VW-"&n+՜]LU<] [eAm.~Xmb8N^Ȱ( dIZP6E^m?ݹ5W^bM# Z\jHM*emfqfow!LG@N0MlPPۡʐmZDPW)ER+pҘMELyÝQY$btel8zp$Ƨ+vAf W&~],Cuk̳SeL R}T ZH¥qηMwjGQ]f4,vXX %[QDrxuܣ̅  SWta-3o_2GSL+/Drf3%  b9 `ZcP_=ypަ@kHb@`µ@t݂zLR*3,(Ti(D[+^KĝkK7!L,ngx(T|5Qpng7 mHBsƶ$1҄Wzƒ 1imu -QΎtCZ&\Ʃblf%>; .7"ؐMZL:"݅:b1]mLJ.[첶[iO&9T56]03=]S i6 ˑS?^x5N1tqu"Jej~:v\ 5=H13t]4 7c?@:Nk.hNO-ֲY_nG묍OzK3܇sɿ%FA].ն_:GYoo㷿k--ޔQ}:P[{<ۺp+ʥ#v޾ZS#&4Ç]8q8q8qsN/9Z7'~xMIx1bcO",)sP-5ة?}ˋe/+^F6L2N+lxRnaR*K{8BWae@L"W&Y&j"ddxv Yl0QfD0 T%iqyx/Ŗ=ws?pe^/f9Y~=ߨv2}[q~=`6[\%ӂH#fMbVb yDđ${JA35T!u(Y-ѢSOu6՝ßB`AT١s~bI;r`,ݥ)fIKi 7uYF妌=$קIgyW:;"k*דلZ[H0չ/93Y MnWs[@j 6|W}H#N0MeV'%?_nOc_)=t?O d@IxP8jzdvIaAU XtRs,̞T߄OP7Άud:Gm*XÈ9.q-alygGe;h3iP<4MZuQֽi_\&+^$}Tߺ^͌9K-Cq=B&\C&FcRVNvL([#b59D{_۹0[ֺ!&ƾ(Dhf<#FQClkMltWn8 Tٝlކ6Y)i6;\is8*ّpNH pb=2%j_iqb<SdN2n4Bo)83̔ J9K#)v,oD*h`EM k씌lQt_PY nSݛQmOrM&aFs-'Ac2yH;ދoljXGrEѱn%vV n3IYh;PHCb[n 6DjQV#(ŰtW+cmLJ{ hlb %T9P”‰U'CCGF,Jnnۋ'>J6-K6f ?fgɉd&"yCѽ,z~kjcr.``+޺eADⱚi@,Hq^Ŀ>:ۗߩA}u/΋Oc~S{#q7ho?hxq^Ŀ>:A}u/w2i,od~n/ +'ٟ_r?\>(1/O?~drXM=_?>W(1/O?~|Pb_f}qv7Tݣp}VLGOJV=;5J֔yT_w)_Mgmӵmok^Zy7_Zw[ZN Qtr- 7pVę/}uQ,"+-(>>BmWAFK#]覫Eo>^\;kj@m4tی%-y[3 gԏ&P\N|Mo8bUW 2C^Dqm9JSϙ{~_<1K'Z\:}9 È#)fܜUTO*!ːݜT}9 c6Cg@ &h52*J] [ B2{;ۭTl%fT&5N9pb'qHON[1` B2S]{˨>a:%5(ck nQY L:zm yk89u3VȘ*"o$.BM{k@$W7w/qٶ@DLz5 m$4c_*ɱ:Z7ZD[@񤏝I昭j)v, b uʱ|gz4m}@2b{6'g쓥*M2 nEO(.G}:A:/>3u ŜȚ̭|%Ԅ(Wbaݰ'AFqycH%Ή8;s@LmoRK#{|2Qݛ5.D 6gaTc<ˋlLtZ_ GJ2f09OqQD^7a.Y,-C pιYVc)<K[8@$jp̠S1+1!_*B. :X4fR\ENeBt.Dfqj+Vr,fRX+ŐOUB %zyidlY)L$39GHI8@ΎT76еZ^ffJ՛6 TYc_fwe.C幾dh3Q/;?Jѫgd ʖE@9Mpr0ع*(rtab5aݮrSpw\qp=|Y%MiF$&R7^xcmH?9jvj"'bfyPX&2$#LT~k*{H=F9jHIo0ӶH&DD"{WX,әڀ5ԍ-wzst.*k"[jպꁶX]_`a]ΊNRzP a#m-`cܒYcһ{zln1dq뱷)}FXL`w!6lCUI|S՞=WJ5,p+1gM$.+E A JP \qc:D#2ä^VL}ս[ٗ:<#Ҟ$mw=B""V 5j,3( dYNpƉ`$GҸu؍f,R&G:%hƂrH+Gg.o0Aet)5$LjJ0Xǣޙv9YaqԉDn5$y$m.O:aAX ! 5#mAmXRe>\8ѹfN; T'ff_y 5xXAAs~=w+R(N] bEZZ7ތuKʰyZj&u[^mݢ|DeOy >6qC,SVRQpipjvXeylyđ3;\\q$r25lp~zN'ÛܮRZJ2#z%z:hݙ'*ma,ŽɵНY#9W3ytBnWO|&y3’Ȁ6E/,zmSfٍNjM:5j[ p/eY|hJ" qb'*2`,GzX!ao6Aۀ5YH H. c'ncӖ*FTqb201M\\yXjYd[q1ijkIfA3z1L%ac-U'lj8@!BlA eruTeݎ stu/nOk3'xF8 8rWq;ʇ 9ʭKTPW$/mnh~c"lIa bZhmiASf#fa>N4zȗ;h.T95hg# Hj>!LOs"d" *a~Ve<#5.ޡyWɜ\N^ϐ_QB 3ŐV[3ZNJ[WTVZ1Q5RVMWJwױW%4O+ GVZ5;Ҋ^A$6dbkB/w',a@6+ ˭@d2#)z+#EMFYƳ-P2*kҋě1V^CNAibIjAҪɂ, #nm,bt"](H 2[ W I4bGsDǫ^8)Bѣ^z'\I /6^b)"Xj k9HқRů,$e"Iұ$,I%Be2̍W4z,MXs.1f`rbCqt82ÅŀSH:"'%k$¨bz s@N&Һ S_c)nlpűߣ`kB6VFhA !\ ZN!6YVK9*zr^y\0#!5GOTtq:a+VVwe2 ٥nzdh=Y/E A*>`^6M=_FY&+?oZҙHaY0(aaT(3 ¹FXˊc2ݐ/SjԪjȐ'g#Oh[Fx0 db7[e@N*֎*vډh;Њ"'#q׻#|a1ݕ2A4Z6̝R3ت×I(x,OLHSflnkuHpyU1 M}f6s}E0X%()r ˉbI;c,q11S+X g/uգ%l6\]tKEf3q l[]q6p2&aߨbYK)\`k"M/GͲջAɣ|6) 0&fI#) \)PD骺OR>!ܡ9GdH <}4d J^4MpD S4I*mX%cpϑ*{I_9Ҩ[{g^BY1\CI Do/jQybs71)p.rFM>N_YmxyA0srNgܨt (XAv*5s`3΅V5 %OZrl.N{,uA4:Hz1꟔Ǎ+#&dGӖw 1,,mQ|Ukdb[gQ|O%KG3.uE+wQN r-|Рq͌y.xKybԍݙWmH\3p1Vat('8 7; yÖ6#ڏe {,swRxP2K*' *ڊZ9/2AuI܄‰{ S3P[3c&a)\rqEF״/}sw@,suv{ha +'x#%jB1T֮0F쫓nR͊/ A'}!?s {+@" N5% 9 q9Ʌ,T^3xOqk &9cPE$"LԪmn)Nt! pފ:]7D`$$?HjcK8 6\]Ov~ R.Qȝ~[U\dU枚P3ɻjFGI,eam@R?`OEFoUƑ'i<\xKhUQ D=+J4]P6 Л[-Z@q:֯{"mre -4Ys>p526.<-MBݻJU7 16Bq d=X1C}'B(2X/cNق\`h&_ی#Ex2 g^|ek6#nU )!8cGٖNA{ #l\/ ۊwN?~?:FTnC+&@T9XIO"s:^M:FFҨ mLHPU=jud^,TsV/eԳ܏FëֲYnG#pht]4 7c?@:Nk.hN4ՋYu,@7#u'{֕gjww6~+JҕiG'ֲWnO#xq3 oe2VM3Y[|iIoKRWu)Z[vmkojى'7Çv˴Ç4Ç4Ç4Ç4ÙI8 bgS =S)JL{<1YY?]ud C @cɲk-jbQ OZP@ MdPՖNPAȴ}4wtvhD\̔c74 =5Xrv$6ACK9?}EEjZ,\yny[<&`]%!؇6E"B a8J9G- Hia㣂ONFsٯ lP4AYTj(}>݌qdD -]υ0Z2E@v2`FK^X;^vzƙ udd{蔥OdO59hXle86.>q&78#+$"f\x4.6ˊLdfuM5e\9I~ak'eGfJӻ|uaUO u垕2Sbci z|B^:\^E&+>S#}2_pz0J iģ'&7W6%DJ@.s=a-T@k?BQ+s`v_C^ k @m cP VeiEʟoup0l?Qhbn zyMFz }0gR&s H(Hy8 \O(K*F:h#TRಡf^A&HgL >\fDs Shd4 .HmDP{B^m5a9P[ ~ݭZ"1 4zd$}c^?Iu**f2Za:j(V;kߝquh ^i^uHkԠpF?P-y,7'58i-wj+R"! \QLgƻ gi,z:c_Jj&֭ fZby)՞pÛ\g`GhÇa0ק`G8qz{{DÇa0ק`GbO~yپӷN+1o'V~䶸V.kWkJɷukxxõ)F>N^TO*xӋwMԩraewa@ck֭-ˬ[ZRO+jfb`|LGl19(}.qZw>z֔߯???Y/#r;Wacx0lxEJIfAx%%#%YKQ.KrZ)~q|Jܠ{% 6Ҳ8PLQ}#=]#~QԏL^ek߷o*N?s5Jն/٣e=؇ ܴ~~]6n%l\r K'Df$vQASmvsnʚ>\ial] K[ ҶJ_miu+O Ҵ+O};VKi]Z[J{ZҔ٭|9D@M9_8Bĸ2i19gIAdq]UeNxqf*ܵK #Ã\RŬEfr.G4UUUSZ}B6. \zK$"QVO<#9ޅsyΆU/S{j}-.Av*a,N6ԥm+JҴ+Ji^|.:;U*t+Q$M4N)J#^%ψAbe^2{#y5ٔhV*n8U<\v MH3hպDABusy2r+I ls,{9ŠnZqr 453J4 ls`je_0|H3O@' 7wN#QԢ}+i1x,# sPF_e!'/)y\wMg.XM@5[gSIb\I[l@-{7)ic 6 K UĶ27=BZ>OH]rKߗ`Ʒy_CV:D1ּ{%p?[Ě1`{VdʝVkVffXӲM*kdK#{nYuvmR>i߿*$u%/G#kvHԴ&K?PI撣O>_}շ+-Z[NZ)Jw׿ʅ{N_|:p}}?Hu|}1kݘ}Ǖ{}eD[MnJ9Gu=q^tpÓ5ÇhÇhÇi}:8ub]K> dniֲiwYt@4ux_Z˩guZsy<־VB7R)ڿt;R·vNՋYu,@7#uO^ݏ͛yto%;R)|ye|+u|ֿM3<8pM8pM8pM8pM8pM~(Tgy;^l/vK'`HpV*]`xeXն_Í5^W5*Gޭb%4nRbgHNf"gb mͧIGz u}s΃DIB%6;?XKgOr_zn; l=?E?8qtet1M~z?'ղewbH,doM =;MF4Ό Bsa.ޅ{4* R?WB&CeI6yabYDZܪ(L{%ֿDB{1X?g|sSZx񦩢q6`~3űH$-P q.GX3Xv赖".8i;$jlbNv.AbE.-6gH֭wo+q}w{AY1_ăL?r>~bјUЯ?=MYZZW$a%|H4#7&/KјUЯ?=MYZZW$a%|H4#7&/KјUЯ?=MYZZLzM~ & nMUX˭Ox\+,[mhŀ'ټ(z7hnjCWXխ=.XٞnֵY ps8G 6f UˮQj__=_7_ۿz{޿'q;i[u-ӽWnzZO }w[@f&*V __.? &n fC9+|Ox|1jOK?7?ݶ kh9Ka 5n8&|*,#C$~=2dFNX0K X[۷zֽ9e*K&V31x|Uo)7. Icjˬ@DCLfb"&c~)Ð0[nP{r;oIs)0'Yu*d!@$V'j1Ë-$K@YW@o&4dYpDfu+S(U w*I)ǽ{|9qԤq]` $!+. fb~DqoM6m{v[auqeVʺŕ: n>c0Ru[0:qm,t9[!=PU$efgd#;@]")4㌅B,q,h%io+c @$2O3OgWQdMZ5fKk M%b1m&d$J \H]%Us'mjr+d¢DM)\q2b%S򭩶^bfh -rize.՘v:8& WXc(a0á#Wi$HQH ϝJܹBb(7-v'X\ 5Ugxf4λjGvY.YFw,Z̺ 0ڜE'PeyvS䧍y>~4̀Qb²n HL0C㒈!gun;hܵXt>X3UxN) )lOH:HUh"{!#qu[Za!LMm0yrƽw.IZuŃ1ȶK I2VUeS$@Xi…Ȁқ3Vܿ%3ØTO=瘞y~|{@޽llC7@b"x"#W.E 'L'0$LEJ]F5# ҩL w3Nta$׷J#NUDQ:W_hVɚI@jNt]4q+ s.,EijKܧIttTds_e[p፠H@qGXDA~&xw y았u[T.igvS22IKE01$S(Jnz灔uZkh@pU#`9E[|9PXWK2}Yf+)e-bx!2F)gq'}X!\{JqVlƔ\PVeWrūYZտ52|9zPY@ DGDIO1Gw--XM,U b${DBtt+NN^};-OûN1 Ƽ8rKbqUH0*8,Nx ү[fRg)ɝ ɼHI+q9!% 2LmjWNtpV/EƜpT||ya<ϯwS#r1(@<<c\b")mȻ䇱n7,oDSRBγo-viC1w8Q]+ED*ǨqCVD,{wN="ČD 5^%c7iy.EDɑDw^!PEp~>n]8333U3$&%=Bɉ`u $Q>:K7Z319>B5130WTBTk!@`@ [MǦmR( ZMQȎ J 1kpqPby@-ZtKjleZ$ mTʷ;tl%a\ [aQLʼeÔ<^8 須z8)\ \QF(YH>ðv̄łj]36_5PkyM#\/GC~+sOBϺ`VBgaPy 5) %bp 1 dn'i}O^kat4_9u<ֲYnG?>~-No5mEuˊi2KA3]Md%pTHzi4IKZUp6"O{2^99e`慷+BʊGA4,^EGPʦio%$?;&5jڣɗ-nq Ʌ&"a,qqK!F$dШU=tf5{`@Ŝ$m^Ԙ̥cYܹbR2\`)+.yGAG6Zk J絾o)Ou@'eꊚ?E?Z }0s~~EƠZӪ*՗lm*pI(ФNzwmd|Ģ4CDdcGI+/Ë'ixY-@G#%=49 ӯ\%N,Y*6N>{ 'Ɇ8Ww{쇋]gFL]^~ .1k+jv ,zlbQe-Vf=k|u#Ý^O]?VwOsïb+L =*lX&T엯]uVkLg&}5+IWTmlJ{A&"n!^ؕg<i%[Eǝq7@cC7XZ Tp=#Pkqۭ'ŮzOFťҳ FjF~iAi*>PċBT$ĎCCq8 ?7!v=닋xl#Wy#Û-!S0/\.gY K})6)bBdlOiXvN{9*Y$[~XvAvF!(ՃgY)N2QJQc@p] b)1΃mk˜8j}8.f"^gCnbl)?k9IɎPvw-@וN%*sMJ(:dBeimcۧTs NyJ.QZ) De#e2PE"h]%9 UR _ݫ $؇;zVăJy[Qtxϩgt֛2ZlOl.3fƴjz66*Of$ M&jdalޜn ɪrviv1ĠTOFOg3P]"Gǵ_J?=evXnUqqTp'r5 ׵2q6TGX'0M{ަ=]z),VIK8G"͆/hb#9X႘;'5Cփ[˱(UIH]s&&æzvqh)P&>&_bZ 1$TL $nr{B%l|4'=>xGSkpcb=!n(6Mf=D4nU֑7WN8?w[ݘq?ҏ|W;gٟiM} ,vC `j ܆egs12yaqmfsL2q">)u$Vך덩_ǻ2*͖Q^ӍomoD59 I,w',Â8ȉI1GP|N j˷_/sײ>{>t"Gk}6#xK9Qu#6x'cIibk2l b "9ʎC؆\PXiֆ8qӶ fsC7BFTi a "eIRL?!"IHQṡLV, #[1ϰR3 GR3V QUAO'>k<ۥkk4 ^ɜ h[gm#:uvCl&(Ո#+{mP.B2woc1 Q[móKJFqp/UCrVT XF2#GC$'7sPwX-06_ ț&B Kqkcm^0[T rR(CەX#VƄt9: &!%XIǨ9ۨϢ2ޛ nHWIAE {MMz/#P-M5hMt*xA.8D6)EMM.ꀍV{mƽ~-pDΫ1m+u~MBnb z.flqY2)tLь'Kr[b a/XB)} :¶C][`i~b_OBPm:6󂌞 'sԛk^'E\QVhr\81R5;Q׈ܜ}ڿN9y }J}]΃2t6KybFMAyNc<^u{ky8ڷ9 omT`6\hċwNFp٧|z#ElK|q0rBM#ug[>#Fe{8ؙf΢:鵭)HbdnD9.nƚƆ"p ԃy.&_S|i 1ڟT_btHF^F~(tfg[֮4% #rmm35V)q?5m4 5Mǂ\tp=6v?fpeiS?-ieH!,Hh͸?݀YRjp/ILF[v Hjxn“=HΛ (lApc BX` Xo:$BR{ZN\ٰ,.bZ_,N~W3PiT=1 sS10> Om *&ZRg3n*_ L kE u%F9ZFÍX6EN0Yj"LMv1bTmX7(՗IPve25STLYa'?)8^?&{;3p?]Ǿ)o2'_^vdas4V-7J#Z yc$g༎W$a%|H4#7&/KdrXOnx76|۩U&lI͔SᄥʸB+Tߍ:4`Ωbم:|Y3e,{\Z7)k I,>oܪ.j#!VcPi7nyq]JdT6$bVIDIG\ItLL3 :.^Tƴ.l=Q xq%0a0e)"$v;A7M 4Zm*"!+@ǹ遲zgBJ%փ3hR y4j2pܝئjj&9/F=04)msFq P%,D `BL,+l͍2mFJ1?#@ܰ{l4 Cr>^ä@B[%&& rsCWK& 6ۄX>8jaIuw> vp+5-q r |g"e::b(ZxR WqWAW(Ö5,vҧ.A O.[n,c2ܭtpYbtᕐeXxG=:VOPk.վ{~w;9{w}>kzJɄThթ$Q+Ծl%GŶz[F|b$s[(`K=V"H8ogNztx;3}N4_m;hv BfsD.PI;|;,2܆s+cla1h,D3VRgkem.sO̭z]H~~%ZKCJjju-yMƫdJ Ɇ R\I&E^\) @e*(͏ ˖lQX sMdf)CBpE U i Nl܀Q> \c)sǐk!qaUv$X%iPczP|^rB0In:9" o I%g$~.ˍLq߹-IZo5YN< Yl^^ap0C˨tU3(ZXAr&Ƚ6!g @ Dـ &HU,\D z"yp7-a#;*0tQEʠeV\̛VF:xaYb-FdF<,R2ӤӈEnTB*X.r ,v4F쵶T[ۅkZ5i iJm62t(&m5*yS+\[׵_PcbYj"#}0QLGн]Q6Ϩ$)Mz(OW{%xmٽ88mEnٴlپX  D.AR#ml֞},hG@Lq*Y莄ktvA#q3 +,O*y!ujuѧ'6lkبq|6bw|S_`v&%Ф6*׎AOېS-^r+ ` [-MEaX,1^ n4+H}=#%Gƞ6\ɾgF۩<2y'CIe!KX|jZG:Obpkyc@PJȋ,4܆ 3FKy ˩mzGw2T)FzbK6 Tgϓ;+^J K#iuf%[,w[XH #SEgl^/tl ռnF^f±,pi1Rf:2A6G ayY;2 zJub`U-Hf;W;;$Il{vLW)$U싧sզ^rF0L0dlX䱸ΐ)X-]Qw; 7EdF!=]Nk\cS#cf%!Os̆f F{[[:Gn#J ecp%@\"oi71*z?m.Sn*"9 -e[b._sO)u**\'vL7juѲ1\B  L!Iګ}䉴exv!ˉ#Z(0kEɍei2y~5S~nk; $Y٘kt(&푢bHO,_F:WCG(jtKڽu"Sh T:cGHu9XYdtbXdY.Ɠ͑:";eCBj]:x(m8 CF GDJZKP9~NSj޳Nj&9G5ߙ 0tc1?(T*)V}{Yֽ۫oUWmN~5,p ȹA\dž =GE$SY3Zj9 uĴ5Q^} -?q䶞TsHRx"iUb"uj@%lDMZG*11ToZw>erB>>F< Z*"#\8qw [ F0y_ _23PZ@e̢ RY Ar]Cz{fVyرXV30k-8bIQ!@y>5{vyfLy)[eӽ+[.SkJ֔{WMyN:*U8Rdr;)2ǷK5m᭪ef rbTi5u54W].׶DmVH֭r`nV1+'AC2$5,n[:Ta?IC:Y+J1\qεӪ{onV7=an_MÍwTUQlе]L=وr^Tnb9";75bNodߎf 0:sH+}֫w2kU):%m2$\qMkYF[̘iڵ%{OOI[:>y&N0sՖp <D$ lpGuҍ2qrfO8$]-M FiȐi av|sDyJ$ DCeMDx5 ܶŌ7DR Cf^A$DDŽx3"yEiTnKarٿǀbc4>'&~¸*eG͊d[k}.ml.Z}q++Vsx$QlxoEϬ5b0hjvRYmܸ+]V%TUn #P N^˜,G 0hıS 8!tK3SA1͗1]a 0.h%m92# s[nF2OK e-U*x]J4ݕ5ٿ)o\J:F aj[(f#Bx눍p3yciW6׳7WSajcj H&oWbӽýiޔ~>>ݻ\OZ:L0j̈́YLksziwμSH&vܱU2 i$ynL@' ,oLK a+@+lˮH'z+vb&XpYؼa`jgdrMJ3]`$9@JH1YğWOt~>늎Z˝kF.mFE֬QI^rd͕jL8rʧ.\ece<*i޷]ZҔ;ִs7^mN8 i&Hl!* )׍$Jk(©.l2}ȳ#emHɹPy#Qb+khoam ͝ԸT/dc۩A$2(~!D([1 K3$R8%܏2ZTj<V+U%]EIVc#nB$q1]d+A2FVLg:#IQKGC&;bGI'g( #M[ߏc<~')ӪpVpF_9kx\א$:MX1t:-! &A^pی=[`돷R7㈂;#l]&=ɒ5#JRY$/0Gs* =!0|?MVnjw=֭W^U<:0ř.JfT *x`}P=q?=풝(d1-fwzCZ ,D%I[M7[jlBC`]=gIE#N4X"фy حF=pnTNK!馯Wݧw{)$ M J6J|ɕGh͹Eg~c)8bpPʧ!Gy ]?/?2`$T)uiY0]hᣨ~#冤PRvg鋦_]= DM"xjEjOZw}=w۷0QaɟtGf2twO 4˷nP#(L:!Өt䤏0u*i)e h> 9h YQNyut8,=e>ȴ'AdH,l+Ϗ\[Ziae D6|xo7R=OךM]^ ]$&(}!:ta/:~T:&XmԮ566MG!67KIx;p>^?%+߷)}wB6#1- ]v,˕ +> EGG3gO t36r!v Ie&.rU3[ տ )LlH@oEnKnJG VX7 v6䄆Na9dl8 7f:o#8`<?W:BlwKMD/lFjV=LbҶ7#9I]a ]b|0~ i>4[֟Zw׵{x|jӽ< S}?-kyuhIDrkSÜ/PY >oCP6#׆.eCI 3̢`OGėBehOT |թZe6ML,qkyh,.'i٦BnTSzu-X0[MlË~F`&Rf٦.sjCd]97Ҥ6ݥQNBΙ&j֋zk(s s:G6Mlt`K}q:%M] ("$pJpdOh[7>mTnd㘴h>AK~s3ƽkid7Nҳ[5[ʭDj')\Mpq߇hQ㿦Yjߦ_q;m}ƚ~y9mx|w\k7/Tsϼan kEma}]׵-ZҔjJx$D9|ˈ3qƶxM1o4 3,u""@yΔtk~mM!&{mH!5B.`<. k]Ӕsk@ o*irGt#KnHuF9<@$1@t)wZdWSMbf!v2"t^r/b(?^U/_{S w>oӇ SveYԪJ\v+m.iNڔyU_}lFb UOrT]LDDG>Q&}5Up!ȮyۘBS ,#CDRe2rS=e͇R953){wW7m'5Ba{qʄN*k7JN np:7C._bcu9UE n9"!>oN.zWVDyަ! Cr3?"pEajɈ|7E P9rle_՘& e=d wW@I@2y)u6,}@zp8h,h&M5%3a "(ϛB2Ցf\%:ۅG73&vU@C:a0b왱ȞxmִRDl HSIs Y8B\(yXET!Fa6,U1ʒk.:-hcnqy zEAԖ!fMb6bI#̵ 퐡l `[U~bJg'\:ld%䄉w.E%qL͉V1 6ܫ-q_!?$\,XB=!@$E1ƽǣI>Z lEcn1lU%IM(=*LGZdf 4ƻNZZd TRMlȡRFfNjRN+U,&F%EXZH=9sAsl]]3ckȮv0ECCy̭-*#/@zd$$$3ܝgV֓7%;=(u.kTtm>엶8ѵD\(Y 3cgMfDT W@)81o>7?QxbE1ҍ 2b=r X+u&D>I^<9~Y}g$+JʱF_*΅(χfC$u!u=i6S-䬧5Z?;JFaaY`.ޭOHřJeq"|"̀ #9qJD:qhnhSo2r ·&Tj&k$[]ǫ1)' `\1$*Ebd*rmr"DžEJ߂-kuݶcm@ZKqb 6 avfQ4hSࠩ1W6Wzn,#deS "op[EFL ,4ySEÒӜϭQӕ!>b=&Kz攣r[5dq;c/'}nFNVH㠓[Ib \ G@3S{;rѓ $qE vr 0g]#*!ϊR'lr5*v=3 ,S`B 'x̮CbΆ*K6*C^5gȭl7N%ok;"!̔rA *:E$/fzț\XEsÕ>+q-gœ Yu8豛sj[׹敇@C\\(~ ST¬T*=,Ql9m=`-b@)P^Sm3rCbrK.Cr)@ $l z$Kp[<ԄaɃSeRHwl0wWX#0A%bs;# P r2 czH@l:1gYXTO3t!>VGˀs߮&.ee&&s:mށVrU.Z(3*u*[*{BB`'ԳiKf:o}7 bZcxȶ_Ge%f[|㶗߿kxӿ:AqLO~PD`b F'b'~\kmi[J[OJSy}_7gz_"^=^˵o3??3o5[v-JRv)JvS?o#I3ο?35~{|~χ?Ni_Oξ-ee[Okm)Nǎֶe+_}im~iO}4|??3uLxJҖYJ]*RiJOO88Xݿao{p8<|9|ο?5owsmi[JRzW?o#NgÇ5M XRϴr?'Y_Z˩gÍ4t]4 7c?@:Nk.hN4ՋYu,@7"uOeTiMքk?t˯ZҝJ_Z˩glo rs6w)_7vci_ҝN[^a4Ç_8q8qn$*3xՏWI4͢k rEV(rjAb!=^N 'mr9ؿ^%m0vL2s}YϥO ׮=,-/^3yNݧQt7'V_+N hqt:H6T D@ܒe7ՔdbSiFSJ!ʏ|.OfDP]+T=ͬ$!&ٌut*7X!,r2:{<+',&+_C]2X/ջ5/_)U#GUmgʬ.&zkKf-"ֵ  kq)s #l'QR^'nڴy^=+ޔ~+Oܗgtm7b"LF&xL`&3?dLL_gx:jCoZ_h:i?On4Vg2,tOiU)@R,h0 J18b#1"Lsf+\N%:URYF ǍƯ&QA:U>s_!?_=6.A}m HXB*Ukڎ۫:Vd!vִ" 3rta}01I3`64$moIAkb{[LBy뻦=YH 'du fq4]}HT:^/6l(f x0!/U6UDټoη͇/Q!fM<ﭮ-e9^z-[Uk',bFEuG1ƻ^ڸo/ Y,=\E=~ْ\J)tlVqcOsÇ է')Ŭ9E~O;7eӫ[/LVO|U۵v;o]O꿭?]}yٿ/ . [;nnFOԭV wj)Z׽+JyT<+JrOX3'XfdfK<{+JW´O>_kȳ[ɧs&ߚz3&{r+mJST~q[miJҞV8,4>q1M4_ ҝn<89\y6´o9Ǒe;i|Ey6vݸyxWɷ=i<<9Í9G84pÍ4pÍ4pÍ4pÍ4pÍ4pÍ4pÍ4ub]K> dn:}k.h~N74wYt@4ux;io:<HV.R˩gӠ#_R;5 )n[KrYcHLZrҕiڗҾU<+NV/eԳ܏Fvˬ?~]]nh{K<.zµVa||i}9~8ww>w|^4ȬH+N#^TgyC;$C1#vBd9ğ %-I_p v6X %9+e9!29,爠N晼)U }8EHWKAV5؆̔oz9pΆT9%&vG'Al%܀c"PEt R59q@C{>Aa4c)#&u鱧AЛl} ^[(?yoGop\dNs5na{/c^('@׆U#عelq)6V%QkA8hiHjO@dVyjb@ ;lozGyTo3iG^~6uSg)()3$Cf5D6auGp@46RS_ t+*M՝] 1JH04ፆC0P5ٖ_AMlד>/,v]km465 l!9~|{cYP:/ʻkuIz:}ekԩm6{NơԒ*&ϫVf,hOOdE(Md8vϘ+ݎļc-ʼnxYtie@kY6vce6%x-TO@1AcS4E)I0kM7Mu%t(rDd9ƘlA*GXr(\B5gJ>\9rcSÿ}/(G!Vrn=eԻ8g f{[UX&8c9IC%€T+.jR- ]z>bOƩ1L}SOZI-T<$'6~MuuuO{`wr ZCb퇢 3h2X.Q F\qU.&(s*&Ćd˕ 0Aι=XCNPܬhSUKS,`w;MҡAaaՏÅ͑E7ԟg3&*%[jT_uQXD.bԠ Z" 0bCLFx]`6^L|ǙUWeÔ5\>z~>?櫍5v\9IQWm=lU*jWeÔ5\>z~>?櫍5v\9IQWm=lU*jWeÔ5\>z~>?櫍5v\9IQWm=lUƝţV SkDc[t6թ*y]yid dkKrs:4Vd@tyA csP5@y Ki}A~\Dkqz4ra»Y{uELN:Qb`cBE' 2|sEv ;3-5}P(W(* 6?bB)Rኯ),5fHp5mggviFɧ͝m.3O y{QEWWr^ تԭ 5v Z͑UBQLD3[pq8vVw ǩͫoUi 9F!oQ0d#8s1'>W~??@}5ng>WY:0BS726N5r1W*]53 =&'ٓ. rl:YIHД疴 jmeYZl1v\U>t_h)τNEQ+lԳ0y9dJ|P&%$3Zn+M(ҸUUf,q v2,%*M]T|$i$ҟF2yDnm܍.}5rq=+xO$*Y ZRNru5Ѱ[]t#0ʏϋT%%AR&B1yGeƱv1tDȸw"'>DnRryYn $6kHHKcS&7zCa7EȎk kY r ҡ"wV$N&e+%RƬfL Iķ u֫^X)n.FmXw2F>ݫ学{B:̅s^ ˸]ZU 46;2N.5)jen<V&,ڤX]AnxK"lQrknܗ$MigeLևR gvӾ( HP5q`?IX(}N@{77 Q*oW;nFS7T ۔=Jl h}$5NŜR&qI}3 -0PeÙ^6>ۛGJ"E-vafdŀtTf'4,6|~J %X-RA͊.{4f]y&+7fXtrɐ7*0h׾\ev\ᩍI^* a[Ee_OI}`GB~n TwыeexʵHbG';8nn n|jJokw&:ٯXwYwI PX5)RMi响DC"noމɝu;#W[0YK,"d3J>nMNHz_0Wُ8v,쬸2(_;O<ݼ8r0-b\ 4[SWe+ǸdZ@⥤J LTȈT/z `9 j289Ue_pLh; ňJ틇*!{K/kʝGe,2]oHJGOrwֈvTdŧ0 Oඥ0_QR; k8܈I?k0 m976 vS=2Am3UM})%#bm_Ife´&d\FL ebLDEw5WM\CoP;6(7mѳPa9|;qKՓQvjfR7pO^DWm.$;K=9R'Ft^A20mW%sGB%^28.ي >@-AHQDN8u.kD{tZ-2Ȗ0,.o)|.FFklf8{Xߣod,VL/xcui׊(WS1}xᅠNmlIHVCY|Z$yfrjs$W(R9F&X dL9K.PjCY?6O1#\ø,K%E(7 |J:F# Uj8 7NY* ʥ6~\KV,\A;`$lP`GTYJngRfվFVO{m{ 6 i]lZUuKbÇ:-xގ8q8q8q8q8q_Z˩gÇV/eԳ܏Fƚ:Nk.hN '~M?M'Xi}:T\WgʶkÀO*=OnZV]ՋYu,@7#uo[ |ZyEeWZm۵W~[ ?MO|8phÇhÇhÇhÇhÇh=?>NWGQ9 osG߱M@-_mdwTԏwcrz_:za$z>"q_zU:U4Qzs`rl䅿TgLkx{+nT{7_Sn v\ptʜbxiYd iBptQ"wE\Ol96W 5+d:]Í4|N9.,TrdǏzR/WN'$Vf;U+xf33L3$cs3㯾.,Rْ|Wjߟ|Yj­ufLut=f91((ÇG8pƚ8pƚ8pƚ8pƚ8pƚX5>%`N3X5>%`N)_s{۩bV?`o9^:ժOOoKYOqa;K#p;0Yl{s_cûSc뿓{E}'Z}<|ْΰ]l|iZ}gҽ)m+ڕzW~ʸYyu~6GϵW,u95n!2b,}Vd6Ci$%$ղ/pv!e,ǤFoRռ$˷ӫX~&}=r`Qsak7.'j~W:~la?󉳿ȺWc@1K,X¢i1dJy*J ԹrVN,`ɓlwj|Y?k;@:鈘{MuJ 5%H#Nb4{MVl!fR["g),:l1B6j%DX>f&g.N&F CK?yEeK j72&cf1 Mrh J A"(DZ9qstC_JF˙p᭰-V !gڭ\1F,zqMӆQbꡃ;ٍtc1j&2UJrCJH |t Z͝va~svWVYiWoGx]'@̗>N 1*7ܣk;Eqۍ3 /Gj;7MY2X&1&ik%aN.BټfqEZmrzXK-ɣd=`*H*?Y&?E#^)EXhLP-^i3*8VrFo<9V+՜J"p(f9ybϲ7_gZ6l36C:)sQm83|hmHHq(cdZ;zLĢ\ߊX4&0sEq.v+SP{- -0;lO)a.KnVAۄ5ӗ*4SU*?_dz&mn8JGT#Y#+X CآNFhw,ß 3#xG+]d0 w,Tu ?13"q'kG8E'#-oy#ە+ȟ:9'TWqq8ʊRN|>G2$RVx 4anM.w=Xϖoo^n+rmǨ3z/[ rLmfi\rY._HKTr)mLʦª]ǀp`-`t(I1 jlq O3!.Q##9f,|U{jڭ)rDȆƒCɴ1F<] nmIrm#ipoQvy_;)i8YI6(65 I{|LAH)-=dF2bX;qw>\@jXk#)1[q!ν\ncXXr^ NmLYN* _YQtBy\24kl1HkiWYQ,6GM$b^+9d!w}3E-VPۇO3.d7Q8@Qk |0~'lرnOHb86r("\U^E++iV+)%arҒ4|"Njq 26[8),0g7kczG"PU`q]L.Cp=͜Чk-Q07+a0lX7y&2iV67pi)_tIdrli"Ug;݁}5(7pffF{$zB2c"ȑU*`Y. s.BX`Tehc2?WZHOCiieMbPlm5Gg& aIZ.XͿ xEM݋RC\jk)z @(Tcbu8VIcr_;W]~z_?⠯YPeJ0ڲ[CڸIe nm~3p9kߒvWET5 ɷZD"T38#%L,)[/-ŌouRajFͼoxAZKg-}ciۚ'Sn#ep;PGX򛓝7 YXq9gikt܌f59#%*+6\`PkV 5~Bf$hF@JW%/!,$qzҫÈoH0Z10KpО@O]LBfkPyi5+p5jBen"Y zGq8v"B,+2aZTu'#%ub:e"HQ!Qb5~;,˘v*b { &ȒԻVҹ}ŪTïUέ6pB)0%͓Xv0#\:B 6n-=ɧ0.,y"dZūb9LsŦu"bhկ0[8_tfҦO0#kNsǍkB$XG[Owr|d7s8צ|b={?Gy/^]Ծ1#NwbnEh˦Oh5F1"=%xVS9`nS8/&)D7c esu37A3{AUQ d*VƁr'86 #ϥ( syJ؜sIn=迊P hXqs!DǕ=S$; -߉ȗA͗خ?A† 9 +$كeiҬf;:IWU4V!ܬ[{⨚8sg#G8G8G8G8G8HV/eԳ܏FëֲYnG#pM'~M?M'XZ˦s4ub]K> dn*N kcv)_m€ع5~Q}?#~][_9̕-ieziYڗҽK,/?5;×飘L#3a@SDZk!#>*_L@%W9UBL?VoÍ UgaUˇLۊPvˑf;]AfY; =oIL8PT"FQ;k56!\YK&۹ E.TY_pqu`NA&u9Y…HP;壌p lNDsj6}v/{%-BMaFeI16m%/ N]FaMy2alUj~9%G ZN=#WBUl G")G$Qu )RbW}]e^i9hك0: ;R9q3X#} jiJ>__B_o1Ϻ߰W~ƽnVOFswͬq}J56\Şqfri̒ƔnLM8BA x&Vu4e LS3pi { \eGS-&C%cKy(hXޟCDn!ąE@q@Kؗ:;.MbƳWR|]1{1cUgFV!R Z8}TCM["\ sI% #irl TKmǝTؑ-Cq+1r]7P .խ:)e'yRmd{Ee/uO'KL$.bzѶ \ik2[b3`Jaʪ'Ò.uwTV9^sHj#fkoG2[+ 9 ;.H~! q:5aGZS2WhvEq.9ěPgђ5sW[ rJ#ֱp{NELl$ad%Ô3?׏UzJf-u eU+cԦ,D)6bVb:zRr3)9gϙ3xMieQWm=lUWeÔ5\>z~>?櫍5v\9IQWm=lU*jWeÔ5\>z~>?櫍5v\>ϻw)7*j;F.Yi[Oc[XV+Mt< fj qUgz4'+#Kq> Mk V>ؙr#,>)<}N>F2ƶʗvzu+łP̟k8.xb==mXT=Z$d $sY` 5Xza]pH6Uu2ceJҴiڴ)ZVҴޟE~O^j9C{ u|hNB R(%ie$fÎqōɍIې[Uk6w”w2RR{))O#v)EIW/8zZ2 (ׄ m 91ょkj*_[ن#ur(HTʔ̙&>f>&ɖW%x);q4jYMԦ>TikTIRt+ %V (]0}Ms3&<5ᅑfDA H le),A(q:D1"^l^{l.s YWVHzs-}ܮZ4;Wg4TNS,C.WW7ld,=Kn^my6_t͋,ѫ tMU&#w e1›2:cVAD͏t1[MqnY)bj\-9ylv qwP )nӭcj䆚9r*K( !Wy P֔{ZAAZJU͘ɒSt̀bebG:JHҋȨ5.$|gըGc"4uJ`apeTk~=*R1R6k3 ѳ@5eCq6G'>\yT2[G[HEJb |dU0*6*5LJ6h>-QJ_HQGc21^xCiX|v\vFNo6y繊 FrVғhY̹(5 Ps%@W*Xv ʙm\h;T%SkN>}M_Oe5E$ۃ&{'5`]1&2$R@CSgoO&"b,*܄Mo+P%Yqb\CFƻ9]4gC#yv߳eǕx+$CgLL1@UIRvw G& _s?%-߮Ȭ}$Hk y$/攢@lI.ouZ̞ۧ\-UZ,I<]ۉInZfZ['֭řoNVjȧPd2UVݪE}{}˩jѕ$&[hjcr _&*B4)-Ň-LإMZ*Mfw-c$ klkЁNdޑ=* Mr%I+.c`,EtXeLf"㺭23 ۡxnD Ɓ3Gc;~`\22VBB̂WvJ)veܒl sqf1ŀ59B-kpRxlpnnZl͒c&&*--Cf_eqxܶO훆ͦj,\f51em&(`nf,~i ֓/rAq dIR=H\S[P nlQ`PP3ɔ6ff4u&4>g8p1Z;|+3ڴq I\^QTY}zCj1 4L\+RYEces$LgDT%3oU،+DeKW৓zG9uhT)s{*Z91E=ҁbol b3yHV@Q˻#6{ɼ0)jhFw5ff* ҶMձM5r{eЫk=vh8kb%jrD:1#20*©ʥFs78]*,waQہok3%t$|e66 i5H=?[Ğ.Q$"EِעRJ-[Mg8%HpJv@^ŲK9m;d+#ŹE)N=ZЭF7w^usn݆ۓJ4g~*T:X%ɋECߛhbBJ'} WY7W񥏣^圍/hy`5baNrL >uq _w]Q KU$WH#7Ν>J4/sȦ Je)gqzgvz)؀y>dRDnH I&Õfaso( <$3fjcB| m tBxyE"'9DVT@E_9GۍJr0a{14zEH%#uX|GN*N ݋K+p<]fO+m]M}ku+^R~_?j}Ç+8q\ihd߻Qb+3q܄Dx~C)5-,h:ax2S:fETH6ɑgȯΦ_{daGHz|F>b&xylsT/&)ylk7%tLtƘ_OL"wk<ֽ wdgZnDh [/4 U T;BRfk%6Z؈i\L@b81ݑrd0&|Zl:ꁒ x.\Q0UHKFͳ#32~2~;?ܴ7SH~ynR>?`?J9|H:f~x%|H:f~x%drXMWݣUȫA3#_g&K dwMriX"8(|SU&8\ /+.,c &BKJPi2I-t;?ܴ7SOg?vO+"L܏~`j}_|H:f~x%drXM=_?>%^$3?r$3?r~b̟Z)=|4<8|H4#7&/KiGoL_{?ܵ?7SOg?vOZy1+^}^-iMyٮ=+Zw֔Ыp֖(};Vi}7VVҗSʭU)Vk]Pv}y>CǙZ9YCdq= L4)TW. XDdN-.Eeۣәlj;Ӷ%4]cdNч_i$pr }rSL͸VhM{dK'z9,=ga*Ekgx]=%L;M)uκVZ0cIP*.C4ap3i#,@ıi9e425Ovi&kb" G-x R+ ::w5.)Fۤ(&Ʒms׶c]bLe)ZH"<!buvj~|X i`%-c5Xe[92r.sPS'[a24TFTh\t7C$SC Ix\"\2߅E dnۘET?<;f5_5V.``'%"^c`X@>s °HÆ^?bX%:2vmx|%UlHYvԲ)V(d9~nfغ$eg-<$٭fH2ݐ˅̛",ň0MkiP1W˛Xvf[#ydR5KVڡŸY$rV  8rV#&U_~5(u̒־o833m=>{^9SY[)=؆:>mRȎ@wV1tPyigI=Z*kX*56=ָ"0-NUGrMi-K'•Ęw,u,+5:.g LC=D[[q7`w-Mvg`qκt)USs55u4$E:L3LV'S(Z1[Q1\->a1(Vm ֯G,;R. $?% I2<}XI/EyL8/N${H6A D 9awDRJrAczwy;"Kc\sV(}}mB&,H< D*#P(2Q o`dw*ȽkFqo4L/={ŲGn,9p9UX{uwG*sn! 6cdB幷 0Me1"R.k\ᶾU7NRmv6y[{ԕv@ znPqr>m;dm,Ȱ{/b5zv!͔mߎ"%O>h=T^@.&92+J4q ӓCr-b!Zđ$c s;^s0d c܎@G@b%|;۞9Oj7j/qυvF(O3cP1BMZ(zW-Uom[(b*bxoY!KĦ" QvrRęǪ9 Rˢ3pu{ŚmbIrMjk>5T|9} MAVP6VklFy YQLkӷbݡ5.yv=r &7$_͂P$#f1,c@DBL'b{$έ_[^P xPѭuzcݷ%aMδo&OvK(]8F+\ӕn>2oK!o`|pa߹"\vGŪO6%+[yguJZY: TP&}j~cl[v#Kh;|Dd =#T-8$j 6{+5q_%[7l׭V;nzpRUB"kpvqA(ޣ|{mSTgo"uVRC#Ln5-Mtf',]ҊRrFÍG}:,{ tճG䍣y2$iΕTK%Y/cjIQL11[rbAFs8Htp$ˊm̡i.*W+sde,w܀Q[G9`Py,m/%Pj `qHg."[ePץg&=!˺37(Y1y)^ :&G" 5(Bۊ*ȌRDY=-zvZ[[Ֆ)R]}sxYndH-\DKwZQXl6K'o9O H[Ve;oiSra}. ܮiK$1wIJ3f<59!_VӥM̌6)rz9؏)ڟ=[BzF.ff)ᷭ#rb =lRfddǻalk6No8M]!558:{jCV`+'.) / _L%1HbN6$=Vif]-I]A54 ,̓Bé UAW V<^el;1 3-!ӚBYuNS}ɲy0L*,RVmgĢR?.\2|x\×ڴamtv "aw,^DV(,9v_fU(a[ qpY6Աdgj^˃sMV5$S;v9M%(:ɫ+?y/iّ0gȰU`WzJY~D#z AḦ́HIi;t)#jucc pSpl;t,FL9xrHH5.6M =ʶ]m=dUĞ޸z9q(l?/RGG=m̭s)bZ퍊өf8pG8G8HV/eԳ܏FëֲYnG#pM'~M?M'XZ˦s4ub]K> dn)F1ݥi[|ʂo+JV)ZW+O ҽZҽb]K) ȯ]dn)2fvVǁL\l|i1ʭk}lvWM8pMIqebr3$x&2p']qK$398%gDz! !@fy*NSq%3Ol!mBE5|gS ۉ85/>gu|;䰑|95G r<`P8-:&1>&'1??}_^$BBC2$3%ĉDLOOPL[vp\<"m %i tr ]>l0#1Lzk( Pre0 ׵QCpL9 3~q頫;,@~7$5H}sR{B wI6arFH)!IL .'֮qj "]11<}*U?I9TԻU\US_o]Z  Mu&yNcUhFR$B'S=152vVld$L!$QDZa)?5RC>1sr/RPODK|15icz롑gOE5m^*݌iaqFSæ.0RmŐLH.W$2#uo_nSq~~v\NNiUW5zi0yvM:?to EˍL(Zyq!Z26! ȍXm-^tp[dИeoBY͜7bى,Foxm(ÌXSiz8 QښA%7"D0j@ɇ3^;U+Y޳2' ' V]#ڢoSeX5f2 G3\LxԪW-cֿFjܦ٫e% ='ȘA ǘ_Iz:6VI򙍖rDҮe(3S乾H)`[1i,Y5‹r\"ؚ +Ć#~7Lm˄d7^A\Nĵv*acbO43#|tXrhAYqahvN5TIm]wAnN6L7i'ڵ÷Z4piE8ȼ9h[}6H}%"c7.t8k ;b |8qNv?A]_Aη_?j?iFz5RqNJI*1{JVՈ.]Sw{ AGYZ,c2c;y/-;H׈$)J:ɵ;+Nͽvl2rR{4 |'!* ͓Tvݣ ~i#ḇQQ-x}11N{&mm7]$ y;-&Qڣ)g 2fȹ6*2uUڝw׭9dŒM9v5[aTvoiN@i "&i} )u o,)AQXm{Br|%ܢX$Xb/O9allNHqa:<{bL]=i;X=L -bFlU͇Zqp+e$/6bcH6kgzIg&Ћc7YM<~FIO##(R6JmD;byζq FPgoĹ$Ўomipc5m"ؔX%֏]HfYM;n4o=3(vtf]U6r9@_`+*d* H"zGSʛgq_e=,ZYS+PV"\-eZba6A2(OOS>vf9|N}P_S|;W}_}2f4o7sI#bMWY/2k9 j)1͌߄?21$S(7euհiE[ܚQ3vQm v"E֗RYm9r-|FhD(3E)ݣq!dH"ק$-mCez}D?Iٓ|;~Q (O;* 0rMl1'E.frV|FF#olE~[pdd+ #Dn,^Pdt3)L[G i̺ u T>!FWyTO/FM69Sz&el50 f-STՐڦ5f%&?Wmœy99%rk׹UoQFZ,٣r@㫘]5Hm80MPyR&©"7~5"sװY ,[5ϑ\ĥzS_vtVuljȖNd|m'^/w1ʂzr [g*po1!<NMwUؔ-dHnT̔29Cї뷨j㳡s K2.x5&]t lxh\kSUTdw_}: e@f\zoa6ƎM:\4yxB\$)VDyzHaـ&K'Y~k[FJak٘N'*2#Kǂ \xͻtv:(drXʷb0,*~@-Z${|rv,M}X;sxK[rm<|șX^KF;~#1)D#ђ$&F8nl:Gu^wڐi#gP'4p~Ԫ#nƓkFRqn3#qFUP*0D z9JtBݕu--a=i00= __}Ib͔1&̂ _/%㗵%R'ղͦ8|LÔo izd[ i$aeػ6iM9%ֳ\C}ů* 13i"0BK>X]ZF'wd^xp†*6lP!+F#"3]LYJ7nܛXd%׳[VZ4n'xEU WUYw2 8sc3G8G8G8G8HV/eԳ܏FëֲYnG#pM'~M?M'XZ˦s4ubeԳ܏do?n*ꢮ vHWȲ!?CqRVU1Y.>]^5XRϴr?'Y7gWl(<)Nzi)Jk_֕k߿j|Çh^4N}N8P'tpGõ[)q 8IKN gp ij J`ޗA9545:w^ƚTTk%}ԧZ/q?Sy''ҡQyucm+ )1|$lb18ehX}2(}ϐ}WڎI$OL\~8K{s Ab:\ @@h-,`TOu$pnly[Rj?ƻiQ?Z/qƚTj?pvܝ#.0a7r; 27?0Jm $^!)SC͆Jil֩꫇W|;|u"J{

;EuKOڟ_-/:>[n;Yg_ϋOɍު[\=UmY D*˶];IK XmQGC !vW fh%0'BƕM:@wG?Ϭ'>;EuKO⟛얧nzZSrq~,k?y{Oɍ޵ %o)FI1R5cIHR v&WIo$i]Vr@4J n4ygE90tyO/]'N=ܝ[uD,%rrĕimė}ǩN_FY|+3Q׷*\wF83*kԷC[B#"f@VHF^SfU*+3-*۲L8L.AUU0ے g.JH-P7`ҦSTzJ#IPWKO!ZU9~S".-/;[\=Uos|=U5SCncc%9wmC%xˌmS{ztn4Hg#^J9|b+]6GSm97So{C骁l^_[:NOם6 yJ3Y&ߎ֙~b=_ʾ39ཬwG?Ϭ'bi/U/s_WwwG?Ϭ'7y*/]օ>F_L[Ѕl8{ɬn2 fo!5 EvJ)^XcF6QؽS?ܻIOmhc5 ~*lԌ1'N J9tq rz%ı gTlI~ yٺ|+N@=)u:J֭էoڮݯ&-J?-}v߻q?^cx>wtɜS[6lY۪{ L#g?lyfcVVusN^x_gʝk0%urJy ˀkT3f؁?r$*sP=xk O@TşЈ'ΑEcǟ˃6?/5d6 Ttw ֚(80-Mr0C|cGa4>̞kj;XژbbPA#AqY@f"͟gv\ msQr+Pdl4&G ).ȉ,a%$V5;b}c6@RS5teN,xA1lX1|YmRb $Y e :M- {%y5$Cv 5EY.bs` ]γhZw.1⪆ʏS{Z!`(B(5'>@>y6\U̝ZDȅ 7qHj65 eux)4*xUUL:Z EPRe?B}YpQ?+rf+Giީ6WLinCqο( e"lk soxiXLӑV&b@LL2!F՟YSw.8u0](hj 0ztody sH8ԁkG'B9ceTl7gF^_L]tgJYQ٩.-'P)2U2+:;MМ %Ga {AsU80́-f"8yxMG-p"Wl<`'zP98F8-T x-ż‚/\Bv"^mgkKϺ5:&œ6TiHlȰZ {^kc5! EBXu+Py(21zs{]65b~~q;a\Av Hs<Ȁ$HIYkln %'iK&)~ʲG)֧q5/=*l<1(x뇏+̫]t>]X7Y ´T0(LZ\h³g-Uj13 |ra˗:~!5\%D?b}UOE+&E&hU/mբSuIC2n@A>o-2$oH\.4TJ ![_~hjܮj\r'ϕ˘Vոetr YL~Kq^^J3>*U/sU*2VOXX$D`ӏvvG8۽Y,^cΚg3*։qzF!]flT&JA=GI6J7`E>߲ 4lQ`GSQv Rzv܈JN ?#߮k(gdEs;!є^%IZ-ڸr3 qanM%b{HLH `tcC7 UxG+Y\^e0E}2a*i jLCM;RC36ܢE}VjpgYRY_puidVC4lLŒ )eEd=T**Sb4yS䲕wд(NuPw yYa~si"∡ mfM_:.'PmbB8mBV.Wkbr#JI an3;Fi;Xco2zq6 $/V ?ccTӔ5޿ID$1_Ƨ~)E} .*TXInݒ\pe2GI JϑCE't٪Job[mv Tꙡ$%shl|KkۙLjU;57.'O7MqLߛd,ڳ(䳲&쌆ў!M^[-2rɖd.B,\L%n^rţloոǥYj'@ܑEluӰ&aj* xUuΦ<2"]JC Eza.q8b {9oMy=rĢ]%A2F;XZӸ\/T@~mlR3U}D.RdW^^lH]? \(G2ϒrIǷ4lk{3x(Z({}?&tYfu!);_X^iFӹ`e%nnb[82u$Mb-m.7эkY ]9 6{Fi3Hka\FiHR58OBl!*Hs &$ْQrkЬZ;7Iprw_;KeONB(V [Jr:A06Q6B\xuFjZ}&T;GlD`Sv"fF 9SZ=J͋qv5 k?;C{1V 뫸BP#&['Xj^k'`ʾ1Xl6 y.@(rgXkRS\J,-voe3RNHAi2u'؇S~!iɝIU^piE n#2lXBH&ƕv"w[,u;%hbgsz$}@+mRУ-xTuT-=$)sSxٚʋv4QKT[ 6tkOY.i7V6l!2e,y]-.Bz WKǥ. ^vVnSȹoRbkQC>38fگq<ʸFbNlnXۗsG&?b}QdܨK]x7/la ԀuCf ?^J/G_O7SPuyl&c] uʙi!r 1m;H632CŔ*['Ж֮Јb GV$S#&|9/Lz4ZJ-p9HB>is_ZW-CG0 4hlqT7B{b8A. < TM{[SUAv;RWiXZeLfJDb.Mn}Z7|%f`.# ;or}A۷oq+7ٳ) Vŋ.u,S7<ς͖6\cJ FHјqȡ 뭖@1rft:ɦ6lѵ;/9D ,<Ê|wW$, ]nb[YLTpfMKDO//dG (8xUsfp3Ư"+5q̑vFNHx#GYrV&w:GJ1Vu- 82׈EMZBrB8+U7Q}cOjuET?Fv'"W(+O\cnVSlvT?G|!L ޭy=nA٭3}9+ܡ^K fsoD9 7Y35#58 2(fZ㍋`@IdҮNwkPihENPR!ZVf&ؖi=t$(IRU¶tkOY.i7V6l!2e,y]-.Bz WKǥ. ^}Ebh`ǜde<vE]`Y;;ޑ>esČmq;[LNȎRYԋYr@VdZ'>J+F2S7Wr}~InqJ'\n+$-&m[-VQ"zԟfb$I A*}~?:ZU|"ʅZv N>1.[X,j\=p VQ WO0p'lm֥C>5RlXXISArpo'Ǫ̈vu3:8亄YV KA4 _q/(.:$e)F^^ir8d6 dn:}k.h~N7muh;io:<t]4 7c?iֲWSsZ־*:W6巶@Kk[*}e㺾7[^j}k.h~N72?uqlv~cHRwkwz8q8qƿ÷߿ۿ(_8_O,QTv!^W'VW97Yy}/ݯ''Mi/O] K{|>|c|$as*cS8U9VmZSs\wקLE;Fn\"ҪИMr\4نʬI <ƨıٙɉGp͒62T6}M ]uXrN_!(EX*uzFVMT.ONPLLQz+ ְG ͠$~LqahA~…uzѮ+s[.TU1O`O2],O_3_ؗ4k8^(ٳQpކA B̼kwIklg"zo?ℛIY I5>)'aHLݒ hp,E^)mnPvi^Ls19 "5"۬ɗ|ˆ~뭩 E 3 Gr!tQӮM/P$RTE,A=w15}o탶P=~̚JHI6Oԍmr5)% 3\ Egd9013> bu1'^%QH.t4]#<]i]|8c8G(QP4tɺtf:&;M;ǓUy{}={<>^%i۷S4&FM_FM_.ˇj7=|?7=|.iMDo$Do$q7˲ƚFM_FM_.ˇj7=|?7=|.iMDo$Do$q7÷FJDҴzWڴ^է.]%q1Y3A lmr4ב@7+}+žh6FleE'u5\ͼ˒qdeʇ)Pz}y/R3Zs6|$9p'z5b@l6Ê k[b!oA^X,x!0( !1?n1/*|4}6: `!D0cMxeHE*=Uf46;*Y-B9MSt"Q uI0AYBA/ ,=H0E fQ̲ 1r7rk3]8L)9!S%LS.gvnz4R[gtEH9%cKd NnKp |Ay ׸7Qɑʝzݦl5T*Z$DDGJRu$,8d0ÎmluI)LdOB̦nlQc VE\ncKo!DF̮ɀp ARp'N YrY6|yJAl{0-ǻ1ʼnnvlcwU+E<ࢁD=J ;=,F=p7LFI{nOep)(;'2ZΫF`[>6squ 9G)* 0P ݪqa۷ؑc-i ?v.{m@gLE1yNsHfʕxoNѕr@hS6MǸlglmzijXUXu->}t PF=Qޛ{ۧwdw-,^Gk} CcصcooݛUk{ ;޴X%_ݵSL7IWml/ΗiOψla?󉳿Ⱥ]/^vo{reNSlv|ڿ<)Ҵiڽ߽q)a0Mu^6EںugBK$]MO[LXq/~6S-o-1ABr)=^"wb͝uAKGҭ ''v:p3ˣf4}ziѕbv=ތ\Oܿ60}@]lÉŚjq:ƹlbY_ok Rvq`;HY@.b+yƬtJYL,QP Rl=]zdEAP%`=Á%J9v},G]0ԕnʂd*[g1tN[ik %:su6,;{ lW&&w.:&eo"(B(EUߟr5o_uf+8T#S26*6JA\K= jp9x{5:P&b`x3xvtv*Hl-4aO1ۗ`23s6XH(\nܱX-R-HN]zK.j8VIA˹L6>GĤB#ǓYXfPJmX2helN=RK^·9+LDSC'ƛVدK#v9 ~͝ͻ${mT*`r 2|M؅*z( {Dlq[,Aٯզ[MKpW hvLBAq6mvW&!EVs%3yo[S,ÍlDDQi෎DT(蹺ܠnʐorP5Bڪ.` ebڈܘh8ē֓} }/;e3Bc$ߋj}L!ԻC(^oDPWj{r 6Y٢(3rA~0l#(*s^ ƭnKK)rs(5v{tlhHTTzrx ُ' D- T]#KԌ\4ɬ@#Jʐ ^Xfxzx8CzX\;'Ӎ9{UQ3\Db(%S 4˩@Z˗ijcaow!ɡx2WoќWdcp941W]1؊tu,Mh]|[ic3fY:%nwFBEd:eME, ) pu,q獇4&(\W 3GeCBeԷ6a~'>fd1"k]|ڍ؉5sŒ jtr[8F{.es`5>`vm 6ʵGZnUL a(u]s[RxtYNTX 51cU O O;mq{k:d_Ccܻf)V̆f\Z]Pw* ϼeSL~3.5SZUPP#"M0fqjXnLI$3Ǖb{2RK[=j)EVSQ8uG!Q҂E&ʱu["8 -^!.Ŋծ{{ 5U4%iGK\ &[2ue.kA9R.gKc 7 Rjbś(E8b~>":%mcĒS&N ADz'{e3{lR+z/wf\F>7ĊY(Yf٨ MFal|Tqt?X1<ZE toһe8c3+ŮQĪe`EvLjh-ؒpE>)7šNѨ7%"] x =H$yZ8jc"*A^kZ튎UR+"  -&הrັo`s}4 .76@up96&F ZE +yGIZ3,E/#C‚j6K̫dqCLW1`+2z#Op=ea=,Hh7-2c4(`b1">@v<(UE^jݎ>M{& uw\faV/>ۦ&ZT MNδ]5n,WZ"d0p˸ qq=eB̂@O$W&;n*lDu':; Z ._6eblVMxfcTˍ`L(x0f(q,b3k:zF>4ԙ=#/χ>/bG.iݐe/i1yH u#azP˟$=@+>&[3]Sw5-Qy͹!>d r&nMH&);򕧟 T"E L \r *&?qQڿ۾{.8#1P$OF^ y=\kz.,ko|7򼋩F8s!v&ÙJÅ:dfϟ8RXÊ۲e͛-魳,v[u/e}ե<Ǽ)>w;M9CdKANbu.}3۶ hAǴ(Gz^ EzZLw6?SO4pvK&$r- RɈuCE VOa6D"\ϡ!Y+2Y9㉅F$La9u{NE}Nl& $.EG+H6͸p?O~4Å}g۷ۿ~Iq"IJ"R\^}٧=PUp"t6WSՆGWg"֎SգQMIaHf -/k\k~y9 0eΧS q9Cn J,0@"X%I@Byœ-5 ا$%N/&kZ΂72B(sjěʑh 9h@I5I\qysڡr\yH稾L0G c:;K;]&l $`!b ͤI66hyNoDW'ȹm5 AlJ.iJV422 k+94PnTfNBw7 JFV4syj[Ⱥ\K©!ZlY #K0IL%@7(F,)cĹU_m^?k_?J;=47>k&PLy3`uNR|= |!O{K{6dviUPrQ+HDAAEΨ)FKQa~6:HvshZ@5|cSE~O;7;ֻɆ4{_u2VS^[iuW֞M+miu-+NNO bJWsNܹsu|gvleOtݓȷڶVִ)e+{[Jxqiqztv"a 5&d6qi\,L1V*i@B%*Q1B:~ikYAof)A#)seTqeL/^-+vO"%Eb6 9j&e?V&<uyV(۟<6C,:)؟y˪mlWgRalS$!eP=<^#щju6U,AroYvyITajNŕg˜d>5o_y=Mb~ke/LjAb hyH(Aj"ϕ=d>DT풢OA"Y C&N12P<΢~wrݫ yuZk%Uep̚{:]c%J$X/Pu)8ؘuJ>9, dx^FJ73c*r.0A7*rW?:tULDxw~2DX˓ݎ:Kɒnt%T",G*VBS[|x8*bf-X0Fe^DBΉR/ıUr`ľ()FA AfZ " "ZP Q5g8$!F k$DLX:'oHq@~ݶê~o&vY8!F͜s"teҩ2>nejF͛s䉞t9&t9U>s_%.d̐L~-[dvT5d>)n$|Z3!WVG$^-'dz}XQ˧ZCm ^4%eV.W BAA$dzU!t@qƣ/qn%iYʭf,)tM(|×h-(8.@c*Hok3 )cѽF$fZLߘK"-RETeYW9L:}a0e;-0 R3۝ԐBԣuժ(%[+THkS{Ñĥ 8ꄔb䅉L>d KDGF#g9NC%YTS& KbN5 6R_7sLjiXxI8Fw !ހV5ۛbn"xۤIq F644Em:DEPlaE&DG'NBɒ }*D͂OХХN 0bcÙLF#ɀ"qD-S31nOnpJʲ]4c(RUz Z#嚙9TL" 2cXMk1Ff#"ֿ7,2g ǷKU1BJxmz5*SӪ)KǞN8rF:8pƚ8pƚ8pƚ@:}k.h~N7XRϴr?'Yh;io:<t]4 7c?iֲY@7#u;U|t ҽO~M;S׷zּozSRϓ7#doe\87aymu)Oo!E_^y9_j4;1b~F|,Qӵz=u|+q7AO-7$S\¦{XO\*31ˁ+'B>QGQԙ0d>Gw69lVR7!qm|b^P`E$ʼrWNhSZzR#I*q}f$`Dbdf"""9fgFZ-)Y0Z#ce X ILđDLF6cY3$Ż={w̱+Lâb$X6 Vv8av$֒b4KO!A oꌠsYwbm:4tEo,5:=7ni;(o.Ĝ-4Qq lکsR8vLd_S͘y=HJyZ 9i9\Sf GN,C>pa}7Fc3P%DI%2u^R?>z %/QvOl?qa0xB; S⍀4ܺ|MVK`ֻSNkag> 1Fm'])nedWܭ{lto]bXw2fXgnBN4 j_۷o^9ךQڿ۾{.X-j9`jPWTFTqS!XyoǓ~LWy7ʲ컽Vͪo񯇻Ci`ic7Nt J T XkّP ZZvCaYTfKb"ne C|V-1,_aui\l D-a0k2ۇ{nFژŝU,۲KRR,ZaJnۑY hL\yCsoi!HzqE[&F5/>nE>BmčMj|?iʍ!ngB]f7XvaB(fzM@W(|q"\I"Yy߁Sȥ)N)gZVz`ՄӳQ4nITU2,4](Jˁ.eM lP߇7?z{w8|<4QEhI֏]<_%?_#}ii%}R{%!c9{ɮ_%Dnp!^EDle GB-~: Lܴߌgwo6YQ?MR~~ѽ#ȮzQ\>U0ey_:)3L1ӫt`3㭐1]A27GD93lη'p&ô0+.A'|ʍpcc$Cpaf1^O*k~TLsI{.Kr{4čD]Lx(@"tPx+^4UYӾ P).4a HZB0s{^;kMjs3¶c]dߨ:pg)y@_pq9k9'so%W c͢z,M;G S3gA ks6"h=8mR "jK%&Lb8jڼXFs)qV'KPd]Kg"%M\θe> ^l1XP]s1Я>ڼRK4ly6.YI1dC2 go7[K&X]уܸVq 8뫒\ʖ֧,ӰLdLA<xٛ$O1?Q~FsL b̑2QmUX*"$IȡRYc6 wϛ%Yu[Jɐ7آ;gkK"Jӿ*k]F\Yɇ7ݚt~^F_D׍8WT#PV S*>{+ۭmx'fV!6YJЙÛ I*vZ(|-q{.Ԩl"{gs3ZĬad({}r卷'`@ rp)&b.K'6!޻Вbb0|^am}3يr)6d\6tIUio1EHy8[Sc5JܐMC_Wl6 oDn֖WW:mVۑ~=ݰyW\EAmR"aeeWT ٳ5 M6N2v%d38Am;a(5p7%ً÷u{kSX^湒vG#o6~fy >u@'8_梐gԷuqؔnG_`K#c]٭rbXL.Y &tשE+ZBכ#au8C@s9ʹp.ѫNx>5M6 yz#0 8Y7PF=WL^ڊP潕Y'psU7aFMfm;&6;s;CpdCo]uZ4mJCps8KTv^{i92̸݆*$\.p;5-DaJ7 y;fƹ v#)vW5R[*c? ;ngflga&h2fxYRlHNe(7)C"g2nfZv.c ~+FgXb#W bͣo(CIߔ8HA|*D&#\jQ*մUOMpua&*rd߃,E-ݐ420 ml-y_ vF}')RlmsbNy*ȵ43/֌D.<(ll\1aْ6/ۉCOl g 6Nܗ[-"U?px_vs-K1^fLt ˚hXE "MrD1^:,SZUWbqΟ5e,vʜFrVFn#+xXLOE!hOpͰfub TTcrc6"e^ZM?[6+@[O aNcF&*6H/Lh;rz1P+ɵ ū uĕHǴ?1#k wPz[*v̱h۹ 6d1IwءF-8a6%Tpn3rn59QwR$9cT^E擒~"?mUZ5RZ\zRrщf39'fxPf/%8ݎnL 2D F &"b'Çe8pM8pM8pM XRϴr?'Y_Z˩gÍ4t]4:>>>?~_GZ˦sƚ@:k.nGoF})hr:7uk +UP,J Ժ&G,,8@^BZepWd9]3C%B%c:5&a3eqGDp"uZʊ299IE-Q橷C23Sԓ*S0'MK4G K42<Ѷ'(o>QyD'*ƇOlxLskG<9'Ϟ'1ҲmiސVVU.bOoҽ*NEYo|`x׌m"mb'&)RR@L.(A2HV,̄0裚cV]Ukmf-aOP; tc˪)JғRVէZV'nq||s<lOOg}n(lՌ5X℥YǀQ w9sנ+O~=Un-]ZRJݨߵ=`0lr}̢ լB`LJ@+L @@G>xV߻tm݇[9_)oa`Yo$y+k\v.ÎՃkޯ+qMGi6׵kn_;|44ӈ[SpfV|s{=OuU^ŬOS.vŬOwjWޔzƵp<\/?ƹ8??~J>k al*۶YQDDzS|:83y)Kif|91_uf̗MqJE2{_^Njq5`^Hg.%k֨NJʳߓ@fEO~]UYX+Z|P+_?j| Ƕ˪+ޕIXiZ֔Zj+_5'"J޾b{nX4&cȔČO9l1l]b66l.,V5:qDs/ũ@OWvðncjvJKxCgsf ܺ ^6)뉶&n)([}خ䳷p%WjʲKޕiJO+sY:!3Q?C* ۆ2e{^k&3briMVnf|qRX[z1u4ZU.}k^B{R;RJvj֯+}"l+Q2b%2r2Giy}W;w-eWۙXd6慠-d,.Zs6Q^$P+J& ׮dkZ 4Rч^iZT+۩xҴ+Ϻu-jRJiִ>*4O {+ŏ1uT{u{Lʭ|׿z2Ɲ)_})_zS+۷zsWg^mGf-&޶BK;~wzmR}>?79ĕO.BZW{_Oike{u+^¼Ym ǶeZRb Sޔ Rc{z1߿S.^Z^ݻ1n kwjuF]ZS应ew2۽+J|1kjV)ZSڞ)+_'SVVX.)wnn ڞ#\|s?Ngq9|̕[+u!Vkkڷ|cOWmQnekm>]+e>1OO)qenݾU^ޟ ZJx(4;p2߷n Zޔv~(O 5{RgcUnwb+@JxxvWiZy=uVf-`iw]@||;SncWR@Ubi-(P;yX p  "1;k-×;nKd2hn=ffŨ`},⫺>֤mcjÜqhݙpr,Nq*,'2"SYkA:]k(A YU9KY25Y0z߽Pt_r!j}.O0Ӡ+S.ԯzW&=akZSi~LJcT˪ub&JھW}2叻'΃cx}_yOs^ƒlʅŚوc lM`MZ+|?^n8MN!lXC E-"]4'6 ߨ:Uo:m{}ts8}@F7uVzn-`>Zr߽|kȷ25,QnִKTL|uW8 `IgB[6ӷ䯛]^Gf'jqKrxɇ;45m-6!.^1F4HCΤN;Hƶ'dFjJU|IwY!D,\FH:G B "D6N"\NÎXmcx2Zrnk[imzuV)Nƞ}=֟-yhs~?67G?ck\\X45ܔ vo4بE^9frtܓ6تARbydH%n9@Lj!a[B+Z{N(/7/C! "uIdڨT}bT٭W+KUϝ h59kXy 9,n;#cڊ8MZZY "]ϘO;흄[zlO0g~mܘ9eǧhaOMTqdo?k^RsmɒM:\p[10kumAӹ0n(efH%SI4>2۸LmŶc!䲿Emzit<WӿU>ckdUZ-L.3r\_2/lzofxe ;_.@&Ȼ/eOZndcH,Mcm5]{Z L6;Kxiҝ]Y҅xㄊ ehEu+иKũ>ɋ ekgcvue̾ԖbkfAoLbȇ驛ihUnjXdl/{,7AO=\~Kb^F5P&5=_Gb~g Z?'t7tm>e&<-r s<1dފ'ÑY6[ΐRili3 M׷p}Ϥ*){Rm:kiȴMIYDi9;p)fSʖAEsU;B!x=\djQC`V4\`8gE'&&Ǩ8QpscbT%ReNS^R$e.^608a K4|ds+x2WˑșbW 5tAgNBJ#slg͜_u+EpNY9%]MU\5"5BHF&r+,kߙ%ۯYRl3P]X2$'^b۲T c-Aʛurx8"WB0 Sώ^5cu?8g.sl&EK0su7`62Zbu X.Yf|zǘԟ%C1iK#[IWUfrf&IP툤HO gfsCo;6_ש '$5D@HսDh,GF[s(}I`'M8kǨ0vEJx(i76+2km``Yœp&]n{9\>'1(-xFrfc9;tbE[6Clw:|aay!h9fƋoAPe{ P"sKEaTqrzRA PT1^HÐ& eŸQ ^s%s6\x}]u:+)xMf͟dQ 4○mо >2t6^myi#AEKl-o8`QűMp{c4VﳀtHL3̣l$!Go8og=Au<@aͳUES.c7^bTjZ Z)g+ LW[0fASm؍W ٟ v"DREa9,bu,PȞbZ UlҺCr tcQĎx`y|ireX[}[nn-e2݆bvg]0D\p &R<;`"3%]PsFF^5^JHXvG[e)ft?l$a;YJFCYc85(v"1`^%MP r#uMd.F^=uŷ4 f5يr&qduv^4b5G.o!ʅgg7*xXKb˵uz_KFZhPAp V߮6OL=4^{k/1 U3i*ӷߧy]ݫP79g(>6˳6fPdp'Z $X^ġ1^ZHSVIB·z5}78ì9X˜ltH{ Pc tRVv5ZMI-S pÂR SMR8dFȳʹVJ  4Nǃ@o'zLebVAJ+UMIβZ$6P1̋&p vA; ,C;1REq`l[;4ǺVwD؀6Wc[-hdDD,LSwc]+x,un>rL9ŇF]F4{/*FYR9-A7#8*'|qti=ID$q2l^Cjxgj2dpѾNˌ%1]`Bcn /Mu*t`-ZQK6=1z\9u 0oN+ GD=1kJ`O -M/hӑhnJaHس>b(r:1J$F2Jn<먯:qd|΍[*#w/\fN2S*A{O WY`.T1cb,B"n?J}/mV*n|q[tf;Hwk;bsS8+V7 gSÇw:[G8G8G8G8G8G8G092/fVQxSh}OeYĒgo Bkm.)Q9)u^*wRV֙XŃ@-Kb0`800( !HjUQbvjʮe{UmW`@XC@(Ŋ` L.Y0\qHM0o) .ĝHUb\$XN!E GYraV&ZHEĬrYGϋёMI.*eEG+{.Le}]ȥ F32%U2+#5l3#2$gz*_WuZYpܢZ-n4XBpuԯdz5B+;MuגV'nՏ]0К%***LNW~ʮgYeSGfXq:{,5&~Giĝ(jn#zk @nex:0x#&TW9k1Xċq$Pd,\ %ICAO6aL穿w-7$7bFf@%\u2j,Օszd*Ysт+wWBj:#t2ɘq TX&t0Y=m"BcB! 9r7bK40^ F eykFvsf͉P9iY R *=7rأS`rZH5B Y0X',൒;r>Oak;,P4nVQV}K44!9L~us37a;!ұ*båƸJ.G1C㖶s&Iة nuD||PmeR RBMsŅZdpPJ#*l^:zhZ`-Rb%2R:L ď3L['g3yKyKn]U0ZԼeɧ>T,M`t0f6O-&#ktl(ǎVdoF3jujzZGl4ni> (ׄ m 91ょkj*_[ن#ur(HTʔpxbEX Ӯ2$DWAGpHLǕ17eּL^{1e M ,N[*VO aKI5AU]"!{ v -Ud& 첋_x#l4/blvb=98KL^]U81,v+@U$`F9N |y --F;.n8 `(R B㤡AG| La~VIgvka3^=i=UI&[)jf4g$V%zt\kD'z b,βJni4vԼXs=P#mt̥I+U7D>j|s@HE(\V9 $W+%k.fREޖ܄TUAiuIܭcqBDLDUDDLf"LS?9$gæ7fb DYܡ*̈+H%}q,C XX`nbQT|G#X3*Ŝn5X-*րF i0,\X;c %9|q}[";ݝH]bڕ>÷8|K1{p_&P]TVl_iBBSYHD+N`:bx"|8Kuϖ^f23X &5ޛ3e\Mi. ( Qax.@U) -\D0)J5N\Ȳ1UFmѤ ,&yf 8o1Tnn,Pjze@TCV#cvexeI[8l>R ["?G#K;z_F!:gNp}F|[r͋uHl=kXd=tL{3؅ʰK#|Mr5.HABDY% ˀƠ}׭W5Σ.[֗N b R!f#"!CmXM˔WЙVc±2EE29btU&tbu8pXa㨑 JC,Ḫf%'RLqTYmM}庐Qzr[8i VÝtCO0@yrڰ%]g8t;yPcL۩O#Xx  !ƠH Ç%KH RØ`1330 1\rV[w#rۻa@c-{͍ddd@Dc8pG8G8HV/eԳ܏FëֲYnG#pM'~M?M'XZ˦s4r 1:FKhdn-${r q_8cB\6HJp"tj9]V|95ߑ3:yH!7 aRkouGێ3Pq7`JE& Q `}k*d҅^D5&qlX`˖sU#%z 7,KXn& i')$YwR vUz٘Z kp漧6bzmًl}J{#ZSǍqdc>JT!n$,N9"䕹9-=l/6zHjVu+Y'b"pu͒IN6P9 V42U5r3ˮp~v ؤ @FEI6M Mʎu8c])_fSzpf9s "խɉF?pco +#9,/%M\[5@Zm9;w*ArWha-CvT93QŹd,` Yc-z}k2xF_wVEV(Y ,[6lIm ! Wd:\W73c+/W+%/JM59R~b&8b❋d|#nlp7#v A8d <ˤR6L-O.6ltg'cqVO9Iq f7CHDh"8aS[`YԨ˂h^ᨈ^c,[<:_Rep!}!dQY{3)Gr68ehՙ`w:(bnTzK/xJm&ZUTp?mK\-!q9)32#11X2$QS(Ŗ?MI$^ &S6ȊSI 9(bg('acJxV K2kf1]^=w d~9#&d&qD^fȚɤKӏEњsw۲][8,ȫ+ղM{ո)\;Lk$3ugO }'DA x `i?rw q70 EHγ 9.:F(L@_0ϡ32 m ;McpxCu3QSS!RUa|IFӵ띙 HInyˌ!TqD^ (ŏ`͍V+3YM, g`}ag`f)*î[Bu6NfOяV')p*ա7r ʞ61 h(]?V\H4d 6-3 zܳmm>YKsjew?-8ױJ2[BwCi+TRJkaiR39Y(BIp,*`=r"7 RD8Ye^ ,J,:jEaDgLѼbеtz}k6LZ@ !VkBy}bǰnjb8Mk+S mJ;0+3 Opec߾}?EVd8[L`h.PY]mvFuS}ǽ/fZ;UNֳ4$:n1?2ashm YDL֊I] gYM ~q&(~ gemtz({rIkz0ƒSd;r㷹qUt.ݵq2mՠ&=Nm5ȭȀ7WYȃf2kV'm͘ceVEt=qZc<zȡ8/Ε$C.HzLj2+2i&b.gI=T>Ҍ/,7C&’ Ӱ3κH[<5'9=7]p7A.>"=a ljD:el)#^=2y,]SjNg#\`Ճ+vosYs5Y8YuV͑#@/hfe{81tuRD6,*q$l%u8جSR@h:H"iIf!ɖJSes\R3}';ScKUƤCL{]8Atqι`N`5RėS76{iښy [xNRiT(56 F=E; |wh .1uoJV%.tQsX=TDM Al]>~˜aŽr%i[VW2A(~' -ճq7SfMxV|9f(VV`oxN'EX :tm(D&\gB5L &Cݩ|\ܜ"\{Jg `hbfTeݎʐ2fu)wi7^~rv+(k•ƎI T@KKdBX.7D6?q'j%M*۹a]E]9IwhS} Xſ-ZfKH3cxXNǸ&~'pZuhiDNFS1=W 2h݀YϷgE%pb[%-WQʆX[_֬c+tY+&[4m8*ީO[\>3z[ُ큈`ukKfHΫy~5CL͈% XE+Ū?KT̀~\VJ(=H;ڌU8;kS42v8%#!q=Vc *jFtߏL_ΖVE]`6qN@BR?t0vIݥJ $."!8تF<ܶyl*6c هq, Hu4Y~ZČDM[y~(Iemcc쪛fJe՜PQz]'jn>OL>l7=kIJI31sI{eVHh_DHȔ30^K2cq%msWh53iM& \j[sLLtِSF6!.X rL&3sU-έ]]';ݢ4Ae Gَ kT|zq[-onqdzf;_ߤjcbڧ!rRT_"TNÓvr:dNn$IG &G[5Ak#hݍRd;& X'j7[Ӹ(;YpB;[&SNk340JZЪ$)5G/ frd{l$͘$bv뢌Ml.j]z{0s1ݭ_\ߦ2;~xm? 4EP {!\c\fDv\##8d%B@%b!{*$㪧ϴȐ"&JSxQI.R˿*z(pd1aJmc>Is^Q0#*ٸT'XRVeɲ6vsNGc9mbݖvbՈgN8WWǬzk7 ܄eft1,ېn%փ=)%ٻ%r7; {U$kЫ]D&Vh0M|w+uSx=7.1N[nm}Njʙe1mg\TNLOBa6̹JL5d7<> X{&&fPV\t3!Jla\Q2_͊l:cm.di)VTvj7-K$NJ4&)T'vo= i( ړdqe&gn\(FY ܻXϤʸ( MβU*,{''7!mY>s2q`o:sq7rs.J;MP:m̤̓U鞄_RЕ61O-N$^[:Qp-hI6*s18Zs·Y|ؠ)ޡMM_i{kn{p JIn$ Sq@:/O1U۹5(mPIŗ$g=[ו:G y4_%zd8D;pnu7vFq2=&UiUsMYL{c!ȩ6(0N;oKYٸhE#|⩤Mr:QBH&Q"m#Y; nSyJ)E~Tn 葻էp֝Q4!ۉ2D=qafq E!er>VPAZ(p[OUL?-5hۅ\0N!qu8Ę{)<ȏV<1aw0ù骞㒷;k'(Ƴ zE:Toa{6-&^W409}1rL|ύ5h|Vees^j'bɖ|x ԗ]2⌶1kUg bQ:v6{+Ǚ/Ki:$J8TF)w1 lzY1TTM'k Jr(Õi#n/!dJn c`A%17{:ouJ܄ޔ5- 2 Ezԓ*6Y1\l(~KڻYZH[Tr1f=Ezu #HY{#YYl.FԢ :$aY(YȊU`SbX?S >y>ly<|8c򼌸쾗[OC+gbK)<ɗcM[9B8%TtL1Hw'GYt˳`lCYHpp\z}ېjSMIÌysh5Ff6^̢3J1r3XLHS gRv+E<9 Z*]#w-(J\ߏ JFMŗ6?G)Km-Vֹ9eYB\XpN`5?`1sz>SN-w1/2ʈ5c!1A^5ڧ^n+zL:sJL,fiÇou:8pƚ8pƚ8pƚ@:}k.h~N7XRϴr?'Yh;io:<t]4 7c?izNroVY6^FPacBg(d<4ZbU"+z/̢.9a-f@F2\,D |IL}cJ.\ ju\\&ڐv*,^0 ֝9LyM  0fE$XȘ'&oWbj˓6_G?9%/}V%k $F`c<LjGqFn儻6RN sZSL()&Ka<s-L {Hl* ʛs vA`T-Ê.2" !†bL8`)qۉ2$•DcËَm)OCuK@D"d9邙333ǯv\Y5bO3x땀F,[@G 0dŎMJJ!3U>_\˻(bHXFQX!,AD[:.?Z|3ŕJX2Mb)LTʑ3̩s 9Lu,@4R+5Pޙꁪ[3֩!yPܝ(=/ImswҗPuq8%O+9䥬F ]m,߃%f.fAi*lZ>izlS/mxrHʗ"]0C 2%DLqq<F Al[z92KBŊ+]^bpA6:Ͽ#1..WT(KVTlڕ Hy3eEvBzz$Kwf%S'}Va7V Jzu"FKx'*7rDbOu/:UpaK<OTO;r_m)K{DY ǯ,m\&8-" bc,O=Bs"jS.S_R,S2NS$ROYH ts3G3=<jz-* U]CaM)8K!݁>_3wH|g x;J2/h-|lǍVKd 9S"!d+q"]~;fo85XLWtܩưrN(*o19,bȘr Z m*xn]r&Rڛ>~51p#_HDG@g&l#.>3E.6ױ=<2mmzY /,[输emiKJ9 T2FR"KP^#:$ن^tj+dr[[qZɥ)C ̊2CS1$HLy|G3yzE`ۖ s,a*u9s{J4b k)1lkc>eMeN*'PBsKL9 H&\Tm]e/ۼ*\xʨŊd4X,DłB(`AAO#DBXI2Ð& (؝"$Iٍ:TSǁ2lYmm::ȑq Kxw'XWqU5Ơ5n[oSbۖp[2t#GGLD|ˏl5dp82&Aus̜3DX3$3 Ob27ī\M&;)ydP=Ѥ rdmSKin T9E.a!@9#( FЧm@n&j#vE*2\ k~|-n}nxrJK K(.`30Sy y癈F%I(~$U@HJ(d:dTD&cXr$VkT嗪nP `"2;uS'q- 5Ҭ}" 8уLjD 82V`ą>,i\+~;1R}9XX @LL<3>g3'jVbBAfzDHF@>8nҰ&6~lm$Pc}5+3TKFMh*Bd>rd3eTݒuax>$L9d4qz/ ƑL碥_R+J2cܹoam:II5D1j,W˦bd>xl<; ,A9 iUk5qc%J!{+_F-㬊g`G KģK9KR"œ>r p'U IE|Ŗ֖GnE~&+;(@:m\= sDPҩ)He WH-ɒ˯U3 L,:V01=#qL#?DϘ&dol=m7`^w:͐0RPGˈ!)`".DSGlTQę04bȕ]+*M~1݁E.Og[rҸ0֗wgbbe5vRckǍ%9VXRhWd*_%Nvbaqdi9<ٟ?;oO͟\0~3O1?r#[qx[sUb<8]CT]s"q̑&S'_LS\=q߰PD Mي|  lv2cNyvmU`ʦq㥹iK-$~VLPFcxb"|DFg.kW$JYJ\v]ks 0fE8PZF6È#`kbA8ʓǟ+b,Wؚ+gjˀVjbD BDHbab!01F8r`Ç4Ç4Ç4ՋYu,@7#up}:8Zi]}6K\P{@:B8\$▛Aʁ.%*( 1&̸P7GZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMVeA]WիtYΫ4n_ 5pZK/pMYۺgQ.; L ِRGwLcMo$sPЖR=!Çkmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/images/arcViGUI.jpg0000644000175000017500000015115610504576271025635 0ustar debiandebianJFIFHHCreated with The GIMPC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222XX"h  !1"AQa2SUdqt#$457T%3BRVeu&6CDbrs'EFfGc3!1A"QaqR2#r ?()JJRRGg O$8578@+WO kO+_ܷ),~VoScNr?ƀRZQM;|JkE74-oh *ߕ[ӿ+_ܷ),~VoScNr?ƀRZQM;|JkE74-oh *ߕ[ӿ+_ܷ),~VoScNr?ƀRZQM;|JkE74-oh *ߕ[ӿ+_ܷ),~VoScNr?ƀRZQM;|JkE74-oh *ߕ[ӿ+_ܷ), dV)TmA-sYtM% :T:@0( R)@)JP R)@)JP R)@)JP R)@)JP R)@*k/OXIE҅s j sMMsi҅^6SX !#2s{'4ۭsډN@uxy%  Pso`ٟPbZk פj?ȊHOmŤZ葶c5ޮ֫!cR1>ZBfѶZkwC/m^sW'ZO}R?lY{;J}>wZ O?zCE) E苶-~ֽOt-PkUg5#R[`m~ܦ7Ntv'w zĈrf6R|۞U~sUsmS%xJZvpm6Zn-Z `F99 r: ҉F_F㖴+^[' ֯kkglmov9+^J^La(`xO_vl!f\\CP$dcJPcNb{yn#9Jw>'sf˂lDmJvL%gԞ)O_ϥ`L{f6h:$%nT-<$l@7W׏Pc9JSP`ڇ1--TPJI NI>l9Xʴ0 Qc'nj5TRD)Fs{?[=*1ѿ^#ҐX>[`O)A,}skq9>|E)c=6gi_?D}Xuw^*G[ƾ O) E苶_tZև>j\ĊjO7''l:WkO6ٟW]V-?{> )HR:4[tIKPi!r ";+=1Gd[Tvu###rִ[CiT- e >B3JFI{{u}9c~Qs10JIUBlE_#'S|5gsO1zaq6 tJ)JPo(dj佤ۛb%ƓhBRݥHX;-<H#ZN2HZz߹6󛸋LrWGWC)81CF |KG4ꐀ 5rfftm.pHR# `%`jTȥ)@)JP R)@)JP R)@)JP R)@)JP R)@)JP mAeĥU]v~#*ݻ޺xdG7{ǚ D.H8^u tٰk It ^GB9iٽ?j>JggJ[˻V:w~>J=+~)7ɩ^QPl#䮣7+~)ljg/sg]Pn;=;T|{BWS%zo%-L<1%} ٯV>ˈ7+~)ljg2 /'񨯡cBWS%zo%-L杋uW;2kvM#hJ߂>J[ fg=X'~J+~)7ƦsaUSWalO]7%zo%;BWRbl:zȯ;|c>J+~)7Ʀssy~J;95%uЕ| ^GKcS9g{{9r>Jl͎ԻBWS%zo%-S9o{{;j>Jw~yԻBWS%zo%-LgvuMZ|}JBS{)G]S%zo%;BWRɩ͙׀_V<#μN7<#䮩7+~*XagY"d~AnlcƒmKmIHb ^GPyO Rui[$gO7Ag~p}3NΩ}>P=/.҄2<ZR)@)JP R)@)JP R)@)JP R)@)JP Rj<$2U]g28#*[?e>[s Xm= x,! x$еJ TϏ4 wS[I.{vsI-e7ᡥFRIz`Rti0fͅ=qy葝b *y@ IvRYxBuRKO<;G`q]rym 87SKQRTNH_%.1)Pd%'HФdPDvo':o7:z՟6yV cyi!2(S-)!+JAAXOnKq0ӕpvO8%D'YI 9c|Cؘoo.̟2LDSYe+'#^ PjVe)@)JP R)@)JP RErmo%vYxk}[NKHǓ5sEjDo*h$0+VG#*f&>[1Wo=ILT<%Pu8Bө=巴N&M1rN4$ E+ rRRNHo*edxAuRNX)H#|X6eL}r.V L0ѩ+$/V*'-;3=ŜA 76FJUJH#/&o)$Ԟ`:ٱXbY qW*K<n( /f-]5':o/_]R7+2]hB ѥ)0*zڐ@<"I+37NYK-)iNPBN?JUvκ[op͌@iAM8y#Ij`[g`l,):TI\sk͢_ >qUo#Fq 3o8o@QNyu[X4ҥaL~;S΢MseɓF5"&^n.B}B10\Y$֢{$o?Wͫo wW0oiLcɎ*}OT3gqbC,6T1OwW7fߝU2c"Ѳ\cl@V2\ ( ӟZ\/Ktt*Ӧ3D:rS\7{ߝN3Υ:j gq~Cl RG!穞>'h+~;SΨ\rN}Vl,HqweRTʒpq@'h+~;SΨ\rN}Vl,HqweRTʒpq@~7pYެr'$drBC.k6w%t8ԣI}yN ST&m5ۗ:e'W0zV(HJ)?]~]-?_k}3c*Rl .mNnN8H Ϗ5(M9Z[{xeb7zFķv#'Qտ^`y+$rͼ1&}{t޵RPjh$"SzN 29^@#S+e.8-r uh޷!> $@'w]ȸ.5RCoiHSC-Nyj&rSvD,T%CYQ-23˕wPg_-m%nvT5RT6Fs?KOLH繶V%n2Co:S( > 0 tzP R)@)JP RYdd յZ$>O0&[˵uWroſq\ZLyp|ye%iKujH8DjppP*ٳRqݶ)/e!RA˃V =yT}_Jw=dh~N8ZFUϠAc=n\_\qCPB5' Ռ"ބٹZdé-8n)AY'=2pSt; Zqץ,]+p@>>>Zָm݊9s۬#zAKy(\V}*bvVNr7)nλtEB\m)o9% Ne `]YGG=mt=mumɄt6|8[G]8[G]p'7<7!2DW$[\%7o1W@2#cUl/'ϸ0a mx Z \ݝg FK%E$ ZzScr^Ltn%)I'k٢KMl[,as'C-+;d' `( b]6ě](TZB]J!82GZt͙uCc6'SB|!Y#"۝yz*_#iX ?z?뚦v;GqȑÎHгA|O==RlW6&#ȷ.@q%(^JTNl$ 1؆Ν㛕+PH䜞x{ln|[N]!($ vvC1.3k6lۅr7qwmk[cr'x/xRO]A }l{b[!v6lTZ@ SM-e\D9#8O]l]=QڌT]y9IoescLmɄw d%Ĥc# yE`do6/mҵ@נ5 2xW}ߦGV,ܧB]:"Nx)roſ*Ǿm ۮ"ˉtaŀriIAWzT%sڞwʥ!yQDxh%`ej<|Ǟ.ι| uΏ۶ óӮ2ȸ1yjF3䳵; * d0 NO,Ohɵvsw8H6yn5C?M냨3>zv!-^Ts_puݛo|Ͳ5(%z5hIW!ԶB5GݩjC!A'Vrvq 8cwx&|f\u)#&X},CV+zJ{l›%8')Ԟ\b*ɲV+L+Ik7YԆRaX Wg;e:+iv f\-aA0J 9c>Qz=6ÏvUءq婍xJgTcVouRktJVzV[IRI#Iy+f&Х)B R)@)Cҩm*9$tNJY9WťeΪeH=U+bt nݭp, {Rp<,Hǚ;*;VaC$ ,oCz$>1KɡȄl]d6KjzP<|o!{,tZ%,zRp|pu;߮vgʭo|am^%ueJQ2:TuǞVc_#??9QJ[g0ʖnhI<Հrp9\?{ߝR2Ora7ROC·|Cr+% J AK^@LPµOssIm+Rm)Z۽S V 犓2*ǝox,5ڎ;xYJ#j)y:_4y6~r"۝v o֭ztq޻**\Gpx$ڎ5YRzѷMɞ3lVujsG"G'D JUą4喝1a,j0Wݯ_]8R,$ ޭSΨ+i3 :dtC%Y9YI.fqGQKcXrc6U)L<ϲeCJ(9Y+=tۘca:[m2NI'$ζ*L.1[ ) v8Ruǚe\!KQư *V:cMJvRףkUy6~rٛlrԭj* x'8h vS-ӘeKJ\wJ$j98V.SΩ'ȹ0W#SlFɸm+Rm)Z۽S V 犓2*ǝox,5ڎ;xYJ#j)y:_4y6~rg+۲tyK]XN+p1 vS-ӘeKJ\wJ$j98G4pu&h??9Z.܊B񒂰yS?{ߝU7 jSͱӟe+R[wJuJ9G$džYF-/aq[Qڀ-kSY$6~r2*ǝox,5ڎ;xYJ#j]p.[θ\ S-&⾟ceGn5xq2c )iBRWR9)c Q>O\)OޫRkQ+a)-m'xy+ddsNJW3Xg.\roVoNa`+0=Nk bd!)uo$Zq65$C'ܪM0ԝ[KvJݤj8Sb(m%K'>a;ߥNS JNsc$݇MAsu)R':u#֭>*K fkFخ!8iA*8= /.ֺ;8lo&?*6Tu%A9IUeO9.sL^(K@PH=<ճ`^GlX{+Fh{y5nݤ͇lut>Rq65$C'ܢjڷϖ~\w;dljI1dZ#Vs˦@>lNطƓWim6S)Q:@O$5{ډw6XlY'wG"GNNVz(ŮFgώ[xOk;xqR 9R0? K fcFخ!8iA3bt nݭp, {Rp<,Hǚ#I-mKRv68Iƈּy r=m(1զ-/.tJR()JUmg_lflq{2 θFqV0|u*+BU1ߪ"_ǵT:nѸ73yi&mʔF@^񲤞@;Wvifun7?VAsgxjVW)3 us+4UwcʄKi2ȐDR'V8Aէ<yOwޱ<6*[mR̶֔ϮsVUNY|mt7?Sc:Êu[+ekHRp= Hȑ5CCNЊz՛ޱfҧx}DJz՛ޱfҞ4Dw}Y:Vn )+cDJz՛ޱfҞ4Dw}Y:Vn )+cDJz՛ޱfҞ4Dw}Y:Vn )+cDJz՛ޱfҞ4Dw}Y:Vn )+cDJz՛ޱfҞ4Dw}Y:Vn )+cDJz՛ޱfҞ4Dw}Y:Vn )+cDJ9l*ZSIqʔ4˦:\Ze:̅3qm2@@Ǐ'ݭfmOIZ~LJ(Α|;7K$dH?L[-NO>BD'\>'Sٜ/5z|O{ӈz|O{״8_pkrWϧrWϯiOfp#"=N"=^Ҟ}GE{_>E{_>=\8}8}{J{3q/Ou|q/Ou|g r<.^.^)y\>'\>'Sٜ/5z|O{ӈz|O{״8_pkrWϧrWϯiOfp#"=N"=^Ҟ}GE{_>E{_>=\iMli XRԵE)ʝ 2|uFιt+le*>bH:t.\RYMK1p}{n!í}{_-{c#%Zދ w8jjF;9P ekH&([ʐdij$C<k@QvKQv&V_.I)d ,xS%JԵ)(3\%4K' rQCicl*ۋ1ݸ˼FydA͋chsqw,2Jo#8W8S&kNfm3l[^ȌYq*Jס8Xϔyk[m7p`[+܇ԭA!@:^[m;$Jai*V$`sYZ.YlDqv&Fasxrm%~l}NF$;*MCKR4$0j*iܶxŝ*8pj+i␤ϐ[;erȐQF>n+ݳ]3ˁcrԧUH>ntFʻ%=5NF^2%G:⢺P|Y<^b{l[56x0)IVJrZϧQOgڽ!#4ĖC,)^,><$b/v0;fe cr@sԠRs9ԔvŇBF~gp%<]WMg֤\lRP\9ZRq#R.[LR,H{:%jr3sr8wn->~[ʼ+pm||i \א⭕7w(a4uBQ:yc=|so ֒5jjjiRewyήX%5oTKө3?.~ &KJ|[+^Z[=Fyj,8|,|3pKkV&5o7spV5sw5xIG {Ʃ6:}U,w= &3I>=zp{yuǹ_?;1uiIsM8g%5W{zutiy)[Ϧ=RaЯR~ &3I_#пTN>s[t7\= 1\{AajԉIsM8g%4_?_~.KԴpKi?.~ [tiy)[Ϧ=֭N'-T'*e@#t`qj w!I_8 nv798e+wǻ)_Bá^ ;%lgcoVuToK]I_#пTN>syMQ1ZwzcwXƮ]qŚ9oTKo(]@Ŀ;WJ)\>2n]GuogV]sŊR6_;8Vzm|S6:?|Խ;mb6:epamy_ķGf;)HHWv=\= t8Ʈ]qf4[&{bPA_wwgՎY38kѣ9vYcݢV Oe oϟ4NOvJv8kѣ89HD53x}F|-9gtqڻES)@)JP R`q/gV{9 ePv_6j[գen@)JPm 8h9”l-qHys@Y~>5Jk\|}C돃P+G ?$#Jy<@yrozQD$N?3[M4 ^xy3 V> >ZrljՉɈE8P # * o\|}C돃Q7nФ )<h }qi> jҀ^=r^RFՀJſJĦ4⥠+9>4/5@m}C돃O}qjpsNݺ~Äo\ )o?˟J6>56c2&^kؗjTkؗj@)UiY.>՛?!!Hr HlKkea\[q=FG#VTtv &iZDXVx2qz$!J}+Vr V'DrJ"K*}*h,'k +x8^HϏh%WF)U76ݸ`cw'y:0U\c<]n[)PR%mZ%EmU'R OԦV=ip'*&%QlҵWrX\[!+4|NS`KD/jK&0}NXq_\!%_mN{[&lҪ\lF BӨiP|^Jޱ$̇!q"V{ q*@I^_eI3N*V&wNzzP8ӢLIe ݬ+Ig*f)Uۖ/ȱ[!"o7m*Ճ *63P)bB3&ʸE jH%BSI%2e֓薅&%LإjmR!J:[OJB~^]=Z&x~:'q,XՏc|r{1x+rp3ϗ:Y4jR R)@)JP [9 eUg}ʠ5,`mk"BV+~R2뤟* m l7)TkcZRg9kҀ]uVa藶XUcZXXQuN{aD# J* ? ޗcz;V]ڽ[1ښS-pN#+H ==픠8,jfFRrZ-CRZk sрHS츧XmŴTAR FGND=}Ҁ_~W`{ثM\c?LX-hPi2S#RPV e P@?rkg"vyfqHZtڊJY#TyAoa\Ţ!?-10V }ZV z᫮kR.̧#o4<.C>9~Dٛk vC2GwJrH#8V*P ſJ[,?Цkjg֭B;+dm 9vg]:"F.6o7'V0H-f"ԡ"$ݛ5-Z֕HRҰ>JJ4%_UwzPv&RT͋BCV Ro d"-f"R:.R$qzA)'«Ҁ39nNm[\ R0uZTB֕$D5skҔL&gmR@eF~ >x$0=/.ҩ]ɾ2]hc|̾1`;zBHP#:S;]qLkgT̶\^5䂞3⮺b.K 3zF~}nޗwh#8k~gЏkNb6C[HυjyRB QN9ghL\esj}vr$xʀy5Cauc@ W uV8M5/9FǶMloˇ$,T) :udǚg6z}EX!Q!4'@$+fbm-RWWCcQzׯEB/-:wH*~cc&N7^o~Ŷnf|WPAMoڍ[aYZ uc |vc-hj9$OIk2#0ۥ2\=T>mRVyX'&ܯw;^Wcx'Rr1_5tv!Ef;er˙5 !&3%#d2]Ko0dfTtKnwŧ8Fpt1y}8g$DoJ[,+tݧ!)^,$Z35Mf+&@ljk"bKey,\Kܚt<)J|JRR(T!Im?טAQ%nB\ΟKy2ys|Ơ;it\\ֳ6r|ΪeNΌgAʦK}k6LsCNe*@9*Z?j["%Z#E_O^S齣\4*KzN Nj}+jIl'JSDYE$3kW09 Toy庻~jZ>aUiLc8oD䫏 -8=wt#xze'e: C6\QVR2wMd(Ed 7kDSeݬ sϯb%L԰599r*3~֙h>si5C]2-ljصZQu(FN2jη?|Ҥ37}iƃw?kQ&$:ch}(B ζ׃yG,VxV rۨ s<|7}iƃw?kD9qƟv1h&jXFrn3ۋ)p |]1V4{Zfoѧ|gBw#T _gOr.kdc'[jDz [7}iƃw?kU(ܕݭOn/vϗ>cKnɈA3R7p׼XNH˗_84{Zfoҝ PuLqe-oVooJô7Y}/9yk3~֙h>sk.IBO*׋޹8۶ }%&$p!<(=r|mZcvE?zVQ r>\Oo3~։;ݖsQ?Rb%L԰599r*.-ljصZQu(FN2j癿ƃw?kL4{Z4f!cKnɈA3R7p׼XNH˗_89)31TݝKJd?)5C]ljR\΀m@d`&+/kxvt‡\٬%ݍ[]Ky֤o RsKMӵ)l=+(kv˟_1Q'{9qƟvLD͙amo929r 6~oAFzReG<%Z+QD4f!g.Ο>1z8Hp#w"rFG.XϜT)Jt.:*˚nox(FN2I}yh'(TUfmW7w~ڲq[?]~]-?_k}3c*oLb\w"﷮Ä=>~7pYެr'$drBC.k6w%t8ԣI}yN ST&m5ۗ:e'W0zV(HJ)?]~]-?_k}3c*Rl .mNnN8H Ϗ5(M9Z[{xeb7zFķv#'Qտ^`y+$rͼ1&}{t޵RPjh$"SzN 2#*Ӳ}{Uޭ/wȭJRR?Y>ڑu'R?⮀JRR(A;GyNҦԻĚn%1c6Pt4PAl'YlGv"g"˟LZp@'IPV],n+kuxԮd8/5hdlMcYL: + KY'9GNT>&ߦߠm\->8xtIq)Hh$N5'9Q^6Q1CCz^ԺRu(5ɱO}l2|e-.P=/.ҀR()JJRR()JJRR()JJRR()JJRR(U^%ʫEV6ݛ{2 +/; dVh~[EoP Rehv 7 IRxҢspxUι-" $GX}`x3t;RHh&.|h&.|ClyO)mZ2zOmWYpn 8̈ӒKiPl%c9ICIg=mڿϖmڿϖ{w C aQg8Jϗ2d޹;lքhq  µ9=:cF亚pKehl֣ ,VSW>UВdFiK^}4=&l %W+}cI\VBeEP*#8 vklĉr\EےB]SͥJmT ӐGPzC*#m̡Joz'>{Ǟ\wڋ7Nн&k3oa Hxm%A@xA$[^{[P}i@!!JRT@ydբn)IkϨ}qjLtyiE#HH,(8R% /@mlNƑn7,vTi:B׫AqGJ>5jo\|cQO??-rm;Vff̦(N54|9nA҉ %-y:s1+'yyޛ-!{["e24ROWyRpQ@v/}qkN6&҉ [!R*=O3uܮ{ln~Wv-!cv).%DQW\r sw9ƸvJrKΤ`Pz`et Xet @)JP R=wKɥ _Mܣs?tK˵t_rlK˵t+r4;&%Cml5 Aԝo`'rc>$7]m4b-̍'unZ-#8>?ee:KJޭΊ'E6] jV< W3nr~Y ɹIWlQi qZ4 d}H;?}VTqIO2 =7=3[۲6Q\9 e=l&$5D |TU}|T$h3F=cݪSLHr1Zy<ӤMg#)mQlŽPPhp$+:y:jKqOov< %Ւ3SקN.\맊RO{])JP R)@)JP PW$uFn?ڋV6ݛ{2NzKipw9 rO.xϘtI䱺޷rSx04VMV͗dVSmaCkBuR$ bU#$ɆxR~kh{FRi1T89LQM=r`ɍ\JոQ@<}sP=孢9%c"Tmk}yd'Ws*UIW*l7atk r|EInkSpWDs[$.C16+''$'':՗mƈV K'BH'^uq&ݢ) CҲN6<]m1&jXF'XNHގ\cBvzU&{1m ԰Ӟwf!|g;GNzr8_6LX[եmn%Tw܀oAK,JQE^ճ/[in8R}S`^@A2c,d*/geHz2В4N@< аan} l 'yC?~m7Ihw2 oO.}|ƗkLD 97.qMJvRף*v[3㇊Fyӑ>,4̅iG)B܀B[#Α':bb|2cn oVo#'QrjǙƃw?kE$ ԑMt]ÇseLxڜS}!9WL#5f>m! CDj=<\TD[v ԍV);`JZnn!YFd'Y@ޞ\E$#SdꖾJdr~ntMTt\҄HRI qX8㫅6/bfnqŎD˯T\]&[,v ҍ㶷d*;@xt0du%p>>Jwzֱqɉze>6薢:>JorV͍-;jF[Bq0|F\<=?;Y">U;HewOS.,n+Ϻ+bs옉3R7p,r'$dr)UZu7U~?{uX=eӍoN#8P\'\\4~jFze'<;Z"fҲƷk<<)&x2B:߯zOޗQkdK ٚc9##.qQq~`-#P#RysIЎ %{}{b_]Rbg]˾ٛM]ߥ>,=m)Vy8A\p$~һ&h _~\mqԔ6u%.' -ilvttu9~7PYެr'$drBC.k6w%t8ԣIEfԟ/3jg9wkl4X`$DNNj:rqRۉ)ROB"+'6ĚnӊozH^5$PiQ;eBl[ln`aV?֗)'KzSђS}r\WoK~OZC슔'˯n[SSkSQmAYMV%p|O`r?]~]-?_k}3c+vqcxIRz~n+$I9>`iQjƼіwn! HWW홻\م&?OCi'8DzEZ*#(:T&m5ۧ:e'W0zSv+nB\ΟKy2ys|ƊI,N1ĥ+JqcxIRz~n+$I9>`jD?-G$bZPtS)@)JP +P m)7"eU_HT]R66϶ J!HK8Β3u;߮ѵ{I0pwW7{ߝY@au;ߎt:Ҁw] 뙾wVzPxo\:7g{ߝY@`s7ߎ~5D/+O~;3ήAd3ҚmiIPds]!VhJ) #3_~;3}ήAmY=]Κw7+c[C BВ412FKEe~$S@DNc<\u;߮~;Xvi.Wm 6IRLfEښ`rZG致G 'Wjzt}3s,s; wS~;6npv6aaʻ1o^25:[8PlddgO1" `.2ڸe3e{ǥ6Ks%`(dgAS~;SήEpyџ2wCTSHS*rU+(RFFR>m:HmvZHX[J׾.@; 뙾wW7g{ߝT%t\e`h5 [>RBI$B$r^"Yѵ^쬪[6Aܣu4]0JP R)@)_M\@ʏA^@jQZ*iE%I%I Js n(nR9XjbQg%1e,IQC)GJH$0< ~Ƶjvl>pC˯NT~kqn8 VGבcŞ˩}@XK h(PgT@"mx7~/{\G'CƤ89y V 6Rq㴧]^ ҔiK;TMD4ۡڏ jxt)JJRR(b.g $DrJ,<ljo*C`,!@R5xWO%iںU3O&|iڹ R)@)JP R)@)JP R)@)JP R)@)JP R}ٜ'~#*YϯgI߈ʠ#-XIe :JRR()JJRR6VP$+HV7d"*= .@՜}y+eC )J>?r qR>h#I8I]cq>JRT,8N IҜu'mvv#nh!)inFz% #R1 RU#@^\ўN1m!3GƷ*AjL HBAX+IŽQt^7guw7?kujϛ< *l*povHL:J JHJҤPV JRR()JXIhd_Gܧw>4\ܣu2]()JJRR()JJRR()JJRR()JJRR()JJRUckLٳeUc^#*{IWWJJRR()Jmg8J8~vC!6ԥK* %@'p3J-luIRѫ%5:nl]jl`R $*%>G,[)@U{kv"b᷋I׾νxH3kUVW oge4UP[|q ήc* $ ( ,喩"uPn"` d)QҤ- R G'$fѦϏ8\$\6THKH)) lLWskod*͹Iu: z JRF36vv6ni棴1$iY8IФy5iSwۈ$l na А19'Ab1-3X@eIk' jz1]ʵ\Lňl<5%1HHsHKq0ӕpvO8%D'YI 9cX@VLfO&"]D^)ԬHq`(+Gά)@)JP R*VxoVj<G>0=/.ҩ]2]h)JJRR()JJRR()JJRR()JJRR()JJRU_lfl= ʫEUf͓@FXJT]}KLT)@)JP RXAW%iCZUpDHa sԟc|ruanmt#V90~Sh/6s,%-Bu5Zr%C?,ugl͕;Ykt>3^]r|ynQwal)u yyX9nmݕû$"]~6uBYycNJ|?Df}8|c7(QHq6 )#BN= ^Rԋv& v7!aiG%xsחZ/dlSL"e]+20ڒBB22g=h bk6me͗22-c%6)u!8Y*INr`9sB#\p-189q6FT9Q מiԽ)DC*1ҋɎ`']XXH;Ĩ+R$xnj}fʷ9ʅ%.-9yc#ݪn.w)' 8\GGjt'CŷVII-<ANtu*.nRPR0H$ tҀ۶7hĻm}N1 =+JHue)D+@G?M;=(d]ݘL=1h >f }D~;-F|"K,(TN!*u! %\1avmfݸ[N)Ɲ8֭YJ!Zs*q6mnKuIm|[֗QA#  H:Vݾ5P%>m).k-D,o2p mk%["pM)X ק%Y%G$֫ q"PSK^6 *Ҽ }}ڭ&:[d3n}j ggC6^ϳ\e mo)lxj8:F\Lg^Qa1 W~)wuFvi͠ G=#h +ϛ;g $F\BT%3xD\ݴ{Aղ5Ҥ"o6(I$ICy?u}OY.*ۅx20IJRJ@sKƆ{"tυnn+~#PZ.xО~XIE,;Quuc=,DA%SJ[ INVF٩\[InI6(mnܙ1R܆a RAFp^rx߶m$8N䁀s&Ԫ/ugܢ\Lu㪝{\J}{ⲕm#NG\@vjW.meV8]&H޸ K-/%+T#NA<!}A٭fIZ*D̆Ѕ/BQJJNybGim-!8ɕ![zѤJ @#V'a 癘բdF[6}iK:9cCi|"O1@vW8s=ۮ=/Kj}ĠF@<|)JJRV#ެ@ς39ܣu2]*ܣs2](q^% Nj}}t;6MSE!d=Z Xsxė  /Q(##WQ3\NlG1ov/ R+Bˁa*G笪}TC*r-]vzТ? ->RWH'.v 7feM̊㱦)oQpS5Tѹ2[EgAs{9!g~VJ_Cy) xS(Us9?v؛NV qJ8#ZїId$u}K.GW,6yN1ne[ӻ +:ϹVN lha\ Yn'uG#YSuJ;EA/jlwHhwl/AX9&k.1p ysϋv1]2JJ)(fE\3=eFMiLX]0$ִ4xʇC?5N%|eW4;PH",uAKuHG 6OQ[hZf˷STK|JRJ%nk/:湗 xCn'.Q 1VJHQ9ϟ^^Zm-eݘA)NDr)ҳxw'fm~=,+l(K.>m%CYJy r9g.fKYz3vH (Xˆ3⨲'Vj|$t]\=eEavvvRՎ@~S %Zav#\)C)m xzvWN[Q5l4 Tl-\ۿO[ȉý"YJҡ'INp ~*Zd|ҔqJRR()JJRUckپd^Ugy/|FUkbS)Qv/i/1R)@+Z|E ͔%,, yd٭ȖZBԓЄ@Eô7Y}/9y4d b4Ra %ą`@^moeą֧lSJh}ɿNϡӧ:VX R!]jAP Y 'V*6Y5nL)XC#gRթdI$5=dYK/]S. ݸ:X衑yط K2c:e+r<M2s3[a1;8Fr1^;7[#v7Ns3YS")IeCC)1gw :uuӞxElJac%jZ6HKPŠ<"GRz 5q7"JQNHG,[̼Ԗ}P.$-$dGPGffl1h-$#!)C`8E٭nEvj)JpJ1+ |n"pYrwtV*E ΀LqffLu[O6`dGܯmX[c8d-H KǢ+LȰd!I[`AG5}4i+qŨ%(H$/5%a:ˉ m()+I03lb fmR4C` ` 2Q @ NQ9cj3>iVPJP2I'F^jK èuۈPRV2##@j[ֻFmoqKzgHO5X#L3}e˪eӁ[T22:@)JP Ru<~e$ΐON_G%iںU/G>P=/.Ҁ߶aWlźC Rѭ(Pq2kٙ=yHa\ T"Da'BR5C1VVt#2%IU(Qնj7VQ-) JUu&>{8" \i >NRs=@ttt:nj\U2e}j!Xp”)'% gIzx흘Y9e4n:Hrr<\JYm2Gb=3!*Μd '|gRKkzJyU%-ĕ99Խ*TїnQ檾]!r3)d-x12RǐB-SJ<2yUҶ'm>26;\XMJCezc Fuȑmr"4vwRRBՄsrt`g8k~u#"ѴwK,W *LeGJXaZAP–I9?<ժt%*cd;[3"cz!>g `OQ7տcmdK 1!#Zt*%*RR(n8jNuIǎVu-ȵŶC@ NNO qJ]oե:0IJT@%c8US;4}EVYԡohoxtG_V/OݶhfE2&][8[ t3g=1)V !)P}/Nҩ}>P=/NҀR()JJRR()JJRR()JJRR()JJRR(V6fv~#*X43yʠ#-c~_b*.>%*RRm[9t)}rwgmT :j]p`JfLdŘ%h}[[By-AXӁe5k(Wm 1x#LANV*%#AO9r8b]ߥZ\6+"ܕKE*AȨͣ"Se{NaNS5DNP5`RRB 4+|z[M#Ij6jRKӵj*mq2뫝!FR۲]'_L`ΣXq nM⋮[ӄ>g@5x gmGᇡ!n6Z( è ǢfzVD3jqKT׆R7g 3e()JJRR()JJRR?doVJƞw'zS퉟vuLS퉟vt)@)JP R)@)JP R)@)JP R)@)JP R)@*_Vjmg;I;T] :cdS'@)JP T]5n-́2=M6ӋBGNS%'/!(wa¦NVFZW<JYdKR 7dLe#Vj R(`sQ-S)2b$)З+ՅaAXԔJv޻{(᝖$@)(#t8]i? gz\FNhp* |z1eT'm 3e Bn RXmkBeIPJJߊSŦԘ 8QXIԭ)XQHV{W8IVTօ B%C qȑ[TI.7?)]oW?DPjU'軰ޮ~̧wa\@|޻Y76ɰ.BDuaZI:A犰lFڋWhč) ( +2SA$gt~2xAntrB)蓞@uyjjnzvuQ`d|dTx%+=WsN I.7?)]oW?DW:jU'軰ޮ~̧wa\@]Tz#2E݆sGevR~ }vڕI.7?)]oW?DPjVkfm [4)9ŠO%zJRW9\>zdrlLӵsgrlLӵs()JJRR()JJRR()JJRR()JJRR()JU!?NFUYj_dcI߉J"X=Ie':JRѝof[$otp2U#NN7|yǎ.gƐ%~hE l$)$.+<``ҀH"s? z ,3ȹ-ĸRpW,λp.KP&F B ):cORѼ[V.wr)mE:xIV9"ñExztvi vm֜$4092P{b_6>̍wm Zhm+RV HRg]LM3d Lr\T9 `yȟjd7#wȑN1unc^3yV)@)JP __tCeSn<44$'NIH7P;Cn\؛3s|F$,)Ā$,x$ ݻ\"5:1q5-T4<9-1oesuH 9(P$<nē6J^IemJ:. ΑWŎnT)SDKxp!D)28~=ń,a+(%I -mV;}{7yN 2qtoP R)@)JP R}{_uzOPʾp}3NΩʎ{B>j@)JP R)@)JP R)@)JP R)@)JP R)@)JP R;[H2U#߈ʠ#-XXIe :JRڷ|߻;BWR~5Z/h?dUe ^GNЕ|ЫnͲZۍ1)RlRJARPNן,]wD6nVyV8$x* I\M#hJ߂>J mn"_]FVdTtVzs%<9VWږU^Na)Zuc0/ѮSg[-"ܧR5k>~??hJ߂>JWJ]W?n+~)7}mM0tgZIJh]ʂR HUAwldͺ_s)BhpsvM#hJ߂>J[q۶fKginPݺ!)J 'n)h$$$ {7)vv ]X8֮7BQ>3 i1 $)¸<[A[+~*&.*EV6sD3# B>:-Ih$t)ydЕ| ^G\D٘I>ZL5V0B@'NAD:3w˖Cf5``xO VuCH;ghJ߂>JvM#Yw=-&ƎQ-E徔$Z*IŦzslh5LL /!ROXŽrqP vЕ| ^G\2't=Y}ˤhN3'}S HHNs u]e,e/y"D]uxRԀI9Ҁܦ=p$ҵVhJ߂>Jz6 To,toZCk\$n]GKg89@;BWS%zo%p`϶~ȁkl.!|JTE|t0(nThDTiP 1whJ߂>JvM#m$=͏pe Yf(Bͷ'a*0G g}U7fZBD Tdi ࣢Av)d) Ip|\Z٨RcY+qOg3ޠ5b_ƝS;w8vt)@)JP R)@)JP R)@)JP R)@)JP R)@*3hgN}C*Ỹ꓿@F[>_b2KLT)@m[oFP%RNP8=39׬Y-Ra6lW$HGܟ_@hZv*ndqIDF}8# ݲ@yg*GsؖsoN^8ǡcyr~q-;ڴ}k\nknJw>igV Ow;fo0=¸t] WD5Gܟ_@bl;Nm\&,tpwmugv̔DBma(*DdarN@9+{V?8Z>Z뽛sؖsoN^8ǡcy٭lL!.亖Xj3@OSuգO/{V?8lX0[&#R­q,FJڈ*IL[ 5jC0!)d! 3>r~q-;ڴ}Շѵj6,9&6ETh*9yz*voyq) #z''''Gܟ_@|6n4q0#odgR ԖJ) a :eK]:(A%N .˪%գO/{V?8lbD m7#Kla n9p7:MɕGEɫAB$)M$S ) $R q[Sl0~f૧#6\, SN&kPN@s~v94薍RգO/jQJRV.g<~-cI=8ܣu4]*ܫw>4\)JJRR()JJRR()JJRR()JJRR()JJRUgk>lVjmg '~#*}acS'Q߬l~_b)JX&LbUɒ # IHIIMgn6 @yِBTC$p F3 |C"4lkp%xֱ JzֈsISiB֖]JR ֹ6mA2ҔN6Ձ $IMgeŝLڡv}AJqJSi:(kT52 Ӣܡ d4Tx:ϊm#nlga>2Q! Jԣg#H{O1rxzO '| Fj)I\isfO*CS4pFE))^$ fZvLe12Ԃg<ׂBpRy(xJW;b9]-έ*RZ@  $@)ZW{Dmɍ7֤ AB-}vR~[ o}?ڕIl7"oPKjU'EޡϧЋaC-@]Tz[>B-}vR~[ o}?ڕIl7"oPKjU'Eޡϭs8*tHφ׆tkʕpI!@lVUNe9myoL@gZ}vklKHk4կYj3 HihHJP0[P\|V> h6/i {^伥=߽ = i(S#RH*Vk()JJRRm(.IVn@jR~Ѧ/ݟ4+kqn"@j>2읍0Ku- %JZj:|UbEFaȓ)(nu=?g.-rBHJQऒH3@]$=Wq[Ku-!j:$+n"M_?4h ";rlLc|ҚZeJ6 =&n~Ѧ/ݟ4+kq֘(MJRi KGR/cPV4{pdi8%*RG6p1R=+IXp-[BR+P><`=*:ow IʖpJ\c;i`K8mLur3x P9Iqmٛ-lra.\\܉*Š$)+E" M]\-8l ( 94Ԩt OH!8%l$)PT9"k3m02TۉO9@ w%Rjy( +Q 9U`nۛ* ,)Ĩ+z4#H0rjψO=@ -D%KTO-pPkpۮѯ8 kQ"ja|]#v@ :)G͜w+"GЍ*BEAZJ]oFI嫦L巈!%K-od͑658, fw.셳.%.P4:HԐH%ߺcv6 p*+l?RRya*X9s9kiԅm'RTNУPƟ jvj;:\|L5#XSj`O"V}4hk )E/>-H. $c* JIA I W)5aOc Ҕ<(Xk7MN)7Cݻۧ%*Z㶴P /no;J8uu6xi%_ߨ d S b46Te%` si%_ߨeqq%JKI tJQ8J@ʔpUv&;g*i(.( r=u#M6g/1IN aGrsI :usNױin0۟ L&L L:\RPԶ]PR @8VzzglIۆqn[)H^O 0׫N|T]*㭸T4G<+89R)ٻ;eo6ۦ-ĥ<c ' XUs.\{u-|} j~<~-k>bT$ s€ܣu4]*ܜqo>W])@)JP R)@)JP R)@)JP R)@)JP R)@)Cҩ???Q7kꗩvڤJN R:8-z4`c:9Xp]c܈QCy5D4!'$s"O{M@"`RǛ!,Gi7lGAm!Z|FRF} ~[>~}E+7g[Z"[=䤁iR٭>jt/f|ꞶHsp8ƥ=J& 'Zsӷ?~U=6ww6|L}FsywHgΣ>Cj%tj櫟UF(dߟU=vV{6^ q⒕-n/SUPrf\$7y}9::Z;Y8E#ts$hс^sJ]YxDv.#5q$hуi^s~Z:%+FVZw=9V35d$o_šէ]i\WtopEjᵫu3^Յc8qR~3]:Ξ\01JsE+uFLujL蔮wwdػFٓj&Hѣ8Ҭ8m=+wyLqJ\{:$pꆭHꔪI?HGfm ftΕc}U8uizR,*gh5<4`c:?~NH2u\lh49?-/kE+^pm-JK'ǀy.!-/h\6wSeўzrgjH~;eɋCOП~}OWJqQ?KGUt/&cW2F9ƕ9娨ⶊkNu6^*q4rT!TujH|}OR %volrJ욯;!~}W$Hw{+W[zg+\RNŭեt>>'h)D-%Tm,"ghu<4`c:?Hpmo5qdhуi^s~Z-}OSZ>JD+/f|F#<^;Nu1NWg8HɇBN>'h+^Oj\-{5%|BUuWt8Mpպ̗Fyj±c8[Gt'$ :Ξ\Υ9䢕ԙ+RZR%jҞOI+'9Sê:$ur72]j܁aK!w~<zZyuO*G(GSJ~w}Zy58$vo7^9ƞy?-/k.%iUD53x}F|-9g}8i|R~;Q.o: O.ol|Twٟp;>Z<GUn~ q[ףFqsPr1Q$!oBl|Twٟp;>Z<)7_\^[tkǃgN%YPAX;wngӞYqp*3ƿσgave/ox][Ϧ3vVߴ-xujΞ}3>*Ʊwoυ<4nqWhҞ*L }nwz3,B]T&G|]կ\c[~ǻwg:yx];ucq⦬=/+xtpZhuss(X7hhO~w\VQ8??FCvvJU9R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@)JP R)@mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/images/viewerGUI.jpg0000644000175000017500000021336210504576271026070 0ustar debiandebianJFIFHHCreated with The GIMPCC,%"   z    ! 1UW"7Af&'(26QVXYagv#$%58hw3BHqx4EFGe)9Rb:CDr K !1aAQR"q2BTU#Ccr$Sbs ?rʩ?}eN\f,SM'M"x蔝1.!CSI6Yj,S'MURx2hKQlY=K 'm2pZ w'aB&Kj5p5Ia'&0 7AF֦@:#C{nmt',Ti $xĬrĔ !!)%F) ӕ$+ku}:&Q)jI+DhzȚD"yM +FJi *2"I5igGЌ%Yac,evcay6Ԛs0I.{>gG~XG0maU˵c^bPZh=sU6 ,&}*מX|/Oz1Ja uXXf.cm+[3~2ӷ]5٣];;sɧYu}дcyuM N#%1Rm%s<6c )B&ۖ}H}e^3B5 !,%ږ6ai4M=.B=5׶}d^ml[}}ջWIѓV@rmGoV5lw.Gidcfǽ;~Io';Fhi/olc evj=wgf* !#LIvuUYڌ! 6a!$, a٭*@cB1Mc}87\Ŷ]'(^d{r̟;#So5l[/i c#Śra {5׫'{jCB2M! 묰1Zunړ^B^a 5~:kc裤>PiDԌ#چ4AtQ<|2y:ɐi=8F0`r>vM+RYtft:czMa{eN}#E` 5&x:w aJ{AXz|gFhk) )a4%ٌ&0l^X4MɑXEQA-bCؕ7%Ƌdrhh'5$DSdI"פJ8#Ovn#TgneˊjH@qkNb4Z奃eZ\//(9ᬙ5_CayS1H^0՚:ѽ B0v_rHXG,ucЎUvc!\]->^Y)1+53 xmSn"4ݵFErlyxszPhB;ZCHGH L4i _c\Nag BRt9X`c&"ZվJFC%Rqf+ f2T*MeF,\[{ j=d͞=$HdnX Lѥ:QIЭ]^}ɪLQA' 6Z+˪v=/3ߊ j z)/k'fKd~OlE̓^a #WLz;'OcSXF0eGY)>f0!ͧz>D- KTK׽:¹, [% DJ;6S j4E.W7Zp8"ei&JJZ÷iHBk; * Fsp%&sJ m1e *y:2+ii\Z&7 $ NF9k[)$lnsc.! <9a4{ tuevϱ 5؏d|ڗc^8K4;#fvaqsݪڨY#ͪM,HF:k5dZisBM+ZI 9if%!il FhM65oPtXP6IBM#,tzS]kM0#'Tm!>9y|%}>Qur{tiէd!f_MIn1 ˺4fw&iHC1[O5Y&ZF02JC.a<%Maˬ!ۦǒ"@t,*nmvk ZhuhB11c#-(οY:7}ϳ}4͏RhiߌЕܗM{kW5KHU|l,w.ݘhicSWNڴOP” L)l#iO{&dzoUa*Ok2M#ZBF>11ܢ];xN_c~Y sg)bo>a]#FH]3O unj2lk$!v^Sf {iw>(V=Lf{{!,G?37z=ꮯJeJ4cҞh1! OXM{vCƤd]esM##-]#R01|֑'ֽo\rsg3vnk܀yح/zQCQ}A@3X#KX_"TT^2K%Jm6׿!ZfXA\榫x&a !rr`MYJJR~իѫJ!,5iby#7ӱ oVr(%r;^(KSSQ2X⨪RST)\N6NY5c6ܱ/uµ*V-_%ծFWtjU!i0 Үfz)FB^zhkL {F $k E]sbaKK_@7;3ɐ,7Fa69P4[ itιᶵeidX15e1NvRvc\A_&4!Q F#gK5` %em#,0.l`7T7°%m'mn, ivw hHC!%>L#DȏK7 9ZFs -PC)J2us6O1L*ʜ`) <,3jMgOPu]$r E(ISVRư5OR mu;,OlyC@ (:7<pC.["g%gW^ FXwZeKRC(e&(UDJDR5 Y @CRwI &&6I] Mb* IM1n."f•)PSSPҭ^ cbD;et{ {s"g{d0k^\{,ri׳\e}H"E EZ@6girll)Ր hJXRaF.0\BmVJwis11q56j(t!v aw+G1G[,L8Z֋%Ĺ;>V lp`dzUE,ʅd~9{Q0 efG^a4Ss5ĢQa<3J! % ucKѷ[P1X1kqKn/̴NT?gs1bVOB'gaU-NZ} Jv;3aЏا=MS0cxNoiHiv=/B߭^ٕsВrO5ڴڙtfэc;qf~^Gmzxd''2W5pʮ)2k&̡YcMRl:Ma8#I$2h)˧l*+u$ek4;#GH[ժB:sc;FN?&s;osz[Pq j5#t8iW^ [ݪ0iCXH]i{ {H+n}W>n1vt'ΣlA󵲾{e):^2uH";T\ˈT9&Rj؝0 6OI5 J@Zn*$18nȒQǪcDa@4P5YWmsqK$)SX1%<81.jf*2*_G(ʨ-^VΖ0F[c}G>9էS45Hd⽙&GOհ[+l[ I{qڡZ,Fek*r9Lu!2KNH'ohƵ ,2̸*rmX xTP:k/;,10X1&0ӢnyE\5.nϡ RŨ+DB0|W1~7׎O7nԝ7.s*p5;m#m;Pca٤6dt}?qp;$]c4ڛv;{ІM5:CZVΒAv5'eqaw5ZFfћNm]GHCq^'3C|}nDGB˛ees1i45FXvn)6Fmr1tGHR a,v HB1ڄфuJ^mO]xJF?F7os4ucj+Z\κ;c>CRklާ=/Ϫ252 ]F:ԕHB1214zF,.XCxfĊe !4;1zy 0f6jgfnnv hKu1DF1펷ksq׷^\_8ЇwW}rNTm'6ɰyW45a1eR&1ٌ#1c ! !gʊgvF1m=uXcegH-ZVʄ?c/WX!5.l!%\׽WAtOB ed \&Һ"dAl,v$eU xQo/gR@Mm ^*r"Lacڊ0X[ pIqRbBy 3j )I^d*B ZImc-;ǿF1L\W8BޭRχs~V1$|rǾ.Wuź4J@np{.Փֿlmlm\42xgFȤqF@ 68#c!R0 JI$BrܧMa#CtȌ SB*J[Nti.TZ(e2KN,l :j0iFn\#oֱTGFz0Wi1ѶnRm.q̻S&KvM~3ԓo=ώsܻoYk[8ՐcWƴ oW%\(@rkSh: 4<++,ViX-r'gć곕UMKX' ,HiYxXLXʉ)!i*dm4W@7Zkuhɦ榍c7{1.d;#1KA"΢1.VH[=ܸyLgO7U]BQqM^!RHԘ(KS0A%l<[H\2 pԊ=`Cmp$r<''a6p[BnnݪҭBj8=`i Y%0 L!XTv4!OX;YU6s1a=CzťZH) 3(PNhaWl]f%br:cki2[1*՚]8Ib20eR1HԚHi(X˳4a`xl5RzYd8RJ VO$i i5XhԌGf0Ň`rzV{oQ5"ޚ]RC]۸c( 2fF##30;gH0qzT':03l#d7IsW㚷{`lz!r*+NS wqQ<[PEy{  Y4cMm&w5 W{Kx_>DШus\BDj|dˈ)DCDֽi# 5Y;Ren*fuSL5":v!IG( a!R*L>N)gb bTj\(HC"zM mIvL˾)8IJPvR#" uVHN"QHtQ}jQlL0L0L0L0L0L0Li6b׋͞+xMn'Oۦm>zae]]5eϺ7i~vqS۵'o\/kv\𝴩pn11O[69$j*ɺ ACCRU"޼reŶʱδ JQbBAېiFg'g&bL"R)JC" ij|j]PV$GdmAۚp,inm: N+jyrg$Q 4ҩۋFci1 !i_dQ/vLez̍{Eݰu+dkh͋.D +h96p'FޮEg[|g3pPn2+wkX]/su. ;@>.V3rM $i,ˤ(rS1Lr+F,NI"EH6$D}}fxPB@rLL I z@xj`)&;:FCP8/Y;]1+cГ1tqYPdej\D)S JF"LA 9O5Ҧ/JèW5JO?hٲ#ВB{Lo2זi…FhҞ-Z&TiB8͵i. (v,JB7AjXJդoi i'RzsM^ЖiƬc,# I6{v7ӊhm,q!_dXk<ҳ2’C N & q@eDV^diZ2l]^-L˔d Vt $^}l C ̍vd娊(S*1+1) LKĈ SFiVa;`>tRrXin<:intr/$o..;[O;[O,AF;`>t"in<:in/$o. K( xîx;`>tr/$o..;[O;[O,AF;`>t"in<:in/$o. K( xîx;`>tr/$o..;[O;[O,AF;`>t"in<:in/$o. K( xîx;`>tr/$o..;[O;[O,AF;`>t"in<:in^R>C]%0 /:m{ X0BifXL&c$cba HB0餍ZrI<XO)Q9q Zpȁzڥ ى FP%LE& < a"y;%|no[x:C]2RgɱQkyrp!N6] ҷ} b5wis3PK54:5L6PebjVH, h) \V8 Z-HTG7vW.:rD*BbµS2bQtn^U9 =òIFk|ݳokumYSpn]fyطyvlj R(znpH[ˢMJ/nd)c/.kmS~u.AuIyB0W2W["p:r>%S',(?j_iTҝ7@vP\ }γ=W>'4HG*=3MàOQbZF۽M>:tS/SRN nΣiEpaAxЇ]l,K ҀTd!R'~7A5mʑHJoZ%%&=T$]bQsۅQ\/V(3a-{,n/7<( q]1R\h]6lf.ߏ~]yqw E:X%u2W) #=E&ҡ'#^< ӥM=i/]nu dK[nnPK.C㯧9Zܡ"a"a"a"a"a"cr}.~mcr}.~mcEGu=y-j)BVvҞyfŠb&K ل4X0{cw\y,D# 䙉d#ixB2kiK;p[BP]BXvQ !_aQaB1DCX㦑5Ca_A{R4d9-Ueq#"BK@0Ls9ň *yKa7#uÝͭa4CI~XϘyMXđ]h\QHJ([xj^Zbt2$*Jmˌ:LjjJY vmbf86~b1J\?5qә #69"^ Dڒ`J"F7h_^o~|PX/7\r9Cf2FH,TFthP!i+tm}0,A1u*VϗY:OI32쌰ؤIpcrL֜-ۧy*,+#6!Ij+u $‹iCUYO9Wׯ) gd9Į׵YBCi}cFx`J;]͏83j {'"zjt9#ce$jiMHxe8 QOW B {߿š~yƾnAfˌWmM..(y!n뛳dk%KjEa)˒f 'B޲M3A'䪁[ǎ*%zˮgũ2J3njth:2!*N]9nJLZQMq>l $ǯ1: nsĎjb\m&V#M,:ÝkIRHS5\aԑջlq뻫7}t0JަIP~sY4hʱH 5E62D'U,JjCH*uܵ@s2'=z!JB$}2iRB]a [ @!]f2jSLӃNZKęTy]ރJӴRJtҺf?+~xn@$fǥl:g; JBUU'7BKLE[4"B]fFȵHnr~0`t i+g Ĥlyj9YfEClj|>ٞձEM_rɞZ]mQ;tW1rgY$aŝ4)A.jr/+o28]a|Cljk+ĶwW0mo=&=r:h< MV[VP5! bh" Tpx3K) {͹rUnmNf~J~̫3 xBk[9WI˾0V`Ф. Q'zS3ڶ#]ZܽJRrձ2MPU">4CMV<2(K:0/)0E.p0qmcJe\ ͋%.'F9c?K[^fN ǶD7&H&V:" ) b G$kɄ§K mws[3ڶ9^.mz$#oYoa{]F!* S[*%l=P(n[bhތSSu 0(Dۥْ9[o$Jl B$ UN|VHQᡙ)E@nz\QkHHvKTKDZH Ae=_\fT..JMDФ\*[ @$j (kfSjC 2Un憕ThǒbX3͊ߜ7p>\iF%+oβ:$̐͒,;,͏vt^ej{*(|b0Ev_!϶gl>Clj8kpm~ xFiw #ափblG)tbM+ Я۱'UF%A Bـ^һ?UvM'y tFKݜPNR.Clj{ePkQ< \AnNDpHz+?A~s9vpH+'Sz*%`)T0"t VFf~fjU: ) M >v "j+Ȼ}=af{V ,oXbָ8fU]ܣqc`Yz]3ʤtT(V^/Fx}U]"iq]RTq357y *^!5˅R-@MZѡR$TSa{+uQBߵS^,`id:HC_@f]ZܽJRrձ2MPU">4CMV<2(K:0/)0E.p0qmcJeR?s[a_\_L ȯȫuaf9\j,3-\ǵ -vd#5Gd4[ bG7bRD56yRo_!϶gl>Clj.vw6f|v5 nV鏨ͽxO zHܣsˢ9;"TJ,{|dpJ۽\tKv%mrוv_p:٠'hvLט$G*oo! e\!#D]|>ٞհ}=c^Ց{J3Y|ț#0ZKxWpٔ٣J[k+Oف̥$M5&NV'\kJ'2q?_?IN>k87uw{}zsr:>ۉ_o?"sYFqX9" #/P!-i"431JL Iti}scRRf$")5BpM=΍3V$fvYn׼˸tJ_OШI("Rǩ[&)9nI zo-n!M6nj0C![RLOݍ~tlv6tr/$o.8Ί@C!؇|@Mg἖Y1 1H]>i!{:'ڇ;Es2 pgpI"U$37y:T#NsznLu:X]&j)MC(NȊўѺ 9pmiҸ߀"Jb&jS)[B9y8“j P)IyWw| y#x|p0^H:\wn6_0|ϝϒknF߉{&˴K4*hipRdteCaHZ,* akjp0 !X/$o. K-KqoYTN߶=W/\=7{z_t~=0^H:\9gw 7ΗZ,Nin)Ր?{D-g,vOi(Bő{;n8*-"BwVu3չQayzy@At_pꒄ'ήgO;`>tr/$o.;VopHt*Shшs'R" -)JPXXD JT$/!3d&f5i@[iX;=L|T^U6.e".Pdr;cLJL9 ɭ3G&*V ,` K,AFERx/w]`{uIBqWq}3M eJjSe^-D޵$!4}h70`A"G{Ç8S5Dם%ilw| y#x|p0^H:\h\$8wKu;m%q[z-R%Ad)Q9.=,ܿ"wJ[:N n(N2|/)9?߿:߽< K,AFctsnMbH䭽wU0O""rh+ ?o3qK߻|9gw 7ΗIC.Dn|Ѐ%B̗kRс U ZEpJ4H2xƥ uDr4Vifl5F' -V;sͷVj iM6fve]! !>uVjmG]ZJp4Bö:=b`uk$#zޣf#fRqiK<:)20Mÿ l-aw+RSo۴ܺMX'FKta9Z9b!Af2V4a,6r0!Bղ(Fӿ1_~iIČ̭>(f6JTpK ^4'+XKp4ibۈ;KitG4ЌOG|n j+iD5SഘNCW -mYpOQ1ڌsf~TTY# KDI#05א^\n^aOwayx">r݊)k3M&nUeqhbkHd| cPl6%[ЩH\%Wj--mfl?1츅>QG%LUmER$ŮZk"s3tOJju&FUTf f >5ؓy( J0|nA[5>x4BbG%,2UNam 5Mps@H$HE"\s ܼ<j9^r E}{/ܾPR9Ԫ28"."WApT!2 jj"79[0WRj+|y/yЍ5v/}"0w$h{9]|m9ku7d7'aUCIM4Tqs9u8m]vźN۵!Zg-S+n^aOwbƧÿδS?Wu:3Sjܼ<j9^r E}{_;E>3}nwYџҟwVTvg-S+ز0Z)qsΌnwZ7/0ZWܼ<j9^ŗ?:O_[w7tgsաyx">r݆Tv, ;w֊}g3?>[֭ 37/0ZWeaÿδS?Wu)zhn^aOwayx">r݋/~uw;o OuCr E}{ 3Y~wgsxgFJ}޷;Zg-S+n^aOwbÿh~;:3Sjܼ<j9^r E}{_;E>3}nwYџҟwVTvg-S+ز0Z)qsΌnwZ7/0ZWܼ<j9^ŗ?:O_[w7tgsաyx">r݆Tv, ;w֊}g3?>[֮Jf/PoO,^SLs)4TCH(c\Ҕ1j%_{Th*ys*霈0 DĠ@ $kV(Ij =RֲmSm7'hV"C.]7 M{ƧWVnM4H0\aa5 QOTxNCՐ%HC> :U%$~!V19p5w ub=_DsX#?.`Fwd\0ü'/4+[wMi}7{`Fwd\u9rpnwY6#ѥO޷;9roOˏ ;xCO¿ougt؏F?zoOˇX#?.< 0 K >w ub=_DsX#?.`Fwd\0ü'/4+[wMi}7{`Fwd\u9rpnwY6#ѥO޷;9roOˏ ;xCO¿ougt؏F?zoOˇX#?.< 0 K >w ub=_DsX#?.`Fwd\0ü'/4+[wMi}7{`Fwd\u9rpnwY6#ѥO޷;$& <-R`X^vb>hA Vd2Hި(K@IVJh;HRCuJ]AJG tQ<ʓ*aGuCRO FJ%eŀ8;lnd_8+8+J( IK~K~<1&q/gWq/gW"ęĿX _ĿX _3g`6~~`6~~( IK~K~<1&q/gWq/gW"ęĿX _ĿX _3g`6~~`6~~( IK~K~<1&q/gWq/gW"ęĿX _ĿX _3g`6~~`6~~( IK~K~<1&q/gWq/gW"63U1V4H/95^HȒ!ᶪF$8/ "T zb)s"xIVlZUG8g33 &)b7U䒽#Ie-J\:SJ}CjD5@% JppGK"XL*\PaKH 2Aǂ̈įMƄD$ٳSNg#XB0FRC:FڏlcA^e6ݺ˳UYKz-41_01hx7aD 1dLHeRDy(3~{iU-W N̓dkU٧VjlMR<Ęk?ӡD᧯W0᧯W1)3?e_Æ?e_gzl|zl|"8iU `鐄ey-IS$C!*R?1"m)lF! 0 ^gZ KMxr{ι-᧯W0᧯W1)3?e_Æ?e_gzl|zl|"8iU cK"T~U!cC=UXI+H,u|r=ö1: {Є!Oņ+ 0ĢbLTz\&*=.Z|FxꫮeunF!{LQb)iZ܀(,U3a89RZfTpzEXT`lc> 3 S/'\{֛&N GݱJ&$LRK HUp=<*J( ۺw`KX8U wԡWۿE ˋ';sd2MJ),&X*]LSɭ+q e.!$-ٿA̘ۃxܵZGBnaam~x\L:Lѵ-(V_*# Ce#d4w2W240eaF6ѼOGSU D#: QIQE@N08MR>Vq'XX?*BqWq}3}r~3>u~7z?i\1+RY |坤[k$/jq=)mf34"=,(釹$3yԩ:p@uMm An陜mS|b##zUFEGhQ+3d( WƦ.#)e2TG*-ŵqկso_hqֻzR2xϺ`oLna &lm{xrߢP>r{"J龜+z [(UsӎdvlCyc=\Aňw/?Lg럏 "IgfLb채ͣpNmDMꋣ%ވ5zU 02C>;,-8/k#R&!a֦Eŵ]X]YؗϲhJ[t:94:2vu.\3u@;Έ=Jw֦t[ BtG ͣ sd.A島FsqVW,KV\KlH=fkvWJ5$6M jDD2S59%2s*R(+}V+qU)LʟhxϨ &b"G0aEaTL"Ӊr:&I%OU*ebe!O:$ŁB8C+  iӔs-nj`VױG +ux{#n[zBGeA%#hijz;  yl6x*sL`n";3T]$L-t,쇧)\ޤFj 5- V $8P*g Uejh%7!b7X_{n>P9{%M[{oÎj1p˛ۊ},B/\=7{z_t~=){yehicOŮ#fMvM ,ng?\]|њ=2t\fuA8ĺJ֋dvj"T%\ۡ`w-\CrsWtB4NqcF(d ymbdZhV;6D`ڲ|j/XJh%7!b7X_{n>P9{>ڙeVEbϵr5cJ3~>R)S @3PVP" ("Jrfk-"ɞC9dʲbYdec );e^Qx(3V'o0oޣfH~1&P i~- 69p/YwtxwU^UCSJW:fmӑi9kH*L q2VF'AK bKࡕ ވz4˱"Hכ(q?0ޑPT ~}#^o`zF?CwP'``hqKF)0V^PաR]&,&2FRFi#ka߮&PG&fJT&)hH--:S#&Ԑ;3<5h0~(ʝz]Ye ]jV=F[˷mZv=LZ*,igml!wUMF1:w\HwaLa"2'osEDdGQDhYN0yEJT%Ud8P1UBS)*M jT|G񽍮LjT&*%!_-E!ZdA˷- KB* VZ4B3kgT|G~H 97Oy/Qob}ߩsxoԞ)V7( *?>^?Rx[Ϝ'GUx{7>Ԟ)V7Io>sx"^?*?O'GURx[Ϝ/7:㻨3H.z/#4'%ǁq I,:*A%>NV'GURx[ϜUZ+lI1j0JS-~<Xp#Q('@660bsM4Nw*?O'GURx[Ϝ/7x{Io>sxoԞ)V7( *?>^?Rx[Ϝ'GUx{7ՌF/?@Z=nQ"B>RJM.I.S,a 2m<#REIJS`Vx9|@3QLPR8])%PSYJ@V:MQؤ:%bꂪ"*W &j+I ͳ-lr1oBW3J"R*V" bꂪ"QTW fj(˛a&a&a.;I$MjsMc.J2:ͬ654 %=a5JxI>ڌ2ZxK<4MRhFMpYG.{,i 0|rI0\vͤ#f-]Y'eG*e6!WRX3i,ЗY 4!!,zfaaÔ~ uMڎ3a?Lw:GYa&a&a*n{Qk c.0uku *5jEY x$ gj1.jpVNTwWt6^0k2 oKc\&Z6P7% "t/-xb&Y3)z54^MݷwkOYǵ ^nnWM|>Ku:9@x$NK?o^5q7;L?U-A)Ӎۈ,jvvtLm˙M؈çd@Z(05 ؠ dT|(b|lZ86$Alm*Vi.Ql/h7jS|H995[ĚzmՋtM醓;()N2!O=GoRFm5͖4y[ԫR_lxW\ucvJXH5 $=DJo0x Y$llrBs֊rOۢ_8OZeZd1Yok% )vʆD a!MaJA)Hv]|:ߨ;{q &^d &,UkjU3b iBTBabu kb 39WTwd\׽qlT㑪uvLšbVHswIK0.qθY )bY28V5Wh"[Zu&ozbC! "Ii-->wPh} /!*H{DнdX:(f!$r&ӵJ,Jfv:`M Y&:Y][e{t|%j&"Z ۈn%kNk8Vw* Ug;V[a&a&a,! fO! fO)_ 0 0 0}d+k* iM3 z$*ԜBh.2_Xjiޱk^ jA„Ny(JqJ!VF04{]!Mbͷ΋l)BFRڪBkeOџn3r u$ٌBgk]qgXlfNe}ʛ)VM6ڏdRi6k{uŜ-|։bQ0 1WF$. Ftb9@ @g @\)u^H%a\.*bjQH5maf?qREO۽Pec񫗥kdt߈ہnF WIYUPqS`bO\9!I 4̉Y! esP\xBK[4^Anh?p ˏRTahe0E:`I h)2]><_Ed=9>sص9ՑfmѻU828vE5^'IMTE<5.1jXZņbeFdzſQȲ|hDoAV6zEhX##.~`u5upsŽ .bD(Z5n^hЍMf# vBLV6Y$%6M'cY[` @2$`h&rPbxusE]IV09Ɠ`NW".^L֋EI1lE΂rbJD"\R:OSTK tqZrDAjT(Se7LBQq 0ekX„f@r|:zTjQ>6[VSQ4e!2G][[Yn^soIog ycQf1bmhh ck@kZ닼1Q6لS^>i*tYapV"#Nijܼ1ɌS,[n8#b#4Ͷ&4p30K\PCd d\^aBA4*DpbZhT/ *jQ5cjcY[8Rv#6k9X}NxP4G0|3Ge&fs&uSy&8<7I+Z cdYx[[mu="MsjEF@DEs|S z5\NF&8q-iJEݒ{.Iɥ A=g02XV֡7ql޶fBv TBom3 en)ZWGo$֕)^[]:MT8szZDH*d 2*3v3968 DO)1Oj%*lˮu3Ff+u,xqݷViqN֢P5%(@< Ԗ.0ZS\_)IxBה0iě\h021(:3QƊ8W^z1Q5yT:Ją,S8Mi9Mr1 (  S/-X!E'Bg ]$3 9<%i1j`j`S!N&DP QFab@qBL& _|Mi^pxRN!F<ۦ;^Ns~rg! _#r(j< SJE?nl U|C|o"6%l4vP9I7ye011 1`Р l&~50 mi=ԫ]\ orKJݻ*V=%fƹN@4B -06"w _|Mi^pxn)ZWK.岴)U\y5pk,vҭQ+pFS7iLA P+"@&{o\{]uQ*l@\@CjQF(NN]]pSJP3J6eό* _|Mi^pxn)ZWuH0tں % @%Z@a^rrTsI4TM\ssׯ^ "U<4fM'IFp ' @ #Z.pv9JRY"p 0 0 pW݃SN-4.K~=XBhOv4vc! ac+Ƶ\Vh@TB \*I6yIfjFY![A翴C/#ӫGdbq?pTu:*R*TeP %AeH5BmҤ.¤5;`>t$`-]dQc3OOb21Ȟ:r˵65[1c6LjfRrXaܳ K,AF1PYÖw| y#x|q,;w| y#x|p0^H:\f8`0^H:\9gw 7Η"ùgw 7ΗYcYÖw| y#x|qA5Ƴs#SrhBz] cbsPebU[]k=XMVYBxZ[pnLv85JJem @1 2gFBƘj!Vdnk##-Lp]4EڈipS\ݕ=D5e`׆4V_6/$o. KUAz:,zك"ۦb%&LԨ Z":Ja%ehSr ^D%F3VPmet|L3$_CUqw,(׫ljk/E֙8f0YcTeRlU.ygw 7ΗY '3^]֥t2|xSҤsp;V1^mTu譍&Y7UPg#B#LJI4_gțg©mbjgP - `R("A(r\RYXD;pr E#Ez\ K,AFUnzӼI7\״ ^\XyPᱚa }GZƮ{bYRMK"SۚwoHq}'#TPtK--2eN&[M( '׆KmS6*NukfA}Q"zQP ) sk}bՑLX -(Mex/ůe^=_&~+Jnk$诌4yن"a"a"a"a"cr}.~mcr}.~mcE'vVykfz6&ښUBy; JJ2q>bwJG_\ T}eʬA²Hی1L3,&aj%ʸE*ɗB$JV|?x{xJx G/ s5eofG23kRk%Ċe,|)'="HU:6[!_>?^]Z=*U|8 vʊ [ҫ@ö{pFoF,bIR D]ݚŜdzpɝ\ oG,*.[x]BVk"ڜwjSq&ܡ ;l05w&ܽuc%N]"U(movY[ڙqs\봏viC[72~К.pmzBvB,K@&2j AU${hևiΰqk䙯em#F8p@(I C2EB~G=2<8#%hZje2Er|&I&RTPe6B9Y}>FV)a1!1`PEEC.80a臣N\hU[e%#"_=] \;Ȧ g5zw(dѩ$S$k:HbJ& `Cvf94zỳgej$or1zYlcئ mmC52ƪbxB J2&ѸKn2eD\'Kv8"J,]*Dߵ9xj$ 1:bhfvʒr \Nq5Eo9B5܃ZǨL+D@0Z ֘ǽt.g88W|$e] nγl7Ȼ_B&"Z$ƺpʄZzR4!S$~gٮaY\Zr]u0޵ٓ pDz_iUp nZع=[rS8ɹsPFΜ'j7VqDlB7(Dܧ+aItNs'G_G+mťi*G5bWkZzT^6Ԏm!sO&It阭 B@*Ӑaq%)Kz",: M2{m2~0XmJ*O$ ASSq\O}mXqq۽-RA.s~qOE &oK5<ÑK[EYV#fyxY$!8{.v/~7K7T"o*f!0׶ɜ_3]eIUT"pW "Q5lTkiM2㮭+jNL)%kZf q 5n|۾E7Hd(<6UM8I@VCqEFīhA:ԋPAcXrDZ"8Rb*JP>$j mYHL+MOQDeΊ1P8QVIFBWP/*@sMĴ \Es)Vӧ9\ SRWyx0\Ar }ҹtK. P&'%!D @  a`SmLSh}O$)2BU**BL@+#OÅ,&$&, (` =iӔ 0D 0D 0D]Fc1]F`BݽSZVcO!c-"[t@×R26r K}{vޤ$u|WLɎɌ³gN6\ODJy"'>=p$"Aۋ8q*pkn2e(n޵%y(8H﹬}>vA},cru%_[|;FpXDy` u:&[ۍ+xɱmGϳڄv:mlaEac]Wyi΢qXAn:E$L몐O[lN6)JpSY$ʼnAE">v2"}@⫼L賰镋T-JMH*|0T!;!X(ՔT9tH# Be/n&*HͽxV[Fv^]'nTᏪ-i8dqR#* ,F^_ُR{L>.ؤ&֨`L ecTfB!.iDQTƆDL a bΉ@T@uI%!;nݷJKjx6@r.rQ "4r,zx#jwA"\1QFl5N!jS/[3;G<[l\ԫk( O\1Z)j Y2P<b0ƻnӚzsۄI2U/^sr$4@ޞ(TŋBIKSb@dD@9 6#L0L0L0L0LaOݍ~tlv3aOݍ~tlv\![<~0*F{3kzڞ,hj2e %Nf$oǶ,Uy}O#u?(ۖxI 64&KUތѧF3Bh GŻbj%BE6-B:ڏGXvwqmiD 1(aaa;fk:FᮋNI9;4e4 /O-/,(ॣ h h$ځuAUJL -mDxԍ𒁶zbYO$h>^lx\X.}`Nn_i֒ScisBkwo[<[] KH7nљ%zx"W*Ã'9z('),h`ke5 [)!OEK4U^1<;pDW|$_3ObH3@ Ea{'Ӎ$pO,[-FOq@  742XrHrX(*6dX=gaGT`,;Np-x$G\^[IYjy8֔wP7뭩 eFovp [rm"-Pیo XD(g<)Yv|6 m;U"WN)H75EGIHȔϯ0E9^]U/VVJPrڙucFvJŠȪ q@v5HBukI!p6ȡ/vfNCQ$N ʬfUsHu-ܛS~e#>&rC=YqNxƤr*֨W[`~X w[ےYZErn넶~LaOTK&^/ʥ:f!(wÆN-aYhOUZjhHY&O8PPvxXN&eg``j8.PwqNFc=NK<ʮFڊcJƮݩv yrm9P@Z[JN63pꇨEv㝭:+!*uZ7ePIw锍*żJ}P8C6dLf\Eȋ $*7˩Eumϕ\^.u<e֓ޯI7r})[K`- Yq(.6.)F Ujm) ։c:<."VjB85}2Vv Q eؚi)r fkAOӹ.lHQ;UN3B%"Č4e2*CpJ,NWG*HB|2 -"B5͓mQz\[|9e^5{j< n'N\]&p&L<'AK+SYX"|ɻdZ+pd9z)]hdZ(oZ'5n`JB,Y,Ւ*4ʲPJtȮ时4Kq k_$Sqtp檾+J8G%MBB476[ӠJ3 K]b4(]ZW8GEYO@zd2\܁[>M#!nVSVT!N- QHjScɑgnj¿KhQ_0i8|H9iɜDҚ#JSn-)&臶r3&;uiԼ&Dog.s[qޣ@ކI;#,9l%⓯U2!l%:@ /L0L0L0L0LaOݍ~tlv3aOݍ~tlvN@=[ܧ)5v-Xb2HN!4k6&z1_7m,BnV^ZelO=uN3V٪f+򱣑U5J2shc) Wjde1m8hْRXB\,^0!6D:G#4=Ǒf@..&j.lڎ5=nwpTD+Jb% '[:#hG&!(D6y]( QT̪m1;x٫AG-oMmCgIJA[pP;EAB7A; (GS/w9c^/ap[5u6RY[prD\xę X2jY"VISTxJt\B#AR5QӔWц*yb\@f$[X&Ivm.hPD9qEn6Xdɔ :"A3lEsƱ1==pxg͛f R.9BfQsl)$/%"IQ $]aZ@6"Iq@"WFCfKZ$IVmkpJ a:#=\5%Fnr'bF B!,d́ǻ ibÜ+A =m,W舫u2Fvq$8ZN磔⾐7B=V뮺u  p`_TJ}<&H5' *G(YDf i*)JK5(R66$mع竞 ZX&:zjjx4 C]$K#q>GkK lpW`/)ܳz4' Q ZK#+ԘpZE%4)(K)$V1$lE+/1<3YCYP{{",N|oc[y[MC$z.+0k%9x5٪4.!}p#ܗʵ[~[{ׁLF!Æt s[4ЧFz[BfHJ<6=Jy}~T gjRR kD[9,9m} G(O(ď&ҕ#il t79ۋdzxuۣo}ۥ/~!B2˞l:nezSRJj=ЩgGAHV06O7"1BB6ڔoeAڻ4bnYsۀ&v@j`^gHBu0{V*n ŷA躋tńL1#@'QbT @ ]4dAqF}65)DJR޷m*\ )2"jbSMf9(vt雗u5Na正FݺʝTM2xTʓV !iJB4̆j7]aTCn-Iaq=l^& Y^n#KTN5^[VwMmɺ8iIՁX1qBdp~n5T™ aVy?MTH&ajpxxTݒȐmh5$>9zawM݃RB]sl;9:| :iǭ钸qPݻB*+˓C 0sv{cosv{co.;9!%[F9ћ9h^X{[ZzaiN0@.c.FIg Ulyl54a+];܂%95҉lp2F[Ϛ+hdgm\ &3t"V$*;Zx/_ S+3d mn[{HqYxaD#UmIW.v^XMZQ ߾ESy rFc:}=GVn#Hi[_ڔZmVVT*fຫSr@콋i7I5.a(l8.#kBjtM (V@Gcg[hҬHz‹L)<;poޕ/xwk G4B ڮ$My4;4%) |l; աJp-- uQϊ_&u]z񫈻ͭgyn"O=ie]wVq zlrFh;ZTaTPG'ig(45JStGL>LY(R"ӷ=X.ök Q+tԫ\Azs,(en"a6|B6 X?w16]h+R[ZWZ*ץG8#+VB a(Nޱp{FIgw7u>Eo@'M'MDtGIs^eҀ9nwJRJ8bl#wmq{w8&`]4Kp*cp-r.c [THBiѦwe2pSgMEKkV Μ3F@5\D|iiS*'6> !Yĸg`f]*cApyjeJss"mشG4լH`)GN#.!;+s|yiI95'T!LHG' *}=%i`Za;;b4XX]r.'m$ng[쒜:yejXgdYcc4zC]5ŬbIFi. d#BZa54wuŪb['Qa"a"a"a"a"a";s/v5o-T#KE`q2ݽkyJS0sYh:|8s Kmmu{[K rŵPn8gb’ȧBZ3YlLJq,W1|\^>?}&SbKIA*EdT e!2mX=2hOT1q"1PDdaq"Jvn.6r$ⷡǮXt"B+uALQL(L )-Gku@2 ?5,%*t'gܻ鸟;1q*ˀi ^S7OjLҵJ54']mbpAoQxs*)Ջϵ:;L*M`lT$4@ޞ(J LgsS3 Ȉ8"a"a"a"a"a"a"a"a"cr}.~mcr}.~mcEov%u(B1eIikXCk 1wb%ڴSF5m$c,c%I!6a6 cњ=!<"vf~Ӆd:dIdh,)[$?cC՚1VVE)&{ղ"8˞#ތc߇}aۋRlQ0 J&5ݤNQE[֮-$1J[l `ǖP #G)NL’39'.k\-0"QӫXgsj^8 m.&mcr.R(l!ꋄv\BF\Q7 iqQ\ 4(7oԄVS&ib$IRdeRLj8MhxP XLHLXQ 0`!ԩ/c>v*ۇtTL/࿐߷zRbg1+W)nޚ}kbهa0 m89;v@7큃S6^7I=ͣJ倈}8^dۉuK9$MzV?]/W.S&Հ%Tbjdȣ!9b0@NjĪIG H3.B ݇R$[ ۀϜWGH[j.~D}R\7^U]yH5yڤBJ3 LƤH  LPK%2vbJ\ zzC¢rtKEw\2` S5q@vʦߍ79JD |^Inq⒢q^RD/8?D;"Q:xp_rtvȕ[}C97q-'yۆd];~qC}ESNoӼ8zڅcE:ٸJ2cB%']36{{:] Yee2pDK5/sv^A-V0ZU6yJ5nzsQVy#єVQ:@E ڶR\R{J[ޜgHtS&։$V$UJd2j8MhFOXrHrX()Qp @ 0S72Hا2Js]i ePYsn\I)BBY4:QBRCZe0@Bxf )i2l` 2ﶸ%[",1IFs}ag91-gv RoQ~ĵ}uG~LKY݂+g91-gvFs}`&G~LKY݇Q~ĵ}",1^m8jk̟+z9dDNu:eBOSfnOL0B݁A*+^@RD 0D]Fc1]F`Rzs],=>gi&c EuN0݉u˦W`zKu-c:ib+:l[M";#ڟj1#Թ#ٗItdt8UN6<,.DMI4l댽쎲lCqiQ0 J&bVI$zt@â"`wP$ʔg^r dث%j: U&Hѧ,$QN7] nsOA0E3u۟~}ц>4Q\eA)ECaT._" D@aIm E.+$]:Eԅ'7Ȣ!%W40 m_RKPkPnjS llͳ̻0ƴzk6}o{ 1b(WN JMm֍13OIfYe٥RH~4~hme-ɽK?-8Yb6i9M(څl7T$C^-D*I3+qtV(XZj70Ee3gomi#Jrw4bqIʑNVӟVW7K=iJdjUYR=9Zxj)q͕ۥ-V:sNWK(g{׵C6t*͛tKp.+؂DSoێQcoMNQܫwew| f'In+8B iĊ`v9Jg i ZoM "剑^^sOzc(Gf4xߧE?0EZ9ލR$Eص쪬?/گʋt]ٱ2q[lMoMp}B"D*$8jAXn2p'_mӜ>t7;uwǫXވ®'|b|ocE)C^xw 3U]I1}fVmV6VEuVDB7DQS/R (Ë*x2潻unH#/юרou24(-d,S@v[4ZM[[?jB$NSNDf踃[͋eZ֯E2WV5DRj\T#7e9om)O/@tn˟:=E!1Ydm)/2; +\`jL#Ij/H7c0b&jÎFq4NeBXܻairk1mZBwir<*K2sF1L)&D9 !U7n<ʉ0d8,A͙leeEm[C\GHn4;VLm=6ԡkWVB" V3HҦii۱奋ݗAi_~8 [%p*6;wTy7vy>aB| F/a-&'Ks܊*;b:"Hۖ1er$T)tz읆@gCsJct¡Ec)&C"4vs:#HTſ;kw8{qL[[z^+rU2{ŕ:q= ܓ"8h|߬a  Q\EZ0r |d)RkTS@-\` Rz%Bݓ/AD܃\ƹ(쵈ܤɊHT.5t:Oר.k) (An4\Z4Y@d;Nd)s0"/6h©l-Rvtk $u!bt)pՊITTP gItG-MB-EEB] YFk'(_yR&;d,@Mu>qXK܉cnMe5X0P&D"`6TƩ[E F{ꨔ˥:׵s۝djN1G|R?E )货AIS,!v܄h)ôwDLHȋ6Hۂ_tHL\Zl `ͫk& (J*d@K8T'g:T~f-ЕfmNz9;`ʙ_$[W(8S[%SlwD$fd,'8 '1OsKmn sz3y[m-*z7d!4;q1JX`n\u V!86>*R;" P5*E;B7RG-HE%UShܻ ,tقJ9 JP 1kRgv6ѱq9>gv6ѱ"ᗻ xݮBmmλZD >1׳]{z1wb5Bv֫N &df8I4HTQ1BBnV'a&i1gJ.!aJa1 oV2F^^Na/lkFxtů #$uCf0׫bYc b0yϬbQ1>IJ)lm OUcB 8!3RPg1ry@H Mi j.B7pH_n6 j.B7pH_n6 W:^VNu^ݽ_ݮ67ˡ%'߽|t_4y~_^K{:! +F2wP A'ዋAV6ҢKƋ "M3T* Ii)aDe0E<\ ~ËC!~?Ѹ0E<\ ~ËC!~?Ѹ0E#Xgi|!Ҭ{0R-4?kIKA=;H9㰅 HM72%+0Ÿˡmv".]ԅo?Fˡmv".]ԅo?Fˡmv".]ԅo?Fˡmv"/z\^Ujj&"-r *;+P#ʂ !LYʀ$9;Tqr~/y7]GC!~?Ѹqr~/y7]GC!~?Ѹqr~/y71-e[t8|-yxT (UЉz0րue7ϚJQ [  #2=3GaNW."GʶҮSy=8H0U,΁P@i—W <)"4WNtÃnj4J  ƫ 7q~&HA3äqLzMcۤ~j6D 0D 0EZ+aZϢܸSQqX63O׷zn.q`ȃ {v"F3rMtTҊR 3*9݉*!+K۸TQf^95ԋe#6@í! Ee:ǕTpɏ=#~C%SfꬎV$ڨ_G &{FtyPscN2i}zeTJ+8‚[^N5oSr[\M**wve2\^\&ԃNUԬ],p-,xZ FIjpj]i):tb0P(/e|\q <oe{m=nҖr)#[]M3yi[[#$Wk' oIqwF ͖sЪ>ry%B(.pue"7M).-GJ0z3g-Yյ3GRGlR#r8F@6`kt;gF1.yIteg4թHMh-v6Xc7Eo"i2o[˂㺢TJC!UPEM,](bwp5hᑻnS@J\v8w0;93 a58͟ R<-oڑpBAG\BդeEAMRhd$}ؐc\Lp)|8lNXE6\ע0Ͳ&E4RqXV{iE'hB22_T'_9AC7յLJe>2"mjP*Tib,xRHH*cET.y-*pTEa9r+5&[ާVʲ$#E-TiArR;H vW5 0TXJo`zg#)ݬï6r?XϽ]"޼bwk>p͜'vGe76r?XϽ:g#)ݬa*M͜'vGbwk>qvX`zg#)ݬï6r?XϽ]"޼bwk>p͜'vGe76r?XϽ:g#)ݬa*M͜'vGvY ޭf%s֤Oi˷0@vaLjHxV\tB8 ʦ@QۼO'z<:0j<`*S^J.4Kf.L7-xqg''F]e5EL*L Njy$LȟH&}2Ypɝst_١c. j\4=ѱZKw86A>tSZJ(Sz*U*S rw3M D /Dߡ:gKN}1hׇd|.:WUں[ ,Zj(&)&79. 7nc}aÆ*y}37Yp]sߥY-.j[=QH8)AtT٢,JS 3*uLPmL0LaOݍ~tlv3aOݍ~tlvef7wk>R]b1=k& vc.f%5#6eل&*=i a,"eVdYfȖ#$Ж03F=F## Z*#4lڄ2&6Sla6ф;nqk" fTFpfJPy`Ѵd,TCP$e9<$$цY}))yKE0ł'q=rbVɉ*MFjSjSONSђ3ӒhY%0Y}6MY})) Y})) Y}6 Y}6MY})) Y})) Y}6 Y}6MY})) Y})) Y}6{+k^uYCE*3\d(9-2^\ؤpҳ0uv.(uCJr- 0D 0D 0D 0D 0D K)7( no7ЯCUM*'ۡZ;[R,@ g\o/A8}1F`3g\o/A8}1F`3g\o/AA/[i)rquR5S!hB&aJ&Du 0^iXsj R$0c3 ȣV<*&MQ5UMrh8Q|Q&vң|S,EL|_YU8p24:XZD:7p8ZE`赏 oԹ#E:cF";FN1bCwhjJdUz\Q>A=6E" |RϱJIe۩<&jy1|.0L_/ј"T!nCtM(E}6 S}|.]']Leow!.<Ȋ&OK5ęE30L_/ј"ęE30L_/ј"9>gv6ѱ،my|tX(L+Izq0LM 4ѡN@%BQ^RR^!Y9X@eE@ ]F`>!wZZFF(Tx${)FaBԳBx }~$LF:p oK!gYveLuLu؆ZxsUvI*14. iex-J4zF ,OE̖ʁiՎk$ xSd) "nQ{f |"_k-]eyPPr@G y[-[Ĕ\kdp;vk]ӭGTdٟFQxܐ@6iȷ>#~nL2s,lBSd(p}>+MQ6BEEA!ID2HY rK1JMgj7Z^qok+&B9k8K D )Ȇ ym&kk!w3~Xmd2,,B8JE[z;q^Ikb"kboi7%/;N)R9_rsHLQvn8 4x5LzH3LhTjP>,!UXԇbL\c’&S!Y~9jC&u)$1$u%TCXXplS&։$V$UJd2j8MhFOXrHrX()Qp @ 0S6^^sO]Q24$jND`F0-mu9!!jWS,ث$lTzsiDJR޷m*\ )2"jbql}2nKs; ZSX4Zu^M/(J #`4G7hM*B:U@z8trLۺdS\c'FؘUh5XY˓AkRNdРQU} JՆHUU3ʲiחe_/@ ʼ*'=x( @p fmܤ9ا45?Vq m&7l {F8HpZ`EoWK爞!87տ^?>?=_?0EKʬ'y*F6PID2U@BНdfvgфʍ ȊCܡ/QhK7m_e\| ['>)z&R5C̷=cwTtbї@:[n+q9{fmUn?S%_ҩ #N߶=Z- ʷI5HDx8Ή! !s{]GOsZ+ د 벆}'&V.|ku`*V`_u sLj2F֚1H)WLַe'73K%*ktK_n*FK/j5me̕ZCZA`/2g_ sJ,d0F40+Ga'5p0 !X;_p ْ. 62C %I5(v\Z\25GS&9H^Pah 'Vkl1!}ZތY8ż90 -@59N;3:5Y|[ȅ+a=Z-Y0CwUY+.1m"if3V}:F/JόtӢ1n&5HͽxVÜm`!]'ԜqHj-iZ R"s ,Z%.]?GRgҶc$e'njfv\_$nOc6nT익'W@I\+KQh:`3X}O7}-0%:޺Y\.^(Y].~*) \HvJRxCan5J:F]V8nQG% E"v9Mv^4IXdR;,+;J Q'QaRc`r 8eݿZr^ⓄDhթCa:JzޒFVıDLhyPۿ\0b9PUU;pW>?Ή.;~ȕ-JT᣸(LD7O~ 8 G!Ct:Pp*[kA%dZUe4dj+*kҷu I. iܾfpep跶TU[j^&$tMR*w"O" eQtޘ=Ü"L!*gD3IhָIސso:!dECzNIt!92C/ʄ"B*2ʂn%,媬\^r -˹bXIUH⦱$cn IUՈϊ)7S*ϊ3}| SJHѸmw-%c-wIB$i5Y==8A:@xoGb-}| Sdtp"C%s(C.S18`nK%2"c1Dɂ5 \pT> )2"jbqKjjYE[Eµnm@4K߶!z%ڇ"!QdL A 9xz!;eNVq-q Ӫ)Jo]:?)B~dDOEx! ![1H4NjD<9{(w ~(nWv: *D75I%nmKRAZ,&$ SPDkVPJ"DOPT@# 4L @eAi pS62ot$q}HQ !D*dTLrpK NQ^lv{co ?c՘\K߻|p݃K^ mBk~/F=a cB431j^B2!r 7%ZЧN56iKN]ў:%r2AƵSEMDR@bb&pT-<=҆jlLIDc=:۬6v"ѦNZH)]7j1jl[J`Ae7:pFfdB.$Iqg#Q:Ol[&"8'Ӷe~S-$bԇIGrwmc9#s9PhF=^)浦)p즗'OVi ;unS5Lc|눇{ǐG.sSRx[Ϝ'GUVW6CfWXvzwOg#a #^O6)u{)i,a #M.;{>a"*Oy~H 9~j3g:IC*^0;:WԄ4Խmpj/O-txjóOC0!F:CXhy/қ~H 97Oy7tTN;HXF5)CHGHH!nj<`MB0)JB12u,1a}Xa0~'GURx[Ϝ?5 VjUJZyf%Eii0# #Շt{>ΚFy}HL;c!;5{; 9E\Ԟ)V7Io>sxHy]6Q:hy5ГY͂# O9 a) PD$PXwއQ")7Oy.rQmŝqсA1 c$U(mY;uB̋ 12+j֨:EBo3^uAǿb~c1ь}Xǿ1lpO5ʞa !dV闧vck\?.ZԬ nkR쁻WJJ5ǿi;Ж?eP)XiEGM4ӳ!d#CQ":ZԬ nkR쁻RIV_$COGXi?PcH.fhGԙ,*m5=8x<=]ZϩY@J0VT{dJeBt˥z1 lP;| qpQ |O=9=<ӧKBgTVMb}!!K$$vwǽcv}XB9E [[EƝ 6886V! M D`dd`2+ `<]j† ZBjԯ^ghVsV}7~xҖkPc7 {XL%4cqR*;PK !7ol!B=0g9EuZϩY@j>gw珏Ի5vi}X\ݺF?###F0!esWHȔ,atat]py.:ZԬ nkR쁻s^dT0&=;O##ý;c/ti#1Lǿ&;#;;ai2>o%tZ-ȿɢn{ѥ݉1"b,g[>, SHpFBj&UiU W'l] JzC NA72mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/images/objpanel.jpg0000644000175000017500000050161310504576271026013 0ustar debiandebianJFIFHHCreated with The GIMPCC8"      !1AQaq"9Wx(2VXYi #$&'7Bw%)*68Sh35HRgFGfrv4EUcsDIuW  !1"AQaq#2$TU3BRc%DSV4Cb5e&6Edsu ?gW,[[|_O_:@{=4TT gq3a2dDJVr9˖ez/1h[j|9l 7dˎۭ9m.^, )aˮu;ǒ۫ZJץ;;w~<חӐֲk#~lvb;"?+/]'+/]'<7Ĥă.jNU "h0ɪ[7pH/`!D̯%=jel4x wcq'BQgnu"p!K*xFeSÃM[weH| "7 ׋T1\VIvhA?3N= seҟjh~_ su- ӭ:ҕr֝|YZoN ӳ.+Dƨqfu lIŎ)V_NxkL>ڸ;+Z3oZᎷɚ8 h,ݾ^xC'`מ{}ۏ/xY<||]6m*?+/]'<+/]'<6Ui擔:?NqGZ҃ x]}=zҝkӿ$@X';VztmD;3׭4ʿs4h~J=9yY~~9Ფ׽Z|s֟8ҕpWkZ[Yz֝׭:lF30 wى8hݱ3WRCAI*!Ef]Ǎ|S{O@?}uW+/g-=7Z᮲frV )ӭ|fSwZX>o{8uⓔ:8$GFAAmi5+Zձ ی"Jq\0lB*?+/]'<+/]'<6Ui擔:?NqGZ҃ x]}=zҝkӿ$@X';NHfzWf|iTY~v]'<+/]'<6TkOu!+hN ҕj,ʹooZNN2ƊECo}4nؙRө! $HѢ]Ǎ*_+/]'<+>ũ?zpcpWִfSwO{8uⓔ:84=y+]}A&r laͿnevҝN= sN_]{熫LmN5ͥҾ`~N?E&(kQ: 8M ~ FE{tnUG;#ح4*e2"Jo;7_;7_ vI9We{Qfm_u<1Y3Gױ^# N9=n;/[}{}ۏ/xY<||]6m*?+/]'<+/]'<67LqʹG n')uJqR?CKS֟M> &"SqQ-M קsӆɖ8[}k7R?sm:[IFRX9ɶՁ]|v>jW kV3a#; uw$mvNyY~~9yY~~9= ZWJ /ZVL 4\>uL]\lklxcq㧍<s =*b *)+Ո=@'o~{8%WFTs5B|xS"(>O{io cN]'>+CeQִe.zuiZƅ/O'-]ֽԭkN62 ?^7vfeHu2Q?BTmS{O@?}uW+vז~8ś|v}/uvҽ{+N{XM OKc\g^^i^n\ >u#m#vj_q8=!+.KS@>J| ׳.x>)V_Nxz-O-:cǖˮ{{Jӳǥ%l&Keӭ]ZR^ԍ>w^qȎGFV )Ϧϧ?wiowioJ^xTv{N=lYgܘ_NmzҴҴ umxv̐OXeBƐ_wiowioEƢV 2εw^z9JS udeҵùy/!µ^cOa<﶑ZrcӳtM㞼sN= si׺|WǕ9+*dzV˳ci^J+Yvw;H}i2H)$ nB#>sS_ez炼yY{9jh>_,L]JVۭZV+OexJEwf u:emiׯ_e+Trf}Iy)dsG#7m|{iyYuZSmsNSܬkNZzk$+/#SGw׺k^u]weSk^:q`Ao;ף$nQё)Vx @)V_Nx>)V_Nxy* mH$>νkӧZWzŚ__eiۭZVJҵѷ zAm$D)c є,>A)V_Nx>)V_Nx{UZ.ҙrYgZvSº{ky):W2utֵݼcy/!µ^cOa<﶑owiowioۮkuե-k_u8=! KL|YׯwN^SUۓ mi3Kj)$ ~ vwiowionk۩֕ӏ=Qan}{%VEk;;xU}I~a"Vo#YF'Gezez燹!q`u:K.:{קW^?}[Kkuե-gJ[Z8++J#$Houeo> |@)V_Nx>)V_Nxy.qq$++JZV:WǨNX̟%q].5iZҿw+ lDXG2:\vIzW7J!i5Q#|IEIJvu*sٖ},ʚfa>4WI"Jn(j0~m{=b09v5~["802T~S~+>Z~M9{**/|C{~]##p܀5~EqEikn(#߈U6l?VkVV/Ҹq/ǯ%~(;ćU;yl3(1<=H g7.'a dSTy\i2@w+ִMu{8X#;qR^?LvһjcrVuokVVnֵ:֜GjkbFН7= پk 5&oC!a_cVC=41F :z*x71ZԳjkI) d t~eb\H\Ҹm5Km"Jb|M3,̡FgVxR^(H %r62Aa{s`_R7 ~k馷j?G}.Ӯ)9V :ꩢd~N/|oӃb bEX (m c#;^d}b|z~&[k_Ӳҝ<*Y6^Zj5m1r8Co7`꠩ūRRf-$ɒ < 8_RBX|FO+=G NkUaeh(8<~G6Kca$&e$rRX:Qj)zb<XtXFnڜxsS5"^V^̤^wi#FMD>8x2+‹ (bWbu gq} #1?ge{ۃvI_)8^#mqN/ ȬtzV2}]ADm::7C(J!k%QM|r%IcǖNuEgOggkoNΝ^-Ã-DIq~o3eN)|~?K)ĈthGO#\5#>/`R@yXaqUB- TXMj |WZBfȰl6FYE ;V9|fAY }#`NƐ}yWI bMELBX6^QWE~?#8XB9x^Ff;ג{}#lն!Ѿ^*@M \7 Zzo\'Qf,VsXmEFE;&/ocq#r霔2c;Y '9˳1 'Dj%4 (DFP2޻$(csSVS@v#本NuEӭ+^b+NtZRg׭N<'ɬ̝k6ca532 ;\pOEɔ4ɒ!5Pv3)YgX+K=$SASk߰FǮCP2z{čԱ_%7."y{3-솿i^QMkԏF{ըK<)F\jݵ4U/҈>-:) GeDѶ:<@Ck>p ㊷/D~#(W7gz'FΟ`NƔ(ix-9 d0x.#$ ]is8܍М% tvh$cx#V!%8Gq ta)5SD]$jH2CD\nvw6ձZapAl}54]]0<ˌ*P{aXFwNi{Vc=y+xgٮ6[nJ⡔%pʒ`ըצ91esV|$+Z|ݭ{Zv{i~L3*lmLLݢ3Cl4I%VlR=[ V tZl-=DMi߫N;_L~A믔<}_ttha^gR+XddwCuf br3SsTme?/0,thǬo#\1#>Si) @C|V\QwB/Z㖪P&L׫ z/1z>^YcbCʚ6eGQaWgCO,J.E[Myų.goUEGқV9,7 E*>"NRHGg7gIjWĠ Uuc|+zVf{ v/c o鷍 Z2y[ Ko[Ƕ m` wx|qFu^Y5Ube hy^j&ZcG}VۜRԀeD>\-rZ9rEoF:x,pqW.Qۂ?M/c'~<~"; ǚ!UYrԓkNv^xяY! 6cTG}!\R@yXaqEB- TXEj|WXBXJ*fx!fO_Ƭ:3_+0lbI8|lO zO1r z>^٣[o[cC6mG#xn*:2yepW:t|`=S ۃ+ 7#\w.iؔv8< Հt(5^bF/=xäE8)gcy{pyq/ө>e'ً݀^m]:OfknFf;א<ߍP, ;έ8ajA֪M僖^jNj5^M<׮_Ҿ[OY2ϸ8͜}KZ"V]'m>v#Zazzz9af4#s$O A𞪲ǐ3.V:ב!5qR ((EAuOăIlRVlS\^Z[NTѴc*=+50pUE!~z-JWinc< 6IIsCiyP 33oUxQc!NV'Pv}mtzC,ausV/ D>\-rX5r5|oF:xYqjWQ__C_/GrIDP%1+ݪ§&[ZkJv=nΔN+^'[iJR~w Ջ9{(%4Z4۔ʑ*B@$z4\Iz WZB2`]i{;;i^׷~uZ$l|ez mòyvҵ)uJէ֡R̤7?~z?_-51$vR xgwTiD0=&}BV\ŤhFP5EATT!m|WƜ R{w5y%`˜m #U3@4o7ЈtO^T-N;)Nqm>^)ҟčV'xciqlA}~{1^![YWp ^q| `\rЗTq,r1A\D]Kp ucˏ yh舤=qeK].~ jo^k5JR;:խ+NWS)>Ou8k JAPlGokcGڤmZ-j%RҔe8k֝:t8HR"du  z*]moճ,NV`f Է25IrE헧1.wZqx-"\uB-!k!H.>A޷zܹbK6d*BMA#McE<}e=[3xs8ryw̳"T0/_s+iIkq&' 03Zt?[Őt -e_$ &U<t)ֵs :(|8`<|l6l~:;LǘF'`Tſ-ǝ:fnlW⿯}+ҽi^wvSʫx_^^/f׻¬[_^{ks֕N;$rPxڭC1ʼn:b„WQĎCb|XqۇeҔRߢWr}Ґ[f~1F!M:&j.x!u{7nqH^DɑOa;i_u;)=)ֵfX";rƮ>ޠ>QYښ$̻:mVoY!u"}hb7DP&` 5q˶1># i3blw⺵u;;.JwiJ_t:="8E*'@U?@SZx ]d~/]q]mTO'Kr|g^5ֶvvҴNq7 驋飃8888i;7! ?^3`b=oyU3} kᆢqyA~ݘL>ZNG*$Ɔ$YTٟ:|YcA?]3NK5~ui`X{F΀| F34?XWL""Pcos+?7I?^34?W~_=gϧۑ~z+?W?I?^3lgwkA[FrEA5#BRr7&cňe"F) |k$++CT-C$Lb h@dfZ-vUxrE`GXȠY K4j7~On }Z R#pAGI c&(fVGȏ?)mJ9W!Q¬FZ5ul !Р@F#)Q p8F°,AI9{lt%g' D9l4P*zs03<*~Sa#d)5_cđ#zS7wIzk/O=j9rl)OvE)BU_c7D ׳3D7L2Vke wYp%i-[mvy~R ]D͢NO/ihjF!{TnCyܪ0c6C(lWpZx$Hфz-(8EW&^dzw7p]g] i^f3DZw! #Hii餢5dޑ6/x6X0;Kq/33\y)_=#~p_ 5qef8092`AZXtb -KLǯ Z95!%ANq1ȽOHߵ\'MF|Io. =#~p_ 5IފqS=}OHގν}Om}܆jjX=hhk !+ѕEm*fR</ơ*T#X&5 s̗4qM4M|^WJpLJ7vx>[ܿn? bdpf:]uiֽ:ֵ{+^sOuӅ| ysˁ7P:O]º۱Jҕ};iJS)Jv4t֕ggkN9)3I?5Y6 /҂UKf,Bf9,& ˓noim $vŶQ`99I3՘֎\Bvüǃšnezv"DX́+(U#bT0.#| St6[2'Ҷ^ MO%YNFf ^ )^޵ZtpSӷTTqɇ5JeW\rq3]WXjdѬ7BZ}uшy͛T)f@)5aFm:gjz#6MB#1UEUVg9s-P)=7(bKp1O1+L 07 `S쀸nTȾzzc#ؚH iƸE,pJ98%a uNt;8Z ٞv'&Cx^Ğ"pLJ2nkJc@quV-b,Jc-$X54jؚ+<\搲6Yֺ'\6#Jg Xc-387y1$QȡV0ᕷBζnrAbI!xEdY5恢K11Qe.x׭zSsJҽm RssY$sy6טq1\"Ufi' ȕ19M6j6ElbKjysII ,0kӜC6@*q )&sQ)k=gMR;;F̅LasETʼntSQ%RJֆVc-v kۑY6e * Vӯu:WxoN}'kIO S[H~xe>/JP ذz1i*1wMZy U b/N=:1>5x9'T5q)5K7YIQUPı#?Nl& 7 %s8$"ĜhzMb)D_2Dlnq䫹?;Y.p ]9 JS<6Hz7E^9b!Eh ]]vӭ{S4^P։T)Zgƌ3NGѓ7vYpɰ>a*&N,bm:*9h`d♢cQ6xv$G6"Y¨zf5A$PWqMNɱcF8U@pH_fdב0Eπ1eFZZt$x$6gR_g\t ZVקzR l9ɣt:l1 `О"w20@72 FUz X%X"z3a̹ږKFtIQtuR=P ^mǹ1QS@y8= 6Ucyĵk#D9)A$O1䨳\lJ݈`ܝԿ_ۗRdfJR3N$W6ٜ)m,ro:VJu:Wqۭ:uNwy푽.6l.s Bё(½'R 'jXL1n2h] B'[[U${PK:űnTc34 w߭U'ˆÈ\"#,o2#B\1Hʼ0"E۸PLzе7N*ƪdxCR[u!5){K1,q8ZUxn2q{o ۼi_^9JZWϟI#2\e Jn B!V)9=ֽ!⢥›ьzR].Zjbٶol-S*|cJ9=WTqBsm]0I<#9Ek1j(>>%hbJ(F;v{$EIR*ϫq0:xIX46ۚ'Y+x/D9 c-U2U(0 r9O%|b2gݎ˹bW53ĉuEswSUIH]jzӧ'.9ӿtn )7jѲlG!s;9U뚒bD$ slpF%STPuz~諚Ai$,A}gz0k,Fm{1{9S%,Z\dz{8'$xY 4d8>Rx3*r (}Ӭ[ʤ&MhI:ļfdX9LDoiJSOmz)^ץ:{ lKeb(d`fYzF B+dfT-:KȍIK]"kU<٫x6HyMhBt/)١1Ragr1֫.J8\9s8-)6wca+" 4bXW腝' $w<+X\;5;#L1ȳ0J8$C -bRkm=֗|~nsKw^zw^k͡#Fhg 4igl͏ ,3gu"kJ1+­zo- Ȫ̡>eh (i#}6յ(JRAmV1׬gyYS"Hlʖr,.T/Qʤݹl`'^ײΩB0W%){qkk-N,jKd%_gXـ7}?kJwkAsC $C0)IL3.FVeC|LGcLuaҧٱ@&ѾU_b-\E!ؔݹ7Zax:cU{^ sh`{z$C ՍDmZ=2HR9Kʼ @!wf8mqBu*GvIGXPfvV^Y2N30U"v\y_͋Ys,@7#u89ke~G^CG)߭eO9;ioќC~l>cc ZJfSd J@ѨӛO%wuwܚs-'w.V?vHVeӍEo "] ]^CDxoӾkD8[SwB#AmBdmiWQbIsgTqض@#\Iַ35ˑ0zl̓[{V4W".b1٬4P{xS1ʡPstaDT"au)&huHd< MʢT-w n1C@w4?Ym`j JB#^xѺ?#6+(D΂qub\ˌ~ąv8f7*Ixr s&$NYr53<%Ǎcs="eBD=Af'fSr"-L1҆* Ƕ]#,\op?ϝz׫,G !̕⬑[`+.Oe;OT5:ӹG2^μQnTữ(! YqvW&z+a,vά5!R)3`=HXGHѡZ֝Ju֔&HZ8_x H=7 (4щ)u-= GvtNJd ^Fdƫ𞿙O i#p䎬BiVu۫~=~pA1jwe6B-Z6ЄZΚ#"m~ֺ&INTVg!;zҌ_^N"(U\6449A/[zq5M 5vާka%%\lC&AOׯ]2;kЇw s27Tqa6^͸5qRk14IQg-.R>Aؖ-C= 2PRS40"c& |w.˾#-6 }czoCʻhu6כf_F\Ogն5[ C'mZ>}VQ_n5 @FMI!0$)Ta<5C d`̯Sn[(]qϞxI66Q" 2B\vpvOo ]-䝬Dr#Hx2{O.!&V;ḱHJ'oGi/oWhI E(ntR^VN6/釛Mn󃩬}P/2Ѱ[mm60s!cb`aQI%*l{as9\UƐC\,6m!Zj|H\r o)f_7sTߙҕHK ZNHdc*߰ꗓj-  @o.(r5lHS2J*.e5"<&DJB8Nyum̗,1+ęۆ9jsrbyn1b|kBx9呤z@A* 叞It7 FSyhkykƍOqY;ߨOHWw[2ı$ς@ruHnv #p1Jc TT3pXkኜv=c>rBeB[NM88((;v3RrYF@Ɛ4D5%v,W$J zhldKFMKa!u"6s aSZU-hW6eU&RUx)6P8dX%ׄYUdpZIEܙcRh# &ѱVbQvqy;>Qo1!/ v>GoeȰa'I&VwA`r0y=4cIrS!n_mFb?/1ly$顶z^pI)\R9k%si韼3$糼 j$PŬrk[^a!徲Uw\~BTg1տ ,*pM_0U{=߭gxb|[Κ͏nmD0J-> .HEI 3R-Pvr8XAG5s!Sӥi*_V[pL? 4ppppG 4}J׿:Qrf>o<َV@쥖ס -)^tҍֵk^~O}+s+w7QFKrYuԹvWm}Sz׶ץ+Zӆ)9u385U9B c*d ~fV yQL"xs'-lɓkm;_TqšWKk6p "h m$LYEҷݟ"4e+=)Noҽi^ޟ?ZJK)ԙ;M~Mf]@;y]zܥ+dGPdk{]e)G<Ded3o[89r61jTu]JVs&i*.*tBJ PHyxDȌ%wl~J׳;߲S^j%zSDa(4v B7@Kbƽ/Sc21d6eK^xՄ4&K3,^Ķcĕ!y;!mɫWo+CkK$RDY[ي7I^Q΁L4;vq䪒!@Y%q]k˝\=xt*ecwYJË)庰Hۈmocz+7jV3If>cgD0%N]HRtBSiox-m->GyJ)Lh!>6GmlS(ƠLx`-_'cMsBl#YCng26eAc-{I-*+Q`E=p+Zu֝;SQDE*VNH;X^jo-YEc8S w*6^7V>ڽLűvA1L#/  j;o!ƋѲUXSRƏ8(k5aCԁLvm[1D eF-f-hvM& HaTqb0`tguΰ{(zӯOg^7֟/_Il4"92ي"ѕ) EHn [j7jNI4Z4lȶ3Y+RnegARCAetnkxM5FX[5\%cU=1: 0XeBQÙv\Kf>lK]'zz bXECD f(|puq/-7 -bjZ);2'N;8緭;~z{XpTFDy9佡ن~ZZ%%{evHR_h #}븜dymU? fM|4{ bֺ3!.0T^lRFA#Cɓ3[ZqMk?[n[M!J7sGҷGf^uRd6)5MpaKUTRpn uׯƟeQA EPU]BrހqaṊB(Zy&gsZy$x+3 a)'yLmZ`TO Ǵk\[ʣlO' xɂʫY,O2i#eӺ᯲YX'R3سTq)HbGk兼 m#:ײzwoOw5 Fnכt=1*>\z;^q^c#7[A\d6cSXlqaބ$6N(o/D]YF,YRcBsrq328 0H?fYA>L)FANDt[r~,du݋W1Zz5 )U&DdI%H(qZ ĜVF:9ju{?N9sG@` pq&@W÷8'o]rn#SFQ(J"5eC sVݖ!ֱYnG#ppsb\> ]dn.kLlZ>VpZ[4M+/eS=?Ł&,=eEx3֝<]ZRiKkZi^:qzz!S(wIϭ4W !n(k.^lzb0j Dq²ĪVaQI^霫Cd㷯 :2V鑎GɶOj:&eT:zS#R֔Nkӧ D7ǿfm/-yE2CPhe-KkJYZҝj_qQ}:uA7'^y{+ӭW0ʓ{]NXOlR4a7;MmTƼmfi~T2\HC/mF㺘,Ibm.1 qC!,yI|OUzZ[2V8k+ٕ̎v{iZR.{iZvҴV)[^_eץRV쯳54m1>ڱJ(nӾysJ9^Xp%٥2_ t~l䗥=d:do ?v*CEDmX4J (5iRP.g|8ZTf!wI;ҏNJBI ȚTAܷ?-dmmN:ZV}ݕom?NJ?jSZ7~uuVճnw5KZ)@!IMV6Qym|<'8*<ͥzWn#wv׺jti^'Zkcc"Hmz뛔 L*kSFk1v nQ]0mmkmri^N^ggzVZRZW^vӺӲzW ^Q:YZGXץrliJ{)J,oo-bշj|N5D~dVPHj˨쉮y_Z|ZowDt<+j-~JVb qЏYc0CEjg]KmkH.-.hRKSrJߓ-)oAr穌3a4q{gnU;hycFэlqUe!)*%łI*^fe,H@vmwTY4I"u.v H.#_YA9Fy鶙y8ZCdd̒0 ;R2B݉.&՗%r*i\"RpuG:u1_gdaN+XgZӷ]GI C%eH7hqܡ@SkQ r7C1~#i*Ý}?#2 fhَ7 6:;˄∼bIjkxVceϻ$0*⑱)`I?VepRfCRBfGnPȎl vqъ֔1ֽ=Y^k׳~J8too7ҿ 1w߇.ww겵^?kA3k_miFk+wWyPݳ m>{35^Y|x!iߐ'o;&:}S1ҿSJ2;i׿+|{oo׿,yWg5;:]J즪sFg]e>_zEo۹aQ> SЈEpl'Z yQB(uHMUy`Ld[ Y۸CDJ6m >8t:,~Gq*ƙJ9i2"WImmSW6G*jZO?@df]/l y#6,8uqOꪙlm"'Vodټ χ.+\OejH.p[,7M"qa % :FKYE̬AbV_#H̷|zY/cM:EB@a:8/.Z_-7ǣTEY[zG:ɲ:vwg^>^ 2G`G;?O>OZjlC)RŸ%O̲!~:fi:7^cʟ%c h>:_5gmǗJק_V{m=qk1YM4Xp ֨vuֶmq)ŵ|EB1 TVIz|WXBe\؝#6.B55wl"f/v˓ǖ4q fyI7^WB֝{1O4wZ 5yDg^?Om]:v겵ܭ,}njC ;} O;u^~^>or^1ӧ[O)|?#2 fhَ7l ╃:;|ZI|jkxF:xY\Nֽ:ǥ=~u?Oڸe8T0Z~[*vhfF_v2M1zj)ZV+Jҽեzҿ5}]mniZnҵZ{]w['Azd4L9ּ ldTH a*y룘fȓăIlPVlfi)oA马3a4q{gnU3lySFэlĔqUe!tyX[6)}٬‘PJ ƒ:z:n.ޙ,{eo^էe}iJ׶xSt}9d-s+kLY< qW-݊[iogJ קrk)]BŦ o lEĻ)~%ϐ :Gek"נQ*V[s7Ȫ)\ch^Z[o "_A!KjSLTιb7|u$0Ơ f=ToOyk}AW`t vPO(&;b޿-K#AmU]_nV)[N֔N&61fOjlקf<]u{R׳ny}jQ]wQ~'Ϩj=jݫ7cb4#sT ikWtCTTa}|W%Ɯ r{w5y%A8FkP}mV7AЀtO^TĭN{b`(Ww20"FG۸yz|tc^[ yPR:1IQ#Ѵ(a"+voo%m&Ki뮭)JӶ}8* K9$>ׯZ{<.}OgN12=g(Lq@@5p ǘAE,Gע"qeLSUu¦+z N}j^ޝ;{8mX{QH%1SqUR1~9J;k ;oi,)?ƮrgL]L_NˬZ]JV_ӧf[ÈrTweWVUk[Zuo}k^cєrшc4VpF4pmYn\HC!o "ז!QIU"|r*z˷|Oz/ad٨,|ekM;ּ١8ժ`/d2 '/>$<@$몕DVه]O 5~Wi#VfWmv~إy)2]Lx}Nԭk:{SN=qⲹ2]Kl:ץ)Oo~jҜMC>Mc\n泓$08m.1_3:d@c|djʨ%0-NV#|>ښb-EU!` yapAbO- ;+J,i hɚ(PH YvR7oIIv& ܞT28XRy~Wrw)׿WO+ӧׯwNJSv1G%/Z(kNҴJ|_TҴܦuҳf;:ҕZwץ{zץ+ŴQB"d~2XEf%5mXe1LVi};zvӯZ}5}~%eG"VzS.Kmm)^]u=u㦌A1cG JT;U ʒ0r@$zDZQz*WZJ/ڮVOrOc"f(xIIQeΟB.Of|$.?),]2ʙ2<)!#Sq.UwN!$+uR)¢tUiN kӯowN?e[m[ӭk֔)Z׷%ډT^MerǷֶ,{]!<N{FݢmA~]U^JKoku+J;?h0eUY6;1eO'1Ey(qb{^!X&ur/ I*y˹x"¶.gN+׷O~4WI"JN(k0~lz\B1xj DqyW*TXlVfœ|֝zҕN{:ץiv3$(ŗlyBId"h2͛TMW?$ӨHw eնI-.͎+֔o{k^ߚzUS6;7u+J4{LSʮ[u][I`n)׻Jvvu{fq6MX2lόYu9siy9eݦS. Ҥ:/(x8&qHZ97G.dUl^C!j`&€,RD97HqֲYnG#ppsb\> ]dn-kֲir\ 7]ci}'[{ _u|ҷZֵtViJu}(+閇wl4 K]$WJo[/_JVw[kZVFOFcx8w77G 4ppppG 4ppppGyɍckAc13+A;"6Ӄ"["u]Qe/Y%. [}v_g)Ni^RIdTﭫ\CǬ8C |k(u|7Q!& 8gȱG&Hp*<7O~_-}}&R٭Cj+HݠD(nH }5nҖB(\`-+ ɣJH2 +Or!H-)X7][˸OC\u9)4vF*9Q2|!eP^v^Yw|$YlTs9αMichZ-,Q Gюg5CjB--ί(9cIZ<-"7e؍Qj0փ^+D͑v#soOPq\q$@L#i\=<׃+E3A<[~F;}Ut= )5ڽj^SGl#9l|d~w62 geכoDfKNOٵ}dx^d<9Me#"'EͅNi5rR MPqBȐm1D6&S8ܖl"ġcL&B۔h,L٣i\Pcta#H3Mr_:nǪ9PϜٳF˛NP ܌ɇE]>oޱx6u_xIHF=yf|7COOHT Δj7IuRՆ"9)A.pWT^<,Z摟~j2uo s&)ڷAf`jvzqjQbGm6T[դ;f$0LR벒69V7>Vn?mj'ܢ2ҤQ_=mﳦ.3՞c 9\QIV,y.7 hyu~d]Bbe9!+Q`ƿM.IrHλ'$B4>JQiړu!o]Cmg2`Y;pB#7\ +@ ̅4Mo{Dh0挒Jmm$(luc=ccnLrR ϔIm1I;Dc$ 8Db(F0Tg$8Q$/q L9m·\ep1a rvg\nDcL3 uۧ#$)F#|dt!.s#6 1ϻ+S\yN|3d$nPG6d{'G[刦e}n0#&X{Qs񐗤]1E#3DկfO1dlɊv>4/hȣ`)+Cu.Dp.4% ϐZBiEVvs\o HMrP YRbcF_#t< LPV9t! jFâTm/oXwu"@hjI81Ä7%0в41\$H\Z~8v'F,lVN yt/>;qu,2ll Ceǘ|Ő(MM"2, }Mo ޖ#!r3kfs'}Q#3^VT/KAm p7\ׄ<B U.TtDB:2`̑bLٓœK캡gG_/Phk_j#dzW!6ZԌRb?uUFl2hGAkZ6( /z:-NF1PGؽR=s8#Ln$}mM4mvnض3+j6dshjXǒ1C܉.l:δК0#0x GD 3fu2[8/+ -G'nty`1eSZG$&*v$ '~}f~%˛4kщ=?*UK6cɼm:u}f16e:g7| d,.).7Edڻ3Mr)X[3N{AY1_AY1_}̗j_w33ɯ0c^iGoL_iGoL_?>9k?hx8WaE>aEw2_9?|=ϣ?s?>'iJ> gZn+ҝz֝UJV˫&ξŁ<Ɋwb;UukmqwKo{zVץ.y/M&ӄꆷ&U#<6/ CW[n6ŶGR=/E,uP>LpF鎥9rKHQ zQ϶V)&݇ L)[T ia%+A^$b鷟_I$[,vP%~nAͅ*pHNa$9ӭ@>isbχKr=OOM/2wɱt"*K7=fd'**3.r,nUDA ]p@O1ozqse|/qG%F ŀiNžxs+l;uu1egM"_nc+qQ5⍫RQ:?"zWcH$1IbR3w3`SMxIERvBΙ-J B ԢKoXu+Y L#jp-"UCl^ UeQo,*{_GRz}sް#0iY G]ETGx^$ ;jajIDܮ=T'8oȰDjBq x-l>[(5/\ 6o"ENqjÂ,R;F92K:#;VXBN{,S^1v1֭;k_1_+h+w_ťI'j6ɎגY Zx+m ë3ǮQj$BB DPyP~I[Z976}tT< 3S305 bi>ۛ:e8E%"#7\qUPi^cgՔ&rr}B,^ %:UMYKmmFeJJ;C˨$rhHsr[~VJR@dX4:#+E-Kꇟ%R( 7f])UYax> PSh~lK!`GyOUrļusfJ*“942\URvo79wVaZׄl`͓[]JG{v6oː)eSgdfJ8͎M\.$y7lgsM/2 BT ij`V @RC@*~KlVoL9%Yl<(У @`A2Xme5Hw]!rGkNKܜm 9 ̄yIH)$*ƻ9F\+ wO;O[)$"ڜ5uDX8i{d[.LflĻٞ !8`<ƘNbq8ԣΦJAH6{tJJش⌘Vsb.k#2г2R+W`:H?/kB C9+3:4va'gabA&.H˂ATم,fKV|<ʬe 'S6{Lz&FwH;r&%f{=<ˍJv#&:tkJ͙X瘒0[`t`#u%\$vcH] JPLp;(1wm$K`{-ؒZrIIkR˖U.}a6:wm~ 8Ű#G :Y]@{ya1ޚ&f?uHmȤ AZ]i=1LoCi`@ jCfY%%|Y-0%oɀ{reB/2`輘HԳ):Չ&YW$oi5F/vwʊZrRiJ;۾Bbr -hkTtuV$r%l>ܮ2gCHōoӪA2aR^wj>8͍nu:˒k=cʃ1%;,y8/g!^5'EG_In؉hc6cdN1Q@N SӷsOҾ)~^;޹ᦎhᦎhᦎi}ؾ2ϴr?Y9Nk.Zh.)߭eO9ᦐl_Z˙gŒRj{xZ4-~iJw<ؾ2ϴr?YPQF;Wܕ=_ZG\7Ҷִ۬u1֔WZvhީhLG飃8888iwwk+Og}iM:;=$uk; ď3$ADÕccE7yHk2x۰)O2xiwu+}R8Xr˥fn$Mx9mkL P@{u"++ٕ^fb &j(N!5 {iֿ^:{;{Zu}5]╵?d0ôtVUpFCFQ ooKdm3qk 4Tb*\Ѷ2s*\LVHy_cTͲ(~-ꆹe\Sd5|9H&?#v=.Hb֚߿_W:g[L'RNntF\ 3+%yʸ6 y) I+$Xeb o^بc r=:;[qL H~Zc8zla%;lwns1uUοOpR^O}{Jذx(Mdz7&#*?T3$k<ѠVkC*۾6A$BP4VVUٕiӛL(Gc&(ԉsb]ÿ, ĺΊ&!-tm⬍5Kݹr%dM~?5ft=} œ6q޼Y(ǒc>YtQP#Qrx6k$BOQ|gm5].[c:3r92M*{`%Vv!$5W9KPԀeCew]<׵ulA#Ni3uVf Xv 0ű/4}J3̰Y{,*x؆}oML]aX2jEmod9boA`Xy-`crբ>~{~羴Uf͛obYuv SҬFr7\B:䤠ӆc8mt42F4wvg}F+ [0{65]"6҈]3lO ԣ0X h v1Wbkl?NϒO^j7SMǢ, ߕfp4r̳/ҖEn4En:u:ւج6F"yW5*M\~ lC3(DLH]'-+uGr--̶R!D z`oi8k]ym%*YDLtQ*I)$f{rXTaKhDvm:!\Vu5Eď)\m#Tubnp3h^vJ̀ vb .&tï60,%YlAW8y?Mn]+F"/ 1q%/6&ESl[m/QP' c%!@aR#aklp<-pB͂QfbyZzj + ʠ'>/@uWl]=829G%d%U,j7`$[k\F57$@3w[q#V4=ذ@~/cfiӳNpU/+R+m!R;%[b<λowzms 9QX G(A4 ,9'̶UbHc^eUWbĒ| 'q(,~+>9n؎sOZR;(]fe bX dK2Yu亮u}W_o^wqAP̜[I#\e}َ4Dו9*ιwq 13[iPNZMGy$"4 ;MTY:kdQy4&ڋv@A-"f#AxnN ՐkWE >rTo Yy/ջ/(G}[,HȨXay 8w.]+_om:u_7o$خ(AKq[^4[ZwRk⟢bԻ/JŅ ,&bd:o0U8Jriu FfUM teq,$8~+9$kZ5R,•@.,纨7=)d:Z A=F4(߼i+k,ŁJyd-](z${Tqlw'w>r67sV\$}bmcHwrw`A+Yv\V%{[Jׯge:]m[J{^gYԻvetFk=9d1i_ K\d;R A(i9Kуtںii1iQDu)f Y+]hf8υ?UƞA5d{;#,p-L(B=ANfm"`vH@yo:}u.>*{3mNLd4 ZkRyZ0T!Ue<5tJK/_]Ҿ֕oN5勵bfRvKRB7"";&lqQd3B2x#e $* Aœt4~fMwDeB&ó@ˑBj!HptQk/VxA' |u (=t$i',N.9*;@ؓN7ޤYD jXĂ_|%A<6jRHZ,)͹M.:]:;|/޽{O]֔u.^o{sԽpHR-u0$'+ĭIcxܞ:.N-;W=yX-΋,v45-)?CvYt%w).5Ho8SM#&.'noK* 8H xa(YZP~0?A^+)BEbOLF:m#l^̀ȊZS m)N'{>/-OWmI{eM1Vy4}@U2Ju'*ȯOY83)Ym#Nz^M8,Dp5٬w:E .DSF$@t keI٪j7dd@, H}wGgUr5i*0؆<9Dmvw$kq R!`5&ɣ%xU##V)ĶEC`lyǙ)b,#.9I637/%: E+K1@r(> X  6u((Rr"Z^A)Vi㬆N4Ȧ7T<7H6\7k7e*};$i$ݨBdcu~ [kZWzzҿ/KrYu[mu:җR_})^xWYcmO/:1&=SQcIAآ?TckFMAzUvarc]0, FM^Ks _|oIYE.!s^&F9 '3udDS:/"F/QTfR{qDҞL weW׋]e(6͏~:(#Џ#A̼kˢ ߗ:ҙ2㲷V־xUn}+JWӍuyIBm&lYؾ"$N E`T2,M }?E0t.c{;P#̒`s 157R) 딆O ɲgJ$MҲZW!?d.L'AQHZY-5[b7H r@T2+}نy\>!\њizie-I0.T6*_Ɏ+K+u)}iYZUNosbc.:dm.Zx[H]?rv mǕ& rՐ&|16(r{&xG^EŔRj' 3W5vPn, E1| +uc{ѥ C*iQV-PKzy3V,g!,@B1$$JnUُ7h-H;W Zs&^#UK%nEQ@ -{ײҿwSg#OhtP"pQ,Z#Qee17sđ 82)3 T(,+*)^}R݄Bv TwU G x, # I %$devFREt`U$ebpppqg\}4͋Ys,@7#u89}k.eh~.7 4r\ 7]cSZ˖sM ؾ2ϴr?Y<;1ݯo, ][C[Zץ+^Rߩm)Jpsb\> ]dnG,pn2x=n|;ޚCu+Jt+ZS:t+ZVhީhS飃8888i~ogoOo|qiWo 5 J͍d7Ka6́afE$Hxy 8rHr"e3,R8PQBAq!Hǧ GSiG1cRBdY̷IzDg`B{+mᦕ3K` nF␥-\usGuy{`At6MrLC Es"LXSd]:o( A^}6<|7 =ЋHB놗0OX(©ᦐ,'g62Cc&V1[3 Dd rl,]ᔥ(A+ ʎAɟ z+yBrPihqєq: ьL rI:mw:±ԃ]Y i/C7I*@>[E0M=kƬYfK]>[2cu/1ZRZlm9h4 lZ͑H@M(So(Jp#@9d'ŸE#S*WM 5Ftb2m:u>WM!dBUM v"%ڻW;n)hCl\K$dZHS>9xNA3zfu ̪PU6 GnKTɒIxҪ)V *2D *Ac% y#O"06yNg_owo:קO=aO>}겎>[oXdOzWpHe9{qy0㹢87r 4)>1?>ӁŭȀJs2 :8Nf]!d,}v} uYc*6@K^m8^g x-=RbWd>_{ּ4&8n5'me3.췫]H$56Xʍ[~6W姼C5v.ydB#MĶ"[ںHw%`Lљ-a&@I1pru"u ̕ᦒhDC`$'5p' 34y.ѳ6UTÕw7ͿeMPt[VE9BrN,Ͷ 7䋀C/&bȷ$X.2(!-)F:^"W3Bݎn62x0Ѳj#Tz 2Ա8E̹-yt$Rs$+u6[-[mg74- -VhRMp ŧH00@%$P䩐@:4x0ËeI ,~4 %J@9ۄ=rRh. E܄4dQܡ6KH^ أ,e<G,1N9I]CI|;ܡu4VgEe H AZfF=C#r(A@uG $cD@7j L,h,F ;z][3R֔muzSnw8uV]mlY[-1xYVK{im|x^kZR i׉~f{;:vs.i_ "ٻzSӥ-Ju)ֹG~XgVm'Ǯ毯P5y~J)ӭ>^GbcsAmUm7J(_(b6xhE[VWfB;+*MjٛJR"BD*N,TX64'esϟ5bÇ+.ɗ.K}[m5tJ2R6 x:ڴaդl4rWh2$hW Sa 'mEz3.[u(cCe""K&i<|oeT2)ȭ:6gq1pȏXW.^\OZǓĒp4͘KnPrxTV:D&6fz;n `d P]珶[WhF3Z>^g`|IOi kXb -f6쐢q} &ȳ?mρ1{`,Oxʗ]YqLm Ky ֲN5~b(#1aVҷX2e_un:E,d~x> oɀ=4L ! +aŊ싃ij2(NSb0b> LaH "mn=c֍k/$1'icX<+NO%lvy&lq5[%jqw2EOe?:܍b> mŹ鱨NFrJ`+CZeÑ:#VR1L$eOhHwh-byPu-) 0yq2B;U:ԉcˆ̷òKi*vV{}8Mm LC@B7aYno<C$Qs8hn8Mq ``f2LhcD^!OIuU.6{%uIc*DM7W*1<8Prbp&m?f|Al ]O/8c .d%"K>NCNM.^^OQ8T#BaB憃-j-prv׫Vsg8pCXSi=.:É]QbԏPV|%jQHYl=DO<`6<~CSO{f{ysXAqivȚNw߶7َ(Sh~^&ֺdžwa))IB̯1&IEdo.єI_>,knzE\ ek"-5-ABa'[6ɆC Dl T8 V|}m{)ZuҵkZ}_e;zR#h"d  4m㓆<ϑ?=W3kqeoEiYI$0R15Hy)G\ׇ;HWd/h25E!H3B)DK D"Vqv\ T.J 0>O9ZTBF)HA!AײdEsbHIKDF$j|3 QLd,c*wWe+ҷNwZu3ͻVeT!8ܟ'bo;>vغӫ`As% a sD`R );|`ke_#f&npݮ@Fre{"jj%f*a@-pɩ~k lwaWQR':NMq͐ 8\`刓R 2٥viN׿^קK_w8@kBpdQN;vmۊ Ww5f~ă&c8wMܓbb2t1,)6ى(]Ϭq:Wgˊ/P|l" !;xg ƺ|n*Re:xUҞu^voeJV۩ZWZq<1CEDT NC#MY+3۰T#O;rwܳf>I>Jҽӯg M g\y_ɖ/h/ReX=c-ҦϞ_N<<cVih81;mǙ.fAq5qˌƨ*r* v\+Q.7]+nrߨƁ-K VKXa{AQd 0Ke;ly";z{{9^ߚ#h^'*N䆤.ab"Ȩ2[`^ģ,سaɏ&;oi#]<+Zu;kN.6FWUu!(!|}u I$Ȍّрee>HA}|+NeْˮGZRvJkB>_NSZ˖swYr@4uxk@9}k.eh~.7 pnoV€|[Cet)ﻧZֵxk9}k.eh~.7 ˭?zu=**ץ}t_e{;8сO$i󃃃M4M4MKCɓܤQ_#݂ըG76,vɏ%خ+뎷xVmiI2boi× ̫q.ӫPyuۦ(A8#2N!W#z-ijx;ln"qY@uɪֈ;:2ɄVdri%**ؓVVolK6_W/616Ͱ)P&ՈI٠OV_kK1%6Fàcі+7">MB[Y¸~o(@Z섹|_񸩏6^ |dnݒDjl: !$›|Oӷ)_}~^kNFɲFmH,;(ڈo❖lL弼e$L-ԍxYAjq.Vňj;77%aYbWoчs)gkb݅#.8)Tw]14H|B53|2#.+75ĸ8i&9NoѥPlݽvr+7Ky(loܶąB#En2(ѧ1 ϟvOMbGfhLw4Y y1=f+AkUeK:FxCЫ>.B1fQƒ+_"ٟᦟ s`n~ퟺUp5]e{"614Wi6 tyiִvJu_lU~ғW5H\rbP2"H͢j^efPqf7Uw0$#<; .Z~{8lKm˩Z]KJӥ~JҴO^xĤMGȅK.ܾ;X'-*˰\0Y+`Bݷ6'}D[f@I&n!hQư> z9 ڹs (BS$8 "w܎*0]u@(@cjʵBHA"QxAv?s\J[1 Lo*_d[,l{V d6;&L„c0e%u)}oZQ%ي񊱮$Z2 |eo.J^YK9߉E/}.^|S31 = Pѓ#'>]T%K*0c6*}&R!ʚtJךXU[`J5|OTHZ1|͛&5X3"vS4~mb8ڊf-R:I$gZkUWT8/FtWy#Kk܅_1+JІO/ c rZ5cVUv\5`"Ա-0&)FbS-&A AicX/E8eg񜃈[ 4qX,iy#!% +jӍiݮ7d,J"%pK:!7{CWE1הTV)rVjN+~lP]罉N359o4cG̦Y&r} 6`E -. D$d9]'ad.\$&ȐhK=7Ksߑ2㉾#HzKh=\,EY}򆆏ΡV$үdMvI 네{{0ۆqKAu=mq֙rRx4tg=o+Uv68ʶ,SVyM#'w[`R!cse`O%z0U5ƛu6349R,m8;R+W"9).Ib+&[plۼ5SSJ5vtq FPi,"+_8pL,|u8m+*QM$2c, YH3cļ!g}22DWӲ E 皭:$ОJX Th tk(W7vRQJsQuVoumiM‘#q`يpA ՜]**rUQA9 Vr͓ QsWì 'nKʎ,El$hѢ B0M 5=`U:j*>zMJkSIԊ5"t^{[+:1xa]TmE K`E*6a]ceԦPWUh5M#c3&pl׻ p+T$yJ\S֙RL)w m)XY EembG~Lk}N0'xHR<,KlNHFcإ+R&Zp32%p#E"H'7;(;̋lO*5684JE$Ʉ0NU; \ 6NN-<7$m(َYM ꙹ1]YXf9JNC+[rT8N= [gT$ZdcW -Ώ4\ߗ5- 1_e1[n,ԾR.)L'^#.*6-vA*SΨc"G+n39ָOwgS_Sh8[yfas$ZfNIE8uŇ:>/ļ H#1,DM*`$DOIae1*jcL^L6Q> [e){({ D Dcݍ.)E0n\U[%d/lB5$Xݥc'Q8V TŶI؆;-u~~|X(jWTcBYC^X{ Gp,b^b)Mn'M""+ _ZHr*Rp7r ڙ`n{|k0(y{Q,Epv{P/_U\uG:*[Ø[#Q1m v\ڋ2Q"1˱$̆$腄E_WB, [bX>\iydtE91X!$ť f pN,VYKl(S*}l -8~pM3( ]xW#ɜ5zkY]dn"FpykXژ6&JXe ʋmXd)`I5c1:k" }~JÚ)oVeQ/8qޖlܰGi)śpLP2%Mo9ypFaőMB"mm<,c64E x+?z)$(?=pS/L^7/|e me7H(sE:\Xxxg.w");mUqeWRW-iJR!oH9鹒bDśiTKc(QX[k#NK+<-JAFUQ-"Ό)OOcÉlXlݲrtỎƒRR'¦}hi`Lԉѓ8.dsh U.ِ N\`G-uؼ1ð"O}.N,WR쾮"h툑FU-#2aQN464e~4IS#Ɗɰ'1aeC$P#EiǡK* l`euvúVk5\\F܆XbL<ݝH%~<m7/R SO%K#qjƙF9d` f2A`mtS)hAq+3^00(ljR &v/FMrM4ջ׆mҫ'x%(k=Rf%zUFz.O मvvvt@yT~!(R"T7X$e6طƷ*D &,=/|v=*F~6s=h\,,$GZHk+r8 rdGj5( m,ԸDžI KgHN94+cwK,8@,/a"xl ^0@qp:ʲen@YXcs41.WPDr] M 52!EI1uGG-ZGPecÖ7 [sIT De3WʬC8P )Lw+g'Kݬ&K?6m0_(%9gSِdOZn_r8dlVie4dv @:彡t˳S᪍x_HV.Ry4eBˉ]kfL^D$8IA;J{H˗Sa YU UHM4xv\qo\[rju8,Uĉ62Ji8.fm<9re+m>uU4ZC)-ˀym6ITc,GQi!(* 8, nn@Nk.Zh.)߭eO9ֲY_nG߮5=ZnC۹ߒr wx˩umΑV[8zYm{ioN_6/e̳܏FB_}o;}m+nt/ 4KҾo֔^5c>Aim4ppppG 4ppppGӧ~Z׾?NUgo^jK!;|1dḰoL/Q+~\^7[-ZXF0i:\I5H-g% \Cr0^f(u^!öh`hg1Nrb qR*+Z1k `H cC2r7 ^4Ry4 U*k=d3: Qi+$@C 0@?B\TLUˋO~,1춸뿣 *D1HƎGCnQx'/QS# |w&6[\%ӂH#fMbVb yDđ${JA35Tu(Y-"SOs6՝ßB`AT١s~bI;rp,ݥ)fIKi 7uYKrFR{dJëHk]Hl-- ܗ& 7+L5yuMl>s R'j^/꺒roq'0LsItz0=82ϻ9}v\3O9685 Aհj5kVUn1bGN *Psī?=%FAǘYd5b6QǾVHъM;g`[A`Q*k-7"odDl&(v5p`TUsq'#hR=y=̶-Wa"r.Pr kl1x `3 >iύo:0@|elt2ii$hdɸѪE"6)SN'-kblk=DH~fc?\^`e60p4EvSMX=mCe2aCƗ32 [ @NĊ0~,ͧ+ RV6#196I9K`c&A&~0S1<@:=bK`LQr[a:kоfH̚ `ݣ"K 7B{v8mcS`4(\e4(:,tTQ){m4#J 7$^MbY'ea v8%!ƃe 41y`!{dH+Ml=0saN_9Z<[KIZ5r6N?D(^M ,)J(#ƿ7k6_ wJtJQ(uSη^ͭ-)#f}>h~\LYZ.nc0*ujm켧OKHؑN\te_yCM~_"ˤ|{lwF_8u_͞5-b 凴yDdB lāt!O4Se[^Ol]ph5o5:+mǯCh58hK.sE3rsnJ\~<8r h;p[j UuQPdQv[\cYȻ 0e}#}*fQ;H&̚ARȞUi <գd{2XV4O#&'/R$F9|0a*Ki#D2Qn3 Pݳ͸ea{޴碩Q52kDLl[S{{:SNӷ)ٽڄ̓PɉPzmZH>ʡ}ֽG*Mj[xU.m^K 6UId!3)d#>b:pxf>4xhqv\ۦr uqWѺn@{17.ǀ_фy0cEe5yV(C!<1BU+s{g]MNx.VyYgA#6V}՘R~Ⱥ/oQb}{Bf:<ܹ wz2]cS$,Y3z}t^ ĿmMܺR7{g%᯹="ToVoÃv^E`P*?!> Kgٟ_r/\ϳ?^s%ƾџ9M  %᯹ Kgٟ_r/\;/>џ9M  %᯹ Kgٟ_r/\gV迻t>9k?UGmkoYeZ֖uԧt^瘟+rUorvVUqmmܴ·ukKׯKJu_ 稑:{ܸܻ%u&"3x%WX<E\Sk.HqLuɉQĄWF]R^y6dIm*;Pv*үmla26,¼Ê@q9iF1WCA[No Xȯe07wow Ulw8yR~,=^!&;7E(8JR4\ 4Ӊ3SleH1RnBVQ'nlN_onΔggg_o)5Y1KCY;aq\J `eNx.yL8,4L˅m(r*HD$ub-q ^Ku';Ot29Kf/ő>ƨWvi6SevؿbؑP>&Mv81 Ӥ]Cw-v(ESQ {*h {Uf}bn<ޑВ Y2'OYyZ56!rw5S`@{l&"I]3qֆ遒 l} vHAH7s` ~\ӣ"}U+YNL80T\ Eyu&T\o32E@!),kMlf-~AJ)-Q^*^KxPcM7<+_<)#,BoδLs[&2ɚE.H6}9FQ0E" EN7ڢEpsBy4U7p< 7ΊC #GFx2!2VlA̗QMKDWT\ F\8Ln]@mT+ #yJ=w3YX65r3͍DkyK<vu{qˤh:`e Ņ .; ֆ6#g’3 8xm :Q9sREӞmIjlkЯ0<됨$yI*\W3xǶȬD C,_?kr*. e݉e]Sx8w*RYbj7T:Z}1 Ys>]UE/1}7MlYv,srBK ͋Bl47焹 awn1lKA޷Ųɧ4Z܎-g(eěrl Ho")ژ~b2VVMod 1MXlHVY=(s U _$;L dIk&kiw/^\oXP5jLV{)WyEN,oCgT!SNu-RDGkf""SݔO˕' R6Pv'kklg g!F*.ܢ(=eQVR?dfJʳ N%}J d6,l8E@9L%EWu\QCbsH^t ɏ1r]xk7fN"l4N"d8hO:m6 "F5jSb,Pz`a |, &=[n6dq68ѨF4@Z5Agk}媯cLI.B9 9ƋƓ6>b-oQk4Yvb&t-G0 jFHL+T2+7 m#w7JH B\쁆᷌O?y{U$ \СK5{"~L\]5nHM?eV{`HXaP RN cE$ܦ˾/,4N@j2o$VH&g룆5dnFTMǎۄmyL&nR ZF!z%*Y,2xr'hYcl(e9$~"IPFg8c8S7Drw/c 03Q3uHEf7 Fͱٌh$ tR2mv ۮ%.{G0 @rZ.Ms{lQbƾ-}Zq[%ڌNsRqhCh$(*V_ uckjnnc?`$~M^%,$q##o3u\DeS 3'Dh`W-a #>OEYIkZ8M3 k6w@$6ebYkB/抹KIswfb˳^>:3'^5%OE5rPF -EA֒&/ M;Wj7@ҹ* $o!m-LŹм/@` 3i=2o1R;E5BY֌#1W3L2DXQtu-Ȓ] 5kx Nj"lb;I:M ]\]BTX3ՍtIĕ;ԊaH\f'7ÅĘSL:"gl%-V~ s@й[FFc`ZĒ$l-p&TӌC]䓮T[0f?"F[~2%ʲl9 \4͚U Ұ fNiź%Syk$Lή4zf4ju@c3(ŝBɉ"E4L+[@+Fh켦VH%vGt26ڌMECfyTbFW0Ql|ϻ2%XT4$qZR+uɴ#].<̊ùJ6Ɲ[cAʚd$,fYWovXC$[v@Or9s'ၢA#ۻ za T3Z7.%+9=(*̛x=.y,OoUb1=veKZ´%IOBgf%lHkJ!FɕQUwÅA>R\]KHGZR@v+ScE硸R n܅ c]٘uBvŨ* {^=-Wy+@:ͰN7\P `\rDK5l6I5\_(N 5N cHsT<3<5u! S(86_C;o:(2JipqI;(nYS-s6(6g%#ِQBbJxoRYW Vgq(c"IMG3Rs=a-T@k?BQ+s`v_C^~ k @m cP VeiE Z #n^@w|Q@iÔiR! 6R9N=BWn`ʢkzYPlsN$]3O&.3HQY9)M\yCr$6f"R( >1jø8Hc>ݭZ"1 4zd$}c^?Iu**f2Za:j)EjЌG֢ UJb}tW̑v\%Zf5E"ךtWm&Z(\ǧhU R˹^=+זWXIUdwrر#~#osͺozg1B ]RU^&k (TKv՟pppqv"D؁ľ^Dкcu$;'q?ùb)Oq?ùb)Oq?I>}{;^֝=^}9ɒZ [._+6ӶN)J4";zӭN_^vfW^+}kOdcyÇ:;K.+_}Vomߎ_emJVS4#J~;F5(%@ۑ1xJuׯ]mVNֽ)OT&~|5l_.o'l3rZδmZQQAR9Zei$er%cĔ †s VƯ4I3"y^fFa9797ww' jI> 3czҔ÷_oN޿'e8g[Qp-Y5l+F"zkl<^fmZ]̇ Ԗ|Ɠ 2091(xڨP4F]D՚ȋ] DEhc&Fty4#G \8y^PxSQ܏og25kK;+J֕㛯|+i[JRM{8%3h35s2MygL8͆٣G(TlVz5'DgAlsU4vx8CmK'cШV+Gnb.Gq)d[IךӦ׈*TtCHpz3bD3QiqM$yB™V[u)[nWiZVVi_g*g\L떔}2|.֕⊤](  *#fv3#A`Xi ,Iۋ*'aio\Sx JegSX,.r[2mJgvGm[V./œ de5BW;Y8Il6|{)ӭӳbbWh we]\InKMiJ7{|(5D k'H:`nӓ$.r-6$5r׻.|4G CiĤT"|͸}k1GM'u cȥgܐdAɴ3Zш^:S+o{ET3EKv̹<$a5P ų2T Wz-Pӕ^V)d`?>`ycdoxϯo%wKZoZB̕d -HW$*(֞PA"!H"+Nr)Mþk<Ĉb&9 O8GLOɂm[ͰBP! E$J'ylBBI}v >6rS5*V 7='v#ю6!1L9G0UWnK5HsdS٘,.C2{2 n5%[ocb Y4y$".uweez_}uK|+nzִSպ]ZRS⊤IwvI9daQ/f*ۃuըpB!=Qa;\ [|v$h;0ms;WAXr6j+jPG!dzJ_;4 w`Sqnę&U`x2ƹʅXr+;̑ &Epy%_ І뷚熼,YX:1K <$|f+2by,Kk[nԧJWkJWZ{}kN'w=Qz^(jZ_% 9˓&O| Xim8 Skׯtig˗wvMK0߹G l{`ч#rsmǛmuM4M ؾ2ϴr?YֲYnG#ppG)߭eO9;iozkv?o{) x!)JV_!i-|]zVkez[ֵiM3<4M4M4% /'a5X Iu6^^DQR JK/}2(a$ӳ1,8/`nld0a 0^A Q7ZS< U[nKMW5JAgXM2[X$RGD3Q3R1_=l@F$AO$ʡrj6;?XK6#꟭˯ʭ}[9O$ooSᦵter1-~z?'ͲewbH,doM =;MF4Ό B30o"~d)VjMUabYDZܪ(T{%ֿDBѲ{1XO|VOoMSD*mgb=t4H!\ $g[p5k-E*!A?\5;uq!wgCbI6ʝ]DĊ][iq\lώZxkwwkR?`!hvq xa*$V*eFHsj,z,<"CR6fYͭE\:Hxrg/e9F)fHԊ.ͧL4^rS)Izظ7YsT؉/,qn2v&Qj .s ܍=*kK1ڕ'FwLi$!  vB~y@6vT?) 5B?-/="= sg-&h):XR7 }\U'A$JmhxOT= Du # ޽1gK*Sz5/E_"ؕՇ$(2ΏI3rjcY33MAޱ{>LԞbĊ1rY\*۾TABZ:ddEtf6w=!ʍ7KlsAQeUmabF/CE/pq/,Sߡ ѺLWbe+E!~r5N3Δ꼖3brܥ$61OYB$hٔ8N`*CtSH4ۨ+kVZ׃AY1_VO#ב=c KCrI?\y$㗁}|4#7&/|4#7&/qլ~:#O|4#7&/|4#7&/p:X??oZ~:#O|4#7&/|4#7&/p:X??oZ~:#O4N-ʛT57MHBO_>Bwu?Pή2 u6m-4; >[;U=:M_hxk7ỲlƈA-` ir@p S Pɐ :thQ`•.X1cooNi^k^?ĩi˄hO}̞<v'K W+xHJxt.;ĹpE%uL QBʙ-ODAj1ËX:#I = kF1ͻn_eT'TNҨU*~PyGCfUg9$I015DW*pM0yom.tיs9-XWg:fi_bH㐆ڈqF#VV4¯x똃EPtp,3,v&A!0q>.IH hBM36кŹȮV }<׭zu{+qN,2*; sUMD}4@Rwa k<Չl< 8S%}ņx:"`P#aECQ+ϸ3K  n 󢏝kT"Uxbv#g8F̧2\hiLEq*gY\8RErr\˲GZS9~1B3+QEu;}׭iN]ZcFE5IT$eaRn;nOY3Ե>Nh&< UxRB^?;!'u8^?ָ0"}i4;صh"Kp/.XǟI+U\Iyl\ hw43^jUVGuŠ Uv<f 'ٜ4l{3Gmw$AN]]uWO/e Wv(`}BF,~o#/1 d/[W8l*UFhV \J/nBpuP<85AFy ¾4iYxPgs/,IƷ 爑us-RX3_e q ^5  rlj Wv^֐3H^&fI ;!([qb,tJO2 %]~O|m66[r@:9BnS]m9̙ro9 8 &jKQŅ/̆BjqTњ#T&Ip{Rc"tZC!fGr敋| br4s1Kle&{zhw3GHJU=-MkzbdGP>u 2PߜSB1k'j⪆XĢk*8[mzHRmDWrYy=XH[[߻s=CkZnkhe?0>Zx͙ѩۓ xW{1 Jm6T# zd͞NpTX\NMP#H۵9%*z2{9 z>=r]8BQ,ٴr-##TVj1;>IlӏQGH:ŀ\q=ik~5*v;YHe/[i +j) *CrߩV0IZzיǗXZb7aŵM)0,<֏̒-]^j'6n_8G6[iE{N5-@t26[!$lplc @B3"%$T<:w9Fuꖭoj~}</\UnB~CFP؏Y.cp櫥Gt;N'E_& #\=aeL c =;`vl43yx_.eM& &Te Jd/$9ʞ3ܚr}ulдf[Wrt(z l".H0.̘I Tq g\VdG X@#Y4i264R]S3L zj[NP~V66r$S ۖj}"\ֶ#R(\eҜN(!${e׻!ؚ. c*}-?c1J;>*$041gw RM^d8)%o%@c.B12By8w05qemq쉹e+ ֶ6L.x);![ɑa2=͹UR=ulhGHÚЙ"kUz,l#-!Ml 밐&tt\(Hgܧb9ZyvBWTp_3iҔTNt0 g kهL3Y[6mv"wD{ks4g*ϱKfe8z[خHsV[ d~9L[ЮXL}†iЬ)fhdy;ZD<0>2*6¶E[닓+S x;\SǐQ*@W٩T3'Kd!d35k7]o=Vg!m֬_W.;"%vidgH["%F umY6[ZlLg1-t֔s$12i Zzg7GC"_p7 mcMsC8ΌA'o^&Tد3|)V8b?M!?McNme!{~aԜQF 4K8eFrI--dÓnl@)Eb^V[m3\ATx%G gcnZiFV3ƚU"ïnjۊ !a)Nː%VS:V&EyQZϓ)s_Ia:}qJlk7.Md}*j%A lpe*6rZ[,Niv_30mT=0s[]z OMY *XTc;n./]ı&WbDOl9Q ͌6t\8DQX&D)dpmN22g͗Ip_!TbQgXvXsmp\fuɺ;uz}bL?r>}bI~?Vӫ]rj+Y8&!uE$|'__?oO6oNN.o7^vTȫ Q=koiJ㶝oZ֝)ӥ<_a.kO$Oֽ>~=]yseJYv;ֶy~VkKԯ^%2 2B~%’n1J_eZgi2P \C0k}w# 6t@ ETD0@ir$L7Nx3*X>LxSœ6\YeS^ߚ=# e7&uM Gi!&EZBHxDeuPJ=Oe5n$:+UޞJJ!UNwXr6=\ƐX<*mw6Y o'qm֫hR&0qi$T%ypDL9TV6, c.lYmnd(#^3`)ȍ~*Z拫 ie / N,[9 0}Q$>WRAkL~aڃ/KVK6i+1UA`$LO֤3cG~{^ؕ /ZmV- ;қj#5(iEz,u.jg @]09.J, Jf;Sޚ9n+)v#VHb`@(#mqX %<ǒ).bREeq WD)RhUg^6 G[@S>3{eI2܈DT\ۆ)1)Z=Tum5tit-NԦ&y 6ňFD)S ݛbKqYukJ(ٯ Z:2V2#56Z0.JTZx s.OenSʃX3ٛ~ل\+h Ԇ<[A9Fᶜ2pDu+ck.;}"k2yqc7! t_in#hfeqt#sץof4 4$͐"-.hvښj1MWk ܭf6;U;?\-<%8-eo^:JW/[jjN_ϖlGA3'i%|jnb.:'ab"΍eկE>,K^_ő#_w[N|dqӂs=#ԔѬn 4*CfW2/CpQ$C j[6ƍ7!!o4r\{*T)zZƟT(ɃW j$ Ǽ}'f9t8lxAcCkyԊSGZSPy!ZY% NCV 2w~#-C d i%Fж^Z&ZMj@hvG8{Z8jIU0}0vŇ*? 33C/(PR:ޑJ "v^C(ٙMek2KhgN'\[:M&rێ7eX^'+bK[LJNf^SeGtZN 0'iubKs^=(%$)KU-+vi$u`;|fX-9!c*fgT"F@g qiZKْlR$eڶ<=idE4j օ4U/j欨v41d܎b7Iܘ>;h/ɈcF(T"Z1UV(?m)g,짳/wfiron!ve8 Jy^S;jVC2:Xr bǂ%eؖ-lkЌL52$`bKdߙ$YSY :-gLNyv5 XnqksB7R˅8+zK2^)SMJEӣ5!+ZJtz.:R)t㵊0eˋ-]fK/;:֟%z֝+ƭ4aO$21m T骸,r<!fc޵$ҁYb%$cR2Ì!U0O%:>7aK3b{Z 3jS8DŽ" (Tj$q br 17!vT3 O 1<ۿ8qXd5hl%7B9;xש=tSۏExHMmXfxӗW˩?'NENQ o;b Ob'D*:2&*VgǛm+[eJiuzV+ӷ/q`JYBv{s34((1ŷ:Q.Ax60UMD 37oe@Gy!LwB+C03m*Jy ؔi!ޑVVW(dDB%T"E0iάt=:r'sNO +`b#UQI 6NI; 2nleÖCԢ0梆`YBY]C:c&ajbv0-ǫP,/ sxh ,%L{sf9 "]l픚 82ȭ5Y\rxu:R]}Rm:ִ)Nӏt6Ny@ m&L@AT8ԧ\89ѮF ٲˎxgPr*4dڬ<ɍ,Y1ϱT7SZF2"fǷMmfE8@)G:<&\A!C .y:RSfQ]b,G+JKrq׎%1;<WxӐᏕ#}o]r:Kpmޘ^^8P 34ӕhbƠH]4k`|v} ؾ2ϴr?YֲYnG#ppG)߭eO9;io -_ɾ3|þ8 $ImBV mœ=dDB/4̘s$]ri,n !;ץ+O{+ZRNMkZwvuzJJ񫩎h[h߹-|9EB!b90 }S av '%؃_ . O*S8ulI9Wgs2R!sej{ˢ4 Dt2c: *`tyL(Q6{Pޒ4սW>ﳃ;;oN$oMZ:/Aq|;08)ir^@62]cE(yn2sm;>Jߎ"썱h&H`{ ?+kK1d/[+dfPp(/Ta6Xv [nuwoOw^i_ҵ5Uρ}-7fCʙ%n%vNY;o<,~"H钤؛6!P!s.zZpXz,}hOȐY/lV7*}iMiWogz{:=Q?{997D56F@:;z92"h( e' N*Td($0Vj%.q{-2s:(eSB7$;́u,^oO^}:vR>o^e+קZҟ-{tߨFs՞Drb%#٫nEr\bgQ(Q0%vL͜sH]C3R|5IwKB|+so m/[$x.2@Q[EmR۬yzR¹u ĝ7y!!{mY#8`<?W:l{KMD/lFjV=LbҶ7#9I]a ]bl0~ i>4[֟ӭ;+NwZSt:;zt;z~~5miM|p"8sZ!gfr`|]"zs?̴"(i5!]yL`hL !oڵ7Lxɩ嗶-syO" xd#4TCʊuZ i8Wt5T30LX8ŸL:jũUv`mfP0>JvGQ9 O2dV-KÊ0KG1[SdgGsN[ip ŕRDEVH(& Cx^L&:T_+SI7|`d++όqm!@HNLjaK@1k2X!HZW.J)1ui( $@>C#pHTYXF`TH۽קk:$FN;6e%qffV"YKI8 k54i5 tNX{DE&CrElɜ;۝&LxRݚug`iXBl596pΫP+i'Z"J#^6qi;!_̮̎kl{F0_6Zjm?b_ rQ68"VJؘ(xa-*,}++"^gh*aOu-t~Ym>w㭩}Ui_ִW~>h,ɍk2%1[LJҗSN?gwZҝk^;˱Q ;mm|k̮$f ̡>mǯ]1NJ;,m-)Nogh=+Z]n| z׿z}kɷ'n}NsSt0x)O-~Z-mowm:{R86A,՘wv?__%Mׯׯ^z^%Mco[v<}8l> 9ه*VX{zYe-_JR㭉kf,vV-nҔa=>97>v߯0ᶗRX[m.Rzxi0ӭ:W;)֞{N>8 97| ]dnh;io~vקJ|{)ӿ{88՞FeTERX;P{}۟_n~z8888vOkw]9~^voeӛ;/,sӮ*rڻq}OmU:t SuoOvo׷ j۫[5+uȷvkJҕzҴKZW8lCB6umxrK3Y$A%IqiKҴiqkScuYO:K,u涔n e{keҿN;pps뾺.Ku+JW_/Nn}7;}7:Y{om?[-:Vz{S8l>맋O=Ϲ':ooe;~Ӄ8tvtOu| zӺ;iWq?VΎ3hᦎhᦎhᦎhᦐl_Z˙g͋Ys,@7#u8iֲir\ 7]ciY/ 1K7`m2c:ޑҙV+}2ӲVSVֲYnG#p߇ۍ_o\tYsH|}ҹ+woƍ꟏4pppq8:u)Ouu)]?4ȬH+N#ToyC;$C1(dvBd9y |y5~io`6c fˍLR`p3";fSFӨg %(pHi^A,iZWSb2RJê{:)RzvLyD}[rٌ+:!b3H|盩*'c oUkצƝn&c0;E{lrnٿ{}==%"Yc6ӜE^-28%ἤzx.}BN[/g[޼=k=&xU9qAe[rׇ$ͺ%]r4蹺q`TM{3 ~s WǛ4_Lb9ZjRpѿ@Yll~N>LgZlx|b%npH{ܳ4z˅\ "m4+mGZj#IJHSi)*$N2K.ZbHד /^{ﳻ_M|6R&$QRfIPLj2"l&>#HidWR>8VT;'Jk=l YV>|>?ɒRi|m7ْZb>`dv:g_͏4'edFѦˑg8i{TЕp6P[< [kӤ. GC‚Lfe'4۠ 'XQNV)F땸xj# 68 #H TFU'ˇ.LuJvuv{{zqFX9>79 s. 1Ʈ`s97ڮ1wM,.R \ilT-+Ux^h75OoT3̚~~p=$eb]zId44$Î8=Q6 VAc<-5jIf_0D|ŋ*3Z&xj"NZ[r0r@$rDZQz*ǭXNLW(W+4s>퇢 fКd\)ǀ<mYXMudQ^pSEʼn ɗ*-+6`y3Y^f-1ҫ Jf22.隘fXk>O%>RBܖxyDb {ri l>oշ\Roī-<U* O;/q]]* O;/p|J5\4pqI<Wī-<UM]* O;/p|J5\4pqI<Wī-<UM]* O;/p|J5\4pqI<W ;G:ֈ|vmS^"J#Ӳ6'I*@FTє\gV?}FḦטAԨ ULz g`@Ic2zTyh0gc V2vi*3c]+g;}r};x/7vd[u/]T޷V)m;)m+iJRe'bJ{}~fA|SM}vodS]ui])N)JS_1]y^iJW}wwZSw R*kdQò ٸBlPyL8Sc [R෮k#d ɿcy_,xFeI}5{cU;~Vn۝+ܑTN؀9Ldm/vwuZ⢵[`]>؋y%9P;vtrf@S2 ˊhw3p=(Â\S0[8=Cv @=E$|lh?(+HD,c;/Pq>٣ >U%S~l4*̚ۍ; `Hk1(ו.2rMWAW.QfxB̈́%dH:le%伥uaQ%BuN%Ҟ=O - dexUqzb{g$ʹjXeQR-]m{+N7ZiJJn fH^X]O4GqV Ckg9#!;29ϙư#-1E8,9LrKwe`Ѵ`ܫ>P7um,BeXwŕE6HoErQ!c1ۨEX<|<'.8imn.u:ӭ~jw׊neonPa MVUήTu!DA 5˱ew1sXga B°mJ$3J`cKvp l1- ]dnh;io-zSmtoTiM4M4M:Νx:4#^c?d0=?~55S2/I1CW|1凌yO8Q| ᦨ_zU9U3!;Y ~1$`k=1__ɚoGzދZ?jyݘ N6YSO +,<(BUj$Y;)C@m&jlK=w\8iJ|64rŋJ]%^:to^{{}Zv!^k2˷ m#s;|;F@56|V\Y)N'OgJӅv8iHG.#F|y ++уAhⶶM4M4MJzV3\ C»b6)^iM)^@+ҽs [4+!,+cJ!il˻$ێ}oJËY~E9y `• |A~pÑĝ:}=+V/_/2Y +[ܾo^We-)Zuz]w쫋= Yg]Wb ,Tn3`b.5Q5/] BF> d*ͩqi4[3GE6nJ J@sQD J>;ڜ/Sak_-/:MƌJ%~ۘǍxhkf.<lr"ˡT4)p-DrByS+H6\Ϗ&r_-jSWv 6bho;:}?G 41h;N9(:dfWL.2jj(44eGltB ͌R[3B$N ^@V}ĕB)~ \3y*>|yRޝE:1ts$ ¨/6^(FU6'/:WnEa=׷Fq8G֫i1o(ðW*h`0&lvi ff4d{e7҅ɢm` =\ &B'ne3[C(P !ؽdvTT!btޭ,\R.)ԃv$jeSX6qrߒeIb7e1N&m@o919˪4DV/~D|AJػȉ!+_yq0GUWU +/1ݝhZRۻyLs6yQ1Z/imrUyfgȕ2~oԎ˗&zIq'aeڱf:Eԙ5Ae=&k2nĒ^l-ۯ| -NJvQ+yiL8 Y*L*$ ~JU!H- 9ŷ1ir 5AƉ0$LJ ǮwSN$ O1̻ٞKi²I;`eDb .|Gx&)-,Mm#t>&B|ؚGyenkXzbJGc-.,ݫ .g vEksWeB*VͫȝuO5V],Fg,A/Vs$nZfun\')frpɶZsɘU#m#dw|A1@=:phÂ+/\ګꂻ"Ϟ}ک|/(?-_X0l;vȍg!6gI-F8\bb4jQ& N}Չ=u;r5ÔOiFB{𽄵ZXf@Qg+~\::6ȋCl͔Tti|Toǘ6JM[lB3"d7S5v IeX5Ri' eBp#X۱+BiJ!c:24p?Q#g"Үw;+O/tb֝uu`c!mx br=w߸XI ֓ZXkL2FbBHXؐ2!SRRԥ)O<_הM4M4M ؾ2ϴr?YֲYnG#ppG)߭eO9;io2H"9%ڋxXIMڿ#輳,O̒uEHӵ#mW5<>wьPk!No+ |"ῃJO_5jo[mTRPq19W4&˔x܎,M9W=8ҍIR;"Dd2|ζZI*pnXڟ :!D]bduUo% y(ZMd=8Ⱥn()y{@Grci~\75zr's%V|4oF<ЀD= Ar}kۧժxiyDKa0ġm;|B$ mXJ8c%Ҩrn$r&p3ivNlM)=oF;#+.{X~8:XdT%qv֍JLY<9~-#'S ^UT>aw+$Y͇e4\\8jKmql3%byÐ$!qÎ'C9zj[a%$iێ^q7H|} [Y$ B"u[q Q!|kuA5c9\g]!օU17 +tCs22~:Z!༓8ވd!m,Nm]l_,L0h_rt_VP[6~o̞{'nQW%͗OMj>%_iexj]$ٮ $ijKf*]D1lVș肄 9y̲V#r!i[S-[o"fT y掅CdƆ˰yiRGÓ냒y0GTaVe&vy{3NAEyَI'b!KQˇ)53{^׽u\ة^y{SV$^QFaR2ʫ!a؝qN Ōj36|mϒ@)7Uv_j&j8߉WZy~?櫃Uv_᦮˃Mj>%_iexj8߉WZy~?櫃Uv_᦮˃ww^ϻu~%_iex'hӕ=;r9lkvj r{ @?R CA4r6sلZeerbn')TFI6^A14kD*/#YNYazX\BdƠub؏;qZًm[J[e+Ҕ_- )ǓdݫɒUEM`l)̲RQϏѺ+. /.w_s+^bFmb9)Nl}:Q4<+شK+un9گC[YlsL&f89G0A &diEkge!*C+&1h~}=ux6Fr(ca(|=ٙ?=@s1'>~y|tˬγ¯_ {)NܣuJvVzwx^&"O+yپ!-γ:3y wnn޵ZiҕJS1]y^wZTgH5 ʝF [llYqmdǗY}[uYu֕kN?G VjT;E9ּ"v1T3x-:@I$yW_f1[=%.,lj؛~<9)gwPN?M<.2k/c L<}ncCrS iA̍~G`59si[ P"hʲS6H5o>F~'p(Ha!Uc`)FbÆ3jRؿjf ,b$1Dx' PLJ5|xA<(ĝz\R*ŕ28$-b{iȞXa:93fYAm-l9T#IU |?B1 ps (mh`c#XY5%+;&M&և$  3ZHN&g6FrPA7O|"8о#W٥Hbeܴ8K¨(_qH/{#8B2KnHk?15H֦Fi& \:8|Y%5-m??/ѻ7>1~k3ԐnXtVZ^Tv,%q#b[ֳ׽7k䤺K"V$o+6m,85׳&rT>;U=ٱ sDKmmidZHuG"^E>T*F[ɬq= RӘnȒ"`"Z)sdőc Cۘ^U@j DfُoDU%ͣ0c maIӍ G,dxkY Խk\lwR&yj}C _FJy,y)S )3DcApI{#zJ6kWl '+c;:(݌r 3f($S.7Cep^k%Q| |<3vp)ĭJuy."VBD\вb HT|dSeIQYi@"у gIMH"#Hԅ(c^/abpܤ"T'{rYGejVJ@G<ZRJ0}&_2*a[K8y;n±FVK\OncȨӚXRl4hE1ۊٷZ"IVRۼ; y-]dn%fs8kZqZlaY/Mf"huę9KV*tYN`;}ǰ 8έdK*^3nz'JVҭۍӟ%շq ^;Ҩ9J;%q䁧D1eXU~ϴgZ>zunlU˔δe[#bb>r m4Zkx?C2 ZIhdݞAlF|It2KSN*Pi )Szu ^W:0x q81ףrF"ڨV6 v.7t\0_Mr N2T[;7QfbIkz'TƧʼڤJ۠B%]%af_wY1:rp 5l\0@lʤm^6BtI8aZ #PZ07hZO̒ )B%^g ]dnl_Z˙gM~-?MXֲiH6/e̳܏FZtnӧNn'wN1RkӯeiSOݠ묏~U'|:ٸp }/' HqݶRY>i飃88\i`d|o5tOSZIqR =tVn6煂qAX:a88_}7ڏ|yv +%Dem6×{PsBFKH26hXZq5`;Bw6Rf Yr1lai%3^$nmynkpGIŔxq \(`O!@F.X9W+\TRJ)dΆi.[eŷ]m/umm+iJ> ްAږWrՐlF|O}} ×!gFWĝ7鿥pq\Q9V59l[$I $RF=T]5um LvjD'`ZF4]O2Mm¦AG$E{dg *?e*lJq'thCzo?Okk bdbOG!!J؃)$$96`5,pq|9h~䘿F~ҽP}M~jW hBN)Ь>!b]ڣC!r4bjD'`xS+2?y_~^џMo^HQ,dc8&Վ{l6QHzqrȱ3„}Rе,ƘZ_v*t].76ÅO;s3xl b<JZ&/џfy*8N{x=mǧ/B7>)wɪL~2)5FnoȕMv4M8E aܗ&?8M1<#X=&q 3d4_%4 !r${G42<} ku $}ʷB5vye&oAC$xx3AC$Ex#1;/?jpla ̏_-KEZ&/џa b<J;/Igs[cįQ b<Ja,M{NM1m$Gr*|IG Q1ᆎ!%p\ I:E̗j$}{Fg?5?|1EZ&/'#??|9h~䘿F~ҽK5_}~=ף?>%~"-ܓWr1{̗j$}{Fg?5?|JEZ&/џa N߂D_~[=iJtׇs%_~џMoa!1H=0m &0C0DsnX^Ӑ)M GzN"EBs~}f~1?av8_^iGoL_iGoL_=̏j}sd~?7Gek_.=yٟ o^ҕ텴.sI}7.ԾovMԺ^e<^uyWHͱJ)`lZɰv5Yq02LFty O U,LY7~iر`ᇍ}"j) =2ȪڭI-r7 /RlFؼ~2(^>jjV7hR-dE~ . j\r&rm#VI2N8d2Q%,{9 9*vx,M1j``՘&dC,Go.m eY 4D jaւii ȣ=qk`'#UIFֹk=heaWx%R5*N,e'xVPZXjpFC(W-r:u~ ѵS{W>pJN3;_J GIXL= sXN̯KHW$m"Ic -€u"JIks +MּmG c4g*UnF ݇L.%ϡH݀]*[m1=и6J02J,nzvb!>~V-%~e%_(M64]Wd{ $\$ Tru+HPS`usu+yo kG?>wvHwa mqXv5ꄀD~w`.xC_Cևmܮqa sb=IP"lu8"7  /b2Eֽ]pεNO0ōF%yy$>6`nu9 jzܤtI-~pejrK th 5K"ҒB(A,6|,Z:7D 1 frgLPPuP1ԥ\W $"Qr O)@L6W#B>a,o?=Jl"5@Oyc} yѠMM f5x beWVcښK8@hrS.a$9^\~[)ZYLNҽ9c==lDy s̰K-a6)ICl KIYgNq.$VqwԣMY9UwdYPYmD?,; `$^Y *ﲵbtZ'xSrـna1s5/̀V;'8e5P+o"IRf9%8#lRvL ¡\8 5&p{e @=d$R.ˎF{ΉFsQ0˒$֫,hX b2x{6\~#!ۊg+9LB_e#``a:]V(D=VX WAi%yknO0Ȍ]gzΎSleĦZxZF-9Cbr|ñhO$(L1/ynpmkb54'L\=s<%ՕZf2DIoT!v) Ke.mضQU E RY'3 8^YXG )aT\UJv{lǒY9qR/TxjEJt1NjLF\) (M3m$+Vsz~} X$!WMdz^,X8LU{_rUǦ$^)L<KY :bz*|;f^n'.,"[2!Y6hĒ0z&݃,孹]K_rȆ>(Ru5rBNW^b ,.Uۢ[KR5=g@af-E,ak6Rwf8R roֶG/!=9@LR( ]u$iMd.64:Vڥ΍"pd՗(-FbS2+S&z\pD/]2eŔyuj>aq=1Y-Y͋FbE䡣`Z$^K_eʆa$2u2lXMu;QBYإޱw3"3F* |-S/wR f"-sTM˒E% iM`٬x҉ѣ&rv `/,N+ XZP界z zR*^)eiKxvҵ)JV:ӯ׉bmz 6eJn_ VPbI]*^mν\W[fU, X0W Ii4V*#iGO96-Y}E3Mbܶ!Zs]:%?N.lTHp 3?y^}Y6>W8%Th')P 12ʇ&H+V7*23-SK,[JW5)Ou)Đ4ZI38mu6pؔ#D4:Զ#lLȪa4r}j19dKxb=K_[V&[3Iyf;W2os'sЯrN \ – *T Ȟ09~Auʍ$@_ƊGRMD܎FoWO7>tW Rs8W s+JWL,rg J֙ K'ĥKFr<}-Q7G^\+ *RapXDs, "0·|G 4ppppH6/e̳܏F}4wYr@4ux@9Nk.Zh. 4sb\> ]dnҴA7ҕi7V)ZW+N˩ZV+׆כֲYnG#pɛ!o[7e2braTǚ Wf[:]-)K/mJӌOҿ4tMIqD3eblr3$h&2p']qK$398%gDz! !@fy*NSqe3uzS[k[fp1Mb)|aN%/9h=pAm1q̇cO| O#G e'DA5;d`UuA3]oy)qr?l'+d(8~ĐIO{ģ :s+bؽdt4%G@ g';cv"Ih#ab1SӱSu3e  [nƹhv.B6gXqqCkPm5Z ^mzvK=@i \hk(W!CmUYsd?8W!T~ >9)=0DWn$duyZlfOygf-C]$w\7 ڿb $!Y,eկZPX WLә3`suE2/&5:A$c!"`!=3 Q̹PY$=3;-Btj/wQ_ Z{768طdYQMdbWacDoehє鷋LqdR1K{j9!#̈yyj۩Szo6~SgMsy;=U#fO݈;ISd^@!6QzS [v\tnhP( Ch"#dFB,{hKE]&6&[ШseCm+ؼnbK6[^.E9+;na^C-TE6Fmm 趲Ȱ>?C6ڱ2aWtGlw̬f<4<0v9u٬R(xJ!j+^R1蛗B*Mϯ1@iuEbmI@.n#^- 7> (k"4ɏMIyZA#;!$kC1i7 =OgN&GB-j4-}FXP$l꒯zI|IZ镒qבvŮp y_Ҍ j+k / fcTb&\ͣ6@"OW-eh^Rwޮd)ߜD0ymAFE!LrPI7 MϽi]'vmͣdY8WӒD٤c9 P\0l&jöCX&OqeYkCpװ6l i cum!2nK<6EɱQr_gFni&g"i͓s t棴S|(oX=p*[HxT'5)6M[nhKtd|`J @@ ԕ!vW')]%E/]nb$pVԌ_^_ǰ!T؍֓;U:|ܣdɹnV+$f\v'>fYKo!4hv{I6Jݭr3waeçd8.)m mlCz&Wh5iMCٿ B9{^k,aьƞdV/_#bRcD|^>t#ZrVfp ⑼ڃbadNPS)jWyecۙD$3p7xS鎢a2]IK ZS/I\VKVQLPSF}tO3mmSIO G:w8oFTͫpŦ GC8AhaBY٭ `2Ѹ%7Wlzo+\]L&B4 6us'Y5xi^޹5)G o9fv"*{H^TTj2JxLAQK ZN@dڣ.oXuKŷvkv?rnWQr3]o;n Iح*C'Mj˂7ft*jlJA_s7ϑLvjXR`_HkEױlK"큃25jG%xpQTqc;S(M}9j"_ug׳ⰸa&!$8ɋq&K;+2H{iI(V?4Mf-J>/Gv-{?oKZi7g w z1OvppG 5>avz>;7y~`ʟ:e\N_qfU7cꭷZWJ]miZӷEWvo&\9ݕE-_bLx-]TŃm,VF>,Nc?kg/{vPP]rpIco/,+Q4vt1:t!%ISZ5@.$ Ua'x##C+0;(muY;w)xwEb+Y=y⚽ZxBC+.,}WlL8dq+r )\MB,2&ʧ:@F-btX9)c[TRY`B2;5&AUoۗ ͑.1:X]+qKȬ65 *NFqo~;m|n>﯇ogkkeԥm.oJ^{iZҼs~@%fdI%Y <܇UkdzY~jM&QA6J>R%FtBlK0Hrw2h; 7΍[e&1 YAU.pM (?b6iȗYb*F"D8J^ۻ8}%jC!k3ʬ K%D4`_^VqZֵֽkק6eyc + -Y ,_qzS.`v\4Cퟩdxa1IX+\n5(HBV)r[3d4 ݑ!>$قc9s+FJ\ȟW y/%2&;Yg3"fMϝ̹d.RX|5fqo[f<'.ŭʥ]nWz{SxjXM0Ee2C BvKob}ud?H6Vr%I9V\M$P> rsl$6f  duS sQs)8rSi/ q)T\(>5zyaM9cϗjxa2$Fjӽy^ƓH-f*G }tK)u,R[[K[׭~q]0b{, ,ңgG ޗlVo387kӏvbR8XKC$+<BS~zʻs"Zv HJȳ6v's#ewuˎ۲YKJm+O^8\u:e_ַtzW^zq `ΒwQW%a$3 y["zڪmUDʶj IS,Նn\N.YvC]&).7vhz"'U|L!o" &nN13("v 2^l_Z˙g¤% [7 S;^AKi^֔kZҵzᦧhuvwWm:ӥ{Z 5LNMwI|;]ÍBJ$騱R Np @K0T UtacCSK_N=+Jv|54ҥ;;uBzEzR8|Qw=޼s;{{{M*?ǗV6Ҽ_pY1LF.i^Q)VѪ":|ٕ}锒Du 4Jn;д(a]p(VNMZ4RGq8VǑN!q./G7k8iGG7?_{T_{6]'H Ms\LM᭬Kty 2ʔ'L)L /2^5ᦕ/~om;?]MS8Tfjq"2e&8O SPIdʡxFHm'”W| ڧ]Ts+dY#T]1D!Aq`oH K߶SD%\r !()qreͰq~8%!" 'B^tO쟳'HdwYqp)9t 9";Y@HTP>?u+G|q](8B, u<<Ӕms~8׺%I;u GOV wme\vǗ)>x_ c\[5+ *2HHab7^AzLZXҲɱFݢpSg/{DqQj>?u+Gx;;:}L{;;:qi;y?Ta.H >?Q_b>֣{>:Htي5d:ưLe%T AB2b R'_F3k^ܫ]qXK`Rem |;#q[!#첮q24\)zL^y-`*FQ%cm£=sl^ʬҹ'ES$~EjʰNErG*^yY,4φOqQ)9\|޽~>n5UCnaorDe /4 kMҍ2Y\HJF}En^lbzR&lܯZZ44Af&%QsԟxA`6!Φ04|ѪMȆgGMƛސjsv^_;:NMך yr 3Y&φ~fEҎ> _=?|*?U~fEҎ~fEҎ?Έ!/ a1y*]b]5A525Ea6.B+nQ\QSP$=bk2B?ډsH#9_GkG=\=L1ණSW>(w$iZS;Zէ]8.1wմ"JROJ֔U)^ViNW+k-}kmn]4-iKS+Zxc9YG }}?}[Fs AI usH=GSX/KٻZ,GOq9Vt3Srd"k 2C̆ג3X .J\q+.,q(H1%\5B$ƽi[h`w5}TT)sfNGY3fiWzV5xBZ(x=]ʤ B.$_=Arj)pWnEʜ VIZEy([ݕaMbAc@0DeL fɱ74zl֯* Z.eH8e!Nםy]rg(%*HA)M6T.YeMOELWJ [V_+qgUQyF7XIK, Ԫ43qτ{.UbbVYv,ϙ~u)KڮZoF]T U]+ykl(U M ^NzڵW[/ QJ~G,%=;jBx:<$Uї!DP>8MV5\-Szbz-WUJkl蟖|%1]doHE䳷ݎB)sFDD\Dwم[sV93~[XqGk䚵)a"? 5o\OW]U7ݤչ~|mJjFBiV C*^J]Y "N')rC=.@^hY%5Y+q=(I0[k)eaL=< qe]ZԮ&4iWbTc[E,Ln1D->aMJ͗Tk$"Ӗ2С(yEs5xIcƣ8ٕma,UNv4,J.RlUFA;%-:6&yG]D)t Fb/d4_/w{E{9^/YmLG{^6:YcvZDhֺ2`fJrBc!,fS>+Oڷ.uunEFW-jPFUb͹ZDhyz nj92#yg4q`]d x27.[i Zm6! *T&[&=ؒ|,P(P~=X# v^t%En:P&G3b [(/] HMv5ޮZwxX d@dե(r:2&8T 0],fEiBJ>l)XݚQ:X˓RO{5[Lˋ<Շnճ/nVbPy֊H%I&Iջqc0HlG#L~{p䜐[ ȜjL`ʏȥѸtsz6Jy{Vm[dZVApL1ciُ=2ϕ6q!6ܦ\!kef4v@uJW' )kDA[S- ^Dp|ǖLdŗlde 6 Bd1v;4Drdd)uՃ {F1-RZfomԓdV^Vsn[0H-~a*0vH1 8%_`a{4"o˺(1-SƛcAgXy\t%~l1MAQ<]9LDUgC:y 3tŽX7@.%O&Ɛ( ȍ2w^ ,{fr܁Z u\^'\tā!39'{Ю-pȖՉnD/$JTqKjna뷙ڳ|Z@!kqrGXJJw뜣3]I^Z<΅5"H6 ʍ`-ªWYCbj=KobSZ{u$۸_F~ykcB]ivh(`6 XQ6.zBw:Ag:saHQf(T$KDkDnٌ ۍq$(q}:`5e2|)6N1jl0.][1 t)H+qHxX֠)dW+T `?.yMHEq˒Yj ʡRc,CFtFg ;[\kl@Uzs070yM%d`*Z*s+[;X!*Z xછNŧR`WZBPv|Kje> z)[3,ly$PŋLUg92<T m[0K`Jv%21qӲdW[rVnj6j!X!kui<Ŗ%f!o*vyXlXd=s}Z J9&nuIS" ZLMU$Y~I /ZlԾgG;dCy3Xn>ފ\g@s6!ƅ63`g _1ZFWs'dV^;a=l5 cu̧;R9RL6-(b Rр=6>\ִ _QG8=>GᵘT !9m_^PFT.YT &Lr̓aֈu#11曢}楁:y(ti1m]k#"4 Xd ⴂ4% &&X.aU_w2]G6Թ7)!K,9ÎS&moL@K4ߕV k mxmd-H*scmP0~ /6gqQ ` U27=-_No^sOw$FF%k}1{==6;RVgXa`y?,ՖBR-,Jfٕ@9}k.eh~.76/e̳܏FSZ˖swYr@4uxiֲWO~nE>o#ֵw8m\;ۖޛRm-oH|++ێ׭xj}k.eh~.7 q̙rݺqlv~cHR_խkM04MM>ӷktY57',.TvCџT^y|*k_%Y^GOߩUGe>zӻSNӮT>~!/K/cVnWpU9VmZSs\wחLE;Fn\"Ҫv姖.i YĒyQ cm3mۓ$m=e WL!lzԻz6c3nBp4Tڭ_ӵ݆>G-\6*'IW]םaz7XBKAWH 9G9vJ*,6 f\H%&]uz%W<*b)ܞd|f{.h:qQOg ἌT 5S祙x, ce_$SF#./ 75: 6@vk|ROJ$'h8Y(:M^ܡFҽb'W7r9DjEY/,= cR1[S3j3'J f07zCltQӮM\^`H'">hXi:y?=Rc08k&o6P~U̚JHI6NzkǠRJ fHr 6/a bf|u4b2OJ2\ v7i4FyLMo3>z_xEB+&c1<b=ꌘGN㆚F.F..˃F.F..˃F.F..˃F.F..˃F.F..˃F.F..˃F.F..˃F.9Qm+miZ]J:VޕJZvWqra+76&h!Q#-nF(#Foxݍ&͌r\7̌P //%SF{KNfD#.Vư9UC qCMvklR-{](" !H%x,R,]2# F {U2\Ű[+$! `4R79/ ci38P*nCcХb@\D-wh]pH҉|̫>I  xaA(k6`e|pmT`HѼvӓ\ٚ.ǑdiQ ڝ,bs8wsѧ 蒒? ˢ*Aȱ+\[ EJp+vb_T3X̸em[fo;ՙYd} &:xSwQƻUU*E]:мWW19cFrf I̜0%өPsy@mja@ BQ_cBrN5Jr - !u7 %;Z&9['1 * RYc &m)AǨʼnaǭruܙ|'olʼnJI9F3ю*Q:%o(-Hױ- ;BO R]mMā0O&R w,KdKGa):,-?-X]1rj<3A)(*WZ񂒻I) cp_ӝG,l~G7)8z2v&zevS [8괔&Mj+ޠݻ??M?4PRٟg,]OGC%?v링Vgt~;7ӳeNSl_ +_viNViҽk׭q ,_vM%V)!nvYptuKȷA W y9>p$.H:Q9'kXlQlW\*ݒ]mQ;:51kG5t˕D*e9 }ԗ ?w6'We+ȕ3nPm;do;5GkJSkJRe)v 64K,>1C=ދ9( ~( 7{ F &.k "b<@ Ps\Pe$MD!KMSLgU'ݴQV9dvfr6#Pz7W9|B>?-rxwV +l^ KOclUL *\sYj|o"{zӧׯZRkJV_QɩטnA/'W H IFQ:x8z5C󡑓Wi<>TMW2cTqɉ>&U,d$jK9Y)c͝`͜o!j2Q{AW{[V=IXK.9׌+1Hy#E3 SmPKF"1t=.iًm-{yjzɝdx,Aw)Nk]I.@[czuӧ r q/'QMc}=s{ Ī~l6a/.͊0VK]ԟ$έq1ar!dXHoU{"Bܡ? h++ P8y@SBviv]'(rz9wk'6}raĬTk:Q8dfcVse`TM Y+BE3QR-$,@y1d!`+0X7P\ސgczڴqRлb`V:ZJ)Ɉ{0ђ2eNcVRFD"8eMEv|*&4kfr+Ҵ)ZwV>jTS挽K&fI8R Ht|z3\NNbpH Ɲrz{Wcƕ09sUͳV-TJD*' gDqnD[4um,&q)(&JQ֖ϻ,(m,XiEJ]._3`H[rhjL$xrqK6 `VhV^?2aJ!A.@ Mi5c(@+@īVbrtß&<ےQ N5l2]695k&Vv"0VE%ɳ*qai+8+~*㹐$h% ?F$x0n MڈH9z pik<=HdZ.A@~#|H9يK UA B9R#3 ;/[b:ncҎ|>NvYI(/R=q0kc.4v,^b56l%k>5[9 %2Xkt4#VEeQIL4Q5ٝCNGkogm}u(ߋ!B"+B2qz#jLS~|F]%A%lU݋Оc;ų"ry}4M4͋Ys,@7#u89}k.eh~.7 4r\ 7]cSZ˖sM ؾ2ϴr?Y(Ŗ{w|nT}| :[uϝ"_e֗[~i͋Ys,@7#_#{O(+mOo: Gޑ_G^׆b+ӯvV?CSSǫN"S*l֔Þ>}^+|/·²n Ę1g[4zF>S7wI׭>JZ{{^ߛAn7 5wlZm.@+8p(LL1*TQ^:EÓ5a^o. =#~p_ 5&zk/O]|/bG.iݐe/I1yH u+azވP˟$<+>&[3]|Yۑbf@!nDXTa")ZxK-B$J ȰUȇ ¡j2a*;Wsw]Â8);"Ion@w^;qeT/'xR5pqhḁKa2|Y3gϜ),Xp`m2͗"kqŎn&Km[mZ[=Nϛ>zGH).8t\]֨$XQfJ ҝUi5Aݔ+l5Jt:(F*^Lf'dWD{Y2̊ݕ:|{޼s@V`sMui5 Mt2×-U:̑c;X,RM$ɏF1dzFG5]9[Y1e#h*DŝiGnr8ΖRivKԕT-1㥑-D!%Ҡ譼WI8n!hr+Qn )/*%Z#R"&wdȧ^qF"+Px_U~vsZ$qqq! Wn&1Wa6mڂmvG4{f/Ƕu the?PeݏlX ŖXbj&Q9 e7*G=jA(ݏ5I$:lRIQX/ kr 2=kWiwit$S$e"F;3$ ܞGab]u2Թ[ Izz)%HG ^' brvfSqhƨ`{$Da+UtIT*e@'!n/"@-#D( giA 1S 6lqbÀYE82dB&`SB qᵔq"ФX%EbLN[FԟQY((LX⎼#eXҭ ;r:{ "m$6;ɀY,/Z'fq,jDٱ_RyI\y(j7pzv{~s֝kOwĐW}ATf3Y~zk R[U(*jAZp֯ 0B08888\4M4͋Ys,@7#u89}k.eh~.7 4r\ 7]cSZ˖sM ؾ2ϴr?Y}.VVJ}M_Gӥ?mo^^׆?ҲY^Y?ʹsfpoqfmwn 3Wܺ#Rx /ώǗ_}(LcşoS&:?Y? 5_ܯZR\yo5?ulfkoKMlP5F vrwJЧϔQu&l@/Q;ͽ8 ].-o ^pk (W.\9 .YDpQ.1_ .mեkj𯇺Kihcm L XTԸk[rV"얺;MAp6 [׫cvjdG QԒ|*1A$ wc3gMesyQӡFrYdo,q9I,2j쨤k<`y]|,0܇ބ䉘NKܝzL& +2y$5,P9ȳKn=i0m˭Cc04r=JaLdBoѸ{Pŏ\qA2XNKbX 4бs C8B pmME;}]+ \As]T"Ci(`ޢbbQч alJJF9HaO쓭uD'qȤIf?~BFr&7y*b-^xW\vLH'>^s~%m7q޺:m+ݎX1JI:WŰ蔨]Xh G]2qCO 䯩1òڝcod2zd IY~ӱd`A6=q6nE>BmčpZryG(@n,۸-vPj Y<ݘj40a~JfrqgyDw0(":b,4=#H:a>Ad4;a =:dL.0]g'VO>z>0|A>(ٔf4ԙ|otŘ]0nֽ͐$Kme3'<[auu$RDD9Ĭך<8J:ي׹ ;?]Fdj +AHs/P,J)J"ҩbk2W5SmKym[oDŽL$P s" ŝs:(ݢL )ĥD8FVW8ѡiy1ݘخjHq?]ѝmehF_F5 y?cB,@&A0zkU)Œd U }1"H6IE 1%Sed$rZxbME7piPulPpM#θEF(į&:=rK7!ovc4Ҧ .4a.IdzLHHQȵط)ogK-)HP;jL+ -a1 \?u'Z@rI$["<ƌ;*""wv *K3IkPݛٟn&AۇE?8MSF†[_]̤;xGTQ*m#d*m9MxeMc:V[͏qAENm@Ə lPY)7 c9PHł3Kzq70>{%6<F;ޕ-s:֦Fh$5saQ/aALJ+Mr:_0wٞ(1ҼWrEfn$YLx&d+.itxgTGθzɟU,+NfOo{8^teś;LkvVf)_o^F_)t}~8LHZ+O:tKѨB]`̟=ն,coe)[N:[V:ֵOҼD3T@ 4$‘˸3["E (s^@g[@Ү2qUKyhe Ba2H*xI׀c5@⹪^%Cf?̑`!V^<Ƭ]/sdeI[qCO!aShbE wNdwXX G&eQȡz>3{=yPKm)ւK6.,ҼuNQ<+<.C2o(7:<E:cBj UIr*0òTq.S/Ibmo{{ k0t&i w2ol &aV mYbr(F %,A͠(_TYdE2`y;v5eOTC S⠙dlfH}1HQ@r( ;RHQޫ#3,, hֲ*-:1v;Y PWT v*ӆ%1!׳?ٖ%[N5;r67 {V;FA Ģ"J.!ȋ^N[m.Z;xN" L)g30C>ư\*<&!>= NPs<ǮGQ%pyuK=FƐcC35T%~+4B;'̺1=iFCzFv&2Nmv(';m1z7CQi$\idwU-y-;z{x춝niRv8U5٩6Kq 5yզ6ebjG䗂 #>=2éن)ȝC8mY40dXkiya,ګ[aI& i @h gLq[Ď{-so<:˗gZ"Z]،-UvĪ"yffgfNBT% [H-⯗x Ih85$2٥s`KNޗxz|zpW>/ˎJַRkoe+^=5 o_3\g:#7ZgH֦q\E![,rͷ # TX8bV3|@K_.8\LPY,Ԩ}L$|#fSmȈƯzI 5v[\2%`*"S ,6w z(֏7#ۭ y㱩=9%ʬeiO9HA #˱l;^ kܑd^Xᘗ ½&JgZ Hss'ZA89kKs_l'R"S }k4d _NA (hLK]\ȥ}[+fvno ,~x)2~$} CqLm>Z,X\e:F`·7̡"tĆWXQ{1Xhw۱֥HYfFgL/4n8Q$ؐ9$85<-[{ |혰-nFɬ,[jm)4,iw2:`J 4[90v+pe\8q2e `Fږg}xvSòJm+J_m.ek֝ :ɏ)ZJRk^zqs; d3=! :GH:V)p6sWn{dfNrvgˍ{c2H=;b@ڱ^eGldmv2'Y@`ɗ\X;Yݤ7襠UE[)'WȨ)0 ui$FxIfR' od0ZYx̱t+"bJ2&j9-Z%Xl]dc战i8+A):lY. {֤m1$wh1)~gTa7{u!($GKHP>8rÊal>r9rm%"f82ٌB2o%KkYE:8&?t3CEb#k zR c6Cƀq|,QpUȗ̑Ʈs=4[fqDc$f݌0̪+maO\rdTI0*20*iNͷ^kci&,RE~'{r=;[/3y WS7BAf&EWhVJ4|'VhB<[&$q۝65,Ɲ~ VV3ىZ%VbTV;rRTbǟj_-i+vlV֝K)Zu}kf7tגGUkXDS!5_:gL2PetX&䯫Za(p="erX7wA+_^Υ_gp dR>hٱg}1ٯC&ݗS}ӎxamխk̨9(Ψu sXq0&[ c]i `ŚJ׉IcPNc} %nj]P#|xGFaXi YRY@-2QHMP߮ !gyVC0AQ :HeE$ٗ "̨TĩI̕)&HDIh\QGba(YG}CJ6>zy;l}|HSed¤(վRv-[zv֕~ 쯳׈T27/8zW,PD*W*AuXU~;%&@% řІs^@jҶǚִmŬ5)?Μs˚)Ҵ)1k -+JҚҴiӳzC׾~}A>^]oV ӺR )Nֿӥ+ZA*vitU ;B1ȖMjAs-K7jrI F6XiNf\պVǬ=:|O|@~~3.j)Ӷbu)֔ҽZSk)/,ʥ%UWՀ e#}7'*eq7crT'+f"`^xYdXnH :v+=IWf6P4܍E!eC9ъ1dg(0U oLJ\q!zۺ- maSڌbU{:ʙ;LIq1/_2Z_jTx2*ɉ[If0`59(M ̕ VtdXqf-"WTjY'$F- rM !(&BXz1umԶLZuiKu+vVҝqlV1e:94kC "˔FhITl@;}/izq}?n K'k6a $xͰTyTӈj;KZ0fm}~:N"ӭo[iMzO}{OSctsV^mz|:w3.jztYX:)ӧuz֝^˾}?y/Z[K3Ɋ0dgT=sh yBLMD`y"+pħ\*׮Qg.x=ysVb֞P+ZֽV^)@V]f[# ex(}WF̽X KƬ<(z/<@/Zy(b6+33tKs+g޺6kcxeRP] 5gOK|.euFRm)Z{zӿՎIb0p ZΗ`6ŋP9r F(if8JcZ[{䝥Ya cMJAcNf|k^ºe;kֿU}[oJRVJS)NqԥTE^(fƑ`WNDnw$~}u&S?ٓ-AW-Z =^6EXsQOcWrtyKn})^q^Jֺ^Ogm+OexR].km+ZҽSO:ӲݕcݿsT[u^_^׷|˚uiu+JW֔R)ֽ:u^{7 smxZZMlZS5v-wu+^Uwm~n9ĕOBZWz_Jikezu+iZWzvV[y1+o3.jײRiM@+Wǯ^̹׭zkmzt_ց_oZ{e_>OܟPAnR۽J)mե-~nҕ)RzW=+^;I֞*ԥkOSҴ+]QZRҟ=iN+2ӭ+Jz)ZS>)^ycVKmnҗtJV@iץ;;|^moѦa@tJS+uv4m}MQNqǞ$ziul0[֧NY~ F7N5nX:vׯwm=Μ+2קN-J:ҝ:wWiZ|?}w~N^F'|k4\N'2p:G R3FWb8 }ivAj*zc=O)uiM0Vt+$iuk^S)}^@̹̋Wf-`iﮠVk^q12^ߋX)ӧZ{k^@O_?N,+bĭ=BPNA`lqms*<4^I cݍRcʁ3>|Ȧ'g9BJ㥣"OWO6Kd'* [XڈDҩ%JpMv56g6 9QpH5.XK V=|y[iu-]ZRiJݨ:w|@n~3.j;zt@Owo_Ե '3YXCrBH`@y bTNj1ۭeozBz-VJ&\nBXLR,)[!deSYxb^Ň59Wf5kZ@ jgN /(4*”Y9v-0M5BPv[Z.u6#- ҟ'euL+2֔)Zz:t~m:WNֵmk׵y2.z2_Zg_ezRqj:>ٮ렎% 3:jf0Af;.lu?XtW}If%f,SaqMj] xN^$FGf1H͞Pr,w.*,+2SYkA:]h(A YU9KY25Yo}ۅSs-)ORe F=Nf\թ^kIXiZ֔Zj+^oo [~3.jնkemŬ> m}+OJ4^-?+u~I~DmA߅on; =*V'J&~n26C$NI2~<ݢ;68Ű,WnWeq(Mp(!G8gm@og3jtWuRgN\ջkֿ݋X;kOmZoZ׷qff hX4m%Cy$Pqn,7_ zg:wsa2e d8ajyNV)vȩ"5J] Frns!a؂A MÆ_WJ/Y1k(th =0"Dbt$MH>p(Dl qđllz#"4r?sQSI\۽jpb+E܂ٻZݾVxmҮji Ef,V;;:}8ä =sg܅c X]K,ȼhF" [^}> \_c.Fh"bͶJk?Y{9.8PT^lhw\3" XDF% I@d=3XjFm.w<ǯbOSE6U^uHHG>J4LazCu;Y qH"U}+@؛kqs FayܞOņ܅)rϊ7kO[NȂ5PO5f+~;ISKC 9@9~GpS`TuY/9Su P.BD-$vF;Dސ]&n=2W,4p0FւCi63Ԭ޶ }Ʊ儉; "P J>k WeL,nؚh k}]w[Zҵ=nI%ZS$2Oz<$WT`gx߸-ʙ_1,O{K4i.E\V@e?k]b)27 ޒ(&'AefN3/ȖW/'u^$Vyvq19n$i]i ^1ľ:2KݡJC\Zȋv+-X{zT6 4eێ1]p]kOοǂq&t~XDzC/2i1͟ҾiE^A?V+TdVJݱ,h9]l6ⰴC%5D/9'Yl"aR)ʴ`$IC9_"jM 2*C:DFim8p|dH)=NK.D8qBDA W׭YSά6Cp7{%U,g WV|mGdd:[ycᤁ-wg iQi/ҘpҔҝz}E{kx4c^}Q4y[8F8 $j9oT9pCÙx0w,-P,qd8%S$+$um1uEg/>F#sig Uh룳ӦsSz)[# UBQ2R/]D69C!4lRUUQ̴c_bR`N,eOr5rCS[_53EFfy #QSaqu:=={qW:[_4.Na*00qJ#6Ș"|[TiqDϸ}ƔS㔛>aN?Xݸ n^Cq`4cO_:< \yɓZBBrd\Bq8ߑM,cI/GZ̊D!!IYth Vpܑ4OgաERXMVYP\R4X^JƬW*_kpW*׭q}\:z0WxaEjs2\U쪭#v -eݥ}])֕w} ]dnh;ioeXˍ=ڣQ֫F7 oy jN%!X5f![f/1/]myr50s@cǺxΙlwLh2ioógh& `QP$#(3D ,AƮ2R*lԶ'E:ݹc_ykhZ'1NAԷ,N&y5܆63 V+C4nZL~Nsȹ\;c+٦lؖȶڑy6o9]eY-`ˊ-"I'Q ­uٖ+6%79eI"kCƟV&$>\X1x̖yco[d9{3hv8&u`بa;lgp %ƮFۨP\8h%a1\hqmn.FH v5q< cgbblpZ7 ^pdC%X/ٖ o5Y"5a,œ3"-ۍJ8k6bKuDdz;=V䣆QVOtAfppĖ1VJƖZpJħ+ab;UJ+bl-Xއ>za%u䭷]Kn)qM۱{-Jj~GL67 .iilI ZR.: qV. r[j]Kc8*ʳgq5n˲- zЍGc"=c!ez b6˓7Oz*2/5-k!+$z"eiruŬQ)s/{8t_"ȉ5.B\ҵf>W(ձa,n?B܊D,;ƒۍ52 66VoM.5X\TлZ.ع8f5.ԴW4f Ypy,9%Mv,M 2h':ك}F4zϕTJO.2tD< (Wߓ ,4m4Y-FĖgU (pVXۚd+Y? fT:-T cG S綁NbЍl{]:*>XE]l\oNCvgGZLG11g$+#Ʀr'IIsn$5|&$5.5${NȠqdCsSjtyU#Q[c7UHbP.ET!h;gjyFNj'ُI&K!3%TBy }{&y^T(ѳ*&6:~Y2G<n݄^m@GPTP9bW9Y3DNHp6FxYx|1f%9%xɟr)q]|7Tp?>ߌRuPA랊&Ó]162Eqb Zѓz35v4j~E!d ,sߵsqS,!i bg E[i ΞHgi;8cvA?jeoŎĽ”.+NV+VifjhԖ%gcwɁ*fi>hoe͝^\ȹ]ڮZ{+4ljV#d]U !fe)f#nD}Q԰.DI2UHpyي#d%ƀ,W]7J8vi]ꆬ&"r2*݋>kVDi1e,@2t)-‹4o]zG*pNE硫h:QTTXA p*ǙńE/aZ ˕%Ju}G+׻_B@CҨf^& `Py;<cյZ)*GPWxc1Bfr4Qc#0R E!LU+G" ]YYG/CMUwu3n#J !Bls-ǚ̖_E1٠0me*x۔++ψFLwƽRV' T3vg_A^$ hȒ 1%ϗH ;xQd9 B|[cHJvZ~VP+ar҈hqǍw \(F¥;hb(p,WǩL1sPzD2{Kul_cjf ,b$1Dx' PLJ5|xA<(ĝz\R*ŕ284:vqGFC5^, eH6 qmuW.ֺ)5Ȓ%\e+':ѝNdymB :DNYh@QRƘ$OqJ(.L8p3b8YgOur9rbDcʥMHc´s7ѫH)tŜH"2x#R%ezSk88QBӬH_jWI:9#g|i0IX#4M5~ Je-;Yq,E-xcI(p87hc&4'ʍzf0onBf Erc}ݔ _!W`21&,3OVgxQgٲC7/rxek"a4&X2-A4Y[f,$x}V&*S2utȒN\Y|D]]4aÂrӶi3j<:mʆR9s(8$m1o1[Hc6 ieU6\T)N:vq;N0QJ,GRgfvzffil@s*qyR OTmFԇVZ3Z_Wh8ȴ+rT"Y\2.ir(BZZZ2Z5:?8d+\¬UxIL!U:5M> 񻝽kSjUb *_" O/"ܪmdH"I#d%J]$U"i!evpg !<8mP'&r:*iv8/D] r&RIċægBXN0r$%n,i,qFTnOa>vrIջW3۳/-SI57xKKR/]Z$b['` pJM2DKM5櫰S{DRDwqYulۦK)(90u͋555܊,i\^6(H B#H$Q1.dYdEF$ev5]8UjllcZc ]jT)&Zu2m4T0ڔlsKl[ni_m:ӳ÷:]m~jҵq9W.dN0>CWhKc#`)F@xT7ˠ[eW$RMp_Qztnt9!텀ՔK\lv YX\;U̠yt*l+$3ndX1(EZ)#pW1˰&K=Ӻ?(r% $NJ2h3ྍѦ1qgOGHf^^*&XR\q}$VLMЕ$Oصjzxi=8ijrXS z QhЎ0m1[mnִn?qa1ST p4|ׅ$& I) UޏgP9攃Eʤ(]$jbYCbAK4dIfLZ2<@Ԕb1ދG >X,3eꊸl!(fUKE_x &Ffͼ3)P1'DZllF2Rfbu2Qӊ$eۼPp)槰nu))<;:u)|kO{)99y1S*k}sƬҫv'MxeaqYJ I #Gػ* Oɼ)b-f gF<[TCm37!2I X<nc+rJ 3M ER.vŻ͠+n7Vi+V^*iѨg5J-KJI%.4굉W#8TD k#RĦ@;.!UoEWmu0shIյaOjɟΡw#0ْ0jMM)Efhdh7mkxU+ogJsSu=~?Y-)sBK1ݳ HUW|.!f31Ľu3*hւ:V11'kfָLH,mIuG|zmq6w]\ï1R*"Wy7݃ vv >B>U#YUIRenZSae&RJXpxsqX#Jы8)exfkIKRtҶSN}8:ξX)9ˍ㳬~`33D3M*hgyn#٢`HlMkƕp ,ߞYfoP񢥚a2 U3mߞow u-u ʼE2ŖVR!AdM]fg^{bzZtjw2U)μ +.-Om{~^9֕~񭜌#؃j@`߅זo4A-U%h\ŐѲWIް*'Kz-^z$2s9*2['l;zxlLxPImES{ 72zT,/&+i&›)$`'plXkH:AxiP۱054U1jLK4"37!nf*[&ط%w]l___qַc|n[+qSw75̔Zu i$ahbsmH'" X^A{=y)}H`r7im#Κ~W9Sh{1WVx؃5m @ !E&M$ P8k%gMڶ5}(ph1 0l{lf cMDύ?Fs*kkDJPuh\2W(,p*ʕ>{$=Q lV d}LBaB\uSt)ƻSzzKK:.Vd:XMSP5BfTE7ba<& Ma䄫l٪Tԉʛ6 n\k*K/GFti~$ 1/ Ù6#`un{5Z*Tsznbtڝ06Rt3=I5Z[h3SDzfUYjjq`'S}qMx8q8տ>LX-sfe ,2[}+L}kKk}R+^ϩ+jCSە\g$9Ѝ~K"N@<ÉZ̈́!J ;:i3.V;-#s#?8Qگԍ\ %Gltiκ]Z'52Ƹ|<-:'K:0a GSQ#iGlx" 9sIhHD|qbiPH1d=ܣǻ_HmfĹfi.epMFLw""f$jJ!{Ri^Ҟߖ=vҴnu+ZRj)PI%)0AbASmvBt,9sse0-уF"Bc lϝ>:vKY"mΐ1["iϢ{ d?q(PS`t u8Rλd-0>KhѸYljjE5H~ΐ]~$mHf2hǍԯfdOxYԈR;lNzI%+Oa U~ 6?ҝku)zۭ=Uxcrvrvba"rHXbW2y8+bH8SMA_g!eaÎxXP*7+ѵ@R.r5\ӻ QuڶO;U(Ӈ/r:ӌ۠-[C5B{bM)ZViZVV>wV;.>^^Hy6cFofߧ_D|VnBvvG,ѹrL92fNEٞvfby?w'Iq ƥط2 % 158,-SY|%nߵUZ֩)gaj9c^H\e܆Q6 -2]rsE{2]-8+t.NٵvDQ)I"8BdX⹐g8$ie{=ٓ,e \,2KQ2-`\JjEDͬ]NX%r%t6xT)[Kzu5}GL4Jܻ3#{NV'#OlKREJJْ6PyVz*ب}5yz zRo 6[eYȔ6f;㥷)DDEt~)6JGLR\X7)ݓ3 da Mi'# 2BCvCL?Ru)cdדzzJ>oWV0vhcN;.$!ÁFq˓v|xWwwYuʑp)q"Ȥl8< kl_N_㿅m{{iƭp^O3oYͷPuyp`~1C Fg H5 \rυi #uJwۮ;thɶrD͸;An;QFhe!{uW#IL&ip d'UՐEK!&}Gr@ `~8F9M2+'P+2岹H9EE d6 _B܇"0^ӯ Զl2o. aWPr44Vf2oǺD^'AdF̀R,Li=R a3>aSț-5-\I:VJXEAފNXP#vTVnؒ~ÚSd ^%&5rG߱T_bicص-ц&_09$aYɍS\yB%Kcģ r`ˎϋl~iiZRRu+ZRBrؓ2qfJ&X[Ab8MS|w-dM{jB+ͅz ʛl R'l@5zcթذKdO>,kgg:Ǡwbg#U+:+hպlqN-ZIe6UF$*e{)/U]U\,82K49z3ЙstX[S.;|uUwt_ʇgZAֈSXyyD$}m2٦0r̊R,j7fT>/C9!)gȎy3YTfse,OҵLnf,EBaWpRMVfR%J27̍POfc26x鑒/h[龝xU䚼QJK^p*BEfθ888:8888i8888iֲYnG#ppsb\> ]dnh;ioJ#5i#ĆXc(o1+FΩC4QxύYLN:7qv٩rp煻4Ru&Gmd,6FM݅_ȘLσh4ӽ3h.1qك= "4EjॉL~+)l3j#eB ,vG$ѥY͖,pY[Vq#@FY\ Kq&IxѰ㎝:t:{^ B! ~D@ kjٜ9^(̬>A!` \бG'#*Ln>ћ%NE3L&*}3^#PÌ%X,ڃi`?|IE}gB X/X8D .:$h`2p7` UB^Ϛ4ZUg`K ew`cٻ0y(mfN͏|߳Vq%SxuŋO !f$.XT*$pq5 6RȪiԐ !k`iȖ`6j& ŏ. We7[}RmִiZWG`șkY/v|`U.X)T0ޢZ䯋Nt;٣F +nA~z+V`VHlMH)7b7 $XQ X](0#B}qH<mumǎku]Zuq1zd4'-ߟ7]b;j˓.O&*d˓&K+ҽ{sƄ(dBA 7exتރڳs2d)+!"C%$3-($#1׵ fĠecP L9>2:{P%] ֕em1bNh)[24(Rę"T1Y;mJ[OS:Ҿ蓼O;Px?/OӬnkʝ/%w^PMKȍ'Qh,nt¯{UE%Gu\.UW9U7fUUsW.J> N\j!J=0k|jtIcM~2?"Ŋ[LI_x;z׳毿{0/yasu/YٽQۻF8ynJ/„Iư1xxJ%Bg(n̄_3ZEv~\s|x5J]WleTXb]-,Tn:W2c&)DJ !nDZ[z|7ۖbZg<mڌ;i;qmm>ZnVG[vH6 m׺Im=m:TF Xj)Tjc0CxFelY#yj$k<Uo%M}4#VnH2+TJ cOfDhSݏmitz|;QDzo$]a[e֬2m4v[lX;hWv#%QR)n"H;[hROm^)kS[̙,«;s%WcK@UEpqX-bUn͂TgK2JaKr KiޗSWvҞoS6$hIrQI;znH\%sM"}0 VSDjS؇#Ifr9kJv׍{1 0;F>OInr91^DB_pX UG5Vk^_ S\ɧpָ)Ȓ0TQ~[+\k[k\geK\~7k!•61d74fectGN3LUfYsh) ;:k^_e}sxjUg &'C2;z˖H<-czaxU&T3 G)-N6l bˊj2~oJҽiN?n3B]u-J]ZW6BWR1F([W5i.\^.iӏS:֞]ƃqnl=zz4{ܵbN܍2sF+ZUiYHܒub3+m(L0^li}/\R&*_mV_m.:ӯY\9ѫ ϕڔ2NC4MW.GPn`WUB;0o^{" q0? yOBF[f-% :ؕfeWWPB#[`ʭH55mywU?y-P?~:$ E㳁HH^ )XV*زgUjVK<7)oOwt^~~wӌva mA签Kǐk~p!xq2_h% A%x B\V'L"Tc*|;1aemm?V{"eIrzUX¬%8b"k:kU^Knb3[1Yu] #bU+YWgչopbyb rk$l$Y=ʯXZYb|v%^2[On4i,1RĩKiL8ov\BrF#dj]ALX2տ6JhFT_U`S(w J֔:קgNӍLQ3 oӥ r텞Up],mF+Nra*٭ukbY4z *KuS'Mlpa_gXaG6 W-4Òɇ,O}nf:[uoZֵx8ȍr BH'rs}>uڳ"PEideFE AmF@F- A5c[su2M55(T='jU9͙:*`×1rYvEy Lz ˰-> $"I=f]F/jA[XTX]H c5*#YR4wZ%H1s\xsd^&K.VzߛS׭iӿO4Gxn |^L'۰e#)=*±֕1: ̈́}+b ]dnl_Z˙gMjŤu֭/Ms}B[Y -3э7[پ\ yOP=B"[H 5mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/images/viewerGUIarc.jpg0000644000175000017500000022010011354250325026533 0ustar debiandebianJFIFHHCreated with The GIMPCCB%"   ~   !1W "7AQUXf$&'(26v#%8aghqw35BVYx4EGHR)9CFerIbsSct J !1aAQR"2BTUq#rCc$Sbs ?r<pJv5N-09LS?rF `uJ2i\$%IU Ypn)&1:kK/vGn1aa {i+i`k$h6dq-.hunHnk r|8ְ]FV8f!2ӿ]5٣];=N}дcyuM N]#VJbJ xlS ;3F0!M,#1zRJfjBXK,lf0iz]{ !k|9}d^mlmþow+M 96~C׍[˲i+ݬ|1GN[hOC ;eaXGO0USY!kT8e(?cϷѱY/s'ӄc,ca7tҼ%HwlMc>o['T1 XBgc0Xi]TΜuqfB^i 55Iܙ^!ѵ(;?LY#rYha+ h&OKG+ֆ"sRAX@E8aN(΍zAIG`בr jq ̹bZӬ/X9yi`wt2Kxk&Amo_^_,t05fގO l!K g/ca#Ԍі:B1؎Uvc!\]->^Y)1+53 xmSn"49M+aÅBxݭE0`V p,)^ r-T.{(6PR2}8RZ"j8qc"šcq|MI`@n. # q ke$M`lzE8"gx,&HGXX^|!ib=j^N2C VҞOdz^kwT,1لcGvCj2]dV4G]!VX>κi%*M$Ӝ4@i{g-;gzM=I}|I~Fm캱'X@mяjGǻ~߱?@_=j_vOcCRX^я~:450:cɲX6@ !cwSфm!!xu+bi$ѫTh3RIRHx%ڌ'i!u;DHeQSͮ`MC;aF:1ýۺ~k޺L]:-"<~}l.ړCO fkXCXz>_NT_C];cvGM]#wդGR}hMaKau|cJxka4=~ )Vҩl.^4ے=M!cM%Cw׷bwA{:N{|!e0d4_ y&ΰB|56`8GAF_c4c `=YUuzT#,*T&Y5F!M0zkӺPt5#$d+hjф鴌q=例R㣫+)Rc:-ʄɎAŽ nވ'*%ij 3jHIEE,NQATӅRIKkJhSa_oJ.5rYRӯg.1)9.Dl S #:ў0$ %\`<=zys#U'JԴi"d1@DBFVhJph[\xMtJb+lҤ5bTbf۪ M0E4:c M V[ͩ9-ox8kj q{4z67\5`vnM=\7Y۬>Tock-h4.HQbR382DQSXUMI IN8BYei򤹹4ZaeXOGI >1!OU\cf.&Fm^:C!!w;,=o %q!;e6G Z`d9}\ hkc4 &C֮b)eGtvT-lvLڎtvc,;: aO*$Ѭph>e:X 1T쐄al,Hkc:^ڄьfh:1\u(޿j2+DCw3L_3"/wJ}{}?Us; Gjrk`P 4Xv_M =ySܤьe;l#F08ij1t|#- Z>X{]Iqa1ZhL:3Gٍcxbw~?Ex ;S؃Ւj]SdFMc8C.֛DYٌu<1qWWU$tɠ.TSHwh:wif0a!oV׏k{7qj:g?7?]gNς?u}{??ϧ62uCb#j]&ȐkX]jB: ;c`&?Wњ:QfDUMi,4I1Xt;]\惏1n֣R:ѹ01n1æqu^<bw~?E:~Σ66l\$CG]v-䄝YHFM{ĤFnN@`9AA@X2 7Tw \B뎄H J"#A%_$m#g\isp8Ќf[rc9RisP>#$\i;A)9,bבvZldFKͮL&lL lXt@fiF1XCqpͩ#iTjO0bWv|MZa^ņ-v.bQFK05Q?Xi6$SGCwJ.0 ڬ!τ5tToT\gqcq%msEle^Joxi׌b//Ub2"NGp'g%m` By"B[ j$Tq:fXdP 2 VdDii- T(E jONj "Z%Y j.A5:D24nWus<njX>_\jfvԚn|0Rq^#^'vjy[-[-G|$P@ոmP_^-#e9b&\x%ڧ$‰O7cZD%Ch& `r DBđqQ| ("@B¤(-:Td>6i#Κ0ڻHCm8[[qcϹP|1isQ{ŎC_2:N{U%3slTF7#'5|g\~mҁO4F:B0! ab2X~eq:Tzk?t_M*vY6c߬a.cMaDݝ-;Khk8}z;c-ZNT#es\LO|'Cx=#~YoVI~Sr2XSv=цڭCF:Q?FCkXwGIn#ϳûg_is:^G-zT ^6.djeYsS; u%U+k.c4eOˤci#ߦ>t-a k=)0X)%2c7MQVt;ss_`B_^>>ۭ1Z'21|u[1ˉwy/9eIjR :z6:憶T1,&5lRR;1xz:0av!! Q\]?iXh뮲=#/~:GmeNT!6w3}b ԺqsCC_|gC^:/Ӿ=-gnMeudEڂE2XH)e0ʪ"ޞCTENyX +kL`ą-@2fcS@   (`rUj'K1Ucc cw7=q_j4|?osFχH囟}<\Ju@.h5 7=ZVNZձVYTlX^^#5p"㕝J"(@ڤ ]H4(LcP)泳 m"bzKSJSg3 8P#SQ9a\®غJ26uK$e6U-КxB[dVaM }21B3iveKg%mk%J).t!,$?Jɵk X/EZD zkuuKA w+n㕌p*ngəXw"sëZPA APXO8*Ͱ2- ''E\j[큱臑Ȩ;{N8GnEAJ˯&f5fn"ӷHXY5@xP3]&i[DtC@ Ҥ4!NsL*C4Ĉ!GWdnQۢ1k-Sq>q4%9ʳ12gͫlf o N]b~L1(U虀)"wZ$e;1WTkoBUzW -4VD$@lŒQBGA.:ISvX"b]z18ꖂLW+DT921l:DAWՔ9st ]v1 &h\zbd+hpHT&)iHbF(f}b|-TPy iZ)0DtRp1()6NmvQQvtڵVhmܶ[uaHuk@KB0_!5QS-'AwĘ-DaZ8nN">bݦՒS7h*dFoH HT (޵RRiEnPϺE|+2+wO:<2@vEHR)f%gf54mnVFV=O.Gǜ)WĤ%D+ 5a9v#OjjudbƯ{Z"DS^$2K"ZK&q# *85 'l,AN%86!9MBt<) rE) JkR>LY$) QL;8)DN(4nZNdk6(8֖Μ¸FIN,r>vDDYNdž6:٘;:d7deL*Y,kqg{ ɇLH;S H9n!5V!8N1و|2 -"B5͓mQz\[|9e^5{j< n'N\]&p&L<'AK+ͧZ)\!t33CRn"T8/p@k.SH %Wfi(Chr Q)e)M++M\G= ]5\9 Ҽ nIS{n !;k%1Yh+)Kso&dg+dJvIhNSxY\M]6Z|$YTY@,;Q&ċ0n"06w–l.-,vדtkh'.QϼC,_~22J{%5CjH"MhNÔgʙD HtHbEy`2e2%^TI73b7t ܓin󺶺ݘS4u'en *.VԀ'G'Ѥ0 &) nw+]|nT$,wZFIlT}-GN].[w^\4/yS9BUND0V,GI2mhOQEbEXHTJ&djXE$% :{x[B%]o.2Nu"]0T*ȠzwdU$x8 TA7Q}jQlL0L0L0L0L0L0Li6b׋͞+6yMp&M}Uun2_Sf]{vߔ_ 8ړ.J; xNT`ySAq87e똈S'}RJu5Dd !hf^f M^2^DTX][XZgZ@`%(![ 431@DD)L!R45>5.+wspc#26W8Wm47Kw6ڝf}'5\<93(RpSDxaTmţ14sympR[e&IL2[fFqͽ":25fŗKVք8ak#oW"鳭3T8(7vʬ.뗁׺\ Iiq+LtF&m4ei9AyB[t[g'u F$\"$pN`bn">R<(W! TbGK&tQe$=\eXRL5Qj ~}C^ocm x̝`hIɺ8 IqjߩL%#D& Tx AGP'qlSa+'@_T-6PMi`Q*4֭Ս:TJmr˳1$K"Y4 tVT6+mJlId,mHhaCvVR̯K+/223-'ZVZ8#y@e T\dj&"Cm^-Sƥw2Vܐj F俖QJ$f.Z8 DPXQdEz1NOKf=3 'vߵ?<;on'ޙF;0^H:\B( x)~׼g|Kp> 7ΗFk3%xvߵ?t"on{wķOL`y#x|pl/$o..;[m^-S;0^H:\:gw K( x)~׼g|Kp> 7ΗFk3%xvߵ?t"on{wķOL`y#x|pl/$o..;[m^-S;0^H:\:gw K( x)~׼g|Kp> 7ΗFk3%xvߵ?t"on{wķOL`y#x|pl/$o..;[m^-S;0^H:\:gw K( x)~׼g|Kp> 7ΗFk3%xvߵ?t"on{wķOL`y#x|pl/$o..;[ۼ;rSNjhJfFN WAᡲpx^10 ~,E]8+֧JYogw K4O>0 (uIk^:VMbcQQYr:K_RR"=D^ e(Sx(\FWYVaJI#F4TNf.eh,c&E(;` NDS"ExJrzAԞhӒ]ƥIxat-Ol 0ĨL0L0L0L0L0TeQqS`\CN6$}i.rhŷɳ[MJʌJH7RLAhxDvXKݾ,2@58uŠe\=;$9b9R,׎)ByhbkI"T/5{Fn왵\ ;%qjKUI]ª5(6S?à]k!`@ݝݭ;gN`q o)8'kxo>P< ,. zPSZH2YFBmYXpt[)v*D@coYUUyNT *B*4WHawތ|mZ(u]R:ʲš$`)!qL= 6928cv ":LSϽŤӍxH2iglk-Z\3T;R倬B p>FS ͔aؚrU) fÂ(!ִR,Qpf+!蝤$j˯N ~̸$Tet]N`OpAѷų)7l[VT"[Yv-]3ڃp$uoF;r袥pSRۙ%X G!Km&_p.tkR^z5E=̯HOAnznp@uIi|3&ڗU4kdpyujk%AϺ<| 'GʏLp&`p(u2efϻt&wTTT[dzn,=n@\Fr^t![$@zd!:fTIߍ'mMm;/{_srR:Dn҇-zֹ:kIUE"X~+T\Ĥph@n5ն?1mqKk+nqn{J7Eo q< nhb%It-#N89tٲ~>gzEvOi K.^?yjrc-éqLI(6zB: :Ytٳڟli M̾WnœE|ΖHE8aaaaaaÜS߯|f8ÜS߯|pS趫ӭyllG9 SHM-#B0{<+µ02ǡecaKB0=#[b)&7.6Iah&Saa;Z駥vӻ_Xǿe_A{R4d9-Ueq#łEaPo ] 0`3Q/ C=4;5!!e<Ս Iuk$+밋*F!QgC"@BQPDiݺw Ҳ9y3hۛbPAL(N\F-1+1Y;I}zO6|fH,J{]!lj=$8\4js~l#:;I*R9@1e6@GĎC4;:zIЫR{.=DS4VWY-R\_Cl'1!pJ))/>ccEͲYd/[[]] m$, l^8h iu#YAH{s(uI mYBt."9w#osΩ"(.&VcRֿֆݔ/CLLM+Q-q eqYt۷XtM'vv>+a>+c+Z.\D;!PWˬ飐D56YmY@ԇL5MS΅,Cx?6iVf];}bpJm)\2kdθ- l^'.W,ZTYBP)FK!NNTJB.>sglG z/$bdDX$W2EUB|h xeL(P3t`^RaD \ `ƕʹT5J]tN' adr~&j lRoM2/]+/`Mk tD:ANR=aI@@HmK OH=v9f|V9f|V+ڥ8YDwm0-Azܱ3kޞ6$=\U*keDǪ lMїzjjnUft2G+mD@-A\6=T㔞=Ơ(s沌\rD:G2_BBZ"E)01&SKʐ1%4)IKa\MUa8٦E9,n)͵!*ɷJpCJBcK,yFKỏf.K4#TQٷgYFRdfHfJf;:ppHA/^ׄ]25=J،]ssl3\tf|ߝ8MZh> F&$rF$Һ!mK NM2uPdbYD-+j.!#WdbwKoԺqkn"]@$ʪBtr9f|VS:5L*`u͑/OT'S$)F*(^PD 60hʠQ-.D)"f"o5w嗶gY,a@m(+ s24*R^"*AljJ(NW @:}AʜnmpݻBU#GMN^Sޓ R2K'@S 1 +4/hLJ pЙ15P5YRJsJisON0Ie~ٟ}n&%8ƶOtVt;k5d7|"2oe8ktI"u>N9(fD,@ Q'vyooa }X_.\mRŶoD8IqJF)Zv]Y7*}J0Sv>+a>+cݗWCvD3y^x$mr#]h~c/?4.޴"eu*e=RRVreC"+Adf`kSУ7`B&B̋_[[P$zbZVmvrƙo-gmt*IPmZExqUttiKƩRHR,x9Hf .MHa6jFJ dQRN!UD\ ~*MxE#BQ }.ukr(^IIV6BIVd8 5XʘPg-./4 ŵ+H935F¿1\_&wƄadWwU]0.5D[.tO2`d-B#)"w L<)@ T[[\;_:&Q,oՆ-j1oaIpr]np9tB'}RE/`O1 Pv{w˞4CΉn$].٘{@'[4ɚ(eMd!Ls˄0$bb[[\b,ެWD'X TEMӀ%̦R\]}Ve.&mѩ42r:\Q>HȔ泓}xW~pGh>v#qW|u 8, Шv431JL In 32IqtE Rj&"Xv{oufI>ݯyqtdDQLQDOMRfLRrܒP[XB%7m`4B~\S߯|pc踠S,bӍ]IFVJxɱ3i4v8c[DT*XHK%:fЧ_fHC$Sk<{3GYc*z8E5t2/F3CIf]b>!{wb ,yS]I&snZO *RZ O aĥUP@TҀIr-˔ +vnҰP$V7喇 %(uK`o)zz:~Jgw KYO/n!nzUb4瘝4lB7<9 [XӕNFr X8lZr/n&4(a'*բhp!31T!@WN9\U#F)ua]9 I9J%[ˊtkdrL@DSO)#*_$*U T)Z2L`y#x|pl/$o.:hq]ZQr9?XkiBֲM>`&) ":YS -|fs%F>)ec!;pԂ~@0iuڣy2:HQo:G;FZ87:ztS)p֣{roJGowfxa:Mޯwo;0^H:\:gw KgE !UlC=p&3pދ.L~ R'DWG|H^ƽ697i AjB\\qI ݜtt 7Η 2W3s䶱sƛ^2I55iJ\9Ըm65w0ie2ָ ccZꁚŶ HV,0RLFڀQHr8P4S;pvj-.U/x(ES0STF۔UӭBXNPqx ֱ/+D@0uAug5t 7ΗFZzeIyƹwKzp?;xPqr˫ۚ{ڠar~-'C%- ˽G/9%֒Owc<5r]l_pδ#u 7ΗFYeʹ$'L*6e#OH'LJTƙI3r)& ilX!oY"r JȩMF!YHt)Bac 5+PpC:gw KL`y#x|pESKqrte/GMki(ESSj .jS'8qL766jnW V2n̉T8DJ%Q9J!ˑ " w}`>tt 7ΗU yellΝZQ5 92xpuj P-)* _!IZݚ?i o{J( KF+,@*^ȵRdpR?()y &,? QIOL`y#x|pl/$o.>x9, vu:AHftkV+RψF kw:͝ǹVMp%B6a|۹r c:@X)j#0 s3Rɾ:gw KL`y#x|pE"WL٠wEąM$zdt2Ʉ8I#iRơ)aC,\-Lا*gifUn4h .'IM*r'SEљ2N'L)1@藗9x &t 7ΗF\Ǎs֑',Bs35Q!\& MF:hPjMҪ]*8'˽_ P§)\Npx4F7/+zzgw KL`y#x|pEzi(Oj]&,9IB(9.nijި{UzCOgzzgw KL`y#x|pEYqwDNbrWd,Y QyS@"$(*'qaS=[&rvh?ݒP_T~cR3ڏ=3æw}`>t"X!oY"r JȩMF!YHt)Bac 5+PpCեm+`ﺫ,2 vSyTh%A1*'i0$t&%CDX 7ΗFE_pA쒄'ԯm| eJjSe^-D޵O$!4h80`A"GÇ8SkB[JJL`y#x|pl/$o.Yjin.Sxl%<m%q\*z-R%Ad)Qs@[hr`"y/w]{vIBsW}SN6}Jj>S 7ΗFctsnMb[{-o۔+EUyN0ɠI阁?O,^,;=Ϻæw}`>tO 9u2#s-ud\◞ pR R&J+WoDxA#+'jRTGCJfiH>[2Wz3PzHǢ^2¶wKFcmt ~E pei}T;Zߦ*z8EզXYz=ʳ)8KvuTF?|8Z^V߸iu e#ʰN݆kC)j=IBZL͹VьDUB1vcNUTBHFY%|fcXCHCAWk֓c ywWZ}Q͂mO5-+X>iHNWK(HD/iXŷvӎ~h=f%V?҈j)0 t:ZڲaBƧc#sg? C*Y,d%GI$isk/w Fv /0j-S+8/0j-S+QKYbi5rs.C^a!1A.c4LؗoODHf =.*PWpkmUE7a_e)?q.PbHsj(r$m}&-t#YM| ST=+0/28tk0c0WrğAA\TvJ 1)x'3VK4?)`s ]h0W9kZ2Gtq"B,e @h]E}}E}}/E2~g*|xFj RZi*pUAU5NJ@UPBTB5о3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֭ 3ڋT9 3ڋT9_3|\3??֮Jf/PoO,^SLs)4TCH(c\Ҕ1j%_{Th*ys*霈0 DĠ@ $kV(Ij =RֲmS-7'hV"C.]7 M{ƧWV2n4H0]aaϼkN,ïV@!ҿsg(ZGʇ$6T57O;i[GL"磧?TQ4.yqY1zX뤧8FFw1$,n̠R%ꃶpih3R.%ZE^"[ )Rt&愪Ъ.Z!PqqkYPw6 WSM6ʚ4 Ӣi xh3PQQ,  uMT/!۪Ju&tzqt(rQ r, VxPm)-Ւ*󾼠: Gc;7ss'eǁ8{9TbܡO3uHpd~ZHsֆfXi. )@';99oOˏ b K > =O؏f?xo̟#|G;g2\xaȗ}{xMi}SW@Yp7ss'eǁ!<|^_Ǹg؏f?xo̟#|G;g2\xaȗ}{xMi}SW@Yp7ss'eǁ!<|^_Ǹg؏f?xo̟#|G;g2\xaȗ}{xMi}SW@Yp7ss'eǁ!<|^_Ǹg؏f?xo̟#|G;g2\xaȗ}{xMi}SW@Yp7ss'eǁ!<|^_Ǹg؏f?xo̟#|G;g2\xaȗ}{xMi}SW@Yp7ss'eǁ!<|^_Ǹg؏f?xo̟#|G;g2\xaȗ}{xMi}SW@Yp7ss'eǁ!<|^_Ǹg؏f?xl$7p\oŽ Q@48 L!FEVD ZJjWؓABȌGݴ^H^UJ U(-"8KVTPp ?P 9JiQVNDcDO _4&Аks'UO9&7%zժ+JhH4M'&Z~JD%70EKL89)*= љq)TAU[b2U5=-n`G0 ZCK`WOYW-l0Huk| 緩G*TNt$ ƈg#DE%ZsRF ()xJx!^ n IPWפE9;3qħcqX@XY}pV@A%dœҵ8@DMAAoC:[EZ@R3в0!^,מY1(m l4+~bt!Ae!uQ`n`;iAxĥȨ;q4hRv-MFd$3׎$#V. ûM6Qp 6",y#lN6$U1]!GZƹølF٦Z0l9hU`К"#馄.(K8V i*R'cJڱQ*@ <51RXV! D Ԁ2Qb̃?q(XbL_s/gWJ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel ( Iel #iZ۲ {z#"Ktڨ"⾘\0P&鈥րi%YiUL4{ ((L}(ү$ԖZԥӥ<؄1C^\P"ī Dt%B1ћ5 4J  H }C$x,ȋN\JhDBL9U4&r>Y%!( iU$=8 *0M C /f>?u `5Auz%>Aԧ^Y @Z3Ԕ @4($ZWT 1d㻋e+P/@XUYKFhͦc xTwmkšݞwaLHeRDy(3~iU-W N̓dkU٧VjlMR<Ę9k?ӡD姿Wrg Fx`L姿Wrg Fx`L姿Wrg Fx`L姿W! dZ5dU'HBT-% ~bETRh0./CJ`εRA/s[]O¯0姿WO¯0姿WO¯0姿WO¯1,SMXhuZDpe0jZK-0 020Zz@ K 461AU17ל_Iw(%xQKfDRCƜzikR)OKrg .#tF#<I*Z{l~a I*Z{l~a I*Z{l~a H#`J44sЂGYtg,hb PW&JthQ=Z$MDRVOR7!<.pHk@8L RZaD)B0ԆDM0 %XS0jQ9~}C^o`z?CwP'``E(8÷ hM`+O *H!,7|R4zKRo:lPHf5)`^Zbau¬ t!(xޜuM4gݺoUYJwѷuNX鵇1Vy`V*ܤ%%=Xs^b1fq(a%b;Ng1QrC3U]wJYYջ0MEMkrCfT8hCIhW1R 'U2q cQݳA\($-L"[qZl85NvU(CHT21J,j0F="U"0(p$pnƭ)-cW&fߠRq\n'.,I΅Y7E(";b4ta2O&t`)tf[2cn ;r֊[D9j !h> q353,FZf|-Ӎ\#,Ҩm)Dp>sF> MT3A T1F%EK80DM5H-ǜ?]{r O^O*:R vlCy=\Aňw/?Tgk "I3ud1vX\fѸxQ ˶ߢ]&E%j|& aai]_0 2.-2.r/JDbĿv}BRۧ&7Yՙv)+t@1"V4#^z+?nhmf!r-7H+ʲbZ*[fA4[[WuvaA')ܔhUCV$$ᒜ %ᨉ)cU@Xr\kXRLߤϔfTxC}@xhP(93(տ1%&bpSm$Z"\!.^@Ż߄}:{$Sf5FZKxi =mL2E"bgbXʥRI)̩РQ\rf(Q~b(JLxVZIt}5Xd!BuqeYx1,[2β u\zj PCQd?^(D4NyVm۴K)TemSr7>FV XL \T .80fCѧN]PCP8 fO'@5 >|0L0\ z/:ai5D44XYhiZ`),ɬ3B~}4|1c\uETQ!z)KBnnBХ[JpENMϬi4v1HŘݾқxՎX;<`# Y|&M;Qϯ:UvW*O4V1 pSYifKO4!1tg҉bQ1sxqԞ)yqGQob}sx"?ܣ?mOu'G*|?ܣRxo:#o>sx"?ܣ?mOu'G*|Vu'G*|sxqԞ)yqGQob}sxqԞ)yqGQoca+^ k *0wmD% J;%)6,u'O41L()S I$e*2yMk)Ye8 CF20 @OIJtEB-LVUfS#*Zx6c\Gb OKD L8\(2VIЭ$&6̶iGU \(J&kZÈ DT P@Z\(jњIУǥӻL1=43jR}a`HzY{6!bYG%Vb.ֱ*!i#nʙ }}uu]=lZ6+,K~kTe1WƝm},?(a% 0rι?Qc9Gg\ݨ1 0D 0D 0EPyߓj7-a,zeеԜ~0zF\@Ⱦ!{oxF!_PN*] ʎChڪ k-v:9@y2n\ם\'-p'E%9Zqp;{qS^snΉM9s)xtl ]%w2q2~F@pB  OGrĝ7h-J׭47mtfJs8SG5G&xTP:sn0gc%#9iD)H 洙yƏ+zjKm u ,zNKcdIM$HCzQcnItR)LrPKLF+- `aE.Pȁ;D> 2uRQ541~)n˯5[[on!W4ẃS$eqJl]<9U#\9 X 5,W@-lD^g<s 7+-J\r5TήI9X=QՒ5O6m,fgXQ#S΍mZSJ6MڪqdVV҄#JSSTI0P6IBʧϦ }ԽK׽qlbް_/D$=h^2J~)dqso}3wv9nlڎ EBa% %3;r`M Y&:Y][e{t}c%j&"Z ۈn%kNk8Vw* Ug<~V[a&a&a,d! fOd! fO)_ 0 0 0~ZrC *-$bi:9 2w6cv{aуW[594($ff"^ua aB&b[s"k,ʔe-IvveQԵt0]BhM.c4t4ŝr̥ Kj {>SSF}[&0gf2iC]uŝbQ0 0 1WF$. Ftb9ހ G'Ssb"Jº]Tԣגj+g8t K<6+qq9\ V] F`j=LQH\Xg 5VcwJ>K1}% OV9z_FIwLmmbznqu*U:v - $A%Ò*D r @Lȟe "!&_W5DŽ)N.J.ZFZ S 䐦%Z\D\A#Ic*a=ZxYf]Z~*㊪M'dSUtLdSR ƥ*ylXf SRE-F?Ae33z.ǹ|%?)X|VcwJr[3RE+sLF98r4b \f/ڕ4s=WTmq4*22^Zi 4QPًD͸A7Mrpp %ω"‰fw"RT4;Aԣ',1RCm!cu,yuh 4qvZ % 5n-r?<c>)I&<`Ld"Y[+1c4Kc%åO{nBSKEAtHZ%UƐ_$Tp,!;V.&Pt,w9XV9$CIM x\kD \Ց==WuR,jy0'j):EȐqn.I.;_H%a4QC; q !nnzio2漁Ab{,`_OtD=1< ]ׅcv0⒙uvb̂v2qj\J>:"5&iU*:W~=ۧ좙QT΂dDZ[k=K.-, 꿟کbT.ۿ'KS ifr=-n&_6ٶרԽoS|:΋{xhBq۾E(LvnzMXBD`ҼtO¯0姿W,9?ť"N:^3\nwʧ޼kUF!:8E̦ozkD~orA-bY *sWs&Ү0PVo N vɵK h5 S2pr싨nZ{l~aidJoNjE֒&̫)CRYiIXRXa` >ex$&Zgׁ56=h@-EE$ ?e 1.0GTZ@1t3$k`ۃ.-s&ޱD ԩr@fdiEOnM\Qh Y!4zviգT<*%ީ,7,}#䋵s^H,:U6<rx%rfbH3ZSˆS'K5+K?&ԙy9쑸k]z׶n!e2=U7Tb!s x_:)[u1ZZ{l~a, uB.jN6a UCL&mzB@$ $JR^^1qkpH[d^SPcb@n }zS@PS+jLº!LBƬsjCp-e"4SMR*ReP-N(Ir#J %*fԨJdL0P!aF5 >0DOcbz?CwP'```E*"oe FYӌg# %{~~1mR ;h @8b.2ӒVϤMMԲN)24@eH;{M&sPbxusE]IV09Ɠ`NW".^L֋EI1lE΂rbJD"\R:OSTK tqZrDAj@!tP=8n6 `!' ͑QǨu'?61|mcG\qӶseccs\W Ck_TU' qMi[O 3W]u4qEO35\OubV4X,pNibdrTdc7Y=J X)(Mt(uiU$M2j琂}PhHI!RM71 Kd-y24`jDiœ8|mc:rŽ(R6"3LhcJaG3 LİU6@E$BG.%I9xf UCVʉPG3WyGj瑳Y"ěsʆ :?Q;.5M^S5G=7{⣇kj Ue"Y4ATsHSy&8<2a>޺  @%Z@a^rrTsI4!B)^JAc Ea5$Vy?i Sd< N0NOS4)N0 AGW.-zt+T4E "a"a"}zR"XPuK ctp;0^H:\:gw K a3æw}`>tp;0^H:\:gw Kn5{D!%'W+BܨZ]@\~L^_1f,WUYF^(eQּՄj\U)W5o!P*~*TV߭#(t`t,qّiIIAqH:fF+2; ߡn'c/CKb!O[.#4o֩\Hw}`>tt 7Η tXUtE1铷MAwAmu2-/ V_xF)3a]pb`x'cZ*Ǭ$ʥ ?g7J]: 7ΗFℓsiIkRx>y<)uiR9`+A6Tk:tVƎ~L3Bf%js/{3MTvem 3IruVJTv9.)Z,,xY9J".F;0^H:\j/jwI&4V[+k"q*ܶ3L'NG)HR\B,Z*m<^m:zj-_eڛ3r'vhv((R uRtt 7Ηmh+Dn ;öpr[M3t"d gW Ʋ;qNJM&N>۵y_}9S4KrL n֊JFv*@Nq`rF!ܶQ@8o*eZ$u+l/$o.3cF;0^H:\f8`l/$o.3cF;0^H:\f8`l/$o.3cF<;tό+2C?nJ)mRsZ׎XeVs9F x=0fYKQ ϳ u; QyǠZK1Iԩ,aJE610xKM$BL1mA[4C܋o-Gf ];qYyR';zx[qP,`W0!( U (kK#!p% WFOmYRBOwȧb鐧tdPLӅt:J%Iw(qg řZ.*MNdGkF&6Eѷ[;.W.ٶRkwI|¬%[lUΘX| y﨓-5W~Y[3kl4&U{ndOqŮidz,tU2$2 l--\In,η'Ke_[/ܵۦ(GyrF*;.i^?[S* =N&J DO=y'YpmZS5YckJ=ID,|lVYb&DG=H4X@"|}0AN!ne, Ѭ"2Fa %:}1* ㅩjD^jR sWYJzJeAmn,{ۗ _RN5D7FiDc1Wս5DBO`eVآTFR=T,9Ez6]:(f|qHUKiL)YSSh )0ÃTͬJ~:F5³N`@>ڨZ=(ѨWsNsl:҉OٱjȄ&,&ʲivyZi{Jpk$_0h?.F:sf`````9;=Ϻc9;=Ϻ ~zwlVj[I?ҩ~̴$ٌGitf ~FJ;MJ j<6g~51m# 6c 1Hśle&=tcKe 暌TȞf-9Y!-M ! fi!,cӌ|c [*d[%AM egȎ#4Є!l0a5BCnqP}= 1dL0L0LO, ^DkAo*Q%Ԥ&:AUїbYNPM4f-A3{4}""X8ܭ@$EDaJ2,qu$l Hg Ÿێ#YLP%j<=K^^ H S#jk HʅĄжvw y8EeB"5]kd˵ mLJ S[= ut!"ABQ v[} +F,+wÆ~ FiWÙ*( `!g뵆l nJe¡dq%D5O%PdqU%);Hq p~_ʨQ/5a)IFR.4V7NoH{kAyU=xVIqf)Ze$-DWV2DS֘8\9O/o PbEWYrFA֬BH0Vyr-jYdLEWo$I⪸F d K'٢}엨fR'q?h}DjO lչ=* \,;g) jőÌ[˓*BQ(`xfgTY)gfcGW"0[5J+{Wnz՚눶6ڔe(k-7D"]Ѹ&w/]X@HvJ[7czkus:#]pM̧_&K|^-K >ZUI.%s=\h&kzxbeeN# phB PQ5LD,3ڙLi9$IRdIU2T8MVFO XLHLX)qQQpP  z!ӧ)!oFVmnnH99txW5)YM^0Y:jD-厒vǨ|Ýh=nh&Zut[^ǺA[,)!GAsgPEqX/'C+RLn%یo) fȒE ' "N^9ڻI'Lq U^yWT Vz3BDV;eItjL'[K9"Ac_ A"v AcnZ ֘ǽt.g88W|$e] nγl7Ȼ_B&"Z$ƺpʄZzR4!S$~gٮaY\Zr]u0޵ٓ pDz_iUp nZع=[rS8ɹsPFΜ'j7W sDlB8(D+aIoql {x~[n-/;N)R9_rsHLQvn8 4x5LzH3LhTjP>, EPJ_^+d te n@*Ԇ/ޕĶ-F7I2ly: ^rJke2->(8m%규/RQݞ._[oMZ zB%79@9Es>$6J-LHeHG4#geLɚc0LJAe 4KѸ?8~Ӛ|(E~\o)u&&M鸷P,`iYN\`|&N.fU6q |>;uyTH@FƱ&D 2sZY:i%Y,][JDrl9$4HI,MJ-U|+'Ĭq@ڤe=1Qh4%=8R!W4ar~-'C%PܬdIpTOwc<$!9{./8KtqgZMSh `D^ۤ[&r~ohv[%&xbIUP\*bTFHձRi6ˎo ;K%2ؤjɘ%6֯ݸvZn"$<pV4')Z)U)%R,YA!ahCJB_q*E@2e!3Ԭ4U<GS:*c4Z8@EXr=&bn$A ]@"Jl8-qȧ, [NN;kr ]]l?*xq :+,5\_tmb˨79W[X82nM/ kt!$ppD+)$"TuđzU |߫FN3xH*_)٥d7q`,S+z1;PNVgTd "ևiDwV$UJF8z+g^6Qq9>g^6Q"wфK^Mud_5Ic,!)r>HN> ڄ|4# 1z1-ֶь`pKJ2 5t{1V-H8 ǥtd6M,B0˞qcHǾ<icjx%cd(Fi㳑%B:$#eoDtec^x_v>ݨa,`````&Njιw~Z4Pnտmz}6jTJ)-S%t ~j<)IPs5066Tfh4h BawE)P<N A*YF @-(hSګRIf[rۅt+GY h.MȏGQJzj+(E0 BFJhRxOZo&ljȮ%P2DѢLq4*$l|8eIi dHQ(ʏH#m_H۵1-sz_)^3&;&3 ͞I;oTgq=)Ԟچ8"L"NC an/&T#KDɔz䢘j#"E feŷ0 ˬ,-y؄M8R4k~%S#Vħ,rw[E;6 UN] B5ҳ)c;&i=,b$hrMmZCW!.@DV\8 ۤ-ov]8(ʏH#m_H۵1-sz_)^3&;&3 ͞I;oTgq=)Ԟچ8컝㲗F0¤ac;"r-ɪ=OH@&JwA)  ]ʔ-*/S " a-rgۆnIukQ)F"LSgf{-pd`j7&XELL0L0L0L0L0LaO׍}lv3aO׍}lvkb4Zyam,XP %|czYa !x5|uogjKONCS{暂Ny|&G @>Ҝqκki4D";!᧥Ǣ uŪly&\ɳ4I6c匱0]tIcGMcװL0```8DP-wޝP' 5 jFm:NyEƤUen sZY*VSJ'+)K; azscaթIIi@oձ=#u'a }n-˚pb^!"3xHN`JQOMBjZ أL&%rjILJN)xW) Á280(ah0BI) -L<*͕hVҶee.1Kp:4TE:u RjV,CHMs˄d{$5qVA+Q0HJ%i Ӵ9t)nhiӍӖrTp< \EոDjG/]܇Xw3j"c`] #v%/i!ɄY\L `EobK3ci)$"3G( a!R*L>N)gb bTj\(HC"zLE"a"a"a"cr}N~mcr}N~mcEWqj˦ܖ40]c6iF:CHwi*S:Fދ ! Q&B4}4ccHi 1gN^mhVh8Yش4: xҬ5{#߮TmM,l"le;{rlQ0 J&a&a&a&1*o:l3zL)5iTPYLz4 BhzC5#ia-&mG=Ջp^렓Am/9(nyAyWPeSˆ~|&o5a޶ev{m%J&8ގImЋ*Tn\'] E4X~"f29@@8Vxe+ՎHe"H\7ı$XTNIU92_Kn#m}Kq( {5YK&׃7Mź ;S]&]p_;:.&DRm[FI}'  vݜWSn'(ū=-s2-"Je4v9)#2: 6N'-AL :p\ǣ2u{ȴnIՅgb ֥pP d$b >#Snj"tZ5lU%ӇGXe2GВK_Lӫ4Ա3b͊H_wqma"_P3=¬Җ FFn]8˷( 0E ){l Uʵ6Atw.ˋ{JU!fi9wYۋ{[]NEl0^~ĘVskw=LJj\J9{ijMM5#~#<1D+$-ȦM Tx:Me+-9:_ rsv)7)XVXqg+Ħϴc-] ڱ\| Ť (P0bF,LFrR' n 8(5{\3!̫1"lSr=HdۤT\ uZE>lK䊍&N rSR sTpZ!dK2KbȸwilOͲ?*utvNMjݣ{"tl%ق>gmIvL˾i8IJPvR#" uVH0N"QE Fyl0D 0D 0D 0D 0DxFc1xF`F^köi E.SHByJѰha4# =u{cKC%KcH>،}4F2lwii*z<ҋ;5+<#+",0)F0j1j46k5bj2SM WnHM a,þHM.FhwGӉaL0L0L0Lg(41TΑy"dAStNA7mP{tkPnj2MmU-kSkcԠM8I2m(Z8I鰒BT7<ScUU V d&@z\QkHHKTKDZHy%&$z7i}scRRf$")5Bpb>Eۍ=cruu]>syz>V ˌ:p2[ keMnu I`u?:7jl˳--?nj{zoɾE˪-ty5!.frnOmJ-'|-xG C=nY!+S4E-ꖱFHk[q`gDl8^,=mڐC˨o$.H73P.k@@MBQ"B)1p̄ݸuv]Ye[;^"{Rg8y[qԺع;~/G}S۟k{e9Zqp;{qS^snΉM9s)xtl ]%w2q2~F@pB  ۋ+Xn:țD괐հ\QRǘ9Gͣ-nDV؈sǙγpr"tD-fA VTy3E+fUv"[S ;#Blr9(ӄ a]q=P4uc7e9ZfIgwg.=9n(~>ue8?wGTp;TB-ֿjqo ۔T2<-P)Rd XWH 5%ue\bX 5xy6pnk! DN{_ND5t 8nP\4^:E ;MPAk'YLu3Ԡho^VJ>\R(_E&8DңHu30:,ff#Lܑ Q8@Ȏe W䛬)Vk3:ٕ\&`4ˊ.So}bWn`iWzBu"؛h@Q1#OUb(sY.Lv\½v03^= {XPĽhɪ2ACK01"OU H6-G,8+?$[_|p&qn>dq$'܉O8#?68tM46̬n4HvpΪ(u-87pxZ\Yk|@X|)Z(}f1tB6Li.,L|Mfm6[ #XΛwDA`Z([ E6 v]Q>M{j<-q׫-6rZz)9i;Y;6Q*_$u-IIMh/0(J%#ic|?]l{@"cͦw ݶÐO`rw*+^EF=$eD,dD֝+mۺB[y#pܽH*@7Nҩ|{.R87͵jBb1kTfD}zQ|ٚ.^7u7鎌􏤸 OW$D:,\sppt$)E>O8- 4ڴm2"Khn@6rC57W8) `^Tbv!Mו0*Lzt݅bvY &_VI$tvcvk6+Z7D䈲VL2tDRr T37p!T($QNؖt=&a&a&a&a&0'>6;0'>6;\(/aB^L'VK @bnVǃ劙ΓSj]$/ Sk,v؉Izna݋f~'≆bQ0 0tXJb5I\{%GEDP̙I :EҮ۳$&ZVqD:e%wo~lBLmWkge-%Ɓc\YilTN\a|ߒeN' +Po7_58.1lt\+6)Ap*mۦ T> j:@͔G(h7(A")9Yۣ|"{Y\0ZBn=ĂAyY7)U[@LA,B.*d$]acܜIefLٮEymz݄=[npsUۗJ 3A$\7IIh-f 'N"a"a"cr}N~mcr}N~mcE¯I/ -9$X S%X44M1=:8c_ ¶+va/A =^v!IGM7`oVȺu5LˑU1㭏b:ӗ)3t6Y%ssW)v;_]?3"ܷʂf[5w>nUgxs#7!9RC/҄"J2r)ޡM$jT?C]\j_qEn3r:$v9B:7AqRa,pE i[q!"S5ȳ8^nӊ*}?3jh3K%)Ɋf@(*O\XLNY6PriN1\Z8+y{\ jIV(t$,] ~jH +HGIt( qm*A=uB_^V}Vr,M:^3X/pþ;lgj$F> HEl]1! ~?2[[ ,쿚3SM5)qs F1W}Y=.7H!șB$H+TqG[U625P5cՑ.F8gsFnY-GC1 D!t6᛽Օd䳪CH]Clj㬭P֕Ъ^{2\vEڽ'  Jʆ#OJ$ ײ`F,:;^BUFhԱs00<7$kQ"86RPYѭa;.6@3dvgwKDd. R\t&nIjG&|B,꺩+:(6^(hAT.mvG2{9!da΃j1Gqn%2\u&[-NnWd * ~Fݫ/D .X(viUPrJR MXePX$H**}*BN>jf<F2Cҡe2v76HOA"5ki \R˺h&j4X72-rHC#NXv&W:6H䙯{J1_+ECx8G %%!*>j pXf4-r*wu5PՉ3+knemN]z嚗EDD W>kli;*龤lHf _M4P&nTu1,oIUC'F1! "&'2 y*>;C#.8{Zw@Anѫ_8V@%jsґ\JdDfgU8A64-M6/Fm)kʆ;X*ӊ;pD#iBR`۠M.2R)EO 0 0sv{ousv{ou.=Y T?AX0uf^hFi=3B]CIp$%[4jWVY䒤FMޏ$,Є)BBYue#ݮ8ea6ӕVk0IK p/ZT@@R-XԊQ6Lh;Ms @SE(ሹvlLbv`Xr Z G HȨ<L&+-93 tZf7;JɫISB*}ǹ~tC)(uIOk&L7Y ʵEĄ[G!0 "!P+WH"V*Eׇwq.[ T @HxU ft ps\dZpRLX;+{ڻF9J4@%L4̰3pSG!f6dO"1.[pIfDMxpU-ѧqSGò"s:R5/^'Ey? a>C(:co1žpa/hfv#bH>aJjtoK!Ɂj]׬l3^.`N ;ҥJit2KT1>r!UyG91C-j *|>)M>/XmxFu5 nSXf㎩&Nk" &*8A q=w68LtŰnKW-e A:B`H8c޽h5)2(s̆xi98.0*V@Fъ ^~" A[[,ٰ́~C5iJ! QpI8z⡂ft ''H(ƾ>X8qr+4j,cGhaj6V&&1 8Vn5J|^B(F5$N,!uKU0д)RÑUʄ>z GZY ߦ9D /ҧT%%Uy /bx`r^2e͗f%ݔo3A2"[k|IEQ>egy4*vlfN0/j3۹TTJRx+#'$Ί<ׄ\Ɲckp&Mu(#pTwvM Ԉ`Mr$5[p"MSEaai«0Eܬ)4܍CxYeV8ㅋ(&v j-D BC2s# P*[tsX^*ߘw6jzX׊#cħob<08Rc u>uX x2]ȍ*WCNV͢FjUY>)*r=E"F[THPQ+dg4{]Z&Tږ!SbR$6{PrEcϗU>jyL<ŅjbZ>T0U jać!4.zAGo7,d{M${%{2B[權hRk4pwjT홑;3R%b5e9/*0c $f$R>71iȀE_0AA\r;.nE$n+vFswakUz2J`j3T)y-P7O&qo~5zKN_[ҽtE: shRoՎr7Jն׎^7-fXGp Xi]w\gM/̈Pn_cR7:y7{?~[Mtߖ]"g^6Qq9>g^6Q"шS%ڴKJY[X؄i%MWHB103F1ل!z0sIwR3hUX$FXwǺ1gK4{nάPC?ӕM4l ږ\KlB6Xkf=gbqUONil0%FX-zd!iΑũF; 0Ģa4-bGƋrgn!nGnN:#Zԅ2G|;9fw0M2N( FT}0ƻd#3EIގA;#p=&T0re_&R-IqI\S|*BwQL ,"=1->,W5Sd$'*D2*HʆN-( LV&U! "pƻ%2z9B̑lO:.HbbHI(ȤjW(eP%$Zڕ gT:(YAtܕʏ/Aʆ`mC(lr{SI4wc * ]}n`Ǩ38.:(#564M˗^a>)["a"a"a"a"a"a"cr}N~mcr}N~mcEÏYZvu=tIMwGlY{|#>JXBmJhM{v P$P! =.=뮸b;N6Q[f!M1# #CYڎ*$ٱoMٓ'>?L0vZ8ѬҧI.䞧:t[!oVǶe Y ̺tC|Ufa1a.Z%Ҫ8;; vW[VMgq1ᝨ7mT0J̭gla= 8MQDNovqi $Mq$U^eYhFLHQ6r*l PzL;n/TӉ&dZM;JeH@soypQ@ N`_5{rcSy9R(B<HIHF;*C̬Z*&FN\g!ԾfU3@6uds~12Ɂ)Mj}:n U`\0B!i&ƹ9[„~F$ie3a w@ ⎁k^Z=wwRM#dݞk2aZsrޒ շÜ~iWQB o\wT=$;uL :R~ZBoҶ'%A$M$!I, |vD463X@apl.0 \tu3,d>t%[ar4>kf™@*K.jT|/&?Cw7}nUۅN$T{Hf<0CwrAnnkv$%N>̀h$`?zdDQ#օ5*Cw7F1(x]uFM[>&愉HRޒ}ZM>uoMݿ۟ދ+$Z{'BөRKcВIzre/=IVYdjM<dGY1TEJ2YJ"a+dMcKPItcB=Ƒŭ}Șa%IPI`iJ{aY+թuP֨ykN4å$lI_i_N(n|V|w=(n|V|w=gBmUCv7|жݖ'Zd' Ǿ5"C%ʇoI*+nLu֨%5KZ-hyޝ¬F=4ZRMyկ]IBԍ7D͒,k 2Ϩwv :`12.xY|8Y|sΙdylIY~+;ZBMܱ!\-VB>jNL!+>;7>+>;.%6Y!綣m-ߚe =!u Jkm2V(V*RG<+0:,;Q }RV㴍qAbDN]RuxCF֌#PC[\bRJn'`h͢f&C">(n|V|w=(n|V|w=^ems,:/bnځ[BڋbvmtߥI yv52%/iVHTFz^X@I(n1X l[0` U@ %HeuΞ$ \kנϣxb Q@%A)#TxdqE2 hbEW)F-/jKwaK MDH KiJ`hwT5 !X 2lКAgs߽4_=Wc~\8nJ߼>on m|9P".(n|V|w=(n|V|w=ye3@ԍuf[\.{pINt=+"؊lʉ!{I\={WۄSMDΠo;}n91׶õyM8|%`bG66sh竝 5k䂗Й-RƩ)v#"?~Ê~6&GB}s_{B@1NشWIz: a +DKn!tc #& s[y˝@tgtXfĞ[r2-7/z;blKf;NW[GXH$iQpiH(gs߽gs߽̪?կV8O -f$ȝjJz-I.n v>%58a+/VH+oX}_ .Z}·H1X*^*Abrs"@pЇu,#r̭P6DV4t;3g% {L *+M `jT^$OI=V4H{ CsUc[s<%؝]b9HW50Tژp GGf)"dhLj.H=NBp, ֚8Y|8Y|P.\KM\$n-j ׭{:)VTɢI5‹ kq_##Ò\`pgjջnX2L;?4+lX- %^Tv{BQHeBWIDaP{P{9 b3wsѹ%vTQ@g@f 'bi^z-^!}ΐCU{B !(Ǯ\ ˖TZ!yqoJxOwUZFqN֩R ,rLmB6P9.;HM^)gs߽-E5vDH.ꥯ'+jfv$X4)/N`ll8]:A-+40\2^ߖlݷ.M͞`:kvꯆzn-;v?#5a"cr}N~mcr}N~mcE {kڭ-iKe}4M4}|1ZnԄM4 !4gM4ieFb(i8 zj{!-t$R´vdlׄiW:mK# Z*iTu&Vzur#Sy$IFXӒyۚ;U#<1OaLI_i_"qTF(ؽMR6<Ws3 020.ztK+Z_ԅ0;7"Du])wWsC n;;g8wSM۪0n,AlmSfmrEyq,`9NIB}?MڙFF$_,kZD Q"O4Ϊ \Hg|u%({o? `{y%47FQGf+iqmoː4E.|z-r4\*>>B<Q+t]]3ԧ<&.5p+2;/@IPZ%OCCfsc*qaKI j'EBnTEqmU>..m /usxIA *nISڛ=DSфRP7fp7vE Ѭ7{YѤ5+ƽt2 /BtƫӪ4g9.fDSHShy~-,9Gt>ߴ yKZA*zN\Mu4;sɚ7vSƖN\ u€@V9zR#ks+n >3*E|[l"˧o9J ߴ yKRe/dsA; Sxvy:nNۇY2Ղ5v)E9àޠղ?D'/0L̍k^rwL(mʙw׍Zmq{MTlѓ'/P2UPT,ȼEf b 8U U1h~-,S{)ۈUQeTH5Lщ0BAKren !Q`77쎫PǕUN+:LP5 J⽾p2NHevxee&K:qҎrt!xjuD&ΰyGI {;^[Xr}׿hcKqm]ڤ[[toK}z64C=?2Yn dd>b<"nգR=A;l"G*ouNp&V1v;n]t[)e/5nOVe*ˌ(;jłr}׿hu%*ຼU E7Fe܀fTMl'5Lʐ:z bcڈE!YRUD!NGٶYwK˻IgES+Gq.!@=gNƨ,\Vi*H_-L|oUiy!@MiR&+ ~-,9Gt>ߴ yKRci {1^3Tj0ʶh;\zedk&])T0 Jh&QS['&)IѪ|֜d:JH?ZpqzWG ɣ&. +:V+S$%T.<0/Hs )hj 'e3LQ~b2~]Th{w^ӾH=gm.>`_u0['eX-a!l(RS 1d,=h *κ ǴF[f}ge`N!rHJ9a$hóɫ0MB;K:~-,9Gt>ߴ yKPO־Y\6noxBBU H5X'h@'Ǹ t'iŠ0! dM(2O9xu%iM"5xş- CSE2&P3#0m,7l,C:T)50LaO׍}lv3aO׍}lv^aS2Uی-ɱz).GKZmkkߦ@8zWmjh,kӌdP rk,iv,Fh4# can9]8Y6bTFOEduZmBXk!:B1{؇"-*mtA{߱؏6|Z% 0 0&{qm\t:\$wWūJ^*=LpGj`;n=,I<ڽvɤ \BwJs$(S:0Ի/Sރ4Ow`Hݦ[2BQ!-(=i58`{.6bddjVA++,P%Ƨ顆iˆӔ!NxL^X*ab@4$g-YNbM[K u2 G Y5&LۂeF\}%+j䦝|ˬW8.T6̝{_^7'KA{q-]i]m˜KwHY%$bk@WHڲgnŪ9Z Eei'-_Np+^E9`xIVDÕrJTD<~09t`*'y{ڱ 7eRƿ0|bM$OO_{kkFO;hA ,Qx\z9?玦XM=YF*(e.+mfTJccMal`9;=Ϻc9;=Ϻ ~2Xmzm[t/GCHwwcæn![x,)l:Gv{]&~8`"y,!4dKc$'ѥ hFXI#4ьK#h8U};B3[e2DZCϱH|1k"a>~MT~&I Q( $ Df)jЭ$4*VE )G姿W"ęO¯0姿W"g};q}<.$QXRJ-g@XP p8EťB 9Z{l~a-= 0g$Z{l~aidJoNjE֒&̫)CRYiIXRXa` D"9EN["(7xCSSR5-@BNAG$i.Tx8Z"ԃLSh}O$)2BU**BL@+#OÅ,&$&, (` =iӗL0L0L0L0L0LG(՝s˷oz.h'Iիb;Rmc8bLȿ [~g$O8܋q<FxbLȿ 2lD8//) X%djƀiqJGf% "LM/NT(EVߑ5bD!q}Ň 3[J.Y%@3Tu"B&Sck}' l9e3,Ye\9UqYìur)_} V4pXTyZGpҜ_@ܩ"5gQ&d^9ZiSѤɗ1Ԫo};i:`GHHX Sgβe<ָELSTlb$b O\1VW UPTVpj*e*Q$TnϦS`kQ}>l91wYe[j9nâErծ@bY JpfKQfڪDE$o2n>-Mg܎ZghH2yJͱsM >pE\|H:M+@9QhSBbCJ E$q}VZu%Xa_5ihReME RB}b$Ԅ:LI=B5sj$#iTԺ@ .ݶZAGeKh%zco;o[ڀBlrO=s-Y* 䔑u]tf\ SwوM븶nK%AۣYhT{*[Ut^4n5oDDge$S,Z:*Z(<Mw[ճ^-Z T-N5HGg{c:P5-L;[5znn[P`$Y%r8u"yU .QT-)JE4]a2G6:EttgIy-2M7_ s{LAGE6c׮8ȞE8"]w2ɽ0w5TRpQOKЇa<1iޒADjvbJ=}`9 *TP" pʐkrfXǂʖm\/Im[`~QO!)앹#j9mIڨw$Iۂ hsdϛ/YQ٩jWtRze֊v;c. 3[NO7~-b}˥h6S>05 õ 頪7R.[f#\X":3ʤ m?D$E^|wN1?Vߨ=ĜUn=?UecyV AWLB}SQE:(sx!>jB&wE\$R54j] YQ㉩!@փS`Lj?2#Yn&.!Qܓz&޳lr!>g^6Q"gт~imcM4KQC|2;q'Å2Q54$hԣ^T:OJygVTifi%#0E^_uԵQ :4:A8V4cac=:paB&I5=!#\*#il 9ʸSekLa$#@):%UkVVaVz,պk 凳:E}$?q XE'=Vm#E<,@HtZD ),HPUza5i膯VY#%Kc|s5Q19uN` U(4)]h`S+,u@Ӝd%y͕Hk*w/!Ն5=\t{AE-syDH~ß,of"C"椻RbŘ~^>|nMy{` tQ;>O㙨1>XGDDmƟP8鮐֖h^ a }oyeM4abL5fF_z:Gϖ73Q!cxnT'6#ԉicAYt'2,GW +WJK%Ao# x=wE/qodc2o/XBGZc} eDŽ&5$8̠ΈA 0-J1b5d<At(jI2y;H~V\>ǭ w8JXͬ%p21 \mw駥yMctj )+ G2wA´{M-e|5t}<=q@:S^Z}Xc )em;}kG؎WvOtf#Gq"ŵ4* !5B1a(1U\h4;R%p]!,m4G؄c!kcEQB]bZϳ+a.3k5 WvOMM|Ák2ɓ#˧]5X]kFHkUNF+]8#aRV=5ӳ.Sj7!D LMDfq@eV\dk^"ƒ\^0i1eo4?n0=:FFц?X+KKKڌ5,cgH]޺ac}<1'QFҰC,VEAJbIH  5`9hNxP:I ezQ@X$P!2I9}@P.xK0p]Knd)Y#kk>nm,"Cw:2o2C3"s:]*0^',E19iRkGѻF?䇱EUʦ#jcJpjG^ )ݼф!uaC׎AEvߵ?<;on%:T|-B:HBTs4cݬtmG1t%ta_ɦn%x=aQm^-Söx)baF0p20tK.cw]߇Ꮀp^WF0)uı6XF=ǨCAכVb}r}N~mc̭XIK3ir1cc#HHG0jJ[!ӣm%uTh3Ca U \KsJ‚LMR@e5 uk(UIwQ\$z,3kfg%4iJL e$ȐHV4֒~)Ֆ3FӖm`9Ej+k 8V`RP5.Prbu@B`X6IFzUh¬cOXpЋ)8r`IRIHӤ%I4 IJ+)+%%CBjKQapv:>MuCe8a/>Oϔe`=?yXCpN~>Ηg_g q yGX 0Ez]8EW 0E{g՛yWG|yt 1|^XcVk}ǝF\s>U}`K <8Jic||xu+ a|}tӝN֞1:|]نe5p_~:(8E}c ";QcL~_(^wb? cϧ;ac 0E릜v9g?<Sq0 0D3نe5\X^f>{s_>ُ8a/>?ǔUyv,? }a:}tӝN֝X>"yEW/uyxW]|:q{|q:~PUzjK*;΄Me~XaF= aBzTC@ѯ0jTN*j5(9Ɯei5M,` mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/snap.rgb0000644000175000017500000057216710504574206023717 0ustar debiandebianno name@wpX++,11s1677j788f899k9::s:;";x;<'<<=/==>4>>?3?x?@@t@A#AyAB(BBC0CCD5DDE=EEFBFFGJGGH[HIIJJKKLLMNJO!PQR RSTVWX YZZ[\^__`abdefPghikl9mcnopqs6tcuvxyMzu{|~hJUl8JB$+qaPI'7k,ȫ,Ϳ@Kz"uk5kC)    .H~#&U)-004 7h:>;AEIHLzP%SWm[,^bf-imCpt7w{TY_>>n.L̩t6ۮx*S d k\U!%Y(,J/3,69=i@DG5JqMPT/W^ZX]z`c_fHiknqyt vyD{~g4p%h{Lp s4KPX] ejr!w&.3;@HMUZ bgot#|+08=E›JãRĨWŰ_Ʊ>ǀ͌(lмY8׎Fx;ݲN-~.2++-1913s674778.889599:;::;B;;U>??N??@<@@ACAABIBBCPCCDVDEE]EF FcFGGjGH!H~HIAIJ2JKAKL^MMNOtPfQaR^SUTSUXV\W_XbY`ZX[O\R]W^__Z`SaSbTcWd`efgijDkvlmnp qCrfstuw>x}yz|}I~d m,h>AI*,{}E4S8ĘɄ Θӟ)ؾ` []`<%  $:] $'x*.\15.8;?kBFJMQbU X\k`cg_jnqqudx|I2+?^jƅ/Ѹv0l$b$^#  J #&)-w04J7;>AEHLKNRUBX`[h^a{d[g<jlorXtwz!|6AnLTynQj\71Xkq x'~-4:AGNT[ ahnu${*17>DKQX^ e¼kr!x'{TǨɥ.[ϣJa>֪dڬ۹}<zH*/I++/o1V1567O778J889P99:W:;;];< >q>??c??@X@AA^AB BeBCCkCDDrDE!ExEF'FFG.GGH>HHIgIJ^JKmKLMKN NOPQRSTUVWXYZ[\]^_`abcdeg&hTizjkmn1oZpqrtu-vhwxz{Q|}~>)> oL:K3*#w)oI{ozbXluٜA>HS5   (An!%<(,/26J9=@DGKINRV<Y]aWdhlosvz }$j#Y|4GP ǹl2ֱo7^f'a *,0 $9'+#.25f8?=><?D9BGD@DF?B?BHBHB@FCF7B50*8%+,-"+)!turd[F46/.&$#$"! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !(/43979c|x}rwqfAB;4, &%,+,+::@FNQTPRUVUUSSPVUXSQVVVW\hh_`e`cgbb[hbckjhcmckpintorsrwsrl|~~w}|w| &#$)-+03:<0@=85.,($)2;7418<H?.<;=9:<686:?4=B?;?C9<:<B=B<9A>E4@0+$3!(%. %' ~opm_VA/1*)!(/43979c|x}rwqfAB;4, &%,+,+::@FNQTPRUVSVSSMUSXSPSRTTYgia`ecab`a[hcbihh`j]glhjrkturwzro~~~{u}~wsz('*++11681=:82-,)&(4=651<<I<,<>@:9:897:?4=B?;?A:=:=C=C=;A>A2=0+%3 &'(&$  ~opm_VA/1*)!(/43979c|x}rwqfAB;4,~~~,~~~,~~~,4~4~4h44:~:~:h::N~N~NhNNf4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4fr:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:rϙNNNNNNNNNNNNNNNϙNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNϙNNNNNNNNNNNNNNf44~f~fff44f4r::~r~rfr::r:NN~~fNNNff4~f~fhf4f4frr:~r~rhr:r:rϙN~~hNNfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr:ϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙNff4f~~~ff4frr:r~~~rr:rϙϙN~~~τϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nf4f4~~~fr:r:~~~rτNN~~~ϙf44~~~r::~~~σNN~~~4f4~~~f4:r:~~~r:NN~~~ϙNf4f44~~~f4f4r:r::~~~r:r:NNN~~~ϙNNff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~G~Lff4frr:r:~J~Prr:rϙϙNN~J~PϙϙNf44~G~Lf4r::~J~Pr:NN~J~PNff4f4~G~Lff4frr:r:~J~Prr:rϙϙNN~J~PϙϙNf44~G~Lf4r::~J~Pr:NN~J~PNff4f4~8 ~?ff4frr:r:~; ~Crr:rϙϙNN~; ~CϙϙNf44~8 ~?f4r::~; ~Cr:NN~; ~CNff4f4~9 ~9ff4frr:r:~< ~=rr:rϙϙNN~< ~=ϙϙNf44~9 ~9f4r::~< ~=r:NN~< ~=Nff4f4~9 ~9ff4frr:r:~< ~=rr:rϙϙNN~< ~=ϙϙNf44~: ~:f4r::~= ~>r:NN~= ~>Nff4f4~/  ~0ff4frr:r:~2  ~4rr:rϙϙNN~2  ~4ϙϙNf44~/  ~0f4r::~2  ~4r:NN~2  ~4Nff4f4~/ ~)ff4frr:r:~2 ~-rr:rϙϙNN~2 ~-ϙϙNf44~/ ̄~(f4r::~2 ̄~,r:NN~2 ̄~,Nff4f4~/~(ff4frr:r:~2~,rr:rϙϙNN~2~,ϙϙNf44~ ~)f4r::~#~-r:NN~#~-Nff4f4~ ̄~)ff4frr:r:~#̄~-rr:rϙϙNN~#̄~-ϙϙNf44~! ̃~*f4r::~$ ̃~.r:NN~$ ̃~.Nff4f4~" ̃~*ff4frr:r:~% ̃~.rr:rϙϙNN~% ̃~.ϙϙNf44~# ̃~+f4r::~& ffff̃~/r:NN~& ̃~/Nff4f4~# ~+ff4frr:r:~& fhjffffghhgf~t~/rr:rϙϙNN~& ~/ϙϙNf44~$ *;3~,f4r::~' f~fffgghijkj~0r:NN~' *;3~0Nff4f4~%1 ~-ff4frr:r:~(vffgiijklmftfrq~1rr:rϙϙNN~(1 ~1ϙϙNf44~& &(,=~-f4r::~)ffghjkklmnof̏on~1r:NN~) &(,=~1Nff4f4~'  G F~.ff4frr:r:~*ffhiklmnnopqrr̮qf~2rr:rϙϙNN~*  G F~2ϙϙNf44~'  ~.f4r::~*fffghjlmnoppqrsttsf~2r:NN~*  ~2Nff4f4~(   ~"ff4frr:r:~+fgjffghf|lnopqrrstuvuurnj ~&rr:rϙϙNN~+   ~&ϙϙNf44~) '+C+   ~!f4r::~,fw{ffffghimopqrsttuuxwwvrnjgf ~%r:NN~, '+C+   ~%Nff4f4~!̃+H;A    ~#ff4frr:r:~$̃fflffghijynpqrsttsrtzyxuqnjh ~'rr:rϙϙNN~$̃+H;A    ~'ϙϙNf44~"    ~$f4r::~%ffghijklmnopjssrpomty|{zyuqmf~(r:NN~%    ~(Nff4f4~$ $ ~&ff4frr:r:~' fghijklmnopfuznmkmsy~}{ymnkh~*rr:rϙϙNN~' $ ~*ϙϙNf44~%  *G  ~(f4r::~(fff fghikklmnoppmkjkklmosx~}uqqol~,r:NN~(  *G  ~,Nff4f4~'  ̍ ~)ff4frr:r:~*ff fghijhjmnlkijkklmnoqrx}̍|yuqtqn~-rr:rϙϙNN~*  ̍ ~-ϙϙNf44~('/ ̌~+f4r::~+fffghijfnmmlkiijkklmnopqsuw}̌|xtuu~/r:NN~+'/ ̌~/Nff4f4~/<  ̍ ~,ff4frr:r:~,ffffghijkfkkihijkklmnooprtuwx|̍|si~~0rr:rϙϙNN~2<  ̍ ~0ϙϙNf44~! !8)! +H0;-~f4r::~$fffffghijihhijkllmnoopqrtvwy{|fhn̂~"r:NN~$ !8)! +H0;-~"Nff4f4~ .#*DA#"!?3+~ff4frr:r:~ fffhighhijkllmnoppqrstvxz{}~f̉~̑~ rr:rϙϙNN~ .#*DA#"!?3+~ ϙϙNf44~ 4O:%$#" ̃~f4r::~fhffghhijkllmnoppqrsstvxz|~|~̃~"r:NN~ 4O:%$#" ̃~"Nff4f4~ ̂&  9/('&%$"!̃~ ff4frr:r:~" ̂f fgffghhijkllmnppqrsttuvxz|~{̃~$rr:rϙϙNN~" ̂&  9/('&%$"!̃~$ϙϙNf44~"̄   $*)('&%# ̃~!f4r::~%̄fx fgihhiijkllmnopqrsttuvwxz|~̃̃~%r:NN~%̄   $*)('&%# ̃~%Nff4f4~%̅ !##$),+**(̏" !~#ff4frr:r:~(̅nffhofghjkkjklmmnoppqsttuvwxy{|~̏~'rr:rϙϙNN~(̅ !##$),+**(̏" !~'ϙϙNf44~( !#%&%)/-,̋(&%# %~f4r::~*fffgiklmmnoppqrgtuvwxxy{}̋~#r:NN~+ !#%&%)/-,̋(&%# %~#Nff4f4~*7  "#%'))(.0/.+*('%$ ~!ff4frr:r:~*f|fghjlmnmnopqqrsfl}wxxyz{}̒̕u~%rr:rϙϙNN~-7  "#%'))(.0/.+*('%$ ~%ϙϙNf44~ < AGDA6431;&-+*'#+21~(ff4frr:r:~!̂rf ̵tuvwxyyz{||}~fj~,rr:rϙϙNN~!̂ 1 ̥B!(*,./135>AGDA6431;&-+*'#+21~,ϙϙNf44~! 9!#2*,.02357877;9865421/.,+'*04~'f4r::~$|gfffghijklnprtvtvwxyyz{|}}~h̙~+r:NN~$ 9!#2*,.02357877;9865421/.,+'*04~+Nff4f4~# !#8K>.024579;:9<<:9764310.-+(/57~'ff4frr:r:~&fghijkmoqsuwxyz{|}}~f}~+rr:rϙϙNN~& !#8K>.024579;:9<<:9764310.-+(/57~+ϙϙNf44~%  !#%')<-.024689;==<;?=<<;:875421/.*-4:~'f4r::~'fmfghijklnprtvxyz{|}}~~+r:NN~(  !#%')<-.024689;==<;?=<<;:875421/.*-4:~+Nff4f4~  "$%')+-/02468:<=?A@?@@>>=<:9764320.,39~$ff4frr:r:~fjfghijklmoqsuwyz{|}~~(rr:rϙϙNN~  "$%')+-/02468:<=?A@?@@>>=<:9764320.,39~(ϙϙNf44~   "$&')+-/13468:<>?ACCBACA@?>=;:875421.18<~f4r::~ fghijklnprtvxz{|}}~r:NN~    "$&')+-/13468:<>?ACCBACA@?>=;:875421.18<~Nff4f4~!  !"$&(*+-/13568:<>@BCȄB@?=<:976532069~ff4frr:r:~$fggijklmoqsuwy{|~fhj̏~rr:rϙϙNN~$  !"$&(*+-/13568:<>@BCȄB@?=<:976532069~ϙϙNf44~̬* / !!"$&(*,./13579:<>@BDFHGGE ̅75414~f4r::~"̄ff̬vklmnprtvxz{}̀ ̅~r:NN~"̬* / !!"$&(*,./13579:<>@BDFHGGE ̅75414~Nff4f4~ &D /L< !!"#%&(*,.013579;=>@AABCFJJHFECB@?=<:864 ~ff4frr:r:~fghfklmoqsuhyz|~fmu̞ ~rr:rϙϙNN~ &D /L< !!"#%&(*,.013579;=>@AABCFJJHFECB@?=<:864 ~ϙϙNf44~ ̡ !$?/?CFHGECB@><:8310,.0̂~ff4frr:r:~ fghijkl ̘k̙̂~rr:rϙϙNN~  ̚.A !"#$%%')+,.024679;<<=>?CFHGECB@><:8310,.0̂~ϙϙNf44~ 5? !"$%%&')+-/02468:;<;;?BFDCB@><:̇310.-~f4r::~̩ffghijklnnprtvn}{̇~r:NN~ 5? !"$%%&')+-/02468:;<;;?BFDCB@><:̇310.-~Nff4f4~̩  !##%&'()+-/12467789:99;?BB@@><̊310.(~ff4frr:r:~!̧ffghijklmnoqsuvxz|~̊̎fim~ rr:rϙϙNN~!̩  !##%&'()+-/12467789:99;?BB@@><̊310.(~ ϙϙNf44~   !#$%&())+-/1345678778;?@>>95320+))~f4r::~ ffghijklmnoprtuwy{}̟̜̑hj~r:NN~   !#$%&())+-/1345678778;?@>>95320+))~Nff4f4~̤ !#$%&'**,-/12234565;95 ,+)('$~ff4frr:r:~̢ghijklmnopqsuvxz|~gkm̡̜s̓u~rr:rϙϙNN~̤ !#$%&'**,-/12234565;95 ,+)('$~ϙϙNf44~   "$%&'(+,./012343%764+F/-+)(&$*I5~f4r::~ fghijklmnoprtuwy{}jik̜~r:NN~   "$%&'(+,./012343%764+F/-+)(&$*I5~Nff4f4~ ̠ !#%&'(+-./01232109HA5"642:@5+)(&$=!~ff4frr:r:~ ̟fgijklmnopqstvxz|~̤̒~rr:rϙϙNN~ ̠ !#%&'(+-./01232109HA5"642:@5+)(&$=!~ϙϙNf44~̠  "$&'()+,-./010/.;#2KA420/-+)'&!̄ ̃~f4r::~̟ffhijklmopqrsuwy{}̏̈̄̃~r:NN~̠  "$&'()+,-./010/.;#2KA420/-+)'&!̄ ̃~Nff4f4~  !#%'(+,+*+,---./.-,-021221/-+)(&!̃~ff4frr:r:~fghijkmnoprtvxz|~̑̒̓̈̅̃~rr:rϙϙNN~  !#%'(+,+*+,---./.-,-021221/-+)(&!̃~ϙϙNf44~̖́  "$&(**,*()*++,--,+*,0//0/-+*(&̈̅~f4r::~́fghijlm̘qrtvx{}̑̒̑̈̀̅~r:NN~̖́  "$&(**,*()*++,--,+*,0//0/-+*(&̈̅~Nff4f4~ ̜̂ !#%'),*+)'&&'( )*++*)(),-,--,*(&́̄ ̇~ff4frr:r:~ ̂gf̙nopqqsvxz|̒̐fit́ḡlpk̇~rr:rϙϙNN~ ̜̂ !#%'),*+)'&&'( )*++*)(),-,--,*(&́̄ ̇~ϙϙNf44~̆1   #%'+)*(&$%&55()('&)+**+*(̋:6.!~f4r::~̞klmnppqqsuwz|~̒yf}̡̋~v̇~r:NN~̆1   #%'+)*(&$%&55()('&)+**+*(̋:6.!~Nff4f4~̡@  "$)*G)'%#$%"EA&'&%$#%('#@,DBK4̄~ ff4frr:r:~̉fh{klmooprtfj}̏̐fw{̦̉̆~|{̄~rr:rϙϙNN~̡@  "$)*G)'%#$%"EA&'&%$#%('#@,DBK4̄~ϙϙNf44~̍ ̆,=)&$"!"#$%$#"!"%,#>~ f4r::~̍fyghijkmnoopȯgz̒̆́~|{yz{~r:NN~̍ ̆,=)&$"!"#$%$#"!"%,#>~Nff4f4~̊)̉%B!̉7J*(&#! !"#"!! !18AJ!~ff4frr:r:~̊ighijlmn̉f|~̈x̄́~|{yxwyxv~rr:rϙϙNN~̊)̉%B!̉7J*(&#! !"#"!! !18AJ!~ϙϙNf44~  ̈ 8()'%#  ! CA!!~ f4r::~fghjklmnoomnpsuwy|~̉qfl̄~|{yxvtvw~r:NN~  ̈ 8()'%#  ! CA!!~Nff4f4~ ̊&)%((&$"  $̅ ~ff4frr:r:~̙fgijklmmngnlnprtwy{}̌fr̋̃~|{yxvt̅uq~rr:rϙϙNN~ ̊&)%((&$"  $̅ ~ϙϙNf44~̢́́  $ !$&'%#!"@J ~f4r::~̤́́ijfsumftkmoqtvxz}fĭfif̃~|{yxvtqqso~r:NN~̢́́  $ !$&'%#!"@J ~Nff4f4~̢́#;(F 2!#%<7$" < ~ff4frr:r:~́f̡fmijloqsuxz|ff~}~́~|{yxwvusrp~rr:rϙϙNN~̢́#;(F 2!#%<7$" < ~ϙϙNf44~̅̇-> ̐.K "%@&$! ̑ ~f4r::~̅fghij̇jlnpş̐fhq}~~}|{||}~}}|{z̑wvup~r:NN~̅̇-> ̐.K "%@&$! ̑ ~Nff4f4~̖̉́* "$'%#!'~ff4frr:r:~̉fghijlḿi̘tvy{}̋xf~|{{|}~}|{zy}~{gixfj~rr:rϙϙNN~̖̉́* "$'%#!'~ϙϙNf44~̥̄̂ $$&&$5Q & ~f4r::~̦̄̂hijkklmljhikmoqtvxz}̊}}{yz{|{zyxwvvw|~rzzȳk ~ r:NN~̥̄̂ $$&&$5Q & ~ Nff4f4~̘̂ ̂!#̉! >̅#ẢH=, ~ff4frr:r:~̘̂ffgijkklmkijjlnprtvxzfĥ̇r}zxyzzyxwvuttux{̅̉|̯ ~ rr:rϙϙNN~̘̂ ̂!#̉! >̅#ẢH=, ~ ϙϙNf44~ ̌$&%" &  DÁ~f4r::~ffghjklljjklmoqsuwxzfy̌~|zwvwxwvutstvwwx{~fr̆̀̀́~ r:NN~ ̌$&%" &  DÁ~ Nff4f4~̉ ̒2L $"   %:#"!! ~ ff4frr:r:~̎fgghijklkkllm ̔r}{ywttuvutsrqrtvxz{hl̋̄́k~rr:rϙϙNN~̉ ̒2L $"   %:#"!! ~ϙϙNf44~ @>̏-9#!     - 8FD$$#  ?3̂~ f4r::~ fhjijjllmmnnoprtvxz|}̎~|zxvtrstsrqpqsuwy{}f}t̆̂~r:NN~  @>̏-9#!     - 8FD$$#  ?3̂~Nff4f4~ 5 @B      ,I@!%'̋&#"! ?."~ ff4frr:r:~f̅ijkkmmnooppqsuwy{}f̄~{ywusqrqpoqsuwy{}̋z~rr:rϙϙNN~5 @B      ,I@!%'̋&#"! ?."~ϙϙNf44~ 3 !̋!   $̇'/M7%$#"&'̅~f4r::~ffthijkmoppqrrtvxz|~̎v}{xvtrpooponmmnrtvxz|~̌̅~r:NN~ 3 !̋!   $̇'/M7%$#"&'̅~Nff4f4~  ́&̉   !"++*)-(''&%$̇~ff4frr:r:~fghiikmoqsqqrlntuwy{}́̋~zxusqommnmlnprvxz|~f̑̇~rr:rϙϙNN~  ́&̉   !"++*)-(''&%$̇~ϙϙNf44~    --!#%&$" ̄  !#$$/F*-,,+**)(̂~f4r::~  fghijmoqsutsfvvxzflyf~̄prpnlkjlnprsuy{}̋hĵ̕~r:NN~    --!#%&$" ̄  !#$$/F*-,,+**)(̂~Nff4f4~ ̈ ̗CD6 "$&%# ?̅  "$&'3!?@+-/..-̈(&&*~ff4frr:r:~̈fgghfqsq̗wy{ff}ẑmkjikmoqsuwy}̍f̈̑~rr:rϙϙNN~̈ ̗CD6 "$&%# ?̅  "$&'3!?@+-/..-̈(&&*~ϙϙNf44~ ̊8 ̇'D!#%̌4H  "$&()**2N?,--.0̉+)'%%(~f4r::~̊rtwy{yvẇ̌~}fjfwnhikmoqsuwy{|̀̐x̉̌~r:NN~̊8 ̇'D!#%̌4H  "$&()**2N?,--.0̉+)'%%(~Nff4f4~  1E̐ "$&%" ̠/1   "$%')+,-6..//030.,*(&!!%~ff4frr:r:~ fhjlptvx{}̐xyzz|~x̾|tpmkifhjlnprtvxz|~fk̙̖̓̇̌~rr:rϙϙNN~  1E̐ "$&%" ̠/1   "$%')+,-6..//030.,*(&!!%~ϙϙNf44~ ̡ !"$&#!̜  /!%')+-/0012221/-+)'%!! ~f4r::~ ̡giknprtvxzgik}{zz{{}̝qomjhfilnprtvxz|~f̖̘̈̇giq~r:NN~ ̡ !"$&#!̜  /!%')+-/0012221/-+)'%!! ~Nff4f4~̣ %!#%$"̂0 ̝  -JA)+-/02234530../.,*(&! |ff4frr:r:~̐fhjmortvxz̋|}~|̂o̞ggjnqsuwy{}tfv̙̇̃k~rr:rϙϙNN~̣ %!#%$"̂0 ̝  -JA)+-/02234530../.,*(&! ~ϙϙNf44~ #B "$%#    "$-(*,.02455 +B,66741.+,̏;N|f4r::~ffiknpsuxz|ffhgj~~xvtqmljihilosvy{}p̏fĥ~r:NN~ #B "$%#    "$-(*,.02455 +B,66741.+,̏;N~Nff4f4~  <)!#%$!   "$&(*,.02468;AJ9:85̐()(#%̂zff4frr:r:~ffgjloqtv~fzfxfhwurpnnomlkjimqux{gi}̉f{~}̂~rr:rϙϙNN~  <)!#%$!   "$&(*,.02468;AJ9:85̐()(#%̂~ϙϙNf44~ ̟̂̂+I "$%" 4  ̖ !!#%')+-/13579;;<<8<=̅30,)'%"0N8{f4r::~ ̂ffhjm̂z|̟}fsqomoqponml̒fq~̚fxx}}|{~r:NN~ ̟̂̂+I "$%" 4  ̖ !!#%')+-/13579;;<<8<=̅30,)'%"0N8~Nff4f4~ ̄̆ ̇!#9=-< !#%#!̤5K   $A;%')+-/13579;=>>?@=;:740-*'%#"5=!̂}ff4frr:r:~ ̄fhff̆psuxz}̢̐rpmnprsrqpnnrv{̛̊~|{zy{̂~rr:rϙϙNN~ ̄̆ ̇!#9=-< !#%#!̤5K   $A;%')+-/13579;=>>?@=;:740-*'%#"5=!̂~ϙϙNf44~̄ ̐ #%'*(%#! "$̨ 5    (?$(*,.02468:<>@AABCC?<98741.+(B̃~f4r::~̂f̄tvqț̐|zpsqnmoqrtutsgprw{gĭ}{zxwwx̃~r:NN~̄ ̐ #%'*(%#! "$̨ 5    (?$(*,.02468:<>@AABCC?<98741.+(B̃~Nff4f4~!$')++)'$" "#!"?   !&)-02468:<>@BDDEFDA>;76542/,)qff4frr:r:~f|fhj̿wz|̉̉}{yvtqomnpqsuvwfpsw{f}y~|zxwjourr:rϙϙNN~!$')++)'$" "#!"?   !&)-02468:<>@BDDEFDA>;76542/,)uϙϙNf44t̄;  "%(+-/,*(&#̪*@  #@"&*.2579;=?ACEGGHFC@<964321/-*8< '2 ̂̅rf4r::w̄fiypsux{}̨j|zwurpnmoprtvxx̊uw{}{yvpt̂̅vr:NNw̄;  "%(+-/,*(&#̪*@  #@"&*.2579;=?ACEGGHFC@<964321/-*8< '2 ̂̅vNff4f4X̃ !#&),/1̔%$#   ̗'?"&*/37:=?ACEGIJKHEA>;84310/-,+"A" =E ̅sff4frr:r:[̃fgjloqtvy|hj̔z}{xvsqolmpqsu̖kxw|}|zuspq̅wrr:rϙϙNN[̃ !#&),/1̔%$#   ̗'?"&*/37:=?ACEGIJKHEA>;84310/-,+"A" =E ̅wϙϙNf44V́ #"%'*-01/(  "37$')592/-* ;D ̏ ̺/K48<@EIMOQSTTQNJGD@=:630.,+*('&$#"!: if4r::Z̬fffffgjloqtwy|̙̆f̡~{yvtrȍprtvwy{}~̋|z~̠srnmmjiimr:NNZ̬ 4>$')592/-* ;D ̏ ̺/K48<@EIMOQSTTQNJGD@=:630.,+*('&$#"!: mNff4f4W̺"%(?;1.+)@? < ̻# :>4848 #6A>:41-% ,A #(%049=AEINRVUQNKGDA=:73-*)(&%$"!  ̂cf4r::[gxff̘y{~̌̚yljrtvwfhyg̻̓~xvtpolkigghîgr:NN[̘7> #6A>:41-% ,A #(%049=AEINRVUQNKGDA=:73-*)(&%$"!  ̂gNff4f4X&A='EC@=63)'$"AE  & $(,059=AEJNQTSPLIFC?<952+)'&%#"! cff4frr:r:[fzf̌fglfz}gi̝̐ftrpmkm{qsuvxf~fu̹̒myyvspnkihggijggrr:rϙϙNN[&A='EC@=63)'$"AE  & $(,059=AEJNQTSPLIFC?<952+)'&%#"! gϙϙNf44Y  6IFC?<5,(&#!9  6K&C"#"$(,159=BFJLOQSNKHDA>:74-*'&$#! 3* df4r::\fffhmpux{fo̜̒uvsqnllnprtuw~f̵̔f~ywsonliggjkfm|hr:NN\  6IFC?<5,(&#!9  6K&C"#"$(,159=BFJLOQSNKHDA>:74-*'&$#! 3* hNff4f4Ỷ ̆A=HEB>̕.+($"   ̄?'<#$%$(-159>BDGJLOQMJFC@<9 ,(%$"! )HA !>4̅dff4frr:r:\f̉ffilqvy̆̕|zwurfzoqs̄zj̳nr}|wvtomlhfjlmm̅hrr:rϙϙNN\̉ ̆A=HEB>̕.+($"   ̄?'<#$%$(-159>BDGJLOQMJFC@<9 ,(%$"! )HA !>4̅hϙϙNf44Y 7%>KGDA>741-*'#!̂̄!##$%&&)-15:;1**'$"!  ̎df4r::\ffffgjmouwz̝fk̂fx̄uwy{ǂ̮f||{zywvutromkhhmnoopq̎uhr:NN\ 7%>KGDA>741-*'#!̂̄!##$%&&)-15:;1**'$"!  ̎hNff4f4Z̗ (FTPMJGC@= 0,)& C@  "$%&&'()-147:  !#$&'()*,/247:;851.+'$! ' "̄cf4r::]̈̂ff̛ffkmoţ̍yvtqomnopqs{|~̓gizyxvutrqpolkjintuuvqxyzz|̄gr:NN]̛̈̂ 8VVSPLIFB?<@/,(̍ >  !#$&'()*,/247:;851.+'$! ' "̄gNff4f4[̄̃̊9 B̌ROKHEB>84@.!   "#%'()*+*-/247:84@.!   "#%'()*+*-/247::740*'#   !"$&(**+*(*-/247:;852.+($! => ̂̉ef4r::Kffq̄h̞ḟ̱̐~{ywtrfssrtvxz|~̑~fwvtsrponlkihifgwty{||}~~̂̉ir:NNK 8!EXXVTKGDA>:740*'#   !"$&(**+*(*-/247:;852.+($! => ̂̉iNff4f4Ī̆B̛ HTUTRPNLJG@=9630,)&" ̂AF  "#%')+,-*('*-/257:=:730-)&# &? 38̂̃eff4frr:r:L̄jk̆ff̨f̛mo}̦ ̂ruwy{}̐}|{wutsqpomlkighkf|v{}́̂~}̂̃irr:rϙϙNNL̄̆B̛ HTUTRPNLJG@=9630,)&" ̂AF  "#%')+,-*('*-/257:=:730-)&# &? 38̂̃iϙϙNf44J ́ *.7BQQRPNLJHFB?<952/+(%" :  "$&(*+-,)'%'*-/257:=<:852/+(%!  !@̆ef4r::M ́́fj̐ffffffikf̨̞~|ywpurrqsuwy{}f̒~}|zyxvutrqpnmljihhjmo̦{}̄́~~||{̆ir:NNM ́ *.7BQQRPNLJHFB?<952/+(%" :  "$&(*+-,)'%'*-/257:=<:852/+(%!  !@̆iNff4f4K  ̭,@4MNLJHFDB><:741.+'$!  3%'(*,-+)'$%'*-/257:<<;98630-*&#   ̆Tff4frr:r:N fffyyf fzffffgf̒n̵̤̂}{sqqrsrrqqsuwy|~f̔}{zywvusrqonmkjigfgikmprft}̃̀~}|{zzyx̆Xrr:rϙϙNNN  ̭,@4MNLJHFDB><:741.+'$!  3%'(*,-+)'$%'*-/257:<<;98630-*&#   ̆XϙϙNf44K  /= GC =IIJKHDB@>:8642/-#   4L%')+--+(&$"%'*57:987641.,(%"  &:Tf4r::N fgkkgv}gh{̭gggffg̩̃q̣̱̫̠̊|wtrqrsrrqsuwz|~f̓̚fgi{zxwvtsrponlkihgfhijklnqn|~~}fkmyxxwwvXr:NNN  /= GC =IIJKHDB@>:8642/-#   4L%')+--+(&$"%'*57:987641.,(%"  &:XNff4f4L +, ̬ 9EFFHB@><:6420.,)'%   5$&(*+,,*((257764320-*'$   :EF*$̆Uff4frr:r:O fgfxhh iiyggfgifô̟̮̩̜|xvsqssrrqppqsvxz|~p̴̓fx}yxwutsqpnmljifghijklmno}~|fwxwvvuut̆Yrr:rϙϙNNO +, ̬ 9EFFHB@><:6420.,)'%   5$&(*+,,*((257764320-*'$   :EF*$̆YϙϙNf44M &CH̆50"9BBCCA?=:8620.,*(&#!  !#$& +**'%#!"%(E?254321/.+(%"  &CF Uf4r::P ffghiifgfjjiĩgkfz̩̘{wursrfkvpportvgi|~̅fȏ̏{xvusrqonmkjigghiklmnoprsuxz|}||{zvvuutssrfhjYr:NNP &CH̆50"9BBCCA?=:8620.,*(&#!  !#$& +**'%#!"%(E?254321/.+(%"  &CF YNff4f4C  .F@6G>>@A?=;942.,*(&$" ̂1  $!#%'&**)('%# "+<-/221/.-,)&    *"Vff4frr:r:F ̅ffgfghhhfvijfihgghzv̧̛̕~|{poprtfs}́ȋṁ̀}zvtsrponlkjhgfijklmopqqstuvy|{zfwyxwvuutssrfoqpoZrr:rϙϙNNF  .F@6G>>@A?=;942.,*(&$" ̂1  $!#%'&**)('%# "+<-/221/.-,)&    *"ZϙϙNf44D /LB/̝,n:<==93(&$"  $G  $B!#%'?)(('&$"%'*-//.-,*)(%  5) 6If4r::G ffghgffgtgghi̕vhg̝wՠ̢̤̟̙flf~srrqfooprt̊n̦fnl|xusqpomlkihgfhjkmnopqrsuvwxyzzyxxfvvutssrqpgonnmMr:NNG /LB/̝,n:<==93(&$"  $G  $B!#%'?)(('&$"%'*-//.-,*)(%  5) 6MNff4f4F P3 (59:7311&$"   !#&()(''&&%$-"%'*--,*)('%*  0H 4JCIff4frr:r:I ffghhihfifggfgg̶ggf{{gsfh̠̞̙f~|zxvtsrqqpwonnw}̎fyw}zwsqpnmljihfghilmnoqrstuwxyz{yxwwvuuttsrqqponmllkjMrr:rϙϙNNI P3 (59:7311&$"   !#&()(''&&%$-"%'*--,*)('%*  0H 4JCMϙϙNf44G  3?$133/51+ .KB!   "%-''&%%̼'E "%'**)('%$#%BG     Jf4r::Jffghfjijifwhgfiklnpzx̙̊f̜̘̑o|zxvtssrrqqppoonpsuy{}̎̽̌yuronmkjigfghjkmnpqrstugsyz{|yxwvuttsrqpoonmmllkkjjiiNr:NNJ  3?$133/51+ .KB!   "%-''&%%̼'E "%'**)('%$#%BG     NNff4f4H C D6*//8./+'%#!  %-1*#"!  "%'('%$#" :   ""  Kff4frr:r:Kffghhfynjjkjj̪jihgggkosvz~̝̐̕f|̖̔̒̍}{ywtssrqqppoonnmoqsuwy{~̐Ɖz~̃}ztpnlkjhgfgijklopqstuvwo{|}}yxvvutssrqqpoonmmlkkjjiihgfOrr:rϙϙNNK C D6*//8./+'%#!  %-1*#"!  "%'('%$#" :   ""  OϙϙNf44I3C #'*+,,-./0.)%#!  %-54&$##"!!  "%&$   :6(=$#! # !'DG  9/ Mf4r::Offghhijjkllmnnonmlkf|qjiilpt̍̏̊̄~ywussrqpponmllmortfmkfn|z{~n~}xuroigfghjklmopfvwyz{|}~~|ywvtsrrqponmlkkjihhgffgghiijklmmhQr:NNO!  J "#%&()$  $25=>:6(=$#! # !'DG  9/ QNff4f4M  5K  "$%%"  '  !!   ̈5 :GD@! ;   & Kf4r::Q̅fghiijjkllmnoopqpqponmmlkkqux|~fs̆̇̂~|zvttsrrqppoonnnklkks|̈sf눆v~}{ywy{~~}|zyxwqnkhfhijlnoqrstuwxyz|}~}{xvusrqpoofvkjihhgfgijkllmnnpqqrmlkjOr:NNQ    >'  !!   ̈5 :GD@! ;   & ONff4f4P      '8  )0 .6=EMJGC?0,/M"!    'C  9ff4frr:r:Sffghhiijkklmnnopqnsrrqqponmlllnqux̍{|zxttssrqqpoonnmfrkkq~̔f̗u~}|{yvvy{~~}|zyxwutpmjggiklmpqrsuvwxz{|}~}|xwutrqponqkjjihggfhiklnoopqrfguuoomkk =rr:rϙϙNNS      '8  )0 .6=EMJGC?0,/M"!    'C  =ϙϙNf44Q     ;!/,1#!     / :f4r::Tkfghiijklmnoppqrrolutssrrqqpoonnmnrvx̓}{ywtssrrqfionmmlko|̇n~~}|{yxvtvy{}|{yxwutsrnkhfhjlmoqrtuvwyz{|~~|ywvtrqoonmlkjiihgfghjlmoprrttflxxhjl>r:NNT     ;!/,1#!     / >Nff4f4R      %) -9FRPLIEA=2/+"!       9G) <ff4frr:r:Sffghijjkklmmnnoppqrpmnswvvuutssrrqppoonnmprtvx|~{ywutssrrqfponmmlkkjjz̶̙gnfu~}||{zgwsstvy{yxwvtsrponifgikmnpstuvxyz{}~~|fsvtsqonnmlkjjihggfhiklnoqstvwwz{{rpnl@rr:rϙϙNNU      %) -9FRPLIEA=2/+"!       9G) @ϙϙNf44R         ?I+7DPRLHEB>;41.$"  #    !  (A  G 6f4r::Sfghijklmnooppqrrssqnkkqvyxxwwvvuuttssrqqpopjwkz{{wutssrrqqpnmmllkjf{̛̲flfn}{{zzfrusqtvxwvtsrqonmkgghjlnoqtuwy{|}~fpvusqpnmllkjiihgfghjkmoprsuxyyz{{|}~~ttrpom:r:NNU         ?I+7DPRLHEB>;41.$"  #    !  (A  G :Nff4f4Q      ; ,A5BNPNHDA>:70-*;F;B"@    !""9A   7ff4frr:r:Rfghijkkllmmnoopqqrrsrolifhnty{zzyxwfhjuuttssrz̉tvxuttsrqponnmmlkkjjfq̢̮̗~y扦trpqtvtsrqonmkjihhikmopguwxy|}̅}~wusrpomlkkjihhgfgiklnoqrtvyz||}~~uvvusqon;rr:rϙϙNNT      ; ,A5BNPNHDA>:70-*;F;B"@    !""9A   ;ϙϙNf44P    A> >@?KMMJ@=:63,̂%<    !"#!   6f4r::Rfghikllmnnoopqqrrstspmjghikqv||}||zzfzxxwwvvuutt̨tuutsrrqpnnmmllkkjiit}̧̓̂wvrqonqsrqonmljihfghiklnpq́yx{|̇~|zyvtrqomlkjiihgffhjkmnprsuxy{}~wusq:r:NNS    A> >@?KMMJ@=:63,̂%<    !"#!   :Nff4f4O     4D %1=IKJJFC52̃!    92  "#$#!      7ff4frr:r:Qfghijlmnopqrstqnkhhjklnty~~~}}|zyyxxwvutsrqqpponmllkjihuwĩi||{yxvtsqpomnqonmljihgghiklmmoqfy|}q}̉~|{yxsqonlkjihhgfgijlnoqrtfuz|}ywq ;rr:rϙϙNNR     4D %1=IKJJFC52̃!    92  "#$#!      ;ϙϙNf44D      C@,    #/;FHGEB?(=1̧$#" 3   +BA 9- "#$&#"   4' !!"#̅$>0 8f4r::Gfghijklnnoppr}rssttuuroliijkmnoqw|́}}||{fwxwtsrrqponmmllkkjjhhp̮̉lf􋉈f||zywutsponllnmljihgghiklnopqqrsz~g̊~}zxvupnmkjihgffhikmnpqsug|~fhj̅xq <r:NNG      C@,    #/;FHGEB?(=1̧$#" 3   +BA 9- "#$&#"   4' !!"#̅$>0 <Nff4f4F  %:.   )<  ̿8DFEDA>;;B-"@?#" "E  2D "#$&%$"!  1LD "#$$%&  ̂̃9ff4frr:r:Ifghijklmnopqqfsstuufgikjijlmopqrtz~~p}vsrmzqpponmlkkjj̿hhnhm̫|̉f{yxvusrqplkiljihgfhiklnoprsuvxz{w̌}|xwusrmkjhhgfgijlmoprtuz}rfh|zxwusr̂̃=rr:rϙϙNNI  %:.   )<  ̿8DFEDA>;;B-"@?#" "E  2D "#$&%$"!  1LD "#$$%&  ̂̃=ϙϙNf44?  5G ' #"!  6r:NNB  5G ' #"!  6Nff4f4A    *E - !!  F? ̶:I7 ?<962/,('%#"! ̈ $!"#%&')$"  ̭  "#%&()*++">9̄0ff4frr:r:Dfghijklmoppqrsttuvupjkmnoqrstvwwzw̄̃~|yvrooonnmmqlkkjii̶gkw^~̅p̋~}{zyxvfnponmljifhik̈rsf{yz|}́̋~{yxkmrqonḽfghjlmoprsuwxz{}l}{zxvtt̄4rr:rϙϙNND    *E - !!  F? ̶:I7 ?<962/,('%#"! ̈ $!"#%&')$"  ̭  "#%&()*++">9̄4ϙϙNf44D  + 3M=!"#"!  9&:>(̮85('&%"! "?  ̆1L!"#%&')($" ̩1  !"$%')*,-..̇1f4r::Gfghijklmnopqrrsstuvvwwvsqjlmnpqrtuvwxyẏ̆~|yvronnmlg̟|jjihhgiu̮̎fuw̉~}|zyxvufonmljihgfhjlmoprs̆{}~fi~̊|{̩qpnmkjighiklnoqstvwyz|~~|ż5r:NNG  + 3M=!"#"!  9&:>(̮85('&%"! "?  ̆1L!"#%&')($" ̩1  !"$%')*,-..̇5Nff4f4G    ="#$%$"!  Ḡ #/;́8̏#;'&%$" ̌ )? @>(! "#%&')*(!2   !#%()+-.011̇ 2ff4frr:r:Jfghijklmnopqrrssttuvvwtrollmopqstvwxyz{||̊̉~|yurolkk̭jiihġr~́̏̆~vutkomlkihgffikmoqstvwy~fẅ~}yxvg{pnmkjigfhiklnoqrtikxz{}~̎̇|{xs6rr:rϙϙNNJ    ="#$%$"!  Ḡ #/;́8̏#;'&%$" ̌ )? @>(! "#%&')*(!2   !#%()+-.011̇ 6ϙϙNf44Ỉ    "$$%&&&'&&%%$$# ̇ !-89̐.76406D&%$"!̅̇ 8 "# 'CG""#$&')**(# ;> '"!"$%(*,-/0234̍ 3f4r::L̋ikfhjopqrsstvwxxuspmlnoprsuvwyz{|}~~̍~|yunk̇iihhggḟou|̐w̅̅|zyxẇonlkihgfilnprtvxz{}pË̊̅~|ywutrmkjigfhiklnoqrtfv{}~̏̍{vr7r:NNL̉    "$$%&&&'&&%%$$# ̇ !-89̐.76406D&%$"!̅̇ 8 "# 'CG""#$&')**(# ;> '"!"$%(*,-/0234̍ 7Nff4f49 "   %&' ((()(('%#  ̄1%*̘55443/*)(&%$#! ̃- ́  "#$&'*<''&')*,*'#  AG!"$%'*,-/01247 !  0ff4frr:r:< fghif|pqrsttuvvwwxyvtqnmnoqrtuvxy{|}~fr|̎~|ur̃iihggff̀̀̑vw}|̃}ṕgfilpqsuwy{}Ž̉fhj}{yfhjqonmjhgfhiklnoqrtfq̨}~̐p4rr:rϙϙNN< "   %&' ((()(('%#  ̄1%*̘55443/*)(&%$#! ̃- ́  "#$&'*<''&')*,*'#  AG!"$%'*,-/01247 !  4ϙϙNf440 4J   "($9+)*+**)(%# ̃ 17)-03433221/+)(%$#! '<0M   !#$&')*+**,+)'#!("  < " ()*,-./023!"!1f4r::3fghijkf|pqstuvwwxxyywtromnpqstuwxy{|~g̐huu̇xykihhgfhms̗̝̑̌̕m}|{yxwvfwonmkjifgjmpsuvxz|~ ̉x|zyfwpomkjgfhiklnoqrtuwx̢}~jpj̎gi5r:NN3 4J   "($9+)*+**)(%# ̃ 17)-03433221/+)(%$#! '<0M   !#$&')*+**,+)'#!("  < " ()*,-./023!"!5Nff4f45̂B    %)*4G++,-,,+(%̜(= &),/110/̡+)('#" ; 5  !#$&(*+-./-)'"+GH,G   #%&'(*+,-/01#$$2ff4frr:r:8̂fghijklm|pqrstuvvwxfhjuspmoprstvwxz{}~̟}{n~jggffrx̡̖̃̌̉f}}|{zxwvtsponmkjigfggjmpsvxy{} Ó̏̉ft|zxvvpnlkigfgijklnopqrtuvwz{|~l̊̅kgi6rr:rϙϙNN8̂B    %)*4G++,-,,+(%̜(= &),/110/̡+)('#" ; 5  !#$&(*+-./-)'"+GH,G   #%&'(*+,-/01#$$6ϙϙNf440 ̂E    !"#"#(++,,,-./%"?E2;C' "%(+/-,++*('$" 8   "$&')+-/1233-+*(&" 5==> i"#$%&()*+-.$%%# 8?/f4r::3 ̂fghiklmnoqrstuvwxxyzg|tqnoprsuvwyz|}~ƌ~{mjghlrufḧgi̓̒̑̋̈~{zxwvusrqonmkjihfgjmpsvy{}~”̉~{ywuomkjhfghijklmmnopqrstwxyz|}~gψ̋fw3r:NN3 ̂E    !"#"#(++,,,-./%"?E2;C' "%(+/-,++*('$" 8   "$&')+-/1233-+*(&" 5==> i"#$%&()*+-.$%%# 8?3Nff4f42 ̐ 1>   !"#$%&%&+--./0/-+(%"   !$'+,*))('̛#!   !#%')+,.024631/.,*('7 8   !"#%&'(*+,&''%" A ̃0ff4frr:r:5 ̔fghijklmopqrstuvwwxxyzzf}rooqrtuvxy{|}̔~{wtqmjinqtf|ij̛̇~|{ywvusrqonmljihfghrgjmpswz|~̙f}w}{ywuspnlkigfhikllmnopqrrstuwwxyz{||}z̄̍zp̃4rr:rϙϙNN5 ̐ 1>   !"#$%&%&+--./0/-+(%"   !$'+,*))('̛#!   !#%')+,.024631/.,*('7 8   !"#%&'(*+,&''%" A ̃4ϙϙNf444 "C  !"#$%&'(( //0121/-,*(%"   5G$')):2'&$#" %7  "$&(*,./1357420.,+)'%31   !"#$%&()*(&$"?*f4r::7fghijklmnopqstuvwxxyzz{{fsppqstuwxz{|~ltr̕~{wtpmlmqz}̘z̊̈̆~}{zyvusrqpnmljihgfgfojmptwz}f}{ywtrpomkjhfgijlmnoppqrstuvvwxyz{{|}~̃k}wof.r:NN7 "C  !"#$%&'(( //0121/-,*(%"   5G$')):2'&$#" %7  "$&(*,./1357420.,+)'%31   !"#$%&()*(&$"?.Nff4f47   !"$%&'()*++212320-+**(%"   @ #&%1N9$"!  ;F !#)+-/13466420.,*(&$ )G   !!"#$%&&'()(&#!#ff4frr:r::fghjklmnopqrstuwxyzz{|yvtqprstvwyz{}~y|~zwtovy}̘̉̆̄~}{zyxvtrqpnmlkihgfg̀jmqtwz}kr~xvtrpnlkigfhikmnopqrstuuvwxyzz{|}~f|wfv~u'rr:rϙϙNN:   !"$%&'()*++212320-+**(%"   @ #&%1N9$"!  ;F !#)+-/13466420.,*(&$ )G   !!"#$%&&'()(&#!'ϙϙNf448   "#$%&')*+,-.BH22345420.,*((' "##"!  ̯;:  "5*,.02467641/-+*(&$" ̷  , !"#$%%&'()** *B ̆ %f4r::;ffghjkmnopqrstuvwxyzz{||zwurqrsuvwyz|}~giǵ}zssrggikflṅ̄̀~}|zyxvutqpomlkihgf̯fhknqtwz}f}{y̷romljhggijlmoqrrstuvwxyyz{|}~f̓t ̆rkjj)r:NN;   "#$%&')*+,-.BH22345420.,*((' "##"!  ̯;:  "5*,.02467641/-+*(&$" ̷  , !"#$%%&'()** *B ̆ )Nff4f49  !"$%&'()*+,./010/14456530.,*(&& # & !!'  #? (E+-/13579641/-+)'%#!  .HI"#$%%&'()**+,<@'%" ̂#ff4frr:r:<fgghjkmnpqrstuvwxyz{{|}{xvsqrtuvxy{|}hig}̆zvv̉su~̍̆̂~}|{{zyxwutsqomlkih̓ffggihhknqtwz}叫~|zxvusmkigfhikmnpqstuvwwxyz{|}}~w}{xml̂'rr:rϙϙNN<  !"$%&'()*+,./010/14456530.,*(&& # & !!'  #? (E+-/13579641/-+)'%#!  .HI"#$%%&'()**+,<@'%" ̂'ϙϙNf44:    !#$%'()* /02332146787531/-+(&%̲́(D9&CIEE  "$&;,.024688641/,*)'%#!   !"#$$%&'())*+,-9)'$"$f4r::=fghhjkmnpqstuvwxyz{|}}|ywtqstuwxz{|~fr̅frź̖̓~̫fjl~}ikzyxwvuutsqpokjfgighknqtwz~̉~|zxvtrpnhgghjlmoqrtuvwxyz{{|}~́|zuonffin(r:NN=    !#$%'()* /02332146787531/-+(&%̲́(D9&CIEE  "$&;,.024688641/,*)'%#!   !"#$$%&'())*+,-9)'$"(Nff4f4<  *?2!#$&'(*+,"+123456547898531/-+)' F@2& . !$%')+-/135798641/,*(&$"    !"##$%&'(()*+,--..-+)&$! (%ff4frr:r:?fgghijkmnprstuwxyz{||}}~}zxurstvwyz{}~of̒̇́|{}fz~}|{fuxwvuutsrqpponlkhgfgf}ghknqtx鄇}{ywusqonljfhiklnpqsuvxyyz{|}~̃fuwupj)rr:rϙϙNN?  *?2!#$&'(*+,"+123456547898531/-+)' F@2& . !$%')+-/135798641/,*(&$"    !"##$%&'(()*+,--..-+)&$! ()ϙϙNf44>  8B"#%&')*,-.3JB3456788769:;:86420.%̇ 4M+&CI -J !$')*,.02468:8631/,*(&$"   !!"#$%&'(()*+,--./0/-*3) 6 &f4r::Afgghijkmoprsuvwxy{|}}~{xvssuvxyz|}wvǧ̆~̀~}{zyykttsrqpponmlkkjifg̔hknquxl|}{ywusqomkigghjlmoprtwyz{|}}~̇fhj̅̂wrsrrs*r:NNA  8B"#%&')*,-.3JB3456788769:;:86420.%̇ 4M+&CI -J !$')*,.02468:8631/,*(&$"   !!"#$%&'(()*+,--./0/-*3) 6 *Nff4f4?  b"$%&()+,-.01,3456789:;;:9;;<;86420.̊!  ̅.< 4!$'*,-/13579;8631.,*'%#!   "#$%&&'()*+,,-./011/,*̈0KE 'ff4frr:r:Bfghhijkmoprsuvxyz{|}~|ywttuwxy{|}ȉ̈~}|{{zxxwvuttsrqpoonmlkjjihgfhff̄gghknruf~|zxvtrpomkiggiklnpqstvhk|}~̈f̉yvstutt+rr:rϙϙNNB  b"$%&()+,-.01,3456789:;;:9;;<;86420.̊!  ̅.< 4!$'*,-/13579;8631.,*'%#!   "#$%&&'()*+,,-./011/,*̈0KE +ϙϙNf44A  !#$%'(*+,./012356789:;<=>=<;=;9 ̅;;&$"!   *F!$(+-/02468::8631.,)'%#!   !"$$%&'()**+,-./00121̌-IT=̆(f4r::Dfhhiijkmoprsuvxy{|}~}ztuwxz{|~oym̄~{zyxwvutssrqponnmlkjjihijlmojghilor̐~|zxvtrpnljhfhjkmoprtuwv}̊̍}xvuvwjnww̆,r:NND  !#$%'(*+,./012356789:;<=>=<;=;9 ̅;;&$"!   *F!$(+-/02468::8631.,)'%#!   !"$$%&'()**+,-./00121̌-IT=̆,Nff4f4C ̩ "#$&')*+-./12345679:;<=>?@̘??=;94/*A$'$#"##"!!     5;!%(+.024579;:8531.,)'$"   -E2 !! &'(()*+,-.//0123.+)&:>%)ff4frr:r:Efjhijjkmoprsuvxy{̩yxwwyz{}~̏̕~|ywvtssrqponnmlkjiiklnpqstvrhghiilux}kmwusqpnljhgijlnoqstvfvfvs̔~|zwuwxyymy-rr:rϙϙNNF ̩ "#$&')*+-./12345679:;<=>?@̘??=;94/*A$'$#"##"!!     5;!%(+.024579;:8531.,)'$"   -E2 !! &'(()*+,-.//0123.+)&:>%-ϙϙNf44C ̫!"#%&')*,-.013456789:;<>?@A?@ȂA2/-+)'%$$#%$##"!"!     "%(+.13578:<:8530.,)'$" 0  >? !"#,('()*+,,-./01231/-+(&#! 8O*f4r::Efijkkmop ̱~~}}||}̏~|ywutsrqponmmlkjlmoprsuvxz{}ysmihiiorux{}kusqomkiggikmoprtuwxfz~|yryz{{{{{{.r:NNF ̫!"#%&')*,-.013456789:;<>?@A?@ȂA2/-+)'%$$#%$##"!"!     "%(+.13578:<:8530.,)'$" 0  >? !"#,('()*+,,-./01231/-+(&#! 8O.Nff4f4C̈!"$%&()+,-/02346789:;<=>?@ABBA@>>? ̌'&&%$%&%%$##$#""̝   "%(+.1468:<<:8530.+)'$"7N  9 !"## (CC)**+,-./011234420.,*(%# ,&<+ff4frr:r:Filjjklm̹xy{|~f ̃f~|z̜qponmmlmnpqstvmz|}{uojihiiloruy|~f̝rqomkighjlnoqstvxy{~fr}{f{|}}}}/rr:rϙϙNNF̈!"$%&()+,-/02346789:;<=>?@ABBA@>>? ̌'&&%$%&%%$##$#""̝   "%(+.1468:<<:8530.+)'$"7N  9 !"## (CC)**+,-./011234420.,*(%# ,&</ϙϙNf44C !"#""!  !#$%'(*+,./1235689:;<=>?@ABCB@?=<#;97520̋'&&%''&&%$%&%̢  "?< !#$"  "%(+.2579;=<:8530.+)&$"?@ABCB@?=<#;97520̋'&&%''&&%$%&%̢  "?< !#$"  "%(+.2579;=<:8530.+)&$"/  #%&''&&(##$&')*+-.01245689:<=>?@ABCDCA@>=8I 97531/-*))(''&')(('&&'(5O2&%"  '>A'(*+)#  "%(+/258:<><:7530. $!   !#$%&&'()*+,,-./0123345631/-,*('$"#̉ ff4frr:r:Agmmfmoprsuvxy{|~fzf}ikf|zxusprtvxy{|~n}wqlkjilosvy|fqz{ywusrpnljhhikmoqrtvwy{|~|{|}~}znzzffy$rr:rϙϙNNA/  #%&''&&(##$&')*+-.01245689:<=>?@ABCDCA@>=8I 97531/-*))(''&')(('&&'(5O2&%"  '>A'(*+)#  "%(+/258:<><:7530. $!   !#$%&&'()*+,,-./0123345631/-,*('$"#̉$ϙϙNf44?̞2M  "$')*++(CM()*,-/0134578:;<=>@ABCDEDDB@?=<@7;:8531/-+**))('')*) ()**?"))'%" %̛ !#$&()+./120*$  "%),/258;=?<:7520.5$!   "$%&'()**+,-./011234567420.,*)'%$!G(#f4r::Bg̗mopri}vxy{|~njtqr̚y|~̔ysmlkjjmpsvy|f}{ywusqomkighjlnpqsuvxz{}~|}~~zwv̭vvfxvu'r:NNB̞2M  "$')*++(CM()*,-/0134578:;<=>@ABCDEDDB@?=<@7;:8531/-+**))('')*) ()**?"))'%" %̛ !#$&()+./120*$  "%),/258;=?<:7520.5$!   "$%&'()**+,-./011234567420.,*)'%$!G('Nff4f4?̹ -; 3 "$&(+-./=".--,,-/0234679:;=>?@ABCEFEDCA@>=;:8986420.,,+**))()+++3)*,+*(%"?JC!#%(*,.02368982,&  "&),/258;>><:7520-/HI!   !#$&(()*+,-../012345567531.,+)'&$"!  *FQ$ff4frr:r:B̹lrnnopfvxy{}~̣v}zz|}̜ztnmlklnpsvy|̖~|zxvtsqomkigikmnprtuwyz|~}~{xtrr(rr:rϙϙNNB̹ -; 3 "$&(+-./=".--,,-/0234679:;=>?@ABCEFEDCA@>=;:8986420.,,+**))()+++3)*,+*(%"?JC!#%(*,.02368982,&  "&),/258;>><:7520-/HI!   !#$&(()*+,-../012345567531.,+)'&$"!  *FQ(ϙϙNf44: ̖&F!"$&(*,/1321235689:<=?@ABCDEFGGFECB@?=<:9776420.--,̍*))+-#A+-..-*( ;  "$')+-/1368:>@?93-'!   ),/259<97520+6<$!   "$%'(*+,,-./0123345678641/-+)(&$#! &f4r::=gkrqlm̖vxy{}~̥̋̒|vpoonmmnprtwz}j}̑~|zxvtrpnljhhikmoqstvxy{}~~}yurnm*r:NN= ̖&F!"$&(*,/1321235689:<=?@ABCDEFGGFECB@?=<:9776420.--,̍*))+-#A+-..-*( ;  "$')+-/1368:>@?93-'!   ),/259<97520+6<$!   "$%'(*+,,-./0123345678641/-+)(&$#! *Nff4f49  ̜ 2!"$&(*,.35676655789;<>?@BCDEFGHHGFFDCA@>=;9865531//-,,+**+-9--./00/-*(%#!!"$&(*,.0579;=?BC;5/) - 3*-0369<=<9742-+(&#!  !#$&()+,-./001234567787520.+*(&%#! ́    !ff4frr:r:< gkq̛noprsvxy{}~̙̓̔u̡̪fu}wqppfyonnnmoqrtvxz}f}̤̔~{ywutrpnljhhjlnprsuwxz|}~̂opqjqlqq%rr:rϙϙNN<  ̜ 2!"$&(*,.35676655789;<>?@BCDEFGHHGFFDCA@>=;9865531//-,,+**+-9--./00/-*(%#!!"$&(*,.0579;=?BC;5/) - 3*-0369<=<9742-+(&#!  !#$&()+,-./001234567787520.+*(&%#! ́    %ϙϙNf448̡  !"$&'),.2479:;:;<>?ABCEFGHIIHGGFECB@?=<:976431//.--,,++-/0/..12211/-+(&#!"$%'(*+-0241+?ABCEFGHIIHGGFECB@?=<:976431//.--,,++-/0/..12211/-+(&#!"$%'(*+-0241+????>>@ABDEGHIJJIHGFDCA@><;986532100//.--,,-/010143320-+(&'(*+-.01357*IBDFHJHB<82,;@ &: $A:*.145667742/-*(&#! + 0J!"$&')+,.01233456789642/-+)'̕ !  6d ff4frr:r:4́ ̦ziovupooprsuvxy{}~̖fk̘l̨̢̡ztřprtvwy{|~k{̞}{yvusqomkihjff|suvxz|}fzft̢f̃ftusuvxyzzxt| rr:rϙϙNN4́ ̺   !#$&()+02468;=>????>>@ABDEGHIJJIHGFDCA@><;986532100//.--,,-/010143320-+(&'(*+-.01357*IBDFHJHB<82,;@ &: $A:*.145667742/-*(&#! + 0J!"$&')+,.01233456789642/-+)'̕ !  6d  ϙϙNf44<̮ !#$&()+/1468:"#%'(*,-/0234567789:97520.,)'&$/!0(:f4r::?̮iouxsopprsuvxy{}~̖f֯suklfox̜pp̧̡̮̎|vsrrrqstvxz{}̛̏̈}{xvtrpn̡ysuwy{|~o̕fi̇f̖uwyz|}~~|w"r:NN?̮ !#$&()+/1468:"#%'(*,-/0234567789:97520.,)'&$/!0(:"Nff4f4A̫ !#$&()-/1358:<>@B+G@GIJKLKJ JIIGF4 ><;986654332211'̦520/1245%?;=>@BDGIMOOLIF@:7/)#   !#%(..//012100-*(%#!: 9!"$&')+,.013456789:;:8631/,*&$6BS 5A$" -HD ff4frr:r:Ḓhntzvqpqrsuvxy{}~̓lmofvɛ̧̡̳̕}ttsssrrsuwp|~̈y̘}{xljhikmurtvxz{}̍~f̓xy{|~́{$rr:rϙϙNND̫ !#$&()-/1358:<>@B+G@GIJKLKJ JIIGF4 ><;986654332211'̦520/1245%?;=>@BDGIMOOLIF@:7/)#   !#%(..//012100-*(%#!: 9!"$&')+,.013456789:;:8631/,*&$6BS 5A$" -HD$ϙϙNf44< !#%&(*-/13579<>@BDJJKLLMLK #/JIH2M?=<:98765543322%BJB//13455 .%9:98535689;4@̝DFHJLNPQNKHEB940*$ !< $$ +,,--.-+(%#   7  !#%&(*+-/02457899:;;964̜&%#!8 !"%A@$#!3 ̄#f4r::?fmzytpqrsuvxy{}~̓̄qzfx̥p̷̜̠̋̚yuutstvwg~̇̊̋s̑}{xvsqomkihjlmosuwxz|~f|̜̙|xzf̂ff̄'r:NN? !#%&(*-/13579<>@BDJJKLLMLK #/JIH2M?=<:98765543322%BJB//13455 .%9:98535689;4@̝DFHJLNPQNKHEB940*$ !< $$ +,,--.-+(%#   7  !#%&(*+-/02457899:;;964̜&%#!8 !"%A@$#!3 ̄'Nff4f4=!= !#%&(+-/03579;=@BFHJMNNOMLL <*KJIGF.A<;:98876554432;110/1356(#:;<:89;<>?ADEGHMORTVSMJGĎ630,&3AO!%'"E*()) +,+*(&#   "$%')*,./134689:;<<:753-IT'%#"  "##$%&%$"!"$ +%ff4frr:r:@̈y{wrqrsuvxz{}~̴̭̒ẹ̴̴̠̑̐f̊̀zuvxż̙̌j̬fsꐐfz}{xvsqomkiijlnprtuwy{}~ȳ}{|fõ})rr:rϙϙNN@!= !#%&(+-/03579;=@BFHJMNNOMLL <*KJIGF.A<;:98876554432;110/1356(#:;<:89;<>?ADEGHMORTVSMJGĎ630,&3AO!%'"E*()) +,+*(&#   "$%')*,./134689:;<<:753-IT'%#"  "##$%&%$"!"$ +)ϙϙNf44:̰̃"@ "  !#%'(,-/02469;FHJLNQRRSNNM=!KIHFECB@?;::9887655443221356878;<==>?ABDEGHJKMNPQ̔XURLJGD852/!6"&))&7J% )W))('&1K  !#$&()+-.023578:;<=:8641;>(&$" !"#$%&''! :1 "#%&$/L<'f4r::=̮̃gxfsrrsuvxz{}̒fk̢̬̱f̡̖̳ḟ̞wwvwyz|̜̈̍̌̀fq̽썍hz}zxvsqnljhikmoqrtvxz|}|ff̈~}l+r:NN=̰̃"@ "  !#%'(,-/02469;FHJLNQRRSNNM=!KIHFECB@?;::9887655443221356878;<==>?ABDEGHJKMNPQ̔XURLJGD852/!6"&))&7J% )W))('&1K  !#$&()+-.023578:;<=:8641;>(&$" !"#$%&''! :1 "#%&$/L<+Nff4f4<'(C  !#%'*,-/12468:GEHJLNPRUVVWNMLIGFDCA?>=;::98776554432213 ":99;=>̢GIKLNO TUWX[ZROIF741+("!(*,(&" >?%&&%%$$##A?   "#%'(*,-/124679;<>;97420-8)&$"!!#$&&'()3AF"$%''&#>?*ff4frr:r:?gk̏suvxz{}̐g̵̢̭̯rṿ̤pr̸̯Zy̝̒}xxwxy{}̝̀̎̎̉̋h}̧}zxusqnljhjlmoqsuwyz|~̊fk||e.rr:rϙϙNN?'(C  !#%'*,-/12468:GEHJLNPRUVVWNMLIGFDCA?>=;::98776554432213 ":99;=>̢GIKLNO TUWX[ZROIF741+("!(*,(&" >?%&&%%$$##A?   "#%'(*,-/124679;<>;97420-8)&$"!!#$&&'()3AF"$%''&#>?.ϙϙNf449̶́)?  "#%'*,-/12468:<>EGILNPRTVYZZ[YOONMMLKFECB@@?>=<;::98776554433%BA:;:<>?@ABČLN"6XZ]ZWT̂EB̉630-+($ "'+.,)&D7""##1:!! 8  !"$&')+,.013568:;=:8531.,*'%#!!#%&'()**62  "#%&')('%",f4r::<̯́wnvssuvxz{}̢̥̭̑ǐ̤~̂̋~yyxz|~́̍̒̏̈f̝̈f{̟}{xuspnliijlnprtvwy{}̠̊h0r:NN<̶́)?  "#%'*,-/12468:<>EGILNPRTVYZZ[YOONMMLKFECB@@?>=<;::98776554433%BA:;:<>?@ABČLN"6XZ]ZWT̂EB̉630-+($ "'+.,)&D7""##1:!! 8  !"$&')+,.013568:;=:8531.,*'%#!!#%&'()**62  "#%&')('%"0Nff4f45̷ )  "#%)*,./13468:<$BEGIKMPRTVXZ]^^QONMLJIFDBBA@??><<;:99877655443'=<<=>@ABCDGH̚3SVXXSPMJD>;630-*'$!$(-/)&.J !E@   !#%&(*+-/024579:<;9641/-*(&$" %&'()*+*,CB!!"$%'()+*)'%!E,ff4frr:r:8̹jpv|yttuvxz{}̸̧̬̣̣̏̊vx̰̹̫̥̜zzyy{|~̂̏̓f}̐̉f̔̅j̃}{xvsqnkiikmoqrtvxz|}̜́fnvx0rr:rϙϙNN8̷ )  "#%)*,./13468:<$BEGIKMPRTVXZ]^^QONMLJIFDBBA@??><<;:99877655443'=<<=>@ABCDGH̚3SVXXSPMJD>;630-*'$!$(-/)&.J !E@   !#%&(*+-/024579:<;9641/-*(&$" %&'()*+*,CB!!"$%'()+*)'%!E0ϙϙNf442   "$%)*,./134689<@BDFIKMOQTVXZ\^!PONLKIHDCBBA@??>=<<;:998776654579:>?ABCD';IJK8M̃SSŖJGA>;852/,)&# !#%*.01<)̇ <>:   "$%'(*,-/124679:997620.+)'$"  .,&')*+,,+*(&%" !#%&')*+,+*)'% -f4r::5 fiou||wtuvxz{}̦̏f̨̪̤́ņ̧{{z{}̅̐̔|̢̢̠̐̆́̀~{ywtrojlmoqsuwxz̙̀f|1r:NN5   "$%)*,./134689<@BDFIKMOQTVXZ\^!PONLKIHDCBBA@??>=<<;:998776654579:>?ABCD';IJK8M̃SSŖJGA>;852/,)&# !#%*.01<)̇ <>:   "$%'(*,-/124679:997620.+)'$"  .,&')*+,,+*(&%" !#%&')*+,+*)'% 1Nff4f4: ̻#"$%')+, 34689=@BDFHJMOQSUXZ\^^:F0POOMLJIGFEDDCBAA@?>>=<<;:9987766579;<>ACDE;B2JKLMNPRMC@=:741.+(%" "$-/24 @-̋#7A  !"$&') .0135689876530.,*(%#! !)EH')*+,-.,*)'%# !"$%'()+,-.-,*('$!,ff4frr:r:= ̻fiou{~zuuvxz{}f{fŗ̤̠̪}f̩}||~̆k̓i̦̔̌l̀~~~{yomjlnprsuwy}~pr̗t0rr:rϙϙNN= ̻#"$%')+, 34689=@BDFHJMOQSUXZ\^^:F0POOMLJIGFEDDCBAA@?>>=<<;:9987766579;<>ACDE;B2JKLMNPRMC@=:741.+(%" "$-/24 @-̋#7A  !"$&') .0135689876530.,*(%#! !)EH')*+,-.,*)'%# !"$%'()+,-.-,*('$!0ϙϙNf44<4J"$&')+,'=2568:=?ADFHJLNQSUWY[[\]"QPPONLKIHGGFEDDCBAA>=<;;:99877679;=>@ACDEFG7I$SVXZXMIGG&C@=:741.+'$"!#%.13542́F1>   !#%&(''024578765431/,+(&$! !"$%;')*+-.//-+*(&$!#$&')*+-.//.-,*('#,f4r::?gntz}xuvxz{}f|ḳ̈uzn̩|̳f}~}~̇f́̕~|}}}}||{~ywtromlnprtvw{h|fu̓0r:NN?4J"$&')+,'=2568:=?ADFHJLNQSUWY[[\]"QPPONLKIHGGFEDDCBAA>=<;;:99877679;=>@ACDEFG7I$SVXZXMIGG&C@=:741.+'$"!#%.13542́F1>   !#%&(''024578765431/,+(&$! !"$%;')*+-.//-+*(&$!#$&')*+-.//.-,*('#0Nff4f46 B>"$&')+,7C3568=?ACEHJLNPRUWXYZ\VRQPOMLJIIHGFFEDCC$:?>>=<;;:998779;=>@BCGIKNPRN8]`_[WLH4QA?<96+̑"%')@A46753 ̌  - "#%' $@H12467654320/-,*('%"  !"$%&()*+-./0/.,*)'%$%'()+,-/0100/-+*(&ff4frr:r:9hnsz{vwxz{}̨ụüǵj̭{̵¾̲^{h̑̉o̧ ̈~fizzy|~̀~{yvtromnprtzfyfprr:rϙϙNN9 B>"$&')+,7C3568=?ACEHJLNPRUWXYZ\VRQPOMLJIIHGFFEDCC$:?>>=<;;:998779;=>@BCGIKNPRN8]`_[WLH4QA?<96+̑"%')@A46753 ̌  - "#%' $@H12467654320/-,*('%"  !"$%&()*+-./0/.,*)'%$%'()+,-/0100/-+*(&ϙϙNf44:̾  E "$&()+-c3568;=?ACEGILNPRTUVVWWX̂[URQONLLKJIIHGFFED7F@@?>==<;;:9989;=?@BGJLORTWY?efb^ZS><99M@'$!!&(*-13689755̋6J  "B@!"$&')+;0135544321/.,+)(&%#! !#$%&()*+-./120/-+*(&&')*+-./123210/-+*('&f4r::=̺gmsy~ywxz{}̃ʃ̢̂y̧̮̹h̤ǎ̗̄~f}xwwy{}̄~{yvtrooqsvxzm̡*r:NN=̾  E "$&()+-c3568;=?ACEGILNPRTUVVWWX̂[URQONLLKJIIHGFFED7F@@?>==<;;:9989;=?@BGJLORTWY?efb^ZS><99M@'$!!&(*-13689755̋6J  "B@!"$&')+;0135544321/.,+)(&%#! !#$%&()*+-./120/-+*(&&')*+-./123210/-+*('*Nff4f4=̂ # "$&()+.023578<=?ABEGIKMPRRSSTTUVWXYTSRRPONMLKKJIHHGFFED C@@?>==<;::99;=?@CE  UWZ\a̬a`]VR:?;7665,)&# !%'),.2579;:87<̌' :  :!#%&(*+/023432210/-,*)'%$"! !#$%&()*,-./12 ̐,-/013443320 ),ff4frr:r:@̂glrx~|wxz|}̢̧̼́̿̕sq̬̼g̡̥̙̣̓̒̇~{̡uuttxzʁ~{ymtroqsuwy{̀̕ ̆qsq0rr:rϙϙNN@̂ # "$&()+.023578<=?ABEGIKMPRRSSTTUVWXYTSRRPONMLKKJIHHGFFED C@@?>==<;::99;=?@CE  UWZ\a̬a`]VR:?;7665,)&# !%'),.2579;:87<̌' :  :!#%&(*+/023432210/-,*)'%$"! !#$%&()*,-./12 ̐,-/013443320 )0ϙϙNf44?   "$&(*-/02357:<=?ABDFIKMOOPPQQRRTTWWTSRQPONNMLKKJIHHGFEEDCBA@@?>==<;;:;=?ACFHKA'UX VTQ̭WYYSP!B>:6200,)&#  *-/468:=<: %>8C#   "/  !#%'(*,/123210//.,+)(&%#"  !#$%&()*,-./1235421/-,**+-./5655432'+$f4r::Bglrx~̇zxz|̧̧̠̺̓̽q̨̭̺̒hk̚q̤̞̊~xursvx|}~f{trqsuwy}̄̕fx|ȗ(r:NNB   "$&(*-/02357:<=?ABDFIKMOOPPQQRRTTWWTSRQPONNMLKKJIHHGFEEDCBA@@?>==<;;:;=?ACFHKA'UX VTQ̭WYYSP!B>:6200,)&#  *-/468:=<: %>8C#   "/  !#%'(*,/123210//.,+)(&%#"  !#$%&()*,-./1235421/-,**+-./5655432'+(Nff4f48 "  "$&(*-/02457:<>?ABDFHJLMMN OOQUVTSRQPPONMMLKKJIHHGFEEDCA@??>=<<;;=?ACFHK9̳5:GEEFLOROIDA=952.*(%"" &$/37:<>?=!E(&#   "" (FA  "$&')+.01210/.-,,*)&"! !"$%&()*+-./0234775420/-,-/01+7876553$@D #ff4frr:r:;gkqw}̈}xz~̡̓oq̷fvx̧̻̳~̸̭̳̰̪̑r̞g̫̍{xrqswyz|~fqtqsuw{}̔fxv̝ 'rr:rϙϙNN; "  "$&(*-/02457:<>?ABDFHJLMMN OOQUVTSRQPPONMMLKKJIHHGFEEDCA@??>=<<;;=?ACFHK9̳5:GEEFLOROIDA=952.*(%"" &$/37:<>?=!E(&#   "" (FA  "$&')+.01210/.-,,*)&"! !"$%&()*+-./0234775420/-,-/01+7876553$@D 'ϙϙNf44: ! "$&(+-/024579:<>?ACDFHIJJK.&M %9QRSTSSRQPPONMMLKJJIHGGFEEDCA@??>=<<=?ADFIKIF̅DEFD̦EB?<:741)%%" BF18;=?A@CFA̶&# 5!"$"; !"$&()+.0/.-,+*)(+G  !"$%&')*+,./023468:875420//123>?̈765,;0/f4r::=gkqw̃||~̒ffo̧̹̺̫̦̅j̫̐j̨̧̟~|yfxuwy{|~ff́yvtsuy{}̕fẅr:NN= ! "$&(+-/024579:<>?ACDFHIJJK.&M %9QRSTSSRQPPONMMLKJJIHGGFEEDCA@??>=<<=?ADFIKIF̅DEFD̦EB?<:741)%%" BF18;=?A@CFA̶&# 5!"$"; !"$&()+.0/.-,+*)(+G  !"$%&')*+,./023468:875420//123>?̈765,;0/Nff4f4<   "$&*,-/124679:<>?ACDFGGHH -IGF:H+PQRSSRQQPOONNMLLKJJIHGGFEDDCAA@??>==?BDEB@AABBC̱EECA<;(0*'$!"$:07:>ACDGKJA;*'% F3J!#$$!!#%&(*,//.--()('&$<>!"#%&'(*+,./013457:=<:8713457:9;::9̃1+ff4frr:r:?gjp|z|~̭̐tf̶̨̧̢̺̱̪e̢̪f{̧̡̝̐̊󐎋ñ~vp̬uwy{}~fz̃~{yvtxzfm̕f}̢jlñ/rr:rϙϙNN?   "$&*,-/124679:<>?ACDFGGHH -IGF:H+PQRSSRQQPOONNMLLKJJIHGGFEDDCAA@??>==?BDEB@AABBC̱EECA<;(0*'$!"$:07:>ACDGKJA;*'% F3J!#$$!!#%&(*,//.--()('&$<>!"#%&'(*+,./013457:=<:8713457:9;::9̃1/ϙϙNf44: !"$(*,-/124679;<>@ABCCEFF*HIIJ LMOPRQPPOONMMLKKJIIHHGFFEDDCA@@?>>>??@ AABB!̰2?=<58;<0O+)&#  '+.59?=;:.35679:;=<;::9865 #f4r::=gjp|xz|~̵̨̬̮̯̹̥̎̇s̰̦̣f̢̜fx̢̛̲̪̒̃̎f̜{x̢uwy{}̝̈~{yvxzf̔f{̞f~ 'r:NN= !"$(*,-/124679;<>@ABCCEFF*HIIJ LMOPRQPPOONMMLKKJIIHHGFFEDDCA@@?>>>??@ AABB!̰2?=<58;<0O+)&#  '+.59?=;:.35679:;=<;::9865 'Nff4f49!"$(*,./124679;<>??@@ACDEFGHIJKLMNQRRQPPONNMLLKJJIIHGGFEEDCCBBA@@?>=>̊!6AB%$#! !#$&'()+,-.0124568:=@B@?.KV789;<=>==:9865Q ff4frr:r:<giu{zxz{}̷̩̬̭̰̎̊~̅j̢ẑ̤̝̏mr̯̉̚q̪}xutvwy{}̃̊t~yvxzș̄f{w} "rr:rϙϙNN<!"$(*,./124679;<>??@@ACDEFGHIJKLMNQRRQPPONNMLLKJJIIHGGFEEDCCBBA@@?>=>̊!6AB%$#! !#$&'()+,-.0124568:=@B@?.KV789;<=>==:9865Q "ϙϙNf448 !#&(*,./134689;;<<==>>@BBABBCDEEFHIJKLOPQQPOONMMLLKJJIHHGFFEDDCCBAA@??>=>>?̇AB ?@?#;<;986)f4r::;fgo{}zxy{}̵̧̩̪̮̍ż̢̥̂̔̃̌fv̛d̬̲̑̊}zwuvxy{f}̃̏fk~{yxz̜̟̑̂fpy̠n-r:NN; !#&(*,./134689;;<<==>>@BBABBCDEEFHIJKLOPQQPOONMMLLKJJIHHGFFEDDCCBAA@??>=>>?̇AB ?@?#;<;986-Nff4f42̪(@ $&(*,./134678899:;;>?@@?@ABBCDFGHIKLNPONNMMLKKJIIHGGFFEDDCBBA@@?>==>>??4@̄A?̣8E.-,+*(%$'! #'#<6:9EH̍SNLF;I964̰)&#!K "$'))9 "$&()('&%#""!  "#%&()*,-.804678;>@CFGECA@>;<=?@AA@6B&ff4frr:r:5̧fg̎z|ywy{}̵̧̤̬̦̣̋̄f̫f̋̇h̵̢̠̭̍́~{xvxzfu̱̎f̃~{y|~̏̊́~k̡*rr:rϙϙNN5̪(@ $&(*,./134678899:;;>?@@?@ABBCDFGHIKLNPONNMMLKKJIIHGGFFEDDCBBA@@?>==>>??4@̄A?̣8E.-,+*(%$'! #'#<6:9EH̍SNLF;I964̰)&#!K "$'))9 "$&()('&%#""!  "#%&()*,-.804678;>@CFGECA@>;<=?@AA@6B*ϙϙNf445 ̡ 2@ "$&(*,.0134455677889;<>?>>??@ABDEFHIJKMNOPONNMLLKJJIHHGGFEEDCCBAA@@?>==>>?>>=7̥<:92?,*)(B" !$(7A;BFJ̌VQNLF>;8̲,)&#1=!"&(*+$>@ "$&'&&%$#!  !#$&')*+-./2B678:>?ABCBBA8??><; f4r::8 ̞oź~{xwy{}̡̥̪̤̥̠̥c|̨̅x̷̩̭̤̱̌̄~{uvxz|̗̌̋~{}̈}~{̩̤$r:NN8 ̡ 2@ "$&(*,.0134455677889;<>?>>??@ABDEFHIJKMNOPONNMLLKJJIHHGGFEEDCCBAA@@?>==>>?>>=7̥<:92?,*)(B" !$(7A;BFJ̌VQNLF>;8̲,)&#1=!"&(*+$>@ "$&'&&%$#!  !#$&')*+-./2B678:>?ABCBBA8??><;$Nff4f4@̡   "$&(*,.00112334455668:;==<<=>?@BCEFGHJKLMOONMMLKKJJIHHGFFEDDCBBAA@?>=>==<=A-L@̂88̝)'&%$?!%),47;BFJM̊UROLIC=:̭/, !#&(*,)&$! "$##" !"$%'(*+,./0275789;>ADFILLJHFDC@ACDEDCBBA@?>< ff4frr:r:C̠ggms~ftzxwy{}̟m̢̩̦̝̦̩̪̤̲̔̂̅̄̊̚f}̆}wtvwy̍̏~{}̆}~̜̦v$rr:rϙϙNNC̡   "$&(*,.00112334455668:;==<<=>?@BCEFGHJKLMOONMMLKKJJIHHGFFEDDCBBAA@?>=>==<=A-L@̂88̝)'&%$?!%),47;BFJM̊UROLIC=:̭/, !#&(*,)&$! "$##" !"$%'(*+,./0275789;>ADFILLJHFDC@ACDEDCBBA@?><$ϙϙNf44=$: "$&(*,..//0011233479:<'::<=>@BCDEGHIJLMNNMLLKKJIIH !%EEDDCBBA@@?>=<(3<@EEC@?>973%>A#!"&-15GNRSROLIC@=4.?!%'(*.,)&$!""!!  "#%()+,./0134589:=@BEHKNOMFDCEFFEEDCBBA?>-̂f4r::@ggmy}fwwy{}̞̔|̧̍p̧̥ߠ̞̚f̄~̔fx̵̛̹̩̕j̥zwtuwy}̋̔̃~}ff|̇̄~|}m̞ikm̪̂!r:NN@$: "$&(*,..//0011233479:<'::<=>@BCDEGHIJLMNNMLLKKJIIH !%EEDDCBBA@@?>=<(3<@EEC@?>973%>A#!"&-15GNRSROLIC@=4.?!%'(*.,)&$!""!!  "#%()+,./0134589:=@BEHKNOMFDCEFFEEDCBBA?>-̂!Nff4f49 6F "$&(*,/-+,,--.+/0012568 +ID9:;=<<;;@BGEDCB+̂97E)'%!$*.2 *;DLONMKHB@=:71.+?@ 2#%'),..,)&!,G !#)*,-/0134569:=<<;;@BGEDCB+̂97E)'%!$*.2 *;DLONMKHB@=:71.+?@ 2#%'),..,)&!,G !#)*,-/0134569:?ABCDIKLMLKKJIIHH!=EDDCBBA@@>=::?9D;2DCBA$A;/@'%#5I #),/@?BI̿KJIEB?<960-%" .K!#%'+,.0.,)$!>?!"-D*+-.01245679;=@CFHKNQT,HOJIIJIHGGFEDDC<̂!f4r::9 fflr}yvwy{fm̕v̘䞟̣k̫n̡̧̡̫̊f̦̕y|xy}̯̹̫̗̏́̋|yvsuw{ṳ̇̑̊~}|{|~fx̢fx̯̂%r:NN9  [ "$&(*,.-+)**++-ID-../2456(789;=>?ABCDIKLMLKKJIIHH!=EDDCBBA@@>=::?9D;2DCBA$A;/@'%#5I #),/@?BI̿KJIEB?<960-%" .K!#%'+,.0.,)$!>?!"-D*+-.01245679;=@CFHKNQT,HOJIIJIHGGFEDDC<̂%Nff4f4Ḅ1 "$&(*-.,+)''(()<*+-/124576789;<>?@AC;A!IJKLKJJIIHGGFEDCCBBA@199:>*;@ADCBA@̄;;*(%?5 )%(+18;?FJJHFECA>;930'$! 6<!#$&*,.01.)&$!8 "#??+,./1235679:;?@AC;A!IJKLKJJIIHGGFEDCCBBA@199:>*;@ADCBA@̄;;*(%?5 )%(+18;?FJJHFECA>;930'$! 6<!#$&*,.01.)&$!8 "#??+,./1235679:;@#@#FGHJKKJJIHHGFFEDCBA@5N)9=BGKİGCBBA@̂#4@ @#&)69=;82,&#  "$(*,.0+)&#!1n!= !#$&9*,-/0134678:;<>ACF (B7TWZYWUQOMLKJJIHGG#f4r::< nfkqvx{}zwuwyf{̖̍ơ̜j̩ḟ̪̂f~f}̧̀ztwb̊f̧̜̪̩̘̏̓̍̄~{xusy}̗̏̑~~f||fl{z{}~̠s̷'r:NN< ̦ 5PD "$&(+/.,*('%%&'(()* !/13455689:;<=>@#@#FGHJKKJJIHHGFFEDCBA@5N)9=BGKİGCBBA@̂#4@ @#&)69=;82,&#  "$(*,.0+)&#!1n!= !#$&9*,-/0134678:;<>ACF (B7TWZYWUQOMLKJJIHGG'Nff4f43̳3M 2 "#&),/-,*(&$##$$%%&&'?@(DEGHIJJIIHGGFFEDDCBA@?6=?DHIHHG̅CBAA:̃11̄4M(@%9"%B47:ADCB@=<841/,   &(*,.>-?!"#%&)+,./1245789;<=?BEH9SVX[\ZXTSQONNMMLLJG ff4frr:r:6ujpuwy|zwuwx̨̛̙̖̙̪̥̯̘̊̆̅̃̄j֦̋}{ỉ̟f̧̛̩̦̤l̛~̆~{swy}f̍fg~ffw{{z̤y̔xxwz|~̹̻̐m$rr:rϙϙNN6̳3M 2 "#&),/-,*(&$##$$%%&&'?@(DEGHIJJIIHGGFFEDDCBA@?6=?DHIHHG̅CBAA:̃11̄4M(@%9"%B47:ADCB@=<841/,   &(*,.>-?!"#%&)+,./1245789;<=?BEH9SVX[\ZXTSQONNMMLLJG$ϙϙNf44<+  !$'*-/-+)(&$"!!""##$%=!,.022356789:;<?@BDEFGHJIHHGGFEEDCCBA@? 7;DIIGGF̄@998́1+6)((.)!Hc$':36;: =6431.QA5(*,./7,) !#$&)*,-/0235689;<=>ADGIL8RZ]`^\ZVTT0RQNLIGf4r::?̨fffjptvx{yvuvz|~̛̣̗̇̕f̧̩s̫̮̄́㑜̎̔̐̈\̮Ɋ̧̡̠̣̚fy̷}wtuw{}f̖̃ffú|yxwwvvvuwy{}~̼̏̄!r:NN?+  !$'*-/-+)(&$"!!""##$%=!,.022356789:;<?@BDEFGHJIHHGGFEEDCCBA@? 7;DIIGGF̄@998́1+6)((.)!Hc$':36;: =6431.QA5(*,./7,) !#$&)*,-/0235689;<=>ADGIL8RZ]`^\ZVTT0RQNLIG!Nff4f48 "%(+0.-+)'%$  !"'(*,./012345689=>?BCDEGHIHHGFFEDDCBBA?=77=<́7̄9*(̘C.*J@A!#/2589:=87 >20/.-:> 2Ic*,./$@@?  !"$%'*+-.0134679:<=>@CEHKNQSVY^aa_][YY5Nj)MJHff4frr:r:;fioftwzxutxz|~̗̇̍̓l{̨̥̮̭̄h̘́̄̐ḩ̪̖̞̔̑p̥̠ywtvy{}f̙ʑ̥̊̃̕{yuuttsssrruwy{}̜̐А rr:rϙϙNN; "%(+0.-+)'%$  !"'(*,./012345689=>?BCDEGHIHHGFFEDDCBBA?=77=<́7̄9*(̘C.*J@A!#/2589:=87 >20/.-:> 2Ic*,./$@@?  !"$%'*+-.0134679:<=>@CEHKNQSVY^aa_][YY5Nj)MJH ϙϙNf443  ,B #&),0.,*)'%#  #$%'*+-012345677;=>@ACDEFGHGGFEEDDCBBA@@A8=AFGIHDB́9́2̄A+)̇3/11̾?@ /02345899630.-,+*$!4&(*,..& !#$&(+,./124578:;=>?ADGJMORUX[]cdba__]*GQI< f4r::6 fiopyxuvxz|~̢̖̖̦̦̯̪̖̆̉̐́́̄̑̇t̾fr̞̠̖̊̕|yvtvz{}̛̕ǐ}f̆srqqpsuwy{}̑}̑$r:NN6  ,B #&),0.,*)'%#  #$%'*+-012345677;=>@ACDEFGHGGFEEDDCBBA@@A8=AFGIHDB́9́2̄A+)̇3/11̾?@ /02345899630.-,+*$!4&(*,..& !#$&(+,./124578:;=>?ADGJMORUX[]cdba__]*GQI<$Nff4f40́́ ̼<@!$'*0/.,*(&%! !#$').00123456+D#̟>@ABCDFGGFFEEDCCBA@<<9>GJH̅@2 ́.̄M+*̅ ./́>8 +<--./01455530-*)'%#  #"$&(*,08#$@   !#%&*+-/0235689;<>?@CFIKNQTWY\_bgfeda\YJI ff4frr:r:3́́f̼vwwtvxz|~̖̟̟̤̈̅̎̕kf̮̅ ́̄̑̅r̔́q̢̜̙̔̋̉̄̚~{xrtxzfr̗̉f̊̄f̊sponnnmprtvxz|~̐Ȑ¿y̱ !rr:rϙϙNN3́́ ̼<@!$'*0/.,*(&%! !#$').00123456+D#̟>@ABCDFGGFFEEDCCBA@<<9>GJH̅@2 ́.̄M+*̅ ./́>8 +<--./01455530-*)'%#  #"$&(*,08#$@   !#%&*+-/0235689;<>?@CFIKNQTWY\_bgfeda\YJI !ϙϙNf445 ́ ̥ S "%(+1/-+*(&#! $',.001223455#89:;̆?@ACDEFEDDCBBA=:,#!̄A?Á ́̃'%̅=5̛1/&)**5001112/,̟ &D#%&(*,.-?1>   "$%'(*,-/124679:<=?@BEGJMPSUX[^acfec`]ZWNA;(f4r::8 ́qfhmptstvxz|~̗̉~~̧̠̂̋̒̐̒̄́ ́̃̋̅f̛̉fi̘̖̍fz̛̘fy̟~{xusvxfn̥̉̔̋|̘fpmknprtvxz|~̎ļ̵,r:NN8 ́ ̥ S "%(+1/-+*(&#! $',.001223455#89:;̆?@ACDEFEDDCBBA=:,#!̄A?Á ́̃'%̅=5̛1/&)**5001112/,̟ &D#%&(*,.-?1>   "$%'(*,-/124679:<=?@BEGJMPSUX[^acfec`]ZWNA;,Nff4f42 ̂   #&),0/-+" "$),./0122345567789:=̌ABCEFEEDCCBA><8;=I:2̂ ̃̅1C9̆C$!@+,,-.. -<!%')*,+*' ,+ !"$&+,.013568:;=>@ADFILOQTWY\^acffea^[X*#I&ff4frr:r:5 ̂fglnquvstvxz|~̗ftv̉~||~̣̰̏̌f̡̂ ̩̃̅̆f̩|fģlfv̆}zwtswyz̓̈mz̐̆f̃yffzhilnprtffz|~fnz̰*rr:rϙϙNN5 ̂   #&),0/-+" "$),./0122345567789:=̌ABCEFEEDCCBA><8;=I:2̂ ̃̅1C9̆C$!@+,,-.. -<!%')*,+*' ,+ !"$&+,.013568:;=>@ADFILOQTWY\^acffea^[X*#I*ϙϙNf441 ̃ $  !$'*00.,+ %$" "&)+./0122345567789::<=>BCDEDDCCB@?;7;:#̂&́̋ 9<:I#̷8%&'(>D)*="  5')++I*̊O,̿ 5!#$(-.023578:<=?AEGJLOQSVX[]`bcba`\Y*G@E f4r::4 tffgkmrturtvxz|~̖p̊~|z|~̨̣̍̂́̋o̷̢̟̠~`̋̆ÿ̤|zywtuwy{~̆f̵̑̐̊̂ywfv̿kmoqsufi~ffx̫¿v̫ "r:NN4 ̃ $  !$'*00.,+ %$" "&)+./0122345567789::<=>BCDEDDCCB@?;7;:#̂&́̋ 9<:I#̷8%&'(>D)*="  5')++I*̊O,̿ 5!#$(-.023578:<=?AEGJLOQSVX[]`bcba`\Y*G@E "Nff4f43̂  %(+10.,<#! $&)+./0122344567789:: =>?@ABDCBA?;8?ADFIKNPSUXZ]_a_^]\[WT6=̅8̃$ff4frr:r:6̂fgffjloqstrtvxz|fn̗f̊}{y{~̊́s ́́́́ ̸́̑̋̄~fẋ̡̌̊|yvtuwy}̆q̎̏s̢{yvt̾jgikmoqsug|Áft̪̽̅̃(rr:rϙϙNN6̂  %(+10.,<#! $&)+./0122344567789:: =>?@ABDCBA?;8?ADFIKNPSUXZ]_a_^]\[WT6=̅8̃(ϙϙNf448#  2),1/-,* #! )+./01223445677899:>=>??@ABCB>:8=@?9A=́ ́̄3,̰ : !!"&(%"  +%')́)̈0: : "$%' <./134689;<>?@BFHKMWZ\^]\ZYXWVROL+?"f4r::;ffgfiknprtrtvxz}i̗̇|~fṕ̤̤̣ ́̄̓̏pg̡̀|̆̉̍|vsuw{}̄̑́̈}̀}{xvĠigikmoqsuw}s̢̬fz|̸x̥&r:NN;#  2),1/-,* #! )+./01223445677899:>=>??@ABCB>:8=@?9A=́ ́̄3,̰ : !!"&(%"  +%')́)̈0: : "$%' <./134689;<>?@BFHKMWZ\^]\ZYXWVROL+?&Nff4f4= 8N)01/-+*&$"!":3+./01223445677899:6A̅?@AABCCB=99>@>=3. ́̂́̒*C"-M"&()&#  "#%'('&,:B !"$&'+,.013568:;<=?@AEGJ,?VY[ZYXUTSRQMK'D́!ff4frr:r:@fgihjmoqsrtux{~f̟̖̌~f̨̆jnj̚ ́̂́Ñḧ̪~|̔́̂̉̍}zwuw{}q̊̏̍̍t}zx igikmoqsxy{}̫̑fxú̳%rr:rϙϙNN@ 8N)01/-+*&$"!":3+./01223445677899:6A̅?@AABCCB=99>@>=3. ́̂́̒*C"-M"&()&#  "#%'('&,:B !"$&'+,.013568:;<=?@AEGJ,?VY[ZYXUTSRQMK'D́%ϙϙNf44;̧ !G'*10/-+'&$"  3D)+./01223445677899:-<=>>̔ABDDD!)DA=9:,#><:4́ ̸́%6< &(*)&#.&D!#%&%$#"  9 !#%&(+-/0235789;<=>@ADGIL @@VXWV3QPONMLJ5;CÁ f4r::>̧jjhhiknprrsuy|̗̈̎́ṛ̫̔ý ̸́̋́wvf̜~~̆ffx{xy{}f̍̈̌ӊ̉fp|flpkhgikmoftxz|~̫̒ẖ́$r:NN>̧ !G'*10/-+'&$"  3D)+./01223445677899:-<=>>̔ABDDD!)DA=9:,#><:4́ ̸́%6< &(*)&#.&D!#%&%$#"  9 !#%&(+-/0235789;<=>@ADGIL @@VXWV3QPONMLJ5;CÁ$Nff4f48 ̤ "%(+10.,+'%#" !x)+./01123445 ".99:;;<=>>?@AEF >K@@8;)Hd:4:́́́̄ ̩́ L  +A*,*$#GA1=!##! "; .!#%'(,-/1245689:<=>?ABFHK":UTSR1MWLKJLH B́ff4frr:r:;ffgi̠ijkmoqqsvy|̘̆̍̄ޅp}̬̬f̠́́́̄ ̬́yru̲t}̆q̋jxy{}ẅ̊Շ̆̅fkfi̡romjhgikmff̔xz|~̬̻̒|̮nṕ#rr:rϙϙNN; ̤ "%(+10.,+'%#" !x)+./01123445 ".99:;;<=>>?@AEF >K@@8;)Hd:4:́́́̄ ̩́ L  +A*,*$#GA1=!##! "; .!#%'(,-/1245689:<=>?ABFHK":UTSR1MWLKJLH B́#ϙϙNf445 ̚  #&),/10.,('%#! $&)+-/012344 =L399:;;<=>>?@BCĚ;G7<&;/9̖́́̃̃́ D ̕??*,+(":! 4-? -K "$%'*,./124567=>?@BEHJMOQPON:IJKMLK/̄ f4r::8 ffgikml̚npqtwz}̄̏ ̊těẃ̖́̃̃́}zs̫rwz}̗̑̈|y{~̂̆Ά̅̄̃̔̚qoljggikmf̔xz|~̑fo̸̬y̰~̄$r:NN8 ̚  #&),/10.,('%#! $&)+-/012344 =L399:;;<=>>?@BCĚ;G7<&;/9̖́́̃̃́ D ̕??*,+(":! 4-? -K "$%'*,./124567=>?@BEHJMOQPON:IJKMLK/̄$Nff4f4C !$'*-01/-,(&$# "#&(+-/53445;899:;;<=>>ACDFHHG#A8::?C[́́̃ ́ ̆+̜!|(*./,# 5= "$&(+-./12356 <;>?@AEGILNNLKJIHJLMJV̄#ff4frr:r:Cfhjlnmklmnrux{́̎ ̊f̨̞̮̞́́̃ ́ ̆t̝̑tx{{̇㎐̔f̒̃}{|~̂̆ʂẁxsqnliggiknuxz|~̑fl̫̲̳x̼̄'rr:rϙϙNNF !$'*-01/-,(&$# "#&(+-/53445;899:;;<=>>ACDFHHG#A8::?C[́́̃ ́ ̆+̜!|(*./,# 5= "$&(+-./12356 <;>?@AEGILNNLKJIHJLMJV̄'ϙϙNf44C  "%(+.11/-)(&&%%%!%$$$&(+-/4LQ344566899:;;<=>?ADFIIIG&=:985+>̠́́́́́̃́́̄ @!$'"-/A# " ̷  "$&(+-./023467 ,><=>@ABFIKKJHGHIKLMNMJH7!f4r::Cffgikmoommnopqsvy̐fůx̞̪wó̰̟̜́́́́̃́́̄pquẍ̦̈̂̊~|̀f̉~}}~ywtro̷gilrtvxz|~̒s̭̮%r:NNF  "%(+.11/-)(&&%%%!%$$$&(+-/4LQ344566899:;;<=>?ADFIIIG&=:985+>̠́́́́́̃́́̄ @!$'"-/A# " ̷  "$&(+-./023467 ,><=>@ABFIKKJHGHIKLMNMJH7%Nff4f45 ̢   #&),/20.-)((DFE''&&(+-/0b2344566799:;;<>?@BD6JJKFB>:8̴́̄̅̇̇ C"#BD/w'$!,!G̹  "$'*+,./0134578:<=>?ABFHIGFFIJLMOOOLKIFF̃%ff4frr:r:8 ̢ffgikmpfwnopqrtw}̏l̴̘̟̬̅́̄̅̇̇joru̪̅̉̎~́fy~}k̮{{|~{yv̹ljhjprtvxz|~̡̬̰̐̃)rr:rϙϙNN8 ̢   #&),/20.-)((DFE''&&(+-/0b2344566799:;;<>?@BD6JJKFB>:8̴́̄̅̇̇ C"#BD/w'$!,!G̹  "$'*+,./0134578:<=>?ABFHIGFFIJLMOOOLKIFF̃)ϙϙNf44B, !$'*-020.++*<*))+-/002344566799:;<=>?ACEFG|LEA=9̃́́́́̂̂̂ ̇";,̇0-+(%"́ *I&   "%*+,-/0124567:;=>?@BEFEFGI MNOOMKE$f4r::Cffhjlnfvopqrs{~̒̒ ̣̘̟̭̬̐̃́́́́̂̂̂lṗ̡̈̇~~}}q{{z̍yxz~vtqoljnprtvxzfg̠̫̐s̶(r:NNE, !$'*-020.++*<*))+-/002344566799:;<=>?ACEFG|LEA=9̃́́́́̂̂̂ ̇";,̇0-+(%"́ *I&   "%*+,-/0124567:;=>?@BEFEFGI MNOOMKE(Nff4f4B̗B "%(+.11/..--,,+-//0133456679:;<=>?@BDFH5MMMI@:85̄̂̇́̅$&)/1.*'%"5<   #%*+,-/0124567:;<>?@BCFGIJ %OPP(PPPOKD+ff4frr:r:Cfgi̗pfrswz} ̧̙̟̳̳k̄̂̇́̅{̖̘̃̊|{z̜yxwvvwy}}{xvsqnlmoprtvxzfj̠̬̐s̶x̷/rr:rϙϙNNE̗B "%(+.11/..--,,+-//0133456679:;<=>?@BDFH5MMMI@:85̄̂̇́̅$&)/1.*'%"5<   #%*+,-/0124567:;<>?@BCFGIJ %OPP(PPPOKD/ϙϙNf44?̗ ! #&),/21 0///.//01456678:<=>?@ACEGIKLNLHD/6-& ̆̂̃ /A0/+($"̈   5Km!#%*+,-/.4567:;<>?ACEHJK ">QQ*GWQQC)f4r::B̗lnprtfntux{~̖|~̵̡̳̕} ̆̂̃́f̗̕̕|yxxwwvvuuttswỳ}{xvoqjmoqsuwx{i~Ӈ̐h̠̯o̷v̪-r:NNB̗ ! #&),/21 0///.//01456678:<=>?@ACEGIKLNLHD/6-& ̆̂̃ /A0/+($"̈   5Km!#%*+,-/.4567:;<>?ACEHJK ">QQ*GWQQC-Nff4f4;̝ !>!$'*-44 322212>56789;<=>?ACDFHJLNOOGDM,&̆́̅̄:>A15/,)1Q # :!#'(*+,-3Qn567:<>@BDFHILMO:Q9QQOGB&ff4frr:r:>̛ffhjlnprṫuvy| ̙z̶̢̧̛̤̮̳̠̘̖̓̆́̅̄fo̘yvuttsrq|~}zftfopqsuwy{x̍fԛ̸̠̳x̸*rr:rϙϙNN>̝ !>!$'*-44 322212>56789;<=>?ACDFHJLNOOGDM,&̆́̅̄:>A15/,)1Q # :!#'(*+,-3Qn567:<>@BDFHILMO:Q9QQOGB*ϙϙNf447̕="%(+.13677 6554677?789:;>?@BDFGIKMOPQKE:̂N( ̆́̃752/,)$<>  A;E !#'(*+,-/24579= ACDFHJLOPQRRQNFBAAA#f4r:::fgikm̓wuvwz}̜f̦̝̱̫̅̂ ̛̝̙̆́̃̅ḳyvrqpoonptxz|~}n̨irtvxy}̍{̙̣o̵̴̧̨̹'r:NN:̕="%(+.13677 6554677?789:;>?@BDFGIKMOPQKE:̂N( ̆́̃752/,)$<>  A;E !#'(*+,-/24579= ACDFHJLOPQRRQNFBAAA'Nff4f46 ̚ $&),/2468:: 9 888779;<<<8789;<@=@ACEGIJLNPRRNH*/̂ ̂̎ -22/,̋  !';"g !#'(*+,-/03579;ACEGIKMNQRSQONLA??@"ff4frr:r:9fh̘prtvxwuvwx{fipȓ̞̞̦̮̂̕ ̂̎q̙̔f̈́ffsponnmllnrtvy{}̎uqrtvh|~̍̚}̷̷̧̦&rr:rϙϙNN9 ̚ $&),/2468:: 9 888779;<<<8789;<@=@ACEGIJLNPRRNH*/̂ ̂̎ -22/,̋  !';"g !#'(*+,-/03579;ACEGIKMNQRSQONLA??@&ϙϙNf44=̞&:A%(+.02579;==<*;;>@AAA@<:̝:9:;)AABD )6MOQSRNG2*̂ ̃̂/72.D/M  !  !%'(*+,.0268:<3HFHJLNOQRSRPMJB@>??"f4r::@̜kmfvuwyywwxy|ff}̡̝̑ņt̙̂ ̝̃̂^̪^̖pmkkjjlosuwfh|zwurqsufi|~̜̌f̙̳&r:NN@̞&:A%(+.02579;==<*;;>@AAA@<:̝:9:;)AABD )6MOQSRNG2*̂ ̃̂/72.D/M  !  !%'(*+,.0268:<3HFHJLNOQRSRPMJB@>??&Nff4f4:̣-I @#&),.1357:<>@@?,C>>>ACFF $FGEB?<7):;<=>ACAAMOPRTPF;1̂$9838"??  7L "# 6P "%')+-/1359;<>@@HJLNPRSTTSRPONMI?==>>)ff4frr:r:=̍fgik̓uwyzy{}̇n̩̤q̭f̨̝̐f̂$栞̟̥qnjhikmqsuwf̄|zwurtuǧ̝̟n̦̻̯ṳ-rr:rϙϙNN=̣-I @#&),.1357:<>@@?,C>>>ACFF $FGEB?<7):;<=>ACAAMOPRTPF;1̂$9838"??  7L "# 6P "%')+-/1359;<>@@HJLNPRSTTSRPONMI?==>>-ϙϙNf449 ̟ +<!$'*-/1368:=?ACCBBBACFHKK"?5HDA>?@̛=<=>?@CDFH8NPRSO:-̄̂=9+"  "< "#< "'),.0246;=?ACEIKMOQSTUTRPONMKJG-==.f4r::< ̝npvxfizz{|̂d̜}̴̡̛̩w-̄̂̑f|xurogikmoqtvẍ̉ffy~|ywttv{}̸̡̯̎̓g̣2r:NN< ̟ +<!$'*-/1368:=?ACCBBBACFHKK"?5HDA>?@̛=<=>?@CDFH8NPRSO:-̄̂=9+"  "< "#< "'),.0246;=?ACEIKMOQSTUTRPONMKJG-==2Nff4f4/ ̤̂ +"%(+-/2469;=?BDFFEEDDFIKNPPQQJGC@ABDE̝@=>?@AFGIKOPQND9=-̂́49  %%1B!$')+.0246;=?ACFJLNPSTSRPNMKJIE&D3P,ff4frr:r:2 ̢̂gikmoqsuwyf{{̵̰̝̬̣̀-̂́ߛffftifiknprtvz|~̋hz~|ywuxz|~̴̡̰̻̊̍f~0rr:rϙϙNN2 ̤̂ +"%(+-/2469;=?BDFFEEDDFIKNPPQQJGC@ABDE̝@=>?@AFGIKOPQND9=-̂́49  %%1B!$')+.0246;=?ACFJLNPSTSRPNMKJIE&D3P0ϙϙNf447  .J #&)+.02579;>@BEGIIHHI PSUVSLIEBCDF̖88>?@BCGIJLNNMC6'<0"$4  #%' A@!%')+-0246:=?ACEJLNPRSPONKJIGD>5; *f4r:::̥fikmoqsuq}~r̳f̵̖̭0̊Zzplhjmofqy{}̉̇~{ywy{|~̷̡̰̲̋| .r:NN:  .J #&)+.02579;>@BEGIIHHI PSUVSLIEBCDF̖88>?@BCGIJLNNMC6'<0"$4  #%' A@!%')+-0246:=?ACEJLNPRSPONKJIGD>5; .Nff4f46̪(!$'*,.1(&<>ACEHJLLKKKKLN*B5[YVRHDE4,K7̃́'#B!#&($"!%')+-/146:ACEHJLLKKKKLN*B5[YVRHDE4,K7̃́'#B!#&($"!%')+-/146:ACEIKLMNNLJ2E@<;9896f4r::6̡qsuwy{̀k̵uf̭qǴ̙o̡̝ 5́̋̅yuqmhim̑wz}̈̐~{xz|~̠̰̰̉|̫:r:NN6̿  #&(*-/1(EIB?ADFHJMOONNNQSV:?B``_[.FG 0IaNO̙IFCABCE;IIJ66 5́% *;"$&)'$"#$&)+-/136:<>ACEIKLMNNLJ2E@<;989:Nff4f40 !$&)+-/24:;=@BDFIKMPRRTVY[^`.eea^6PIJL~P#>! CCDEAG@,̅F̂̅ ,  "$)+)'$!#$&(+-/':<>@CEHIJKLKJI#>?<:875ff4frr:r:3fkptvxz~̡̺ǔf~̶̯ḟq~̧̓̅F̂̅fvuqmiqtvy|~̆̏̃}{z|~̉ft̠̮̥̉9rr:rϙϙNN3 !$&)+-/24:;=@BDFIKMPRRTVY[^`.eea^6PIJL~P#>! CCDEAG@,̅F̂̅ ,  "$)+)'$!#$&(+-/':<>@CEHIJKLKJI#>?<:879ϙϙNf44, "%')+.0259<>@BEGILNPSY[^`cfhjgc`\YU8KLMO) ̐H*E7BCC7EE?4-̆Ĉ%GL  !&(+,)&$#$&(*,/#@:<>@BDFGHJJIGFDB764f4r::/fifsvxz|~̠̿ÿ̱̲{o̩̫̐̆Ĉjspjnrux{}̂̌̅}{}~̉n̠̬̪uw8r:NN/ "%')+.0259<>@BEGILNPSY[^`cfhjgc`\YU8KLMO) ̐H*E7BCC7EE?4-̆Ĉ%GL  !&(+,)&$#$&(*,/#@:<>@BDFGHJJIGFDB768Nff4f4< #%'*,.135:<>ACFHKNQUXcfhkmomfb_[XTQLOQ1N̐?=@A*'>3-E̍;"%'*-+%# 7"$&(*,.1:9<>?ABDEGHGFECB<4-554ff4frr:r:?ff}uy{}̠¾̶̳x}̧̣̐m̍E̡̍yvgjfkwz|ff{̉̔̌|~f̡̢̝̠̫f̚8rr:rϙϙNN? #%'*,.135:<>ACFHKNQUXcfhkmomfb_[XTQLOQ1N̐?=@A*'>3-E̍;"%'*-+%# 7"$&(*,.1:9<>?ABDEGHGFECB<4-558ϙϙNf44: 0M!#&(*-/149;>@CEILPSWZ^hlosrokda^ZWSPP ON6A̐B?>?;>2.̄C̃;DP$&,--*(%"@"#%(*,.059;<>?@CDEFECBA@9FS48f4r::=qw|~̶̟ţ̵̦̥̀̐v̙̄C̃mjgd{^y̶芍̒̔̃~ķ̛̠̩̟y̬<r:NN= 0M!#&(*-/149;>@CEILPSWZ^hlosrokda^ZWSPP ON6A̐B?>?;>2.̄C̃;DP$&,--*(%"@"#%(*,.059;<>?@CDEFECBA@9FS4<Nff4f4@̻)! "$&)+*6;=AD *=UY\`ginppljd,R*>KJH̋?<<==0yB̂9 <> #%+.00-*!j "#%'*,.0589;<=>ABCCBA@>:853 8ff4frr:r:C̻tzf̡fsf|n̢̥̋B̂lihtx|̢̑̕flч̧̛̛̟̙ <rr:rϙϙNNC̻)! "$&)+*6;=AD *=UY\`ginppljd,R*>KJH̋?<<==0yB̂9 <> #%+.00-*!j "#%'*,.0589;<=>ABCCBA@>:853 <ϙϙNf44> !!$&)+5Q7?CFJM?A+\^`ehjkiec8Q*RN+JIHFD̋=::;;:1@"$*,./12/:E "#%'),.045689 #=?@BA@>=97622 6f4r::Alqw|̇f}̦~f̴̰̫̠̋@hff|̐g̅̚r̥̙ :r:NNA !!$&)+5Q7?CFJM?A+\^`ehjkiec8Q*RN+JIHFD̋=::;;:1@"$*,./12/:E "#%'),.045689 #=?@BA@>=97622 :Nff4f4<  "#&(+.0= >EGJLNQUXZ]_dfhfb`\X=<865321 5ff4frr:r:?msy~̈y̫̼̿}̶̲̭̞̈Fkxy}̘̌ƍ̙̅fp̤̘ 9rr:rϙϙNN?  "#&(+.0= >EGJLNQUXZ]_dfhfb`\X=<865321 9ϙϙNf44; #&(+.257otẓ̸̧̺̼̳̬̊̇̃Stwy}̋fk̺f̗̆̅t̢ 8r:NN> #&(+.257@CEGJLQSVXZZXVTRPNJGHHIJ̄@>̅73Q "$(*,0236630.+%#!"$&'()+-./124678976421/- 2f4r::: s}̷̠̤̰̮̰̈̄x̙̅Q~f̛̖̝̆̌̓ 6r:NN: "&(+-0249>@CEGJLQSVXZZXVTRPNJGHHIJ̄@>̅73Q "$(*,0236630.+%#!"$&'()+-./124678976421/- 6Nff4f45 ̶ $'),.03:< FHKORTVVT48 GDEFFGGHIIGG0><̂76Q@$&(+-/06631.)'$#$%'()+,./0345665310.- 1ff4frr:r:8 ̶r̠fx̶f̫̬̯̭ŵ̭Qţ̜̜̙̒̏̊̒ 5rr:rϙϙNN8 ̶ $'),.03:< FHKORTVVT48 GDEFFGGHIIGG0><̂76Q@$&(+-/06631.)'$#$%'()+,./0345665310.- 5ϙϙNf444 ̰)F%(*-/1683IDGINPSQOM%E@CBBCDEEFGHHFD̄>>=;̅ Ś̮%(*')*,1642/*'%&'()*+-./1235786432@f4r::7 ̰i̜fy̴ḡ̪̫̮̬̅ Ś̛̮̗̝̜̍̐̌̔Dr:NN7 ̰)F%(*-/1683IDGINPSQOM%E@CBBCDEEFGHHFD̄>>=;̅ Ś̮%(*')*,1642/*'%&'()*+-./1235786432DNff4f42 ̤&<!&)+-0579@=CEHLNLJHFDB?@@AA̋DDEEFGFCB̄=<0Ēc̃+(% -25>('()*1012346;<87?ff4frr:r:5 ̛̤̍{̳̦̭̪̋̄̄c̃̏fr̘̓fk̤̍f̡̖l̟Crr:rϙϙNN5 ̤&<!&)+-0579@=CEHLNLJHFDB?@@AA̋DDEEFGFCB̄=<0Ēc̃+(% -25>('()*1012346;<87CϙϙNf448 ̵"'*,.358:?ADFJHFDB?==>>?"ABBCCDDEEBA?9(̄ j̤"??(-03>))*+2L2368:<@H>f4r::; ̵~̙̥̰̤z̨̬̩̥̟̎̄ j̤k̦̔}̥̐^z̘̦j̮Br:NN; ̵"'*,.358:?ADFJHFDB?==>>?"ABBCCDDEEBA?9(̄ j̤"??(-03>))*+2L2368:<@HBNff4f47 ̱$(*-1469=@BDCA?=;:;;<5I/@AABBCCDBÁ̄ ḥ5="$7-*+-./0379<>@BBA>ff4frr:r:: ̘̘̤̩̣̀f{̧̨̪́̄ ḥÿg̨̙̞̓̒Brr:rϙϙNN: ̱$(*-1469=@BDCA?=;:;;<5I/@AABBCCDBÁ̄ ḥ5="$7-*+-./0379<>@BBABϙϙNf446 %)+0257<>A@<:899:;<?>??@@AAB̄́̃ g̃7̞4B.-./02598BDFGC?f4r::9 ̢̡̖̣}̄́̃ g̝̞̃{̟̪̔̓̀Cr:NN9 %)+0257<>A@<:899:;<?>??@@AAB̄́̃ g̃7̞4B.-./02598BDFGCCNff4f4C!',.136:=<865667889::;<<==>?22̆ h ̚8&/02468;?&?22̆ h ̚8&/02468;?&f4r::D ̖̌̔́̃~̑ Br:NND &*,/./0122B'./01??̃~̑ BNff4f4@ (++,-.,--?>011̃̆~́̂Jff4frr:r:C ̒̓x̃̆~́̂Nrr:rϙϙNNC (++,-.,--?>011̃̆~́̂NϙϙNf44A +,,--//0I̋~Jf4r::D ̑̒̋̕~Nr:NND +,,--//0I̋~NNff4f4@,-../ ̋~̂Jff4frr:r:C̔ ̋~̂Nrr:rϙϙNNC,-../ ̋~̂NϙϙNf44? ̉~́Jf4r::B ̉~́Nr:NNB ̉~́NNff4f4>  ~Jff4frr:r:A  ~Nrr:rϙϙNNA  ~NϙϙNf44I  ̈~̄Jf4r::L  ̈~̄Nr:NNL  ̈~̄NNff4f4G  ~Jff4frr:r:J  ~Nrr:rϙϙNNJ  ~NϙϙNf44F  ~̃Jf4r::I  ~̃Nr:NNI  ~̃NNff4f4S ~Jff4frr:r:V ~Nrr:rϙϙNNV ~NϙϙNf44S ~Mf4r::V ~Qr:NNV ~QNff4f4S~4Nff4frr:r:V~4Rrr:rϙϙNNV~4RϙϙNf44R~> Xf4r::U~> \r:NNU~> \Nff4f4R~= Xff4frr:r:U~= \rr:rϙϙNNU~= \ϙϙNf44R~>bf4r::U~>fr:NNU~>fNff4f4R~@bff4frr:r:U~@frr:rϙϙNNU~@fϙϙNf44Q~[bf4r::T~[fr:NNT~[fNff4f4Q~~Aff4frr:r:T~~Err:rϙϙNNT~~EϙϙNf44Q~~Af4r::T~~Er:NNT~~ENff4f4P~~Bff4frr:r:S~~Frr:rϙϙNNS~~FϙϙNf44Q~~Bf4r::T~~Fr:NNT~~FNff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nff4f4~~~ff4frr:r:~~~rr:rϙϙNN~~~ϙϙNf44~~~f4r::~~~r:NN~~~Nf4f4~~~fr:r:~~~rτNN~~~ϙf44~~~r::~~~σNN~~~4f~~~f4:r~~~r:N~~~ϙNf4f4f4f~4~4P4f4f4f4f4r:r:r:r~:~:P:r:r:r:r:NNN~N~NPNNNϙNNff4fff4f4f4f4f4f4f4f4f4f4f44f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f44f4f4f4f4f4f4f4f4f4f4f4f44f4f4f4f4f4f4f4f4f4f4f4ff4frr:rrr:r:r:r:r:r:r:r:r:r:r::r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r::r:r:r:r:r:r:r:r:r:r:r:r::r:r:r:r:r:r:r:r:r:r:r:rr:rϙϙNϙNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNϙNNNNNNNNNNNNNNNNNNNNNNNNϙϙNf4f44~f~fOf4f44f44f4r:r::~r~rOr:r::r::r:NNN~~ONNNNNNff4ff4~f~fMf44f4f f4ff4frr:rr:~r~rMr::r:r r:rr:rϙϙNN~~MNNN NϙϙNf4f44~f~fOf4f44fff44f4r:r::~r~rOr:r::rrr::r:NNN~~ONNNNNNff4ff4~f~fMf44f4f ff4ff4frr:rr:~r~rMr::r:r rr:rr:rϙϙNN~~MNNN NϙϙNf4f44~f~fOf4f44f fff44f4r:r::~r~rOr:r::r rrr::r:NNN~~ONNN NNNff4ff4~f~fMf44f4f ff4ff4frr:rr:~r~rMr::r:r rr:rr:rϙϙNN~~MNNN NϙϙNf4f44 fffffffffffff~f~ff4f44f fff44f4r:r:: rrrrrrrrrrrrr~r~rr:r::r rrr::r:NNN ~~NNN NNNff4ffff4 fffffffffffffffffffffffff~f~ff44 f f4f ff4ff4frr:rrrr: rrrrrrrrrrrrrrrrrrrrrrrrr~r~rr:: r r:r rr:rr:rϙϙNN ~~NN  N NϙϙNf4ff44 ffffffffffffffff~f~ff4f f44f fff44f4r:rr:: rrrrrrrrrrrrrrrr~r~rr:r r::r rrr::r:NNN ~~N NN NNNff4ffffff4 fffffffffffffffff~f~ff44fff f4f ff4ff4frr:rrrrrr: rrrrrrrrrrrrrrrrr~r~rr::rrr r:r rr:rr:rϙϙNϙN ~~NN N NϙϙNf4ffff44 fffffffffffffff~f~ff4fff f44f fff44f4r:rrrr:: rrrrrrrrrrrrrrr~r~rr:rrr r::r rrr::r:NNN ~~N NN NNNff4ffff4 ffffffffffffffff~f~ff44f f4f ff4ff4frr:rrrr: rrrrrrrrrrrrrrrr~r~rr::r r:r rr:rr:rϙϙNϙN ~~NN N NϙϙNf4f44ffffffffffffffffffffff~f~ff4f44f fff44f4r:r::rrrrrrrrrrrrrrrrrrrrrr~r~rr:r::r rrr::r:NNN~~NNN NNNff4ff4ffffffffffff~f~ff44f4f ff4ff4frr:rr:rrrrrrrrrrrr~r~rr::r:r rr:rr:rϙϙNN~~NNN NϙϙNf4f44Cff~f~ff4f44f fff44f4r:r::Crr~r~rr:r::r rrr::r:NNNC~~NNN NNNff4ff4Cfff~f~ff44f4f ff4ff4frr:rr:Crrr~r~rr::r:r rr:rr:rϙϙNNC~~NNN NϙϙNf4f44Ef~f~ff4f44f ff44f4r:r::Er~r~rr:r::r rr::r:NNNE~~NNN NNNff4ff4~f~fMf44f4ff4ff4frr:rr:~r~rMr::r:rr:rr:rϙϙNN~~MNNNNϙϙNf4f4~f~fOf4f4f4f4r:r:~r~rOr:r:r:r:NN~~ONNNNff4ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4frr:rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr:rϙϙNϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙψϙϙNf4~~~f4r:~~~r:N~~~σNff4f~~~ff4frr:r~~~rr:rϙϙN~~~ϙϙNf4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4ff4r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:rr:NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNff4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4f4ff4frr:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:r:rr:rϙϙNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNϙNf4~f~fhf4f4r:~r~rhr:r:N~~hNNff4~f~fgf4f4frr:~r~rgr:r:rϙN~~gNNffffffffffffff44fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff44ffffffffffffff4rrrrrrrrrrrrrr::rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr::rrrrrrrrrrrrrr:ϙϙϙϙϙϙϙϙϙϙϙϙϙϙNNϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙϙNNϛϙϙϙϙϙϙϙϙϙϙϙϙϙNf4~~hf4fr:~~hr:rςN~~hςNmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example2j.jpg0000644000175000017500000004737610504574206024652 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?xP[dkS8VwfĀ8pM#9a8H:.KzW;pw1m7c:ԫYF>KJZlĿY[ \GqsV#(cqXr?"lRIeHc/=)w.e7n# Dp`P2.~3>%֛?/Fsq>t\.q,O?!UtIn.eYhb`(򎞃Ҁ|K6_筄}#k8uKuϤ~5-\b_$H6cvg|Qcw 4q4g d+>B6(.~3>%֛?/Fsq>t\҇VGo Fk䀭R/->ֶ}  0MۻsQ@OuKuϤ~!.~3~+Ӛ쫩ԣn]0 g#O/*k/[H#eUdt% 2+Gڀ'>%֛?/Fsq>t\ĺg%zN:?CC^cQ%cM|Nc0rsz),-.I J9;r>_zPM#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\̷Req?.J_l29#!@M#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\̷Req?.J_l29#!@M#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\̷Req?.J_l29#!@M#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\̷Req?.J_l29#!@M#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\̷Req?.J_l29#!@M#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\̷Req?.J_l29#!@M#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\̷Req?.J_l29#!@M#9a8H:.C]idg=l's_Eu/˶YGc运nv(#1~] .~3>%֛?/Fsq>t\.P"2 $` ~]=)eN,9$x82ωuKuϤ~!.~3au*Q0O?Cҁu*Q0O?Cҁ`׵8't\x3Wn'xtẋĺg%zN:?Ce#Tfق}nÎ3XM^G$["b-BP hM#9a8H:.lXk-/KFq@82(g s楡O}?2b(+@Gr:`zVq,67"$*_A^89 @eyn|PeFy C%MJǿ0OO~=ILg;ҹۇ1iOڞy-65Ϟa@ 3c=GXM]eG`G xJp9'S|q?#EFr@ ;mxNLK`|#KbU#C K}0[+HM\kũCuDOlӧU⹑^Ƨ9Vm~f+{WXc L|x,zUc[nNxh[ϧ!͈z~>'2cS_I5.-4>e;`$U Rt5Hm#Q$tąV:9*͈z~>!͈z~>'2cS_UMtUo9)Xtdѥg5rvE'q N>5\7w~gd>5\7w~gdAj+E>ر@b8.q=*}NU/.1 ;>o91Ǖ`Z|ma.x?v>z=qNNe=OqV;PCyJ$.~\-WsԤb$XD4UT`;ۊ5"8ssד / woaNNdƧnyx75opHrƚvӑ@17^O>˸{u|:jOtI)Ori~c;q>˸{u|:j40Ӑbnz3ʟȷ$dbooe}99p5?Msui [NFIy>Orƺx${ϔo}99p5?MsuiOaori`-!DzgӓwcS_t74Ӱ@}>]W?#v׎;W2|kHLM\v~gӔN tqێߙ]W?#v׎;W0|iassׯNTOE# {{/̻:oG^8G#v`Nr2H&~gӕ>5$[g|;}?3̻:oG^8G#vcM8|/ un;~gӐNm9 &^=>˸{u|:jOt[217񦝂d Mדϧ'2Ƨnyx7&p-_vϧ'2Ƨnyx7nyxsƚvӑ@17^O> "=37=qNNe=Oq|<ۊ[1IH˟- LMs1ϧ2CM2 :H`<0v#rh]WFգ[}H :8`Wk '$Y_`&CXx?ņO8or؅CqM9_oz㓙wcS_ts Ӏ~q?1w#?szʃ0E~B3\4AP*o38Z<$zbcEBij$t̃Wq?Ej>;?~>z t^/uI%b# >աB9vF="<ǩ)||&o4 hc=\JǬ4,J#?Ng.UYpzתxtۧ]ѿdMWCgO^i]otWUhpsn󿽖:?+Q[;kJ{(һ Ex{-i]otWUhð__WGGUZ(p??w=i]otUgG󿽖:?+Q_[e+J{*{8vZһ ?:?ªG`#_WGGUZ(p/wGQw=V=;x{-i]otWUhð}oe+J{*{8v;kJ{(һ EG󿽖:?+Q>wGQw=V=; uw=i]otUg#_WGGUZ(p[;kJ{(һ EZһ ?:?ªGaoe+J{*{8v?w=i]otUg{-i]otWUhðwGQw=V=;Zһ l_^厘O ϷQymz ?y?~>E)ZL=U97q5ljIY` $ ́O~=IQF="<ǩ+c;#p~]tѿzO?.ݺzvNnoγ_H(0(((((((((((((((((((((((Qc!>[!u]^Cl}4?OC_2*/)a.;z]=>v?%jqߎO?.ݺzvNnoν{|Hçn=;z'C7_7toY|$EEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW1M-:.Qc!>[!uOC}[ǿ0OO~=IGa.;z8|Hçn=;z'C7_7to^$a˷n7>Gcs_"+C(((((((((((((((((((((((+~myGW1M-:D JG-@􋧧?ǿ0OO~=IZgw$a˷n7^0۷ONމ }]k#?QEQEQEQEQEQEQEQEQEQEQEU+odژUX;sçYʤcCREiczy'6 !UI8$mv剄Uٞ:M^{E{<^n#hΙi"P9QXzØ6v?%=Hz|J;#p~]tѿzO?.ݺzvNnoγ_H(0(((((((((E.꣩8mk8I+I.TZߵ s\ڱSҶs\WsbVGw^D]NQLAXP]Կi+ Ŀ&ueңpkr{d p85ۍ|YGI`bڦC?pJ9=pU>3CᛔgPprCʖ(((((((((+~myGW1M-:D JG-@􋧧?ǿ0OO~=IZgw$a˷n7^0۷ONމ }]k#?QEQEQEQEQEQEQEQEQEQEX0IVti5p$H9?'dإ.TꬴAIηt-9WIYG؟cVNku$M\Q5tV>a#*`0=8/\4zf-Yʃkhė^gNki¶!ƪJU+IoVWּ {z [`֪,9 -鯺KMbxyX1n8݁~!]6ͥr/\}x؜40䦬:(0,B(sP((((((((Qc!>[!u]^Cl}4?OC_2*/)a.;z]=>v?%jqߎO?.ݺzvNnoν{|Hçn=;z'C7_7toY|$EEVQEQEQEQEQEQEQEQEQET{\TT2Zyi5fvf8_4@[!u]^Cl}4?OC_2*/)a.;z]=>v?%jqߎO?.ݺzvNnoν{|Hçn=;z'C7_7toY|$EEVQEViIc vד)UY\\Y8%y9 ,YXmxەu?0@5z9Úڒl;{#7 qT;= @{rn7-uG ժ9zz"yB{IK(WF]F+"V@5gIRYX!)k3+F{2gqAn;IBZc.M:/fSPAyN\_nNoQbv՛or7]C*ӭ&ׯZ f2yryv0e8@z~՛UO֟"{D? (5 ( ( ( rcz֛JY%rKqi\p9v^A3@>=5m=Mz;'k.{ezμݩIA'@M}7XtuD)^w.~fFm[zt٘)G_& [t.MۘN<_S:ː9W_]}(C"ٻ28wu+[!u]^Cl}4?OC_2*/)a.;z]=>v?%jqߎO?.ݺzvNnoν{|Hçn=;z'C7_7toY|$EEVQET deZ1_ZTj/:0,*aѦL0<#LXJ:28ErϿ @Tޒ9gמU[XgfMzg#:i1$W6_b]ތ̭{$d}^)tM$F*ר k*po.7Vi(V*˾9d^̧ӂ=A"v4Mh} FeV?0!pdUSкR^ݯQEQEQEQEU63.nFC۟UiHa%P #Lqi4ZGy zضs(7qZ&@?xxQĵuN_s:=A.^w=NRAv+#*ݭ猍{qks:jԗ5H4Fٌ͝ ki#ml5 0O5ƻ؁Ƒdžg\N=3^W]ߏ.. ttf;;qǿ\jMQ׫ (Т((((((((Qc!>[!u]^Cl}4?OC_2*/)a.;z]=>v?%jqߎO?.ݺzvNnoν{|Hçn=;z'C7_7toY|$EEVQEQEYB# *֔!+;| + mnW{2>wyW#;736=NkIʓmKbkB9Q-R,`8;+˂`9fT܊iw K?!W :2FN*Vk*I+*2HU ku$d[LS XV1$aHTSۡ:]PQEQEQEQES# Sʙ_JObne}=m͌W: "\5}Qڒ P\\5 XBaԫssֱKg]^ܺMAuӚ|uc̯6>y@ gP^[^}L&2?uyvu=Š(((((((((+~myGW1M-:D JG-@􋧧?ǿ0OO~=IZgw$a˷n7^0۷ONމ }]k#?QEQEQ[{#$=R* m Up s%Jѻ~?~U{zii O?Ahݛm TnGsX9RI_dӔ~G#D{HD3B0g.0Spp=S]Q ro~hdC4# >}v{{4LŠ(HQEQEQESwȫn fRې.#)=NI3.р1ȭX 1hycZ>o`c!9ҰA z""Q>QE(j̽ߪLBc/\! #B=˄r@5[] h>Y쩭 P\"!SpO\=w^(Oi4{ pC<<|# `+c((((((((+~myGW1M-:D JG-@􋧧?ǿ0OO~=IZgw$a˷n7^0۷ONމ }]k#?QEQE-Ķж\F A EW3 rjC)S&)RuN-]&N23BN -F㶝fZG\b#A 3U)#D!&"o@]A*zt9'ir?]' r;o~״ћw=cEM5xex>Ǟ?԰Ywy3B;HcХituMxUea *K4>^[|M_ϱ#RUeQmww (((((׶YQV`#mi\:>⹧E=>a[U袻[K];ʲNpqcMBP8VT{<…߆SVk_ZYA\C5FL'Qw-"L}k2+1QVGVM]B(fQEQEQEQEQEQEQEQE? 6Kc<˫~myFSvP_E# zEcxRQ@􋧧?N30۷ONމ }]ׯxtۧoD|>5O䈨 ( .&qqGc X[ Pi;+ #$S&(r4]MV}3}?Gkyl38*9m|p2ԩ#v>`ҌsZiNV]?FI Fep [}‘}L9G?U:9DpIg.$•owD6_sMoɒ%U8.p{?֪Ӥr0}6R[U9;O%QTdQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE? 6Kc<˫~myFSvP_E# zEcxRQ@􋧧?N30۷ONމ }]ׯxtۧoD|>5O䈨 ( ( (%$;,t,?o|j*Z}cR)Y?e}K_b}ʎ Ϩ4hB_iou+vQEFAEPE[!u]^Cl}4?OC_2*/)a.;z]=>v?%jqߎO?.ݺzvNnoν{|Hçn=;z'C7_7toY|$EEVQEQEQEQEQEQEQETJNxQ"*(v,f& 2:0ʖ9_.@Ld玪}GwlaЏQND2(EPIb L~Iۨbx%1ȸa}=2*Kl(W.2c>OnGpӶEj)Jcp {9zeQAEPEPEPEPEPEPEPEPEPEP^Cl}4?OC_v?%=Hz|J;#p~]tѿzO?.ݺzvNnoγ_H(0((((((( Kqm$v+E&'-yp@ 0A J`Prƫ*EuEV *G!8vV?x쬎Qԫ)`MIQE (6ToQQ/FVfa9zATG{>HrF=4+s=ӇI zsQQEik%m(aEPEPEPEPEPEPEPEPEP^Cl}4?OC_v?%=Hz|J;#p~]tѿzO?.ݺzvNnoγ_H(0(((((((@s.9= ק#0e8".P&g<'EHWN7^Å;~^]LoW1RQ;X(B (5g 2ՠc^]ѷ[B= Wm?nV]pFPx h㟽uG m2QKGmL@ ''׮jUedhQEQEQEQEQEQEQEQEQEQE? 6Kc<˫~myFSvP_E# zEcxRQ@􋧧?N30۷ONމ }]ׯxtۧoD|>5O䈨 ( ( ( ( ( ( ( mxă I:}MCRE.̫..qq}ETmxL 2 lMGA9EpOOܤ{Y[|O_}A#mdQP0(Xƛw_[ ˸Hr?(rQ*k,]}0@5R)T)PLD玪}G",MH =EKWѲ[pEhrq} QM+"QEQEQEQEQEQEQEQEQEQE? 6Kc<˫~myFSvP_E# zEcxRQ@􋧧?N30۷ONމ }]ׯxtۧoD|>5O䈨 ( ( ( ( ( ( ( (=R+qg$'{GpTKBdZ"3y[|O8ϸ=$+ko;0A6Եh%1vv s#] K@rI I6ĹrQTXQEg>|?KSW&"sG*}G"!V[H#=:@X`pA kxRKi1U*##ך*ݯQE(((((((((+~myGW1M-:D JG-@􋧧?ǿ0OO~=IZgw$a˷n7^0۷ONމ }]k#?QEQEQEQEQEQEQEQEQW!xMi%ó\0:l7a7,Bᰣ\ɏ=uC,O9 =#0S\[!%Y >fΟ'Cؘ~/-?&VkhǯX`pA T%ÇnӠݯQE(((((((((+~myGW1M-:D JG-@􋧧?ǿ0OO~=IZgw$a˷n7^0۷ONމ }]k#?QEQEQEQEQEQEQEQĚIV %Okc'X>GRcIpHYˠyqҽZX#F $a9cwl =@}=.Q+QEFaEPpp"5t3B0?Cؗ]:?D0 ~EM^EJ*k ˛}q?ϽCTCVv (Q@Q@Q@Q@Q@Q@Q@Q@Q@z ?y?~>?c饱~}GQ(?WH{#tԔxF="<ǩ+SwČ:}vӷt>CusFu~6K˶3ĦG@>^.oγ_oH(@(((((((((((((((((((((((Qc!>[!u]^w̛6o[HP|z tZNr=Hz|J%~"9Ͳ6PK7|zԒIZgm$a˷n7^0۷ONމ }]k#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE? 6Kc<˫~myFSvP_E# zEcxRQ@􋧧?N3W!aP,Td tωuKuϤ~:ZqW?st'x#2=Fŋ(=~CҐuKuϤ~!.~3浧.y7&ȄÍe~Q`{S`5$wpC| (g2.~3>%֛?/Fsq>t\c" JLRBJ9@t>#پCCɈ>/ j|K6_筄}#k8uKuϤ~4Ui̫qdij& 0d$TN=H%֛?/Fsq>t\ĺg%zN:?CouecbX\D &@9r0)yCv'}]lZ2B͸` 8d@OuKuϤ~!.~3qq0&c1\L10njc=(]idg=l's_E|K6_筄}#k8蹜\L10njc=( bi11JZlĿY[ \GqrM#9a8H:.g bi11JAc x?~CҀ >%֛?/Fsq>t\ĺg%zN:?CAc x?~Cҁq0&c1uKuϤ~!.~3qq0&c1\L10njc=(]idg=l's_E|K6_筄}#k8蹜\L10njc=( bi11JZlĿY[ \GqrM#9a8H:.g bi11JAc x?~CҀ >%֛?/Fsq>t\ĺg%zN:?CAc x?~Cҁq0&c1uKuϤ~!.~3qq0&c1\L10njc=(]idg=l's_E|K6_筄}#k8蹜\L10njc=( bi11JZlĿY[ \GqrM#9a8H:.g bi11JAc x?~CҀ >%֛?/Fsq>t\ĺg%zN:?CAc x?~Cҁq0&c1uKuϤ~!.~3qq0&c1\L10njc=(]idg=l's_E|K6_筄}#k8蹜\L10njc=( bi11JZlĿY[ \GqrM#9a8H:.g bi11JAc x?~CҀ >%֛?/Fsq>t\ĺg%zN:?CAc x?~Cҁq0&c1uKuϤ~!.~3qq0&c1V4͸*ٱя'@|K6_筄}#k8uKuϤ~314aM 1u9eGϸ>%֛?/Fsq>t\سs]|ȬIP3=M3NJ}{PW! UO#LZlĿY[ \Gqsj[5F]@mo{}ʹ*mGWiiaދFH6lNwwdiw"Usn=:QqO,Q\3#u~g%/\?OAjv4{y-f+( cvfySs.\f&~gӘo ]Wl4okP[! .uXTc6ZV6O}Xwrn.Eij$*3 uO93{}?3|oa =qNNe=OqfڶmvۄIH}w}FO^l$ӴՊݥTMbI>q@:t{qOrs.\f&~gӓwcS_tW0|oa =qNC{qOrs.j+93{}?3|oa =qNNe=Oq\8boo}993{}?3̻:z+>7\Mϧ!8boo}99p5?OEs >7\Mϧ'2Ƨ`ÜApz17> ]W=s.\f&~gӐÜApz17>˸{㧢{qOrs.\f&~gӓwcS_tW0|oa =qNC{qOrs.j+93{}?3|oa =qNNe=Oq\8boo}993{}?3̻:z+>7\Mϧ!8boo}99p5?OEs >7\Mϧ'2Ƨ`ÜApz17> ]W=s.\f&~gӐÜApz17>˸{㧢{qOrs.\f&~gӓwcS_tZNV={qOrZuCbr=zQ̻MS]D& $  ;~j93{}?3|oa =qNNe=Oq.40~viֳ@44"XnGyH”P9܏ɮzK/v-hHb@ $tAwcS_t*'`٫Sã1מz\ޕ&^<4i<˹I##g>^w$mO('OCn*sEOGUտo9E2KZ1> 8]:dey&w=¤OJ׬qK>aQL}sSI)izvi]otWU(p~e+J{*{8vAG{-i]otWU(ò?oJ{(һ E}o?WGGUJ(px[һ ?:?ªQGd[GQw=R=; #~?:?+Qw=i]otTg>e+J{*{8vAG{-i]otWU(ò?oJ{(һ E}o?WGGUJ(px[һ ?:?ªQGd[GQw=R=; #~?:?+Qw=i]otTg>e+J{*{8vAG{-i]otWU(ò?oJ{(һ E}o?WGGUJ(px[һ ?:?ªQGd[GQw=R=; #~?:?+Qw=i]otTg>e+WṯI ،r<3xx{:ߏ_!).BR<;'׼_ux#DOXTg=exi\5x#DOXTg=exi\58?=cQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@{:ߏ_aQL}sװ_qK>aQL}sr;(gEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE??;~=>uxg/?3OX}??nGV}ǂ4N/uF{}3ߦ[W3^}ǂ4N/uF{}3ߦ[W3YS?EVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEW<SX\ǫ~Ǭvz?}᜾8_=cx>OQZf;ľ~o^?1{;ľ~o^?1g/?3OX}QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPE{O NsWWfâ$m\ی0_A/nkPQ@Q@Q@Q@Q@Q@Q@Q@{:ߏ_aQL}sװ_qK>aQL}sr;(gEQEQEQEQEQEQEQEQEQEQEQEQEQEQECpz]T,Q|?*#86Wmaiss* nsFO$F ɾN*OअK`h®pIPO]Ǎ7U^EJZ Een:"ʹ*8n+VFwIb_P|Ka[Ԅ`QEQEQEQEQEQEQEQE??;~=>uxg/?3OX}??nGV}ǂ4N/uF{}3ߦ[W3^}ǂ4N/uF{}3ߦ[W3YS?EVQEQEQEQEQEQEQEQEQEQEQEQEQEQE| \DI\> !-J#5 V8]'zw?jD߻9Q\·_53 Mº%j)(((((((+~Ǭvz?}??;~=>_~ge/ZDG<Ehۨ3Bh_ gLܯ??fh_ gLܯ??fG֧S>(0(((((((((((((()%sC%KVg?DxIÿ#'o luxJ+uZ?O6KK]!58g D5×|0 6uԂ$ QB 3;$ܒh)(((((((+~Ǭvz?}??;~=>_~ge/ZDG<Ehۨ3Bh_ gLܯ??fh_ gLܯ??fG֧S>(0(((((((((((((([dOϓwmǚ [~qt7As^xwWZUϖl-gys 䎀⸟Amj3֐i/}BrR\u`'8OV{'Ě">E;VsI9s'IZ-fd)m_-N3dGZGZEo+CD^$qɣ_sDukc>+$ CdBOz(_r5Uꭤ[m`BO>$Տ4 ʫV+2=˘8wXq}XM'FUWoKaR_{3JVF1Fp#L]MAηWRG$MG$QkPEclP'SLJ%$\=Z.nIE;_~ge/ZDG<Ehۨ3Bh_ gLܯ??fh_ gLܯ??fG֧S>(0((((((((((((((P|5a[_~ hiWDRRUV :Vzʧyk¶5kwujB]]%.+PK*FKMI@n8"*ưZ6[ۡb_ORǒiڮĶp ~XXO+>WwfӚQ__7QEF!WO O *]QTۢQ*L((((|zoǯx?=^N=cq< vRuOGQx4/F%No{}c>k/F%No{}c>k9|qjz3袊 ( ( ( ( ( ( ( ( ( ( ( ( ( (7 %_ѫ^Lwخm߱m3gwgMKo;u\۷l]ҼJۛomG_nd1G*.L9F N8#2_?=Ҽt|[kz}l6 :x:-̺|{"p;ivF@븆9|R/[8[fD1$M>-ղƫ4 dscO[:S\0*'3ч>\ۿo׬J->h \[j%cU'f\d>Z$x2ƺ|hΠ 8U￴i5?,zFwJDWT({KVg7C-HΉɊ6خ}-x'|R/[8(ɠ0FK<&/ }=A>K "At==zsGu]5gtEVf+_(FKDp}>o:JTZ2U+袊QEQEQEQEW<SX\ǫ~Ǭvz?}᜾8_=cx>OQZf;ľ~o^?1{;ľ~o^?1g/?3OX}QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEP^H~otM+٭^۷Nswv>%^FAT6Z-? hPbiϓs$<OM ۝^9S c|7L+>h%jͿd~J}~,,ROEQlT4ps5ZX{ P;_KݶӲiMC[(K ( ( ( ( uxx{:ߏ_3K֧Q>OQG?#+Cо'o}:£=-+O?`'o}:£=-+O?vQuϢ+C((((((((((((((+о06oG+ͤQM`ŋT+zupŕI~y5iT%'k3bu1!s(CnWzw^1ׯ|R/[A{oVfˍxAN^Hq̣ʅnR8uxg/?3OX}??nGV}ǂ4N/uF{}3ߦ[W3^}ǂ4N/uF{}3ߦ[W3YS?EVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE3gWrA #k^!nx`0ku/Z6}L2*#}XZY='67fmi'sm* kN<_C4Wsj{g>VQ7c#B<(0(((((((ay_W<SX\9|qjzu}??n8 <v|'Ӭ*32rXc <v|'Ӭ*32rXc_~geZL(8Š((((((((((((((((((((((((|zoǯx?=^N=cq< vRuOGQx4/F%No{}c>k/F%No{}c>k9|qjz3袊 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( uxx{:ߏ_3K֧Q>OQG?#+Cо'o}:£=-+O?`'o}:£=-+O?vQuϢ+C((((((((((((((((((((((((+~Ǭvz?}??;~=>_~ge/ZDG<Ehۨ3Bh_ gLܯ??fh_ gLܯ??fG֧S>(0((((((((((((((((((((((((ay_W<SX\9|qjzu}??n8 <v|'Ӭ*32rXc <v|'Ӭ*32rXc_~geZL(8Š((((((((((((((((((((((((|zoǯx?=^N=cq< vRuOGQx,ceg"K{sHesBp9fk/F%No{}c>k9|qjz3袊 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 4wadvMySr<~|zoǯx?S?.9Ec??n8 <v|'Ӭ*32rUY.N`U'fC?|9lLH g$d4asz>g(եsVktvyn?焿_ׯ/4asz>2O f(ZV5r٠'^zCg}xK|>q<% {%ς|?gtj* =v_4asz>ܿ Gn?焿^_ iV'L}x~m0չI=v?^ `_yn?焿_ׯ/4asz> ? 6j_y}/<_[/kח~m0չI=v?^🆛oL5nqx]ׂ<>C[/h-5? 6j_OM&8<gzAly}!-4}xK|🆛oL5nqx]ׁ|' [to3kAO gxK|>q<% zOM&8<gm:O^[_r3~q<% ey|' [to3kA_ iV'L}x/S-/?e ^m:O/4asz>ܿ Gn?焿^_ iV'L}x~m0չI=v?^ `_yn?焿_ׯ/4asz> ? 6j_y}/<_[/kח~m0չI=v?^🆛oL5nqx]ׂ<>C[/h-5? 6j_OM&8<gzAly}!-4}xK|🆛oL5nqx]ׁ|' [to3kAO gxK|>q<% zOM&8<gm:O^[_r3~q<% ey|' [to3kA_ iV'L}x/S-/?e ^m:O/4asz>ܿ Gn?焿^_ iV'L}x~m0չI=v?^ `_yn?焿_ׯ/4asz> ? 6j_y}/<_[/kח~m0չI=v?^🆛oL5nqx]ׂ<>C[/h-5? 6j_OM&8<gzAly}!-4}xK|🆛oL5nqx]ׁ|' [to3kAO gxK|>q<% zOM&8<gm:O^[_r3~q<% e~k3v/5 ,eaO1|' [to3kAO gxK|χux9|' [to3kASF;{IJ0X|=A`ܓcZ*twm2>OQG?#+Sǻ?xPEPA/Z袀 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (:UEQEQEmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example2l.jpg0000644000175000017500000005213610504574206024642 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?}JP[,HѰYEU$ђp09 T<'qW> AOn_UNX| $8gamWcPI&,$jn-?sLY s֬[^yu` eKU)##!AhG:"q? x?8Opۏ?..PE2|-v/a{K хvu㑸)w:"q? x?8Opۏ?>]:u෈Kq4{6Bdž/p{t+BT +e=N3 gamWcO30{t13N>R23ۏj')ǵ P30{t1'tDo=:n?cd8hi]TgTʲƒFC)?ր"Koxy6gZx?8Opۏ?͉fASXH@#?9}cֱKCRi¢TyQRO@gamWc_[^ZKhHc0Q8of}opjpFIEf#g ϥVv Xm9%Fp>cBZ_JΛ!?ǧ"Q:l}yױǾOi>ofƑ&c4DWfWh*J>c[6igecR%"EntN>c|ƒ%kzr{HALGs; 2p:7q#\gM}cӐx^3zg }1p#}~F8׎{bG$qӟW μ>fA99>dI$O og_&N?#GBN8+7/__zrtL=99>og_|7uؠuttL=9:lpTϷ3aONGN}ϥdI-5tL=9:lp꘏uy8H#n=\gM}cӐx^3zg }1LGs:G$qӟPŸ3 J:lp6C8ekNNxwb?I$OЁ瓎9:lp6C8ekNNxwb?`3x(qrG9?r6C8ekNAyxΛ!2ǧ'<;1SdӟoF@8RKtr6C8ekNAyxΛ!2ǧ'<;#}BN8(>glW μut0'#>ҹyxΛ!2ǧ gM}cӓ꘏udI-4DX 8L~\xgM}cӗ[x:v{ v~G<;#}c51\C'*r 4Lm<;mݖ'>5 1grgO:N/DɖW4fƫR[?Ƿw*&3aiGaLzw%YDV<6=#Wj̗*J0W|AJc⚗%?EvN8FKd?i{}>?5*rZ_y?GgfU~֧?3y?Gn?缟٨vkSK缟٣3y?QQG*/kSK'hLOTQʻg'hM5rj3~?4}'j*(]j3~q=i{}9WaZ_=ifU=Oy/gf=EEOy/n?缟٣3y?QQG*?kSK缟٣7OTQʻ%LO缟٨v%M4}'j*(]j3~?4}{}9W`?i{}>?5r?if=EEOy/gfy?QQG*֧?3y?GgfU^֧?7O缟٨v%LO'j*(]g'hLOTQʻ g{}>?5r?i{}>q=EE{Z_=w?ݛ;ٸ%L?]Óh88e}k9:ӔQ7_U~q_c[cܔjo.?uk^{l}>_{8K_yXF{=e~x! + %?^{tMKBVzk~LEV QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWyĚ90n91}ZrqM7̾gSO_U~q_c[cܔjo.?uk^{l}>_{8_yXF{=e~x! + %?^{tMKBVzk~LEV QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWyĚ90n91}ZrqM7̾gSO_U~q_c[cܔjo.?uk^{l}>_{8_yXF{=e~x! + %?^{tMKBVzk~LEV QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWyĚ90n91}ZrqM7̾gSO_U~q_c[cܔjo.?uk^{l}>_{8_yXF{=e~x! + %?^{tMKBVzk~LEV QEQEQEQEQEQEQEQEQEQEQJUK3I5hgԗerAzzYԫj2ZJWFK{"1o1\<~ S4wEsۑۿ|%w#$2B^Y \rSއ`],Lj;lhbU (N((((lj4s`sc2>yĚ90n91}ZΧ;0 _R[?Ƿw(bߪ\~vV|%hq %?^{tMKBWAJc⚗%?:R(@(((((((((({x+gPtֺY@+.77Dyk{G|'ڵ&uvzȣP3U`oc9`~06-jF":qkR/ZuiVZ 1jg;p:N:|u-X{n>W%^٧#s{$µ"bpK&9G"wk-uCfn5esrpQ֥NkEv#[0cS[tnO;;QD@TOva>; V-m|ݏomrQſT{J-|AJc⚗%?kȔ=z63++5/K!Yu7%2QZEPEPEPEPEPEPEPEPEPEPK:t-<$Qs[cc y>svkD2ѝӧmn:W]|e)U|CɴīVNwʯ32j1Sns&H-UB# yrZt淔n{jwր<4"{Y$9qϷlj!j~j)S`u Nrߐ;=$*I+>f)`!py#¹lԥ!j=G.n1I;6hZ{tGce\+i=+^1p@UTHqx؉sTz*|[jƂlUL3dejwfG:dc\'8=,y>ѐ?{0Km8ւqJ קwO,׺Ova>; V-m|ݏomrQſT{J-|AJc⚗%?kȔ=z63++5/K!Yu7%2QZEPWVX )!U99FN*[S*m/l_+`pG֡/o}fvyҳ\d~Ua*s Ǹ?NA  1Fr\6 H|R1 p9{U+xeIbvI+R:{$irZx`0vGNL楣VaQԌi/O(wcomVRO٤[aEUQEQEQEQEoxvqksx?Һ[yJ\pȧ`2WEk(Ԧ-5QɛP U5)]gm/L-Ҳ=:u'O]yM%?k ]vdvrX\OZEV# [hm0dA5?սny9<~^LхZ+&!#'#yĚ90n91}ZΧ;0 _R[?Ƿw(bߪ\~vV|%hq %?^{tMKBWAJc⚗%?:R(@({gMQm5!k˹$]1FxY#vGBYN#qZ2*CnXk[lFC,B?Ԛ"4Ъ7KGouqH|#PS%$F HAj֛i7VGQb}# Һ5]kZڳmMc`BW jV** FHQ-R `92 ;Gː ACk6CMo +C`((((KNs<} m[\c2J ߲,V-8RT˶]9s"!7vd,B<~HFͰ18ogI]X59[_/jzV.ب+:HmӞC7$~A:嫣F=yd2Iw=1{fh凊% q~V /HY InIaֻpxVSfc^i(C.m:s[mh[V>YkO]e/8O9inئ*ʶzt"Z+3fú9#6Ə if X5i6$x~h|g+ľ}>uC8BQC}qc4zYe6xcqJ(8Š((((χ'$qqq?]Óh88e}k:g|54v[KnWOU~q_c[cܕZȔ=z63++5/K!^)ezlgۦWWj_B_oKeJ(9(X&*(9U_P{֔tƨy2ׅݬVX~\p+2n^W{SjjBjWUOktP$VE=8 j]6{K{֋sRI`T6L2:W6mLte%Y):pG W<'+wu*{܎-RE]{Vm1Dv>;pz0 N<OD1-9 _\@#+"_9+zl(((((Ӧ>H:[7G#GɎ~kerU¸IGo[܁=V7,5a4ɕAUr 7E8=Ofu@5 Zǵd;@݀ά;a?`P3I'ȟ;uV Z'@NCf+QX֓a]+en2#Qj⫧,Ӱq\ȷcЩY(WgAm6[An'ASjG,˟s^wc+>ͨ1sk5vN[)X'~ޕmܒ0~g*\Z毆AV6l޵d Sy惚kT2=gL/%?3,dfK.F7vuWv1iFC2gmW}0QEQEQEQEWyĚ90n91}ZrqM7̾gSO_U~q_c[cܔjo.?uk^{l}>_{8_yXF{=e~x! + %?^{tMKBVzk~LEV QES)ecb=@Tap?>JJ XSϨ*y&@k?=F9Gas)Rp~Z kU[XgfMzg#:[a#$p_Ql#Mz~#:t9_O(((((ӧ)·fW)?##Um+ 9$޸Fga*sы:i5OVfFDe#\F~:MikA:{V2E#)"Q(mFdvvc\Mhka6 {uI|2+j XkbO6I6|ꄞyĚ90n91}ZΧ;0 _R[?Ƿw(bߪ\~vV|%hq %?^{tMKBWAJc⚗%?:R(@(烙;;X,y$Cp 'I33 |I]#*pWKLdT-Gq,㒾;x$vAdGWn玟"Ԯun<,rGO:+z& [J/ P;'I8*oMS*+QZ-ayruFI1$WΧ)lMjndVaEUQ@Q@Q@Q@zbđ_zlGTz1\/ɞTsɭ[cᨚYFTb[KNxEpri R.ss&Ŵ9f&9ou9(0bx8 ]lX ԌscQ\enx)|I :*'^V ٳQ5m[kxۊ#,K?Cn\[ErPMZ=9S;K%Ѯ)#=[YE>[ m&4qy`>* A")`#5M=#|-+kR ą ~t(QEQEQEQE|98&ss~_qָ:>xG9 9?s/cY>fbߪ\~vV|%[KnWO2D9ѱOn_^)B_ NEIYJO&O:hћwFGƓZ[A 85V9  V7F:Ҥћd5{袼~jHׇl%.2W;OP+Š((((χ'$qqq?]Óh88e}k:g|54v[KnWOU~q_c[cܕZȔ=z63++5/K!^)ezlgۦWWj_B_oKeJ(9(C)Ў) ؚX>ϙꜫ·* d[ԳCᕷuB;AGtgVu[۷wQEFAEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP]Óh88e}klj4s`sc2>Ova>; V-m|ݏomrQſT{J-|AJc⚗%?kȔ=z63++5/K!Yu7%2QZEPEPEP>s.:9*m?q~TSXTUSFеyVoB;H4QBJ.T\( (IgȞXE;IyUyH"& :svL[tsI4r[ESQEQW TYFFDuFG=-?dG:)QRBR930oQUŠ(aEPEPEPEPEPEPEPEPEP]Óh88e}klj4s`sc2>Ova>; V-m|ݏomrQſT{J-|AJc⚗%?kȔ=z63++5/K!Yu7%2QZEPEPEPEPEPEPEPOVFOFE{b$N9cl# CK$`/&2qU>{`;_`dtQE (&w# |y}=A.-B&1PGb8`eM/Q鑆U QX8w#rB>pG8? 9%fnQN陔U>{O699D(HR4i+)(((((((((+rqM7̾pu|98&ss~_qֳ}N'W/GaſT{J5Xݵv=ն>/Zeϩلjh5Xݵv=ն>/FR[?Ƿw+C)ezlgۦWWj_B"SLܯԿ!/g/ֿʔQEhrQ@Q@Q@Q@Q@Q@Q@X1)䤒#yoz ufE>p~oRvnaТp e_eaKԚ (( T[Uu;kj\;Ou9VS.x4*eFG^G ,V˒+t2k` 9|g֫EZIhKDQE1Q@Q@Q@Q@Q@Q@Q@Q@Q@wNϩلjh5Xݵv=ն>/FR[?Ƿw+C)ezlgۦWWj_B"SLܯԿ!/g/ֿʔQEhrQ@Q@Q@Q@Q@Q@Q@MX)6s*r;Fqi=@ȏ~N#d#˜ar?ƲFfaGO{n0UsZߘQE (.-Vd oC8XŌnhAV[uQʫ 2= :X("LD㞪}=0&ϹM)- GG2n#T8ϧAێJ(JESQEQEQEQEQEQEQEQEQEWyĚ90n91}ZrqM7̾gSO_U~q_c[cܔjo.?uk^{l}>_{8_yXF{=e~x! + %?^{tMKBVzk~LEV QEQEQEQEQEQEQEU,/. 8-e}85Ǔ|_3AG8? wf-3V@݆G:Kx" Hl'О{wbj\[;]̅Lc>qR IQEfEPc1D|rG}[O؂0n#CTJLRb'ϩلjh5Xݵv=ն>/FR[?Ƿw+C)ezlgۦWWj_B"SLܯԿ!/g/ֿʔQEhrQ@Q@Q@Q@Q@Q@Q@UYa 9W5`}`p=!1]؊܎d/ # v7 d}A# FZ+`pA 4j7ۼ [ƹ#?!J((bBNxQ"wSDGs2JU\t{z{?ƧVkh[He` aчTOq:i${ΣkQE1Q@Q@Q@Q@Q@Q@Q@Q@Q@wNϩلjh5Xݵv=ն>/FR[?Ƿw+C)ezlgۦWWj_B"SLܯԿ!/g/ֿʔQEhrQ@Q@Q@Q@Q@Q@Q@T-SK*6x aŅJ㕖DrrpCۡ UV Xe?[x#$@ q8߆&]eZ((*~쿟ת+م9"`?./TDZu4Sq:6>vg \?s^"I'QEQEQEQEQEQEQEQEQEQE|98&ss~_qָ:>xG9 9?s/cY>fbߪ\~vV|%[KnWO2D9ѱOn_^)B_ O<7w)Vb,s83ޥ! +?xĿ&T+C(((((((((((((((((((((((+rqM7̾pu|98&ss~_qֳ}N'W/GaſT{J}ٽ܆}uLt}ӾߧIZc> %?^{tMKBWAJc⚗%?:R(@(((((((((((((((((((((((lj4s`sc2>yĚ90n91}ZΧ;0 _R[?Ƿw(bߪ\~vV|%hq-f$X#rwT8'ۀq*Zޡ#k 㖞L^8:RandU`GkILh/?tqi=闸} UIu?~ :?_SG}zu/'AALh/1s4~ :?_S@o?dD>_q|qILh/?tq-~ :?_S@o?dD>_q|qY^4:84~ :?_S@o?dD>_q|qm ^4yOoe?_C@o?dj2q^}|88IyY^4:8Oe?_C@o?dj2q^}|88΃Ϭ{/qËuOoe?_C@o?dj2q^}|88Iyz/qË\<'2j2q5[8_hQW@>_<{/qËi2j2q5[8_hQW@>_bAi=闸} N:'2j2q5[8_hQW@>_<[H=?闸} .t}f{5[8_hLc4{(׫_r /?tqi=闸} N?崃{5[8_hLc4{(׫_r /1s4~'Af{5[8_hLc4{(׫_r /?tq-~:>ILhLc4 Vc&N1=C:84~'AALhLc4 Vc&N1=CyOoe?_C@q|qILhLc4 Vc&N1=C:8Oe?_C@q|qY^4 Vc&N1|1'}M!ܿËuOoe?_C@q|qm ^4 Vc&N1|1'}M!ܿË\<'2|88IyY^4 Vc&N1|1'}M!ܿËi2|88΃Ϭ{/q|1'}MUIu?~e~_N:'2|88Iyz/q|1'}MUIu?~e~_ ΃nǝ'*3̿|88IyY^5{ˉ%y I1V 1Lc4{(_r /?tq-~<3 _KALhFE\wq :?_S@o?dRw~KM]JvXċ#mrW:s#$fH>QZmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/annClip_PropPanel.jpg0000644000175000017500000007524010504574206026316 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222L>" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( +'_Igut3mvv;KF5e-FYc bqnOZFOM{?Ί?/)mk?q~u =_qR_?/)mk?]޿.tW1 }Kk]iߴ{w_z0\%-u?ֺ~e}OEsq~K8[ZO?Gu =_qR_?/)mk?]޿.tW1 }Kk]iߴ{w_z0\%-u?ֺ~e}OEsq~K8[ZO?Gu =_qR_?/)mk?]޿.tW1 }Kk]iߴ{w_z0\%-u?ֺ~e}OEsq~K8[ZO?Gu =_qR_?/)mk?]޿.tW1 }Kk]iߴ{w_z0\Ajp|=yK,pcVf/PW,(DE]CpHbjeMɧ_ptQE@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?^8ꄃwv[S*LoW>pLjEه l8Pa\ό_uV^4JbuVK(rΥU- ij\ |ajmcjKtͧ3RaH*@uQ\ό_aak7;Rgۿݏnoݷo9BNԖ鯛O6f6mT1\0$7<ι0c%jB{K3욥e)CQOAa]H*&n򿳵/?CGwq\ό_uVmF{[kkٮ#D&O.``˻b!/ ?j:|bƪj(:|bƨ/ ?j!/ ?j:|bƪjdE6T{M=>oD4vCbyqcG=3?!xw?YmkwLF>qcG=3?!xw?Ymi'&7ݢ)((5-j=:g fP85PӕIrkZӢ4n V{uM ˑF {z:' Aj)ʜfŠ( (hZjf~O?sv9j.["QHAEPEFUUӤI gѱw隨?յ*ݢ](麬<~r\d5zQqvNdŠyZgT_&X"Ip8E>q3Cۿľs\~|гETU]V VN$X~c0N1ϧ*T/8J]ޮhZjf~O?sv9O-u[lmW8$48I+Ӛ\;}f( (((<!=`zy\zs!<^~uwƶgaERT'Bm^jjdp>"3ZK@g/x_@h__G}LJZ*}LJKm+V>oCQ^eN"k#i"Bd:rI5Mφ_^}o&>zgBIJ۩RӧV\v[n}_w5G]VBFg]QyAGUE^_r DIoInb0@@F?x'>9䁏ڱ$aK/MWUE:U9ۣ_zk*!ҨZ5:p+ Ҽ,7 5Â͉0d OvUΙBI$Ґ[;ZƑXIF,' FeX)Aʯ9W{EL)ބO6o=W^Z_j6H2N̈+˱[# `4I'vng&WX+1:G]^Cԋ4K\z71mW|㼓M> 6̉'m-:g)EEK[$M,J*KM4jyGlJk(dNS̀8QrÁ kNC;XっvZ1U$2y+Jwi^zLڮpMv4UOؿ A-o_7g;>\ίYZU[KMq$;%w-=bO$סQR_|o~9wݽwxXXpAn-xC `PcrvwsFO_E^k_]KZ~ (0 (9̼px=?n98gq̇=yǧL9OXWן]]QEO 9d}2ZRY纗K[xQ]8#æ$7m#[(\ݵɖna$h -.JM][nIeW21BP9r>jP麮y];k|*kAwb0[.)ΩfthaۆN1@G͸0#8:B6:yiZ@+C|x&]Z{}fjrAg4)o<2˸`8F}3SBgufkUa%Xw$v>8Ҥ-̳wYkY{rbi2p66|-1e~MP$M:e&ۇ̩_8G=Jt|Ob_:Rka 5wkCy 8tDqu?Jui!ZA8p)][nIeW21BP9r>lN:p\@tǦjMi W{|#XV a@w)-HdB\`%,r^2FFC4A;KE,+(~GάA ːaI5hi&}68Xi[#!ބq hDo崶wi>I๖W@b@n0XsxBk[X1Y^4~/8*sǧJvncZyǥaYIRilVr˹F G?잽*Qu)JUM_E7 KG>AY? k Z[H֓-  ݓN[moev;Eq7Tp1W^\v<#[:\vo j~wo:V_+NE$=YՎ9'^]VuF㷰 $g#o|ݽ1{nw5urI;z.ciV^D3\7t2v瞇:\v{oc\~>AY? h׿+'-S'Nvs*HN8ݱG\Щ)(UAG*{$_c}{=Rx_NcZg??)5QƐ>c&#C7| :*Qu)JUM_E7_:ܓ=ţچ6ݡqKm i3PvN2qY復.\|WLc!1hvφS=soODzr+O4J.&[,2s'<~rYڑ{oc\~>AY? j];Ey$f6ch#ֲ4[[lݵ\y( pv)[;[DHBJw(uRIO)ԕ>xurI?GDqNogy.61׏Y]bMGGKC1Ppqf?ZK4&G6i.wyet3*jUDٜ9oODZ=[?@ߞ6̹&wLF>qcG=3?!xw?YmkŚ]n>I}x9p\p~n~lmױ|}cbP)>:SRqtӯPtF])&U::+?(йkj5ĺ-W:[#rzI=<)q|i$}7h\nxYZ,-c:w%񕮥xwI0N0'#mޗ\qO%YQ^~:+W:֛# ;1  0xf;wP~#ǩ]%Kf8Gnhv)$ie:nI'jyf_~zn޹]?U&jLyAcGO gUmTpr{+w;+ķ:v 0rye;{ _Rۙz]s}ۛ4QEYQEQEQEQEQEQEQEr<x񩓐zsqG%o ^Kx<^~|y2S' E:KPxOՍlڊ( (|s#u;~lkw7vv||lEEyhɬGHW67@I'%yDl6zuZ=H:3*3taY<̱Ƕ{GFrO` LYt[Uu2Zf@TA;QNq;DPiW6ϥ][Ei%/A;IfrO*D/my^x`'t,jy=2>Vˤn<$ݿڞ^Om6* K]>o\jv# J&|XS3@{s;&iO*$ڣ`Zo߆ 7ΐciu |7d=:Om7J+ҢdO7N.,쒝ꠐEVRĂտ*oӟnu1.7c8@}Fw>o9<{ٮhOOmnUHtmR& y-fv>ZZ 7z+,!>궶Fg|ˈLeESXp 5%1gTfdhI cVoKA5[5nv穢XJ-VKA< Zw[Q/m3yRzۗ?QC61`{u:ciT0fUzzy>"3iXLs[$ . /ƛ5ռ@# l=@Qsqmե\ukRե^_m6K3Npб' zՕմ׳{-Z6 8-q?ŭ}Y*y;$`;.r{Qo4uW{xͶ%pmch4m[Fri/qoB&o0^]K4V0$-T@3 CMlu bٍLs8vx3O)U=mV I䪀 gXZJO9}ͯ|;-*Z;r'ONƭC5(&XaQI!,P wָ{LW$.//noV8|n@nQvrFΙKO-J&N880z~ESZ -TV^j[˨][M{7MBխcm0J)g+2h`ԧfl~xytzs[MGP4O9rd28Ȯ&G#7qC !'+sQ_IJGVy!2:\20[֫GG{ve9\K/~ ppd[Tmj 3GEVoL sxkQVdcMjVIi!z1XOcN'dڬr[x[m:4Kkwd _?t@HsAt]:OO m=btt7:d0^C7w,p lѫG d*UԤ}.[VU6hpr x`Hg+;vby/A#RTnt֮M$gŖQS"3&y 5M4isT8jWkmZQEr!EPEP!9-?Qr^Oܟǟ/52rO[>-!+u?.XB (/'k\bJnqU$t :6};/v63g+Z+x,ycv߻٠ RKeelL$*~fc+:}ֲZd8$gPTa)E]eyly[̒1ϸ5h՘QNuvReEysc<ᬧ31xRcG=_?!xw?Ymk,y,c]^?Ls'D/GK--:WQE!Q@W/{ ^j67P]D472 C'GhS#Nmƕ΢ki|3!$eHՔҮ75c(I#FOt摗W:XEe@$}kHɧ]Z3Xa+IS[Ꞌ]3hd0$@>V1YE[ǝ2Ih 14nG~BcylꞺgf:lD#yl٧woƭAygoYiw ѺjӼHn,ằkT"i\ʣ6ݭG8F*湶o%+=BQpRL>\ ^qsXJ-מ=8Jwy={uVݱ:kxS(Y&Wsqmbm9h Ju-uBVc&u 00O 8sL/u>ǩY5ti?ƽd-b7X9r'z4d2wy[ׯ}Zksd7>ԉor7m tIlm[tGY1!qx8Q֗k8U_ٸwUhkL_[_[Fj.p%}vI'4<`R'uӚF]\aa?gؑ:ײ_?Pʕk_f2Y^ɍ鸮pAP*rn4J l25*UXo@;|OxZ앒K-&1A~GL_S4w}m_1MF6ګyOQTKMYA}LF#fARpFxjiZ̨a^M/u:+[꺌064fyٙ{sQO-RЦɣL J 3^*JMA_[tץYI WwKM|ץ΢|E]}>31:u*uvVWrR$7[o@Fv(ioPךRK5gUP^Yr]²*tnCڹ}GƷ[owGٶ{cQA`ͷǾ.7& M;KkN[αNg: I/O;Zi[w]:cEF'}@}zśPF3!GE?(8(zKcK[{*00@}(ҭ IFKO.oZ4q&OgQg_?ϟ._evvsc[Nl_ _],2oL3ԂGa0z䜍jtoV[xfJ|wem kOc^mM] lեエշAc5}Ҧ J[i$7ch5? @GƠH# cO$)J2\0۳4aVݐGW7]BOxI `. gYXc+#8u(ϟy_Zk^~aV*>I]ks4{_[}=sTԼow6)^9n/asX4JI`޼?O䱺͂ۗ`Cv#1Ň1;ӵGY{hb#:|APS+{t_ؗj]%oq%{+-&]r;y'l*a9ݜ2?Wve}*􈯧:%ՒCfTΘI0ǞXH95ķ> d0F򫲨+:ӫN wI}z*V;򴞉|Wv볽wKhWWj~;l֯*@$`sߠMkCmEj-jN8~6`y㌁;W N-[E_wcΎ.\Z㶋 +; o1D);\m9Ƿj<5,-#d"529%ϰQUi??׸ee~Lm<3v$+nIP0î@8揩Yj䷻1'"قPG8}5N8MlZ }ON+{+ZVOb-#Ԝ0;z%ڶfMZq[SxݵmcRЮ5մKw"٭_tUe' HA SIHb,2 ߻y#>ZTb/-[e?Zʣ~m|:ʺ&/'lSF ؁Ar;{'[iEC1]`q⤬JC,gr=쌧8"([x|-wggKZB4)+GTD pX?(F D v#8*Z? ֵQH2*Ha~hսc#cQ[!:0X{e̹.p})VRgCԢ((m[o,y,c]^?Ls'D/GK--yE>uKK}ȅeSOCv( (zeYKuAwr)N/.̨NP]3vhmU mbn3>>khqFsL@l*!z(u'ޞ2%̤6kPEZv$t|6+C {ZzhYJ[sz95EՒImV֔c'vuzxKsoy1trA'9GxJ]qi!Z*>Vqq۴.)sE Hek%esxfcuv+00w }jxK}*m1sk;Hۃnfr$iQ* -W֪F M(wd_[DO[M䑑9QC^ቾb-+UvsS׭hQKղ\_Yҏ;~9K$I7pm_ҠO !խ9}Eýl9! 1] KY}Nҷ;7ʛK崩fkR&DR XduNѴȴmO`M6 8$j9G?"UJ}o_vaEVf!EPEPEPEPEPEPEPEP!9-?Qr^Oܟǟ/52rO[>-!+u?.XB (:լpڮ'@R4YHXHig Rߋm 99LH U$mz#2vb277mE-VQtH"Gf<}= J(;CMk%Ln˟0F~FUQYZ휷,v'/VJ..Y̕8f9Vyf(㹷uXd13ۖg*J(mXmݞq/k?Z*+{/!;<,HVeۻh( ;{ 71 #8<`ҦDTEDP@[+!v18v>Ż@O*ã ((΢m,wC[x}1ϣ;,yT<1.cu/9~"x#%O?ꖝ?~c} (((((((((((((((((((Cǟ/52rO[>-!+u?=o?^8u ²VDzdUޭ(9RGPkZ(&GVnovKmP?e]xH)čʣy@ (31=*M 2c آe"EtHꈁk]#~kQ@>~֢)FPI 1-uot, ##jWڬaңcP>U{n0$ GJQB Z( ( >|:΀<ǟ: }n>zBIJ۩RהXX_Լ~>WO^[u<Zt ɍ7hB ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (9̼px=?n98GkY-2cv\3}7|!kZޟtȉփ NJ:rGl$V3$3`ts:Zh^R&{"lEʒ:Z^1G;ѧ*&qYkkdrwCmP?e]xH)čʣy@ȹͽē"!ܰ8RV?I3FSd[->|3ڥ-!m#"ff8rIItoou"{gg ̻w`~-dkE_kZ (pYC$`0G4jY ӱ{-yVV,zսвf\L8+i_jo!J @ZvWjQEQETU-}Ct<1.cu/9~"x#%O?ꖼǟ: }n>zBIJ۩RӧO~LoERQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQExeƦNAqu%z=.w'=yǭL9/ Jz]CǧOz=?V5;j(+/ZᲴۢ9I!%1zԢI$ ukky`%Lp9"sJ+x,ycv߻٠ RKeelL$*~fc+:}ֲZd8$gPTa)E]eyly[̒1ϸ5h՘QNuvRU=ąf]H? ( s<*dEDTE 0 *սc#cQ[!:0(*[o*>|:| t1?A ünK^Qcρc>RcG=_?!xw?Ymi'&7ݢ)((((((((((((((((((-!+u?=o?^8g-vIo2K8@G>8լhYmu+"g2*VʔQ#5ATqyg ՖG*x ,6U׉4y8bHܪ1  I:H,23%czTc;de8A@αnۻ<=_"?H],: ffc$H@6P^B'vxX˷v RO_fG1RF d{@핐;gjݠp aхbǬ][ -fes@H=86tol~Q@Q@KmP?ER?@Ycρc>RcG=_?!xw?Ymk,y,c]^?Ls'D/GK--:WQE!Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@?^8uKK}ȅeS(wC[x}1ϣ;,yT_nEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEq?)S@YhΦr(e[H<uG'Px]CP/z~CǭL9/ Jz]CǧOz=?V5;j((YnxHc8U᭠tU#Rq(W֓OTl|3U[I UV5r$gUίsi4|7}21Ӱӭbmts9f fP?ٮR8-Dق'َYߜvu4tjZv=­ǝAf*$`^Km{Oյiۛ{ەFH]q QTBìd=^\Ҳh]VQȌ쮄(W! ڿ2jph}ɵ t5Pn$dw ]r͍tS-]M%Q]H O6GX/sqd;k+}2Lh4.ki+HA;xV%@l2N0z-F][Dki-RDt&Eu!цB `@[kv׶6Hqv$.vG͉-9n izd '̸wB뷖%h$[ {hg #^ $C`m/w#@{a2AX+΢Xnb>\d\r @:i7>١Z\٥]$@ " GqoG'3P'OBy硭еBA4( T99UY05KsTӠdY% '@uoEr&ҵYm-+paXp(u"xNPWӵ)`ӥT,_'hbI x7ơJ=mu~+]#io2!އ{i w:±VFd8[h8 txԼak]^v=CEo,VmTkG]M%Q]H O6GX/sqd5xB^nҼ7|"jvImijra5j5v3mJ7ۑk<oe^ڲ^A#< ӏ#` Y5]7ՔkjP[gخ,WAn0ŗreޫA"[ omܶ1>FH0H2۰ lA׭@Md 8(@K|ϖi0t='ӵ-WPHP)Q(,'iH|Oky}okakyyAxXKv.Wْx8lc^#:YҮ&]O.%6Rw2>T<G5x~]tt;p 4&\.9= |QqLbn9@G<+bi6yi70~uEOɵtaQ}a7+_g~)%Y)DIP̸lvӭ^ҿ'ghm `)k$WKi~/Qҿ'gjK}oI[, &=~jγ.cG_޿*°yNDCrVQȢ!|,C|#pN@g/;?ݻ91e?SVd7r[K#PIl䔧i*-~,ӼU[NBs\i7 qa(V)&H.Taׅ=SQUBrv2'''қo/#C߷nν[3Ǚfۍ}=+CJюy$wl]\=ϒPݖ>^1dw嚦_M^x.I)_[oh 4fn.lRs^FGu22^3:}&6\ڽ}En3,Zm5kkdq{v ӌG?gWWCW Xmw|44We.h3{s>ae|w`@  2;dcw8[z[M$jmicɩĊ.dH#}z1.y2[RkMطG$ڶYmez(ٮ7BD#+Y*{MsiV:[[ũۙC8uυbi am$$?Z?wjD/< /L\6g߳0NgvMS_ Zs>{v--| `c*N@ȫվM&q?1]#y#8#m>.e[*Ngx3ܒq[:\xgif3rjC+Zo[~v7 +Z֓ˣ>cS׼)scW6nHݽI# c8m}VO祌ܰ2W4{km/o}<,g5Ͷy.YfbdeN:FXp 3ryՋ ywuyV<36nuS^;T՚]:nm6~r'2O<,V[>erOk]vzQEygQEr<x񩓐zsqG'5f/T~P?EA}GfF!GYfx|>?5~31[iA / ,gbGӞ{X+=o?G٧2&+tM9>!CEA埌V{s}Bkg'h4Oג4^Yn=(h(7|NzQbO!Gr?4}'k/ ,gbGӞ4^Yn=(Vz٧2&O?5~31[iA / ,gbGӞ{X+=o?G٧2&+tM9>!CEA埌V{s}Bkg'h4Oג4^Yn=*{?v[<pu[@`91ۀB=S?R[̷1 ּ+tM9>!CEA埌V{s}Bkŏ>uKK}ȅeS(ttQؔي?36YNI$ϣeEzBIJ۩Rִ7&)t7hB ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (*j^jVXaY6 8$go!>)+H՜&b0 LhDŽ_MO4^/&h3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&B|'S/?[Q3Y_O4^/&`+h#(bPTP0RQS*cQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Example3.html0000644000175000017500000001202110504574206024600 0ustar debiandebian  

Example Three:  a simple surface and its normals

This example starts by importing the function which we will use to read in a precalculated msms surface from the files 'surface.vertices' and 'surface.triangles': (For the code for this example, see Example3.py)

>>> from tutorialFunctions import readSurface

The function readSurface returns v, a list of vertices and t a list of triangles
>>>  v,t = readSurface ('surface')

We make a numeric array out of the vertices so we can easily separate vertices and normals

>>> import Numeric
>>> vn = Numeric.array(v)

We get a viewer:

>>> from DejaVu import Viewer
>>> vi = Viewer()

We add the surface to the viewer
>>> from DejaVu.IndexedPolygons import IndexedPolygons
>>> srf = IndexedPolygons('myFirstSurface', vertices = vn[:,:3], vnormals=vn[:,3:6], faces = t)
>>> vi.AddObject(srf)
To see the new object, we have to redraw the scene:
>>> vi.Redraw()


The surface composed of triangles should appear in camera 0.   The buttons at the bottom of the Viewer GUI let you change this display.  First make "~myFirstSurface" the current object.  Then, click on the Front button.  A drop-down menu appears with 4 radiobuttons: inherit, point, line or fill.  Try changing the surface to Fill.  While it is shown in this representation, experiment with the Shading menu.  The Culling menu allows you to select which side of the surface is hidden (culled).  Try rotating the object while the front is culled.  Notice that if Front_and_Back is culled the object disappears!
To see the effects of selecting "INHERIT" for the Front representation, make "root" the current object and change its representation from line to fill or to point.
Notice what the surface looks like if Culling is set to None: If the Front and Back representations are both set to Line you see all the triangles in both the front and back.  If you now change the Back representation to Fill, you will see the Front triangles on top of the Back shaded areas. Experiment with changing culling.

To make this example a little more interesting, we will add lines to represent the normals to each vertex , spheres to mark the center of each face and lines representing the normal to the center of each face:

To add the normals to each vertex (each point in pts which is a copy of vn):
>>> from DejaVu.Polylines import Polylines
>>> pts = vn.__copy__()
>>> vn[:,3:6] = vn[:,:3]+vn[:,3:6]
>>> pts = Numeric.reshape( vn, (-1,2,3) )
>>> p = Polylines('normals', vertices = pts)
>>> vi.AddObject(p)
To see the new object, we have to redraw the scene:
>>> vi.Redraw()

To add the face centers (by computing the center of gravity of each triangle):
>>> from DejaVu.Spheres import Spheres
>>> pts = Numeric.take(vn[:,:3], t)
>>> cg = Numeric.sum(pts, 1)/3.0
>>> s = Spheres('faceCenters', centers=cg, radii=0.1 )
>>> vi.AddObject(s)
To see the new object, we have to redraw the scene:
>>> vi.Redraw()

To add the normals to the triangles placed on the face centers we just computed:
This is done by calculating the normals to the triangles:
>>> from OpenGL import GL
>>> vc = vn[:,:3].__copy__()
>>> nf = GL.glTriangleNormals(vc, t, 'PER_FACE' )

Then by drawing lines from the center of the triangles to these points:
>>> pts = Numeric.concatenate( (cg, cg+nf), 1 )
>>> pts  = Numeric.reshape(pts, (-1,2,3))
>>> pf = Polylines('faceNormals', vertices = pts)
>>> vi.AddObject(pf)
To see the new object, we have to redraw the scene:
>>> vi.Redraw()

 'normals' and 'faceNormals' have been show in the viewer as a collection of lines. 'faceCenters' has been added to the viewer and appears as a collection of spheres marking the centers of the triangles making up the surface. (NB:You may need to do a "Reset" if you transformed the surface in the viewer before these additions.) As discussed above, transformations are directed to the current object so that it is possible to transform 'normals',  'faceNormals', or 'faceCenters' independently of  'myFirstSurface.'  If 'root' is the current object,  everything in the viewer is transformed together.

mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Example1.py0000644000175000017500000000450110504574206024266 0ustar debiandebianimport sys; sys.path.insert(0, '.') #Example 1: Getting started from DejaVu import Viewer #instantiate our first viewer: MyViewer = Viewer() #Now let's display a bunch of lines. To do this we need 3D coordinates: coords = [ [0.,0.,0.], [1.,1.,0.], [0.,1.,0.], [1.,0.,0.] ] #an array of indices telling which vertices are to be connected by lines: #(each entry represents a line between two points whose indices in the coords array are given) indices = [[0,1], [2,3],[0,2],[2,1],[1,3],[3,0]] #Alternatively, the lines could be specified where each list represents #a line through the points whose indices are given. The value -1 terminates #the line. The first two entries draw the diagonals and the third the box #itself: indices = [[0,1, -1, 0,0], [2,3,-1,0,0], [0,2,1,3,0]] #an optional array of materials. Here the tuples represent RGBA values: materials = ( (1.,1.,1.), (1.,0.,0.), (0.,1.,0.), (0.,0.,1.) ) #We create a geometry object of type IndexedPolylines: from DejaVu.IndexedPolylines import IndexedPolylines cross = IndexedPolylines('MyFirstObject') # add the vertices, lines and materials to that object: cross.Set(vertices=coords, faces=indices, materials = materials, inheritMaterial = 0 ) #add the geometry to the viewer: MyViewer.AddObject(cross) MyViewer.Redraw() #Now the object listbox should have one more line ~MyFirstObject. #The ~ is used to visualize the hierarchy. By default, AddObject makes the #new object the child of root.  This can be changed programmatically #In the camera you should see a square with four vertices colored #white, red, green and blue. You can use the mouse to transform this object: ###????### # next, add a clipping plane: #NOTE:You must make ~MyFirstObject the current object by selecting it in the #ViewerGUI or by clicking and you should increase the size of "cross" with Shift-Middle Mouse Button #before starting this section. ALSO you must select Clip on the Properties panel #and turn the row1 "on" button so that the clipping plane will interact with # the current object and the "disp" display button if you want to see the #clipping plane. cl = MyViewer.clipP[0] #Make the clippingplane visible cl.Set(visible=1) # translate it to the right cl.ConcatTranslation( (0.5, 0., 0.) ) # activate this cliping plane for our geometry cross.AddClipPlane(cl) print "end of Example1"mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/surface.vertices0000644000175000017500000007700510504574206025447 0ustar debiandebian-7.077971 1.661946 0.256205 -0.590810 -0.659212 0.465171 -6.670194 0.496391 1.691761 -0.862661 0.117826 -0.491866 -6.928249 1.696931 0.595264 -0.690625 -0.682535 0.239132 -6.430055 0.214034 1.394297 -0.662545 -0.117472 -0.739753 -6.837832 1.379589 -0.041259 -0.390694 -0.894509 0.217284 -6.208928 0.021615 1.164239 -0.809964 0.010808 -0.586381 -5.878191 -0.116878 0.812425 -0.644595 -0.058439 -0.762287 -6.580593 1.271873 -0.314891 -0.176327 -0.984273 -0.010743 -5.492701 0.401808 -0.099909 -0.901589 -0.404230 -0.154064 -5.331727 0.498831 -0.650445 -0.806898 -0.347158 -0.477909 -6.445921 1.353041 -0.775470 -0.064101 -0.916632 -0.394559 -5.086001 0.095459 -1.708011 -0.970715 -0.078244 0.227135 -5.033598 0.619343 -2.310819 -0.933284 0.295959 -0.203442 -6.397677 1.835347 -1.330437 -0.023898 -0.514711 -0.857031 -6.053586 1.919875 -1.444705 -0.253293 -0.571063 -0.780852 -4.928777 0.787518 -2.446005 -0.858412 0.416084 -0.300004 -5.929512 2.118939 -1.604721 -0.191256 -0.471530 -0.860860 -5.338941 1.881940 -1.774006 -0.584970 -0.313530 -0.748003 -5.208245 2.354614 -1.979804 -0.519622 -0.077193 -0.850902 -5.798816 2.591614 -1.810518 -0.125908 -0.235193 -0.963759 -4.927301 2.427811 -2.212181 -0.706918 -0.125991 -0.695984 -4.496892 3.429579 -2.113126 -0.348243 0.708816 -0.613439 -5.245432 3.879601 -1.683163 0.150784 0.408801 -0.900081 -4.654861 3.642601 -1.852448 -0.242930 0.566801 -0.787224 -4.363240 4.099555 -1.474832 -0.097120 0.795278 -0.598416 -4.953811 4.336555 -1.305546 0.296594 0.637278 -0.711273 -5.160631 4.626099 -1.197202 0.434474 0.444249 -0.783502 -4.846681 4.916852 -0.509009 0.696099 0.686544 -0.210008 -4.550161 4.710382 -0.420726 0.498420 0.824191 -0.268863 -3.959590 4.473382 -0.590012 0.104705 0.982191 -0.156006 -3.752494 4.394534 0.242850 0.208253 0.942767 0.260425 -4.343065 4.631534 0.412135 0.601967 0.784767 0.147568 -3.398384 4.337193 0.345439 -0.027820 0.980994 0.192032 -3.376327 3.861242 1.088720 -0.009439 0.584368 0.811433 -4.314706 4.019597 1.367783 0.616147 0.478799 0.625392 -3.724134 3.782597 1.198497 0.222433 0.636799 0.738249 -3.735698 3.707359 1.263488 0.216651 0.599179 0.770744 -4.326270 3.944359 1.432774 0.610365 0.441179 0.657887 -3.544210 3.119946 2.266491 0.088992 0.990788 0.102076 -3.899532 3.032518 2.550067 -0.207110 0.917932 0.338389 -4.783112 3.831952 1.797372 0.381944 0.384976 0.840186 -5.027309 3.679184 2.033401 0.544742 0.486820 0.682834 -6.570562 2.636631 1.876252 -0.741301 -0.381975 0.551877 -6.767293 2.491525 1.595324 -0.610147 -0.285238 0.739162 -6.545006 1.114408 2.469585 -0.758338 0.632840 0.156321 -6.173194 2.795462 2.266626 -0.410162 -0.249615 0.877188 -6.147639 1.273240 2.859960 -0.427199 0.765200 0.481633 -5.845821 1.383451 3.048662 -0.628411 0.691726 0.355831 -5.549711 3.066177 2.406448 0.109408 -0.024019 0.993707 -5.044199 1.731514 3.228433 -0.227600 0.865757 0.445717 -4.421933 2.419511 2.923115 -0.642444 0.407092 0.649262 -3.792457 2.152885 3.314794 -0.117881 0.184904 0.975661 -4.234873 1.388709 3.732020 0.177063 0.694355 0.697510 -3.822159 1.797995 3.426020 -0.098080 0.421497 0.901510 -3.307620 1.373765 3.552578 0.159190 0.209383 0.964789 -3.720334 0.964479 3.858578 0.434333 0.482240 0.760789 -3.770593 0.700151 4.115449 0.467839 0.658459 0.589541 -3.267985 0.063139 3.941312 0.886679 0.127616 0.444426 -3.074124 0.145465 3.634686 0.757438 0.072732 0.648843 -2.661410 0.554751 3.328686 0.482295 -0.200125 0.852843 -2.414921 -0.040661 2.864752 0.605540 -0.497831 0.620876 -2.827635 -0.449947 3.170752 0.880682 -0.224973 0.416876 -2.107383 -0.020514 2.655473 0.400514 -0.511262 0.760395 -2.152703 -0.485483 2.038620 0.362748 -0.898736 0.246350 -2.885903 -1.047763 2.377655 0.851548 -0.523882 0.020327 -0.574189 -2.337763 1.445940 -0.689595 0.336118 0.641470 -2.591139 -1.114862 1.531781 0.508307 -0.691166 0.513726 -1.192862 -1.895138 0.968219 -0.423878 -0.170981 0.889434 -0.699959 -2.519491 1.385497 -0.752480 0.245254 0.611249 -3.011674 -1.229492 2.317211 0.788663 -0.614746 -0.009894 -1.537746 -2.935716 1.057164 -0.193955 0.522737 0.830137 -1.930073 -3.292010 1.048851 -0.520894 0.225825 0.823209 -3.516093 -1.687585 2.306522 0.536453 -0.843792 -0.015239 -3.737850 -1.879233 2.076628 0.684291 -0.716027 0.138024 -5.195051 -1.472205 0.999436 -0.530042 -0.376838 -0.759637 -5.389637 -1.164264 0.921560 -0.400318 -0.582132 -0.707720 -4.578504 -1.549464 -0.278630 -0.941074 -0.325332 0.092407 -4.658332 -1.142648 -0.479384 -0.998094 -0.034749 -0.050989 -5.484128 -0.682727 0.683933 -0.447564 -0.341363 -0.826533 -4.794804 -0.574875 -0.675473 -0.907113 -0.413264 0.079737 -4.827907 -0.499711 -0.686416 -0.925504 -0.371506 0.073658 -5.518807 -0.603983 0.672469 -0.464904 -0.301992 -0.832265 -5.158587 -0.051047 -0.230025 -0.705051 -0.670616 -0.230603 -4.904146 -0.254806 -0.978109 -0.967859 -0.235448 -0.088394 -5.232840 0.187481 -0.514122 -0.748729 -0.530305 -0.397719 -4.996140 -0.187472 -1.584131 -0.906529 -0.280337 0.315620 -4.707701 -0.714572 -1.083779 -0.858723 -0.490873 -0.147099 -4.822276 -0.594391 -1.677655 -0.782340 -0.570994 0.248818 -4.581241 -1.266288 -0.840758 -0.943030 -0.123063 -0.309113 -3.309860 -1.785900 -1.624095 -0.034900 -0.494214 -0.868639 -3.550895 -1.114003 -2.460992 0.125789 -0.942145 -0.310708 -2.066549 -2.092126 -2.309031 -0.863775 -0.290063 -0.412016 -1.866002 -1.831115 -2.736572 -0.763501 -0.159558 -0.625786 -3.381467 -0.893494 -2.822190 0.246809 -0.784638 -0.568707 -2.046001 -1.213972 -2.910572 -0.643501 -0.570986 -0.509786 -2.042603 -1.191561 -2.939307 -0.641801 -0.559780 -0.524154 -3.378596 -0.874560 -2.846467 0.248860 -0.771114 -0.586047 -2.054580 -0.976103 -3.243017 -0.633817 -0.703419 -0.321681 -1.886083 0.732119 -3.442436 -0.493402 0.720099 -0.487863 -3.195573 0.980923 -3.063077 0.379591 0.554230 -0.740769 -1.825964 1.004725 -3.195704 -0.533482 0.538362 -0.652352 -1.811745 1.310099 -2.881722 -0.526373 0.691050 -0.495361 -3.183561 1.238911 -2.797817 0.388171 0.738508 -0.551298 -3.422246 2.475744 -2.376006 0.547295 -0.086047 -0.832505 -4.854756 2.220540 -2.219442 -0.646464 -0.298717 -0.702035 -4.739563 0.961707 -2.627756 -0.723259 0.540505 -0.429825 -5.114973 2.088123 -1.989139 -0.472986 -0.210439 -0.855570 -1.527632 1.618012 -2.634683 -0.384316 0.845006 -0.371842 -3.201270 2.715231 -2.183865 0.731442 0.113526 -0.672387 -0.802936 2.300231 -2.729420 -0.867447 0.390193 -0.308683 -0.734393 2.499618 -2.579767 -0.810327 0.556349 -0.183972 -3.132726 2.914618 -2.034211 0.788561 0.279682 -0.547676 -2.900934 2.980509 -1.750986 0.634033 0.235755 -0.736493 -0.319638 2.718020 -1.772477 -0.464698 0.738350 0.488769 -2.367677 3.261312 -0.713042 0.900662 0.376156 -0.217521 -2.321304 3.455798 -0.398033 0.869747 0.246498 -0.427527 -1.894843 2.618127 -0.894483 0.686934 0.720256 0.096712 -1.232157 2.373873 -1.349517 0.245144 0.883092 0.400067 -0.251974 2.661560 -1.643629 -0.408312 0.691300 0.596142 -2.253641 3.399338 -0.269185 0.926133 0.199448 -0.320154 -0.274110 2.450721 -1.336380 -0.393555 0.831860 0.391310 -0.258112 2.438497 -1.295627 -0.385556 0.825749 0.411686 -2.241199 3.389831 -0.237488 0.936501 0.191526 -0.293740 -1.228112 2.233314 -0.787739 0.261110 0.962538 0.073094 -1.153204 2.033269 -0.165018 0.305174 0.844864 0.439401 -2.178530 3.222473 0.283482 0.988725 0.052061 0.140402 0.229248 2.161362 0.182371 -0.616460 0.759468 0.207809 -1.892101 2.510891 0.053148 0.763511 0.430880 0.481035 -0.503899 1.899109 -0.005148 -0.161957 0.838734 0.519898 0.206407 2.097649 0.307089 -0.635494 0.706374 0.311741 -2.201371 3.158760 0.408200 0.969691 -0.001033 0.244333 -0.997482 1.742649 0.343200 0.167098 0.943041 0.287667 -1.048798 1.691951 0.497284 0.124335 0.900792 0.416070 -2.252687 3.108062 0.562284 0.926927 -0.043282 0.372736 -2.046741 2.148223 1.336365 0.789630 0.596611 -0.143318 -2.569326 2.623150 1.940357 0.528337 0.834075 0.158678 -2.659142 3.477450 1.032055 0.588215 0.264542 0.764213 -2.818031 2.794672 2.159278 0.694141 0.719727 0.012731 -3.505522 3.116734 2.257450 0.121232 0.988112 0.094542 -3.346632 3.799512 1.130228 0.015306 0.532926 0.846023 -3.685956 3.703230 1.251864 0.241522 0.597115 0.764932 -0.923786 1.530870 0.718171 0.228512 0.766558 0.600143 -1.886010 1.941118 1.620363 0.869995 0.493059 -0.001319 0.280103 1.885870 0.682060 -0.574081 0.529891 0.624217 0.388264 1.593962 0.925187 -0.483947 0.286635 0.826823 -1.746946 1.565808 1.932955 0.939527 0.305404 0.154978 -1.587847 1.228962 1.930743 0.833461 0.529968 0.156452 0.515916 1.230175 1.044000 -0.377570 -0.016520 0.925834 -1.460195 0.865175 2.049556 0.939837 0.226813 0.255463 1.098694 0.324620 2.040667 -0.766088 0.587183 0.261389 -0.977219 0.252728 1.737405 0.327137 -0.743063 0.583814 0.407218 -0.039729 1.732595 -0.595821 -0.548092 0.587020 0.904883 -0.594163 2.120834 -0.927597 -0.178469 0.328195 -1.654006 -0.053607 2.129723 0.778328 -0.538839 0.322269 0.023259 -1.205054 1.244786 -0.339848 0.228792 0.912227 0.018098 -1.212502 1.244705 -0.342883 0.224410 0.912179 -1.658323 -0.059839 2.129655 0.774731 -0.544032 0.322212 0.061442 -1.790507 1.562985 -0.371779 0.609747 0.699992 0.025120 -1.210764 1.246898 -0.338753 0.225433 0.913470 0.068995 -1.788637 1.565344 -0.368003 0.610681 0.701172 0.906440 -0.598940 2.122601 -0.926300 -0.182450 0.329668 1.086447 -0.814807 2.345992 -0.776294 -0.362340 0.515827 0.300431 -2.066181 1.852561 -0.252284 0.471910 0.844781 0.448669 -2.310919 2.087658 -0.351109 0.635068 0.688049 -0.009575 -3.236892 2.061680 -0.732979 -0.136576 0.666400 -0.288739 -3.256718 1.819160 -0.546869 -0.123359 0.828080 -0.776882 -3.653147 1.613874 -0.221441 0.140927 0.964937 -1.184178 -2.933014 1.191721 -0.425089 0.500993 0.753860 -0.696035 -2.536586 1.397006 -0.750518 0.236707 0.617003 -1.534694 -2.949011 1.066116 -0.191412 0.511657 0.837597 -1.621396 -4.089472 1.206744 -0.643698 -0.077236 0.761372 -1.874752 -3.848478 1.077801 -0.474794 -0.237898 0.847334 -1.542110 -4.712615 1.399601 -0.696555 0.338193 0.632801 -2.123797 -5.124514 0.307846 -0.987399 0.132243 0.086923 -2.327176 -4.168844 0.228658 -0.851813 -0.504870 0.139715 -2.203083 -4.501371 0.114989 -0.934542 -0.283186 0.215495 -2.295083 -3.907782 -0.707681 -0.980541 0.013609 -0.195841 -2.398731 -3.707164 -0.411196 -0.911442 -0.120137 -0.393497 -3.504742 -2.442523 -0.694489 -0.174102 -0.963231 -0.204635 -3.509914 -2.249765 0.341832 -0.177796 -0.825547 0.535594 -2.403493 -3.529705 0.542877 -0.915411 0.027746 0.401564 -4.211270 -2.116927 1.570655 0.289775 -0.914106 -0.283621 -2.729294 -2.449915 0.870755 -0.698210 -0.692114 0.182978 -3.134706 -2.133085 1.101245 -0.427935 -0.903334 0.029319 -2.108648 -3.732156 -1.215709 -0.887324 0.101422 -0.449855 -3.347237 -2.294149 -1.123685 -0.061598 -0.857249 -0.511204 -2.215949 -2.775566 -1.565774 -0.815791 -0.536305 -0.216478 -2.181303 -2.311191 -2.024458 -0.786919 -0.149326 -0.598715 -3.309605 -1.789742 -1.621911 -0.034718 -0.496959 -0.867079 -2.066247 -2.096674 -2.306446 -0.863624 -0.292337 -0.410723 -1.826833 -2.839285 -2.075315 -0.491527 -0.589404 -0.641096 -1.610499 -2.775652 -2.371834 -0.635750 -0.631826 -0.443417 -1.367388 -3.827618 -2.138649 -0.797823 0.069485 -0.598874 -0.622294 -3.862172 -2.600062 -0.176912 0.040690 -0.983385 -0.652521 -2.820078 -2.965080 -0.156760 -0.654039 -0.740040 -0.313405 -2.796061 -3.121173 -0.382838 -0.670050 -0.635978 -0.105248 -1.854362 -3.523303 -0.209373 0.114698 -0.971086 -0.384890 -1.609323 -3.482104 -0.022945 -0.048661 -0.998552 -0.564890 -0.992180 -3.656104 0.097055 -0.460090 -0.882552 -0.808129 -1.056161 -3.631406 -0.024565 -0.492081 -0.870203 -0.628129 -1.673304 -3.457406 -0.144565 -0.080652 -0.986203 -1.094434 -0.870792 -3.781316 0.166305 -0.615660 -0.770263 -2.025275 -0.994766 -3.258087 -0.609396 -0.718972 -0.334239 -1.824925 -1.832700 -2.784684 -0.742963 -0.160350 -0.649842 -2.004925 -1.215557 -2.958684 -0.622963 -0.571778 -0.533842 -0.478655 -0.210572 -3.866400 0.140173 -0.069286 -0.987700 -0.838176 -0.213111 -3.964089 0.379853 -0.067593 -0.922574 0.066488 0.157571 -3.964114 -0.223256 -0.314715 -0.922557 -0.675937 1.346484 -3.626782 -0.594468 0.279742 -0.753891 -1.415617 0.711598 -3.701720 -0.101348 0.702999 -0.703933 -1.221080 0.978341 -3.529068 -0.231040 0.525170 -0.819034 -0.932356 1.913864 -2.919702 -0.722678 0.563432 -0.400351 -1.477499 1.545721 -2.821988 -0.359249 0.808860 -0.465494 -0.763943 2.244005 -2.875102 -0.834953 0.343338 -0.430085 1.161912 2.435887 -3.046407 0.324456 0.824444 -0.463703 0.864932 2.650023 -2.973650 0.522443 0.681686 -0.512208 2.134341 2.769744 -2.646978 -0.323830 0.601872 -0.729989 2.117745 2.815141 -2.600653 -0.332127 0.624570 -0.706826 0.852024 2.685332 -2.937618 0.511687 0.711110 -0.482182 2.109802 3.123109 -2.390396 -0.326832 0.419258 -0.846997 1.511443 3.244806 -1.112439 -0.825464 0.520672 0.217967 0.253665 2.807029 -1.659662 0.013054 0.812524 0.582782 0.794284 2.620179 -0.837565 -0.347358 0.937090 0.034718 0.721044 2.589433 -0.797460 -0.383978 0.921716 0.054770 0.196701 2.783114 -1.628469 -0.034416 0.792595 0.608776 0.302758 2.607004 -1.316888 -0.105121 0.910002 0.401056 0.327334 2.319614 -0.489540 -0.580833 0.786807 0.208730 -0.090952 2.337185 -1.008969 -0.301976 0.775093 0.555016 -1.072705 2.139125 -0.521237 0.352526 0.907133 0.229861 0.327661 2.311690 -0.459891 -0.580670 0.782845 0.223555 -1.072401 2.131758 -0.493672 0.352705 0.902799 0.246075 0.296847 2.243759 -0.092582 -0.560127 0.828132 -0.021318 1.045574 2.545798 -0.155933 -0.221713 0.899899 0.375534 0.855224 2.425843 0.143830 -0.094813 0.979869 0.175692 1.599717 2.897226 -0.275933 -0.591142 0.665613 0.455534 1.976632 2.673119 0.270968 -0.402684 0.553559 0.728984 1.148380 2.251537 0.569197 0.149484 0.834614 0.530164 2.436060 2.642262 0.750111 -0.708970 0.574131 0.409555 2.478736 2.141612 1.230711 -0.687632 0.323806 0.649855 1.181573 1.862143 0.942997 0.177144 0.510119 0.841664 2.468879 1.689898 1.633139 -0.681061 0.624949 0.381570 2.341551 1.413516 1.783131 -0.744724 0.486758 0.456566 1.082540 1.647179 1.059657 0.094617 0.330983 0.938881 1.852123 0.963945 1.786560 -0.418439 0.786472 0.454280 1.755636 0.890097 1.816903 -0.466682 0.749549 0.469452 1.007494 1.589742 1.083258 0.032079 0.283119 0.958548 1.590272 0.684187 2.079925 -0.356440 0.886822 0.294104 1.913510 0.898281 1.939471 -0.387745 0.753641 0.530735 1.713064 0.690552 2.175255 -0.254114 0.892127 0.373546 2.402939 1.347852 1.936042 -0.714031 0.453926 0.533021 2.818241 1.014851 2.495997 -0.506379 0.287425 0.812999 2.036077 0.431551 2.610775 0.015064 0.676292 0.736480 3.242098 0.984422 2.917711 -0.788951 0.307711 0.531856 3.520178 -0.119566 3.293363 -0.649911 -0.244283 0.719682 2.252361 -0.427107 2.902949 0.195301 -0.039256 0.979957 2.606892 -0.538709 2.875077 -0.041054 0.035145 0.998539 1.838607 -1.407977 2.502336 -0.425197 -0.399488 0.812168 1.654805 -1.103204 2.613039 -0.302662 -0.602670 0.738366 1.017027 -2.599315 2.354706 0.122523 0.394737 0.910588 2.682534 -2.071536 2.242165 -0.003233 -0.731268 0.682083 1.673416 -3.115417 2.152350 0.669513 -0.035347 0.741959 2.928971 -2.293750 2.072906 -0.167524 -0.583125 0.794922 3.070504 -2.529857 1.867754 -0.049580 -0.779881 0.623961 1.814949 -3.351524 1.947198 0.787457 -0.232103 0.570998 2.057077 -3.404102 1.671969 0.626039 -0.197051 0.754484 1.539139 -4.111788 1.662034 0.367069 -0.550894 0.749517 1.412108 -3.901947 1.939471 0.451757 -0.690789 0.564559 1.130282 -5.131360 1.649606 0.639641 0.128820 0.757803 1.026580 -5.125062 1.730354 0.587790 0.131969 0.798177 1.331451 -3.897048 2.002275 0.384543 -0.686706 0.616896 0.779785 -5.232604 1.987831 0.752320 0.203664 0.626526 -0.500607 -4.704646 2.073187 -0.314672 0.643628 0.697656 0.051060 -3.369090 2.087631 -0.682450 -0.246742 0.688026 -0.698923 -3.823116 1.647241 -0.182462 0.055942 0.981620 -0.569000 -4.727270 2.060007 -0.371667 0.624775 0.686673 -0.786858 -3.852204 1.630295 -0.226429 0.041398 0.973148 -0.707572 -4.475347 1.823152 -0.279286 0.456827 0.844576 2.216290 -4.369918 0.561603 0.705645 -0.679959 0.199301 1.807433 -5.389489 0.549174 0.978217 -0.000245 0.207587 2.446003 -4.282714 0.279691 0.552503 -0.738095 0.387243 2.463860 -4.316498 0.176876 0.567383 -0.766248 0.301563 1.830392 -5.432925 0.416983 0.989696 -0.021963 0.141491 1.912194 -5.664275 0.136320 0.935161 0.132271 0.328600 1.429737 -5.486718 -1.215941 0.533114 0.280235 -0.798284 1.210091 -5.204637 -1.321638 0.679546 0.092181 -0.727819 1.130805 -4.581494 -1.514495 0.732403 -0.323247 -0.599248 0.320059 -4.829084 -1.981179 0.327030 -0.447042 -0.832589 0.399345 -5.452227 -1.788322 0.274172 -0.031613 -0.961161 0.132490 -4.617065 -2.224472 0.452075 -0.588388 -0.670394 -0.892724 -4.726402 -2.156273 -0.402270 -0.679501 -0.613561 -0.918788 -5.592802 -1.700637 -0.384894 -0.101901 -0.917318 -0.998074 -4.969659 -1.893494 -0.332037 -0.517330 -0.788747 -1.616088 -4.923521 -1.490342 -0.641044 -0.494260 -0.587171 -1.536802 -5.546663 -1.297484 -0.693901 -0.078832 -0.715742 -1.688957 -5.864960 -1.179377 -0.592464 0.133366 -0.794481 -2.101370 -5.708861 -0.505456 -0.936142 0.263449 -0.232880 -2.067048 -5.345965 -0.431015 -0.959024 0.021518 -0.282508 -2.146333 -4.722822 -0.623872 -0.906167 -0.393911 -0.153936 -1.394634 -3.842600 -2.102508 -0.820528 0.057000 -0.568757 -1.643387 -3.833343 -1.824367 -0.654693 0.050829 -0.754184 -1.854079 -2.854267 -2.039175 -0.514232 -0.601889 -0.610979 0.750444 -4.034369 -1.993530 0.542222 -0.049685 -0.838765 0.467234 -3.998954 -2.234079 0.731028 -0.073295 -0.678399 0.776123 -2.932843 -2.755190 0.525102 -0.784036 -0.330992 0.926294 -3.946838 -1.868907 0.630147 -0.005919 -0.776453 0.912895 -2.864763 -2.658261 0.639079 -0.727302 -0.250217 1.414437 -3.550410 -1.663621 0.304718 -0.270205 -0.913311 1.748258 -3.161982 -1.594033 0.471629 -0.075991 -0.878517 1.172534 -2.562652 -2.604137 0.855445 -0.475544 -0.205114 2.473090 -2.109319 -1.969137 -0.011592 -0.777766 -0.628447 2.442824 -1.440443 -2.384666 -0.036813 -0.220369 -0.974722 1.142268 -1.893777 -3.019666 0.830224 0.081853 -0.551388 1.636713 -0.555999 -3.388555 0.500594 -0.809999 -0.305462 0.729097 -0.357800 -3.886317 -0.255753 -0.644833 -0.720265 0.234652 -1.695578 -3.517429 0.073877 0.247019 -0.966190 -0.127875 -0.788028 -3.648551 0.315562 -0.358014 -0.878776 0.565200 -0.059927 -4.017912 -0.392333 -0.396606 -0.829927 -0.338600 -0.405049 -3.817744 0.210200 -0.166525 -0.963372 0.206543 -0.036906 -3.915458 -0.153229 -0.411953 -0.898229 1.755994 1.016933 -3.770658 0.599995 0.500777 -0.623882 1.737564 1.347628 -3.597560 0.612282 0.280314 -0.739280 2.983216 1.461377 -3.275103 -0.218153 0.204481 -0.954252 2.973450 1.524020 -3.257557 -0.226292 0.256684 -0.939631 1.725007 1.428169 -3.575002 0.606004 0.320584 -0.728001 2.697436 1.762026 -3.175573 -0.042282 0.098013 -0.994287 4.103389 1.741479 -2.783484 0.715324 0.437899 -0.544570 4.150214 2.041615 -2.566051 0.684107 0.237808 -0.689525 5.066525 2.955227 -2.211887 0.073232 -0.371267 -0.925634 4.236495 3.879778 -2.041563 -0.519646 0.289127 -0.803973 3.167729 3.135982 -2.364442 0.192865 0.784991 -0.588721 2.926456 3.372653 -2.206677 0.353713 0.627211 -0.693897 3.841668 4.263401 -0.635299 -0.801666 0.563144 0.200501 2.562964 3.725830 -0.912021 0.050803 0.921525 0.384982 3.601668 3.965924 -0.196742 -0.641666 0.761462 -0.091871 3.338714 3.688439 0.227582 -0.773143 0.622720 0.120291 2.358444 3.510008 -0.581992 -0.119630 0.741674 0.660007 2.437428 3.312582 -0.275561 -0.172286 0.873291 0.455720 1.458524 2.979574 -0.686779 -0.661738 0.706787 0.250111 1.597075 3.251002 -0.901828 -0.754104 0.525835 0.393477 0.904382 2.628145 -0.566779 -0.292309 0.941073 0.170111 3.285151 3.563614 0.416776 -0.799924 0.560307 0.214888 2.383866 3.187757 -0.086367 -0.199067 0.810879 0.550316 2.843294 3.156900 0.392776 -0.505353 0.831450 0.230888 3.839283 2.889879 1.632228 -0.522859 0.223439 0.822614 3.397426 2.483165 1.608228 -0.228287 0.494582 0.838614 4.259711 2.851307 2.054371 -0.803144 0.249154 0.541185 4.260306 2.845790 2.057774 -0.802847 0.246395 0.542887 3.398021 2.477647 1.611631 -0.227990 0.491824 0.840316 3.812020 1.995504 2.435774 -0.503990 0.813252 0.290887 3.790826 1.981326 2.438127 -0.514587 0.806163 0.292063 3.376826 2.463469 1.613984 -0.238587 0.484735 0.841492 3.366969 2.011755 2.016412 -0.232016 0.785878 0.573206 4.260935 2.845858 2.058672 -0.802533 0.246429 0.543336 3.812649 1.995572 2.436672 -0.503676 0.813286 0.291336 4.247220 2.403144 2.456815 -0.793390 0.541572 0.277907 6.297032 0.327723 0.227385 0.231516 -0.496139 -0.836808 5.862461 -0.079849 0.207242 0.521230 -0.224424 -0.823379 5.438603 -0.049420 -0.214472 0.803802 -0.244710 -0.542236 4.776611 -1.248245 0.364384 0.472805 -0.844123 -0.252808 5.200468 -1.278674 0.786098 0.190234 -0.823837 -0.533951 4.287182 -1.697817 0.367812 0.799091 -0.544409 -0.255094 4.262676 -1.787581 0.511267 0.786838 -0.589290 -0.183366 5.175961 -1.368438 0.929553 0.177981 -0.868719 -0.462223 4.157970 -2.072896 0.726652 0.856642 -0.399080 -0.326956 3.977678 -2.261331 1.644463 0.706399 -0.556109 0.437885 4.944158 -1.610711 2.109595 0.062079 -0.989856 0.127797 4.909901 -1.609664 2.462796 0.084917 -0.990553 -0.107670 3.951103 -0.753847 3.363324 -0.714081 -0.277372 0.642770 3.711419 -0.510375 3.267417 -0.554291 -0.439687 0.706709 2.798133 -0.929518 2.849132 0.054567 -0.160259 0.985566 4.292412 -1.418907 3.014315 -0.429657 -0.831589 0.351929 3.236959 -1.784595 2.400405 0.273979 -0.587798 0.761203 3.360190 -2.070574 2.195982 0.191825 -0.397145 0.897485 3.702171 -2.141986 0.088418 0.506585 -0.766493 -0.394791 3.722022 -2.348545 0.397770 0.493351 -0.628787 -0.601025 2.973689 -3.350211 -0.326674 0.992240 0.038991 -0.118062 2.727485 -3.742293 0.469767 0.787071 -0.287744 0.545639 3.475819 -2.740627 1.194212 0.288182 -0.955522 0.062676 2.578195 -3.675092 0.805987 0.886598 -0.332546 0.321493 3.644811 -2.031092 -0.153542 0.477906 -0.711046 -0.515771 2.929076 -3.263961 -0.514866 0.955063 0.110866 -0.274888 3.320187 -2.030072 -1.087088 0.694322 -0.711726 0.106593 2.622640 -2.172144 -1.870209 0.113033 -0.830120 -0.546008 2.231529 -3.406033 -1.297987 0.373774 -0.007527 -0.927489 1.940537 -3.242756 -1.466841 0.567768 -0.116378 -0.814920 1.676412 -4.062684 -1.297308 0.435706 -0.526342 -0.730154 2.026098 -4.043754 -1.166129 0.202582 -0.538962 -0.817607 1.188269 -4.459112 -1.502594 0.761134 -0.262056 -0.593297 1.204130 -4.535688 -1.444420 0.769065 -0.300344 -0.564210 2.038434 -4.103313 -1.120882 0.212862 -0.588594 -0.779902 1.486767 -5.451091 -1.161438 0.580639 0.309924 -0.752865 4.034375 -1.428105 -0.354490 0.672688 -0.409553 -0.616245 3.623181 -1.561082 -1.243381 0.946817 -0.320902 -0.023651 4.523804 -0.978534 -0.357919 0.346402 -0.709267 -0.613959 4.543709 -0.482876 -0.754915 0.356354 -0.461438 -0.812457 3.638662 -1.175570 -1.552156 0.959718 0.000358 -0.280963 4.553566 -0.031162 -1.157343 0.349783 -0.762581 -0.544172 4.470348 0.100224 -1.364185 0.308174 -0.696888 -0.647593 3.573937 -1.073381 -1.713033 0.905781 0.085516 -0.415027 4.010920 0.131081 -1.843328 0.614460 -0.717459 -0.328164 3.952327 0.138545 -1.956874 0.585163 -0.713728 -0.384937 3.528365 -1.067576 -1.801347 0.867804 0.090353 -0.488622 3.949476 0.261313 -2.309680 0.587064 -0.795573 -0.149733 3.250318 0.269457 -2.867583 0.004432 -0.788786 -0.614652 2.829207 -1.059432 -2.359249 0.285173 0.097140 -0.953541 2.023096 -0.174987 -3.363138 0.822580 -0.492490 -0.284282 4.107406 0.263972 -1.927286 0.662703 -0.651014 -0.370143 4.070093 0.358867 -2.286667 0.687578 -0.714277 -0.130556 4.566834 0.233115 -1.448143 0.356417 -0.630443 -0.689572 4.950580 0.988869 -1.663476 0.548290 -0.252566 -0.797238 4.368562 0.946676 -2.454148 0.936302 -0.224437 -0.270123 5.392437 1.395583 -1.639476 0.253719 -0.523709 -0.813238 5.176278 2.280656 -1.985005 0.145639 -0.081172 -0.986002 4.200438 1.635066 -2.722893 0.796199 0.349222 -0.494077 5.171942 2.839641 -2.146073 0.148530 -0.453828 -0.878623 6.231110 2.643012 -1.478601 0.673055 0.100006 -0.732800 6.063092 3.145769 -1.718249 0.785066 -0.235165 -0.573035 6.400307 3.473009 -1.537912 0.560256 -0.453326 -0.693260 5.055604 4.818352 -0.118021 -0.560330 0.667793 0.489983 4.602467 4.607089 -0.175954 -0.258238 0.808635 0.528604 4.502205 4.372738 0.346973 -0.191398 0.964869 0.179987 5.369797 4.770824 0.156230 -0.298502 0.628186 0.718525 4.906168 4.311631 0.699582 0.010584 0.934315 0.356291 5.326596 4.273059 1.121725 -0.269702 0.960030 0.074862 6.095900 4.800079 0.125527 0.306583 0.652566 0.692939 6.260156 4.310674 1.082249 0.197078 0.978837 0.055124 6.613677 4.282302 1.082749 -0.038602 0.997751 0.054791 7.442083 3.439310 0.178662 0.651736 0.295258 -0.698615 7.325250 3.226827 -0.080149 0.729625 0.436914 -0.526075 6.924305 3.957088 -0.778560 0.996921 -0.049927 -0.060467 6.652410 3.469104 -1.240113 0.770341 -0.456580 -0.445094 6.975670 2.599419 -0.673573 0.554835 0.123209 -0.822787 6.555241 2.637990 -1.095716 0.835120 0.097495 -0.541358 5.888502 0.814976 -0.598255 0.501751 -0.814012 -0.292627 6.308930 0.776405 -0.176112 0.221465 -0.788298 -0.574056 5.436788 -0.043452 -0.219826 0.802894 -0.241726 -0.544913 5.438076 -0.044960 -0.217254 0.803538 -0.242480 -0.543627 6.310219 0.774897 -0.173540 0.222109 -0.789051 -0.572770 6.296504 0.332183 0.224603 0.231252 -0.493909 -0.838199 5.872877 0.813488 -0.620281 0.493938 -0.814756 -0.303641 5.421163 -0.044941 -0.241853 0.795081 -0.242470 -0.555926 5.431020 0.406774 -0.644281 0.788510 -0.543613 -0.287641 6.148096 1.225582 3.873924 0.157048 -0.047209 0.986462 6.502186 1.211563 3.859385 -0.079012 -0.037864 0.996154 -6.558738 1.196627 0.979775 -0.936965 -0.348999 -0.017209 -6.405434 1.016370 0.789873 -0.678960 -0.652363 -0.336804 -6.251217 0.900918 0.645156 -0.781770 -0.575394 -0.240325 -6.043306 0.813857 0.423996 -0.534518 -0.678929 -0.503334 -5.468031 1.010681 -1.193538 -0.716028 -0.688392 -0.115846 -5.440059 1.290325 -1.515311 -0.662310 -0.151363 -0.733781 -7.434482 2.814341 -0.719349 -0.887902 0.301118 -0.347791 -7.386620 3.178582 -0.659020 -0.919810 0.058290 -0.388010 -5.296986 1.326783 -1.673197 -0.757692 -0.175668 -0.628524 -5.210993 1.464752 -1.784101 -0.670269 -0.035405 -0.741273 -6.791376 4.236290 -0.918649 -0.622188 0.587146 -0.517825 -6.062836 4.911003 0.678341 -0.257918 0.924501 0.280670 -6.589848 4.548115 -0.896283 -0.756540 0.379262 -0.532736 -6.023205 5.072891 0.345820 -0.284338 0.816575 0.502351 -6.403486 4.107619 1.591148 -0.428243 0.522810 0.737074 -6.287600 3.893593 1.873004 -0.505500 0.665493 0.549170 -6.612682 -0.105767 2.803375 -0.814735 -0.383972 0.434479 -6.443734 -0.389557 2.975911 -0.927367 -0.194779 0.319455 -5.358206 0.110573 4.179850 -0.384603 0.055286 0.921426 -4.222752 -1.328516 3.786451 0.183124 -0.664258 0.724726 -5.044494 0.036002 4.365328 -0.593745 0.105001 0.797773 -4.161362 -1.083290 4.059351 0.142198 -0.827742 0.542792 -2.943738 -1.688189 1.412492 0.743373 -0.308948 0.593252 -2.363600 -2.359759 0.916537 0.356614 0.138766 0.923889 -3.045126 -1.780266 1.410343 0.222475 -0.782005 0.582214 -2.420869 -2.411768 0.915323 -0.193696 -0.361003 0.912227 -5.291017 -1.856213 2.585285 -0.351008 -0.928106 0.124142 -5.118346 -2.010388 2.293444 -0.466122 -0.825323 0.318703 -2.673742 -1.377689 -2.252823 -0.458979 -0.766354 -0.449488 -2.529230 -1.189608 -2.560904 -0.321349 -0.587229 -0.742898 -2.622809 1.724817 -2.259907 0.014337 0.414571 -0.909904 -2.460902 1.900287 -2.119128 0.237864 0.656823 -0.715545 -2.393839 2.321846 -1.832914 0.193155 0.375783 -0.906354 -1.466671 2.161412 -2.043819 -0.424957 0.482739 -0.765751 -2.385645 2.345681 -1.815024 0.290507 0.658973 -0.693801 -1.458477 2.185246 -2.025930 -0.327605 0.765930 -0.553197 -1.734382 2.365875 -1.730550 -0.143668 0.645511 -0.750117 -1.549606 2.463175 -1.370897 0.355281 0.908247 0.221049 -1.551412 2.368230 -0.841199 0.457980 0.886854 0.061189 -1.547109 2.364942 -0.830236 0.473775 0.874786 0.101426 -1.833426 2.256799 0.266192 0.724394 0.600274 0.339005 -1.867137 2.223495 0.367414 0.669894 0.546430 0.502649 -0.940809 1.436939 0.861026 0.239861 0.829178 0.504906 -0.891579 1.304076 0.971687 0.369282 0.479892 0.795823 -0.733309 1.099512 1.052345 0.263768 0.616268 0.742051 -0.686931 0.967342 1.095512 0.424328 0.158702 0.891493 -0.975073 -0.516408 1.237638 0.325706 -0.230305 0.916992 -0.977396 -0.519761 1.237601 0.320780 -0.237417 0.916915 -1.348914 -0.625435 1.404587 0.568458 -0.166968 0.805591 -0.682756 -1.295816 1.185085 0.124353 0.279953 0.951926 -1.492832 -0.749345 1.378086 -0.077166 -0.722828 0.686706 -0.881389 -1.466833 1.148509 -0.484794 -0.244502 0.839758 -2.646835 -2.967012 -0.613308 -0.746040 -0.613571 -0.258756 -2.519955 -2.847488 -0.959050 -0.613120 -0.488356 -0.620961 -1.191688 -6.046052 1.709146 -0.521344 -0.328526 0.787572 0.349218 -6.623366 1.626689 0.249109 -0.617183 0.746344 -0.945535 -5.948930 1.971335 -0.685446 -0.393275 0.612779 0.252947 -6.397951 1.907202 0.313289 -0.767460 0.559335 1.120857 -6.917395 0.360878 0.634929 -0.764198 0.113438 0.571838 -6.715340 -1.177950 0.360419 -0.663170 -0.655975 1.360333 -6.818863 0.092683 0.475278 -0.829885 0.292234 0.933318 -6.661709 -1.104184 0.119432 -0.698924 -0.705153 -0.552588 -7.085876 -0.844638 -0.201793 -0.848437 -0.489319 -1.516456 -6.721050 0.730413 -0.683728 -0.666025 0.298206 -0.923456 -7.062126 -0.827163 0.045453 -0.864271 -0.500969 -1.673132 -6.778372 0.397877 -0.579277 -0.627810 0.519897 4.184533 1.554706 3.333961 -0.317733 0.592853 0.739980 4.830401 0.843170 3.796950 0.005201 0.237085 0.971475 5.558985 0.071679 3.688530 0.369493 -0.148660 0.917265 6.154522 -0.531298 3.040809 0.667261 -0.450149 0.593404 6.440649 -0.787195 2.045602 0.810324 -0.578097 0.095801 6.332633 -0.620230 0.997631 0.756316 -0.494615 -0.428184 4.619105 1.962278 3.354104 -0.607448 0.321139 0.726551 5.264973 1.250742 3.817093 -0.284513 -0.034629 0.958046 5.993556 0.479250 3.708673 0.079779 -0.420374 0.903837 6.589094 -0.123727 3.060952 0.377547 -0.721863 0.579975 6.875220 -0.379623 2.065745 0.520610 -0.849812 0.082373 6.767204 -0.212658 1.017774 0.466602 -0.766329 -0.441613 5.730783 -0.332636 3.490515 0.455392 -0.350818 0.818257 5.521720 -0.615605 3.536845 0.594767 -0.162171 0.787371 5.094133 4.546314 -1.807825 0.092951 0.765224 -0.637018 5.508249 4.762401 -1.620378 -0.183126 0.621167 -0.761983 4.242564 3.795115 1.313297 -0.321218 0.676057 0.663148 4.662992 3.756543 1.735439 -0.601504 0.701772 0.381720 7.510953 2.899374 1.969801 0.822476 0.273187 0.498901 7.586518 3.184624 1.773068 0.772099 0.083020 0.630057 6.815060 1.574960 -0.607221 0.474530 -0.389020 -0.789611 6.394632 1.613531 -1.029364 0.754815 -0.414734 -0.508182 7.241809 1.106796 0.227603 0.687905 -0.623102 -0.372198 7.762878 1.720604 0.928075 0.948439 -0.316198 -0.021962 7.718973 2.434380 1.720245 0.926486 0.040689 0.374122 7.123107 3.036548 2.369299 0.628554 0.341774 0.698649 6.151906 3.348617 2.682849 0.142953 0.497808 0.855425 5.093248 3.278084 2.567955 -0.386376 0.462542 0.797978 7.228095 0.664082 0.625746 0.697048 -0.327959 -0.637627 7.749164 1.277890 1.326219 0.957582 -0.021055 -0.287391 7.705259 1.991666 2.118387 0.935629 0.335832 0.108693 7.109393 2.593833 2.767442 0.637697 0.636917 0.433221 6.138191 2.905902 3.080992 0.152096 0.792951 0.589996 5.079534 2.835370 2.966098 -0.377233 0.757685 0.532549 6.520936 0.211488 3.417351 0.343469 -0.554256 0.758176 7.350350 0.211488 2.587937 0.758176 -0.554256 0.343468 7.806924 1.225582 2.215096 0.986462 -0.047209 0.157048 7.434083 2.239675 2.671669 0.800042 0.459837 0.385335 6.604670 2.239675 3.501083 0.385335 0.459837 0.800042 6.857298 2.000303 3.569398 0.216916 0.619419 0.754498 7.502398 2.000303 2.924298 0.754498 0.619419 0.216916 7.792386 1.211564 2.569186 0.996154 -0.037864 -0.079012 7.437273 0.422824 2.859173 0.700227 -0.695146 0.162644 6.792173 0.422824 3.504273 0.162644 -0.695146 0.700228 -0.050439 0.455394 1.133713 0.000000 0.500000 0.866025 -5.589000 -1.401259 3.355074 -0.500000 -0.700629 0.509037 -4.716949 -0.595886 -2.607878 -0.707107 -0.572061 -0.415627 -7.279051 4.062000 0.117000 -0.866025 0.500000 0.000000 -7.279051 3.562000 0.983025 -0.866025 0.250000 0.433013 0.851000 -6.790258 1.152074 0.500000 -0.700629 0.509037 -0.149000 -7.121051 1.134000 0.000000 -0.866025 0.500000 -0.149000 -7.389000 0.134000 0.000000 -1.000000 0.000000 -0.149000 -6.389000 -1.598050 0.000000 -0.500000 -0.866025 3.820000 0.904233 3.501278 -0.500000 0.267617 0.823639 7.598051 1.853000 0.105975 0.866025 -0.250000 -0.433013 5.834000 2.320000 3.633051 0.000000 0.500000 0.866025 7.197000 0.737385 3.564000 0.500000 -0.433013 0.750000 mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/__init__.py0000644000175000017500000000000010504574206024337 0ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Example4.py0000644000175000017500000000333610504574206024276 0ustar debiandebianimport sys; sys.path.insert(0, '.') #Example Four: Callbacks and the event Manager #This example illustrates the event Manager property of the camera. #First get a handle to the event manager: from DejaVu import Viewer MyViewer=Viewer() ehm=MyViewer.cameras[0].eventManager #The eventManager is a property of an individual camera. You can #get a complete listing off all the callback functions bound to keys strokes #existing in the event Manager at any time: ehm.ListBindings() #or the list of all callbacks bound to any specific key stroke: ehm.ListBindings('') #Predefined callback functions can be added to specific key strokes in the camera: def mycallback1(event): print 'mycallback1 Event at %d %d' % (event.x, event.y) def mycallback2(event): print 'mycallback2 Event at %d %d' % (event.x, event.y) ehm.AddCallback("", mycallback1) #you can check: ehm.ListBindings("") #Note that the callback function must have 'event' as its parameter and #the key stroke must occur with the cursor over the camera. AddCallback #adds this callback to whatever else may have been previously bound to this #keystroke. Another function, SetCallback, replaces the previously bound #funtions with the new one. It returns a list of the previous callbacks #which can be stored and restored. funcList = ehm.SetCallback("", mycallback2) #Now, funcList is a list: funcList #and mycallback2 is bound to F1. mycallback1 could be restored #as follows: ehm.SetCallback("", funcList) #Callback functions can be removed if they are currently listed: #if mycallback2 is one of the current callbacks for F1, it can be removed if ehm.HasCallback("", mycallback2): ehm.RemoveCallback("", mycallback2) print "end of Example4" mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/annCam_PropPanel.jpg0000644000175000017500000011547510504574206026134 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222;P" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (9]ZceZ,6\<޴?}PyI@g^6u&rRUpKks=rCQjm N{^>U#N=Ak9[.UR\ψ '8дOGhGb9ƅ&=$ӏI-@q-%D2*E1吞{#0s IMz~MFNL|d qA]alLΪ8(@;dQJ5;]*NavBe*H<%Q#JgVGH"X]dmҏ(0 V^׵,M+w+ %$"-K+) Aۆt4x{WPJ8ՕS8*c Y]^fHXr!pF_kf -X./Q SyqA 898vZu텵ݵԗ q !X:FV@`rvᮯ`cu+[7eLY|Ӻ_3z :2XJ.o.%d [1@2@9&{֏EӖ$\7oy )9eq fv 084 ţlauYm-[aXpʹt*kW=$FW:&z˱]}yvۋV#b;,(瓝J()81 ;TɧQ@#Լw Cig+ʅ R8OM-n)-+2H˳H9\]E0rW=pz¦lqD\ W *j0RkVJcNR[#> V}wxvMՋ~?q^{'5z")?M(.!$Y鶪\iqwH?۶Qu^# "=88zO}|ܨz#3vx?.(ݳ: ?ӢvsQW3?l玣"Z_{KٌEzVh' h:vS9{nl|Gu \2m^>@A;WVfdh~]_snzk|5hRo}-Xزa`c$c ㌜V _RkVC nIz+HmZ|o{zEvП27]!%QEk;ߒve{-KWNjwڔQ{9} ۀF@ 3MӚSop|Kv 1Ѭ[Mm$m"fg[|lNX+/^KGUEg$ vl0{@p34[yDeajJ[&KUO]ugEc=*]v?>Y @pgv^3IHh E±I2@p2x# M ]|5X,`AeF:xſG~ݻ:n+fn7qԔW.g*kgw{w_"']k(_ h_4"vg=S,xvyڝH.TOe?SVd7r[K#PIl:^tȵ$[-{w-u@ EA#H** O˿uNUai-{Z|g>-:s}=q[i;(^  t W=x]KwŸc4W1kv$(eRT 9Jm&uyu?jk7u9fAlmŽ E'|9&uyy1EP6O9cy nEkJyt*餢֋vAǎ!5k6Wc3;\*;#rgs3sS4:Mƣ_,H zO9o5 YVbd9L aeeծ4ybBiB}ݭ28\{]5mn<^[ko_ⵛW0uwT_1oٵ߳]y2*Yn2N@t: 6-t|K5>v۹U|uIuFQktԖ9|4}0r>\vqmj>7wZ5j,7#eQ*In##5NxI(oEkKn`oIm͌IJɪGeim3i'3)lr8}Hֿu[,S222zJmEièA&aŊ[' p;Ea߱xAo y^>c׵dIrﶷN9`ҋǾ_m~׮H-o-LfLWUsr1BxI=jqidnŪ!, mӽZ|6m.l&k&|FH ]nۮp ;Yxۣx9Mkn˿[CY<jju]V#nɷfJ  c}~FY_RG2Iff`Ý[#<8뙃7g}i"R]+S嵭cĎѴl FT3&PYZaaogc,JXB}͕yݶ (((?(Nj6e=]~ *z]OݧL/xcڛ`2Ӟ.׿~x=.ǧӏotKC_ QE$ZZdXct?*:ȵh-!t>] FmAiLh r f~]m]7íS8M'owo9f{ƴW*F\0p9\22x$`T$L6ƒ8kY?{B2`ے0>y{_ _]멾l#3-!_zZVW^ֵH//";d'KUJf)<6uvy(TqYZB4yy- u^]z&;-(~Q:mN9"~*mbhtOYh򨺗JQ2UI!hk[NK'gx\@EX-!ڟfM+xSc,v4;r}t^E#Gk?6=׷jAcRmc;v1-} ~ /,cNxne% flˆ[ |_Fsoq$m#Hbf+,?U#N=AZ𿉵67YRL`~W5=>; {d[Ҩf z`tJ䋅*qv;:* [w0NҸ@OO~ GkiҘ/n$qXW z\)w}McA7Zc(B7eBG j5AEFOĒ#> FQӥ:SQqvm G×˦[ir¤+pĝTE((F@a.;|]h:gcDlXX̅YF0tr< A_ow-`iCs¨$ ITjE(}1t Jiͺ3]ΑGnH+aa3>ڥj"\O+%6;//';TwS6p+gjG .#a풭7c29)s+^RqwmGx{QQZU_5ІCc<Sr\ŸO1]5oUٍJ> J)0%ICGW<ϡ4ӎ!8V^mO::MB>1 ?,oTp*H\M/L g&ѵ>\c I{2ᦉ㷙֪G? *En9 !,O@MeTw*ѕ҄#͎K2Mu 2ǀ ~V@</׍.tydIg7u* AڽVS,b2v 钝x5_Jbc bW z/NE;\=eunO3Nck%,->DA(7$:Kk3I 6Gˌd{9uV2#pYb +ӃRZzEF[KFA3}2"{]ǓVn/Ë 1#+Hne]$ k&uA-fUg{:+IYݻT 'D21*Aw [;fN<7˸۷ݝ9kDg)DWk'}ZV}>rG&呷Ff08Q]uHVEhNHXoB8lFT+wUUibz1ɩ#a풭7c29)F׹UIE>S_, +TܛRu;>+y#iմ+*c>ih~AqxSn\!I^Yv7p*rI ̭{QȢڕu*OK/ ea,GKwPwI<7^jI^5euy-:Os,T6[jrNӷӼ1unh;^8N8!}j< A_o#FQvBLJekkԎanU0,6<#6t?Ҫi K$w '.f",Ji5َ9OASrIٰ).QiynFMYVVqEj&C#z՛[[茶0F8pG~EWyߡ=BMwHW]V$BU##<>:?]FUiEyT7WVVqwq&7I+Uev1d΋WNϰ_xLmq3Q̯k/?+{h[{'Ln[F\sЃZ4&•9'%kQE2(((((((u #?lnxv3HAZRT4VtNM5;3 k}v8ǣY k=zqޝt`1w\">H1 y t_F<]-9}{rcN.$kO6W:MWÖ:֙Zї2*Ʊ&dg*&>t;ӥbX$aWA?xU-51W7J3j/ݾ팝[:t:*|*ԚZ^juP bY \̖,UyST6][KRVW[ˍ#sPTRTKRc15%T&vbi1EYHMZ<3kON/h1gAִh.[+beQUu%̶ww_=?tm͟Pn>q}8zU]Gկ彽}FKq"¨n|GsiVA9kGyW,C׭ rX3.gӴ &+++1$ORk,кȌdC GzŰǢiHH9.>PdUKl`+/' K wLou dUX89'N[ Dj5;_^%մ-/\[mFXUāBŸ0g*&>t;ӥbX$aUkhu@vȈ Vns=׊tK9 JUQ@Y>v!zQW7J3j/ݾju˥eePFaTխ'B;VӮ⅜T/rO@+ LlmjVv>cu! pιbr 9b5y|]B(}nbxd nl|ǁBSKP*Rq].lEs ]Ms9Ԛiv p'leXef}Gypg۷g|O<9QH^'9m*NpFqЂq zky{K}6_-G)gJW2gJu1x)ͻmvݽ;m{;n`: D8`rwdžtmҟP&3:t2,llռ;EkIo E%UIdCW#ҼEbKO%][u![B:ЩA+$TMTu$ww^~@g!OgyN:WQG5koo_Q\o`ȹp@+bVx#CQ#<A Q[X@g!d8Vb_i ˝tߕ{Xi6YY^_ov)I'BzX?% IFAt&*maGcɗP+wӹ>^ZZWѶV RWtjַ~G<_6~(<3sʳ?'Mei[zb]uuF:1,$`sxYMFÆ Qn<ՓCc G#҇|W^&:XI|wm/-[^ڟ92uԸ|keEaakv&$I=IfOB'1Aj x銭A'' =C⻽6-|jC4SErQ'1;OLgM;*եUL>:5JSrJ֏5-&yk+."}SQZ΅-5Ko@ wa#9RBkmB?jүdmTeʜ M?W$Mtl"V"S0rPrW둜Zvz֭\k:M+ݷx?Av?g1yRAσ^%ީc1aXu3CA wH7I1;I~OoVխ~1iv֬!$(űrt|aUcIלڒkYѴ-7oi}˽,@zY7_<-{y=Ɨyi$oJ73kܥuZ# %FgmĜ8 cEj5(Zuش>{B)e=@<\i&T1ԱU۷2m7?MN2#+A>n?ۜk煬 O$mNSp[E2Z>W`l2'{BGF>˽F#yٵd˪Ʊ B-+o><2Nk>z߫wau #?lnxv3HAFÞUgm>8k:θ/_nЍd ???^jנ :\6R@ID@<6t*:GWYIÿ3~dF???^jנbÚ:mOkDǘ=<ï߶j׊mյP-dnVຒV ,=POɵh` mBXdRچWR0A@5[ov6H`iO!*wd*r3lu۹<w%J #!ѹQs[VVT ۫8Y5-38jPOĚ=޶q>=qDd'!e?2䍧Th:njtd@fee&TSQE 1Vz???^4ᑥ9'C܂Hv2:pH4$meaAEen+S۟ @'ax_Ikخ&UNJzc جjףsZJT;nj׫U%RMkVOB?POEdn+S۟ @O^MCMS՚ D $c֮Čtu*˧8*F>Q4Xl w\_@ڸK "!^q(B ( >EC,/A2p% u?>nscl淡utm}nn|9g2[}[mהJÂg#׷AeuAsIJa 9#Iݮ102:> pYBpʑ}NnjO}[6mݷsjVׅ}? ?}Əd֟m_r2@yLnbX (Pmッ5𵘞xoaZ]Xו9TEU[!b-Zߖ=sX? ֲɳaVݿx@黮J>!ȲբY<*A;NXc#Zת:>C$ ۶b8'\yJoWq+ߪ;_QFuX=Ĥ19HpG\nQEe*C %UʜiWQEffQEQEQEQEQEQEyF<]-9}{rcF<]-9}{rcouQE!Q@Q@Q@Anӫt@sio$[$Qs,æI, g8ZCg6sWpHn$voW:.(nҵ(Yf[k;#6s&ydN_iq~KtR wG=0$@zΗecxJ?m<.Yg0bH&]3!qkF/ },^-Mx~|<3nDdewZg+;iE>1O3Z5SCϩDj׾<˕ =ī aoglkDz5 []~ٝ̓s9bXhkZ 1䷊k+3(.#|ɵ8__ibm'v72Z _3k(x'v7"=:{"kh129.3;z >7Fm?I,!ٲ6T6:Q":UI hG*?2 @\J+˼3c_S٧>ўw|h5x5A]AO^N6=4A3؁537!Sm,$jRGQ+tz\(`aVVKGQjg+G/U+U?o9G7A"C{ EW_FZ}2fp 8{82=~?y7|.gH`?׾:}{VCN,QJ$[~mH;Kdv:׸t=N4%y ҍ5Efyt=GGNԽ~?/e_tVgGNj/n-6y04x]Ҕ*qJIYkjwtxŶK^^"xݐ= @$3Zc9M JSӍܕ/K`׋YFDQ崈CzrlMGǚQk-1+ /`pw Hsӭ:򗶔~ZK_Gѕ*oNgRWZK't9)#] HC0ƶscTP_kڅN@]/qހWsmg#hMs|ÎޢmsMAd^QobifR"I# kZ֛{_m]-i>{'/EcX<߳G8ϗ͟c ukԭ{ᆚbѩ>x8/1u6NNϊE]#v0 (e ϧZmۯ#2Y%!gN: #!ZJ]-}ޡOT֖-I|;m3 QhېN}rkѣQ5i=Mv['C)!hcEX@cEywqkxo84uO2EvH HnF=)o?&MNȈzAJ;y5ovNKe OjWťı/RGlcan7<.['woK$+%N P[Ou6oսϭ4^{Ͷ޽<kMIal {wp4kZ+V]oK-ﯦ>'tݧY+m}6 (8(((((((xSlZse/==ǧmǷ: OxSlZse/==ǧmǷ:[%!먢B ( ( (41\GJݵ0Ϯu_/O _VHbiXԀOGEZ<ʧL%$C888uUX"UC?<@H6ṷj ݊^jo) M#t,@Ew'OSu([[%|EJ9`=9(ߗҧ( >k%0e!63;TgXuku]VmW:BϐNpVeٰPEPEPEPP2fmST7 Y[Pjw,`6tC;{ޯk\n]Α|u 8 z QE!Q@p#^/r7:BA' k'5كx˚9n;NT!k=; KsxU]% -A`ٶS D9lSk+jZ,mu ޴ 3|xq5E g qyd}sqԟZ9l֪ߥ~5i8jm嵝kYL4Hj>'hmXKEX 2m _ls߇/`ݳG孾=ԙSqҫY>/y ~R6zTGU.h_"sE-gN^Jg UK:|W~`y&lm0X#9#8.jV%jڋ;IfVY|ϳKרsר┱f}b>HﻵEcv#б{l $d'qBN U!Vn ݆rȨHUd!N{]YZ_"0ۂMp~M: H hcP2rpU\g%%7%W=)Fkޓ+o%ks}ue-vyɴW`zW wily-سERQEQU5 ]?jD_);:*7I6aEEsq3aC# p==I&*є 6G"4=b.jM^oTw vcf_*JCAȩZiّ(=Š( (((((J1M?i_߿CǤ%L5\IʹpW}Dc&q c7Im%dJ]<YPܜ=?G٧2&SY~&k)?yg;͛s]fx|i9k^<:b14YWO2 d]_(M{4h4]w~ Olfv8-"ѿ.ܭ#ݞ{WumSK.oV6KN;IN;cjPM8oNM3jqp;[v]7x7#}q&#QCHN9UWWڴ NP4D6ao9 [cU*ҫ˿MoC8Wu߮glH#ŋ9VtJ_Z^C4ZDZ 0"1]G_?^El;+(ӧgg9͓J/U߯uMgg|Կ ~govqް^KK7R|i@jvܩ@cѲ8.뺶5s]JI$˜`8 މAi7+gB#9AJD4vX3J 鶯k=l F鶯YkiCBC"m@!9''=7NLhbfvWI\(i$yNrNw^KI_ljTv^I_kQXQ@Q@Q@Q@Q@Qjm N{^Ǿ='-`}AQjm N{^Ǿ='-`}@$5ԒIe8P}'jY!'hLOTPi{I}>?5/gFSO{Amm8$r@iՉih4Yl, Ŝި3(?1%f.Ak΢ۮfn"yKQhLO紟Ѯo\ˢi\iy%&Wcaˢ1Wܿ3ZGXZ5w3Oo'ӠYT;yhf' =3i?QivLȪUb@$gJ6 吕U,B3(fP@$N+M?b1-sNͧNyBw/?9_m(PLOr_OIvQmIpJ]XmdlͲyokp }  (I5 '{7Z8*i%rHa'j }U.}AfI0ݘ;[NC\kpW:f.-t / 0*9Um)dhmf]B4IIHq紟ѣ3i?\&}/5&KfDE&٦WB`߻dwku cMf]fEH[K2$d|W Ŷ0w紟ѣ3i?QQ@'hLOUxLҘ 3Lc8Nu%wiJJߑ紟ѣ3i?\ޙ?Q;%q3=kGkJ_jakS,mW.Iܳ]ܦvq*0r;MSEc`&Ե}1MFљpNPjhوO2l3.wyDc1Qj+[WicD0zpqp>}_=G/Í:]txwe@G';8=ޯqCΝI4B^戮ֿiYӿ)?ƏH? KW Ӣ?#3RZlu bٍLs8^'l5du7U[:+3U֢l2A=pqe74 Kk@x ~^:akMsF7BR*PiEteWh#nDȲp7&FH$d^/d6//:Gw* LlVuԱ^Ny\3ON{ۧQ^ii{lI5El ÞUI$i ^OH8D9QY&Y E$derOzb*l%Zm2Cfrq}xT*9E]5*v7kI4tmvIv$m 945m~I8>uyu"qy鼎˜ 8rU6jOZ5&o'Es~1ӭR Bܡw?9$8*9s$z䗝 &5IWr=rx*8 LN_+d[YV/YefK`p{49mbH/cRM8%K&sF3Rb#\׌)&Ż*n$૶~tuJ3ЩI'5kx{]ymcsTF7u8sjAG[;\!+Fžrzk:m;?q:m~*N*Hq1d`|GZV!;[7s\QXNzeAǩꕵmk q6oMKEsB[d)$[FvgpݜdI=*[?^qߣ]D۔IWvOU#9"{ŵ(=5O7ڍ^q}r؆.܌@3IR+ui]][$Q7܂(@fe@K:~oݵvm3ZוQcqЂI,Ip3[UJr.YU*RQEaEPEPcڛ`2Ӟ.׿~/I=>Kn=Ajxcڛ`2Ӟ.׿~/I=>Kn=A:/ |'q?xU~!S{uDUO?oRjB5?֣Zj?+GZ5ޱonsN8&z.,W}!WRʙڤ8qlj/?֣ I淲xs=KBĒ5݄Vw"AmM:M>K{I-"hݙ-Zx*XsaWS#@E-'m2D#J&܌X~Zдao堜$L9s;v1_ b/?֣ZEupmM{/c?#0=sֹ=:ޟ[[_?Zmh&šY~=c6x'#6cٕ±il˖"NW(:Yy;݆ggza3IByϾk -YٺK;\2 >ݿ)r3C]m13յ1.'){ @E5DֳEmlG ?J5m'RُXg$wy 9ޢu=+X>UWkz> j᥿Rkcn~E wu; ԎYe彔QaU f5I[KtгlBI+inkH5/x.# U9{bO߷.&{!v5 {Lۖ-f,p/~WiEJQOM?Y!EE=4_$ڨ=Бw"@s\Eik5Ppdjή&uc=1]F56m;/<']ͦxR vKt$ Bvt==:iowjKqT0/m0e9N9Usr3ywQ6Wor{8x<XnfȶO2 &Hg+*X ĦHvVc& ox46gS1S}u:^oy4foR2Xfou]&f+yb1'<3tt(?&ԹۿO7jTeήss_)%<3}c d|̤0^HH{fY,WztM+,wvJKn=Ajxcڛ`2Ӟ.׿~/I=>Kn=A:/ |']ERQEQEr&X Tnnߝs+3We;Tt3G0>k߰+o.9lV qg%Δl9'13eS9g57lR(# >v q;3OHڤ|2X=0]<Ѽ2[ʑ:dps6G 8m&QtA,VXΊXYYC)r!0A5oZ}Ϟd2\+X` 5;m/AK%}PvmX`n/ #G{efy&H'b(t+J2hWWSݵ,b|O.p3V·o?#aӮwZvIOtw2Ij1gu42]>Ya r<:֦א%_QV;f+oO#\a(niXrFe0Z%mU0hZimi/nehԻ!e8e8+Xۀ*U}?%_jR'򱍞ocۊ]cK{K? ۛI\yQ 7.-ѪSǠ7"h?Q_78sv>]ة/-崺ӵT{&k_6)#NUar0p#Uhq\bQ-䷕#Y6($xM`hm.]>i/kh.i0i.%I]8Q}Nnw!-|?3ZCM$Tu k.pڼԃOq]H\^_GQEQҿg~(ҿg~+ R'7-r2C{ EWҿg~*+K]>M ҲAQj]9h3o "=88z58?:mQ}29P0I߿߯psC6^j}<8ѿtVg#OwR.:+3wU[+KVv[qHc $SKo넼T;[eyi[d4rd 䑌0O;-+W_\i]KI:7 G  )ROQ^:pr絼z]5꺭̾T7-m7tתEG46\_ CspiT|͖# ǩ/MqtkFkIT(b0=1#*9ƣeqey ,IIo(+]+MJKQX9PFP((*#o[[ ui;= ,Wl26tu\ mjQY[29%ʌѓJhմ[xqt @\?4u jzի~m'7pG}&<3P{[Ԋ4P畷}KxKt۬$ȩ([q1ģ a]\Cul Mс N#'8#+|I%y Q푊$I;F2xZ..'S[ !n8>իNݺwC/O9%Zug5&6n9霌OƑ\Kp,Xؘr'pxw 6F8*IfNN qsľuH[&kfxџ2I<#M}|"4.I7m_^Gwm~oo;;C[hf,>RPT`݀䘴٬ż+{8#\ѭg,.DbkxV&ز@z~}kúx-Zi_$kn<X٬R.u.O=۞*6*_{_mS?'WSڬ *nFc0 lj61yiuwkTƱs)$r$gwVMK^k%Ւ(Ojc6#0k+9d%/PqG&rZ++y0SZ+;нe7DG$A dG'r@e+XKnV|tu%Um|5ȇM!wC6* 8=q-o5^[tiffػ]\ p3UxH7wxiT_F-Ǚ4xi]=cۮơ;=>H+$kx0_L qk;۴dv )EwbFsg|UӅ$}O)$.ѓ@q]iz洚o}AVxC\!]09uPs'h:WL4k 7BK2* 䃴Uҵ]RXӬKXkk֘y#$9Ӄ3ޓhmxvf5ٔ8HUAu4~%˙`عT\Pv>#jSxVk*3su/kWz֫?-[|7+ӆ_ौGku؇?{ǦQEQEQEQEWK_*麶-u/nLȪHq^X\z ܷwQY- {^+/ O)sB#;EWXQEQEQEQE2iT5@M4vCId>ezڦo}^趤#ʵqv0:DCGW57|.gH`?׾:}_ ((+#Pג[ͼ,Umn;c^9Tv:S`5.m,"\om ''t>2vK?,0azѩ($ʆEh:*6/3wJdlNy9G۾5|ΙN~GfYiܷ1YΦH%h\\|9CVNV#ZS 2 euUJH˕rBd(ZmF;Ym⸓"yU]p0 ≵kgLlUv'''I>s{&Y>cYf6Ca\gwmF;Ym⸓"yU]p0 Ivg>̳ESVmZE-ahUē*, Prx$G*[K0[hy Zi{9Ԟð,> wh?+GH?v6KtSvz֯ U^XJѽ㳳6Ϩ9m`PeW@8W o.aH߃YrJ[sg;m[xk7r+Zs_iCr0xQk6Bm{txEl wCVTI;nhRR* :(@b3OVV2۬3wqA }r{TƜk-ȍ)ɫ- *մ*u Q#JaT&A#{KYaĒHxAy=irKk 'kD Z $-BZ54Man.QNg?T)NrQջ|ʅ$v^עM]Gk=WcdO*N99++rZ4&V8's4SD4 2/G&tbҀ Bv` [Wj6[D#r08<z4۽?RO' P!7I,!7"K xb"7m6냶]men,] CE &);r@8W:x?t ? OOvš8nc9̑,i|I&23sqרM+Y[X,ѕH~$vyF?0Ebw&w_c&.)::j)B)?t ?Əsh0i7n>V9LerӠ8zFu}t5xöƣwȦdcMSbO81df"{)4>8tHVYO RxSxV>eR>b~fݸ@Q}{=΁\X1;;)7N*,% ޭ՞5|N\Cuחxo*A,~fcN?t ?&MY¸4hqS?imE 8W:x?t ?'N0cG+}N5eӲ^^Cu}ܿ˼|[??=je/e/3??=jZZmͿ݌yث=*Qgo*ܿ+@53ZnڬVwYU pgһț0[_Go=QIr- HF@=mVK]? ;?ӃZ7ZWViW1I53!Upm\$3/G"aH>KG-nͥR6+2K +k)uK|(Z)'N]W ^^ԭ/Jmicm~ү{ ]'b;w_`\ޖK(tˠj+5]٣LR u|9Zu|[BZRg #1'm`Kw n.@'I%V%ozuڄו'w%k~juVԋY^kv!Qd+mp{L889/|S]YpH?#oS]ih s_M4FtDb;p3P%ֽ^yg3AQX*O%O9ROu~ի&60 wT]뭚G3Yo|HTTar-}uyYA"{[d)8OۆP9ҼKoJf3WO"\rX \x Z}>;;-ޱ#$i ExTI+oK+ ~!¬Sw~\^v~uoP#}KY- +d@pG5}VXM1E BRp3_  sGe GXMa VH3((Xl J(i[;Y7LȻ!89`J6WEo_d®"uSJэm"~ßMk\$/3$(#9 S.-t;>kA-{S3[ anƒ.a,FK $[&x h/cH䜏8<D}vQ>y|蕯'קQ-_ %d6*!h|z~u[aEmD[_2 iyrcNI:fuvipo!ҖL+ԍKc+r+#)&zXim1qfZMA在^zf_]h~)[{kk_)UI'gH"mi-otV+{Y 6(>L'(9\瞄V_Q)OqOةyQZkW̾oD3I-c-o~Miw[b 6q- !I|e|n0BG@17'ZW- % ' C wQ\%ȳ9FbEms̷:LZَv$ rJ \nĺRiZU^5lV[ܢP;`dWyjJ*e;m,wOn 0+<((J1M?i_߿CǤ%L5={\PStp5?#,֊↡Stp5?5S?鯹OifvW5S?鯹Ax*<xM}}{H 3x*<xM}} CħT+Ok#GY CħT+Ok#j%8O^:_sl=h!OI'E`/e1Jc?鯿}{H 3o}^趮@j%8O^:_slK 'lvJ ==OifszK "!^_s&!qϡ8U?=Š( (ܷ&2K(a;`ܗڀg p3qEoC: u:pتv>!s[9i-P&,UKa=3V?Iw˧nV*R$ͭn/U\o~9[ ∵k[~hCV9brrp;fxwPAiѢf:][N7`eyaQBUSU:oK0*J9ЯYnmN_0!em690<$Ɣ.&EF;~f'!qJh uX+tY ƼJڤ쬿.4KXZdBHc#v2g?/vV-%l 69V$s{iE(jYwba^ $5g/7nӑ -TKNJ r1|όsLQyI585E>Y c1oqy.Nt#֣}@[m г<r;Y}j}4 ~W.~/^XZ'."d>R93m:%.itm}o+ehr>Rp@'v4U=>v.+A@lܢx8r5~ gS*64Š(s((((G[Oj y6Z;EL崌F9VqX4uxp1aezk/y Kw^ׇ1_zQ Kw^ׇ1_zWG}ܿ |,[d!VCsgAkÁKO{/=+ھ_ ׵%c ׵%ctQ_e/?Picc1^J?Picc1^J:(4uxp1ae4uxp1aez{W}TX8İtײCҏTX8İtײCҽ=@y* ,}{^ bXx:~!G* ,}{^ bXx:~!^E_r <>1,1,VTmC"9$N:\u}@*Nsֵ{fir$#=#oA@2.L)q{oV5 gNm`OtU}R'>(`G'z÷L E.{o$1`rs۩=9xHc:wskz}:\tql7O|uZ#46\E&wȒU8 n=4xk%u;^Uv)=>5 gNm`OtUkΝ1힟F[αw (%wN#S4-ڪG5 gNm`OtUkΝ1힟FZ׾+RMvHO-#$n'8V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V?Rs'_P9J?_?\kΝ1힟F@<$1;c9=>V][P6A~l4ӫ?Rs'ˍsCӼ=3X==j1=;t?*di +e03gXu}@*NsXXK1KR@#r;r}Fr\tql7O|uZ!ͬn국>ͪkkE GHL$H8î1)QANmyK6m^xtIuDEb@I 8f2d 9#n}Fx=W7凇fv uYg\vqUEUon(W^{\Kc{=e~axQZKw1WjQ9-_.j7A$n,sK r,H12XrVT]J!g%P{u y$ xzSNjS}XqG$~)ec} ,wQH( NPbQa9C\{2!M7/uFe*O^AҥhJ/#P8,gw;lxE8MgՇ=}xNpt-kndX1`f:zQ]: {}CQJy+Uʍ0S[)lc>8#xE8MgՇ=}Ϧ5O?+og6!;WXӴDjKqy+K|%XFWeW~<]3Î>S}XqG gZ+s;KmX4R\p@❤io4 %vÕUP?+sFG5<]3Î>S}XqG eO5Vw6t$)$p1$ =cFƗY XMQ.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7(161Vt?<]3Î>ܢNjS}XqG vqϫ:{dr.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7(161Vt?<]3Î>ܢNjS}XqG vqϫ:{dr.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7(161Vt?<]3Î>ܢNjS}XqG vqϫ:{dr.N?caOsl)lc>8# + xE8MgՇ=}h鱌㧿@7(161Vt?<]3Î>ܢNjS}XqG vqϫ:{dzsszH=k?X}2T f*b.T0rv~+a f KCzrz 8%)lc>8# <8v3’L%e_$FO5f|A|\~?s#)lc>8#,|[^vb8~ÜQ?0ץ5hWX\\}a#rcU*ǎLjZ3c=}gg$~\gGG~o[[?;l}8Wr=֝k%̐P)lέq;=;~"ui!,*Goǧ &PYQj62}Jk{2dװ|AcѱOn_^'B_ QRcѣZ,+7g̿&Kqȿ#4l\r/gUCظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pf"qȿ#5ECظ_?.?ƳChb܋?G"}{(v OCb~Ghظ_Ϣevhl\r/܋?YQ?1?틏Eb~Gk>=;'١qȿ#4l\r/gG`;4?.?Ə틏E(Pg_[tpN|+5MoU62$HX߶Wy?3RF%zg"ߪa݌vVqJTWKX~Rwn+c eLܯԿ!/{gLV>z%?/>D7%2QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPS ?щ^Ecն>cҼ)o3o[[?;l}8WgOyzW|AcѱOn_^'B_ ψ<{}z63++/K!Gs_*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEu> ΓaK ~ߺ݄Qv1[c?+!'–1+z%?lɗףc=2rORϐ/7%2QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPS ?щ^Ecն>cҼ)o3o[[?;l}8WgOyzW|AcѱOn_^'B_ ψ<{}z63++/K!Gs_*QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEu> ΓaK ~ߺ݄Qv1[c?+!'–1+z%?lɗףc=2rORϐ/7%2QZaEPEPEPE>Yg7"V`Gzp=>աk:]̰'C@$ HpHfQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE3C:O-bWx-~vGom3gt [įL[V"{N1Y^f/y2XlgۦWW_B&^+^{t=KBQ/>@ʔQEhqQ@Q@=!Tb]RB.B >z>wCqr8`2ƩijZI$o1B28(RA ހ9*E ޸4]1 W,G JFI@O-OָeNO c]/,NF@ʌF| jnY%FeFAᙌPtt#r^Xʺ/5dƟh pL'@!>mFEn_&a2;a&?̌POR]۴- DH 7yr`C@]"ծ w0InRF*yBh7[9]vWTe'wzN[Eu \Fh{>E]Hrv;V}<u=Vi*++~qA$`FV1Z|<񳖼ylF?{d'Mp"6Fy^FzXex;wS۷~ˍN32eyHԱXpr(-jf͔#?u$j;&M<2ڷΧǷz{o^z'C|EҴhgiZxXHI#sUW/\\js2[p8EQEQEQE3C:O-bWx-~vGom3gt [įL[V"{N1Y^f/y2XlgۦWW_B&^+^{t=KBQ/>@ʔQEhqQ@hZ(HcV[kΠy6}].1"}`\Z&)#8H {M22 FAkE[R]Z͙i1&Jh~hbҵ#/l/ 7D۷l2RH^,ױKo<u.|Tր6_s3 Y1$6c~@`!BYB䓶<͍ZGniojuq,[,kqGVI9`FH:.ci-Rl[#`(e* -`H5Y>4inbqQnlpL-P3C M IE &Ȃ`6m? 8ʒu? Uukmmfsa(((+NE}q4ϑs&R!I %rP0l3*:u=E$8P]3O4^MxRkhHA>!zI GOA?\ilq: "6pxI/-5K6qq 4Kop*Ӯ?|PumЏ+uFٌ2**?0To|kQbxKmd-7*Q:a$=my-mio!e&GYDEs!IFJ,b|iD@C IUdV nIqMāDE]+X))ZhUKUQT`,7:="/#ՠ5vY%I @04Ñ]xdR} . ѦA<34K(+Q=PMYkMM@*R,VbWTl5vcY˳H%e8->sԊ歮$H 9i@!Tg$($ [%-G1EK1?.A!ͿlW֗Y[]c5⋆(]8G p@ Ehn|ggӸQrS`kY9Q+`!{PK,5 y` D<YcV,oK}_0Ycs6ܦ~m 1@ybum^NKTA >`<_#?.+̵+i<#s ̺B3ڽ3Rܵƣqsm(4IDq1t)MzӤn;p~vRUJT<9 $Ui Ƹ;rP33"MғNղܙ"|B 078X 1x?Ao/fԦK]*I.n &e+6TݴzP9EkkڕX%j8w*痕by^EPEPS ?щ^Ecն>cҼ)o3o[[?;l}8WgOyzW|AcѱOn_^'B_ ψ<{}z63++/K!Gs_*QEQEiz6zu3H2q"Q<V5oes [L8 7y%N Xcu kۀ %g~4xg]dQiRQY6m l+Uwsag $VM+mdVr8$2um6kh5MWX$Os)8=m̷Z'+RpVQIg/-s2եBeAP9XA,p8nƟi:SHYHV8AQ]ioo[H%א7 :9p!}^;,ݜVuQn}U1T-nahWSB*M8ܹd 99׆K; 9 M٭DrM*CNr%[hd-_Zb- $4/",~re wd)[EftP: 3uB7 N54OO/ͤڕf[U.3]Y 1 -D.Mwב3$Ū?گmNэr i+ԞkإLګ'BFAڮ6ejKY[[*۸ı#O"" FC@&E~;,.yM2;#(?)p",|7FnVYB5U_4"]t8c/kPVME<6WBr1'n$PBl:CڶZ De{VT QټƑs)zt!Ga#4wPyʴW̗4 1kɵ>mV8g7?0{D>=ē6oF:9\m%tBUWv^f[ۭj[GR|A&@aUg} 5j)id نeoh Hօi5=GL.6 7 @lᔦ1_3PUXk=@Z+/с!pw/ 8*r8`A50nwsm{\[E $1BĬf)V; n>/4}RYV) ,58) 3Ypַ4F]]ıs$R̩(AF@242_|G5SX?q 5<8_ܨ"470 Mv^ ColMwϠY #ve$[TQbI+b`f# ?.oxE}YVK,1[Mk!]|!=9 W<[%ԬX1ق pr!!%r7r(%y0墂pYFߘ6zxN:=1nh$۞9#zkڌ ΌtI(:$$p+ _ EA1ę' xteA}h7&Y&b#c 怹 2#@1\G܈hQ`X b_W 8#DP3cn@w¬Ok0tБGwUX#.aCTaSXxѢc^I-ÛrNUp@BÚN ;W{B$nyln% !R[k)mD^ 2#+0WoVl2Kk׋Di[%\0cp;P{OZd1#ܖKh>b@'pUA'䓓 sΰ]*$wĊ̜'cUø薺uڮ{ [Suv2;xnI-Z6smof\Ȭ:h6n}W yElt-s6ȣ] gpRq(gt [įL[V"{N1^g ?щ^Ecն>cҳN_K+c eLܯԿ!/{gLV>z%?^|/ɕ( ( 5kM3 ukB[c9mۺɜ`cWoVIiz|K,#I}m #VQÓ!?2NxwM[beN?vσߕ']8|y͢L_"C-0>frBRkZKx>g9mAoB$vE'θ@>u 0fq21]#}(:M}:K02WA@ v6T5oc; G̉4uDX, y3}Ul :'s%h`})X &3{9`p#I&\xsW%7@g[ UےS؀p$By2'T>e1~_2%Z<BrX۽MGJNfе"1 T Ջ -mw XKki5 ƪsH&2G'k瀆$. KK Awc!PZB$88d<o[h!s_^J<;N 1spS/lutFK*lB&..r1v7T"XYIGy*Eqo cG#TB|PGS7rWh6i$djr 2dr31`ɞGūcL.mp,۩'#~hfp n)υt~j{dy6Z!$fr2Fհ-籚;G G΁2Ͱ2fsp>lt;;K;;[#MB ZEPDlnc#2Oaww`#-+@U/sKF3j7mأ`)0r4VfI&jǘ&` HuIgoIiRV6 -3|Ӆ矪g{u-m%5-$!Á,r2s`;q&dxfch!F#qѵEo3bI% Ka 0pxuKK=WpĥD2L ++nWrJrLŦU$i^{bLKPu䏺psUܑCܣ OI.VXL|',/bZI&XIUE| Cq͖p~a F7)516}y4h4[eJx.cvV2 epH(~VtA>il|V.7~\fp00Zׂ[ ifhP%R]]Ie7u@ z坬˩[Cup>AH{Fn!Zj5-㸎!p/(UI1b(cIf!ZLÖVW5ڽnZIe,V Wwnno7ǷyF!* srLQ+/$6BUIVW *B bimxT. ۺ773N n pW*wGzr2劺ŘP +)\z߄{Ŕia_"݌]$!`@ lw#4r,p!d5e mXF3WQCrGuiikbѹʶ@oݖR ! eX- N+y[U9EdgAwPS{8Cxru=Ɩ){o=eހ!SPž{~.m Kp=cwWae 0Hu|<=X㘥L8'ϖR ر[a!]虔(+0}( #`瓍dյh#&ip ỶBFM`]=ZO*[FW Vִsjyaq ~TBI#'Șr! _ۛ-A&-&{.g Sl}F_1-~[L5i%y24!K|PɁy\h'YK !S^B1lsa8?v tn6;ԡe[KBRwa`>$n哮IЮ5!ҬZTy .SvP\[C|_W$BckEÑ27<`c[t닭Jgy#LB*Y' ةpǨIeQkZ9'GD8RT˳;#.`[XdD]$lO]H邺)tg|>*YarA,Ae'phcN SOCd<$x8e`]|3Xjj_keg>`Yԑ('9\B4[I&೪Pdo"0\Gi1GvB&ˈ7H;A,3n.XڊM~Mm!}6Idנ41Dhubw?AjZ7Y\jKtgfU4\2q2>\oQO6,0YK au'RwO10εmZqhE/nn6zn$a$_`P[hU崾Q upk`1YdQ$򌝱{ Kew7wW/>k5!]>H#/ WP3vwV/mym5c|S!F\@E3C:O-bWx-~vGom3gt [įL[V"{N1Y^f/y2XlgۦWW_B&^+^{t=KBQ/>@ʔQEhqQ@nhIR, N(񁽔1XUg}[kioʏ.cPv#7aդyEմUD5}NAgVQkdkp" ̲YY[-p#;QN:"JXwu*؅!Uq[xUO;\(Y;ˈ`ҼJ2:@*IY][>켎NPrʠ8%99mg%@۴11-/ }V ^E-IC5 f*u+ud'9p޼vVk+h )#\FF 5_t֒[%7'+ǝ\F˴W^M1?E,ѕUda*v ckgBS-u v4j$+|1@ XqT4N Vnm$.Da#yg(=(gLc6QZ[G e|ϓ p6kVƬҴ[jʉ /Y0 6e r%-q~,yf`!1TG Lmg bNmM PȾ6˷Q@VT,-Z&L&l〾PLq+ EeySjn2=scIӼMg(iX-̘*p@#LJi:6kGo{5H( QJ}Č22w6M.u4i BI[ltwvpYZD򶨏mēcL_+Ӵ E#w6H=`gGn[+;]A.m~0S,$U#F, ^B@WZS }YQ*2Ń'ʃ@ݕ#KD|5f@$ǹԗ!rCJI tKgk[2B2H<6CsXUC6'1mXYw!Ҥ;3Ir( u`FԶPDql1#< gh#iaNM,Ec*wsRIɻ,odu9Ƨ2۪uSdcFps+V+izuwW|0D|˝@6 ݵN@s@:Xv-X /FP3CKt FDi>-H3).;`.Wv4CF=2@,@5(&f6QGί6`H+^hkv^ys$QtĥМdeNr<Z KKmwy(] Cp̪RP<#`ʽ&ln"teBn;(AEfӠih&ٖX8$R@,AO xK \$d܆is%8w1N c@:m~~"RHw!Zg<]f"+wl Saf䐉xdM~$g[X$>]Uȑ~8<`.-a$k \\|0>NH`Aʀt7ZӮu3m'W*2%+«Y>a.}CdJꭈr%r`Qg;qê]ٵHϕrX,Unb@CI&Z-ս3ʜ`FVqO'c&w<x0$rv|OcgZOk˩I!g A(iǤ uK%p9 NUT&.1@yncJF)WtmϜ 'Oȡ2A+aT GvTXʡF3Z1ڼ[ec\a[ 4{n8Xg^̒p[p*jKR&Ҟ>v# ȦFaڻNafhUבnnu+" pW1`dV6׺.ysɩW1N[z#N3() 0cT-u-A:M j7+0)n٘]܃ 6_p\eBJ~W-@4F@S@^ii%| f%~X-u@v&՚9¶(Q ǐ1_1$9#/eމhW/miu).qN'둷BI8/T%>tS QEu> ΓaK ~ߺ݄Qv1[c?+!'–1+z%?lɗףc=2rORϐ/7%2QZaEP]O?eOqMJ[pQ`~ \yj[S!iuM8a$H+#Fv䐜Aѭ,bk-Fe(7Π K{kեn˩"m+1X8oǨXGqʍeU27la9;= \"HAFG*w|*`0qHu%$r<MxL`\eJe&n]\bYA'rHc )Ee=fkt謠,Jʘ-9ePTU88<msF#V;˳ 2 qD p,wWk6y'-%adUe: fi(m8x&Pt-yr,Wh09,vN6-X(®BC*1\'$6)c}r;mT@!ÒT2@9L.mB{dᄔHW.1k~X$/,ʪ%BUɲ#, iayqfE]5Qq9 Xܨ6^(N/5R7J$.&s$uİixaզE + yl@Rs=cP尕Ď !X"bXƻGXǦG=[LwFъ}cd8=|I9`NL^#ֵ ,mbqHn34ɓ$)ˀ.u^\wV+1*Du 82 ~` lV+K 9W͕H?+/ †=Ι4Zڻݭ&gj*d(| nR7_l. [HI*Cɵ+E9Jb~^ 9K.5 7Ϻr/jq^ A$\wA rlFv<Xud5]x-Xtl#!y%Xd#\}&S͠T5Xp81l6CZ{{K]oDyn1sDq)M rʻvXud8uTLR5˿;t6{j]q g+/ȅ[+ "ne u $ChڊZ_8c #GԢIO3 H_ )#F;.71=[D[#¢[8KbҿخT;p{Xj͡nO-!KY`U2V.TF#bkDm.;k5[ ST?x VCaa\ɏ=hF&8x܎aOV\z]>Kt44RhLN;&] eWҼ)yi^Տ_,9Rszy|Jv.-`mC)..PHޥ2w3KLխzvm1XͿ7(v#nv -XL$v9PF?POB$ٕ=pz.u=FPܳG%zS#q3cvgc3 S3d3@u{ؖeL[:a$#Sm#(u9Z.O]Y4L<[Dݑ \-dMtehe1B˅!U$CNy\*x/QᵷԵ ëLKEIhثn#! g I;$QB-#X@Uշ4p9ا-̖-s]@Dt.PPXF\uh?mR( :4nR1IxΆsi3ʹ!+ ۗz;PMq>uz혒xs3CUwp9!j,^/gkAE.`u jim_0(Ѿ $)Pq'Ai,Z-RI MVu=(á$vEAz}}9Q#6|BpIegwiw!ቭIpmPJp'mOay׺{M2+b*rU88\R&6I~o-Li[p(>\q9u2F8կ1%Q|%*Fpa@fCwW3X [,!3P\Z;BYR2Z[y>CGò8 lK+Wsk,kC T 9:ɽn^VH2ʊBIQ qywkg>,gemL H+=~PKo=fm6g%S$-IC;mIwe7 k!bd3dմn?\o"rY xY2= !K4f\rH$b 7pk*EСgز,{Tm+kF Ƀn2[瑆? ֺ=sÚ 6u+e@R9$e.Q8U,`\O%wk%г2a%^Fxd%O^ƀ!(gt [įL[V"{N1^g ?щ^Ecն>cҳN_K+c eLܯԿ!/{gLV>z%?^|/ɕ( ( ( 4RNu$Acxv:m/)n#UEK; o徜ֈ0Z\nUHR0\ь[[O~SB.\WJ#p ~cM.6ElcqjXKEݐhӵdluY-BN͐X2ijUB2кo|1b~|@?(f~m4Pi|adx?*~QRH5Z%:Lw>pYÜ6?Lӭ4K}F$(F$ ڌ^2rIl.q˺h)AO>c0Qsj'D2̒ %;0y@t ?nKvU uEЂW!iSC14{jжvfM Rr.9''2K] r|o-qr!YOts[eXDѴM"<' u62Ef^H=3O"-0P8"Lc(8&J^ƒ[2"7r?ʧ i.|1y?`HFpA@S0k:Dfwycpy2^,$V0Ȣɑ)H%c 5?:Nhzlv=4 Sl_nC]uTMGMἹT2S,W$9 ەn8k7ϥ]8fveXpNxA/on!uK A5ݽyE]L6%r2y/^Y\\P#BWrnS9`n@9=uB82JtGc+@P0s{/"4HT|c-&ry4W:厑nn#y_eؠpN[F+1/#rJɩo.A"-Ǜd 27t+Qyqo3\udio)@` fsS&̶r^ :vą߷_-T-sI,*OẁWU'i'o99^c贫/$RLn9.ޭ'vÄ>m2(;7ES;oi>S LJ#nT1PfL^*)2M&@O0j%ݔL#.C$lyج6xRv_t]B-Ջ2K!e%W!#XeF՞%խLHKJq'* Pլn-c Ky6W~~^pۥgI^y,Lf,rr`=~p*xR?xZs!+Wd;d#h'婒wJ٧Laɒ̥ccepy`OilRBp,?8w4]9$WOP"UX+*(FwCi~"յ1e6ò< #n~q鏦뱋 \[^*(M21T`ޅBejY4kSǚi'-B mq,ڞwI#ckn`Z@$9r' }WE$TpDiKʄE۱7.[U{&=KOy"1hx$AaZMʑCmK ֋q+Oҫ.0}~V);sj in}/U"bFT1<6W==_C}^4Dr"@YP3(~eP*Fk KDTIyf;%aJ<>kfMUcpty61ss!XUwTͽhbF"AY9GTcJ (:gIJEUon(W^~ ΓaK ~ߺ݄Qv1[c?+:{4¿6;&^+^{t=KBW|AcѱOn_^'B_ ?R(0(x`]Q³.ypqk~qaCdO qK=wsF 0 \eZ Qi7Wen\- (̄K]YGo\ tk$v.eyyH͜3q\Z53Mn3!Fǎ0XqZ,EӣKU!,_n\'U+mIַvcvp˒Nl .sRytۉl,Χy!^ FѼ_@<7#i\\O;e. 2il`|Xf^/# 9,b0$@ 8 mUnafƱ1:h>) Ӵ _]ZjvpVP?>R3ݹc8nxvKMNuN}3fm}͟˴1̺sºsO>07!|b@GMmiq}K !XmA} | ?A\i1Bmgf@vF|7 sʜzkEm7$UFx+$i!X⥌ $dк6TsTaSreI B[:㿼i<ƕ YUs02sZZtkiͅ?-׮'H@+Ghʭ ժFTrW%Iٍpp\= @^"[u/qA7yeT>pW`Qm 1s,q[5FrGع (͇AH뻆* .1&AbS6{_.GM=$11Ta#g$nM9/i:캶{ҿ#$o+n2BaluY rE!u#䛄d732Gb5E*ˆi?wۥfj:LY\ipMs,3&7#oMRKmn#,Vch݄M?(  T:0v)\R K$Rl924 eX*`@"H%NK +c Tkt94:jR.)"ۢx9nq}%[Rf$++yj@3#<9pI}Xx-ЛRaB.?=A۹Y<@gf f`Ʉpr h8b$Ydhwbcp!ll<ΐm_8~-P3HrA<3,mt2Ȫ6+`'!O[$sK\ⅷsI!wn(y}Cč=*5lA*Ku]! '{<fr6{hV'x!'=[nq6muX/HmZ !1=˴n9$(WI ʯ.j]#:yr7“۱Qnh..фRE"O3ȒX]nW]&f/gvcuaK;s#nC7I{/}K"39VYy^@{$kli} XggANW6ZE0BBs׌ ԣJէԛMBx'q~7^ OʹcAҿn%v3EI:r]`Q vo=æ[˥D}%Sʹ#NcknҽK4#AqnrKDTIT09AQuH/ u/ )V8b2@ (_ܴ:呺c /w#ܳnW$-Rr{m.[ƸdrO2+dF!|_wZu&I%c rc.++4Rp2 !&Ф2>M K=,rY@BЩ#rNу)ްG}e>;u,Ep䙢$䳠d8d(2{4;kkӤ\̤Ia;u!çL͏yE(2H%dKWOŕ$zā:V,`B EQE3C:O-bWx-~vGom3gt [įL[V"{N1Y^f/y2XlgۦWW_B&^+^{t=KBQ/>@ʔQEhqQ@Q@V_M `ۤ92&A󁀡 :זvi*d,>mh'h23Ӎ`Ogb04"5NC* w@rYy.|Kw%b4V1Ōp3q;Tн0E`[j~XASĖ$[hfs&]JK;$HID'd`*yn.LL+i:5Es4Q.6* 9$i4 ]&)n76녅9fC6yAZ,Ȃ OuYY]ߧ:m&5oŠ&H]Ċ ),@ls5[OFLƒ;Fےdžu CEv/oKExD; - Tps]-mOd1Z̙!&`v䃂zs@nkjb;cy|tK dWR:"K}/R mi٘y¸Ph*8+Y]7gʘg"ṇVpp@'oFt}%=,4y>~7vOE r@ es@04h!qC6^Fb IJ)+A\9meKk4^ Bej K#'M<8ee럳N7mya`!5 [#i[nK{W ^_*bss \be܈UpWY8B/VSOp,?_*Y,ф 92'rn Rq. K9i[ծukoIk BFfp#2c&}n D76T /?/MߦunZIYtf +W߫Z!uNDk@nSH܀8MKWOG̞`V'|̙$`!Շn{y6P dcllp  !I-w]jVޓ:,@KĀ qɠ ;iM`ey'mʠ3+ij3YcԵ WkK䭻}iNbe8*sC.jM{n&KU"#w pY)nb,є*$-dܠgh~=7q ,(Rnz5.ozY[j C 9# 8ZFYLm..-Em?٢Dvb+mᘝH99%4햆K9 бé'lJ0FKxA&8^ 7RW,B2>LVK",..-[Dw%©9%VB0Ь i@Ke,7rsq*e}ws .]($Ra]aֵ W۬VQI7Q#v9*$m9ȴ.-d#x*A A ڹؚe_[i:uv`1F rˀN~Cisl! . U81LWp[xn{x7w+) c J㱅IF;K}RXR$V34j#V?8\om&s[AqK-rLc)F<6Z$وhо~|B1 h6iosbF`4x;Y&(]}.֗cؙ0Ҫn\F*x*!x3^Osw32aMێۓ Cy'vzYۻ ΪTʽ:p2q VMӦ6:r~F&&FpLd P蚜>$X5Xw!FY0C5!-SQ}/Q]gbrI+#9%IgҟM `t.q#a#E '2dc Al Vn_xEy#j)l"y|9$5g=u:7ΈPB8X`g?6A4nP*$bxPE\ H-m&}ab2n?Sa@"|6WA*n^=Dun.#oVUTnB20MWDD,7v^Y*%qU! r>M?In;LX;+!h>$猁Y:|ܛF&V"0Ĺ#6юz?Mk[W?^df43;vv`0)\8zV{j]_ʮ`mYm0iϊ$[)٥%شkހp9vmGRu ;mF;sn`$6Gn#P0 KpNFHYkV: =#+s| zB+->%J\wB[ Cckya\%]cd11)"+Osk,-.X6aB(Ojo>I$Ý6 Նݭj7zӪ ms' =f]ֿlEĶep@;1m35PB]JTr)vVb71ĞV(((((gt [įL[V"{N1^g ?щ^Ecն>cҳN_K+c eLܯԿ!/{gLV>z%?^|/ɕ( ( ( ( a}.vƩ"S$cUlu%%FGU4O$#y319$ԓL{,I#Ļ# Ą\$ISEEVYd}F8Cn̍4 u-q<1M ,lgy'>3FM%WkFkeS9r hdF;z>e8 Ffbp&;+kQGti1c&k4bG|ā\jV[6+yc-/uM9H n |Tt@hX:ol4x\LmvIHb@(9U&t*:d؃A<7I%LR\%]]\igޥ RWBPdg89t6;Om>O4 $8TVGp FrXYt]6{4eUFeE`F lZ]2,~BǪovR%7{=2՟N[h4wW0 hؒ .Isd`mtʋgi{"LGgf..h ;b#8ʐrTm#O^u%Pi3,͍G%H$d!Zq\Qȱ\4w&~.Umvg1w +?j7w 1HM11RHwsx,WdiX-Ǔۛ#c%ޛXV1"'cnEe ͸Wmn4Qm;FQS2am1? PY}7TO7F_"VC,xbU͡K{[c}rBT -uP٧Ns<‘f*H1a[*2+!Ӧ+m~֣˹\\3М h[CisP՛rbrP9WkhdtղE/dys* eLܯԿ!/ ~LEVQEQEQEQEQEQEQEiz{L/(o4FXeQ{zsi!5k]GU2ƪ0}N933\G]3햇aGx(Xn]Gs X7hqiZ֧G]"![PI^RY1VP~ff-[l$Pd8c;L;aPg2@j<$k?),>pCndi-4{}%+o|,וr_ $ZZZ>]'(!FT$t;t~҈%&[.@[.~<XEvd“9bce } ewkc #}M2ssP z[)/`N1gFn yAlګܯ'>w z;hu( 0a:v^+Nu{8-bEH%POp95^_m \ǕM r i5힟_E`P1|ǻ䟛J]Yڦg,zd=ҁ{2),k:2*쑩y͑v:L4=r}NkIݾ䝑d*H?04Յ 9YeY$;Cmm8lr% 8×ֺsod n#{C0*9i?Qu1I%9r0 L,vsZ]]Kjۡ>8G%>TLYhB8",XKf>c&\b6RNbZVm#Y.(d1l009]XpXk.mB$#pA]mqMJ;&kµCvقc Qն( 1T ĞVxKiTu=yq<#`“Іc&ڗ0xOQ-=; ?K ؑ\3(Fp6ߟܛJ _Kka( L*J``mߏ״.lnT2(*p@m !lM֒>Dl`*0GbF1f 9(((((((()o3o[[?;l}8Wy?3RF%zg"ߪa݌vVqJΞ;1 /͎ɗףc=2rORy2XlgۦWW_ByĿ&T+C(((((((sˮH< ueݻoE,F@^O>mxO\%I fnpB=Ԋ[Q\z+;ǩMElqk4e{.V4xghpx0uj4{ LZM9pY8(|G#U˸j4}[]Bpn*vcʶ: WJ~!R,]VoSE,go'Y@Qs&/KGCSh\|@ZʃR[22+–F coLYi0BY9d3 Hې8c!K7NuVqB9=K ky-<FbG 2.0OSjھ ,ɽ\C.NN Q+<6/djЧ#1~) Oe l' 1;[R՛XЭmޣmrf/ٰBwRz`@ͪ/n!HE*+ >@b\k7nbL{Cdٻl1;kwjy໸̐LL(qr @{hYx3Qt nmey LڧQLrHs\:LOeX^YP )ZiZs\Oi]+%혻w20V@Q*tZ֧SL}*5.K2nEʆvh[6?41.ɕDFF.Osiv [MӯsWwg8QBϔBJ@yY4-'Œ4'N,u=Gw_ƱH# Gf26P~3ڿ4,X*Kocm@@e\h PX0Uc%y\sp,]$xWAm#>kwj24\ `$ cs ܀s8f ( ( ( ( ( ( ( (:gIJEUon(W^~ ΓaK ~ߺ݄Qv1[c?+:{4¿6;&^+^{t=KBW|AcѱOn_^'B_ ?R(0(((((((#Ú%imɆcWfPH#j:cVΆu>,.3 l&$|T8ruV>%Y#5m+;[Ye JeHn$ՙmgylг(fU6)`B[;5mXW:]֑]wZ[6D,ێALV&:CLv4lܧo`;ҿ)|⹲մ&q6Ss](4cs=DN[j)r78cͫDws."Z7<!JKOM'ig̱; 6)X@O1ҵFou",NPƻGB @-jZÿͳa[\aLj$g#pBݶO ZDWh́BW.$a1UI<$.z\Kq#J*Q[ \Y=%]Ko2mL3A(uY[ӯl-KjºG K ;Hm2tŒַ&qn.7*.]|T˾@7.U~nhϵO6[lKGkt{6%*IT,דmJkX)U-$g½U5/--nac@JZE/"&<34B">eii!h,wkY0 ':ECjzyY;I87~UJ(((((((((gt [įL[V"{N1^g ?щ^Ecն>cҳN_K+c eLܯԿ!/{gLV>z%?^|/ɕ( ( ( ( ( ( ( ( (-i]xؗȮWل*ClnĜxtKmYl$ZdӄW`r$.aCͩ&u-*1^6#RxroZ_(ԖIM>[]FT$|m@vW ߹<(S_4+\tar9>w3OL w;x((%ic <{_ n-)QUgF.TSL!`]CmRNz;AcL"V0HZ@UI c#ږz̚mݥv?qG,CE 1/dw_Ŗeij*>ZyMd(n9k(EEP1 2$&Ì'9 xs-\2[NXy_i63ζ<+opԬB-,b|ؗ+'\2pj^qg-bi&wW1U\.-7[} 19*C ij7z=NiN]N77V<''rΛfv-UB b>0ɠ((((((((()o3o[[?;l}8Wy?3RF%zg"ߪa݌vVqJΞ;1 /͎ɗףc=2rORy2XlgۦWW_ByĿ&T+C((((((((o4:yuGՔy&zsh7B@i:ޭOpNۤ8*gx_W^++K\;O]̥`|r+gJ.oYΗ6w"IM 5̘)ּnK)lo,+,;~J4ZVѽuQƑ@&z.py^+:}r+CFemž]Rr͖Ǟ|AOZjusW+pyrUs"Vam@w5k=#k$GNsybrln߃F-ʟtj cҼ)o3o[[?;l}8WgOyzW|AcѱOn_^'B_ ψ<{}z63++/K!Gs_*QEQEQEQEQEQEQEQEQEQEQEv[3DӼy3Onbĸ8Ǖ=Efw4#Tؒ@U=((((((((((((gt [įL[V"{N1^g ?щ^Ecն>cҳN_K+c eLܯԿ!/{7noR/7p1gKBQ/>@ʔQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@O?3RF%zg"ߪa݌vVqJ?gIJ[Mi.ueL-AˌuzVtًi~l/F{=e~x! +> eLܯԿ!/ ~LEVQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE3C:O-bWx-~vGom3gt [įL[V"{N1Y^f/ɵkǷH#fV݁}9@+\Qu#nk O&{/q\ׯo.$aWá~4ԇZ*b?@@th様: 2_E1'@f{п X:\QI$?z} Xa$?8۟?3rE&SF MG:ĂAR?j}l:fEq'@f{>^{/qu6q6y% p?SH[gc?}M?`~$֢K_S/N?tqi=闸} N:'2֑wjq}MIZVU׏a߈iUo%*:84~'@f{Ոƴ˟h6 c?_SND֏xsnNqd~']yE{+N:'2|88I9Y^5j5]7n{cakBOmϨoK5̬^"qzqsILh/N?tqi=闸} \Xu.W؏Dbs?_SPuXΫ͹={*4ڒGËӏuOoe?_C@qzqsILjMhD^>;s51Hܞo?*Ye+:84~'@f{ըZ*[rs?<:p#;N0m8 ~]#9֣GNM4{N_S/N?tqi=闸} N:'2Z/M6A$'c d>~$k_ "qzqsILh/N?tqi=闸} Z5&@6wijaTsny?d~ViQ˗_+N:'2|88I9Y^5rXumO6ǰ5#Zy"Oh᜛rq?t~g{[j8)+\|88I9Y^4:84~ ֋0֏?6qjDZ*b?@@PO5WËӏuOoe?_C@qzqsILj i$ '&SZ\??}M/c锳:fD#N:'2|88I9Y^5`id?œsq=jEZ؏<0=i%_ "qzqsILh/N?tqi=闸} LNV3mpjMҲ|/6d~g{FJy/T|88I9Y^4:84~F5\kGe'r&|[rs#9=*+K_U/N?tqi=闸} N:'2W Zm[sZxn}@}M?`k~"YG.egWGËӏuOoe?_C@qzqsILjíyr$`ca#>>u^md~+.߈iQԖ_B>^{/q22'<<}}-քA㱷? aJuxW;6Aɣ.߈jT|_P/N?tqi=闸} N:'2QU^?ݢ6?_SNxu2lFv`p@}M?`~"yӷ2W< }c/}$0];$+ǩ6uY2Eظ"=mqFZag96Ec\IJɨڹ#@u/W\$sǪR^[?mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/Example2.py0000644000175000017500000000342310504574206024271 0ustar debiandebianimport sys; sys.path.insert(0, '.') #Example Two: Changing materials #Start this example by making a collection of points, v: v = ( (0.,0.,0.), (1.,0.,0.), (0.,1.,0.), (1.,1.,0.), (0.,2.,0.), (1.,2.,0.), (0.,3.,0.), (1.,3.,0.), (0.,4.,0.), (1.,4.,0.), (0.,5.,0.), (1.,5.,0.), (0.,6.,0.), (1.,6.,0.)) #defining some colors: RED =(1., 0., 0.) GREEN = (0., 1., 0.) BLUE =(0., 0., 1.) #and collections of colors: col = ( RED, RED, RED, GREEN, GREEN, GREEN, BLUE, BLUE, BLUE, RED, GREEN, BLUE, RED, GREEN ) col2 = ( RED, RED, RED, RED, RED, RED, RED, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN, GREEN) #Define a list to specify the faces of the lines we make later: ind = (range(14),) #Start up a viewer : from DejaVu import Viewer vi = Viewer() #and make a line: from DejaVu.IndexedPolylines import IndexedPolylines p = IndexedPolylines('testColor', vertices = v, faces = ind, materials = col) #and add it to the viewer: vi.AddObject(p) #and make another line: p2 = IndexedPolylines('testColor2', vertices = v, faces = ind,materials = col2) #and add it to the viewer: vi.AddObject(p2) #With these two objects in the viewer, try changing the current object #and transforming it. #Add another line: norm = ((1.0, 0., 0.0 ),) * 14 pn = IndexedPolylines('testMaterial', vertices = v, faces = ind, materials = col, vnormals = norm) vi.AddObject(pn) #Add another line: pn2col = IndexedPolylines('testMaterial2', vertices = v, faces = ind, materials = col2, vnormals = norm) vi.AddObject(pn2col) #Finally, try making some rows of spheres colored differently: from DejaVu.Spheres import Spheres s1 = Spheres('test', centers = v, radii = (0.4,), materials = col,quality=15) vi.AddObject(s1) s2 = Spheres('test', centers = v, radii = (0.4,), materials = col2) vi.AddObject(s2) print "end of Example2"mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/Tutorial/example3h.jpg0000644000175000017500000011627710504574206024646 0ustar debiandebianJFIFGCREATOR: XV Version 3.10 Rev: 12/16/94 Quality = 75, Smoothing = 0 C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?X-QdiNYݛk$pE­V>%?/ֆs.􏏽}tvJnN-? z'C0cH1a?J[lĿZN:>>qW1ojˤ=r|Ð;fиcH1a?J}XF"o/9X[lĿZN:>>qW!.~3puϤ|}fbi11?!UeӡYn.K 0IG]mhg?8Hߡ\ĺg%q>CC%=BA+8++NG߻cHC+]OlIecIsMc/ͼFdCGj|K_ \'s{8[lĿZN:>>qW8.,XG$Y*a0rsm?RN$~tI PR}?!@>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zP.' cc1~CҀ!>%?/ֆs.􏏽}|K_ \'s{8Ac x1zS.;éܷ9 #p8~.~3puϤ|}C]mhg?8Hߡ\.' cc1~Cҁq8&c1#V {T{I ׁ;X\evqNlv̇ĺg%q>Ccs)]W36c0L>{݇flRI.&EH[T$T ={|K_ \'s{8 IԴo17<_ 8b7(E AwZԴ=)/;LOqGLJn%F$ZdT 9s#)`JElDGEgn%>Fr'9~P+y;t1;Wsim\nK&T9)=3޴]4iڭ͵1Xx\f Pp0pgY817>ܸR*_c>w YA{%>ȗ*J%Vq817>|Z[.e yR|ģ^}ϧ'2?cS_tu_jٵ6,1&cIb8+|cW>6\{f&~gӐÜAq혛NNe=Op5AqlfFqp.S$dhڔ Cir$O$*'9W9ى>6\{f&~gӓwcS_SMtUo9)Xtdѥg5rvE'q RXs.={}?3|ma Mϧ'2Ƨ"K klXK {FQ1rXcDgյ˘eA -H#GskqǶboo}99ى]WejoiCu $7Bgq9]TqQq \817> lOrs.j+O9ى>6\{f&~gӓwcS_tW2|ma Mϧ!817>˸{㦢kqǶboo}99ى]W5̟Xs.={}?3|ma Mϧ'2Ƨ騮dÜAq혛NCkqǶboo}99p5?MEs' lOrXs.={}?3̻:j+>6\{f&~gӐÜAq혛NNe=OqQ\817> lOrs.j+O9ى>6\{f&~gӓwcS_tW2|ma Mϧ!817>˸{㦢kqǶboo}99ى]W5̟Xs.={}?3|ma Mϧ'2Ƨ騮dÜAq혛NCkqǶboo}99p5?MEs' lOrXs.={}?3̻:j+>6\{f&~gӐÜAq혛NNe=OqS=ۏ;}cOG˟Xs.={}?3$+Ho0AR;{94s.j+|KmE:$D]!CԎ6sZMm Ğdċ#ykqǶboo}99ى]WE|>8ߦ?yĺU/ fSS_N{/ j0'!4~_)q,8Oz:sJ1OyG<]4wCq-l֊dxĮI1~4U ħ\<#֊8>Lq]ѿzO1zcD|>?y;QZaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^C}49<}r>/s饱ϧ!FrvP_ENx3q)3<9?3ħ\<#֊|Hv=1Ǣt>AusFu;G>ӷ= 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z9kԾqϦ>oGuC}9ħ\<#֊'7#9sϓ\?Z+CO#pc}]ׯtN߇8N.oγ#?QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_ 8KcOCϷ#:-R_!>[~}Qg/'eU_47#9sϓ\?Z( J|>Nsr?h1\Nsr?hx3q)3<9?388>Lq]ѿzO1zcD|>?y;QZaEPEPEPE1Yh6i3$J$u8R$9Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@z9kԾqϦ>oGuC}9ħ\<#֊'7#9sϓ\?Z+CO#pc}]ׯtN߇8N.oγ#?QEQEQEQS\ZOiyɴM6{8<EC]s£fBq$ғl̓ymx7,'#٠>XeMUu `O= PE2|Q!h?cV5QEQEQEQEQEQEQEQEh.v^6TIa[(ZH# g'c#2!`"B,ǎOrRH_~ОjZ4nFc \ݖ[Cئwҝ%9$t3fe'$V v27++`3Rshg:Gm.$~^/}3TےI8hk;Im̸b2c2x.+O/-Zk:@#9V 0 g<įݟQͼ@?ָF Տ+pY4[fgo8uqQEQEQEQE_ 8KcOCϷ#:-R_!>[~}Qg/'eU_47#9sϓ\?Z( J|>Nsr?h1b$ ےrqUjkK˫ 3X\.FpHk5K[h5K쑻O<~ /i˨G 7=%!UG4kʹlm+y<:wq hhe'2Pr: mCᾥcq4]Еb6/YP Xaq۟*h݃Hg6pwl1-VkyN1ASIuP@b[#qPs#ߦ/JhPr@(8 2 r>"&++9-8l o 0w%MB+Asv6&2zm6WrEig5ZޓWB@ވ ve@ wW}Ա^U; ~J@PrhWK2.~HbX9wmA N3Zz]Ŕjv DX,W s%֗v$1 2e.GH9u EXXAAմN]巄9nN@Q3n|"+X7$BDpbd%' enJxZ<'ZLRdHLoi+f[hXH {M*--0[Co(F۷ޭ$'hWivֲ#LoaYI>X#;rppz (X>ľ)V(_.8* *TM#-Аp~=EW((((( 4RNu$+-<|wZR+!C-B *}H9}fhcĞ[˻|k e7nQ+}G;is0|ˋwP[7$i` wMu᫋-Oy'u$/U@̰2Ǒ?'nXwhl.`El/(~b3¾T$H5 O&纍 DI3C1 .5ɶ>4B9̛<弶9G<(y&ϛ5SP,ʻ,Q% '?73FrREҵtb)mo-YRGNCP`WI -!foMoH+@3Q=⶷-I&y ]O%1F;&LN<HB ܡ3(Yt#PE YþwA$9)Qos HfnBlc{yA[d{s!iK nT1nRW1cY/簟h+%'גîH@6um"$FC*Tmcت6w4ۋ?|,v7QOܸH\mAqH"s}i]ZD<$;U)p8]-Gjh2 [krkt!7pwR<@/s饱ϧ!FrvP_ENx3q)3<9?3ħ\<#֊|Hv=1Ǣt>AusFu;G>ӷ= 7kODTQEhqQ@oӧiKgbHuA\g:EyO[:M6lu !p1K-gfGBHl碣G@6:[}&บU7B'GT3F ]ꚥ}1ڥXI$.3X sYZhzl{{P  X_K} Mqfe.6-=7\xM}&s䵺6VDܻDT*Oq-!oeleп1Js?.%GBESgs Bٞ n d89bTWn`8[xNr2%!i[9H ([X&ʇBiOʤcz] &{a:iW;êR*{dn N‰_<+S@gȍ t8Am˼/y}|1;<睻>]xN+fK5CuMeV[B0l0*+ 8r'3OӖKy LQ^ys-<;+fD#fB p 39\$.y-."]X;ʍT#!81I]˧kmDDA'A88@Moguyi̲H[b裹׵vfK\ befI ">fУSBr7 ęb4rR7!b2s\_܆c u%wcjwp; 2,Xg+ܱk[u7j#FVvIy }. Nzrvɥ[XrVJCJ#/1|pA4WraLle[ TՓXΎTF\pH>f $&rCp{X[r&I$#l`SW%k4o>RH G< .-6ډē,#Nej^ IinT#%VAH;N1c@{4Y oBn:st!mLx~ΝLse@P?)T JwsjRi#0z$ u1¿k9ڈ$ d``zTNw:ǥn{9RxY$b$V)PIPOXi # yI2T~b5Z61-RSەVU,5KJ]~k,2 9RLr|kF[+O,8"nNUמ"k)Vx&T9ۜrHk=oh7.s+חޥ+NreDmŜn( gEu%ң#h]:ayr͜ (R_!>[~}Qymz99|Q;(ѧ<˞|DfSg.ysgEhq$q };~: :#pc}]v?5'"*(8Š(7ٺ7{Yy+lu烑ީTqA5W7fyea-I嶎N8h޿OƯo)oJ2:qxۿxnmR.L^ϙ/gn+X|Iw](_qu=J#mTŽZDaa!wGII$GWc mCKwx¬@@6g 5Zjz$v6s䘀 G_省qh1ћVF6G {ߕQ{Hm͇YP\p}9jнGn!)v^"`R,8v*H#rM5 N(Єxr7` Y F·Zufezc$ܶګxkQM P!t4rk2Av,iLwCn ۸P;sYu{vGi'16FF*OAtt;KKNc$Ry#K*Bb*X*mB; oIọ>Wi5FA<$BiglTRӸyNq8׿V%ޣ"KY\BfK&-Ch@fLnu=t9m%(f' >Qrci84v=}k뗖ȩWk[i#UBYy0't&Yl%K3hA;!98pwLH/nh8WM/ (T~p kZe[^])ed6w` \g -*hbX."#k5hIc ǍŘymZyh㙣to*8&t +8^iFWh!cf8!,c,QMճ4Fⱨ<%>_h0kjׯRomrUp$x\5X@t;RӦ#aB=0!A #jg粷_2HGo,(C³|8j/KjgA{uur, ɺT (|Õ c`|VZҵnO7Ω?xNsiM-ïeQ6$PT2NI$A\4N-QP*ȉ9~0UTB:TN}aIw|SdpHY1:\yĞRDȹ$~PC/$)#5{C-Lʚs!6(䁑#3_HHKs]./<ܸѐC>lb믪_][%W*~ ~M1y9A\/bAdpw<[ N4>)nnL) ijBȫܾࠜg.GXե7=@p{ӶO&9I4+8n0]ZkbDQ+W}#XўYjPc@7g* @YeV-r ' g7`VmN9uRљ W#X/O<XL]I-u:acV`@8]pd1,Ӵcy@#Ԅ`Q,s} [d\JF׌(Ww99)iE=Ȑ\67}FB <8p YOiYE܄ ccq] pA9ݗ6cIh"D!<܍1Lr䝙nX. Z ErgJ,|b|˅#V\*^GtfYhR)-)|'[U@<德'c%26Om*"{=P8#ʄW2cBrFJh{wk14׶|ۆTIٰ ņ8 3"D+1aU=I8z*[15in߻8+m< /'boGu[^C}49<}r>_N4in%>Fr'9~Q<˞|ZbxtN߇8N.oν|Hv=1Ǣt>AusFuH(0(,RkȡB8& ?j[\nϑ?Ka(#s=3@ZJ͏iex;˸a Jm7dİ꒾YaC\y :>ⶊP1݋c@' k_f\,30a(GUv;u7VӬ[JȐ<~^r[$(g+|3O8/m }F ҆z!'#$rF:^ZLz%T6q"*ݺX}MJkKy-o#qmdXXu5;MC[q-DiL) =ր! 8&S&Q{Fέ|'߽6H-4Kܬ3mmѧ!vDёA˫Kya#Ԃk2z\', |,W끂NJP &"Ujh/p\Kjw.쁁 0sO_R;[JĠ"7 `wץhul57)c_%AwCӒ@$Ull~]#l$2'*]Yk !r׺wIt6-ث󀭷]]_.ܒMr]ьU-_J#]I%߽kl%1>w!9Ӳ_\:Y"ZcdFYqÝ4r*MM$+,X ђAG^Nø#5Rw㵸0Dbu[, br\ƅhfhډ"\:0 *TܵE=6XdRdmx6YX~SpEv͑1Bb. ڍP Ύ˫H̺yW*`D˓G aZ5+w4Ǿ*60$8GClE56 ܑnCdu, Y0[y ’A 5q[E6hVPd]*6v$֨ ߈hzF[8$p#*kWJ^["?7F|b (8bKbW΋2ǻnԍaa`/rjZf UrxvIN! p.^_iIg 4oA,۲_d~Lz֚ėn̏MM*xFkEAX61Utaln QH0d̒J o7Po>4.m"HӤ bwg.Ł`8siɬɩL%](Ҭ0"EVLUUð^w=ki9M_1Dh F \֮Z&Ťy2ɑ@y< ۶ doQ#V^S|FmF* CR[+"'6Ff7?>muvR8iȸ.LS6Cgsv’@k&G-,Ȁ6Ee 7`erx+!wgAhc T H 3XSI ÓuB6Nig}?ܱ ,63c 1⟨qr-`dpݸ'hQv޼P# pfg)Hf9!sKΟ''AT#dUMe!:uDCK bK0=r8&v7vѴQEH  pB`[#qiKye.{gk+==oGn]͟Obv`pܾ;O`d Usbݑ-ږ*G+"Ym  &N,nm#n L[8`Y~`0MhڅrA eDĬ>`\ I$ Z ]fĈd n#9;5u5k;{)9rdIc]=8ے[u[ndcnnlR gPH#mX< b()nV %jW*3[4=iڽͅΗ@cF,+6v*9 k[i3$0*2dw( "0x&y:ʖ`~Vq (KP"k X6 QSsyWUѴi5 n6mJdmyr~w iI϶4Z1imbѨeB8G&.K1kUk{q\s8=ߡ!5ڦ]J//4@& 2I(UsVwN}#Rm.-eY;Y%J%5)Uϗ (Y!@F= 񭍖[^[Jn C;6 *?80in'yyeřIIVscyV{iE; [QEW|/M-}?y>\Nsr?hx3q)3<9?388>Lq]ѿzO1zcD|>?y;QZaEPEPQiU7\C{JYUo gѴX $% t>[c l]/ǧMF,ex`QrnOBM_𶑬i:w]DR]&2FaMimi-Z!J<sOf,9QTb̸85 }dF8bb'?. `psZT+{$MY ;DdVX0lm&Sa⾖,5qnSwcr[9Lt{ۈmfF*[nҸl\zנx:e%[-&¨N̓pU-:K]m2hVqp`grm`r2 x|E$ʦ۫v+pB$pq2(T^UYBŒwy8pi`J}.G-]ţ$6đ%¬+L3T)<f\hVY+xdl+wa0 ޝOZj˧[o= my7TgHF ' I G9VK}ɧgĠ^FQm+fJI3:lg n]29 l$uWXw\#vvA)\1 nWN|;$q4K!U+|c"4/tt9c[lw i&^*X !ZEsL S\FɁĐ\* lbWqxFv[c@KmH]3 G^VCLj--L#̚_1eg0dHdQ5-GPqa1A#\(7jݝʦ 4y;.%n x.O8OK]Lzi>8+cdeUX^Jf EϔL{XH :]ܺlh졔 0)(Ĝɜsk3MsYI]BWw%55)l4q9 w(g=\qk̭ .񸢰3B @'n\yÂIRFGݘ_ا]fΚ/-tIv&8#Qp9y]C^ M]ir:]bqU';<،s:T~Ϩ3, 4 dۃc9X׵ mڔ&ͻ$WG/T>ܙө Y2I}(gg )-g0 O9;6sIR7Cd\G'h\3*/sOyGOn%>Fr'9~V;G>ӷ= 7_8>Lq]ѿg/>Gcs_"+C((+I1zʣkB# @N=:ijVxۯppv0~Ti8}2㲏:B̌>U9,)!);(VVk&." Y}!nU / JYIl%%ฉ[@ BrWfn'k iIlv\m߷O|>Rk[p63hf9f uz%©LSHH(d(W F8uh[>)&m̓H>ۆ acs46k+ LQMegnp S6 }j^ KQ`UhU ;vrljڝʿ0'8ʞ0x+b#!|&y YI;߆ 2=Ν:ۘIOv(y8d2"ZK0D1';vb{ Aɠ =GkV; s[sZ˭hZi\;Ry$3Yx~ izEea<KٸUvלtW+iv6R),L7bB{PxWOi}8W,4j;d`P .x85j:~ nėfie(VV&w@`0&<;nt ` c ==+^-Bjŏ'L]u҆xCu#=@ r~俿J,TO|ܢzɵFK'fB u bXq D` GP,53 ҄  Ilݳ,p7_3Ru6w@#s9f FA Y 7Qv29\ Iq}KUY],|ah"<(!X ߑz~>[ϑi‘A@so% 6@f /fT`am&»2`x˴M B4`5FQ@ݷ錃NJȱGJUC & ,Jp5t{m1}(Imq唰 H`7wq>ɖ&ecq\J?*nzÎF1mƃnsO~@[".|s/c * P7w m9`mS,B'{zɥOK[yl)~h+7==P,Lx ';-:Z],M/6v;ܱ6Z&r^j` v`|- //㘄 }ÕwgE}z]Nho-gٝySp̜۴.6qؗC[K[nayB㌑iŮ4n(MC g'2%Κ4Qs!X޻^b61BdWI%RǒIl=O9gv2)yĻatc`c,APpw DQOd!6&w\mpXPHݳXE lm$F4xbۈi3 ޙz%OQ&I!91Fy5 SWKKdGY.b9a,c X‚6p8" s/&+9΁h 02 *0U/mւ)6c co[i-:ɍ8Sn;w soaqAs `;\Xp7n9$x@BՑ'L׭vArH.|6Čm'/s饱ϧ!FrvP_ENx3q)3<9?3ħ\<#֊|Hv=1Ǣt>AusFu;G>ӷ= 7kODTQEhqQ@urVy$57KGG*,i\,0v: {5qY-p02O_;VvRCNM$2 \!b$ sPiZE3$=r9㞵iRigԌk>YJ)F2vs9'o#ĺ|6SY(Y|U86(oޠv:|i,GC sL>r70<QQnª.V];o$"ϼØ,f@@ 8թ`mAX6֋v91_;p۶ Aiyyqݸdk'j728g*0~ẹ6o/fg"KЩaca9!{y mlnt==cJf7M(q6/$nu䱸[Uf3AZ6ip1c'ngXçJAcdme+'$Bx/z?*0bkf>II\Nzs0?Zq;YwSLRʎrI?8 񊱧kv:Pӛ[cuq{v8; ~\rk3^+6LH0 d9W,{ ]NPYԳ<;*Im[ eIj=̒in6fmv8=ᑜR嶏-}RGUrst&*Z?e 3u9_\vx Q3KRt9\l`܊v(#I%t[0kveXpWgoK mnYNYFVFc!Fq`^ RM)um:+kC1hWv~V >H.?o*げ3f?44),d~팈׀8j槡jV֖«2r~fVe==Q* ɌrXl5e{DxFq !nH.Vv$D qpg88xqAƒY;i#&L;$9ڃ1@gӴ%wm.c$2F\&c .2$rѯn!ɹT+jKlmy^Xу#XZV+%̮-;mۇ.û0dlwwKf`.!FۼXD;w{@,I#Ļ# Ą\$IUY'MNasm )dʃpJo6o Th.+DBɴw PEP^C}49<}r>/s饱ϧ!FrvP_ENx3q)3<9?3ħ\<#֊|Hv=1Ǣt>AusFu;G>ӷ= 7kODTQEhqQ@Q@Q@vn-%PO<.9|~)on|d$P$'UF(DvdZBQUL$ `=3%ݾjc2%"T,Np(=sdY琖I6B1,\ΘjVfmգp 2(#bQX%VkUbfPC}G@-[k.$ie2`Fr@G9k.]Ȱr&ՁT)|.ޠi=|HʬR%LdBwJngu5X,uoK\[[I6ܴJO `p~ZgE;L$X `I\pJego&VCbisp}#>":ݬqwD^Y]1rp>\åYaK\}FpqPsG@ =>M?PƏ K0^[j0gicAL4ۙ&O[)vlCC\0! U!ѯgI!B$%Ão-bե9D7V;ɖHۋ66ǖUe_Nt:a"mBiZ8#YRP,yy/XSB!ichIQI`.xC[K]Z ;&iӢEEx5RAtnAua|?|V֓n䴔A<#r Iw:c~P0H(x{X><"Q$w\m-QO|Imn-M?G\uu4(n| 2$R^kwZuơi=ܓ&)$`!m`z7&-$tŔC[tb[]3@tleg |K!FLͿ$ lEnڂY\I)0)%vA>}2ƶQ${}KȤ+0! dt_1 11$e8Zn3PGrY;d߂F+\mj ljZo&Lory߅kũicVEiagvAyl̶-rof[ O6m$*ۑW NVi1ie3`v]w} 6omk#ߞ=yyFyݱ<;wkY%6)NC9ⶼuu]\jw UnLq0rr~R:ƾѢcŧiyՄ{>a)#y@.Du_Y ؊HZ`K{#kJQgt˛`[-$#33Œ.sIq,7P@n3t'AA$ET-ck,+o1s(8&jp^ܤVIau#*FsKm9 92j6s3Z1G4r19l /C,05aXw"M\k?c&c|H$cfKWRI22!CpIFR9` b{7lEip-m"@'˰m8l/4ءTKlcd' |J{+۶ӖvMə$pYFsjZ^ᮮͭ14eL,RpG/9=Ic33=B&.[bNY#jBHӤ4fiHnBAt!BwxċD[1=Ibk>/m:[)uf{8 +KŚZ|6ѵmdkb3IcҸ ߐqkn6*u@ 8EEV:ơ!*$ި1mP9ɢ&y1;G@OSp(((Kilsy}GQ_ 8KcOCϷ#:D FfSg.ysgEOyG'O1zcD|>wĎ:}oz'C_7toYϑ䈨 ( ( (4仂HkG%%W* e\ f̢?4MCT46bób?q!scVm.4NJ r\r'%IRWO[K?}*8aMPܞ(-R F]´jR f$%&bHVdErTPS[imcmγ2,f ;NAxoŧZSV2*.2O?,p{隀X7X~~xlP{@pp0by>qn1aj$1>309=[ZXOٝ+=HF0 7iSOfK764b32 ?L`Ե]ye7S~cC"+X#y b6W:,{Lb[SqÁ &y8<{ r̫&!S I/¶ Na,j~l#c@T6K8۴(kچ]Yg}.*&5` sx4_*JVhH=ʍ26Ho>֧ama.СP)݃Ǒu.o=m#H%3 N, `R?{VquȿIwHR@@`IzkMYӵKK: r ތ n ! 9',i 4` 2t6tu}*-hmVkuH6]mP2ډtR.d,r}I8Q>B2- .{ѦKPUYBi np2sfa$~Uw tnC֧ r?Fpr+b84ti,u;&W;PG* pU{dRS]\آy wa@8s@+Y˥msmxЌ%ênpl5HI$yۜf<Žw]%!/u{-z}ˣyk{auvY96€QλϤ2,*qp*m2.Or=0:H-; K.'6e`9SܑVaz4wIpVлr;_!y1j֐A|uHB'F s4ZS[hm^H$pW#I!nK[lbT۸ NqHl,ou[M<2|D2 ̪s 8N졒MJNU|7zyH825Lz,#/<3 ˔|xQ'4oh#'w߆^Harm``B 8O*ғX{I+XG0}X8ȏC@!?طv]ıEq{=aL9ٌm ɍîf3Him(dnř& 2PjGc2(E 7Á$ n<9 oSuGd7]%%BH ㌂0@ 7.uKN۶q"$XUIsf-[_؏i8FcP3@Q@Q@Q@Q@Q@z9kԾqϦ>oGuC}9ħ\<#֊'7#9sϓ\?Z+CO#pc}]ׯtN߇8N.oγ#?QEQEQEQEeh'dZ6 u$G4(]j+qtcX$$۝vf=PEPKXjq[]XH9mױč$=Zf%`# ϝ@._Cu+f{w#^XکKL" sf2ʍp6F[>a$p@;+㳃RRV1g RՑLWp{;CN og+彵Ƈ XA'y1>:v~sAho #K 겾H%Z2r6|,0j-rU[k+mp"ue x32noZ6ˏ7;ԼKՊ䷗To K=فRspqBej- demyZ]j >ݢfHwdFB z]%wO1d1VToy'P;pCjV pP0>P'I53-퀷5Mr6FnYYp NRC9[vcrf*ĩv 03=1OLֶ%H7*@󺤚։˪S[63@ R6:Ē^jInRT?7_N>~<ږii "yu}9ہ/{W "m/֟noͤ 98W^Yܧqo#E*ddpy_bf'ϗݷqh((((((Kilsy}GQ_ 8KcOCϷ#:D FfSg.ysgEOyG'O1zcD|>wĎ:}oz'C_7toYϑ䈨 ( ( ( ( ( ( ( )-o,0D3I5mc I+2? *@qY:dεηn鹗FTiPJ; !j,~`ԾeX7˜Ѓު4<wĎ:}oz'C_7toYϑ䈨 ( ( ( ( ( ( (&{;d2nea `H8#kUAos]F[ۖ0A hzōܯC ζl*3hڦΰA?$eR9a$grd*qwm{]CJDէϹMቡ-v0e!e'8?cxHKR˥fLH! Be':ZiB[ngy,c)y _q'""5=6}9+-X F88qR0WCSͺ3RtFy\$D\zl;{梶~|>!e7Ta9BpsY6 mo)oo.?kYQyp<- ndaIT́p89Z5yMi/ xU''J0[Zi$D e_h=9AkSU,nYEFz?7gh Kp> Ƅ~s^{qVeVƙ-G$FBΟ"*HޜtRmECn#BcN.GlMo0tyQ;.Aag#V۞(opͩEkC ෙNI9.v7w{Z{ѹV<ͱ.JЀgj s {x0:H v.6(m#n293~ oSKYyndY 99 QfOapIǚoU ,Km-ƫ S$v,*Lq9WckT%'naˋ{V(£(}w,2:]Wߍ]jWZd Dfŏ'41wĎ:}oz'C_7toYϑ䈨 ( ( ( ( ( ( ( ( |ڄ/\iS͔W=\-jvbK9A6V-$> ,YIQm˞;56keqwu Aޘ|.0OC8ػOk=:oo - Wbt 7J@S#0/eXmR0\N(#ྷg94`lBT`OHvc獬grq >S.M`͎ޜuZ :x[[[53( >c#0#G4i <',H봒Tc݅ZNiN,?3Me:TvFP ;rv@ WYX%*ݷ 8 S[ZOp әwu.9r rkSumq0Ҿvܜש4e-Ưd$a3A% X`Lx'.$j:mpŐ.xq^n21uum-&3 l` ln28+z#C}ͽPM3cTw[=H|oP\1zYQ@Q@Q@Q@Q@Q@Q@Q@Q@z9kԾqϦ>oGuC}9ħ\<#֊'7#9sϓ\?Z+CO#pc}]ׯtN߇8N.oγ#?QEQEQEQEQEQEQEQEQE̎) I]4ǖVg,H&i1(y_hb{J[xfm鲼l6y+%0*%˓&KėzsǩYf1r_kw#-h^sVM\~vvP<܀  @9f,Swmx,\JޘC{{i{LHlW%~_l[\@2I89$0s7VN'-m&h3(!@= 5j!ĆTRʆ2og: @/Y6y2̷[; G϶,v sj[2^ŦQ$*倊/s饱ϧ!FrvP_ENx3q)3<9?3ħ\<#֊|Hv=1Ǣt>AusFu;G>ӷ= 7kODTQEhqQ@Q@Q@Q@Q@Q@Q@Q@Y׶\}U}'98ukj oif]NAL;aՉw8I¢ (:O^+Tg,ڰ[A8^§%YZHVUG;PHFzaO\l_B:Ie Mj-!\$R? :V׈=m bw% ڥŲrg9nK)lo,+,;~Jlo_e{$E 903Ѹ$v< 湱K-ow~pXFILlͿ oUoRLWq=H(UQڀ.xN]?T&+w_:_;Gw͔uxpNVM>Y#Uv$PG=@2 ( ( ( ( ( ( ( ( ( /s饱ϧ!Gש|/M-}?y>\3*/sOyGOn%>Fr'9~V;G>ӷ= 7_8>Lq]ѿg/>Gcs_"+C((((((((((+CFNyZwI ƽ{e}YPEPEPEPEPEPEPEPEPEPEPEPEP^C}49<}r>/s饱ϧ!FrvP_ENx3q)3<9?3ħ\<#֊|Hv=1Ǣt>AusFu6KK3S#~C g/Cw_7toYϑ䈨 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( /s饱ϧ!Gר1&͛Ɣw2I=Nk9|Q;(ѩ<˞|Zy݋]Xb'4V$q };~: :#pc}]v?5'"*(8Š(((((((((((((((((((((((Kilsy}GQ_ 8KcOCϷ#:D FfSg.ysgEOyG[^M!aP X` |:D;%zZ{7}* ]qa\c#|F9EAF~C1(&tJ9M^OÍhg:s{'>t211OO}*|s>ӯlX|LSLK+/O{5v_ ~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#UkTn}=?3:{{kH(~kC9sxs-??8ֆs7Z#Io2h-/m1k|"X Go&?3:{{kH(~kC9sxs-??մMf{khT# aXӯC}_oq|N9ROHg7#9sϓ\?Z+I#9,I?*V!mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/doc/__init__.py0000644000175000017500000000000010522754517022541 0ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/source.list0000644000175000017500000000161107262424345022071 0ustar debiandebian# # $Header: /opt/cvs/python/packages/share1.5/DejaVu/source.list,v 1.1.1.1 2001/04/03 19:47:49 gillet Exp $ # # $Id # SOURCE =./Viewer.py ./ViewerGUI.py ./Camera.py ./Light.py ./Clip.py \ ./Materials.py ./ColorChooser.py ./ColorWheel.py \ ./PropertyEditor.py ./extendedSlider.py \ ./colorTool.py ./EventHandler.py ./Texture.py ./spline.py \ ./povray3.py ./bitPatterns.py GEOMS = ./Geom.py ./Transformable.py ./Displayable.py ./IndexedPolygons.py \ ./IndexedPolylines.py ./Polylines.py ./Spheres.py ./Cylinders.py \ ./Labels.py ./quad_strip.py ./triangle_strip.py ./Arcs3D.py \ ./Points.py ./Box.py ./GleObjects.py MISC = ./datamodel.py ./Slider.py ./viewerFns.py ./viewerConst.py \ ./jitter.py ./Trackball.py # Measure.py follow.py ALL = $(SOURCE) $(GEOMS) $(MISC) mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/0000755000175000017500000000000012146207755021336 5ustar debiandebianmgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/AddSelMask.xbm0000644000175000017500000000131611446761523024017 0ustar debiandebian#define im_width 32 #define im_height 32 static char im_bits[] = { 0x03,0x00,0x00,0x00,0x0f,0x00,0xf8,0x7f,0x3f,0x00,0xf8,0x7f,0x7f,0x00,0xf8, 0x7f,0xff,0x00,0xf8,0x7f,0xfe,0x01,0xf8,0x7f,0xfe,0x07,0xf8,0x7f,0xfe,0x0f, 0xf8,0x7f,0xfe,0x1f,0xfc,0x7f,0xfc,0x7f,0xfc,0x7f,0xfc,0xff,0xfd,0x7f,0xfc, 0xff,0xff,0x7f,0xfc,0xdf,0xff,0x7f,0xf8,0xff,0x07,0x00,0xf8,0xff,0x03,0x00, 0xf8,0xff,0xff,0xff,0xf8,0xff,0xfe,0xff,0xf0,0xff,0xff,0xff,0xf0,0xff,0x01, 0xe0,0xf0,0xff,0x03,0xe0,0xe0,0xff,0x07,0xe0,0xe0,0xfb,0x07,0xe0,0x00,0xf8, 0x0f,0xe0,0x00,0xf0,0x07,0xe0,0x00,0xe0,0x03,0xe0,0x00,0xe0,0x01,0xe0,0x00, 0xc0,0x01,0xe0,0x00,0xc0,0x01,0xe0,0x00,0xc0,0x01,0xe0,0x00,0xc0,0xff,0xff, 0x00,0xc0,0xbf,0xff,0x00,0xc0,0xff,0xff }; mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/Ztrans.xbm0000644000175000017500000000137011446772172023332 0ustar debiandebian#define im_width 32 #define im_height 32 #define hand_x_hot 0 #define hand_y_hot 0 static char im_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x40,0x02,0x00,0x00,0xb4,0x02,0x00,0x00,0x15,0x02,0x00,0x40,0x57,0x03,0x00, 0x80,0x0a,0x01,0x00,0x00,0x44,0x01,0x00,0x00,0x12,0x01,0x00,0x02,0x41,0x01, 0x00,0x84,0x8a,0x01,0x00,0x42,0x9c,0x00,0x00,0x2d,0xb6,0x00,0x00,0x8a,0xe3, 0x00,0x00,0x55,0x01,0x00,0x00,0x06,0x07,0x00,0x00,0x91,0x04,0xff,0x80,0x05, 0x06,0x81,0x00,0xc0,0x03,0x9f,0x80,0x7c,0x00,0xcc,0x80,0x07,0x00,0x64,0x00, 0x00,0x00,0x26,0x00,0x00,0x00,0x33,0x00,0x00,0x00,0xf9,0x00,0x00,0x00,0x81, 0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00 }; mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/AddSel.cur0000644000175000017500000001027611446772172023215 0ustar debiandebian ( @ ,+ /,++-, *)˙1/.--,CA*)2053<:fe97,*H/-5353hg醅:9.-I.-;31,+ +*ި4253RP炁lkBAe20!4297.-۔.-f0.+*2053?={z߀:9VU.-{A>D@@=64,+܊-+5364mk愃PU/-EAA>>::7634253WV烁LKIH41/$64B??;;8745353CA~}WVGFP/-s>;@=<985535375qoꈇ]\CBu-,A>=:96635353\[脃푐~>=lk1/31>;:7645353GE~썌ԗFE/-U85<985535397usꉇsrUT!5353U538,*<996535353b`腃ⰰGFgf53U5353.,:7645353KJ恀쎍՞GFzy53U5353.,*20745353;9xwꊈIHww5353U53U535353ƛ53U53U538,*l52535353ge醄^]WVV53U5353535353535353+)635353PO炀쏎FEԪba)538535353ƛ5353535353q-,,+5353><{z닉zy@?ji 53U5353-+)/-5353kj釅蘗RQNMZ53U5353,*b2053UT烁퐏{z?>ê[Z 5385353q~+*42A@}|䆄SRDCv^]+*ǜ75pnjh:9ɧQP),+OMDC;:nRQ{*)/-<:DD?????>?>?~?????mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/Ztrans.cur0000644000175000017500000001027611446772172023342 0ustar debiandebian ( @ UqUUUUU-++*׀+*+),*i-+4.,q876ͰKI5342200..,,*,+v/-(q898}|KI53535364969641,*:9}|KI535353649675+*EDZtsꈇ}|KI5353420.+*0.RQ%cbꈇ}|KI53/.+*MLꈇ}|KI42-+-,=>=풑[ZwvKI42,+-,</-+*+*ML_ԍml@?y>=wuKI42,+-,=+)7442/-.]\cbؑ=<IH"=<;^]GF!==wvKI53535364.-/-=GCGCGCGC@=/-2031FBFBFBFBFBFB2042,+?;-+z,*976463@=@=646397+*-+*)+*׉,*\-+Q1//-+<9<9.,20)-+O,+V+*׃+)-,-+*).,6331+*R,*8585,++*X4153.,*)-,-++*l,+315353/--,*+*ϲ5353,*-+40.535331,++*f-,/.!~+)Ŕ1/535353530.-+-+-+.-5353/--+-+-+0/535353530/~*)0//.,*425353535353535353535353535353535353535353535331,+200.21getrtrtrtrtrtrtrtrtrtrtrtrtrtrtrtrtrtrtrtrtrtrdb10͇21>=53\[臆ꈇꈇꈇXW>==;>=FEꈇꈇLK@?<;=<Ķ\[ꈇꈇꈇ膅ZY65@? FEK@?yxihQP6?>EDKJ@mlxw@?ڞHGEWVA@tKJֆЁ@?VCBIH=<\҄ՆLKCBq[Z[Z >=q76@?]A@^VU@EDML\[:A@[@?X76>=q]\ >=ٛɉńdžƆי;;@?汰ߨEDvhgdc]\srNM㵴߯RQyrq SRTSzy YXVȒǏ^]QFEGFpoIHӒKJױsrag ??00?00??mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/MinusSel.xbm0000644000175000017500000000137011446761523023606 0ustar debiandebian#define im_width 32 #define im_height 32 #define hand_x_hot 0 #define hand_y_hot 0 static char im_bits[] = { 0x03,0x00,0x00,0x00,0x0d,0x00,0xf8,0x7f,0x31,0x00,0x08,0x40,0x49,0x00,0x08, 0x40,0xa3,0x00,0x08,0x40,0x22,0x01,0x08,0x40,0xc2,0x06,0xe8,0x5f,0x42,0x0d, 0xe8,0x5f,0x86,0x16,0x0c,0x40,0x84,0x6a,0x0c,0x40,0x04,0x9d,0x0d,0x40,0x04, 0xf4,0x0e,0x40,0x0c,0x6a,0xff,0x7f,0x08,0xd4,0x05,0x00,0x08,0xd8,0x02,0x00, 0x08,0x60,0xff,0xff,0x18,0xb0,0x62,0x8c,0x10,0x90,0xfe,0xbf,0x10,0x40,0x01, 0xa0,0x30,0x80,0x02,0xe0,0x20,0x0e,0x05,0xe0,0xe0,0x0b,0x05,0xa0,0x00,0x18, 0x0a,0xa0,0x00,0x30,0x04,0xa0,0x00,0x20,0x02,0xe0,0x00,0x60,0x01,0xe0,0x00, 0xc0,0x01,0xa0,0x00,0xc0,0x01,0xa0,0x00,0x40,0x01,0xa0,0x00,0x40,0xff,0xff, 0x00,0x40,0x23,0x8c,0x00,0xc0,0xff,0xff }; mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/ZtransMask.xbm0000644000175000017500000000131611446772172024146 0ustar debiandebian#define im_width 32 #define im_height 32 static char im_bits[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x01,0x00,0x00, 0xfc,0x03,0x00,0x00,0xff,0x03,0x00,0xc0,0xff,0x03,0x00,0xc0,0xff,0x03,0x00, 0x80,0xff,0x01,0x00,0x00,0xfe,0x01,0x00,0x07,0xff,0x01,0x00,0x8f,0xff,0x01, 0x00,0xdf,0xff,0x01,0x80,0xef,0xff,0x00,0x80,0xff,0xf7,0x00,0x80,0xff,0xe3, 0x00,0x80,0xff,0x01,0x00,0xc0,0xff,0x07,0x00,0xc0,0xff,0x07,0xff,0xc0,0xff, 0x07,0xff,0xc0,0xff,0x03,0xff,0xc0,0x7f,0x00,0xfc,0x80,0x07,0x00,0x7c,0x00, 0x00,0x00,0x3e,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0xff, 0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00 }; mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/NoAction.cur0000644000175000017500000001027611446772172023573 0ustar debiandebian ( @ !!b!!b !!b !!b!!b!!b-!!cu""e""g!!n""m""g""e!!cu!!b,!!b!!b!!b;""e ""e!!b|x`@>|??mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/MinusSelMask.xbm0000644000175000017500000000131611446761523024422 0ustar debiandebian#define im_width 32 #define im_height 32 static char im_bits[] = { 0x03,0x00,0x00,0x00,0x0f,0x00,0xf8,0x7f,0x3f,0x00,0xf8,0x7f,0x7f,0x00,0xf8, 0x7f,0xff,0x00,0xf8,0x7f,0xfe,0x01,0xf8,0x7f,0xfe,0x07,0xf8,0x7f,0xfe,0x0f, 0xf8,0x7f,0xfe,0x1f,0xfc,0x7f,0xfc,0x7f,0xfc,0x7f,0xfc,0xff,0xfd,0x7f,0xfc, 0xff,0xff,0x7f,0xfc,0xff,0xff,0x7f,0xf8,0xff,0x07,0x00,0xf8,0xff,0x03,0x00, 0xf8,0xff,0xff,0xff,0xf8,0xff,0xfe,0xff,0xf0,0xff,0xff,0xff,0xf0,0xff,0x01, 0xe0,0xf0,0xff,0x03,0xe0,0xe0,0xff,0x07,0xe0,0xe0,0xfb,0x07,0xe0,0x00,0xf8, 0x0f,0xe0,0x00,0xf0,0x07,0xe0,0x00,0xe0,0x03,0xe0,0x00,0xe0,0x01,0xe0,0x00, 0xc0,0x01,0xe0,0x00,0xc0,0x01,0xe0,0x00,0xc0,0x01,0xe0,0x00,0xc0,0xff,0xff, 0x00,0xc0,0xbf,0xff,0x00,0xc0,0xff,0xff }; mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/AddSel.xbm0000644000175000017500000000137011446761523023203 0ustar debiandebian#define im_width 32 #define im_height 32 #define hand_x_hot 0 #define hand_y_hot 0 static char im_bits[] = { 0x03,0x00,0x00,0x00,0x0d,0x00,0xf8,0x7f,0x31,0x00,0x08,0x40,0x49,0x00,0x08, 0x43,0xa3,0x00,0x08,0x43,0x22,0x01,0x08,0x43,0xc2,0x06,0xe8,0x5f,0x42,0x0d, 0xe8,0x5f,0x86,0x16,0x0c,0x43,0x84,0x6a,0x0c,0x43,0x04,0x9d,0x0d,0x43,0x04, 0xf4,0x0e,0x40,0x0c,0x4a,0xff,0x7f,0x08,0xd4,0x05,0x00,0x08,0xd8,0x02,0x00, 0x08,0x60,0xff,0xff,0x18,0xb0,0x62,0x8c,0x10,0x90,0xfe,0xbf,0x10,0x40,0x01, 0xa0,0x30,0x80,0x02,0xe0,0x20,0x0e,0x05,0xe0,0xe0,0x0b,0x05,0xa0,0x00,0x18, 0x0a,0xa0,0x00,0x30,0x04,0xa0,0x00,0x20,0x02,0xe0,0x00,0x60,0x01,0xe0,0x00, 0xc0,0x01,0xa0,0x00,0xc0,0x01,0xa0,0x00,0x40,0x01,0xa0,0x00,0x40,0xff,0xff, 0x00,0x40,0x23,0x8c,0x00,0xc0,0xff,0xff }; mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/Cursors/MinusSel.cur0000644000175000017500000001027611446772172023620 0ustar debiandebian ( @ ,+ /,++-, *)˙1/.--,CA*)2053<:fe97,*H/-5353hg醅:9.-I.-;31,+ +*ި4253RP炁lkBAe20!4297.-۔.-f0.+*2053?={z߀:9VU.-{A>D@@=64,+܊-+5364mk愃PU/-EAA>>::7634253WV烁LKIH41/$64B??;;8745353CA~}WVGFP/-s>;@=<985535375qoꈇ]\CBu-,A>=:96635353\[脃푐~>=lk1/31>;:7645353GE~썌ԗFE/-U85<985535397usꉇsrUT!,*<996535353b`腃ⰰGFgf.,:7645353KJ恀쎍՞GFzy.,*20745353;9xwꊈIHww,*l52535353ge醄^]WVV53U53535353+)635353PO炀쏎FEԪba)53U53535353-,,+5353><{z닉zy@?ji -+)/-5353kj釅蘗RQNMZ,*b2053UT烁퐏{z?>ê[Z ~+*42A@}|䆄SRDCv^]+*ǜ75pnjh:9ɧQP),+OMDC;:nRQ{*)/-<:DD????????mgltools-dejavu-1.5.7~rc1~cvs.20130519/DejaVu/EventHandler.py0000644000175000017500000001274107656517277022651 0ustar debiandebian############################################################################# # # Author: Michel F. SANNER # # Copyright: M. Sanner TSRI 2000 # ############################################################################# # # $Header: /opt/cvs/python/packages/share1.5/DejaVu/EventHandler.py,v 1.4 2003/05/08 18:15:27 gillet Exp $ # # $Id: EventHandler.py,v 1.4 2003/05/08 18:15:27 gillet Exp $ # from Tkinter import Frame class EventManager: """Object used to manage callback functions for the events of a Widget Public Methods: ValideEvent(eventType) AddCallback(eventType, callback) SetCallback(func) RemoveCallback(eventType, func) ListBindings(event=None) """ # NOT USED, imstead I simply try to bind to a dummy widget to check if # the given event type is valid # # eventTypes = ('Key', 'KeyPress', 'KeyPress', # 'Button', 'ButtonPress', 'ButtonRelease', # 'Enter', 'Leave', 'Motion') # # eventModifiers = ('Control' 'Shift', 'Lock', # 'Button1', 'B1', 'Button2', 'B2','Button3', 'B3', # 'Button4', 'B4', 'Button5', 'B5', # 'Any', 'Double', 'Triple', # 'Mod1', 'M1', 'Meta', 'M', # 'Mod2', 'M2', 'Alt', # 'Mod3', 'M3', 'Mod4', 'M4', 'Mod5', 'M5' ) # buttonDetails = ( '1', '2', '3' ) # keyDetails = any keysym def __init__(self, widget): # keys are Tk events, values are lists of callback functions self.eventHandlers = {} self.widget = widget # create a dummy frame to try to bind event to check for event validity self.dummyFrame = Frame(widget,width=1, height=1) def DummyCallback(self, event): """dummy function used to check event validity""" pass def ValideEvent(self, eventType): """Check if an event is valide""" try: self.dummyFrame.bind(eventType, self.DummyCallback) except: return 0 return 1 def AddCallback(self, eventType, callback): """Add a callback fuction""" assert type(eventType) == type('string') assert callable(callback) # Here we should also check that callback has exactly 1 argument if not self.ValideEvent(eventType): raise ValueError('%s is not a valide event type' % eventType) if eventType in self.eventHandlers.keys(): self.eventHandlers[eventType].append(callback) else: self.eventHandlers[eventType] = [callback,] self.widget.bind(eventType, callback, '+') def BindFuncList(self,eventType, funcList): """Bind a list of functions to an event""" self.widget.bind(eventType, funcList[0]) for f in funcList[1:]: self.widget.bind(eventType, f, '+') def HasCallback(self, eventType, callback): """Check whether a function is registered as a callback for an event """ assert callable(callback) if self.eventHandlers.has_key(eventType): for f in self.eventHandlers[eventType]: if f==callback: return 1 return 0 def SetCallback(self, eventType, callback): """Set func as the callback or list of callback functions""" assert type(eventType) == type('string') if self.eventHandlers.has_key(eventType): funcList = self.eventHandlers[eventType] else: funcList = None if callable(callback): self.eventHandlers[eventType] = [callback,] self.widget.bind(eventType, callback) elif len(callback)>0: self.eventHandlers[eventType] = callback self.BindFuncList(eventType, callback) else: raise ValueError('First argument has to be a function or a list of\ functions') return funcList def FindFunctionByName(self, funcName, funcList): """find a function with a given name in a list of functions""" for f in funcList: if f.__name__==funcName: return f return None def RemoveCallback(self, eventType, func): """Delete function func from the list of callbacks for eventType""" if not self.eventHandlers.has_key(eventType): return None # raise ValueError('Widget %s has no event %s registered' % \ # self.widget, eventType) if type(func)==type('string'): func = self.FindFunctionByName(func, self.eventHandlers[eventType]) if not func: return try: self.eventHandlers[eventType].remove(func) except: pass if len(self.eventHandlers[eventType])==0: del self.eventHandlers[eventType] self.widget.bind(eventType, self.DummyCallback) else: self.BindFuncList(eventType, self.eventHandlers[eventType]) return func def ListOneBinding(self, key): """List all bindings for one events""" print 'Event', key if self.eventHandlers.has_key(key): for f in self.eventHandlers[key]: print '\t %s' % f.__name__ else: print '\tNone' def ListBindings(self, event=None): """List all bindings for one or all events""" if event is None: for k in self.eventHandlers.keys(): self.ListOneBinding(k) else: self.ListOneBinding(event) class CallbackFunctions: """Base class for objects with callback functions""" def __init__(self): self.callbacks = [] def Callbacks(self): """Call all callback functions, to be implemented by sub class""" pass # for f in self.callbacks: f(self.val) def SetCallback(self, func): """Delete all and set a callback fuction""" assert callable(func) self.callbacks = [func, ] def AddCallback(self, func): """Add a callback fuction""" assert callable(func) self.callbacks.append(func) def RemoveCallback(self, func): """Delete a callback fuction""" self.callbacks.remove(func) def MouseUp(self, event): """Call callbak function for non immediate sliders""" self.Callbacks() mgltools-dejavu-1.5.7~rc1~cvs.20130519/setup.py0000644000175000017500000000721211565034076020232 0ustar debiandebian#!/usr/bin/env python from distutils.core import setup from distutils.command.sdist import sdist from distutils.command.install_data import install_data from glob import glob import os from string import find ######################################################################## # Had to overwrite the prunrefile_list method of sdist to not # remove automatically the RCS/CVS directory from the distribution. ######################################################################## class modified_sdist(sdist): def prune_file_list(self): """ Prune off branches that might slip into the file list as created by 'read_template()', but really don't belong there: * the build tree (typically 'build') * the release tree itself (only an issue if we ran 'sdist previously with --keep-temp, or it aborted) """ build = self.get_finalized_command('build') base_dir = self.distribution.get_fullname() self.filelist.exclude_pattern(None, prefix=build.build_base) self.filelist.exclude_pattern(None, prefix=base_dir) class modified_install_data(install_data): def run(self): install_cmd = self.get_finalized_command('install') self.install_dir = getattr(install_cmd, 'install_lib') return install_data.run(self) ######################################################################## # list of the python packages to be included in this distribution. # sdist doesn't go recursively into subpackages so they need to be # explicitaly listed. # From these packages only the python modules will be taken packages = ['DejaVu', 'DejaVu.gui', 'DejaVu.materialsDef', 'DejaVu.Tests', 'DejaVu.VisionInterface', 'DejaVu.VisionInterface.Tests', 'DejaVu.VisionInterface.Tests.Data', 'DejaVu.scenarioInterface', 'DejaVu.scenarioInterface.Tests', 'DejaVu.Icons'] py_modules = ['DejaVu/Tests/Data/rgb10_map', 'DejaVu/Tests/Data/rgb10_transparent_map', 'DejaVu/Tests/Data/rgb128_map', 'DejaVu/Tests/Data/test_map'] # list of the files that are not python packages but are included in the # distribution and need to be installed at the proper place by distutils. # The list in MANIFEST.in lists is needed for including those files in # the distribution, data_files in setup.py is needed to install them # at the right place. data_files = [] def getDataFiles(file_list, directory, names): fs = [] if find(directory, "Tutorial") >= 0: #do not include Tutorial in data_files return for name in names: ext = os.path.splitext(name)[1] #print directory, name, ext, len(ext) if ext !=".py" and ext !=".pyc": fullname = os.path.join(directory,name) if not os.path.isdir(fullname): fs.append(fullname) if len(fs): file_list.append((directory, fs)) os.path.walk("DejaVu", getDataFiles, data_files) # description of what is going to be included in the distribution and # installed. from version import VERSION setup (name = 'DejaVu', version = VERSION, description = "an OpenGL based 3D geometry viewer python package", author = 'Molecular Graphics Laboratory', author_email = 'sanner@scripps.edu', download_url = 'http://www.scripps.edu/~sanner/software/packager.html', url = 'http://www.scripps.edu/~sanner/software/dejavu/dejavuoverview.html', packages = packages, py_modules = py_modules, data_files = data_files, cmdclass = {'sdist': modified_sdist, 'install_data': modified_install_data }, ) mgltools-dejavu-1.5.7~rc1~cvs.20130519/version.py0000644000175000017500000000002011475262404020543 0ustar debiandebianVERSION="1.5.6" mgltools-dejavu-1.5.7~rc1~cvs.20130519/MANIFEST.in0000644000175000017500000000245411755250751020262 0ustar debiandebian# This list all other things to be done # include, exclude.... which are not described in the setup.py. include MANIFEST.in # list of the non python module to be included in the distribution include DejaVu/cw.ppm #include DejaVu/Tests/Data/* include DejaVu/RELNOTES #include DejaVu/Tutorial/* #include DejaVu/Tutorial/images/* include DejaVu/source.list #include DejaVu/VisionInterface/Tests/Data/* include DejaVu/Cursors/* include DejaVu/Icons/* # include all the CVS directories include DejaVu/CVS/* include DejaVu/gui/CVS/* include DejaVu/materialsDef/CVS/* include DejaVu/Tests/CVS/* include DejaVu/Tests/Data/CVS/* include DejaVu/VisionInterface/CVS/* include DejaVu/VisionInterface/Tests/CVS/* #include DejaVu/Tutorial/CVS/* #include DejaVu/Tutorial/images/CVS/* include DejaVu/VisionInterface/Tests/Data/CVS/* include DejaVu/Cursors/CVS/* include DejaVu/scenarioInterface/CVS/* include DejaVu/Icons/CVS/* include DejaVu/shaders/CVS/* include DejaVu/scenarioInterface/Tests/CVS/* include DejaVu/doc.tar.gz include version.py include DejaVu/LICENSE include DejaVu/shaders/* #exclude files from Tests directories (leaving just empty directories with CVS entries , so the 'setup.py install' command does not fail) exclude DejaVu/Tests/*.py exclude DejaVu/Tests/Data/*.py exclude DejaVu/scenarioInterface/Tests/*.py