2017-05-25 2 views
1

J'ai une question de base que je suis nouveau à VTK. Je dois dessiner des données de nuage de points en direct dans VTK. J'ai modifié le code donné en How to display point cloud in vtk in different colors?. Le pointcloud doit être mis à jour pour le nombre de fois indiqué par itérations (ici 30). J'ai utilisé Initialize() pour éviter de bloquer le flux de contrôle comme mentionné dans certaines solutions, dans chaque itération le nuage de points est mis à jour, et render() est appelé pour pouvoir mettre à jour la fenêtre avec de nouvelles données.mettre à jour les données pointcloud en direct dans vtk python

Je n'arrive pas à comprendre pourquoi cela bloque le flux de contrôle et les données ne sont pas mises à jour. Une fois les itérations terminées, après l'appel de renderWindowInteractor.Start(), l'interaction est activée.

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) 

Répondre

0

Donc vous voulez faire une animation. Une meilleure pratique est de suivre this sample en expliquant comment utiliser un événement TimerEvent.

Voici ce qu'il ressemblerait avec votre code:

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() 

Notez que je iter aux itérations parce retitré iter est un nom réservé en Python.

+1

merci, c'est exactement ce que je voulais. Juste une petite correction, renderWindowInteractor devrait être initialisé avant de créer le timer. –

+0

De rien. Je ne vois pas l'erreur que vous mentionnez. Aussi, je suis assez nouveau ici, mais je pense qu'il y a un bouton pour marquer une question comme "résolu", pour "nettoyer" le but. –

+0

Merci, excellente suggestion. Je pensais d'abord que par "initialisé" vous vouliez dire "création d'objet" (c'était déjà le cas), mais en fait vous vouliez dire "appeler la méthode Initialize()". –