Package Pmv :: Module SLCommands
[hide private]
[frames] | no frames]

Source Code for Module Pmv.SLCommands

   1  # 
   2  # $Header: /opt/cvs/python/packages/share1.5/Pmv/SLCommands.py,v 1.30 2007/05/15 17:39:37 vareille Exp $ 
   3  # 
   4  # $Id: SLCommands.py,v 1.30 2007/05/15 17:39:37 vareille Exp $ 
   5  # 
   6   
   7  import Tkinter, Numeric, Pmw 
   8  from DejaVu.IndexedPolygons import IndexedPolygons 
   9  from ViewerFramework.VFCommand import CommandGUI 
  10  from mglutil.gui.InputForm.Tk.gui import InputFormDescr 
  11  from Pmv.mvCommand import MVCommand 
  12  from DejaVu.GleObjects import GleObject 
  13  try: 
  14      from SpatialLogic import geometrylib 
  15      initCommand = True 
  16  except: 
  17      print "WARNING: Spatial Logic module not found" 
  18      initCommand = False 
  19   
  20  from opengltk.OpenGL import GL 
  21  from time import time 
  22  import thread 
  23  from string import split, find ,replace 
  24  import types 
  25  from os import path 
  26  from math import sqrt 
  27  from MolKit.molecule import AtomSet, Atom 
  28  from Pmv.displayCommands import DisplayCommand 
  29  import string 
  30   
  31  BHTree_CUT = 40.0 
