python - vtkRenderWindowInteractor stalling program -
i've been working on prototype application in python stereoscopic imaging of 3d model using vtk, i'm running issues on interface end of things. goal of code below @ moment zoom in on both renderwindows when middlemouse pressed. however, upon calling vtkrenderwindowinteractor.start()
function, vtkrenderwindowinteractor
s stalling out entire program if being run in same thread. more curious keyboard interrupts not being thrown when use ctrl-c (i'm working in unix shell) until close render windows manually using 'x' button. if close window manually without hitting ctrl-c, program picks directly after start()
call (e.g. in code below, infinite while loop). i've provided sequence of screen captures @ end of post visualize happening in case explanation confusing.
i've tried multiple workarounds remedy none far have worked. threading renders isolated threads made no difference when tried using ncurses input, while forking them new process resulted in os issues i'd rather not deal with. current interactor styles method (shown below) use built-in vtk listeners works degree, allowing me detect inputs when windows in focus , interactors active, because of lack of association between camera , myinteractorstyle
class, can't access cameras without inclusion loop after start()
call, leads me right started.
any thoughts? misunderstanding how vtk's render tools supposed used?
from vtk import* import os.path #import thread #import time #import threading #import curses class myinteractorstyle(vtk.vtkinteractorstyletrackballcamera): pos1 = [0, 0, 200] foc1 = [0, 0, 0] pos2 = [40, 0, 200] foc2 = [0, 0, 0] def __init__(self,parent=none): self.addobserver("middlebuttonpressevent", self.middlebuttonpressevent) self.addobserver("middlebuttonreleaseevent", self.middlebuttonreleaseevent) def middlebuttonpressevent(self,obj,event): print "middle button pressed" self.pos1[2] += 10 self.pos2[2] += 30 self.onmiddlebuttondown() return def middlebuttonreleaseevent(self,obj,event): print "middle button released" self.onmiddlebuttonup() return def main(): # create 2 cameras camera1 = vtkcamera() camera1.setposition(0,0,200) camera1.setfocalpoint(0,0,0) camera2 = vtkcamera() camera2.setposition(40,0,200) camera2.setfocalpoint(0,0,0) # create rendering window , renderer ren1 = vtkrenderer() ren1.setactivecamera(camera1) ren2 = vtkrenderer() ren2.setactivecamera(camera2) # create source reader = vtkpolydatareader() path = "/home/compilezone/documents/3dslicer/slicerscenes/legomodel-6_25/model_5_blood.vtk" reader.setfilename(path) print(path) reader.update() # create render window renwin1 = vtkrenderwindow() renwin1.addrenderer(ren1) renwin2 = vtkrenderwindow() renwin2.addrenderer(ren2) # create render window interactor inputhandler = myinteractorstyle() iren1 = vtkrenderwindowinteractor() iren1.setrenderwindow(renwin1) iren1.setinteractorstyle(inputhandler) iren2 = vtkrenderwindowinteractor() iren2.setrenderwindow(renwin2) iren2.setinteractorstyle(inputhandler) # mapper mapper = vtkpolydatamapper() mapper.setinput(reader.getoutput()) # actor actor = vtkactor() actor.setmapper(mapper) # assign actor renderer ren1.addactor(actor) ren2.addactor(actor) # enable user interface interactor iren1.initialize() iren2.initialize() renwin1.render() renwin2.render() iren1.start() iren2.start() print "test" while 1: pos1 = iren1.getinteractorstyle().pos1 foc1 = iren1.getinteractorstyle().foc1 pos2 = iren2.getinteractorstyle().pos2 foc2 = iren2.getinteractorstyle().foc2 print if __name__ == '__main__': main()
program running keyboardinterrupt (ctrl-c hit , echoed in terminal nothing happens) render windows manually closed, keyboardinterrupt thrown
calling start()
on renderwindowinteractor starts event loop necessary execute render events, event loop in gui. you're trying do, starting 2 event loops, doesn't make sense.
a conceptual workaround not call start
on renderwindowinteractors write small gui multiple toolkit-specific renderwindowinteractors , use gui's event loop.
as example, here's how done gui toolkit-specific code in tvtk's wxvtkrenderwindowinteractor class, doesn't call start on renderwindowinteractor instead uses gui's event loop manage events:
def wxvtkrenderwindowinteractorconeexample(): """like says, simple example """ # every wx app needs app app = wx.pysimpleapp() # create top-level frame, sizer , wxvtkrwi frame = wx.frame(none, -1, "wxvtkrenderwindowinteractor", size=(400,400)) widget = wxvtkrenderwindowinteractor(frame, -1) sizer = wx.boxsizer(wx.vertical) sizer.add(widget, 1, wx.expand) frame.setsizer(sizer) frame.layout() # more correct (api-wise) call widget.initialize() , # widget.start() here, initialize() calls renderwindow.render(). # render() call through before can setup # renderwindow() render via wxwidgets-created context; # causes flashing on platforms , downright breaks things on # other platforms. instead, call widget.enable(). means # rwi::initialized ivar not set, in specific case, # doesn't matter. widget.enable(1) widget.addobserver("exitevent", lambda o,e,f=frame: f.close()) ren = vtk.vtkrenderer() widget.getrenderwindow().addrenderer(ren) cone = vtk.vtkconesource() cone.setresolution(8) conemapper = vtk.vtkpolydatamapper() conemapper.setinput(cone.getoutput()) coneactor = vtk.vtkactor() coneactor.setmapper(conemapper) ren.addactor(coneactor) # show window frame.show() app.mainloop()
(note code not altered , has clear differences trying do.)
also, reason ctrl+c doesn't work because vtk event loop doesn't event. guis respect event, including wxpython. if aren't using gui respects event (for example, qt) can manually tell python interpreter intercept event , crash instead of forwarding event gui event loop:
import signal signal.signal(signal.sigint, signal.sig_dfl)
Comments
Post a Comment