OpenStructure
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
__init__.py
Go to the documentation of this file.
1 #------------------------------------------------------------------------------
2 # This file is part of the OpenStructure project <www.openstructure.org>
3 #
4 # Copyright (C) 2008-2011 by the OpenStructure authors
5 #
6 # This library is free software; you can redistribute it and/or modify it under
7 # the terms of the GNU Lesser General Public License as published by the Free
8 # Software Foundation; either version 3.0 of the License, or (at your option)
9 # any later version.
10 # This library is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this library; if not, write to the Free Software Foundation, Inc.,
17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #------------------------------------------------------------------------------
19 from _ost_gfx import *
20 from py_gfx_obj import PyGfxObj
21 
22 WHITE=Color(1.0,1.0,1.0)
23 BLACK=Color(0.0,0.0,0.0)
24 GREY=Color(0.5,0.5,0.5)
25 RED=Color(1.0,0.0,0.0)
26 DARKRED=Color(0.5,0.0,0.0)
27 LIGHTRED=Color(1.0,0.5,0.5)
28 GREEN=Color(0.0,1.0,0.0)
29 DARKGREEN=Color(0.0,0.5,0.0)
30 LIGHTGREEN=Color(0.5,1.0,0.5)
31 BLUE=Color(0.0,0.0,1.0)
32 DARKBLUE=Color(0.0,0.0,0.5)
33 LIGHTBLUE=Color(0.5,0.5,1.0)
34 YELLOW=Color(1.0,1.0,0.0)
35 DARKYELLOW=Color(0.5,0.5,0.0)
36 LIGHTYELLOW=Color(1.0,1.0,0.5)
37 CYAN=Color(0.0,1.0,1.0)
38 DARKCYAN=Color(0.0,0.5,0.5)
39 LIGHTCYAN=Color(0.5,1.0,1.0)
40 MAGENTA=Color(1.0,0.0,1.0)
41 DARKMAGENTA=Color(0.5,0.0,0.5)
42 LIGHTMAGENTA=Color(1.0,0.5,1.0)
43 PURPLE=MAGENTA
44 DARKPURPLE=DARKMAGENTA
45 LIGHTPURPLE=LIGHTMAGENTA
46 ORANGE=Color(1.0,0.5,0.0)
47 DARKORANGE=Color(0.5,0.25,0.0)
48 LIGHTORANGE=Color(1.0,0.75,0.5)
49 
50 
51 def Stereo(mode,flip=None,alg=None):
52  """
53  Stereo control
54 
55  :param mode: 0=off, 1=quad-buffered, 2=interlaced
56  :type mode: int
57  :param flip: invert order of left/right display
58  :type flip: bool
59  :param alg: stereo algorithm (0 or 1)
60  :type param: int
61  """
62  if(flip):
63  Scene().SetStereoFlip(flip)
64  if(alg):
65  Scene().SetStereoAlg(alg)
66 
67  Scene().SetStereoMode(mode)
68 
69 def FitToScreen(gfx_ent, width=None, height=None, margin=0.05):
70  """
71  Setup camera such that it is centered on the graphical entity and the entity
72  fits the entire viewport. The longest axes of the entity are aligned along
73  the x- and y- axes of the screen.
74 
75  :param gfx_ent: The graphical entity
76  :type gfx_ent: str or :class:`Entity`
77 
78 
79  """
80  from ost import geom
81  import math
82  def _XYZ(view, axes):
83  """
84  returns the vectors in x, y and z direction respectively. The smallest
85  vector is in z, then y, and the largest along x.
86  """
87  rows=[axes.GetRow(i) for i in range(3)]
88  lengths=[]
89  for axe in rows:
90  min_proj=geom.Dot(axe, view.atoms[0].pos)
91  max_proj=min_proj
92  for atom in view.atoms[1:]:
93  proj=geom.Dot(axe, atom.pos)
94  min_proj=min(proj, min_proj)
95  max_proj=max(proj, max_proj)
96  lengths.append(max_proj-min_proj)
97  def cmp_x(rhs, lhs):
98  return cmp(lhs[1], rhs[1])
99  sorted_axes=sorted(zip(rows, lengths), cmp_x)
100  return [r*l for r,l in sorted_axes]
101  scene=Scene()
102  if not isinstance(gfx_ent, Entity):
103  gfx_ent=scene[str(gfx_ent)]
104  width=width and width or scene.viewport.width
105  height=height and height or scene.viewport.height
106  atom_positions=geom.Vec3List([atom.pos for atom in gfx_ent.view.atoms])
107  axes=atom_positions.principal_axes
108  sorted_axes=_XYZ(gfx_ent.view, axes)
109  x_bigger_than_y=geom.Length(sorted_axes[0])>geom.Length(sorted_axes[1])
110  if x_bigger_than_y:
111  if width>height:
112  x_axes=geom.Normalize(sorted_axes[0])
113  y_axes=geom.Normalize(sorted_axes[1])
114  else:
115  x_axes=geom.Normalize(sorted_axes[1])
116  y_axes=geom.Normalize(sorted_axes[0])
117  else:
118  if width>height:
119  x_axes=geom.Normalize(sorted_axes[1])
120  y_axes=geom.Normalize(sorted_axes[0])
121  else:
122  x_axes=geom.Normalize(sorted_axes[0])
123  y_axes=geom.Normalize(sorted_axes[1])
124  z_axes=geom.Normalize(geom.Cross(x_axes, y_axes))
125  rotation=geom.Mat3(x_axes[0], x_axes[1], x_axes[2],
126  y_axes[0], y_axes[1], y_axes[2],
127  z_axes[0], z_axes[1], z_axes[2])
128  rtc=geom.Mat4(rotation)
129 
130  center=gfx_ent.center
131  aspect=float(width)/float(height)
132  factor_y=1.0/math.tan(math.radians(scene.fov))
133  factor_x=factor_y/aspect
134  z_off=geom.Length(sorted_axes[2])*0.5
135  rtc[0,3]=center[0]
136  rtc[1,3]=center[1]
137  rtc[2,3]=center[2]
138  rtc[3,0]=0
139  rtc[3,1]=0
140  rtc[3,2]=-(max(factor_x*(1+margin)*geom.Length(sorted_axes[0]),
141  factor_y*(1+margin)*geom.Length(sorted_axes[1]))+z_off)
142  scene.SetRTC(rtc)
143 
144 
146  def __init__(self, node_list, name):
147  self._node_list=node_list
148  self._name=name
149 
150  def __iter__(self):
151  for node in self._node_list:
152  yield getattr(node, self._name)
153 
154  def __call__(self, *args, **kwargs):
155  for node in self._node_list:
156  bound_method=getattr(node, self._name)
157  bound_method(*args, **kwargs)
158 
159 class GfxNodeListProxy(object):
160  def __init__(self, node_list):
161  self._nodes=node_list
162 
163  def __getattr__(self, name):
164  if name.startswith('_'):
165  return super(GfxNodeListProxy, self).__getattr__(name)
166  return GfxNodeListAttrProxy(self._nodes, name)
167 
168  def __setattr__(self, name, value):
169  if name.startswith('_'):
170  super(GfxNodeListProxy, self).__setattr__(name, value)
171  for node in self._nodes:
172  setattr(node, name, value)
173 
174 def _Match(scene, pattern="*"):
175  import os
176  import fnmatch
177  def _Recurse(path, node, pattern):
178  matches=[]
179  for child in node.children:
180  full_name=os.path.join(path, child.name)
181  if fnmatch.fnmatchcase(full_name, pattern):
182  matches.append(child)
183  matches.extend(_Recurse(full_name, child, pattern))
184  return matches
185  return GfxNodeListProxy(_Recurse("", Scene().root_node, pattern))
186 
187 SceneSingleton.Match=_Match
188 
189 def _to_vec3(p):
190  import ost.geom
191  if isinstance(p,ost.geom.Vec3):
192  return p
193  else:
194  try:
195  return ost.geom.Vec3(p[0],p[1],p[2])
196  except:
197  raise TypeError("expected either a sequence or a geom.Vec3 object")
198 
199 
200 def _primlist_add_point(self,pos,color=None):
201  pos=_to_vec3(pos)
202  if not color:
203  color=WHITE
204  self._add_point(pos,color)
205 
206 def _primlist_add_line(self,pos1,pos2,color1=None,color2=None,color=None):
207  pos1=_to_vec3(pos1)
208  pos2=_to_vec3(pos2)
209  if not color:
210  color=WHITE
211  if not color1:
212  color1=color
213  if not color2:
214  color2=color1
215  self._add_line(pos1,pos2,color1,color2)
216 
217 def _primlist_add_sphere(self,cen,radius=1.0,color=None):
218  pos=_to_vec3(cen)
219  if not color:
220  color=WHITE
221  self._add_sphere(pos,radius,color)
222 
223 def _primlist_add_cyl(self,pos1,pos2,radius1=None,radius2=None,radius=None,color1=None,color2=None,color=None,):
224  pos1=_to_vec3(pos1)
225  pos2=_to_vec3(pos2)
226  if radius is None:
227  radius=1.0
228  if radius1 is None:
229  radius1=radius
230  if radius2 is None:
231  radius2=radius1
232  if not color:
233  color=WHITE
234  if not color1:
235  color1=color
236  if not color2:
237  color2=color1
238  self._add_cyl(pos1,pos2,radius1,radius2,color1,color2)
239 
240 def _primlist_add_text(self,text,pos,color=None,point_size=None):
241  pos=_to_vec3(pos)
242  if not color:
243  color=WHITE
244  if not point_size:
245  point_size=1.0
246  self._add_text(text,pos,color,point_size)
247 
248 PrimList.AddPoint=_primlist_add_point
249 PrimList.AddLine=_primlist_add_line
250 PrimList.AddSphere=_primlist_add_sphere
251 PrimList.AddCyl=_primlist_add_cyl
252 PrimList.AddText=_primlist_add_text
253 
254 # entity reset
255 
256 def _entity_reset(self,*args,**kwargs):
257  import ost.mol as mol
258  eh=None
259  ev=None
260  qr=None
261  qf=None
262  for a in args:
263  if isinstance(a,mol.Query):
264  if qr:
265  raise TypeError("Reset: more than one query string given")
266  qr=a
267  elif isinstance(a,mol.EntityHandle):
268  if eh:
269  raise TypeError("Reset: more than one entity handle given")
270  eh=a
271  elif isinstance(a,mol.EntityView):
272  if ev:
273  raise TypeError("Reset: more than one entity view given")
274  ev=a
275  elif isinstance(a,str):
276  if qr:
277  raise TypeError("Reset: more than one query string given")
278  qr=mol.Query(a)
279  elif isinstance(a,int):
280  if qf:
281  raise TypeError("Reset: more than one QueryFlags given")
282  qf=a
283  else:
284  raise TypeError("Reset: unknown option of type '%s' given"%type(a))
285 
286  for key,val in kwargs.iteritems():
287  if key=="entity":
288  if not isinstance(val,mol.EntityHandle):
289  raise TypeError("Reset: expected mol.EntityHandle for 'entity' option")
290  if eh:
291  raise TypeError("Reset: more than one entity handle given")
292  eh=val
293  elif key=="view":
294  if not isinstance(val,mol.EntityView):
295  raise TypeError("Reset: expected mol.EntityView for 'view' option")
296  if ev:
297  raise TypeError("Reset: more than one entity view given")
298  ev=val
299  elif key=="query":
300  if isinstance(val,mol.Query):
301  pass
302  elif isinstance(val,str):
303  val=mol.Query(val)
304  else:
305  raise TypeError("Reset: expected mol.Query or string for 'query' option")
306  if qr:
307  raise TypeError("Reset: more than one query string given")
308  qr=val
309  elif key=="query_flags":
310  if not isinstance(val,int):
311  raise TypeError("Reset: expected integer for 'query_flags' option")
312  if qf:
313  raise TypeError("Reset: more than one query flags given")
314  qf=val
315  else:
316  raise TypeError("Reset: unknown key '%s'"%key)
317 
318  if eh and ev:
319  raise TypeError("Reset: entity and view are mutually exclusive options")
320 
321  if ev:
322  self._reset4(ev)
323  else:
324  if not eh:
325  eh = self.query_view.entity
326  if not qr:
327  qr = self.query_view.query
328  if not qf:
329  qf = self.query_view.GetFlags()
330  self._reset3(eh,qr,qf)
331 
332 Entity.Reset=_entity_reset