c++ - VTK:直到用户交互后 View 才会更新

标签 c++ vtk

长话短说

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

长版

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

我尝试过的:

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

    this->reader->Update();
    
  2. 在 actor 上调用 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();
    

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;

}

最佳答案

您实际上没有尝试在当前渲染窗口上调用 Render(),您是在当前渲染器上调用它,这是两个不同的事情。作为 vtkRenderer::Renderer() 的文档州,

CALLED BY vtkRenderWindow ONLY.

End-user pass your way and call vtkRenderWindow::Render(). Create an image. This is a superclass method which will in turn call the DeviceRender method of Subclasses of vtkRenderer.

所以把this->GetCurrentRenderer()->Render();改成this->GetCurrentRenderer()->GetRenderWindow()->Render();

关于c++ - VTK:直到用户交互后 View 才会更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48573811/

相关文章:

c++ - 如何在预处理阶段获取 C++ 函数调用者名称

c++ - "variable"的定义是什么?

C++11 随机数和 std::bind 以意想不到的方式交互

linux - 如何启用 vtk "direct"硬件渲染,X11/Ubuntu 11.04 x86-64?

c++ - 数组 [] 运算符返回一个引用,那么如何更改它的值呢?

python - Paraview 用户输入弹出窗口

c++ - 在XCode 7.0.1中设置VTK 6.1

vtk - CGAL与VTK

c++ - 如何围绕特定点旋转 vtk 场景?

c++ - C++ 中纹理数据指针的 union