将转换应用到 PolyData

Apply transformation to PolyData

我希望能够将转换应用于 Polydata,但无论我如何尝试,它就是行不通。

这是我在 class 调用 Drawing.cpp 中对 "drawing" 我的多数据的了解:

Drawing.h

vtkSmartPointer<vtkPlane> clipPlane; 
vtkSmartPointer<vtkImplicitPlaneRepresentation> planeRep; 
vtkSmartPointer<vtkActor> actorPlaneSource; 
vtkSmartPointer<vtkActor> mainActor; 

vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter; 
vtkSmartPointer<vtkTransform> translation ; 
vtkContextView* ctxView ; 
vtkRenderWindow* win ; 
vtkRenderer* ren ; 
vtkCamera* cam ; 
vtkSmartPointer<vtkPolyData> inputPolyData;

然后调用读取函数并开始渲染,这里是drawing.cpp中的函数:

void Drawing::read(){ 

        std::string filename = BUNNY; 
        // Read all the data from the file 
        vtkSmartPointer<vtkXMLPolyDataReader> reader =vtkSmartPointer<vtkXMLPolyDataReader>::New(); 
        reader->SetFileName(filename.c_str()); 
        reader->Update(); 
        inputPolyData = reader->GetOutput(); 

        cout << "File Found and Loaded : " << filename << endl ; 

        vtkSmartPointer<vtkTransform> translation = vtkSmartPointer<vtkTransform>::New(); 
        translation->Translate(0.3, -0.05, 0); 
        transformFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New(); 
        //transformFilter->SetInputConnection(reader->GetOutputPort()); 
        transformFilter->SetInputData(inputPolyData); 
        transformFilter->SetTransform(translation); 
        //transformFilter->Update(); 

        vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); 
        mapper->SetInputConnection(transformFilter->GetOutputPort()); 

        mainActor = vtkSmartPointer<vtkActor>::New(); 
        mainActor->SetMapper(mapper); 

        ren->AddActor(mainActor); 

        vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); 
        iren->SetRenderWindow(win); 
        vtkInteractorStyleMultiTouchCamera *style = 
        vtkInteractorStyleMultiTouchCamera::New(); 
        iren->SetInteractorStyle(style); 

        //Start the event loop 
        iren->Initialize(); 
        iren->Start(); 

        defineClipping(); 
        win->PolygonSmoothingOn(); 
        win->Render(); 
        win->Start(); 
} 

由此,我有另一个线程 运行 一个服务器,它获取消息并有一个指向我的绘图对象的指针,并且应该根据从其客户端获得的消息调用这三个函数之一:

void Drawing::scale(float k){ 
        vtkSmartPointer<vtkTransform> transform =vtkSmartPointer<vtkTransform>::New(); 
        transform->Scale(5,1,1); 
        vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New(); 
        transformFilter->SetInputConnection(cone->GetOutputPort()); 
        transformFilter->SetTransform(transform); 
        mapper->SetInputConnection(transformFilter->GetOutputPort()); 
        ren->GetActiveCamera(); 
} 

void Drawing::translate(float x, float y, float z){ 
        cout << "Translate: " << x << " - " << " - " << y << " - " << z << endl ; 
        vtkSmartPointer<vtkTransform> transform1a = vtkSmartPointer<vtkTransform>::New(); 
        //transform1a->Translate(x,y,z); 
        //transformFilter->SetTransform(transform1a); 
        //transformFilter->Update(); 
        double* position = mainActor->GetPosition(); 
        mainActor->SetPosition(position[0]+x,position[1]+y,position[2]+z); 
} 

void Drawing::rotate(float x, float y, float z){ 
        cout << "Rotate: " << x << " - " << " - " << y << " - " << z << endl ; 
        vtkSmartPointer<vtkTransform> transform1a = vtkSmartPointer<vtkTransform>::New(); 
        //transform1a->PostMultiply(); 
        //transform1a->RotateX(x); 
        //transform1a->RotateY(y); 
        //transform1a->RotateZ(z); 
        //mainActor->SetUserTransform(transform1a); 
        mainActor->RotateWXYZ(20,1,0,0); 

}

None 这些函数之所以有效,是因为渲染 windows 中没有任何变化,除非我单击渲染 window 本身。 所以我想也许我应该尝试添加到每个转换函数中:ctxView->Render(); 但是当我这样做时,我得到:

Error the ressource is already busy.