32 -def triangle_normal(p1, p2, p3):
33 """computes a normal for a triangle""" 34 v1 = [0.0, 0.0, 0.0] 35 v2 = [0.0, 0.0, 0.0] 36 for i in range(3): 37 v1[i] = p2[i]-p1[i] #vector (p1,p2) 38 #v2[i] = p3[i]-p2[i] #vector (p2,p3) 39 v2[i] = p3[i]-p1[i] #vector (p1,p3) 40 v = [0.0, 0.0, 0.0] 41 v[0] = v1[1]*v2[2] - v1[2]*v2[1] #v3 = v1^v2 42 v[1] = v1[2]*v2[0] - v1[0]*v2[2] 43 v[2] = v1[0]*v2[1] - v1[1]*v2[0] 44 norm = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]) 45 if (norm>1.0e-8): 46 for i in range(3): v[i] = v[i] /norm 47 else: 48 for i in range(3): v[i] = 0.0 49 return v
50 51 OPS = ("union", "join", "difference", "intersect") 52
53 -class SLGeom:
54 """An interface class based on Spatial Geometry library (geometrylib.so)"""
55 - def __init__(self):
56 geometrylib.Initialize_Geometry_Module(geometrylib.Default_Geometry_Module())
57
58 - def readFile0(self, filename):
59 """ opens a brp(boundary representations) file, returns the data """ 60 f_ptr = open(filename) 61 lines = f_ptr.readlines() 62 f_ptr.close() 63 return lines
64
65 - def indexedFromFile0(self, brp):
66 """Reads data from .brp(boundary representations) file , returns 67 an array of vertices and a list of faces.""" 68 69 vertDict = {} 70 faceList = [] 71 findex = [] 72 mode = None 73 vnumber = 0 74 for s in brp: 75 sp = split(s) 76 77 if len(sp)<1: continue 78 if sp[0] == 'POLYGON': 79 mode = 'face' 80 continue 81 if sp[0] == 'PT': 82 vertices = [float(sp[1]), float(sp[2]), float(sp[3])] 83 vstring = '%12.6f %12.6f %12.6f'%tuple(vertices) 84 85 if not vertDict.has_key(vstring): 86 vertDict[vstring]=(vnumber) 87 findex.append(vnumber) 88 vnumber = vnumber + 1 89 continue 90 else: 91 findex.append(vertDict[vstring]) 92 continue 93 if sp[0] == 'TX' or sp[0] == 'N': 94 continue 95 else: 96 if mode == 'face': 97 faceList.append(findex) 98 findex = [] 99 mode = None 100 101 vertArray = Numeric.zeros( (len(vertDict),3) ).astype('f') 102 #normArray = Numeric.zeros( (len(vertDict),3) ).astype('f') 103 104 for i in range(len(vertDict)): 105 s = split(vertDict.keys()[i]) 106 index = vertDict.values()[i] 107 vertArray[index] = ([ float(s[0]), float(s[1]), float(s[2]) ]) 108 #normArray[index] = vertDict.values()[i][1] 109 110 return vertArray, faceList #, normArray
111
112 - def readBrepFile(self, filename):
113 114 """ opens a brp file, returns the data """ 115 f_ptr = open(filename) 116 lines = f_ptr.readlines() 117 f_ptr.close() 118 ## i=0 119 ## sp = split(brp[i]) 120 ## while (len(sp) < 1): 121 ## i = i+1 122 ## sp = split(brp[i]) 123 ## if sp[1] != "ASCII": 124 ## print "file is not ASCII text" 125 ## return 126 ## if sp[2] != "BREP": 127 ## print "file is not BREP" 128 ## return 129 vertList = [] 130 faceList = [] 131 for s in lines: 132 sp = split(s) 133 134 if len(sp)<1: continue 135 if sp[0] == 'POLYGON': 136 faceList.append(int(sp[-1])) 137 continue 138 if sp[0] == 'PT': 139 vertList.append([float(sp[1]), float(sp[2]), float(sp[3])]) 140 return vertList, faceList #, normArray
141
142 - def writeBspt(self, bspt_set, filename, ascii = 0):
143 """ writes a Bspt in a file""" 144 # if ascii == 1 - Bspt is written in a text file. 145 fid = geometrylib.New_FileID() 146 from os import path 147 if path.splitext(filename)[-1] != ".bsp": 148 name = filename+".bsp" 149 else : 150 name = filename 151 #name = split(filename, ".")[0]+".bsp" 152 fid.file_name = name 153 fid.ascii = ascii 154 fid.fp = geometrylib.Open_File( "test", fid.file_name, "w" ) 155 #geometrylib.Write_Set(bspt_set, fid) 156 bspt_set = geometrylib.Discard_Set_Shps(bspt_set) 157 status = geometrylib.write_Set(bspt_set, fid) 158 #print "write status: ", status 159 return status
160
161 - def readBspt(self, filename):
162 """ reads a Bspt from a file""" 163 if not path.isfile(filename): 164 print "File %s does not exist." % (filename,) 165 return 166 t1 = time() 167 fid = geometrylib.New_FileID() 168 fid.fp = geometrylib.Open_File( "test", filename, "r" ) 169 fid = geometrylib.Read_FileID( fid.fp ) 170 set = geometrylib.Read_Set(fid) 171 set = geometrylib.Form_Set_Shps( set ) 172 t2 = time() 173 #print "time to read %s : %.2f"% (filename, (t2-t1)) 174 #print "set: ", set 175 return set
176
177 - def buildBrepSet0(self, points, indeces, solid=1):
178 pts = [] 179 for p in points: 180 pts.append(geometrylib.Assign_Point(p[0], p[1], p[2])) 181 182 #no vertex normals 183 null_normal = None 184 colors = None 185 has_texture_coords = 0 186 has_vertex_normals = 0 187 has_vertex_colors = 0 188 material = geometrylib.Default_Material() 189 brep_set = geometrylib.New_BrepSet() 190 sh = indeces.shape 191 for i in range(sh[0]): 192 brep_face = geometrylib.New_BrepFace(material, has_texture_coords, 193 has_vertex_normals, has_vertex_colors) 194 #print "face No: ", i 195 for j in range(sh[1]): 196 brep_face = geometrylib.Add_BrepFace_Vertex(brep_face, 197 pts[indeces[i][j]], 198 0., 0., #has no texture coords 199 null_normal,#has no vertex normals 200 colors) 201 #print points[indeces[i][j]], 202 #print '' 203 brep_set = geometrylib.Add_BrepFace(brep_set, brep_face, 1) 204 geometrylib.Make_BrepSet_Solid(brep_set, solid) 205 return brep_set
206
207 - def buildBrepSet(self, points, indeces, normals = None, solid=1):
208 """create Brep set""" 209 has_normals = 0 210 if normals: 211 has_normals = 1 212 brep_set = geometrylib.CreateBrepSet(points,indeces, has_normals, normals) 213 geometrylib.Make_BrepSet_Solid(brep_set, solid) 214 return brep_set
215
216 - def Brep_To_Bspt(self, brep_set, expense = 0.5, exponent = None):
217 """create a Set object of BSPT_SET type from Brep_Set""" 218 parameters = geometrylib.New_BrepToBsptParams() 219 if exponent: 220 parameters.exponent = exponent 221 bspt_set = geometrylib.BrepSet_to_BsptSet(brep_set, expense, 222 parameters, None ) 223 set = geometrylib.New_Set( geometrylib.BSPT_SET, bspt_set ) 224 return set
225
226 - def buildBsptSet(self, points, indeces, normals = None, expense = 0.5, 227 solid=1):
228 """create a Set object of BSPT_SET type""" 229 has_normals = 0 230 if normals: 231 has_normals = 1 232 brep_set = geometrylib.CreateBrepSet(points,indeces, has_normals, normals) 233 geometrylib.Make_BrepSet_Solid(brep_set, solid) 234 parameters = geometrylib.New_BrepToBsptParams() 235 bspt_set = geometrylib.BrepSet_to_BsptSet(brep_set, expense, 236 parameters, None ) 237 set = geometrylib.New_Set( geometrylib.BSPT_SET, bspt_set ) 238 return set
239
240 - def operateBsptSets(self, set1, set2, operation, expense = 0.5, copy = "duplicate"):
241 """operates with two sets of BSPT_SET type. 242 - operation can be one of the following: 243 'union', 'join', 'difference', 'intersect' . 244 - copy can be None , 'duplicate' or 'copy' (for duplicating 245 or copying given operands)""" 246 247 #ops = ("union", "join", "difference", "intersect") 248 if operation not in OPS: 249 print "wrong operation name: ", operation 250 print OPS 251 return None 252 copy_func = None 253 if copy: 254 if copy == "duplicate": 255 copy_func = geometrylib.Duplicate_Set 256 elif copy == "copy": 257 copy_func = geometrylib.Copy_Set 258 if operation == "union": 259 if copy: 260 set = geometrylib.Union_Sets(copy_func(set1), 261 copy_func(set2), None) 262 else: 263 set = geometrylib.Union_Sets(set1, set2, None) 264 elif operation == "join": 265 if copy: 266 set = geometrylib.Join_Sets(copy_func(set1), 267 copy_func(set2), None) 268 else: 269 set = geometrylib.Join_Sets(set1, set2, None) 270 elif operation == "difference": 271 if copy: 272 set = geometrylib.Difference_Sets(copy_func(set1), 273 copy_func(set2), None) 274 else: 275 set = geometrylib.Difference_Sets(set1, set2, None) 276 elif operation == "intersect": 277 if copy: 278 set = geometrylib.Intersect_Sets(copy_func(set1), 279 copy_func(set2), None) 280 else: 281 set = geometrylib.Intersect_Sets(set1, set2, None) 282 ## rset = geometrylib.Convert_Set(set, geometrylib.BREP_SET, expense) 283 ## size = geometrylib.Size_of_BrepSet(rset) 284 ## nvert = size.vertices 285 ## nface = size.faces 286 ## print nvert , nface 287 return set
288
289 - def convert_to_Brep(self, set, expense = 0.5, duplicate = 0):
290 """Converts Bsp tree set to Brep set (boundary representation)""" 291 292 if set.type != geometrylib.BSPT_SET: 293 raise TypeError, "Set is not BSPT_Set type" 294 if duplicate: 295 return geometrylib.Convert_Set(geometrylib.Duplicate_Set(set), geometrylib.BREP_SET, expense) 296 else: 297 return geometrylib.Convert_Set(set, geometrylib.BREP_SET, expense)
298
299 - def discardSet(self, set):
300 geometrylib.discard_Set(set)
301
302 - def getBoundaries(self, set, has_vnormals = 0, has_fnormals = 0):
303 """returns arrays of vertices, faces, normals """ 304 305 if set.type != geometrylib.BREP_SET: 306 raise TypeError, "Set is not BREP_Set type" 307 size = geometrylib.Size_of_BrepSet(set) 308 nvert = size.vertices 309 nface = size.faces 310 import Numeric 311 verts = Numeric.zeros((nvert,3), 'f') #all vertices 312 faces = Numeric.zeros(nface, 'i') #number of vertices per each face 313 if has_vnormals: 314 vnorms = Numeric.zeros((nvert,3), 'f') 315 else: 316 vnorms = None 317 if has_fnormals: 318 fnorms = Numeric.zeros((nface,3), 'f') 319 else: 320 fnorms = None 321 322 geometrylib.BrepSet_out(set, verts, faces, vnorms, fnorms) # verts, faces, norms 323 # must be contiguous Num. arrays. 324 #print "in getBoundaries: brepsize: ", size, "nvert: ", nvert , "nface:", nface 325 return verts, faces, vnorms, fnorms
326 327 328
329 - def indexedFromArr_old(self, verts, faces, vnorms = None, fnorms = None):
330 """returns indexed arrays of vertices, faces, normals .""" 331 332 if not len(verts): 333 print "vertices array length = 0" 334 return None, None, None, None 335 vertDict = {} 336 faceList = [] 337 findex = [] 338 vertList = [] 339 vnormList = [] 340 fnormList = [] 341 vnumber = 0 342 fcount = 0 343 vcount = 0 344 count = 0 345 for v in verts: 346 vstring = '%12.6f %12.6f %12.6f'%tuple(v) 347 if not vertDict.has_key(vstring): 348 vertDict[vstring]=(vnumber) 349 findex.append(vnumber) 350 vertList.append(v) 351 if vnorms: 352 vnormList.append(vnorms[count]) 353 vnumber = vnumber + 1 354 else: 355 findex.append(vertDict[vstring]) 356 vcount = vcount+1 357 count = count + 1 358 if vcount == faces[fcount]: 359 faceList.append(findex) 360 if fnorms: 361 fnormList.append(fnorms[fcount]) 362 findex = [] 363 vcount = 0 364 fcount = fcount + 1 365 import Numeric 366 vertArray = Numeric.array(vertList) 367 if len(vnormList): 368 vnormArray = Numeric.array(vnormList) 369 else: 370 vnormArray = None 371 if len(fnormList): 372 fnormArray = Numeric.array(fnormList) 373 else: 374 fnormArray = None 375 return vertArray, faceList, vnormArray, fnormArray
376
377 - def indexedFromArr(self, verts, faces, vnorms = None, fnorms = None):
378 """returns indexed arrays of vertices, faces, normals .""" 379 380 if not len(verts): 381 print "vertices array length = 0" 382 return None, None, None, None 383 # Not all the faces may have the same number of vertices -> 384 # find the maximum number of vertices in the face array. 385 import Numeric 386 maxvertnum = Numeric.maximum.reduce(faces) 387 faceArray = (Numeric.ones((len(faces), maxvertnum)) *[-1]).astype("f") 388 vertDict = {} 389 vertList = [] 390 vnormList = [] 391 fnormList = [] 392 vnumber = 0 393 fcount = 0 394 vcount = 0 395 count = 0 396 397 for v in verts: 398 #vstring = '%12.6f %12.6f %12.6f'%tuple(v) 399 vstring = '%.12f#%.12f#%.12f'%tuple(v) 400 if not vertDict.has_key(vstring): 401 vertDict[vstring]=(vnumber) 402 faceArray[fcount][vcount] = vnumber 403 vertList.append(v) 404 if vnorms: 405 vnormList.append(vnorms[count]) 406 vnumber = vnumber + 1 407 else: 408 faceArray[fcount][vcount] = vertDict[vstring] 409 vcount = vcount+1 410 count = count + 1 411 if vcount == faces[fcount]: 412 if fnorms: 413 fnormList.append(fnorms[fcount]) 414 vcount = 0 415 fcount = fcount + 1 416 import Numeric 417 vertArray = Numeric.array(vertList) 418 if len(vnormList): 419 vnormArray = Numeric.array(vnormList) 420 else: 421 vnormArray = None 422 if len(fnormList): 423 fnormArray = Numeric.array(fnormList) 424 else: 425 fnormArray = None 426 return vertArray, faceArray, vnormArray, fnormArray
427 428 429 sl = None 430
431 -class SLCommand(MVCommand):
432 """Command that performs Bsp tree operations such as 'union', 433 'difference', 'intersect'.""" 434
435 - def __init__(self):
436 MVCommand.__init__(self) 437 self.obj_dict = {} #keys - full names of the Viewer objects 438 #values - {'copy_obj': IndexedPolygon(new instance from 439 # asIndexedPolygons()), 440 # 'v_f': tuple of num_of_verts, num_of_faces of original 441 # object}. 442 self.setdict = {} #keys - as above; 443 #values - built Bsp trees for objects. 444 self.cl_atoms = {} 445 self.isDisplayed = 0 446 self.currOptn = Tkinter.StringVar() 447 self.currOptn.set("union") 448 self.recomputeBSPT1 = Tkinter.IntVar() 449 self.recomputeBSPT1.set(0) 450 self.recomputeBSPT2 = Tkinter.IntVar() 451 self.recomputeBSPT2.set(0) 452 self.bindToMol = Tkinter.IntVar() 453 self.bindToMol.set(0) 454 self.newobj_name = Tkinter.StringVar()
455 #self.sl = None 456
457 - def checkDependencies(self):
458 try: 459 from SpatialLogic import geometrylib 460 except: 461 print "WARNING: Spatial Logic module not found"
462
463 - def buildFormDescr(self, formName):
464 if formName == "sl": 465 idf = self.idf = InputFormDescr(title = "Geometry operations") 466 self.updateObjectDict() 467 entries = self.sort_entries(self.allnames_dict) 468 idf.append({'name': 'object1', 469 'widgetType':Pmw.ComboBox, 470 'wcfg':{'labelpos': 'n', 471 'label_text':'Choose object 1', 472 'scrolledlist_items': entries}, 473 'gridcfg':{'sticky':'we', 'column': 0, 474 'columnspan':2}, 475 }) 476 idf.append({'name': 'object2', 477 'widgetType':Pmw.ComboBox, 478 'wcfg':{'labelpos': 'n', 479 'label_text':'Choose object 2', 480 'scrolledlist_items': entries}, 481 'gridcfg':{'sticky':'we', 'row': -1, 'column': 2, 482 'columnspan':2}, 483 }) 484 485 486 ## idf.append({'widgetType':Tkinter.Label, 487 ## 'wcfg': {'text':'Recompute Bspt for objects:'}, 488 ## 'gridcfg':{'sticky':'we', 'columnspan':4, 489 ## 'pady': 5} 490 491 ## }) 492 idf.append({'widgetType':Tkinter.Checkbutton, 493 #'name': name, 494 'tooltip': "Recompute Bspt of selected object1 every\ntime a set operation takes place.", 495 'wcfg':{'text': "Recompute Bspt obj1", 496 #'width':5, 497 'variable':self.recomputeBSPT1, 498 'onvalue': 1, 'offvalue': 0}, 499 'gridcfg':{'sticky': 'we', 'column': 0, 500 'columnspan':2} 501 }) 502 idf.append({'widgetType':Tkinter.Checkbutton, 503 #'name': name, 504 'tooltip': "Recompute Bspt of selected object2 every\ntime a set operation takes place.", 505 'wcfg':{'text': "Recompute Bspt obj2", 506 #'width':5, 507 'variable':self.recomputeBSPT2, 508 'onvalue': 1, 'offvalue': 0}, 509 'gridcfg':{'sticky': 'we', 'column': 2, 'row': -1, 510 'columnspan':2} 511 }) 512 idf.append({'widgetType':Tkinter.Label, 513 'wcfg': {'text':'Select operation type:'}, 514 'gridcfg':{'sticky':'we', 'columnspan':4, 515 'pady': 5} 516 }) 517 518 #ops = ["union", "join", "difference", "intersect"] 519 tips = ["A single solid object is created from the two objects.\n The goemetry of the overlapping area is eliminated.", 520 "Similar to union, exept that faces of the 2nd object \noverlapping the 1st are retained.", 521 "Subtraction: 1st object is left, minus its \noverlapping region with the 2nd object.", 522 "Preserves the overlapping region only, \neliminating all the rest of both objects."] 523 i = 0 524 for name in OPS: 525 idf.append({'widgetType':Tkinter.Checkbutton, 526 'name': name, 527 'tooltip':tips[i], 528 'wcfg':{'text': name, 529 #'width':5, 530 'variable':self.currOptn, 531 'onvalue': name, 'offvalue':None}, 532 'gridcfg':{'sticky': 'we', 'column': i, 'row': 4} 533 }) 534 i = i+1 535 self.newobj_name.set('') 536 idf.append({'widgetType' : Pmw.EntryField, 537 'wcfg': {'labelpos':'w', 538 'label_text' : "New object name(optional):", 539 'entry_textvariable': self.newobj_name}, 540 'gridcfg':{'sticky': 'we', 'column':0, 541 'columnspan':4, 'pady': 5} 542 }) 543 idf.append({'widgetType':Tkinter.Checkbutton, 544 'wcfg':{'text': "bind new object to molecule", 545 #'width':5, 546 'variable':self.bindToMol , 547 'onvalue': 1, 'offvalue': 0}, 548 'gridcfg':{'sticky': 'we','columnspan':4} 549 }) 550 idf.append({'widgetType':Tkinter.Button, 551 'wcfg': {'text': 'Operate', 552 'relief' : Tkinter.RAISED, 553 'borderwidth' : 3, 554 'command':self.operate_cb}, 555 'gridcfg':{'sticky':'we', 'columnspan':2}, 556 }) 557 558 idf.append({'widgetType':Tkinter.Button, 559 'wcfg':{'text': 'Dismiss', 560 'relief' : Tkinter.RAISED, 561 'borderwidth' : 3, 562 'command':self.dismiss_cb}, 563 'gridcfg':{'sticky':'we', 'row':-1, 'columnspan':2}, 564 }) 565 566 return idf
567
568 - def sort_entries(self, name_dict):
569 keys = name_dict.keys() 570 vals = name_dict.values() 571 vals_sorted = map(None, vals, range(len(vals))) 572 vals_sorted.sort() 573 keys_sorted = [] 574 for v in vals_sorted: 575 keys_sorted.append(keys[v[1]]) 576 return keys_sorted
577
578 - def guiCallback(self):
579 if self.isDisplayed: 580 self.idf.form.lift() 581 return 582 self.isDisplayed=1 583 val = self.showForm('sl', force = 1, modal = 0)
584 #print val 585
586 - def updateObjectDict(self):
587 """Updates a list of objects on which set operations canbe performed. 588 Called with every callback of the command.""" 589 vi = self.vf.GUI.VIEWER 590 591 allobj = {} 592 allnames_dict = {} 593 # get a dictionary of all objects in the viewer 594 for o in vi.rootObject.AllObjects(): 595 if o.asIndexedPolygons(run=0): 596 v = hasattr(o, 'vertexSet') 597 f = hasattr(o, 'faceSet') 598 indict = 0 599 v_f = () 600 if v and f: 601 v_f = (len(o.vertexSet), len(o.faceSet)) 602 if v_f[0] >0 and v_f[1] > 0: 603 allobj[o.fullName] = {'obj':o, 'v_f':v_f} 604 indict = 1 605 elif v: 606 v_f = (len(o.vertexSet),) 607 if v_f[0] >0: 608 allobj[o.fullName] = {'obj':o, 'v_f':v_f} 609 indict = 1 610 if indict: 611 short_name = o.name 612 entry = short_name + '(' + \ 613 replace(o.fullName, short_name, '')+ ')' 614 allnames_dict[entry] = o.fullName 615 #check if objects had been added/removed to the viewer since 616 #last callback of the command: 617 allobj_names = allobj.keys() 618 slobj_names = self.obj_dict.keys() 619 for name in slobj_names: 620 if name in allobj_names: 621 #check if the object has changed(number of vertices and faces) 622 if allobj[name]['v_f'] != self.obj_dict[name]['v_f']: 623 if self.obj_dict[name].has_key('copy_obj'): 624 del(self.obj_dict[name]['copy_obj']) 625 self.obj_dict[name]['v_f'] = allobj[name]['v_f'] 626 self.obj_dict[name]['obj'] = allobj[name]['obj'] 627 if name in self.setdict.keys(): 628 del(self.setdict[name]) 629 allobj_names.remove(name) 630 else: 631 del(self.obj_dict[name]) 632 if name in self.setdict.keys(): 633 del(self.setdict[name]) 634 for name in allobj_names: 635 self.obj_dict[name] = {'v_f': allobj[name]['v_f'], 636 'obj':allobj[name]['obj']} 637 self.allnames_dict = allnames_dict
638
639 - def operate_cb(self):
640 641 name1 = self.idf.entryByName['object1']['widget'].get() 642 name2 = self.idf.entryByName['object2']['widget'].get() 643 if not name1 or not name2: 644 print "object(s) not selected " 645 return 646 opname = self.currOptn.get() 647 if not opname: 648 print "Operation type is not selected." 649 return 650 newobj_name = self.newobj_name.get() 651 bindToMol = self.bindToMol.get() 652 apply(self.doitWrapper, (self.allnames_dict[name1], 653 self.allnames_dict[name2], 654 opname, newobj_name, bindToMol), {}) 655 self.dismiss_cb() 656 self.vf.GUI.VIEWER.Redraw()
657
658 - def __call__(self, name1, name2, operation, newobj_name = '', bindToMol = 0, **kw):
659 """ None <- SL(name1, name2, operation, newobj_name = '', bindToMol=0) 660 name1, name2 - names of two objects (full names, eg: 1crn|msms); 661 operation - can be one of the following: 662 'union', 'join', 'intersect', 'difference'; 663 newobj_name - name of new object(optional); 664 bindToMol - 1 for binding new object to molecule, 665 0 if no binding is needed. 666 """ 667 668 self.updateObjectDict() 669 names = self.obj_dict.keys() 670 if name1 not in names: 671 print "%s is not a valid operand" % (name1,) 672 return 673 if name2 not in names: 674 print "%s is not a valid operand" % (name2,) 675 return 676 #ops = ("union", "join", "difference", "intersect") 677 if operation not in OPS: 678 print "%s in not a valid operation" % operation 679 return 680 apply(self.doitWrapper, (name1, name2, operation, newobj_name, bindToMol), kw)
681 682
683 - def doit(self, name1, name2, opname, res_name, bindToMol):
684 if not res_name: 685 res_name = split(name1,"|")[-1] + '-' + \ 686 split(name2, "|")[-1] + '-' + opname 687 if res_name in self.setdict.keys(): 688 print "%s object exists." % (res_name) 689 return 690 global sl 691 if not sl: 692 sl = SLGeom() 693 ## thread.start_new_thread( self.doSetOperation,(name1, name2, opname, 694 ## res_name)) 695 self.doSetOperation(name1, name2, opname, res_name,bindToMol)
696
697 - def doSetOperation(self, name1, name2, opname, res_name, bindToMol):
698 """ Performs Bspt set operations. """ 699 ex = 0.5 700 expon = 1.0 701 bspt_set1 = None 702 bspt_set2 = None 703 if name1 in self.setdict.keys(): 704 #check if we need to recompute the Bspt for the object 705 if self.recomputeBSPT1.get(): 706 if hasattr(self.obj_dict[name1]['obj'], "SLnewobj"): 707 # this object had been created by SL : 708 # do not recompute 709 bspt_set1 = self.setdict[name1] 710 else: 711 #remove the computed Bspt from self.setdict 712 # remove a copy of the object from 713 # self.obj_dict so that the function could use 714 # updated arrays of vertices and faces. 715 del(self.setdict[name1]) 716 if self.obj_dict[name1].has_key('copy_obj'): 717 del(self.obj_dict[name1]['copy_obj']) 718 else: 719 bspt_set1 = self.setdict[name1] 720 if not geometrylib.Size_of_Set(bspt_set1): 721 bspt_set1 = None 722 if not bspt_set1: 723 if self.obj_dict[name1].has_key('copy_obj'): 724 object1 = self.obj_dict[name1]['copy_obj'] 725 else: 726 ## if isinstance(self.obj_dict[name1]['obj'], GleObject): 727 ## object1 = self.obj_dict[name1]['obj'] 728 ## else: 729 object1 = self.obj_dict[name1]['obj'].asIndexedPolygons(run=1, removeDupVerts=0) 730 self.obj_dict[name1]['copy_obj'] = object1 731 v1 = object1.vertexSet.vertices.array 732 #print "object1: ", object1 733 ## if isinstance(object1, GleObject): 734 ## f1 = self.triangulate_strips(object1.faceSet.faces.array) 735 ## else: 736 f1 = object1.faceSet.faces.array 737 #print "obj1, verts: ", len(v1), "faces: ", len(f1) 738 brep_set1 = sl.buildBrepSet(v1,f1) 739 t1 = time() 740 bspt_set1 = sl.Brep_To_Bspt(brep_set1, expense = ex, 741 exponent = expon) 742 t2 = time() 743 print "time to build bspt_set1(%s) is %.5f " % (name1, (t2-t1)) 744 if name2 in self.setdict.keys(): 745 if self.recomputeBSPT2.get(): 746 if hasattr(self.obj_dict[name2]['obj'], "SLnewobj"): 747 bspt_set2 = self.setdict[name2] 748 else: 749 del(self.setdict[name2]) 750 if self.obj_dict[name2].has_key('copy_obj'): 751 del(self.obj_dict[name2]['copy_obj']) 752 else: 753 bspt_set2 = self.setdict[name2] 754 if not geometrylib.Size_of_Set(bspt_set2): 755 bspt_set2 = None 756 if not bspt_set2: 757 if self.obj_dict[name2].has_key('copy_obj'): 758 object2 = self.obj_dict[name2]['copy_obj'] 759 else: 760 object2 = self.obj_dict[name2]['obj'].asIndexedPolygons(run=1, removeDupVerts=0) 761 self.obj_dict[name2]['copy_obj'] = object2 762 #print "object2: ", object2 763 v2 = object2.vertexSet.vertices.array 764 ## if isinstance(object2, GleObject): 765 ## f2 = self.triangulate_strips(object2.faceSet.faces.array) 766 ## else: 767 f2 = object2.faceSet.faces.array 768 brep_set2 = sl.buildBrepSet(v2,f2) 769 t1 = time() 770 bspt_set2 = sl.Brep_To_Bspt(brep_set2, expense = ex, 771 exponent = expon) 772 t2 = time() 773 print "time to build bspt_set2(%s) is %.5f " % (name2, (t2-t1)) 774 rset = sl.operateBsptSets(bspt_set1, bspt_set2, opname, 775 expense=ex, copy = "duplicate") 776 777 brep_set= sl.convert_to_Brep(rset, expense=ex, duplicate=1) 778 verts, faces , vnorms,fnorms = sl.getBoundaries(brep_set, 779 has_vnormals = 0, 780 has_fnormals = 1) 781 vs,fs,vns,fns = sl.indexedFromArr(verts, faces, fnorms=fnorms) 782 #sl.discardSet(brep_set) 783 #brep_set = None 784 if find(res_name, "_"): #name should not contain "_" 785 res_name = replace(res_name, "_", "-") 786 ## if vs: 787 ## length = map( len, fs) 788 ## mlength = max(length) 789 ## for i in range(len(fs)): 790 ## d = mlength-len(fs[i]) 791 ## if d: 792 ## for j in range(d): 793 ## fs[i].append(-1) 794 vi = self.vf.GUI.VIEWER 795 mol= None 796 res_fullname = 'root|'+res_name 797 if bindToMol: 798 from Pmv.guiTools import MoleculeChooser 799 mol = MoleculeChooser(self.vf).go() 800 if mol: 801 #mol_geom = self.vf.Mols.NodesFromName( molname )[0].geomContainer.masterGeom 802 mol_geom = mol.geomContainer.masterGeom 803 res_fullname = mol_geom.fullName+'|'+res_name 804 805 #find if an object with the same name already exists: 806 obj_fullnames = self.obj_dict.keys() 807 objnames = map(lambda x: split(x, '|')[-1], obj_fullnames) 808 overwrite = False 809 if res_name in objnames: 810 ind = objnames.index(res_name) 811 if res_fullname in obj_fullnames: 812 ipg = self.obj_dict[res_fullname]['obj'] 813 if hasattr(ipg, "SLnewobj"): # the object is a result 814 # of SL operation 815 if ipg.SLnewobj: 816 overwrite = True # will overwrite the object's 817 # vertices and faces arrays 818 ## if not overwrite: 819 ## ipg = self.obj_dict[ obj_fullnames[ind] ]['obj'] 820 ## if isinstance(ipg, IndexedPolygons): 821 ## #ask the user : 822 ## root = Tkinter.Toplevel() 823 ## root.withdraw() 824 ## from SimpleDialog import SimpleDialog 825 ## ans = SimpleDialog(root, text="Object %s exists. Overwrite it?"% (obj_fullnames[ind],), 826 ## buttons=["Yes", "No"], 827 ## default=0, 828 ## title="overwrite dialog").go() 829 ## root.destroy() 830 ## if ans == 0: 831 ## overwrite = True 832 if overwrite: 833 ipg.Set(vertices = vs, faces = fs,fnormals = fns, 834 freshape = True, tagModified=False) 835 if mol: 836 cl_atoms = self.vf.bindGeomToMolecularFragment( 837 ipg, mol.name,log=0) 838 #addToViewer=False, log=0) 839 if cl_atoms: 840 #self.vf.bindGeomToMolecule.data[res_name]['fns']=fns 841 self.vf.bindGeomToMolecularFragment.data[ipg.fullName]['fns']=fns 842 else: 843 ipg = IndexedPolygons(res_name, vertices = vs, 844 faces = fs, #fnormals=fns, 845 #materials=col2, 846 visible=1, inheritMaterial=0, protected=True,) 847 if self.vf.userpref['sharpColorBoundariesForMsms']['value'] == 'blur': 848 ipg.Set(inheritSharpColorBoundaries=False, sharpColorBoundaries=False,) 849 if mol: 850 cl_atoms = self.vf.bindGeomToMolecularFragment( 851 ipg, mol.name, log=0) 852 if cl_atoms: 853 #self.vf.bindGeomToMolecule.data[res_name]['fns']=fns 854 self.vf.bindGeomToMolecularFragment.data[ipg.fullName]['fns']=fns 855 else: 856 vi.AddObject(ipg) 857 else: 858 vi.AddObject(ipg) 859 ipg.Set(frontPolyMode=GL.GL_FILL, shading=GL.GL_FLAT) 860 ipg.Set(fnormals = fns, tagModified=False) 861 862 self.setdict[ipg.fullName] = rset 863 ipg.SLnewobj = True 864 print "size of bspt_set1:", geometrylib.Size_of_Set(bspt_set1) 865 print "size of bspt_set2:", geometrylib.Size_of_Set(bspt_set2) 866 print "size of rset:", geometrylib.Size_of_Set(rset) 867 else: 868 print "Number of vertices of the resultant object is 0." 869 if name1 not in self.setdict.keys(): 870 self.setdict[name1] = bspt_set1 871 if name2 not in self.setdict.keys(): 872 self.setdict[name2] = bspt_set2
873 #self.dismiss_cb() 874
875 - def timeBspt(self, expon = 1.0):
876 object = self.vf.GUI.VIEWER.currentObject 877 name = object.fullName 878 if not isinstance(object, IndexedPolygons): 879 print "object %s is not IndexedPolygons instance" % (name,) 880 return 881 v = object.vertexSet.vertices.array 882 if isinstance(object, GleObject): 883 f = self.triangulate_strips(object.faceSet.faces.array) 884 else: 885 f = object.faceSet.faces.array 886 n = object.normals 887 ## if not self.sl: 888 ## self.sl = SLGeom() 889 global sl 890 if not sl: 891 sl = SLGeom() 892 t1 = time() 893 #brep_set = sl.buildBrepSet(v,f,normals = n) 894 brep_set = sl.buildBrepSet(v,f) 895 #brep_set = sl.buildBrepSet0(v,f) 896 t2 = time() 897 print "time to build brep_set for %s is %.2f " % (name, (t2-t1)) 898 t1 = time() 899 bspt_set = sl.Brep_To_Bspt(brep_set, exponent = expon) 900 t2 = time() 901 print "time to build bspt_set is %.2f " % (t2-t1) 902 if name not in self.setdict.keys(): 903 self.setdict[name] = bspt_set
904
905 - def rm_neg_inds(self, arr):
906 """From every face of the given face array removes 907 entries that == -1 """ 908 fl = arr.tolist() 909 for face in fl: 910 while(face[-1] < 0): 911 face.pop(-1) 912 return fl
913 914
915 - def triangulate_strips(self, faces):
916 """Triangulate surfaces built with triangle strips.""" 917 918 size = faces.shape 919 # number of triangles in each face (containing triangle strip 920 # vertices) from faces array. 921 ntr = size[1]-2 922 # new length of triangles array 923 nfaces = size[0]*ntr 924 new_faces = Numeric.zeros((nfaces, 3), 'i') 925 i = 0 926 for f in faces: 927 for n in range(ntr): 928 if (n/2)*2 == n: 929 new_faces[i] = [f[n], f[n+1], f[n+2]] 930 else: 931 new_faces[i] = [f[n+2], f[n+1], f[n]] 932 i = i + 1 933 return new_faces
934
935 - def dismiss_cb(self):
936 """Withdraws the GUI.""" 937 self.cmdForms['sl'].withdraw() 938 self.isDisplayed=0
939 940 SLGUI = CommandGUI() 941 SLGUI.addMenuCommand('menuRoot', 'SL','Operate objects', index=1) 942
943 -class SaveBsptCommand(MVCommand):
944 """Command to save a Bspt set in a file."""
945 - def __init__(self):
946 MVCommand.__init__(self) 947 self.isDisplayed=0
948 #self.sl = SLGeom() 949
950 - def checkDependencies(self):
951 try: 952 from SpatialLogic import geometrylib 953 except: 954 print "WARNING: Spatial Logic module not found"
955
956 - def guiCallback(self):
957 if not hasattr(self.vf, "SL"): 958 return 959 else : 960 if not len(self.vf.SL.setdict): 961 return 962 if self.isDisplayed: 963 self.idf.form.lift() 964 return 965 self.isDisplayed=1 966 val = self.showForm('saveBspt', force = 1, modal = 0)
967
968 - def buildFormDescr(self, formName):
969 if formName == "saveBspt": 970 entries = self.vf.SL.setdict.keys() 971 idf = self.idf = InputFormDescr(title = "Save Bspt in file") 972 idf.append({'widgetType': Pmw.ScrolledListBox, 973 'name':'BsptList', 974 'wcfg' : {'items':entries, 975 'labelpos': 'n', 976 'label_text': "Select a BSPT"}, 977 'gridcfg':{'sticky':'we', 'columnspan': 2} 978 }) 979 idf.append({'widgetType': Tkinter.Button, 980 'wcfg': {'text': 'OK', 981 'relief' : Tkinter.RAISED, 982 'borderwidth' : 2, 983 'command':self.select_cb}, 984 'gridcfg':{'sticky':'we',}, 985 }) 986 987 idf.append({'widgetType':Tkinter.Button, 988 'wcfg':{'text': 'Cancel', 989 'relief' : Tkinter.RAISED, 990 'borderwidth' : 3, 991 'command':self.cancel_cb}, 992 'gridcfg':{'sticky':'we', 'row':-1}, 993 }) 994 995 return idf
996
997 - def select_cb(self):
998 selection = \ 999 self.idf.entryByName['BsptList']['widget'].getcurselection() 1000 if selection: 1001 savefile = self.vf.askFileSave(types=[('BSPT file', '*.bsp')], 1002 title = "Save as .bsp") 1003 if savefile : 1004 apply(self.doitWrapper, (savefile, selection[0]), {}) 1005 1006 self.cmdForms['saveBspt'].withdraw() 1007 self.isDisplayed=0
1008
1009 - def cancel_cb(self):
1010 self.cmdForms['saveBspt'].withdraw() 1011 self.isDisplayed=0
1012
1013 - def doit(self, savefile, selection):
1014 global sl 1015 if not sl: 1016 sl = SLGeom() 1017 status = sl.writeBspt(self.vf.SL.setdict[selection], savefile) 1018 print "write status:", status 1019 return
1020
1021 - def __call__(self, savefile, selection, **kw):
1022 """None <- SaveBspt(savefile, selection): 1023 savefile - name of file with .bsp extension; 1024 selection - name of Bspt set """ 1025 1026 if not hasattr(self.vf, "SL"): 1027 print "Warning: SLCommand is not loaded" 1028 return 1029 if not path.isfile(savefile): 1030 print "Warning: file %s does not exist" % (savefile,) 1031 return 1032 if not selection in self.vf.SL.setdict.keys(): 1033 print "Wrong selection: %s" % (selection,) 1034 print "list of avalable Bspt(s):" 1035 print self.vf.SL.setdict.keys() 1036 return 1037 apply(self.doitWrapper, (savefile, selection), kw)
1038 1039 1040 SaveBsptGUI = CommandGUI() 1041 SaveBsptGUI.addMenuCommand('menuRoot', 'SL','Save Bspt', index = 2) 1042
1043 -class RestoreBsptCommand(MVCommand):
1044 """Command to build a geometric object out of previously built and 1045 saved in a file Bspt set. Adds the new object to the viewer. 1046 The object can be linked to a molecule.""" 1047
1048 - def checkDependencies(self):
1049 from bhtree import bhtreelib 1050 try: 1051 from SpatialLogic import geometrylib 1052 except: 1053 print "WARNING: SpatialLogic module not found."
1054 1055
1056 - def __init__(self):
1057 MVCommand.__init__(self) 1058 self.isDisplayed=0
1059
1060 - def guiCallback(self):
1061 if not hasattr(self.vf, "SL"): 1062 self.warningMsg("This command requires 'SLCommands' module. Load the module.") 1063 return 1064 file = self.vf.askFileOpen(types=[('BSPT file', '*.bsp')], 1065 title = "Read .bsp") 1066 if file: 1067 root = Tkinter.Toplevel() 1068 root.withdraw() 1069 from SimpleDialog import SimpleDialog 1070 ans = SimpleDialog(root, text="Bind object to molecule?", 1071 buttons=["Yes", "No", "Cancel"], 1072 default=0, 1073 title="new data dialog").go() 1074 root.destroy() 1075 mol = None 1076 if ans == 0: 1077 from Pmv.guiTools import MoleculeChooser 1078 ans = MoleculeChooser(self.vf).go() 1079 if ans: 1080 mol = ans.name 1081 apply(self.doitWrapper, (file, mol), {})
1082
1083 - def doit(self, file, molname=None):
1084 global sl 1085 if not sl: 1086 sl = SLGeom() 1087 bspt_set = sl.readBspt(file) 1088 brep_set= sl.convert_to_Brep(bspt_set, expense=0.5, duplicate=1) 1089 verts, faces , vnorms,fnorms = sl.getBoundaries(brep_set, 1090 has_vnormals = 0, 1091 has_fnormals = 1) 1092 vs,fs,vns,fns = sl.indexedFromArr(verts, faces, fnorms=fnorms) 1093 #sl.discardSet(brep_set) 1094 #brep_set = None 1095 name = path.splitext(path.basename(file))[0] 1096 if find(name, "_"): #name should not contain "_" 1097 name = replace(name, "_", "-") 1098 if vs: 1099 ## length = map( len, fs) 1100 ## mlength = max(length) 1101 ## for i in range(len(fs)): 1102 ## d = mlength-len(fs[i]) 1103 ## if d: 1104 ## for j in range(d): 1105 ## fs[i].append(-1) 1106 ipg = IndexedPolygons(name, vertices = vs, 1107 faces = fs, 1108 visible=1, inheritMaterial=0, protected=True,) 1109 if self.vf.userpref['sharpColorBoundariesForMsms']['value'] == 'blur': 1110 ipg.Set( inheritSharpColorBoundaries=False, sharpColorBoundaries=False,) 1111 vi = self.vf.GUI.VIEWER 1112 cl_atoms = None 1113 if molname: 1114 cl_atoms = self.vf.bindGeomToMolecularFragment(ipg, molname) 1115 1116 else: 1117 vi.AddObject(ipg) 1118 ipg.Set(frontPolyMode=GL.GL_FILL, shading=GL.GL_FLAT) 1119 ipg.Set(fnormals = fns, tagModified=False) 1120 vi.Redraw() 1121 if molname and cl_atoms: 1122 self.vf.bindGeomToMolecularFragment.data[name]['fns']=fns 1123 self.vf.SL.setdict[ipg.fullName] = bspt_set 1124 else: 1125 print "vertices array length of converted brep set is 0"
1126
1127 - def __call__(self, file, molname=None, **kw):
1128 """ None <- RestoreBspt(file) 1129 file - a .bsp file""" 1130 if not hasattr(self.vf, "SL"): 1131 print "SLCommand is not loaded" 1132 return 1133 if not path.isfile(file): 1134 print "file %s does not exist" % (file,) 1135 return 1136 apply(self.doitWrapper, (file, molname), kw)
1137 1138 RestoreBsptGUI = CommandGUI() 1139 RestoreBsptGUI.addMenuCommand('menuRoot', 'SL','Restore Bspt', index = 3) 1140 1141 1142 if initCommand: 1143 commandList = [ 1144 {'name':'SL', 'cmd':SLCommand(),'gui': SLGUI}, 1145 {'name':'SaveBspt', 'cmd':SaveBsptCommand(),'gui': SaveBsptGUI}, 1146 {'name':'RestoreBspt', 'cmd':RestoreBsptCommand(), 'gui': RestoreBsptGUI},] 1147 else: 1148 commandList = [] 1149 1150
1151 -def initModule(viewer):
1152 if initCommand: 1153 for dict in commandList: 1154 viewer.addCommand(dict['cmd'], dict['name'], dict['gui'])
1155