]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wx/lib/vtk.py
Patch from Will Sadkin:
[wxWidgets.git] / wxPython / wx / lib / vtk.py
CommitLineData
d14a1e28
RD
1"""
2VTK is now including a package for using VTK with wxPython, so this
3module is now officially nothing but ancient history. If for some
4strange reason you really need this code (I don't know why, it didn't
5work all that well anyway,) then just remove the triple quotes below.
6I'm told that the module from Kitware is excellent and so you should
7really use it. See the URL below to get a copy from CVS.
1fded56b 8
d14a1e28
RD
9http://public.kitware.com/cgi-bin/cvsweb.cgi/VTK/Wrapping/Python/vtk/wx/
10"""
1fded56b 11
d14a1e28
RD
12print __doc__
13
14'''
15#----------------------------------------------------------------------
16# Name: wxPython.lib.vtk
17# Purpose: Provides a wrapper around the vtkRenderWindow from the
18# VTK Visualization Toolkit. Requires the VTK Python
19# extensions from http://www.kitware.com/
20#
21# Author: Robin Dunn
22#
23# Created: 16-Nov-1999
24# RCS-ID: $Id$
25# Copyright: (c) 1999 by Total Control Software
26# Licence: wxWindows license
27#----------------------------------------------------------------------
28
29# This class has been rewritten and improved by Prabhu Ramachandran
30# <prabhu@aero.iitm.ernet.in>. It has been tested under Win32 and
31# Linux. Many thanks to Eric Boix <frog@creatis.insa-lyon.fr> for
32# testing it under Windows and finding and fixing many errors.
33# Thanks also to Sebastien BARRE <sebastien@barre.nom.fr> for his
34# suggestions.
35
36
37try:
38 from vtkpython import *
39except ImportError:
40 raise ImportError, "VTK extension module not found"
41
42from wxPython.wx import *
43import math
44
45#----------------------------------------------------------------------
46
47DEBUG = 0
48
49def debug(msg):
50 if DEBUG:
51 print msg
52
53
54class wxVTKRenderWindowBase(wxWindow):
55 """
56 A base class that enables one to embed a vtkRenderWindow into
57 a wxPython widget. This class embeds the RenderWindow correctly
58 under different platforms. Provided are some empty methods that
59 can be overloaded to provide a user defined interaction behaviour.
60 The event handling functions have names that are similar to the
61 ones in the vtkInteractorStyle class included with VTK.
62 """
63
64 def __init__(self, parent, id, position=wxDefaultPosition,
65 size=wxDefaultSize, style=0):
66 wxWindow.__init__(self, parent, id, position, size, style | wxWANTS_CHARS)
67 self._RenderWindow = vtkRenderWindow()
68
69 self.__InExpose = 0
70 self.__Created = 0
71
72 if wxPlatform != '__WXMSW__':
73 # We can't get the handle in wxGTK until after the widget
74 # is created, the window create event happens later so we'll
75 # catch it there
76 EVT_WINDOW_CREATE(self, self.OnCreateWindow)
77 EVT_PAINT (self, self.OnExpose)
78 else:
79 # but in MSW, the window create event happens durring the above
80 # call to __init__ so we have to do it here.
81 hdl = self.GetHandle()
82 self._RenderWindow.SetWindowInfo(str(hdl))
83 EVT_PAINT (self, self.OnExpose)
84 self.__Created = 1
85
86 # common for all platforms
87 EVT_SIZE (self, self.OnConfigure)
88
89 # setup the user defined events.
90 self.SetupEvents()
91
92
93 def SetupEvents(self):
94 "Setup the user defined event bindings."
95 # Remember to bind everything to self.box and NOT self
96 EVT_LEFT_DOWN (self, self.OnLeftButtonDown)
97 EVT_MIDDLE_DOWN (self, self.OnMiddleButtonDown)
98 EVT_RIGHT_DOWN (self, self.OnRightButtonDown)
99 EVT_LEFT_UP (self, self.OnLeftButtonUp)
100 EVT_MIDDLE_UP (self, self.OnMiddleButtonUp)
101 EVT_RIGHT_UP (self, self.OnRightButtonUp)
102 EVT_MOTION (self, self.OnMouseMove)
103 EVT_ENTER_WINDOW (self, self.OnEnter)
104 EVT_LEAVE_WINDOW (self, self.OnLeave)
105 EVT_CHAR (self, self.OnChar)
106 # Add your bindings if you want them in the derived class.
107
108
109 def GetRenderer(self):
110 self._RenderWindow.GetRenderers().InitTraversal()
111 return self._RenderWindow.GetRenderers().GetNextItem()
112
113
114 def GetRenderWindow(self):
115 return self._RenderWindow
116
117
118 def Render(self):
119 if self.__Created:
120 # if block needed because calls to render before creation
121 # will prevent the renderwindow from being embedded into a
122 # wxPython widget.
123 self._RenderWindow.Render()
124
125
126 def OnExpose(self, event):
127 # I need this for the MDIDemo. Somehow OnCreateWindow was
128 # not getting called.
129 if not self.__Created:
130 self.OnCreateWindow(event)
131 if (not self.__InExpose):
132 self.__InExpose = 1
133 dc = wxPaintDC(self)
134 self._RenderWindow.Render()
135 self.__InExpose = 0
136
137
138 def OnCreateWindow(self, event):
139 hdl = self.GetHandle()
140 try:
141 self._RenderWindow.SetParentInfo(str(hdl))
142 except:
143 self._RenderWindow.SetWindowInfo(str(hdl))
144 msg = "Warning:\n "\
145 "Unable to call vtkRenderWindow.SetParentInfo\n\n"\
146 "Using the SetWindowInfo method instead. This\n"\
147 "is likely to cause a lot of flicker when\n"\
148 "rendering in the vtkRenderWindow. Please\n"\
149 "use a recent Nightly VTK release (later than\n"\
150 "March 10 2001) to eliminate this problem."
151 dlg = wxMessageDialog(NULL, msg, "Warning!",
152 wxOK |wxICON_INFORMATION)
153 dlg.ShowModal()
154 dlg.Destroy()
155 self.__Created = 1
156
157
158 def OnConfigure(self, event):
159 sz = self.GetSize()
160 self.SetSize(sz)
161 # Ugly hack that according to Eric Boix is necessary under
162 # Windows. If possible Try commenting this out and test under
163 # Windows.
164 #self._RenderWindow.GetSize()
165 #
166 self._RenderWindow.SetSize(sz.width, sz.height)
167
168
169 def OnLeftButtonDown(self, event):
170 "Left mouse button pressed."
171 pass
172
173
174 def OnMiddleButtonDown(self, event):
175 "Middle mouse button pressed."
176 pass
177
178
179 def OnRightButtonDown(self, event):
180 "Right mouse button pressed."
181 pass
182
183
184 def OnLeftButtonUp(self, event):
185 "Left mouse button released."
186 pass
187
188
189 def OnMiddleButtonUp(self, event):
190 "Middle mouse button released."
191 pass
192
193
194 def OnRightButtonUp(self, event):
195 "Right mouse button released."
196 pass
197
198
199 def OnMouseMove(self, event):
200 "Mouse has moved."
201 pass
202
203
204 def OnEnter(self, event):
205 "Entering the vtkRenderWindow."
206 pass
207
208
209 def OnLeave(self, event):
210 "Leaving the vtkRenderWindow."
211 pass
212
213
214 def OnChar(self, event):
215 "Process Key events."
216 pass
217
218
219 def OnKeyDown(self, event):
220 "Key pressed down."
221 pass
222
223
224 def OnKeyUp(self, event):
225 "Key released."
226 pass
227
228
229
230
231class wxVTKRenderWindow(wxVTKRenderWindowBase):
232 """
233 An example of a fully functional wxVTKRenderWindow that is
234 based on the vtkRenderWidget.py provided with the VTK sources.
235 """
236
237 def __init__(self, parent, id, position=wxDefaultPosition,
238 size=wxDefaultSize, style=0):
239 wxVTKRenderWindowBase.__init__(self, parent, id, position, size,
240 style)
241
242 self._CurrentRenderer = None
243 self._CurrentCamera = None
244 self._CurrentZoom = 1.0
245 self._CurrentLight = None
246
247 self._ViewportCenterX = 0
248 self._ViewportCenterY = 0
249
250 self._Picker = vtkCellPicker()
251 self._PickedAssembly = None
252 self._PickedProperty = vtkProperty()
253 self._PickedProperty.SetColor(1,0,0)
254 self._PrePickedProperty = None
255
256 self._OldFocus = None
257
258 # these record the previous mouse position
259 self._LastX = 0
260 self._LastY = 0
261
262
263 def OnLeftButtonDown(self, event):
264 "Left mouse button pressed."
265 self.StartMotion(event)
266
267
268 def OnMiddleButtonDown(self, event):
269 "Middle mouse button pressed."
270 self.StartMotion(event)
271
272
273 def OnRightButtonDown(self, event):
274 "Right mouse button pressed."
275 self.StartMotion(event)
276
277
278 def OnLeftButtonUp(self, event):
279 "Left mouse button released."
280 self.EndMotion(event)
281
282
283 def OnMiddleButtonUp(self, event):
284 "Middle mouse button released."
285 self.EndMotion(event)
286
287
288 def OnRightButtonUp(self, event):
289 "Right mouse button released."
290 self.EndMotion(event)
291
292
293 def OnMouseMove(self, event):
294 event.x, event.y = event.GetPositionTuple()
295 if event.LeftIsDown():
296 if event.ShiftDown():
297 self.Pan(event.x, event.y)
298 else:
299 self.Rotate(event.x, event.y)
300
301 elif event.MiddleIsDown():
302 self.Pan(event.x, event.y)
303
304 elif event.RightIsDown():
305 self.Zoom(event.x, event.y)
306
307
308 def OnEnter(self, event):
309 self.__OldFocus = wxWindow_FindFocus()
310 self.SetFocus()
311 x, y = event.GetPositionTuple()
312 self.UpdateRenderer(x,y)
313
314
315 def OnLeave(self, event):
316 if (self._OldFocus != None):
317 self.__OldFocus.SetFocus()
318
319
320 def OnChar(self, event):
321 key = event.KeyCode()
322 if (key == ord('r')) or (key == ord('R')):
323 self.Reset()
324 elif (key == ord('w')) or (key == ord('W')):
325 self.Wireframe()
326 elif (key == ord('s')) or (key == ord('S')):
327 self.Surface()
328 elif (key == ord('p')) or (key == ord('P')):
329 x, y = event.GetPositionTuple()
330 self.PickActor(x, y)
331 else:
332 event.Skip()
333
334
335 # Start of internal functions
336 def GetZoomFactor(self):
337 return self._CurrentZoom
338
339
340 def SetZoomFactor(self, zf):
341 self._CurrentZoom = zf
342
343
344 def GetPicker(self):
345 return self._Picker
346
347
348 def Render(self):
349 if (self._CurrentLight):
350 light = self._CurrentLight
351 light.SetPosition(self._CurrentCamera.GetPosition())
352 light.SetFocalPoint(self._CurrentCamera.GetFocalPoint())
353
354 wxVTKRenderWindowBase.Render(self)
355
356
357 def UpdateRenderer(self, x, y):
358 """
359 UpdateRenderer will identify the renderer under the mouse and set
360 up _CurrentRenderer, _CurrentCamera, and _CurrentLight.
361 """
362 sz = self.GetSize()
363 windowX = sz.width
364 windowY = sz.height
365
366 renderers = self._RenderWindow.GetRenderers()
367 numRenderers = renderers.GetNumberOfItems()
368
369 self._CurrentRenderer = None
370 renderers.InitTraversal()
371 for i in range(0,numRenderers):
372 renderer = renderers.GetNextItem()
373 vx,vy = (0,0)
374 if (windowX > 1):
375 vx = float (x)/(windowX-1)
376 if (windowY > 1):
377 vy = (windowY-float(y)-1)/(windowY-1)
378 (vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport()
379
380 if (vx >= vpxmin and vx <= vpxmax and
381 vy >= vpymin and vy <= vpymax):
382 self._CurrentRenderer = renderer
383 self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\
384 +vpxmin
385 self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\
386 +vpymin
387 self._CurrentCamera = self._CurrentRenderer.GetActiveCamera()
388 lights = self._CurrentRenderer.GetLights()
389 lights.InitTraversal()
390 self._CurrentLight = lights.GetNextItem()
391 break
392
393 self._LastX = x
394 self._LastY = y
395
396
397 def GetCurrentRenderer(self):
398 return self._CurrentRenderer
399
400
401 def StartMotion(self, event):
402 x, y = event.GetPositionTuple()
403 self.UpdateRenderer(x,y)
404 self.CaptureMouse()
405
406
407 def EndMotion(self, event=None):
408 if self._CurrentRenderer:
409 self.Render()
410 self.ReleaseMouse()
411
412
413 def Rotate(self,x,y):
414 if self._CurrentRenderer:
415
416 self._CurrentCamera.Azimuth(self._LastX - x)
417 self._CurrentCamera.Elevation(y - self._LastY)
418 self._CurrentCamera.OrthogonalizeViewUp()
419
420 self._LastX = x
421 self._LastY = y
422
423 self._CurrentRenderer.ResetCameraClippingRange()
424 self.Render()
425
426
427 def PanAbsolute(self, x_vec, y_vec):
428 if self._CurrentRenderer:
429
430 renderer = self._CurrentRenderer
431 camera = self._CurrentCamera
432 (pPoint0,pPoint1,pPoint2) = camera.GetPosition()
433 (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint()
434
435 if (camera.GetParallelProjection()):
436 renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0)
437 renderer.WorldToDisplay()
438 fx,fy,fz = renderer.GetDisplayPoint()
439 renderer.SetDisplayPoint(fx+x_vec,
440 fy+y_vec,
441 fz)
442 renderer.DisplayToWorld()
443 fx,fy,fz,fw = renderer.GetWorldPoint()
444 camera.SetFocalPoint(fx,fy,fz)
445
446 renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0)
447 renderer.WorldToDisplay()
448 fx,fy,fz = renderer.GetDisplayPoint()
449 renderer.SetDisplayPoint(fx+x_vec,
450 fy+y_vec,
451 fz)
452 renderer.DisplayToWorld()
453 fx,fy,fz,fw = renderer.GetWorldPoint()
454 camera.SetPosition(fx,fy,fz)
455
456 else:
457 (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint()
458 # Specify a point location in world coordinates
459 renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0)
460 renderer.WorldToDisplay()
461 # Convert world point coordinates to display coordinates
462 dPoint = renderer.GetDisplayPoint()
463 focalDepth = dPoint[2]
464
465 aPoint0 = self._ViewportCenterX + x_vec
466 aPoint1 = self._ViewportCenterY + y_vec
467
468 renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth)
469 renderer.DisplayToWorld()
470
471 (rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint()
472 if (rPoint3 != 0.0):
473 rPoint0 = rPoint0/rPoint3
474 rPoint1 = rPoint1/rPoint3
475 rPoint2 = rPoint2/rPoint3
476
477 camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0,
478 (fPoint1 - rPoint1) + fPoint1,
479 (fPoint2 - rPoint2) + fPoint2)
480
481 camera.SetPosition((fPoint0 - rPoint0) + pPoint0,
482 (fPoint1 - rPoint1) + pPoint1,
483 (fPoint2 - rPoint2) + pPoint2)
484
485 self.Render()
486
487
488 def Pan(self, x, y):
489 self.PanAbsolute(x - self._LastX, - y + self._LastY)
490 self._LastX = x
491 self._LastY = y
492
493
494 def Zoom(self,x,y):
495 if self._CurrentRenderer:
496
497 renderer = self._CurrentRenderer
498 camera = self._CurrentCamera
499
500 zoomFactor = math.pow(1.02,(0.5*(self._LastY - y)))
501 self._CurrentZoom = self._CurrentZoom * zoomFactor
502
503 if camera.GetParallelProjection():
504 parallelScale = camera.GetParallelScale()/zoomFactor
505 camera.SetParallelScale(parallelScale)
506 else:
507 camera.Dolly(zoomFactor)
508 renderer.ResetCameraClippingRange()
509
510 self._LastX = x
511 self._LastY = y
512
513 self.Render()
514
515
516 def Reset(self):
517 if self._CurrentRenderer:
518 self._CurrentRenderer.ResetCamera()
519
520 self.Render()
521
522
523 def Wireframe(self):
524 actors = self._CurrentRenderer.GetActors()
525 numActors = actors.GetNumberOfItems()
526 actors.InitTraversal()
527 for i in range(0,numActors):
528 actor = actors.GetNextItem()
529 actor.GetProperty().SetRepresentationToWireframe()
530
531 self.Render()
532
533
534 def Surface(self):
535 actors = self._CurrentRenderer.GetActors()
536 numActors = actors.GetNumberOfItems()
537 actors.InitTraversal()
538 for i in range(0,numActors):
539 actor = actors.GetNextItem()
540 actor.GetProperty().SetRepresentationToSurface()
541
542 self.Render()
543
544
545 def PickActor(self,x,y):
546 if self._CurrentRenderer:
547 renderer = self._CurrentRenderer
548 picker = self._Picker
549
550 windowY = self.GetSize().height
551 picker.Pick(x,(windowY - y - 1),0.0,renderer)
552 assembly = picker.GetAssembly()
553
554 if (self._PickedAssembly != None and
555 self._PrePickedProperty != None):
556 self._PickedAssembly.SetProperty(self._PrePickedProperty)
557 # release hold of the property
558 self._PrePickedProperty.UnRegister(self._PrePickedProperty)
559 self._PrePickedProperty = None
560
561 if (assembly != None):
562 self._PickedAssembly = assembly
563 self._PrePickedProperty = self._PickedAssembly.GetProperty()
564 # hold onto the property
565 self._PrePickedProperty.Register(self._PrePickedProperty)
566 self._PickedAssembly.SetProperty(self._PickedProperty)
567
568 self.Render()
569'''