VTK:在用户交互之后,View才会更新

时间:2018-02-02 00:10:14

标签: c++ vtk

TL; DR

我有一个管道,它使用VTK读取图像并显示网格;在将输入更改为图像阅读器并更新管道时,网格不会更新,直到我与窗口交互为止。

长版

我有一个目录,其中包含一系列分段文件(即3D图像体积,其中像素值对应于相应图像中的结构),其显示结构如何随时间变化。我在VTK编写了一个实用程序,它允许我在目录中加载第一个图像,将标签可视化为网格,然后执行" step"通过更改输入图像的文件名并更新管道,使用箭头键前进或后退。这几乎是可行的 - 唯一的问题是,在更新管道之后,网格不会更新,直到我与窗口交互(例如,只需单击窗口中的任何位置就会导致网格更新)。 p>

我尝试过的事情:

  1. 在阅读器上调用Update()

    this->reader->Update();
    
  2. 在演员身上调用Modified()

    const auto actors = this->GetCurrentRenderer()->GetActors();
    actors->InitTraversal();
    for (vtkIdType i = 0; i < actors->GetNumberOfItems(); ++i)
      {
      actors->GetNextActor()->Modified();
      }
    
  3. 在当前渲染窗口中调用Render()

    this->GetCurrentRenderer()->Render();
    
  4. MCVE:

    注意:阅读器已在KeyPressInteractorStyle::UpdateReader()更新。

    // VTK
    #include <vtkSmartPointer.h>
    #include <vtkNIFTIImageReader.h>
    #include <vtkPolyDataMapper.h>
    #include <vtkActor.h>
    #include <vtkRenderer.h>
    #include <vtkRenderWindow.h>
    #include <vtkRenderWindowInteractor.h>
    #include <vtkCamera.h>
    #include <vtkDiscreteMarchingCubes.h>
    #include <vtkProperty.h>
    #include <vtkInteractorStyleTrackballCamera.h>
    
    // Define interaction style
    class KeyPressInteractorStyle : public vtkInteractorStyleTrackballCamera
    {
      public:
        static KeyPressInteractorStyle* New();
        vtkTypeMacro(KeyPressInteractorStyle, vtkInteractorStyleTrackballCamera);
    
        virtual void OnKeyPress() 
        {
          // Get the keypress
          vtkRenderWindowInteractor *rwi = this->Interactor;
          std::string key = rwi->GetKeySym();
    
          // Output the key that was pressed
          std::cout << "Pressed " << key << std::endl;
    
          // Handle an arrow key
          if(key == "Down" || key == "Right")
            {
            this->index += 1;
            this->UpdateReader();
            }
    
          // Handle an arrow key
          if(key == "Up" || key == "Left")
            {
            this->index -= 1;
            this->UpdateReader();
            }
    
          // Forward events
          vtkInteractorStyleTrackballCamera::OnKeyPress();
        }
    
      void UpdateReader()
        {
        std::cout << "Frame: " << this->index << std::endl;
        const auto fn = this->directory + std::to_string(this->index) + ".nii.gz";
        std::cout << fn << std::endl;
        this->reader->SetFileName( fn.c_str() );
        this->reader->Update();
        const auto actors = this->GetCurrentRenderer()->GetActors();
        actors->InitTraversal();
        for (vtkIdType i = 0; i < actors->GetNumberOfItems(); ++i)
          {
          actors->GetNextActor()->Modified();
          }
        this->GetCurrentRenderer()->Render();
        }
      unsigned int index = 0;
      std::string directory;
      vtkSmartPointer<vtkNIFTIImageReader> reader;
    };
    vtkStandardNewMacro(KeyPressInteractorStyle);
    
    int
    main( int argc, char ** argv )
    {
    
      std::string dn = argv[1];
    
      const auto renderer = vtkSmartPointer<vtkRenderer>::New();
    
      unsigned int frameid = 0;
    
      const auto reader = vtkSmartPointer<vtkNIFTIImageReader>::New();
      reader->SetFileName( (dn + std::to_string(frameid) + ".nii.gz").c_str() );
    
      const auto cubes = vtkSmartPointer<vtkDiscreteMarchingCubes>::New();
      cubes->SetInputConnection( reader->GetOutputPort() );
    
      cubes->SetValue( 0, 1 );
    
      const auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
      mapper->SetInputConnection( cubes->GetOutputPort() );
      mapper->ScalarVisibilityOff();
      const auto actor = vtkSmartPointer<vtkActor>::New();
      actor->SetMapper( mapper );
      renderer->AddActor( actor );
    
      const auto window = vtkSmartPointer<vtkRenderWindow>::New();
      window->AddRenderer( renderer );
      const auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    
      const auto style = vtkSmartPointer<KeyPressInteractorStyle>::New();
      style->reader = reader;
      style->directory = dn;
      interactor->SetInteractorStyle( style );
      style->SetCurrentRenderer( renderer );
    
      interactor->SetRenderWindow( window );
    
      window->Render();
    
      interactor->Start();
    
      return EXIT_SUCCESS;
    
    }
    

1 个答案:

答案 0 :(得分:2)

你实际上试图在当前渲染窗口上调用Render(),而是在当前渲染器上调用它,这是两个不同的东西。作为vtkRenderer::Renderer()州的文件,

  

仅限vtkRenderWindow。

     

最终用户通过你的方式并调用vtkRenderWindow :: Render()。创建一个   图片。这是一个超类方法,它将依次调用   vtkRenderer子类的DeviceRender方法。

所以将this->GetCurrentRenderer()->Render();更改为this->GetCurrentRenderer()->GetRenderWindow()->Render();