将转换应用到 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();
实际上 vtkRenderWindowInteractor
的 start()
方法正在阻塞,因此无论我之后可以调用什么都没有被处理。摆脱它允许我调用我的转换函数。然而,由于失去了与数据的可能交互,并且 window 在每次应用转换后立即关闭。
我希望能够将转换应用于 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();
实际上 vtkRenderWindowInteractor
的 start()
方法正在阻塞,因此无论我之后可以调用什么都没有被处理。摆脱它允许我调用我的转换函数。然而,由于失去了与数据的可能交互,并且 window 在每次应用转换后立即关闭。