визуализация vtk с некоторым взаимодействием внутри приложения PyQT - PullRequest
0 голосов
/ 07 октября 2019

Я новичок здесь. Вот мои спецификации: Mac OS X, python 3.7.4, VTK 8.1.2 и PyQt 5.13.1

Я пытаюсь собрать в python и приложение, используя PyQT5, где я могу запустить следующий пример:

https://vtk.org/Wiki/VTK/Examples/Python/Interaction/HighlightAPickedActor

, где в трехмерном пространстве есть сфера, где можно выбрать одну сферу, которая становится красной.

Вот мой код:

import sys
import vtk

try:
    from PyQt5.QtWidgets import QMainWindow, QAction, qApp, QApplication
    from PyQt5.QtWidgets import QWidget, QSizePolicy, QPushButton, QVBoxLayout, QFrame

    from PyQt5.QtGui import QIcon
    from PyQt5.QtCore import Qt, pyqtSignal, QTimer, QObject, QSize, QEvent
except ImportError:
    raise ImportError("Cannot load either PyQt5")

from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor    


NUMBER_OF_SPHERES = 10

class MouseInteractorHighLightActor(vtk.vtkInteractorStyleTrackballCamera):

    def __init__(self,parent=None):
        self.AddObserver("LeftButtonPressEvent",self.leftButtonPressEvent)

        self.LastPickedActor = None
        self.LastPickedProperty = vtk.vtkProperty()

    def leftButtonPressEvent(self,obj,event):
        clickPos = self.GetInteractor().GetEventPosition()

        picker = vtk.vtkPropPicker()
        picker.Pick(clickPos[0], clickPos[1], 0, self.GetDefaultRenderer())

        # get the new
        self.NewPickedActor = picker.GetActor()

        # If something was selected
        if self.NewPickedActor:
            # If we picked something before, reset its property
            if self.LastPickedActor:
                self.LastPickedActor.GetProperty().DeepCopy(self.LastPickedProperty)


            # Save the property of the picked actor so that we can
            # restore it next time
            self.LastPickedProperty.DeepCopy(self.NewPickedActor.GetProperty())
            # Highlight the picked actor by changing its properties
            self.NewPickedActor.GetProperty().SetColor(1.0, 0.0, 0.0)
            self.NewPickedActor.GetProperty().SetDiffuse(1.0)
            self.NewPickedActor.GetProperty().SetSpecular(0.0)

            # save the last picked actor
            self.LastPickedActor = self.NewPickedActor

        self.OnLeftButtonDown()
        return

class Menu(QMainWindow):

    def __init__(self):
        super().__init__()
        self.initUI()


    def initUI(self):               

        exitAct = QAction(QIcon('exit.png'), ' &Quit', self)   
        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Exit application')
        exitAct.triggered.connect(qApp.quit)

        self.statusBar()

        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAct)

        bar = self.menuBar()
        file = bar.addMenu("Edit")
        file.addAction("New")

        self.setGeometry(300, 300, 300, 200)
        self.setWindowTitle('Simple menu')    
        self.show()

        self.frame = QFrame()
        self.vl = QVBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)

        self.vl.addWidget(self.vtkWidget)



        self.renderer = vtk.vtkRenderer()
        self.renderer.SetBackground(.3, .4, .5 )

        self.renwin = vtk.vtkRenderWindow()
        self.renwin.AddRenderer(self.renderer)



        # An interactor
        self.inter = vtk.vtkRenderWindowInteractor()
        self.inter.SetRenderWindow(self.renwin)

        # add the custom style
        self.style = MouseInteractorHighLightActor()
        self.style.SetDefaultRenderer(self.renderer)
        self.vtkWidget.GetRenderWindow().AddRenderer(self.renderer)
        #self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
        self.inter.SetInteractorStyle(self.style)
        #self.iren.SetInteractorStyle(self.inter)
        #self.iren = self.vtkWidget.GetRenderWindow().SetInteractor(self.inter)


        # Add spheres to play with
        for i in range(NUMBER_OF_SPHERES):
            source = vtk.vtkSphereSource()

            # random position and radius
            x = vtk.vtkMath.Random(-5,5)
            y = vtk.vtkMath.Random(-5,5)
            z = vtk.vtkMath.Random(-5,5)
            radius = vtk.vtkMath.Random(.5, 1.0)

            source.SetRadius(radius)
            source.SetCenter(x, y, z)
            source.SetPhiResolution(11)
            source.SetThetaResolution(21)

            mapper = vtk.vtkPolyDataMapper()
            mapper.SetInputConnection(source.GetOutputPort())
            actor = vtk.vtkActor()
            actor.SetMapper(mapper)

            r = vtk.vtkMath.Random(.4, 1.0)
            g = vtk.vtkMath.Random(.4, 1.0)
            b = vtk.vtkMath.Random(.4, 1.0)
            actor.GetProperty().SetDiffuseColor(r, g, b)
            actor.GetProperty().SetDiffuse(.8)
            actor.GetProperty().SetSpecular(.5)
            actor.GetProperty().SetSpecularColor(1.0,1.0,1.0)
            actor.GetProperty().SetSpecularPower(30.0)

            #renderer.AddActor(actor)
            self.renderer.AddActor(actor)


        self.renderer.ResetCamera()

        self.frame.setLayout(self.vl)
        self.setCentralWidget(self.frame)

        self.show()

        self.inter.Initialize()
        self.inter.Start()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Menu()
    sys.exit(app.exec_())        

Однако, несмотря на то, что мой код запущен, я получаю два отдельных окна: «меню» с одной стороны и средство визуализации vtk как другое окно. Я хотел бы знать, что я делаю неправильно, если вы хотите мне помочь.

Заранее спасибо

1 Ответ

1 голос
/ 07 октября 2019

Появляется второе окно, потому что в Menu.initUI вы создаете отдельные экземпляры vtkRenderWindow и vtkRenderWindowInteractor вместо тех, которые предоставлены вашим QVTKRenderWindowInteractor объектом. Поэтому вам следует заменить эту строку

self.renwin = vtk.vtkRenderWindow()

на эту

self.renwin = self.vtkWidget.GetRenderWindow()

, а эти две строки

self.inter = vtk.vtkRenderWindowInteractor()
self.inter.SetRenderWindow(self.renwin)

на эту

self.inter = self.renwin.GetInteractor()
...