""" python/ui/view.py: CCP4MG Molecular Graphics Program Copyright (C) 2001-2008 University of York, CCLRC This library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3, modified in accordance with the provisions of the license to address the requirements of UK law. You should have received a copy of the modified GNU Lesser General Public License along with this library. If not, copies may be downloaded from http://www.ccp4.ac.uk/ccp4license.php This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. """ import pygl_coord from global_definitions import * #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- class CView: #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- names = [] insts = [] #----------------------------------------------------------------------------- def __init__(self,name): #----------------------------------------------------------------------------- self.recentre = 0 self.centring = 'extent' self.names.append(name) self.insts.append(self) self.name = name self.previous = "weight" self.com = [0.0,0.0,0.0] self.origin = [0.0,0.0,0.0] self.continuous_on = 1 self.continuous_mode = 'roll' self.continuous_sleep = 0.005 self.continuous_last_step = 0 self.continuous_last_time = 0 self.continuous_transform = { 'rotate_x' : 0.0, 'rotate_y' : 360.0, 'rotate_z' : 0.0, 'translate_x' : 0.0, 'translate_y' : 0.0, 'translate_z' : 0.0, 'zoom' : 0.0 } self.continuous_rock = { 'fraction' : 0.1, 'nsteps' : 60 } self.continuous_roll = { 'nsteps' : 180 } #------------------------------------------------------------------ def delete(self): #------------------------------------------------------------------ i = self.insts.index(self) self.names.pop(i) self.insts.pop(i) #------------------------------------------------------------------ def set_attribute(self,attribute,value): #------------------------------------------------------------------ if attribute == 'recentre': self.recentre = value elif attribute == 'centring': self.centring = value self.recentre = 1 #------------------------------------------------------------------- def GetMaxDimension(self,selAtoms,nSelAtoms,extent=0): #------------------------------------------------------------------- import time #t1 = time.time() """ Work out how big viewport should be and tell OpenGL. """ import symmetry ext = symmetry.molecule_extents_t(selAtoms,nSelAtoms) left = ext.get_left() right = ext.get_right() top = ext.get_top() bottom = ext.get_bottom() front = ext.get_front() back = ext.get_back() minx = left.get_x() maxx = right.get_x() miny = bottom.get_y() maxy = top.get_y() minz = front.get_z() maxz = back.get_z() xdist = maxx - minx ydist = maxy - miny zdist = maxz - minz if extent: return [ minx, maxx, miny, maxy, minz, maxz] else: dist = max(xdist,ydist,zdist) #t2 = time.time() #print "time to calculate max dim", t2 - t1 return dist #----------------------------------------------------------------------------- def centreModels(self,molobj=[],dispobj=[],recentre=1,resize=1, \ _resize='',**keywords): #----------------------------------------------------------------------------- """ This doesn't work properly yet, but is close ... """ # resize command from GUI requires a resize but not a recentre #print "centreModels",molobj,dispobj,recentre,resize,_resize if _resize: recentre = 0 com = [0.0,0.0,0.0] origin = [0.0,0.0,0.0] nat = 0 glthread = BUILD().glthread # Centre on input specified dispobj or on all currently # visible MolDisp objects if dispobj: d_list = dispobj elif molobj: d_list = [] for m in molobj: d_list.extend(m.get_dispobj(object_type='MolDisp')) else: import dataobj d_list = dataobj.get_dispobj('MolDisp') dispobj_list = [] for d in d_list: #print "centreModels getNofAtoms",d.SelHandle.getNofAtoms() if d.parent.visible and d.visible and d.SelHandle.getNofAtoms() > 0: dispobj_list.append(d) #print "dispobj_list",dispobj_list # Get out now if no visible object if len(dispobj_list) <= 0: glthread.glevent.centre_on(self.origin) return maxsize = 0.0 maxdist = 0.0 # Centre on the midpoint of max/min extent of all objects if self.centring == "extent": extent = [999999.9,999999.9,999999.9,-999999.9,-999999.9,-999999.9] for sel in dispobj_list: for i in range(0,3): if sel.extent[i] < extent[i]: extent[i] = sel.extent[i] for i in range(3,6): if sel.extent[i] > extent[i]: extent[i] = sel.extent[i] # Recentre if recentre: self.com = [0.0,0.0,0.0] self.origin = [] for i in range(0,3): self.origin.append( (extent[i+3] + extent[i])/2.0 ) #print "view self.origin",self.origin if resize: maxextent = 6.0 for i in range(0,3): d = extent[i+3] - extent[i] if d > maxextent: maxextent = d glthread.setmaxviewsize(maxextent/1.8) zoom = 1 else: zoom = 0 glthread.glevent.centre_on(self.origin,radius=60.0,zoom=zoom) else: for sel in dispobj_list: nSelAtoms,selAtoms = sel.SelHandle.getSelIndex() size = self.GetMaxDimension(selAtoms,nSelAtoms) o1cart = pygl_coord.Cartesian(sel.origin[0],sel.origin[1],sel.origin[2]) if size > maxsize: maxsize = size for sel2 in dispobj_list: o2cart = pygl_coord.Cartesian(sel2.origin[0],sel2.origin[1],sel2.origin[2]) dist = (o1cart-o2cart).length() if dist > maxdist: maxdist = dist for i in [0,1,2]: # Find weighted centre for all displayed models. # Possibly broken if self.centring == "weight": if self.previous == "weight": #print sel.com[i], sel.origin[i] com[i] = com[i] + (sel.com[i] * sel.nSelAtoms) origin[i] = origin[i] + (sel.origin[i] * sel.nSelAtoms) else: sel.origin[i] = origin[i] com[i] = com[i] + (sel.com[i] * sel.nSelAtoms) # Overlay models # Probably broken! elif self.centring == "overlay": com[i] = com[i] + (sel.com[i] * sel.nSelAtoms) sel.origin[i] = -sel.com[i] if self.previous == "weight": pass nat = nat + sel.nSelAtoms self.previous = self.centring if nat*nat < 0.00000001: return if maxsize > maxdist: re_size = maxsize else: re_size = maxdist + maxsize glthread.setmaxviewsize(re_size/2) #print "after setmaxviewsize 2 re_size",re_size for i in [0,1,2]: self.com[i] = com[i] / nat self.origin[i] = origin[i] / nat #print "self.origin",self.origin glthread.glevent.centre_on(self.origin) self.recentre = 0 #---------------------------------------------------------------------- def SetContinuousTransform ( self,mode='rock'): #---------------------------------------------------------------------- if not mode: self.continuous_on = 1 # ?Todo Revert to initial view else: import time self.continuous_mode = mode self.continuous_on = 1 self.continuous_last_time = time.time() self.continuous_last_step = 0 if mode == 'rock': last_phase = 0.0 rock_delta = [] import math,copy for step in range (1,self.continuous_rock['nsteps']+1): phase = math.sin ( float(step) * math.pi * 2.0 / \ float(self.continuous_rock['nsteps'] ) ) rock_delta.append(phase-last_phase) last_phase=copy.deepcopy(phase) #print "rock_delta",rock_delta self.continuous_rock['deltas'] = rock_delta ''' if interrupt_label: GUI.GUI.insts.StartInterrupt(gui=interrupt_label) ''' #----------------------------------------------------------------------- def UpdateContinuousTransform ( self, jq=None ): #----------------------------------------------------------------------- if not self.continuous_on: return import time import utils import rebuild import copy glthread = BUILD().glthread self.continuous_last_step = self.continuous_last_step+1 # make sure we are not going too fast delay = (self.continuous_last_time + self.continuous_sleep) - time.time() if delay>0.0: #print "ApplyContinuousTransform delay",delay time.sleep(delay) self.continuous_last_time = time.time() glthread.Wait() glthread.Pause() t = self.continuous_transform if self.continuous_mode == 'roll': d = 1.0/float(self.continuous_roll['nsteps']) else: i = self.continuous_last_step % self.continuous_rock['nsteps'] d = self.continuous_rock['deltas'][i] * self.continuous_rock['fraction'] glthread.rotate_camera([t['rotate_x']*d,t['rotate_y']*d,t['rotate_z']*d]) #glthread.move_camera(t['translate_x']*d,-t['translate_y']*d,t['translate_z']*d) #glthread.zoom_camera (t['zoom']*d ) glthread.UnPause() ''' # After recording a rock return to initial position if transform_rock: # return to original position glthread.Wait() glthread.Pause() #print "restore",float(rotate_y)/2 glthread.rotate_camera((float(rotate_x)/2,float(rotate_y)/2,float(rotate_z)/2)) glthread.move_camera( float(translate_x)/2, -float(translate_y)/2, float(translate_z)/2) glthread.zoom_camera ( float(zoom)/2 ) glthread.UnPause() ''' ''' if interrupt_label: GUI.GUI.insts.EndInterrupt(interrupt_label) '''