2017-05-25 161 views
1

我有一个基本的问题,因为我是VTK的新手。我必须在VTK中绘制实时点云数据。我修改了How to display point cloud in vtk in different colors?中给出的代码。在vtk更新直播点云数据python

pointcloud应该更新迭代次数(这里是30)的次数。我已经使用Initialize()来避免阻塞控制流,正如在某些解决方案中提到的那样,每次迭代中都会更新点云,并调用render()以便它可以用新数据更新窗口。

我不明白为什么这会阻止控制流,并且数据不会更新。只有迭代结束后,renderWindowInteractor.Start()被调用后,才会启用交互。

import vtk 
from numpy import random 

class VtkPointCloud: 

    def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6): 
     self.maxNumPoints = maxNumPoints 
     self.vtkPolyData = vtk.vtkPolyData() 
     self.clearPoints() 
     mapper = vtk.vtkPolyDataMapper() 
     mapper.SetInputData(self.vtkPolyData) 
     mapper.SetColorModeToDefault() 
     mapper.SetScalarRange(zMin, zMax) 
     mapper.SetScalarVisibility(1) 
     self.vtkActor = vtk.vtkActor() 
     self.vtkActor.SetMapper(mapper) 

    def addPoint(self, point): 
     if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints: 
      pointId = self.vtkPoints.InsertNextPoint(point[:]) 
      self.vtkDepth.InsertNextValue(point[2]) 
      self.vtkCells.InsertNextCell(1) 
      self.vtkCells.InsertCellPoint(pointId) 
     else: 
      r = random.randint(0, self.maxNumPoints) 
      self.vtkPoints.SetPoint(r, point[:]) 
     self.vtkCells.Modified() 
     self.vtkPoints.Modified() 
     self.vtkDepth.Modified() 

    def clearPoints(self): 
     self.vtkPoints = vtk.vtkPoints() 
     self.vtkCells = vtk.vtkCellArray() 
     self.vtkDepth = vtk.vtkDoubleArray() 
     self.vtkDepth.SetName('DepthArray') 
     self.vtkPolyData.SetPoints(self.vtkPoints) 
     self.vtkPolyData.SetVerts(self.vtkCells) 
     self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth) 
     self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray') 

def func(pointCloud): 
    # Renderer 
    renderer = vtk.vtkRenderer() 
    renderer.AddActor(pointCloud.vtkActor) 
    renderer.SetBackground(.2, .3, .4) 
    renderer.ResetCamera() 

    # Render Window 
    renderWindow = vtk.vtkRenderWindow() 

    renderWindow.AddRenderer(renderer) 

    # Interactor 
    renderWindowInteractor = vtk.vtkRenderWindowInteractor() 
    renderWindowInteractor.SetRenderWindow(renderWindow) 

    # Begin Interaction 
    renderWindow.Render() 
    renderWindowInteractor.Initialize() 
    return renderWindow,renderWindowInteractor 

def main(iter): 
    while iter > 0: 
     pointCloud = VtkPointCloud() 
     for k in xrange(10000): 
      point = 20*(random.rand(3)-0.5) 
      pointCloud.addPoint(point) 
     pointCloud.addPoint([0,0,0]) 
     pointCloud.addPoint([0,0,0]) 
     pointCloud.addPoint([0,0,0]) 
     pointCloud.addPoint([0,0,0]) 
     if iter == 30: 
      renderWindow,renderWindowInteractor = func(pointCloud) 
     else: 
      #pointCloud.vtkPolyData.Modified() 
      renderWindow.Render() 
     iter -= 1 
    renderWindowInteractor.Start() 

main(30) 

回答

0

所以你想做一个动画。 更好的做法是按照this sample解释如何使用TimerEvent。

下面是它看起来就像你的代码:

import vtk 
from numpy import random 


