1""" 2A simple VTK widget for wxPython. 3 4Find wxPython info at http://wxPython.org 5 6Created by David Gobbi, December 2001 7Based on vtkTkRenderWindget.py 8 9Updated to new wx namespace and some cleaning by Andrea Gavana, 10December 2006 11 12""" 13 14""" 15Please see the example at the end of this file. 16 17---------------------------------------- 18Creation: 19 20wxVTKRenderWindow(parent, ID, stereo=0, [wx keywords]): 21 22You should create a wx.App(False) or some other wx.App subclass 23before creating the window. 24 25---------------------------------------- 26Methods: 27 28Render() 29AddRenderer(ren) 30GetRenderers() 31GetRenderWindow() 32 33---------------------------------------- 34Methods to override (all take a wx.Event): 35 36OnButtonDown(event) default: propagate event to Left, Right, Middle 37OnLeftDown(event) default: set _Mode to 'Rotate' 38OnRightDown(event) default: set _Mode to 'Zoom' 39OnMiddleDown(event) default: set _Mode to 'Pan' 40 41OnButtonUp(event) default: propagate event to L, R, M and unset _Mode 42OnLeftUp(event) 43OnRightUp(event) 44OnMiddleUp(event) 45 46OnMotion(event) default: call appropriate handler for _Mode 47 48OnEnterWindow(event) default: set focus to this window 49OnLeaveWindow(event) default: release focus 50 51OnKeyDown(event) default: [R]eset, [W]irefreme, [S]olid, [P]ick 52OnKeyUp(event) 53OnChar(event) 54 55OnSetFocus(event) 56OnKillFocus(event) 57 58OnSize(event) 59OnMove(event) 60 61OnPaint(event) default: Render() 62 63---------------------------------------- 64Protected Members: 65 66_Mode: Current mode: 'Rotate', 'Zoom', 'Pan' 67_LastX, _LastY: The (x,y) coordinates of the previous event 68_CurrentRenderer: The renderer that was most recently clicked in 69_CurrentCamera: The camera for the current renderer 70 71---------------------------------------- 72Private Members: 73 74__Handle: Handle to the window containing the vtkRenderWindow 75 76""" 77 78# import usual libraries 79import math, os, sys 80import wx 81from vtkmodules.vtkRenderingCore import vtkCellPicker, vtkProperty, vtkRenderWindow 82 83# a few configuration items, see what works best on your system 84 85# Use GLCanvas as base class instead of wx.Window. 86# This is sometimes necessary under wxGTK or the image is blank. 87# (in wxWindows 2.3.1 and earlier, the GLCanvas had scroll bars) 88baseClass = wx.Window 89if wx.Platform == "__WXGTK__": 90 import wx.glcanvas 91 baseClass = wx.glcanvas.GLCanvas 92 93# Keep capturing mouse after mouse is dragged out of window 94# (in wxGTK 2.3.2 there is a bug that keeps this from working, 95# but it is only relevant in wxGTK if there are multiple windows) 96_useCapture = (wx.Platform == "__WXMSW__") 97 98# end of configuration items 99 100 101class wxVTKRenderWindow(baseClass): 102 """ 103 A wxRenderWindow for wxPython. 104 Use GetRenderWindow() to get the vtkRenderWindow. 105 Create with the keyword stereo=1 in order to 106 generate a stereo-capable window. 107 """ 108 109 def __init__(self, parent, ID, *args, **kw): 110 """Default class constructor. 111 @param parent: parent window 112 @param ID: window id 113 @param **kw: wxPython keywords (position, size, style) plus the 114 'stereo' keyword 115 """ 116 # miscellaneous protected variables 117 self._CurrentRenderer = None 118 self._CurrentCamera = None 119 self._CurrentZoom = 1.0 120 self._CurrentLight = None 121 122 self._ViewportCenterX = 0 123 self._ViewportCenterY = 0 124 125 self._Picker = vtkCellPicker() 126 self._PickedActor = None 127 self._PickedProperty = vtkProperty() 128 self._PickedProperty.SetColor(1,0,0) 129 self._PrePickedProperty = None 130 131 # these record the previous mouse position 132 self._LastX = 0 133 self._LastY = 0 134 135 # the current interaction mode (Rotate, Pan, Zoom, etc) 136 self._Mode = None 137 self._ActiveButton = None 138 139 # private attributes 140 self.__OldFocus = None 141 142 # used by the LOD actors 143 self._DesiredUpdateRate = 15 144 self._StillUpdateRate = 0.0001 145 146 # First do special handling of some keywords: 147 # stereo, position, size, width, height, style 148 149 try: 150 stereo = bool(kw['stereo']) 151 del kw['stereo'] 152 except KeyError: 153 stereo = False 154 155 try: 156 position = kw['position'] 157 del kw['position'] 158 except KeyError: 159 position = wx.DefaultPosition 160 161 try: 162 size = kw['size'] 163 del kw['size'] 164 except KeyError: 165 try: 166 size = parent.GetSize() 167 except AttributeError: 168 size = wx.DefaultSize 169 170 # wx.WANTS_CHARS says to give us e.g. TAB 171 # wx.NO_FULL_REPAINT_ON_RESIZE cuts down resize flicker under GTK 172 style = wx.WANTS_CHARS | wx.NO_FULL_REPAINT_ON_RESIZE 173 174 try: 175 style = style | kw['style'] 176 del kw['style'] 177 except KeyError: 178 pass 179 180 # the enclosing frame must be shown under GTK or the windows 181 # don't connect together properly 182 l = [] 183 p = parent 184 while p: # make a list of all parents 185 l.append(p) 186 p = p.GetParent() 187 l.reverse() # sort list into descending order 188 for p in l: 189 p.Show(1) 190 191 # initialize the wx.Window 192 if baseClass.__name__ == 'GLCanvas': 193 # Set the doublebuffer attribute of the GL canvas. 194 baseClass.__init__(self, parent, ID, pos=position, size=size, 195 style=style, 196 attribList=[wx.glcanvas.WX_GL_DOUBLEBUFFER]) 197 else: 198 baseClass.__init__(self, parent, ID, pos=position, size=size, 199 style=style) 200 201 # create the RenderWindow and initialize it 202 self._RenderWindow = vtkRenderWindow() 203 self._RenderWindow.SetSize(size.width, size.height) 204 205 if stereo: 206 self._RenderWindow.StereoCapableWindowOn() 207 self._RenderWindow.SetStereoTypeToCrystalEyes() 208 209 self.__handle = None 210 211 # refresh window by doing a Render 212 self.Bind(wx.EVT_PAINT, self.OnPaint) 213 # turn off background erase to reduce flicker 214 self.Bind(wx.EVT_ERASE_BACKGROUND, lambda e: None) 215 216 # Bind the events to the event converters 217 self.Bind(wx.EVT_RIGHT_DOWN, self._OnButtonDown) 218 self.Bind(wx.EVT_LEFT_DOWN, self._OnButtonDown) 219 self.Bind(wx.EVT_MIDDLE_DOWN, self._OnButtonDown) 220 self.Bind(wx.EVT_RIGHT_UP, self._OnButtonUp) 221 self.Bind(wx.EVT_LEFT_UP, self._OnButtonUp) 222 self.Bind(wx.EVT_MIDDLE_UP, self._OnButtonUp) 223 self.Bind(wx.EVT_MOTION, self.OnMotion) 224 225 self.Bind(wx.EVT_ENTER_WINDOW, self._OnEnterWindow) 226 self.Bind(wx.EVT_LEAVE_WINDOW, self._OnLeaveWindow) 227 228 self.Bind(wx.EVT_CHAR, self.OnChar) 229 230 # If we use EVT_KEY_DOWN instead of EVT_CHAR, capital versions 231 # of all characters are always returned. EVT_CHAR also performs 232 # other necessary keyboard-dependent translations. 233 self.Bind(wx.EVT_CHAR, self.OnKeyDown) 234 self.Bind(wx.EVT_KEY_UP, self.OnKeyUp) 235 236 self.Bind(wx.EVT_SIZE, self._OnSize) 237 self.Bind(wx.EVT_MOVE, self.OnMove) 238 239 self.Bind(wx.EVT_SET_FOCUS, self.OnSetFocus) 240 self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus) 241 242 def SetDesiredUpdateRate(self, rate): 243 """Mirrors the method with the same name in 244 vtkRenderWindowInteractor. 245 """ 246 self._DesiredUpdateRate = rate 247 248 def GetDesiredUpdateRate(self): 249 """Mirrors the method with the same name in 250 vtkRenderWindowInteractor. 251 """ 252 return self._DesiredUpdateRate 253 254 def SetStillUpdateRate(self, rate): 255 """Mirrors the method with the same name in 256 vtkRenderWindowInteractor. 257 """ 258 self._StillUpdateRate = rate 259 260 def GetStillUpdateRate(self): 261 """Mirrors the method with the same name in 262 vtkRenderWindowInteractor. 263 """ 264 return self._StillUpdateRate 265 266 def OnPaint(self, event): 267 """Handles the wx.EVT_PAINT event for wxVTKRenderWindow. 268 """ 269 dc = wx.PaintDC(self) 270 self.Render() 271 272 def _OnSize(self, event): 273 """Handles the wx.EVT_SIZE event for wxVTKRenderWindow. 274 """ 275 if wx.Platform != '__WXMSW__': 276 width, height = event.GetSize() 277 self._RenderWindow.SetSize(width, height) 278 self.OnSize(event) 279 self.Render() 280 281 def OnSize(self, event): 282 """Overridable event. 283 """ 284 pass 285 286 def OnMove(self, event): 287 """Overridable event. 288 """ 289 pass 290 291 292 def _OnEnterWindow(self, event): 293 """Handles the wx.EVT_ENTER_WINDOW event for 294 wxVTKRenderWindow. 295 """ 296 self.UpdateRenderer(event) 297 self.OnEnterWindow(event) 298 299 300 def OnEnterWindow(self, event): 301 """Overridable event. 302 """ 303 if self.__OldFocus == None: 304 self.__OldFocus = wx.Window.FindFocus() 305 self.SetFocus() 306 307 def _OnLeaveWindow(self, event): 308 """Handles the wx.EVT_LEAVE_WINDOW event for 309 wxVTKRenderWindow. 310 """ 311 self.OnLeaveWindow(event) 312 313 def OnLeaveWindow(self, event): 314 """Overridable event. 315 """ 316 if self.__OldFocus: 317 self.__OldFocus.SetFocus() 318 self.__OldFocus = None 319 320 def OnSetFocus(self, event): 321 """Overridable event. 322 """ 323 pass 324 325 def OnKillFocus(self, event): 326 """Overridable event. 327 """ 328 pass 329 330 def _OnButtonDown(self, event): 331 """Handles the wx.EVT_LEFT/RIGHT/MIDDLE_DOWN events for 332 wxVTKRenderWindow. 333 """ 334 # helper function for capturing mouse until button released 335 self._RenderWindow.SetDesiredUpdateRate(self._DesiredUpdateRate) 336 337 if event.RightDown(): 338 button = "Right" 339 elif event.LeftDown(): 340 button = "Left" 341 elif event.MiddleDown(): 342 button = "Middle" 343 else: 344 button = None 345 346 # save the button and capture mouse until the button is released 347 if button and not self._ActiveButton: 348 self._ActiveButton = button 349 if _useCapture: 350 self.CaptureMouse() 351 352 self.OnButtonDown(event) 353 354 def OnButtonDown(self, event): 355 """Overridable event. 356 """ 357 if not self._Mode: 358 # figure out what renderer the mouse is over 359 self.UpdateRenderer(event) 360 361 if event.LeftDown(): 362 self.OnLeftDown(event) 363 elif event.RightDown(): 364 self.OnRightDown(event) 365 elif event.MiddleDown(): 366 self.OnMiddleDown(event) 367 368 def OnLeftDown(self, event): 369 """Overridable event. 370 """ 371 if not self._Mode: 372 if event.ControlDown(): 373 self._Mode = "Zoom" 374 elif event.ShiftDown(): 375 self._Mode = "Pan" 376 else: 377 self._Mode = "Rotate" 378 379 def OnRightDown(self, event): 380 """Overridable event. 381 """ 382 if not self._Mode: 383 self._Mode = "Zoom" 384 385 def OnMiddleDown(self, event): 386 """Overridable event. 387 """ 388 if not self._Mode: 389 self._Mode = "Pan" 390 391 def _OnButtonUp(self, event): 392 """Handles the wx.EVT_LEFT/RIGHT/MIDDLE_UP events for 393 wxVTKRenderWindow. 394 """ 395 # helper function for releasing mouse capture 396 self._RenderWindow.SetDesiredUpdateRate(self._StillUpdateRate) 397 398 if event.RightUp(): 399 button = "Right" 400 elif event.LeftUp(): 401 button = "Left" 402 elif event.MiddleUp(): 403 button = "Middle" 404 else: 405 button = None 406 407 # if the ActiveButton is released, then release mouse capture 408 if self._ActiveButton and button == self._ActiveButton: 409 if _useCapture: 410 self.ReleaseMouse() 411 self._ActiveButton = None 412 413 self.OnButtonUp(event) 414 415 def OnButtonUp(self, event): 416 """Overridable event. 417 """ 418 if event.LeftUp(): 419 self.OnLeftUp(event) 420 elif event.RightUp(): 421 self.OnRightUp(event) 422 elif event.MiddleUp(): 423 self.OnMiddleUp(event) 424 425 # if not interacting, then do nothing more 426 if self._Mode: 427 if self._CurrentRenderer: 428 self.Render() 429 430 self._Mode = None 431 432 def OnLeftUp(self, event): 433 """Overridable event. 434 """ 435 pass 436 437 def OnRightUp(self, event): 438 """Overridable event. 439 """ 440 pass 441 442 def OnMiddleUp(self, event): 443 """Overridable event. 444 """ 445 pass 446 447 def OnMotion(self, event): 448 """Overridable event. 449 """ 450 if self._Mode == "Pan": 451 self.Pan(event) 452 elif self._Mode == "Rotate": 453 self.Rotate(event) 454 elif self._Mode == "Zoom": 455 self.Zoom(event) 456 457 def OnChar(self, event): 458 """Overridable event. 459 """ 460 pass 461 462 def OnKeyDown(self, event): 463 """Handles the wx.EVT_KEY_DOWN events for wxVTKRenderWindow. 464 """ 465 if event.GetKeyCode() == ord('r'): 466 self.Reset(event) 467 if event.GetKeyCode() == ord('w'): 468 self.Wireframe() 469 if event.GetKeyCode() == ord('s'): 470 self.Surface() 471 if event.GetKeyCode() == ord('p'): 472 self.PickActor(event) 473 474 if event.GetKeyCode() < 256: 475 self.OnChar(event) 476 477 def OnKeyUp(self, event): 478 """Overridable event. 479 """ 480 pass 481 482 def GetZoomFactor(self): 483 """Returns the current zoom factor. 484 """ 485 return self._CurrentZoom 486 487 def GetRenderWindow(self): 488 """Returns the render window (vtkRenderWindow). 489 """ 490 return self._RenderWindow 491 492 def GetPicker(self): 493 """Returns the current picker (vtkCellPicker). 494 """ 495 return self._Picker 496 497 def Render(self): 498 """Actually renders the VTK scene on screen. 499 """ 500 if self._CurrentLight: 501 light = self._CurrentLight 502 light.SetPosition(self._CurrentCamera.GetPosition()) 503 light.SetFocalPoint(self._CurrentCamera.GetFocalPoint()) 504 505 if not self.GetUpdateRegion().IsEmpty() or self.__handle: 506 if self.__handle and self.__handle == self.GetHandle(): 507 self._RenderWindow.Render() 508 509 elif self.GetHandle(): 510 # this means the user has reparented us 511 # let's adapt to the new situation by doing the WindowRemap 512 # dance 513 self._RenderWindow.SetNextWindowInfo(str(self.GetHandle())) 514 self._RenderWindow.WindowRemap() 515 # store the new situation 516 self.__handle = self.GetHandle() 517 518 self._RenderWindow.Render() 519 520 def UpdateRenderer(self, event): 521 """ 522 UpdateRenderer will identify the renderer under the mouse and set 523 up _CurrentRenderer, _CurrentCamera, and _CurrentLight. 524 """ 525 x = event.GetX() 526 y = event.GetY() 527 windowX, windowY = self._RenderWindow.GetSize() 528 529 renderers = self._RenderWindow.GetRenderers() 530 numRenderers = renderers.GetNumberOfItems() 531 532 self._CurrentRenderer = None 533 renderers.InitTraversal() 534 for i in range(0,numRenderers): 535 renderer = renderers.GetNextItem() 536 vx,vy = (0,0) 537 if (windowX > 1): 538 vx = float(x)/(windowX-1) 539 if (windowY > 1): 540 vy = (windowY-float(y)-1)/(windowY-1) 541 (vpxmin,vpymin,vpxmax,vpymax) = renderer.GetViewport() 542 543 if (vx >= vpxmin and vx <= vpxmax and 544 vy >= vpymin and vy <= vpymax): 545 self._CurrentRenderer = renderer 546 self._ViewportCenterX = float(windowX)*(vpxmax-vpxmin)/2.0\ 547 +vpxmin 548 self._ViewportCenterY = float(windowY)*(vpymax-vpymin)/2.0\ 549 +vpymin 550 self._CurrentCamera = self._CurrentRenderer.GetActiveCamera() 551 lights = self._CurrentRenderer.GetLights() 552 lights.InitTraversal() 553 self._CurrentLight = lights.GetNextItem() 554 break 555 556 self._LastX = x 557 self._LastY = y 558 559 def GetCurrentRenderer(self): 560 """Returns the current renderer. 561 """ 562 return self._CurrentRenderer 563 564 def Rotate(self, event): 565 """Rotates the scene (camera). 566 """ 567 if self._CurrentRenderer: 568 x = event.GetX() 569 y = event.GetY() 570 571 self._CurrentCamera.Azimuth(self._LastX - x) 572 self._CurrentCamera.Elevation(y - self._LastY) 573 self._CurrentCamera.OrthogonalizeViewUp() 574 575 self._LastX = x 576 self._LastY = y 577 578 self._CurrentRenderer.ResetCameraClippingRange() 579 self.Render() 580 581 def Pan(self, event): 582 """Pans the scene (camera). 583 """ 584 if self._CurrentRenderer: 585 x = event.GetX() 586 y = event.GetY() 587 588 renderer = self._CurrentRenderer 589 camera = self._CurrentCamera 590 (pPoint0,pPoint1,pPoint2) = camera.GetPosition() 591 (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() 592 593 if camera.GetParallelProjection(): 594 renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) 595 renderer.WorldToDisplay() 596 fx,fy,fz = renderer.GetDisplayPoint() 597 renderer.SetDisplayPoint(fx-x+self._LastX, 598 fy+y-self._LastY, 599 fz) 600 renderer.DisplayToWorld() 601 fx,fy,fz,fw = renderer.GetWorldPoint() 602 camera.SetFocalPoint(fx,fy,fz) 603 604 renderer.SetWorldPoint(pPoint0,pPoint1,pPoint2,1.0) 605 renderer.WorldToDisplay() 606 fx,fy,fz = renderer.GetDisplayPoint() 607 renderer.SetDisplayPoint(fx-x+self._LastX, 608 fy+y-self._LastY, 609 fz) 610 renderer.DisplayToWorld() 611 fx,fy,fz,fw = renderer.GetWorldPoint() 612 camera.SetPosition(fx,fy,fz) 613 614 else: 615 (fPoint0,fPoint1,fPoint2) = camera.GetFocalPoint() 616 # Specify a point location in world coordinates 617 renderer.SetWorldPoint(fPoint0,fPoint1,fPoint2,1.0) 618 renderer.WorldToDisplay() 619 # Convert world point coordinates to display coordinates 620 dPoint = renderer.GetDisplayPoint() 621 focalDepth = dPoint[2] 622 623 aPoint0 = self._ViewportCenterX + (x - self._LastX) 624 aPoint1 = self._ViewportCenterY - (y - self._LastY) 625 626 renderer.SetDisplayPoint(aPoint0,aPoint1,focalDepth) 627 renderer.DisplayToWorld() 628 629 (rPoint0,rPoint1,rPoint2,rPoint3) = renderer.GetWorldPoint() 630 if (rPoint3 != 0.0): 631 rPoint0 = rPoint0/rPoint3 632 rPoint1 = rPoint1/rPoint3 633 rPoint2 = rPoint2/rPoint3 634 635 camera.SetFocalPoint((fPoint0 - rPoint0) + fPoint0, 636 (fPoint1 - rPoint1) + fPoint1, 637 (fPoint2 - rPoint2) + fPoint2) 638 639 camera.SetPosition((fPoint0 - rPoint0) + pPoint0, 640 (fPoint1 - rPoint1) + pPoint1, 641 (fPoint2 - rPoint2) + pPoint2) 642 643 self._LastX = x 644 self._LastY = y 645 646 self.Render() 647 648 def Zoom(self, event): 649 """Zooms the scene (camera). 650 """ 651 if self._CurrentRenderer: 652 x = event.GetX() 653 y = event.GetY() 654 655 renderer = self._CurrentRenderer 656 camera = self._CurrentCamera 657 658 zoomFactor = math.pow(1.02,(0.5*(self._LastY - y))) 659 self._CurrentZoom = self._CurrentZoom * zoomFactor 660 661 if camera.GetParallelProjection(): 662 parallelScale = camera.GetParallelScale()/zoomFactor 663 camera.SetParallelScale(parallelScale) 664 else: 665 camera.Dolly(zoomFactor) 666 renderer.ResetCameraClippingRange() 667 668 self._LastX = x 669 self._LastY = y 670 671 self.Render() 672 673 def Reset(self, event=None): 674 """Resets the camera. 675 """ 676 if self._CurrentRenderer: 677 self._CurrentRenderer.ResetCamera() 678 679 self.Render() 680 681 def Wireframe(self): 682 """Sets the current actor representation as wireframe. 683 """ 684 actors = self._CurrentRenderer.GetActors() 685 numActors = actors.GetNumberOfItems() 686 actors.InitTraversal() 687 for i in range(0,numActors): 688 actor = actors.GetNextItem() 689 actor.GetProperty().SetRepresentationToWireframe() 690 691 self.Render() 692 693 def Surface(self): 694 """Sets the current actor representation as surface. 695 """ 696 actors = self._CurrentRenderer.GetActors() 697 numActors = actors.GetNumberOfItems() 698 actors.InitTraversal() 699 for i in range(0,numActors): 700 actor = actors.GetNextItem() 701 actor.GetProperty().SetRepresentationToSurface() 702 703 self.Render() 704 705 def PickActor(self, event): 706 """Picks an actor. 707 """ 708 if self._CurrentRenderer: 709 x = event.GetX() 710 y = event.GetY() 711 712 renderer = self._CurrentRenderer 713 picker = self._Picker 714 715 windowX, windowY = self._RenderWindow.GetSize() 716 picker.Pick(x,(windowY - y - 1),0.0,renderer) 717 actor = picker.GetActor() 718 719 if (self._PickedActor != None and 720 self._PrePickedProperty != None): 721 self._PickedActor.SetProperty(self._PrePickedProperty) 722 # release hold of the property 723 self._PrePickedProperty.UnRegister(self._PrePickedProperty) 724 self._PrePickedProperty = None 725 726 if (actor != None): 727 self._PickedActor = actor 728 self._PrePickedProperty = self._PickedActor.GetProperty() 729 # hold onto the property 730 self._PrePickedProperty.Register(self._PrePickedProperty) 731 self._PickedActor.SetProperty(self._PickedProperty) 732 733 self.Render() 734 735 736#---------------------------------------------------------------------------- 737def wxVTKRenderWindowConeExample(): 738 """Like it says, just a simple example. 739 """ 740 741 from vtkmodules.vtkFiltersSources import vtkConeSource 742 from vtkmodules.vtkRenderingCore import vtkActor, vtkPolyDataMapper, vtkRenderer 743 744 # every wx app needs an app 745 app = wx.App(False) 746 747 # create the widget 748 frame = wx.Frame(None, -1, "wxVTKRenderWindow", size=(400,400)) 749 widget = wxVTKRenderWindow(frame, -1) 750 751 ren = vtkRenderer() 752 widget.GetRenderWindow().AddRenderer(ren) 753 754 cone = vtkConeSource() 755 cone.SetResolution(8) 756 757 coneMapper = vtkPolyDataMapper() 758 coneMapper.SetInputConnection(cone.GetOutputPort()) 759 760 coneActor = vtkActor() 761 coneActor.SetMapper(coneMapper) 762 763 ren.AddActor(coneActor) 764 765 # show the window 766 767 frame.Show() 768 769 app.MainLoop() 770 771if __name__ == "__main__": 772 wxVTKRenderWindowConeExample() 773