VTK:測量類widget總結

   關於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()



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章