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



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