zoukankan      html  css  js  c++  java
  • [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);不然标尺不同就。 )

  • 相关阅读:
    基于摸板匹配的目標跟蹤算法
    spoj 2713 Can you answer these queries IV
    zoj 3633 Alice's present
    hdu 3642 Get The Treasury
    poj 1195 Mobile phones
    poj 2760 End of Windless Days
    zoj 3540 Adding New Machine
    spoj 1716 Can you answer these queries III
    spoj 1043 Can you answer these queries I
    spoj 2916 Can you answer these queries V
  • 原文地址:https://www.cnblogs.com/dawnWind/p/3D_08.html
Copyright © 2011-2022 走看看