vtkRenderWindowInteractor停止程序

发黑的牙齿

我一直在研究使用VTK进行3D模型的立体成像的Python原型应用程序,但是我在接口方面遇到了一些问题。目前,以下代码的目标是在按下中间鼠标时放大两个renderWindows。但是,在调用该vtkRenderWindowInteractor.Start()函数时,我的vtkRenderWindowInteractors实际上使整个程序停顿了下来,就好像它们在同一线程中运行一样。更令人好奇的是,当我使用CTRL-C(在UNIX shell中工作)时,直到使用“ x”按钮手动关闭渲染窗口时,才会引发键盘中断。如果我只是手动关闭窗口而不按CTRL-C,则程序会在Start()调用(例如,下面的代码中的无限while循环)。在本文的结尾处,我提供了一系列屏幕截图,以直观地显示我的解释令人困惑的情况。

我已经尝试了多种解决方法来解决此问题,但到目前为止都没有奏效。即使我尝试使用ncurses进行输入,将渲染器线程化为孤立的线程也没有什么区别,而将它们分叉到一个新进程中却导致了一些我宁愿不处理的OS问题。我刚刚使用内置的VTK侦听器的最新的交互器样式方法(如下所示)在一定程度上可以正常工作,允许我在窗口处于焦点且交互器处于活动状态时检测输入,但是由于缺少交互关系摄像头和MyInteractorStyle班级,如果没有在Start()通话后添加循环,我将无法真正访问摄像头,这使我回到了起点。

有什么想法吗?我只是在误解应该如何使用VTK的渲染工具?

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 two 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 a rendering window and 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 a 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 to the 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()  

程序正在运行KeyboardInterrupt(在终端中按CTRL-C并在其中回显,但没有任何反应)渲染窗口手动关闭,抛出KeyboardInterrupt

Aestrivex

调用Start()RenderWindowInteractor会启动执行渲染事件所需的事件循环,就像GUI中的事件循环一样。因此,您要尝试执行的操作(启动两个事件循环)并没有任何意义。

一个理论上的解决方法是不调用StartRenderWindowInteractors,而是编写一个带有多个特定于工具包的RenderWindowInteractors的小型GUI,并使用该GUI的事件循环。

As an example, here's how this is done with GUI toolkit-specific code in tvtk's wxVtkRenderWindowInteractor class, which doesn't call start on the RenderWindowInteractor but instead uses the GUI's event loop to manage events:

def wxVTKRenderWindowInteractorConeExample():
 """Like it says, just a simple example
 """
 # every wx app needs an app
 app = wx.PySimpleApp()

 # create the top-level frame, sizer and 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()

 # It would be more correct (API-wise) to call widget.Initialize() and
 # widget.Start() here, but Initialize() calls RenderWindow.Render().
 # That Render() call will get through before we can setup the
 # RenderWindow() to render via the wxWidgets-created context; this
 # causes flashing on some platforms and downright breaks things on
 # other platforms.  Instead, we call widget.Enable().  This means
 # that the RWI::Initialized ivar is not set, but in THIS SPECIFIC CASE,
 # that 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 the window
 frame.Show()

 app.MainLoop()

(Note that this code is not altered and has some clear differences with what you are trying to do.)

Also, the reason that ctrl+C doesn't work is because the VTK event loop doesn't do anything with this event. Some GUIs do respect this event, including wxpython. But if you aren't using a GUI that respects this event (for example, Qt) you can manually tell the python interpreter to intercept this event and crash instead of forwarding the event to the GUI event loop:

import signal
signal.signal(signal.SIGINT, signal.SIG_DFL)

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章