class VtkPointCloud: 

    def __init__(self, zMin=-10.0, zMax=10.0, maxNumPoints=1e6): 
     self.maxNumPoints = maxNumPoints 
     self.vtkPolyData = vtk.vtkPolyData() 
     self.clearPoints() 
     mapper = vtk.vtkPolyDataMapper() 
     mapper.SetInputData(self.vtkPolyData) 
     mapper.SetColorModeToDefault() 
     mapper.SetScalarRange(zMin, zMax) 
     mapper.SetScalarVisibility(1) 
     self.vtkActor = vtk.vtkActor() 
     self.vtkActor.SetMapper(mapper) 

    def addPoint(self, point): 
     if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints: 
      pointId = self.vtkPoints.InsertNextPoint(point[:]) 
      self.vtkDepth.InsertNextValue(point[2]) 
      self.vtkCells.InsertNextCell(1) 
      self.vtkCells.InsertCellPoint(pointId) 
     else: 
      r = random.randint(0, self.maxNumPoints) 
      self.vtkPoints.SetPoint(r, point[:]) 
     self.vtkCells.Modified() 
     self.vtkPoints.Modified() 
     self.vtkDepth.Modified() 

    def clearPoints(self): 
     self.vtkPoints = vtk.vtkPoints() 
     self.vtkCells = vtk.vtkCellArray() 
     self.vtkDepth = vtk.vtkDoubleArray() 
     self.vtkDepth.SetName('DepthArray') 
     self.vtkPolyData.SetPoints(self.vtkPoints) 
     self.vtkPolyData.SetVerts(self.vtkCells) 
     self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth) 
     self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray') 


class AddPointCloudTimerCallback(): 
    def __init__(self, renderer, iterations): 
     self.iterations = iterations 
     self.renderer = renderer 

    def execute(self, iren, event): 
     if self.iterations == 0: 
      iren.DestroyTimer(self.timerId) 
     pointCloud = VtkPointCloud() 
     self.renderer.AddActor(pointCloud.vtkActor) 
     pointCloud.clearPoints() 
     for k in xrange(10000): 
      point = 20*(random.rand(3)-0.5) 
      pointCloud.addPoint(point) 
     pointCloud.addPoint([0,0,0]) 
     pointCloud.addPoint([0,0,0]) 
     pointCloud.addPoint([0,0,0]) 
     pointCloud.addPoint([0,0,0]) 
     iren.GetRenderWindow().Render() 
     if self.iterations == 30: 
      self.renderer.ResetCamera() 

     self.iterations -= 1 

if __name__ == "__main__": 
    # Renderer 
    renderer = vtk.vtkRenderer() 
    renderer.SetBackground(.2, .3, .4) 
    renderer.ResetCamera() 

    # Render Window 
    renderWindow = vtk.vtkRenderWindow() 

    renderWindow.AddRenderer(renderer) 

    # Interactor 
    renderWindowInteractor = vtk.vtkRenderWindowInteractor() 
    renderWindowInteractor.SetRenderWindow(renderWindow) 
    renderWindowInteractor.Initialize() 

    # Initialize a timer for the animation 
    addPointCloudTimerCallback = AddPointCloudTimerCallback(renderer, 30) 
    renderWindowInteractor.AddObserver('TimerEvent', addPointCloudTimerCallback.execute) 
    timerId = renderWindowInteractor.CreateRepeatingTimer(10) 
    addPointCloudTimerCallback.timerId = timerId 

    # Begin Interaction 
    renderWindow.Render() 
    renderWindowInteractor.Start() 

注意,我改名ITER到迭代,因为ITER是Python中的保留名称。

+1

谢谢,这正是我想要的。只是一个小修正,renderWindowInteractor应该在创建定时器之前初始化。 –

+0

不客气。我没有看到你提到的错误。此外,我在这里很新,但我认为有一个按钮可以将问题标记为“已解决”,因为“清理”的目的。 –

+0

谢谢,很好的建议。我刚开始认为,通过“初始化”你的意思是“对象创建”(已经是这种情况),但实际上你的意思是“调用方法Initialize()”。 –