]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wxPython/lib/vtk.py
229c087be1958470b808ab097e0af796726c2e1f
1 #----------------------------------------------------------------------
2 # Name: wxPython.lib.vtk
3 # Purpose: Provides a wrapper around the vtkRenderWindow from the
4 # VTK Visualization Toolkit. Requires the VTK Python
5 # extensions from http://www.kitware.com/
11 # Copyright: (c) 1999 by Total Control Software
12 # Licence: wxWindows license
13 #----------------------------------------------------------------------
15 # This class has been rewritten and improved by Prabhu Ramachandran
16 # <prabhu@aero.iitm.ernet.in>. It has been tested under Win32 and
17 # Linux. Many thanks to Eric Boix <frog@creatis.insa-lyon.fr> for
18 # testing it under Windows(TM) and finding and fixing many errors.
19 # Thanks also to Sebastien BARRE <sebastien@barre.nom.fr> for his
24 from vtkpython
import *
26 raise ImportError, "VTK extension module not found"
28 from wxPython
.wx
import *
31 #----------------------------------------------------------------------
40 class wxVTKRenderWindowBase(wxScrolledWindow
):
42 A base class that enables one to embed a vtkRenderWindow into
43 a wxPython widget. This class embeds the RenderWindow correctly
44 under different platforms. Provided are some empty methods that
45 can be overloaded to provide a user defined interaction behaviour.
46 The event handling functions have names that are similar to the
47 ones in the vtkInteractorStyle class included with VTK.
50 def __init__(self
, parent
, id, position
=wxDefaultPosition
,
51 size
=wxDefaultSize
, style
=0):
52 wxScrolledWindow
.__init
__(self
, parent
, id, position
, size
, style
)
53 style
= style | wxWANTS_CHARS
55 # This box is necessary to eliminate flicker and enable proper
56 # event handling under Linux/GTK.
57 self
.box
= wxPanel(self
, -1, position
, size
, style
)
59 self
._RenderWindow
= vtkRenderWindow()
64 if wxPlatform
!= '__WXMSW__':
65 # We can't get the handle in wxGTK until after the widget
66 # is created, the window create event happens later so we'll
68 EVT_WINDOW_CREATE(self
.box
, self
.OnCreateWindow
)
69 EVT_PAINT (self
, self
.OnExpose
)
71 # but in MSW, the window create event happens durring the above
72 # call to __init__ so we have to do it here.
73 hdl
= self
.box
.GetHandle()
74 self
._RenderWindow
.SetWindowInfo(str(hdl
))
75 EVT_PAINT (self
.box
, self
.OnExpose
)
78 # common for all platforms
79 EVT_SIZE (self
, self
.OnConfigure
)
81 # setup the user defined events.
85 def SetupEvents(self
):
86 "Setup the user defined event bindings."
87 # Remember to bind everything to self.box and NOT self
88 EVT_LEFT_DOWN (self
.box
, self
.OnLeftButtonDown
)
89 EVT_MIDDLE_DOWN (self
.box
, self
.OnMiddleButtonDown
)
90 EVT_RIGHT_DOWN (self
.box
, self
.OnRightButtonDown
)
91 EVT_LEFT_UP (self
.box
, self
.OnLeftButtonUp
)
92 EVT_MIDDLE_UP (self
.box
, self
.OnMiddleButtonUp
)
93 EVT_RIGHT_UP (self
.box
, self
.OnRightButtonUp
)
94 EVT_MOTION (self
.box
, self
.OnMouseMove
)
95 EVT_ENTER_WINDOW (self
.box
, self
.OnEnter
)
96 EVT_LEAVE_WINDOW (self
.box
, self
.OnLeave
)
97 EVT_CHAR (self
.box
, self
.OnChar
)
98 # Add your bindings if you want them in the derived class.
101 def GetRenderer(self
):
102 self
._RenderWindow
.GetRenderers().InitTraversal()
103 return self
._RenderWindow
.GetRenderers().GetNextItem()
106 def GetRenderWindow(self
):
107 return self
._RenderWindow
112 # if block needed because calls to render before creation
113 # will prevent the renderwindow from being embedded into a
115 self
._RenderWindow
.Render()
118 def OnExpose(self
, event
):
119 # I need this for the MDIDemo. Somehow OnCreateWindow was
120 # not getting called.
121 if not self
.__Created
:
122 self
.OnCreateWindow(event
)
123 if (not self
.__InExpose
):
125 dc
= wxPaintDC(self
.box
)
126 self
._RenderWindow
.Render()
130 def OnCreateWindow(self
, event
):
131 hdl
= self
.box
.GetHandle()
133 self
._RenderWindow
.SetParentInfo(str(hdl
))
135 self
._RenderWindow
.SetWindowInfo(str(hdl
))
137 "Unable to call vtkRenderWindow.SetParentInfo\n\n"\
138 "Using the SetWindowInfo method instead. This\n"\
139 "is likely to cause a lot of flicker when\n"\
140 "rendering in the vtkRenderWindow. Please\n"\
141 "use a recent Nightly VTK release (later than\n"\
142 "March 10 2001) to eliminate this problem."
143 dlg
= wxMessageDialog(NULL
, msg
, "Warning!",
144 wxOK |wxICON_INFORMATION
)
150 def OnConfigure(self
, event
):
153 # Ugly hack that according to Eric Boix is necessary under
154 # Windows. If possible Try commenting this out and test under
156 #self._RenderWindow.GetSize()
158 self
._RenderWindow
.SetSize(sz
.width
, sz
.height
)
161 def OnLeftButtonDown(self
, event
):
162 "Left mouse button pressed."
166 def OnMiddleButtonDown(self
, event
):
167 "Middle mouse button pressed."
171 def OnRightButtonDown(self
, event
):
172 "Right mouse button pressed."
176 def OnLeftButtonUp(self
, event
):
177 "Left mouse button released."
181 def OnMiddleButtonUp(self
, event
):
182 "Middle mouse button released."
186 def OnRightButtonUp(self
, event
):
187 "Right mouse button released."
191 def OnMouseMove(self
, event
):
196 def OnEnter(self
, event
):
197 "Entering the vtkRenderWindow."
201 def OnLeave(self
, event
):
202 "Leaving the vtkRenderWindow."
206 def OnChar(self
, event
):
207 "Process Key events."
211 def OnKeyDown(self
, event
):
216 def OnKeyUp(self
, event
):
223 class wxVTKRenderWindow(wxVTKRenderWindowBase
):
225 An example of a fully functional wxVTKRenderWindow that is
226 based on the vtkRenderWidget.py provided with the VTK sources.
229 def __init__(self
, parent
, id, position
=wxDefaultPosition
,
230 size
=wxDefaultSize
, style
=0):
231 wxVTKRenderWindowBase
.__init
__(self
, parent
, id, position
, size
,
234 self
._CurrentRenderer
= None
235 self
._CurrentCamera
= None
236 self
._CurrentZoom
= 1.0
237 self
._CurrentLight
= None
239 self
._ViewportCenterX
= 0
240 self
._ViewportCenterY
= 0
242 self
._Picker
= vtkCellPicker()
243 self
._PickedAssembly
= None
244 self
._PickedProperty
= vtkProperty()
245 self
._PickedProperty
.SetColor(1,0,0)
246 self
._PrePickedProperty
= None
248 self
._OldFocus
= None
250 # these record the previous mouse position
255 def OnLeftButtonDown(self
, event
):
256 "Left mouse button pressed."
257 self
.StartMotion(event
)
260 def OnMiddleButtonDown(self
, event
):
261 "Middle mouse button pressed."
262 self
.StartMotion(event
)
265 def OnRightButtonDown(self
, event
):
266 "Right mouse button pressed."
267 self
.StartMotion(event
)
270 def OnLeftButtonUp(self
, event
):
271 "Left mouse button released."
272 self
.EndMotion(event
)
275 def OnMiddleButtonUp(self
, event
):
276 "Middle mouse button released."
277 self
.EndMotion(event
)
280 def OnRightButtonUp(self
, event
):
281 "Right mouse button released."
282 self
.EndMotion(event
)
285 def OnMouseMove(self
, event
):
286 event
.x
, event
.y
= event
.GetPositionTuple()
287 if event
.LeftIsDown():
288 if event
.ShiftDown():
289 self
.Pan(event
.x
, event
.y
)
291 self
.Rotate(event
.x
, event
.y
)
293 elif event
.MiddleIsDown():
294 self
.Pan(event
.x
, event
.y
)
296 elif event
.RightIsDown():
297 self
.Zoom(event
.x
, event
.y
)
300 def OnEnter(self
, event
):
301 self
.__OldFocus
= wxWindow_FindFocus()
303 x
, y
= event
.GetPositionTuple()
304 self
.UpdateRenderer(x
,y
)
307 def OnLeave(self
, event
):
308 if (self
._OldFocus
!= None):
309 self
.__OldFocus
.SetFocus()
312 def OnChar(self
, event
):
313 key
= event
.KeyCode()
314 if (key
== ord('r')) or (key
== ord('R')):
316 elif (key
== ord('w')) or (key
== ord('W')):
318 elif (key
== ord('s')) or (key
== ord('S')):
320 elif (key
== ord('p')) or (key
== ord('P')):
321 x
, y
= event
.GetPositionTuple()
327 # Start of internal functions
328 def GetZoomFactor(self
):
329 return self
._CurrentZoom
332 def SetZoomFactor(self
, zf
):
333 self
._CurrentZoom
= zf
341 if (self
._CurrentLight
):
342 light
= self
._CurrentLight
343 light
.SetPosition(self
._CurrentCamera
.GetPosition())
344 light
.SetFocalPoint(self
._CurrentCamera
.GetFocalPoint())
346 wxVTKRenderWindowBase
.Render(self
)
349 def UpdateRenderer(self
, x
, y
):
351 UpdateRenderer will identify the renderer under the mouse and set
352 up _CurrentRenderer, _CurrentCamera, and _CurrentLight.
358 renderers
= self
._RenderWindow
.GetRenderers()
359 numRenderers
= renderers
.GetNumberOfItems()
361 self
._CurrentRenderer
= None
362 renderers
.InitTraversal()
363 for i
in range(0,numRenderers
):
364 renderer
= renderers
.GetNextItem()
367 vx
= float (x
)/(windowX
-1)
369 vy
= (windowY
-float(y
)-1)/(windowY
-1)
370 (vpxmin
,vpymin
,vpxmax
,vpymax
) = renderer
.GetViewport()
372 if (vx
>= vpxmin
and vx
<= vpxmax
and
373 vy
>= vpymin
and vy
<= vpymax
):
374 self
._CurrentRenderer
= renderer
375 self
._ViewportCenterX
= float(windowX
)*(vpxmax
-vpxmin
)/2.0\
377 self
._ViewportCenterY
= float(windowY
)*(vpymax
-vpymin
)/2.0\
379 self
._CurrentCamera
= self
._CurrentRenderer
.GetActiveCamera()
380 lights
= self
._CurrentRenderer
.GetLights()
381 lights
.InitTraversal()
382 self
._CurrentLight
= lights
.GetNextItem()
389 def GetCurrentRenderer(self
):
390 return self
._CurrentRenderer
393 def StartMotion(self
, event
):
394 x
, y
= event
.GetPositionTuple()
395 self
.UpdateRenderer(x
,y
)
396 self
.box
.CaptureMouse()
399 def EndMotion(self
, event
=None):
400 if self
._CurrentRenderer
:
402 self
.box
.ReleaseMouse()
405 def Rotate(self
,x
,y
):
406 if self
._CurrentRenderer
:
408 self
._CurrentCamera
.Azimuth(self
._LastX
- x
)
409 self
._CurrentCamera
.Elevation(y
- self
._LastY
)
410 self
._CurrentCamera
.OrthogonalizeViewUp()
415 self
._CurrentRenderer
.ResetCameraClippingRange()
419 def PanAbsolute(self
, x_vec
, y_vec
):
420 if self
._CurrentRenderer
:
422 renderer
= self
._CurrentRenderer
423 camera
= self
._CurrentCamera
424 (pPoint0
,pPoint1
,pPoint2
) = camera
.GetPosition()
425 (fPoint0
,fPoint1
,fPoint2
) = camera
.GetFocalPoint()
427 if (camera
.GetParallelProjection()):
428 renderer
.SetWorldPoint(fPoint0
,fPoint1
,fPoint2
,1.0)
429 renderer
.WorldToDisplay()
430 fx
,fy
,fz
= renderer
.GetDisplayPoint()
431 renderer
.SetDisplayPoint(fx
+x_vec
,
434 renderer
.DisplayToWorld()
435 fx
,fy
,fz
,fw
= renderer
.GetWorldPoint()
436 camera
.SetFocalPoint(fx
,fy
,fz
)
438 renderer
.SetWorldPoint(pPoint0
,pPoint1
,pPoint2
,1.0)
439 renderer
.WorldToDisplay()
440 fx
,fy
,fz
= renderer
.GetDisplayPoint()
441 renderer
.SetDisplayPoint(fx
+x_vec
,
444 renderer
.DisplayToWorld()
445 fx
,fy
,fz
,fw
= renderer
.GetWorldPoint()
446 camera
.SetPosition(fx
,fy
,fz
)
449 (fPoint0
,fPoint1
,fPoint2
) = camera
.GetFocalPoint()
450 # Specify a point location in world coordinates
451 renderer
.SetWorldPoint(fPoint0
,fPoint1
,fPoint2
,1.0)
452 renderer
.WorldToDisplay()
453 # Convert world point coordinates to display coordinates
454 dPoint
= renderer
.GetDisplayPoint()
455 focalDepth
= dPoint
[2]
457 aPoint0
= self
._ViewportCenterX
+ x_vec
458 aPoint1
= self
._ViewportCenterY
+ y_vec
460 renderer
.SetDisplayPoint(aPoint0
,aPoint1
,focalDepth
)
461 renderer
.DisplayToWorld()
463 (rPoint0
,rPoint1
,rPoint2
,rPoint3
) = renderer
.GetWorldPoint()
465 rPoint0
= rPoint0
/rPoint3
466 rPoint1
= rPoint1
/rPoint3
467 rPoint2
= rPoint2
/rPoint3
469 camera
.SetFocalPoint((fPoint0
- rPoint0
) + fPoint0
,
470 (fPoint1
- rPoint1
) + fPoint1
,
471 (fPoint2
- rPoint2
) + fPoint2
)
473 camera
.SetPosition((fPoint0
- rPoint0
) + pPoint0
,
474 (fPoint1
- rPoint1
) + pPoint1
,
475 (fPoint2
- rPoint2
) + pPoint2
)
481 self
.PanAbsolute(x
- self
._LastX
, - y
+ self
._LastY
)
487 if self
._CurrentRenderer
:
489 renderer
= self
._CurrentRenderer
490 camera
= self
._CurrentCamera
492 zoomFactor
= math
.pow(1.02,(0.5*(self
._LastY
- y
)))
493 self
._CurrentZoom
= self
._CurrentZoom
* zoomFactor
495 if camera
.GetParallelProjection():
496 parallelScale
= camera
.GetParallelScale()/zoomFactor
497 camera
.SetParallelScale(parallelScale
)
499 camera
.Dolly(zoomFactor
)
500 renderer
.ResetCameraClippingRange()
509 if self
._CurrentRenderer
:
510 self
._CurrentRenderer
.ResetCamera()
516 actors
= self
._CurrentRenderer
.GetActors()
517 numActors
= actors
.GetNumberOfItems()
518 actors
.InitTraversal()
519 for i
in range(0,numActors
):
520 actor
= actors
.GetNextItem()
521 actor
.GetProperty().SetRepresentationToWireframe()
527 actors
= self
._CurrentRenderer
.GetActors()
528 numActors
= actors
.GetNumberOfItems()
529 actors
.InitTraversal()
530 for i
in range(0,numActors
):
531 actor
= actors
.GetNextItem()
532 actor
.GetProperty().SetRepresentationToSurface()
537 def PickActor(self
,x
,y
):
538 if self
._CurrentRenderer
:
539 renderer
= self
._CurrentRenderer
540 picker
= self
._Picker
542 windowY
= self
.GetSize().height
543 picker
.Pick(x
,(windowY
- y
- 1),0.0,renderer
)
544 assembly
= picker
.GetAssembly()
546 if (self
._PickedAssembly
!= None and
547 self
._PrePickedProperty
!= None):
548 self
._PickedAssembly
.SetProperty(self
._PrePickedProperty
)
549 # release hold of the property
550 self
._PrePickedProperty
.UnRegister(self
._PrePickedProperty
)
551 self
._PrePickedProperty
= None
553 if (assembly
!= None):
554 self
._PickedAssembly
= assembly
555 self
._PrePickedProperty
= self
._PickedAssembly
.GetProperty()
556 # hold onto the property
557 self
._PrePickedProperty
.Register(self
._PrePickedProperty
)
558 self
._PickedAssembly
.SetProperty(self
._PickedProperty
)