我是 VTK 的新手,但我觉得很奇怪,我什至不能对对象进行简单的转换。真的很想得到一些帮助。

编辑: 好吧,在尝试不同的事情几个小时后,我注意到如果我注释掉 iren->Start(); 行,我的旋转和平移就会被调用。但是,程序一完成就关闭,我无法再与我的 window 交互。您对此有何见解?

提前致谢。

是的,我可以尝试提供一些对多数据进行旋转的代码,但我想这与您的管道有所不同(我使用 vtkImageReslice 对象作为 m_pReslice):

int nExtent[3];
double dSpacing[3];
double dOrigin[3];

m_pReader->GetOutput()->GetSpacing(dSpacing);
m_pReader->GetOutput()->GetOrigin(dOrigin);
m_pReader->GetOutput()->GetDimensions(nExtent);

double dCenter[3];
dCenter[0] = dOrigin[0] + dSpacing[0] * 0.5 * nExtent[0];   // nExtent[0] is width
dCenter[1] = dOrigin[1] + dSpacing[1] * 0.5 * nExtent[1];   // nExtent[1] is height
dCenter[2] = dOrigin[2] + dSpacing[2] * 0.5 * nExtent[2];   // nExtent[2] is depth

vtkSmartPointer<vtkTransform> pTransform = vtkSmartPointer<vtkTransform>::New();
pTransform->PreMultiply();

int nDirection = CDirectionDlg::GetDirection();
if(CDirectionDlg::DIR_AXIAL == nDirection)
{
    pTransform->Translate(dCenter[0], 0, dCenter[2]);
    pTransform->RotateY(180);
    pTransform->Translate(-dCenter[0], 0, -dCenter[2]);
}
else
{
    pTransform->Translate(dCenter[0], dCenter[1], 0);
    pTransform->RotateZ(180);
    pTransform->Translate(-dCenter[0], -dCenter[1], 0);
}

m_pReslice->SetResliceTransform(pTransform);
m_pReslice->SetInterpolationModeToLinear();
m_pReslice->Update();

考虑另一种在视图中旋转对象的方法是移动相机......我希望它能帮助你。

正如 flaviu2 所写,你绝对需要调用

ren->Render();

更新您的 vtkTransform 之后。渲染器不会观察正在渲染的 VTK 对象以查看是否有任何更新。您需要显式调用 Render() 成员函数。

注意线程。可以使用线程,但大多数 VTK 都不是线程安全的,这可能会让您有些头疼。为了将这个问题与使用不同线程更新对象引起的潜在问题区分开来,我会尝试在没有线程的情况下让它工作,如果你仍然遇到问题,请更新这个问题。

由于您的问题是交互器,请尝试执行此 hack。它所做的是为交互器创建一个计时器,这将有助于摆脱启动阻塞方法:

class CommandSubclass2 : public vtkCommand
{
  public:
    vtkTypeMacro(CommandSubclass2, vtkCommand);

    static CommandSubclass2 *New()
    {
        return new CommandSubclass2;
    }

    void Execute(vtkObject *vtkNotUsed(caller), unsigned long vtkNotUsed(eventId), 
                    void *vtkNotUsed(callData))
    {
        std::cout << "timer callback" << std::endl;
        renderWindowInteractor->ExitCallback();
    }
};

// 在你的 main

vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); 
iren->SetRenderWindow(win); 

iren->CreateRepeatingTimer(1);

 vtkSmartPointer<CommandSubclass2> timerCallback = 
      vtkSmartPointer<CommandSubclass2>::New();
iren->AddObserver ( vtkCommand::TimerEvent, timerCallback );

vtkInteractorStyleMultiTouchCamera *style = 
        vtkInteractorStyleMultiTouchCamera::New(); 
iren->SetInteractorStyle(style); 



while(true)
{
    iren->Start();     
    ren->Render();
}

可能不是这样做的好方法,但我不知道还有什么其他方法可以摆脱交互器阻塞方法start()

感谢这里的人的帮助以及对代码和文档的一些研究,我发现我的代码中的这一部分在尝试 rotate/translate/scale 我的 Polydata 时没有发生任何事情:

//Start the event loop
iren->Initialize();
iren->Start();

实际上 vtkRenderWindowInteractorstart() 方法正在阻塞,因此无论我之后可以调用什么都没有被处理。摆脱它允许我调用我的转换函数。然而,由于失去了与数据的可能交互,并且 window 在每次应用转换后立即关闭。