Python VTK 多数据未更新

Python VTK polydata not updating

我正在尝试使用 VTK 绘制点,然后使用一组给定的点位置以交互方式更新它们的位置。

我可以交互式地使用多数据对象来绘制点,但是当我调用 self.polydata.Update() 时它们不会更新。当我调用 self.polydata.GetCellData().SetScalars(someCharArray)

时,积分会更新

这是 VTK 中的错误,还是我没有正确更新点坐标?

我已经包含了一个示例脚本。如果您在 sliderCallback 中注释掉 self.polydata.GetCellData().SetScalars(someCharArray),则当您使用滑块时绘图将不会更新点的坐标。但是,如果您保留该行,它们将更新。

谢谢!

import numpy as np
import vtk
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from PyQt4 import QtGui
import sys

class ViewerWithScrollBar(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(ViewerWithScrollBar, self).__init__(parent)
        # Define the renderer and Qt window ------------------------
        self.frame = QtGui.QFrame()

        self.hl = QtGui.QHBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.hl.addWidget(self.vtkWidget)

        self.ren = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
        self.iren.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
        self.ren.ResetCamera()

        self.frame.setLayout(self.hl)
        self.setCentralWidget(self.frame)

        # Point coordinate data ---------------------------------
        self.coordData = {}
        self.coordData[0] = np.array([[0,0,0], [1,0,0], [1,1,0]])
        self.coordData[1] = self.coordData[0] + np.array([[0.2, 0.1, -0.05], [0,0,0], [0,0,0]])
        self.coordData[2] = self.coordData[1] + np.array([[0.2, 0.1, -0.05], [0,0,0], [0,0,0]])

        # Define the slider bar and add it to the window ---------------
        slider = QtGui.QSlider()
        slider.setAccessibleName('Time index')
        slider.setRange(0, len(self.coordData)-1)
        slider.valueChanged.connect(self.sliderCallback)

        self.hl.addWidget(slider)

        # Create the polydata object -----------------------------
        points = vtk.vtkPoints()
        points.SetNumberOfPoints(len(self.coordData[0]))
        self.polydata = vtk.vtkPolyData()

        for i in range(len(self.coordData[0])):
            points.SetPoint(i, self.coordData[0][i])
        self.polydata.SetPoints(points)

        ptsFilter = vtk.vtkVertexGlyphFilter()
        ptsFilter.SetInputConnection(self.polydata.GetProducerPort())
        ptsMapper = vtk.vtkPolyDataMapper()
        ptsMapper.SetInputConnection(ptsFilter.GetOutputPort())
        ptsActor = vtk.vtkActor()
        ptsActor.SetMapper(ptsMapper)
        ptsActor.GetProperty().SetPointSize(10)

        self.ren.AddActor(ptsActor)

        self.show()
        self.iren.Initialize()

    def sliderCallback(self):
        index = self.sender().value() # The index that the slider bar is currently on
        someCharArray = vtk.vtkUnsignedCharArray()
        points = self.polydata.GetPoints()
        for i in range(len(self.coordData[index])):
            points.SetPoint(i, self.coordData[index][i])
        self.polydata.GetCellData().SetScalars(someCharArray) # For some reason the polydata won't update unless this is called.
        # self.polydata.Update()
        self.iren.Render()
        return

if __name__ == "__main__":

    app = QtGui.QApplication(sys.argv)

    window = ViewerWithScrollBar()

    sys.exit(app.exec_())

在lib的指点下,我修改了代码。在 sliderCallback 方法中调用 self.polydata.Modified() 解决了问题

import numpy as np
import vtk
from vtk.qt4.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from PyQt4 import QtGui
import sys

class ViewerWithScrollBar(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super(ViewerWithScrollBar, self).__init__(parent)
        # Define the renderer and Qt window ------------------------
        self.frame = QtGui.QFrame()

        self.hl = QtGui.QHBoxLayout()
        self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
        self.hl.addWidget(self.vtkWidget)

        self.ren = vtk.vtkRenderer()
        self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
        self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
        self.iren.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
        self.ren.ResetCamera()

        self.frame.setLayout(self.hl)
        self.setCentralWidget(self.frame)

        # Point coordinate data ---------------------------------
        self.coordData = {}
        self.coordData[0] = np.array([[0,0,0], [1,0,0], [1,1,0]])
        self.coordData[1] = self.coordData[0] + np.array([[0.2, 0.1, -0.05], [0,0,0], [0,0,0]])
        self.coordData[2] = self.coordData[1] + np.array([[0.2, 0.1, -0.05], [0,0,0], [0,0,0]])

        # Define the slider bar and add it to the window ---------------
        slider = QtGui.QSlider()
        slider.setAccessibleName('Time index')
        slider.setRange(0, len(self.coordData)-1)
        slider.valueChanged.connect(self.sliderCallback)

        self.hl.addWidget(slider)

        # Create the polydata object -----------------------------
        points = vtk.vtkPoints()
        points.SetNumberOfPoints(len(self.coordData[0]))
        self.polydata = vtk.vtkPolyData()

        for i in range(len(self.coordData[0])):
            points.SetPoint(i, self.coordData[0][i])
        self.polydata.SetPoints(points)

        ptsFilter = vtk.vtkVertexGlyphFilter()
        ptsFilter.SetInputData(self.polydata)
        ptsMapper = vtk.vtkPolyDataMapper()
        ptsMapper.SetInputConnection(ptsFilter.GetOutputPort())
        ptsActor = vtk.vtkActor()
        ptsActor.SetMapper(ptsMapper)
        ptsActor.GetProperty().SetPointSize(10)

        self.ren.AddActor(ptsActor)

        self.show()
        self.iren.Initialize()

    def sliderCallback(self):
        index = self.sender().value() # The index that the slider bar is currently on
        points = self.polydata.GetPoints()
        for i in range(len(self.coordData[index])):
            points.SetPoint(i, self.coordData[index][i])
        self.polydata.Modified()
        self.iren.Render()
        return

if __name__ == "__main__":

    app = QtGui.QApplication(sys.argv)

    window = ViewerWithScrollBar()

    sys.exit(app.exec_())

我修改为PyQt5和运行的版本,并在Windows 10, PyCharm 2018.1 (社区版)。看起来需要修改 "points" 而不是 "self.polydata"。否则,它不会显示更新的点。

import numpy as np
import vtk
from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor
from PyQt5 import Qt
import sys

class ViewerWithScrollBar(Qt.QMainWindow):
    def __init__(self, parent=None):
    super(ViewerWithScrollBar, self).__init__(parent)
    # Define the renderer and Qt window ------------------------
    self.frame = Qt.QFrame()

    self.hl = Qt.QHBoxLayout()
    self.vtkWidget = QVTKRenderWindowInteractor(self.frame)
    self.hl.addWidget(self.vtkWidget)

    self.ren = vtk.vtkRenderer()
    self.vtkWidget.GetRenderWindow().AddRenderer(self.ren)
    self.iren = self.vtkWidget.GetRenderWindow().GetInteractor()
    self.iren.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera())
    self.ren.ResetCamera()

    self.frame.setLayout(self.hl)
    self.setCentralWidget(self.frame)

    # Point coordinate data ---------------------------------
    self.coordData = {}
    self.coordData[0] = np.array([[0,0,0], [1,0,0], [1,1,0]])
    self.coordData[1] = self.coordData[0] + np.array([[0.2, 0.0, -0.05], [0,2,0], [0,0,3.5]])
    self.coordData[2] = self.coordData[1] + np.array([[0.2, 10.0, -0.05], [0,5.0,0], [0,0,0]])

    # Define the slider bar and add it to the window ---------------
    slider = Qt.QSlider()
    slider.setAccessibleName('Time index')
    slider.setRange(0, len(self.coordData)-1)
    slider.valueChanged.connect(self.sliderCallback)

    self.hl.addWidget(slider)

    # Create the polydata object -----------------------------
    points = vtk.vtkPoints()
    points.SetNumberOfPoints(len(self.coordData[0]))
    self.polydata = vtk.vtkPolyData()

    for i in range(len(self.coordData[0])):
        points.SetPoint(i, self.coordData[0][i])
    self.polydata.SetPoints(points)

    self.ptsFilter = vtk.vtkVertexGlyphFilter()
    self.ptsFilter.SetInputData(self.polydata)
    ptsMapper = vtk.vtkPolyDataMapper()
    ptsMapper.SetInputConnection(self.ptsFilter.GetOutputPort())
    self.ptsActor = vtk.vtkActor()
    self.ptsActor.SetMapper(ptsMapper)
    self.ptsActor.GetProperty().SetPointSize(10)

    self.ren.AddActor(self.ptsActor)

    self.show()
    self.iren.Initialize()
    self.iren.Start()

def sliderCallback(self):
    index = self.sender().value() # The index that the slider bar is currently on
    points = self.polydata.GetPoints()
    for i in range(len(self.coordData[index])):
        points.SetPoint(i, self.coordData[index][i])
    points.Modified() # Here you need to call Modified for points
    self.show()
    self.iren.Render()

    return

if __name__ == "__main__":
    app = Qt.QApplication(sys.argv)
    window = ViewerWithScrollBar()
    sys.exit(app.exec_())