VTK的交互器样式(vtkInteractorStyle)通常只是控制相机以及提供一些简单的键盘和鼠标事件的交互技术。交互器样式在渲染场景中并没有一种表达形式,也就是说,在交互时我们看不见交互器样式到底是什么样子的,用户在使用这些交互器样式时,必须事先知道哪些键盘和鼠标事件是控制哪些操作的。然而,渲染场景中的大部分操作都需要直接、简单。比如,如果某条线段的端点可以由用户放置的话,那么沿着某条线段改变倾斜度,就变得非常容易。
Widget就是针对这种功能而设计的。与vtkInteractorStyle类似,Widget也是vtkInteractorObserver的子类。换句话说,它们会监听由vtkRenderWindowInteractor所调用的事件。我们知道,vtkRenderWindowInteractor可以将基于具体操作系统的事件转换成VTK事件。但与vtkInteractorStyle不同的是,Widget在渲染场景中可以用多种不同的表达式。
下面来看Widget的基本使用步骤。
Widget包含两个重要的组成部分:
Interaction
和
Representation
.
Interaction
Interaction
是一些名叫vtk*Widget的类(比如vtkBoxWidget2)。它包含了交互的所有选项和事件处理。
Representation
Representation
是显示并与之交互的一类对象,以名叫vtk*Representation.
用法
创建一个Widget:
vtkSmartPointer<vtkBoxWidget2> boxWidget =
vtkSmartPointer<vtkBoxWidget2>::New();
boxWidget->SetInteractor( renderWindowInteractor );
大多数Widget都有默认的Representation。如果你想改变它,可以手动创建一个Representation并设置到widget.
vtkSmartPointer<vtkBoxRepresentation> boxRep =
vtkSmartPointer<vtkBoxRepresentation>::New();
boxRep->SetPlaceFactor(1);
boxRep->PlaceWidget(actor->GetBounds());
boxWidget->SetRepresentation(boxRep);
事件处理
往往你希望响应用户在Widget上所作的操作,那这时候就需要定义一个vtkCommand的子类,并在一个类似于vtkCallbackFunction回调函数的方法Execute中来处理这些操作。
class vtkBoxCallback : public vtkCommand
{
public:
static vtkBoxCallback *New()
{
return new vtkBoxCallback;
}
vtkSmartPointer<vtkActor> m_actor;
void SetActor(vtkSmartPointer<vtkActor> actor)
{
m_actor = actor;
}
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkSmartPointer<vtkBoxWidget2> boxWidget =
dynamic_cast<vtkBoxWidget2*>(caller);
vtkSmartPointer<vtkTransform> t =
vtkSmartPointer<vtkTransform>::New();
dynamic_cast<vtkBoxRepresentation*>(boxWidget->GetRepresentation())->GetTransform(t);
this->m_actor->SetUserTransform(t);
}
vtkBoxCallback(){}
};
绑定事件
将自定义的事件添加到Widget上,需要创建vtkCommand对象并调用Widget的AddObserver方法。
vtkSmartPointer<vtkBoxCallback> boxCallback =
vtkSmartPointer<vtkBoxCallback>::New();
boxCallback->SetActor(actor);
boxWidget->AddObserver(vtkCommand::InteractionEvent, boxCallback);
启用Widget
使用Widget时,一定要注意顺序:
boxWidget->On();
renderWindowInteractor->Start();
效果
示例代码
#include <vtkSmartPointer.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkBoxWidget2.h>
#include <vtkBoxRepresentation.h>
#include <vtkCommand.h>
#include <vtkTransform.h>
class vtkBoxCallback : public vtkCommand
{
public:
static vtkBoxCallback *New()
{
return new vtkBoxCallback;
}
vtkSmartPointer<vtkActor> m_actor;
void SetActor(vtkSmartPointer<vtkActor> actor)
{
m_actor = actor;
}
virtual void Execute(vtkObject *caller, unsigned long, void*)
{
vtkSmartPointer<vtkBoxWidget2> boxWidget =
dynamic_cast<vtkBoxWidget2*>(caller);
vtkSmartPointer<vtkTransform> t =
vtkSmartPointer<vtkTransform>::New();
dynamic_cast<vtkBoxRepresentation*>(boxWidget->GetRepresentation())->GetTransform(t);
this->m_actor->SetUserTransform(t);
}
vtkBoxCallback(){}
};
int main(int argc, char* argv[])
{
vtkSmartPointer<vtkConeSource> coneSource =
vtkSmartPointer<vtkConeSource>::New();
coneSource->SetHeight(1.5);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(coneSource->GetOutputPort());
vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
renderer->AddActor(actor);
renderer->ResetCamera();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =
vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
renderWindowInteractor->SetInteractorStyle(style);
vtkSmartPointer<vtkBoxWidget2> boxWidget =
vtkSmartPointer<vtkBoxWidget2>::New();
boxWidget->SetInteractor(renderWindowInteractor);
vtkSmartPointer<vtkBoxRepresentation> boxRep =
vtkSmartPointer<vtkBoxRepresentation>::New();
boxRep->SetPlaceFactor(1);
boxRep->PlaceWidget(actor->GetBounds());
boxWidget->SetRepresentation(boxRep);
vtkSmartPointer<vtkBoxCallback> boxCallback =
vtkSmartPointer<vtkBoxCallback>::New();
boxCallback->SetActor(actor);
boxWidget->AddObserver(vtkCommand::InteractionEvent, boxCallback);
boxWidget->On();
renderWindowInteractor->Start();
return 0;
}
Ref