關於vtk中的交互方式(VTk交互)以及widget交互模式(widget交互)在前面的博客裏有介紹。這裏主要簡單介紹幾個具體的和測量相關的widget: vtkAngleWidget(角度測量) 、vtkDistanceWidget(距離測量) 、vtkSplineWidget(樣條部件)。 最後一個vtkSplineWidget是擬合樣條的顯示部件,本人把其當作曲線長度測量工具。由於其本身不能顯示長度信息,所以對其進行了擴展,使其能夠實時顯示長度信息。這個文章後面會具體提及。三個部件的樣式如下:
vtk部件實例化的一般步驟:
1.實例化Widget;
2.指定渲染窗口交互器。Widget可以通過它來監聽用戶事件。
3.必要時使用觀察者/命令模式創建回調函數。與widget交互時,它會調用一些通用的VTK事件(94個事件列表),如StartInteractionEvent、InteractionEvent、EndInteractionEvent。用戶通過監聽這些事件並作出響應,從而可以更新數據、可視化參數或者應用程序的用戶圖形界面。
4.創建合適幾何表達實體。用SetRepresentation()函數把他與Widget關聯起來,或者使用Widget默認的幾何表達實體。
5.最後,必須激活Widget,使其在渲染場景中顯示。默認情況下,按鍵<I>用於激活Widget,使其在場景中可見。
以vtkdAngleWidget爲例子具體說明vtk實現方法。
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkAngleWidget.h>
#include <vtkAngleRepresentation2D.h>
#include <vtkTextWidget>
//角度顯示回調類
class vtkAngleCallBack : public vtkCommand
{
public:
static vtkAngleCallBack *New()
{
return new vtkAngleCallBack;
}
virtual void Execute(vtkObject *caller, unsigned long eventId, void *callData)
{
if(!m_text)
return;
if(eventId == vtkCommand::StartInteractionEvent)
m_text->On();
if(eventId == vtkCommand::InteractionEvent){
char text[200];
sprintf(text,"Angle: %f",m_angle->GetAngle());
m_text->GetTextActor()->SetInput(text);
}
}
vtkAngleWidget *m_angle = nullptr;
vtkTextWidget *m_text = nullptr;
};
int main(int argc, char *argv[])
{
// A renderer and render window
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
vtkSmartPointer<vtkRenderWindow> renderWindow =
vtkSmartPointer<vtkRenderWindow>::New();
renderWindow->AddRenderer(renderer);
// An interactor
vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
renderWindowInteractor->SetRenderWindow(renderWindow);
//實例化幾何表達
vtkSmartPointer<vtkAngleRepresentation2D> rep =
vtkSmartPointer<vtkAngleRepresentation2D>::New();
rep->ArcVisibilityOff();
//實例化vtkAngleWidget
vtkSmartPointer<vtkAngleWidget> angleWidget =
vtkSmartPointer<vtkAngleWidget>::New();
angleWidget->SetRepresentation(rep); //添加集合表達
angleWidget->SetInteractor(renderWindowInteractor); //添加交互器
//角度顯示面板
vtkSmartPointer<vtkTextWidget> textWidget =
vtkSmartPointer<vtkTextWidget>::New();
textWidget->CreateDefaultRepresentation();
//實例化回調類
vtkSmartPointer<vtkAngleCallBack> callBack =
vtkSmartPointer<vtkAngleCallBack>::New();
callBack->m_angle = angleWidget;
callBack->m_text = textWIdget;
angleWidget->AddObserver(vtkCommand::InteractionEvent,callBack);//添加回調類
renderWindow->Render();
renderWindowInteractor->Initialize();
renderWindow->Render();
angleWidget->On();//調用On函數激活angleWidget
textWIdget->On(); //調用On函數激活textWidget
// Begin mouse interaction
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
vtk部件將事件交互相應與實體表達分離開。widget部件本身主要響應各種事件,而部件實體表達交由vtkRepresentation來完成。可以通過調用widget->CreateDefaultRepresentation();函數創建默認表達。也可以像上面那樣自己實例化一個表達實體添加進去。實際使用時候有幾個可能會用到的成員函數 這裏提一下:
SetWidgetStateToStart();
調用該函數 此時會重置部件爲開始狀態,此時表達實體恢復不顯示狀態 通過鼠標交互來設置三個點。
SetWidgetStateToManipulate();
調用此函數 狀態設置爲“Manipulate”,則假定該窗口小部件及其表示將以編程方式初始化,而不是以交互方式放置。
vtkSplineWidget本身並不顯示長度信息,本人擴展該類 爲其添加了一個textWidget顯示面板 作爲長度信息顯示 代碼如下:
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderWindow.h>
#include <vtkSmartPointer.h>
#include <vtkSplineWidget.h>
#include <vtkCommand.h>
#include <vtkTextWidget.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkTextRepresentation.h>
#include <vtkCoordinate.h>
#include <vtkProperty.h>
#include <QDebug>
/*!
* \brief The vtkLengthCallBack class
* SplineWidget的回調類
* 主要用來實時顯示長度信息
*/
class vtkLengthCallBack : public vtkCommand
{
public:
static vtkLengthCallBack *New()
{
return new vtkLengthCallBack;
}
virtual void Execute(vtkObject *caller, unsigned long eventId, void *callData)
{
if(!m_text)
return;
if(eventId == vtkCommand::StartInteractionEvent)
m_text->On();
if(eventId == vtkCommand::InteractionEvent){
char text[200];
sprintf(text,"SummedLength: %f",m_spline->GetSummedLength());
m_text->GetTextActor()->SetInput(text);
}
}
vtkSplineWidget *m_spline = nullptr;
vtkTextWidget *m_text = nullptr;
};
/*!
* \brief The SplineWidget class
* 曲線長度測量工具。該工具繼承自vtkSplineWidget
* 並在其內部集成了vtkTextWidget作爲長度顯示面板。
* \see vtkSplineWidget
*/
class SplineWidget : public vtkSplineWidget
{
public:
static SplineWidget *New()
{
return new SplineWidget;
}
//定義VTK類的基本函數
vtkTypeMacro(SplineWidget,vtkSplineWidget)
void SetInteractor(vtkRenderWindowInteractor *iren){
vtkSplineWidget::SetInteractor(iren);
}
void SetText(vtkTextWidget *text)
{
this->m_text = text;
m_lengthCallBack->m_text = text;
}
void On(){
vtkSplineWidget::On();
if(m_text)
m_text->On();
if(this->Interactor){
this->Interactor->GetRenderWindow()->Render();
}
}
void Off(){
vtkSplineWidget::Off();
if(m_text)
m_text->Off();
if(this->Interactor){
this->Interactor->GetRenderWindow()->Render();
}
}
protected:
SplineWidget():
m_lengthCallBack(vtkLengthCallBack::New())
{
//[1] --創建回調函數
m_lengthCallBack->m_spline = this;
//[1]
this->AddObserver(vtkCommand::InteractionEvent,m_lengthCallBack);
this->AddObserver(vtkCommand::StartInteractionEvent,m_lengthCallBack);
}
~SplineWidget(){
m_lengthCallBack->Delete()