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, vtkrenderwindowinteractors 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

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -