[VTK]VTK的角度測量


VTK模型重建后可能需要角度測量這樣一個小功能。

對於角度測量首先需要擁有一個角度,而這個角度通常由兩條線段組成,VTK的角度測量里面也有直接應用該方法可實現的。

也就是說通過定義兩天線段,線段有兩個端點(兩個線段共用其中一個),移動其中端點就會響應一定事件並對點信息進行更新以及計算,最后將結果顯示。

下面先看對移動端點顯示部分代碼:

// 這里定義了2個全局的lineWidget
vtkLineWidget *lineWidget1; vtkLineWidget *lineWidget2; class vtkLWCallback : public vtkCommand { public: static vtkLWCallback *New() { return new vtkLWCallback; } virtual void Execute(vtkObject *caller, unsigned long, void*) { vtkLineWidget *lineWidget = reinterpret_cast<vtkLineWidget*>(caller); double O[3], A[3], B[3];
//重新設置兩條線段到同一個端點 lineWidget
->GetPoint1 (O); lineWidget1->SetPoint1 (O); lineWidget2->SetPoint1 (O); lineWidget1->GetPoint2 (A); lineWidget2->GetPoint2 (B); double OA,OB,AB; AB=sqrt((A[0]-B[0])*(A[0]-B[0]) + (A[1]-B[1])*(A[1]-B[1]) + (A[2]-B[2])*(A[2]-B[2])); OA=sqrt((A[0]-O[0])*(A[0]-O[0]) + (A[1]-O[1])*(A[1]-O[1]) + (A[2]-O[2])*(A[2]-O[2])); OB=sqrt((O[0]-B[0])*(O[0]-B[0]) + (O[1]-B[1])*(O[1]-B[1]) + (O[2]-B[2])*(O[2]-B[2])); double cosAOB = (OA*OA + OB*OB - AB*AB) / (2*OA*OB); double angle; angle = acos(cosAOB) * 180 / 3.14159; char cAct[100]; sprintf((char *)cAct, "%.4f", angle); this->Text->SetInput (cAct); } vtkLWCallback():Text(0) {} public: vtkTextMapper *Text;
//如果不想定義全局的 vtkLineWidget也可以在這里定義局部變量並從調用函數傳遞初始化之 };

在調用函數部分則需要初始化兩線段,並進行一些構建模型的基礎操作,直接上碼:

#include "vtkActor.h"
#include "vtkCommand.h"
#include "vtkInteractorEventRecorder.h"
#include "vtkLineWidget.h"
#include "vtkDICOMImageReader.h"
#include "vtkRenderWindowInteractor.h"
#include <vtkPolyDataMapper.h>
#include <vtkImageData.h>
#include <vtkSphereSource.h>
#include <vtkActor2D.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkImageActor.h>
#include <vtkImageShiftScale.h>

#include <vtkProperty.h>
#include <vtkScaledTextActor.h>
#include <vtkTextMapper.h>
#include <math.h>
#include <string.h>
int degreeVTKExample()
{
    vtkSphereSource *sphere = vtkSphereSource::New();
    sphere->SetThetaResolution(12); 
    sphere->SetPhiResolution(12);
    sphere->SetRadius(100);

    vtkPolyDataMapper *innerMapper = vtkPolyDataMapper::New();
    innerMapper->SetInput(sphere->GetOutput());

    vtkActor *innerSphere = vtkActor::New();
    innerSphere->SetMapper(innerMapper);
    innerSphere->GetProperty()->SetColor (1,1,1);
    innerSphere->GetProperty()->SetOpacity (0.5);

    vtkTextMapper *textMapper=vtkTextMapper::New();
    textMapper->SetInput ("Welcome you!");//所要顯示的注釋文字
    vtkScaledTextActor *mmm=vtkScaledTextActor::New();
    vtkSmartPointer<vtkTextMapper> vtkTMapper = vtkTextMapper::New();
    
    mmm->SetMapper((vtkPolyDataMapper2D*)textMapper);
    mmm->SetDisplayPosition(100, 10 );//設定注釋位置


    vtkRenderer *ren1 = vtkRenderer::New();
    vtkRenderWindow *renWin = vtkRenderWindow::New();
    renWin->AddRenderer(ren1);

    vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);

    vtkLWCallback *myCallback1 = vtkLWCallback::New();
    myCallback1->Text = textMapper;

    lineWidget1 = vtkLineWidget::New();
    lineWidget1->SetInteractor(iren);
    lineWidget1->SetInput(sphere->GetOutput());
    lineWidget1->SetAlignToYAxis();
    lineWidget1->PlaceWidget();
    lineWidget1->GetLineProperty()->SetColor(1,0,0);
    lineWidget1->GetHandleProperty()->SetColor(0,0,1);
    lineWidget1->AddObserver(vtkCommand::InteractionEvent, myCallback1);
    lineWidget1->On();

    vtkLWCallback *myCallback2 = vtkLWCallback::New();
    myCallback2->Text = textMapper;

    lineWidget2 = vtkLineWidget::New();
    lineWidget2->SetInteractor(iren);
    lineWidget2->SetInput(sphere->GetOutput());

    lineWidget2->PlaceWidget();
    lineWidget2->GetLineProperty()->SetColor(1,0,0);
    lineWidget2->GetHandleProperty()->SetColor(0,0,1);
    lineWidget2->AddObserver(vtkCommand::InteractionEvent, myCallback2);
    lineWidget2->SetPoint1(lineWidget1->GetPoint1 ());
    lineWidget2->On();

    ren1->AddActor(innerSphere);
    ren1->AddActor(mmm);//顯示注釋文字

    ren1->SetBackground(0, 0, 0);
    renWin->SetSize(600, 600);

    ren1->InteractiveOff();

    iren->Initialize();
    renWin->Render();


    iren->InvokeEvent(vtkCommand::CharEvent,NULL);  
    ren1->InteractiveOff();

    iren->Start();


    myCallback1->Delete();
    lineWidget1->Delete();
    myCallback2->Delete();
    lineWidget2->Delete();
    sphere->Delete();
    iren->Delete();
    renWin->Delete();
    ren1->Delete();
  
    return 0;
}

最終的結果如下圖所示:

 

PS: 其實VTK本身就有求取角度的widget也就是vtkAngleWidget

http://www.vtk.org/doc/nightly/html/classvtkAngleWidget.html#details

發現實例爽歪歪:

http://www.vtk.org/Wiki/VTK/Examples/Cxx/Widgets/vtkAngleWidget

http://www.vtk.org/Wiki/VTK/Examples/Cxx/Widgets/vtkAngleWidget_2D

不過這個例子有點簡單,不過還是可以具體地分析下,接下來將他們應用到我的程序里面

這里是默認的效果,注意左下角的圖標確實出現了角度測量的功能,但是當用鼠標隨意滾動時候會出現角度的3個點

不隨着圖形變動的想象。

而上面2個例子的效果都差不了多少。

但如果將實例2的相關代碼修改成:

    /*vtkSmartPointer<vtkAngleRepresentation2D> rep = vtkSmartPointer<vtkAngleRepresentation2D>::New();*/
    vtkSmartPointer<vtkAngleRepresentation3D> rep = vtkSmartPointer<vtkAngleRepresentation3D>::New();
    rep->ArcVisibilityOff();
    vtkSmartPointer<vtkAngleWidget> angleWidget = vtkSmartPointer<vtkAngleWidget>::New();
    angleWidget->SetRepresentation(rep);
    angleWidget->SetInteractor(iren);
    angleWidget->CreateDefaultRepresentation();

可以看出其會隨着鼠標的滾動、縮放等更新變換。

有可能是前面的vtkAngleRepresentation2D是只適應於2D平面的情況,而這里的模型是3D的因此就會這樣的效果。

但這樣好歹也知道了3D平面做角度求取的簡單方法了罷:)

What's more

http://www.vtk.org/Wiki/VTK/Examples/Cxx

實例里面擁有許多的例子從點間距離到點采集、圖像拷貝、存儲、CenterOfMass、ExtractSelection、SeedWidget等可以說是一個大寶藏

坑爹的是例子都只配了一張圖,除非自己copy代碼運行否則效果也太難看出來鳥~~

如下面的vtkDistanceWidget也是個好東東,加上

vtkSmartPointer<vtkDistanceRepresentation3D> rep3D = vtkSmartPointer<vtkDistanceRepresentation3D>::New();

vtkSmartPointer<vtkDistanceWidget> distanceWidget =
vtkSmartPointer<vtkDistanceWidget>::New();
distanceWidget->SetInteractor(renderWindowInteractor);
distanceWidget->SetRepresentation(rep3D);
distanceWidget->CreateDefaultRepresentation();

就可以有3維可用的距離測量!

(當然記得設置好自己的dicomReader->SetDataSpacing(2.0 / 3, 2.0 / 3, 1);不然標尺不同就。 )


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM