776 lines
23 KiB
Python
776 lines
23 KiB
Python
"""
|
|
A simple VTK widget for wxPython.
|
|
|
|
Find wxPython info at http://wxPython.org
|
|
|
|
Created by David Gobbi, December 2001
|
|
Based on vtkTkRenderWindget.py
|
|
|
|
Updated to new wx namespace and some cleaning by Andrea Gavana,
|
|
December 2006
|
|
|
|
"""
|
|
|
|
"""
|
|
Please see the example at the end of this file.
|
|
|
|
----------------------------------------
|
|
Creation:
|
|
|
|
wxVTKRenderWindow(parent, ID, stereo=0, [wx keywords]):
|
|
|
|
You should create a wx.App(False) or some other wx.App subclass
|
|
before creating the window.
|
|
|
|
----------------------------------------
|
|
Methods:
|
|
|
|
Render()
|
|
AddRenderer(ren)
|
|
GetRenderers()
|
|
GetRenderWindow()
|
|
|
|
----------------------------------------
|
|
Methods to override (all take a wx.Event):
|
|
|
|
OnButtonDown(event) default: propagate event to Left, Right, Middle
|
|
OnLeftDown(event) default: set _Mode to 'Rotate'
|
|
OnRightDown(event) default: set _Mode to 'Zoom'
|
|
OnMiddleDown(event) default: set _Mode to 'Pan'
|
|
|
|
OnButtonUp(event) default: propagate event to L, R, M and unset _Mode
|
|
OnLeftUp(event)
|
|
OnRightUp(event)
|
|
OnMiddleUp(event)
|
|
|
|
OnMotion(event) default: call appropriate handler for _Mode
|
|
|
|
OnEnterWindow(event) default: set focus to this window
|
|
OnLeaveWindow(event) default: release focus
|
|
|
|
OnKeyDown(event) default: [R]eset, [W]irefreme, [S]olid, [P]ick
|
|
OnKeyUp(event)
|
|
OnChar(event)
|
|
|
|
OnSetFocus(event)
|
|
OnKillFocus(event)
|
|
|
|
OnSize(event)
|
|
OnMove(event)
|
|
|
|
OnPaint(event) default: Render()
|
|
|
|
----------------------------------------
|
|
Protected Members:
|
|
|
|
_Mode: Current mode: 'Rotate', 'Zoom', 'Pan'
|
|
_LastX, _LastY: The (x,y) coordinates of the previous event
|
|
_CurrentRenderer: The renderer that was most recently clicked in
|
|
_CurrentCamera: The camera for the current renderer
|
|
|
|
----------------------------------------
|
|
Private Members:
|
|
|
|
__Handle: Handle to the window containing the vtkRenderWindow
|
|
|
|
"""
|
|
|
|
# import usual libraries
|
|
import math, os, sys
|
|
import wx
|
|
from vtkmodules.vtkRenderingCore import vtkCellPicker, vtkProperty, vtkRenderWindow
|
|
|
|
# a few configuration items, see what works best on your system
|
|
|
|
# Use GLCanvas as base class instead of wx.Window.
|
|
# This is sometimes necessary under wxGTK or the image is blank.
|
|
# (in wxWindows 2.3.1 and earlier, the GLCanvas had scroll bars)
|
|
baseClass = wx.Window
|
|
if wx.Platform == "__WXGTK__":
|
|
import wx.glcanvas
|
|
baseClass = wx.glcanvas.GLCanvas
|
|
|
|
# Keep capturing mouse after mouse is dragged out of window
|
|
# (in wxGTK 2.3.2 there is a bug that keeps this from working,
|
|
# but it is only relevant in wxGTK if there are multiple windows)
|
|
_useCapture = (wx.Platform == "__WXMSW__")
|
|
|
|
# end of configuration items
|
|
|
|
|
|
class wxVTKRenderWindow(baseClass):
|
|
"""
|
|
A wxRenderWindow for wxPython.
|
|
Use GetRenderWindow() to get the vtkRenderWindow.
|
|
Create with the keyword stereo=1 in order to
|
|
generate a stereo-capable window.
|
|
"""
|
|
|
|
def __init__(self, parent, ID, *args, **kw):
|
|
"""Default class constructor.
|
|
@param parent parent window
|
|
@param ID window id
|
|
@param **kw wxPython keywords (position, size, style) plus the
|
|
'stereo' keyword
|
|
"""
|
|
# miscellaneous protected variables
|
|
self._CurrentRenderer = None
|
|
self._CurrentCamera = None
|
|
self._CurrentZoom = 1.0
|
|
self._CurrentLight = None
|
|
|
|
self._ViewportCenterX = 0
|
|
self._ViewportCenterY = 0
|
|
|
|
self._Picker = vtkCellPicker()
|
|
self._PickedActor = None
|
|
self._PickedProperty = vtkProperty()
|
|
self._PickedProperty.SetColor(1,0,0)
|
|
self._PrePickedProperty = None
|
|
|
|
# these record the previous mouse position
|
|
self._LastX = 0
|
|
self._LastY = 0
|
|
|
|
# the current interaction mode (Rotate, Pan, Zoom, etc)
|
|
self._Mode = None
|
|
self._ActiveButton = None
|
|
|
|
# private attributes
|
|
self.__OldFocus = None
|
|
|
|
# used by the LOD actors
|
|
self._DesiredUpdateRate = 15
|
|
self._StillUpdateRate = 0.0001
|
|
|
|
# First do special handling of some keywords:
|
|
# stereo, position, size, width, height, style
|
|
|
|
try:
|
|
stereo = bool(kw['stereo'])
|
|
del kw['stereo']
|
|
except KeyError:
|
|
stereo = False
|
|
|
|
try:
|
|
position = kw['position']
|
|
del kw['position']
|
|
except KeyError:
|
|
position = wx.DefaultPosition
|
|
|
|
try:
|
|
size = kw['size']
|
|
del kw['size']
|
|
except KeyError:
|
|
try:
|
|
size = parent.GetSize()
|
|
except AttributeError:
|
|
size = wx.DefaultSize
|
|
|
|
# wx.WANTS_CHARS says to give us e.g. TAB
|
|
# wx.NO_FULL_REPAINT_ON_RESIZE cuts down resize flicker under GTK
|
|
style = wx.WANTS_CHARS | wx.NO_FULL_REPAINT_ON_RESIZE
|
|
|
|
try:
|
|
style = style | kw['style']
|
|
del kw['style']
|
|
except KeyError:
|
|
pass
|
|
|
|
# the enclosing frame must be shown under GTK or the windows
|
|
# don't connect together properly
|
|
l = []
|
|
p = parent
|
|
while p: # make a list of all parents
|
|
l.append(p)
|
|
p = p.GetParent()
|
|
l.reverse() # sort list into descending order
|
|
for p in l:
|
|
p.Show(1)
|
|
|
|
# initialize the wx.Window
|
|
if baseClass.__name__ == 'GLCanvas':
|
|
# Set the doublebuffer attribute of the GL canvas.
|
|
baseClass.__init__(self, parent, ID, pos=position, size=size,
|
|
style=style,
|
|
attribList=[wx.glcanvas.WX_GL_DOUBLEBUFFER])
|
|
else:
|
|
baseClass.__init__(self, parent, ID, pos=position, size=size,
|
|
style=style)
|
|
|
|
# create the RenderWindow and initialize it
|
|
self._RenderWindow = vtkRenderWindow()
|
|
self._RenderWindow.SetSize(size.width, size.height)
|
|
|
|
if stereo:
|
|
self._RenderWindow.StereoCapableWindowOn()
|
|
self._RenderWindow.SetStereoTypeToCrystalEyes()
|
|
|
|
self.__handle = None
|
|
|
|
# refresh window by doing a Render
|
|
self.Bind(wx.EVT_PAINT, self.OnPaint)
|
|
# turn off background erase to reduce flicker
|
|
self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None)
|
|
|
|
# Bind the events to the event converters
|
|
self.Bind(wx.EVT_RIGHT_DOWN, self._OnButtonDown)
|
|
self.Bind(wx.EVT_LEFT_DOWN, self._OnButtonDown)
|
|
self.Bind(wx.EVT_MIDDLE_DOWN, self._OnButtonDown)
|
|
self.Bind(wx.EVT_RIGHT_UP, self._OnButtonUp)
|
|
self.Bind(wx.EVT_LEFT_UP, self._OnButtonUp)
|
|
self.Bind(wx.EVT_MIDDLE_UP, self._OnButtonUp)
|
|
self.Bind(wx.EVT_MOTION, self.OnMotion)
|
|
|
|
self.Bind(wx.EVT_ENTER_WINDOW, self._OnEnterWindow)
|
|
self.Bind(wx.EVT_LEAVE_WINDOW, self._OnLeaveWindow)
|
|
|
|
self.Bind(wx.EVT_CHAR, self.OnChar)
|
|
|
|
# If we use EVT_KEY_DOWN instead of EVT_CHAR, capital versions
|
|
# of all characters are always returned. EVT_CHAR also performs
|
|
# other necessary keyboard-dependent translations.
|
|
self.Bind(wx.EVT_CHAR, self.OnKeyDown)
|
|
self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)
|
|
|
|
self.Bind(wx.EVT_SIZE, self._OnSize)
|
|
self.Bind(wx.EVT_MOVE, self.OnMove)
|
|
|
|
self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus)
|
|
self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
|
|
|
|
def SetDesiredUpdateRate(self, rate):
|
|
"""Mirrors the method with the same name in
|
|
vtkRenderWindowInteractor.
|
|
"""
|
|
self._DesiredUpdateRate = rate
|
|
|
|
def GetDesiredUpdateRate(self):
|
|
"""Mirrors the method with the same name in
|
|
vtkRenderWindowInteractor.
|
|
"""
|
|
return self._DesiredUpdateRate
|
|
|
|
def SetStillUpdateRate(self, rate):
|
|
"""Mirrors the method with the same name in
|
|
vtkRenderWindowInteractor.
|
|
"""
|
|
self._StillUpdateRate = rate
|
|
|
|
def GetStillUpdateRate(self):
|
|
"""Mirrors the method with the same name in
|
|
vtkRenderWindowInteractor.
|
|
"""
|
|
return self._StillUpdateRate
|
|
|
|
def OnPaint(self, event):
|
|
"""Handles the wx.EVT_PAINT event for wxVTKRenderWindow.
|
|
"""
|
|
dc = wx.PaintDC(self)
|
|
self.Render()
|
|
|
|
def _OnSize(self, event):
|
|
"""Handles the wx.EVT_SIZE event for wxVTKRenderWindow.
|
|
"""
|
|
if wx.Platform != '__WXMSW__':
|
|
width, height = event.GetSize()
|
|
self._RenderWindow.SetSize(width, height)
|
|
self.OnSize(event)
|
|
self.Render()
|
|
|
|
def OnSize(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def OnMove(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
|
|
def _OnEnterWindow(self, event):
|
|
"""Handles the wx.EVT_ENTER_WINDOW event for
|
|
wxVTKRenderWindow.
|
|
"""
|
|
self.UpdateRenderer(event)
|
|
self.OnEnterWindow(event)
|
|
|
|
|
|
def OnEnterWindow(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if self.__OldFocus == None:
|
|
self.__OldFocus = wx.Window.FindFocus()
|
|
self.SetFocus()
|
|
|
|
def _OnLeaveWindow(self, event):
|
|
"""Handles the wx.EVT_LEAVE_WINDOW event for
|
|
wxVTKRenderWindow.
|
|
"""
|
|
self.OnLeaveWindow(event)
|
|
|
|
def OnLeaveWindow(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if self.__OldFocus:
|
|
self.__OldFocus.SetFocus()
|
|
self.__OldFocus = None
|
|
|
|
def OnSetFocus(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def OnKillFocus(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def _OnButtonDown(self, event):
|
|
"""Handles the wx.EVT_LEFT/RIGHT/MIDDLE_DOWN events for
|
|
wxVTKRenderWindow.
|
|
"""
|
|
# helper function for capturing mouse until button released
|
|
self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate)
|
|
|
|
if event.RightDown():
|
|
button = "Right"
|
|
elif event.LeftDown():
|
|
button = "Left"
|
|
elif event.MiddleDown():
|
|
button = "Middle"
|
|
else:
|
|
button = None
|
|
|
|
# save the button and capture mouse until the button is released
|
|
if button and not self._ActiveButton:
|
|
self._ActiveButton = button
|
|
if _useCapture:
|
|
self.CaptureMouse()
|
|
|
|
self.OnButtonDown(event)
|
|
|
|
def OnButtonDown(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if not self._Mode:
|
|
# figure out what renderer the mouse is over
|
|
self.UpdateRenderer(event)
|
|
|
|
if event.LeftDown():
|
|
self.OnLeftDown(event)
|
|
elif event.RightDown():
|
|
self.OnRightDown(event)
|
|
elif event.MiddleDown():
|
|
self.OnMiddleDown(event)
|
|
|
|
def OnLeftDown(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if not self._Mode:
|
|
if event.ControlDown():
|
|
self._Mode = "Zoom"
|
|
elif event.ShiftDown():
|
|
self._Mode = "Pan"
|
|
else:
|
|
self._Mode = "Rotate"
|
|
|
|
def OnRightDown(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if not self._Mode:
|
|
self._Mode = "Zoom"
|
|
|
|
def OnMiddleDown(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if not self._Mode:
|
|
self._Mode = "Pan"
|
|
|
|
def _OnButtonUp(self, event):
|
|
"""Handles the wx.EVT_LEFT/RIGHT/MIDDLE_UP events for
|
|
wxVTKRenderWindow.
|
|
"""
|
|
# helper function for releasing mouse capture
|
|
self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate)
|
|
|
|
if event.RightUp():
|
|
button = "Right"
|
|
elif event.LeftUp():
|
|
button = "Left"
|
|
elif event.MiddleUp():
|
|
button = "Middle"
|
|
else:
|
|
button = None
|
|
|
|
# if the ActiveButton is released, then release mouse capture
|
|
if self._ActiveButton and button == self._ActiveButton:
|
|
if _useCapture:
|
|
self.ReleaseMouse()
|
|
self._ActiveButton = None
|
|
|
|
self.OnButtonUp(event)
|
|
|
|
def OnButtonUp(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if event.LeftUp():
|
|
self.OnLeftUp(event)
|
|
elif event.RightUp():
|
|
self.OnRightUp(event)
|
|
elif event.MiddleUp():
|
|
self.OnMiddleUp(event)
|
|
|
|
# if not interacting, then do nothing more
|
|
if self._Mode:
|
|
if self._CurrentRenderer:
|
|
self.Render()
|
|
|
|
self._Mode = None
|
|
|
|
def OnLeftUp(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def OnRightUp(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def OnMiddleUp(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def OnMotion(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
if self._Mode == "Pan":
|
|
self.Pan(event)
|
|
elif self._Mode == "Rotate":
|
|
self.Rotate(event)
|
|
elif self._Mode == "Zoom":
|
|
self.Zoom(event)
|
|
|
|
def OnChar(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def OnKeyDown(self, event):
|
|
"""Handles the wx.EVT_KEY_DOWN events for wxVTKRenderWindow.
|
|
"""
|
|
if event.GetKeyCode() == ord('r'):
|
|
self.Reset(event)
|
|
if event.GetKeyCode() == ord('w'):
|
|
self.Wireframe()
|
|
if event.GetKeyCode() == ord('s'):
|
|
self.Surface()
|
|
if event.GetKeyCode() == ord('p'):
|
|
self.PickActor(event)
|
|
|
|
if event.GetKeyCode() < 128:
|
|
self.OnChar(event)
|
|
|
|
def OnKeyUp(self, event):
|
|
"""Overridable event.
|
|
"""
|
|
pass
|
|
|
|
def GetZoomFactor(self):
|
|
"""Returns the current zoom factor.
|
|
"""
|
|
return self._CurrentZoom
|
|
|
|
def GetRenderWindow(self):
|
|
"""Returns the render window (vtkRenderWindow).
|
|
"""
|
|
return self._RenderWindow
|
|
|
|
def GetPicker(self):
|
|
"""Returns the current picker (vtkCellPicker).
|
|
"""
|
|
return self._Picker
|
|
|
|
def Render(self):
|
|
"""Actually renders the VTK scene on screen.
|
|
"""
|
|
if self._CurrentLight:
|
|
light = self._CurrentLight
|
|
light.SetPosition(self._CurrentCamera.GetPosition())
|
|
light.SetFocalPoint(self._CurrentCamera.GetFocalPoint())
|
|
|
|
if not self.GetUpdateRegion().IsEmpty() or self.__handle:
|
|
if self.__handle and self.__handle == self.GetHandle():
|
|
self._RenderWindow.Render()
|
|
|
|
elif self.GetHandle():
|
|
# this means the user has reparented us
|
|
# let's adapt to the new situation by doing the WindowRemap
|
|
# dance
|
|
self._RenderWindow.SetNextWindowInfo(str(self.GetHandle()))
|
|
self._RenderWindow.WindowRemap()
|
|
# store the new situation
|
|
self.__handle = self.GetHandle()
|
|
|
|
self._RenderWindow.Render()
|
|
|
|
def UpdateRenderer(self, event):
|
|
"""
|
|
UpdateRenderer will identify the renderer under the mouse and set
|
|
up _CurrentRenderer, _CurrentCamera, and _CurrentLight.
|
|
"""
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
windowX, windowY = self._RenderWindow.GetSize()
|
|
|
|
renderers = self._RenderWindow.GetRenderers()
|
|
numRenderers = renderers.GetNumberOfItems()
|
|
|
|
self._CurrentRenderer = None
|
|
renderers.InitTraversal()
|
|
for i in range(0,numRenderers):
|
|
renderer = renderers.GetNextItem()
|
|
vx,vy = (0,0)
|
|
if (windowX > 1):
|
|
vx = float(x)/(windowX-1)
|
|
if (windowY > 1):
|
|
vy = (windowY-float(y)-1)/(windowY-1)
|
|
(vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport()
|
|
|
|
if (vx >= vpxmin and vx <= vpxmax and
|
|
vy >= vpymin and vy <= vpymax):
|
|
self._CurrentRenderer = renderer
|
|
self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\
|
|
+vpxmin
|
|
self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\
|
|
+vpymin
|
|
self._CurrentCamera = self._CurrentRenderer.GetActiveCamera()
|
|
lights = self._CurrentRenderer.GetLights()
|
|
lights.InitTraversal()
|
|
self._CurrentLight = lights.GetNextItem()
|
|
break
|
|
|
|
self._LastX = x
|
|
self._LastY = y
|
|
|
|
def GetCurrentRenderer(self):
|
|
"""Returns the current renderer.
|
|
"""
|
|
return self._CurrentRenderer
|
|
|
|
def Rotate(self, event):
|
|
"""Rotates the scene (camera).
|
|
"""
|
|
if self._CurrentRenderer:
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
|
|
self._CurrentCamera.Azimuth(self._LastX - x)
|
|
self._CurrentCamera.Elevation(y - self._LastY)
|
|
self._CurrentCamera.OrthogonalizeViewUp()
|
|
|
|
self._LastX = x
|
|
self._LastY = y
|
|
|
|
self._CurrentRenderer.ResetCameraClippingRange()
|
|
self.Render()
|
|
|
|
def Pan(self, event):
|
|
"""Pans the scene (camera).
|
|
"""
|
|
if self._CurrentRenderer:
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
|
|
renderer = self._CurrentRenderer
|
|
camera = self._CurrentCamera
|
|
(pPoint0,pPoint1,pPoint2) = camera.GetPosition()
|
|
(fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint()
|
|
|
|
if camera.GetParallelProjection():
|
|
renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0)
|
|
renderer.WorldToDisplay()
|
|
fx,fy,fz = renderer.GetDisplayPoint()
|
|
renderer.SetDisplayPoint(fx-x+self._LastX,
|
|
fy+y-self._LastY,
|
|
fz)
|
|
renderer.DisplayToWorld()
|
|
fx,fy,fz,fw = renderer.GetWorldPoint()
|
|
camera.SetFocalPoint(fx,fy,fz)
|
|
|
|
renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0)
|
|
renderer.WorldToDisplay()
|
|
fx,fy,fz = renderer.GetDisplayPoint()
|
|
renderer.SetDisplayPoint(fx-x+self._LastX,
|
|
fy+y-self._LastY,
|
|
fz)
|
|
renderer.DisplayToWorld()
|
|
fx,fy,fz,fw = renderer.GetWorldPoint()
|
|
camera.SetPosition(fx,fy,fz)
|
|
|
|
else:
|
|
(fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint()
|
|
# Specify a point location in world coordinates
|
|
renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0)
|
|
renderer.WorldToDisplay()
|
|
# Convert world point coordinates to display coordinates
|
|
dPoint = renderer.GetDisplayPoint()
|
|
focalDepth = dPoint[2]
|
|
|
|
aPoint0 = self._ViewportCenterX + (x - self._LastX)
|
|
aPoint1 = self._ViewportCenterY - (y - self._LastY)
|
|
|
|
renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth)
|
|
renderer.DisplayToWorld()
|
|
|
|
(rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint()
|
|
if (rPoint3 != 0.0):
|
|
rPoint0 = rPoint0/rPoint3
|
|
rPoint1 = rPoint1/rPoint3
|
|
rPoint2 = rPoint2/rPoint3
|
|
|
|
camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0,
|
|
(fPoint1 - rPoint1) + fPoint1,
|
|
(fPoint2 - rPoint2) + fPoint2)
|
|
|
|
camera.SetPosition((fPoint0 - rPoint0) + pPoint0,
|
|
(fPoint1 - rPoint1) + pPoint1,
|
|
(fPoint2 - rPoint2) + pPoint2)
|
|
|
|
self._LastX = x
|
|
self._LastY = y
|
|
|
|
self.Render()
|
|
|
|
def Zoom(self, event):
|
|
"""Zooms the scene (camera).
|
|
"""
|
|
if self._CurrentRenderer:
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
|
|
renderer = self._CurrentRenderer
|
|
camera = self._CurrentCamera
|
|
|
|
zoomFactor = math.pow(1.02,(0.5*(self._LastY - y)))
|
|
self._CurrentZoom = self._CurrentZoom * zoomFactor
|
|
|
|
if camera.GetParallelProjection():
|
|
parallelScale = camera.GetParallelScale()/zoomFactor
|
|
camera.SetParallelScale(parallelScale)
|
|
else:
|
|
camera.Dolly(zoomFactor)
|
|
renderer.ResetCameraClippingRange()
|
|
|
|
self._LastX = x
|
|
self._LastY = y
|
|
|
|
self.Render()
|
|
|
|
def Reset(self, event=None):
|
|
"""Resets the camera.
|
|
"""
|
|
if self._CurrentRenderer:
|
|
self._CurrentRenderer.ResetCamera()
|
|
|
|
self.Render()
|
|
|
|
def Wireframe(self):
|
|
"""Sets the current actor representation as wireframe.
|
|
"""
|
|
actors = self._CurrentRenderer.GetActors()
|
|
numActors = actors.GetNumberOfItems()
|
|
actors.InitTraversal()
|
|
for i in range(0,numActors):
|
|
actor = actors.GetNextItem()
|
|
actor.GetProperty().SetRepresentationToWireframe()
|
|
|
|
self.Render()
|
|
|
|
def Surface(self):
|
|
"""Sets the current actor representation as surface.
|
|
"""
|
|
actors = self._CurrentRenderer.GetActors()
|
|
numActors = actors.GetNumberOfItems()
|
|
actors.InitTraversal()
|
|
for i in range(0,numActors):
|
|
actor = actors.GetNextItem()
|
|
actor.GetProperty().SetRepresentationToSurface()
|
|
|
|
self.Render()
|
|
|
|
def PickActor(self, event):
|
|
"""Picks an actor.
|
|
"""
|
|
if self._CurrentRenderer:
|
|
x = event.GetX()
|
|
y = event.GetY()
|
|
|
|
renderer = self._CurrentRenderer
|
|
picker = self._Picker
|
|
|
|
windowX, windowY = self._RenderWindow.GetSize()
|
|
picker.Pick(x,(windowY - y - 1),0.0,renderer)
|
|
actor = picker.GetActor()
|
|
|
|
if (self._PickedActor != None and
|
|
self._PrePickedProperty != None):
|
|
self._PickedActor.SetProperty(self._PrePickedProperty)
|
|
# release hold of the property
|
|
self._PrePickedProperty.UnRegister(self._PrePickedProperty)
|
|
self._PrePickedProperty = None
|
|
|
|
if (actor != None):
|
|
self._PickedActor = actor
|
|
self._PrePickedProperty = self._PickedActor.GetProperty()
|
|
# hold onto the property
|
|
self._PrePickedProperty.Register(self._PrePickedProperty)
|
|
self._PickedActor.SetProperty(self._PickedProperty)
|
|
|
|
self.Render()
|
|
|
|
|
|
#----------------------------------------------------------------------------
|
|
def wxVTKRenderWindowConeExample():
|
|
"""Like it says, just a simple example.
|
|
"""
|
|
|
|
from vtkmodules.vtkFiltersSources import vtkConeSource
|
|
from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer
|
|
# load implementations for rendering and interaction factory classes
|
|
import vtkmodules.vtkRenderingOpenGL2
|
|
import vtkmodules.vtkInteractionStyle
|
|
|
|
# every wx app needs an app
|
|
app = wx.App(False)
|
|
|
|
# create the widget
|
|
frame = wx.Frame(None, -1, "wxVTKRenderWindow", size=(400,400))
|
|
widget = wxVTKRenderWindow(frame, -1)
|
|
|
|
ren = vtkRenderer()
|
|
widget.GetRenderWindow().AddRenderer(ren)
|
|
|
|
cone = vtkConeSource()
|
|
cone.SetResolution(8)
|
|
|
|
coneMapper = vtkPolyDataMapper()
|
|
coneMapper.SetInputConnection(cone.GetOutputPort())
|
|
|
|
coneActor = vtkActor()
|
|
coneActor.SetMapper(coneMapper)
|
|
|
|
ren.AddActor(coneActor)
|
|
|
|
# show the window
|
|
|
|
frame.Show()
|
|
|
|
app.MainLoop()
|
|
|
|
if __name__ == "__main__":
|
|
wxVTKRenderWindowConeExample()
|