VTK 画箭头带长度测量

40 篇文章 7 订阅

思路:

vtkDistanceWidget可以实现测量功能,本来以为在此基础上改一改就可以变成箭头带长度测量功能,

but,两个端点的十字线始终找不到隐藏的办法,不知道底层在哪里绘制的。

后来找到了绘制箭头的功能vtkLineWidget2,but,令人恼火的是,这个画箭头的widget和vtkDistanceWidget交互不一样,

不支持鼠标点选取,上来就绘制了一个箭头,然后让你改位置。

两个方案:

(1)vtkLineWidget2基础上增加鼠标交互功能

 // Point Handle
    vtkNew<vtkPointHandleRepresentation2D> handle;
    if (_cursorShape)
    {
        handle->SetCursorShape(_cursorShape);
    }
    double color2[3] = { 1,1,1. };
    handle->GetProperty()->SetColor(color2);
    handle->GetProperty()->SetOpacity(0.0);//隐藏两端十字线
    handle->SetTolerance(10);

    // Distance Representation
    vtkNew<vtkCustomDistanceRepresentation2D> distanceRep;
    distanceRep->SetHandleRepresentation(handle);
    int distancePrecision = 2;

(2)利用vtkDistanceWidget的鼠标交互功能,影藏测量的线,真正绘制箭头线

 

方案二的实现:(代码未整理)


#include <vtkCommand.h>
#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>

#include <vtkDistanceWidget.h>
#include <vtkDistanceRepresentation.h>
#include <vtkAngleWidget.h>
#include <vtkProperty2D.h>
#include <vtkLeaderActor2D.h>
#include <vtkAngleRepresentation2D.h>
#include <vtkBiDimensionalWidget.h>
#include <vtkBiDimensionalRepresentation2D.h>


#include <vtkLineRepresentation.h>
#include "vtkLineWidget3.h"
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include "vtkWidgetEventTranslator.h"
#include "vtkWidgetCallbackMapper.h"
#include "vtkWidgetEvent.h"

#include <vtkHandleRepresentation.h>
//#include <vtkDistanceRepresentation3D.h>
#include <vtkDistanceRepresentation2D.h>
#include <vtkPointHandleRepresentation2D.h>


#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkInteractionStyle)
VTK_MODULE_INIT(vtkRenderingFreeType)
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2)

class vtkLineCallback : public vtkCommand
{
public:
    static vtkLineCallback* New()
    {
        return new vtkLineCallback;
    }

    virtual void Execute(vtkObject* caller, unsigned long, void*)
    {

        vtkLineWidget3* lineWidget = reinterpret_cast<vtkLineWidget3*>(caller);

        // Get the actual box coordinates of the line
        vtkNew<vtkPolyData> polydata;
        static_cast<vtkLineRepresentation*>(lineWidget->GetRepresentation())
            ->GetPolyData(polydata);

        // Display one of the points, just so we know it's working
        double p[3];
        polydata->GetPoint(0, p);
        std::cout << "P: " << p[0] << " " << p[1] << " " << p[2] << std::endl;
    }
    vtkLineCallback()
    {
    }
};


class vtkBiDimensionalCallback : public vtkCommand
{
public:
    static	vtkBiDimensionalCallback*  New()
    {
        return new vtkBiDimensionalCallback;
    }

    virtual void Execute(vtkObject* caller, unsigned long, void*)
    {
        vtkBiDimensionalWidget* biDimensionalWidget =
            reinterpret_cast<vtkBiDimensionalWidget*> (caller);
        vtkBiDimensionalRepresentation2D* representation =
            static_cast<vtkBiDimensionalRepresentation2D*> (biDimensionalWidget->GetRepresentation());
        double p1[3];
        representation->GetPoint1DisplayPosition(p1);
        double p2[3];
        representation->GetPoint1DisplayPosition(p2);
        double p3[3];
        representation->GetPoint1DisplayPosition(p3);
        double p4[3];
        representation->GetPoint1DisplayPosition(p4);
        //显示其中一个点的屏幕坐标(px)
        std::cout << "P1: " << p1[0] << " " << p1[1] << " " << p1[2] << std::endl;
    }
    vtkBiDimensionalCallback() { }
};

class vtkDistanceCallback : public vtkCommand
{
public:
    static	vtkDistanceCallback*  New()
    {
        return new vtkDistanceCallback;
    }

    virtual void Execute(vtkObject* caller, unsigned long eventId, void*)
    {
        vtkDistanceWidget* distanceWidget =
            reinterpret_cast<vtkDistanceWidget*> (caller);
        vtkDistanceRepresentation2D * representation =       //  vtkDistanceRepresentation   vtkDistanceRepresentation3D  vtkDistanceRepresentation2D 
            static_cast<vtkDistanceRepresentation2D *> (distanceWidget->GetDistanceRepresentation());
        double p1[3];
        representation->GetPoint1WorldPosition(p1);
        double p2[3];
        representation->GetPoint2WorldPosition(p2);
        
        std::cout << "P1: " << p1[0] << " " << p1[1] << " " << p1[2] << std::endl;
        std::cout << "P2: " << p2[0] << " " << p2[1] << " " << p2[2] << std::endl;


        {
            //p1[0] += 100;
            //p1[1] += 100;
            //p2[0] += 100;
            //p2[1] += 100;

            

            _lineRepresentation->SetPoint1WorldPosition(p1);  //GetPoint1DisplayPosition  GetPoint1WorldPosition
            _lineRepresentation->SetPoint2WorldPosition(p2);
        }

  //  representation->Print(std::cout);
        
           // vtkDistanceRepresentation3D* representation = vtkDistanceRepresentation3D::New();
            distanceWidget->SetRepresentation(representation);
            distanceWidget->SetPriority(0.5);
            //representation->GetLineProperty()->SetOpacity(0.0);
            //representation->GetLineProperty()->SetColor(0., 0., 0);
            //representation->GetLabelProperty()->SetOpacity(0.);
            //representation->GetLabelProperty()->SetColor(0., 0., 0);
            representation->GetAxisProperty()->SetColor(0, 0, 1);
            //representation->GetAxisProperty()->SetOpacity(1.0);
            
                      
            representation->SetVisibility(false); //!

            vtkPointHandleRepresentation2D *handle = vtkPointHandleRepresentation2D::New();
            handle->GetProperty()->SetColor(1, 1, 0);
            representation->SetHandleRepresentation(handle);
            
            representation->GetPoint1Representation()->SetVisibility(false);
            representation->GetPoint2Representation()->SetVisibility(false);

            // vtkProperty* pointProperty = vtkProperty::New();
            // representation->SetHandleRepresentation(pointProperty);
            representation->GetPoint1Representation();
            //representation->GetPoint1Representation()->SetVisibility(false);

            representation->SetNumberOfRulerTicks(0);
            representation->SetRulerMode(false);
        

        switch (eventId)
        {
        case vtkCommand::StartInteractionEvent:
           // this->DistanceWidget->StartDistanceInteraction(this->HandleNumber);
            break;
        case vtkCommand::InteractionEvent:
           // this->DistanceWidget->DistanceInteraction(this->HandleNumber);

            std::cout << "InteractionEvent \n";
            break;
        case vtkCommand::EndInteractionEvent:
          //  this->DistanceWidget->EndDistanceInteraction(this->HandleNumber);
           // representation->GetPoint1Representation()->SetVisibility(false);

            std::cout <<"GetVisibility1 is " << representation->GetPoint1Representation()->GetVisibility() << "\n";
            representation->GetPoint2Representation()->SetVisibility(false);

            //vtkDistanceRepresentation2D * representation1 = vtkDistanceRepresentation2D::New();
            //representation1->SetVisibility(false);
            //vtkPointHandleRepresentation2D *handle = vtkPointHandleRepresentation2D::New();
            //handle->GetProperty()->SetColor(1, 1, 0);
            //representation1->SetHandleRepresentation(handle);

            //if (nullptr != representation1->GetPoint1Representation())
            //{
            //    representation1->GetPoint1Representation()->SetVisibility(false);
            //}
            //if (nullptr != representation1->GetPoint2Representation())
            //{
            //    representation1->GetPoint2Representation()->SetVisibility(false);
            //}
            //distanceWidget->SetRepresentation(representation1);
            std::cout << "EndInteractionEvent \n";
            break;
        }

    }

  vtkDistanceCallback() 
    {
        _lineRepresentation = vtkSmartPointer<vtkLineRepresentation>::New();
    }

    vtkSmartPointer<vtkLineRepresentation> GetLineRepresentation()
    {
        return _lineRepresentation;
    }

private:
    vtkSmartPointer<vtkLineRepresentation> _lineRepresentation;
};


int main()
{
    int WidgetType = 0;
    std::cout << "Please select the Measurement Distance WidgetType: " << std::endl;
    std::cout << "0 vtkDistanceWidget \n";
    std::cout << "1 vtkAngleWidget \n";
    std::cout << "2 vtkBiDimensionalWidget \n";
    //std::cin >> WidgetType;

    vtkSmartPointer<vtkJPEGReader> reader = vtkSmartPointer<vtkJPEGReader>::New();
    reader->SetFileName("0.jpg");
    reader->Update();

    vtkSmartPointer<vtkImageActor> imgActor = vtkSmartPointer<vtkImageActor>::New();
    imgActor->SetInputData(reader->GetOutput());

    vtkSmartPointer<vtkRenderer> render = vtkSmartPointer<vtkRenderer>::New();
    render->AddActor(imgActor);
    render->SetBackground(0, 0, 0);
    render->ResetCamera();

    vtkSmartPointer<vtkRenderWindow> rw = vtkSmartPointer<vtkRenderWindow>::New();
    rw->AddRenderer(render);
    rw->SetWindowName("MeasurementDistanceApp");
    rw->SetSize(800, 600);
    rw->Render();

    vtkSmartPointer<vtkRenderWindowInteractor> rwi =
        vtkSmartPointer<vtkRenderWindowInteractor>::New();
    rwi->SetRenderWindow(rw);

    vtkSmartPointer<vtkInteractorStyleImage> style =
        vtkSmartPointer<vtkInteractorStyleImage>::New();
    rwi->SetInteractorStyle(style);
    /****************************************************************/


 //实例化Widget
        
        vtkSmartPointer<vtkDistanceWidget> distanceWidget =
            vtkSmartPointer<vtkDistanceWidget>::New();
        //指定渲染窗口交互器,来监听用户事件
        distanceWidget->SetInteractor(rwi);
        //必要时使用观察者/命令模式创建回调函数(此处没用)
        //创建几何表达实体。用SetRepresentation()把事件与Widget关联起来
        //或者使用Widget默认的几何表达实体
        distanceWidget->CreateDefaultRepresentation();
        static_cast<vtkDistanceRepresentation*> (distanceWidget->GetDistanceRepresentation())->SetLabelFormat("%-#6.3g mm");
       // auto DistanceRep = static_cast<vtkDistanceRepresentation*> (distanceWidget->GetDistanceRepresentation());
        DistanceRep->SetDirectionalLine(true);
       // DistanceRep->SetNumberOfRulerTicks(0);
       // vtkHandleRepresentation* pRep = DistanceRep->GetPoint1Representation();
        
        {
            vtkDistanceRepresentation2D * representation = vtkDistanceRepresentation2D::New();
            distanceWidget->SetRepresentation(representation);
            distanceWidget->SetPriority(0.9);   //0.5 ==>0.9
            //representation->GetLineProperty()->SetOpacity(0.0);
            //representation->GetLineProperty()->SetColor(0.,0.,0);
            //representation->GetLabelProperty()->SetOpacity(0.);
            //representation->GetLabelProperty()->SetColor(0., 0., 0);
            
            representation->SetVisibility(false);

            // Create the widget and its representation 
            //vtkPointHandleRepresentation2D *handle = vtkPointHandleRepresentation2D::New();
            //handle->GetProperty()->SetColor(1, 0, 0);
            //representation->SetHandleRepresentation(handle);

           // vtkProperty* pointProperty = vtkProperty::New();
           // representation->SetHandleRepresentation(pointProperty);
            //representation->GetPoint1Representation()->SetVisibility(false);
            //representation->GetPoint2Representation()->SetVisibility(false);
            
            representation->SetNumberOfRulerTicks(0);
            representation->SetRulerMode(false);
            
        }

  vtkSmartPointer<vtkDistanceCallback> bidiCallback =
            vtkSmartPointer<vtkDistanceCallback>::New();
        distanceWidget->AddObserver(vtkCommand::InteractionEvent, bidiCallback);
        distanceWidget->AddObserver(vtkCommand::EndInteractionEvent, bidiCallback);
        distanceWidget->AddObserver(vtkCommand::StartInteractionEvent, bidiCallback);
        distanceWidget->AddObserver(vtkCommand::MouseMoveEvent, bidiCallback);
        

        
        distanceWidget->On();


        
        vtkNew<vtkLineWidget3> lineWidget;
        lineWidget->SetInteractor(rwi);
        lineWidget->CreateDefaultRepresentation();

        // You could do this if you want to set properties at this point:
        //vtkNew<vtkLineRepresentation> lineRepresentation;
        auto lineRepresentation = bidiCallback->GetLineRepresentation();
        lineRepresentation->SetDistanceAnnotationVisibility(true);
        lineRepresentation->GetDistanceAnnotationProperty()->SetColor(0, 1, 0);
        lineRepresentation->GetDistanceAnnotationProperty()->SetBackfaceCulling(true);
        lineRepresentation->SetDistanceAnnotationScale(20.0,20.0,100.0);
        lineRepresentation->SetDistanceAnnotationFormat("%-#6.2f mm");
        //lineRepresentation->SetDistanceAnnotationFormat("%");
        lineRepresentation->SetLineColor(1, 0, 0);
        lineRepresentation->SetDirectionalLine(true);

        lineRepresentation->GetEndPointProperty()->SetColor(1, 0, 0);
        //lineRepresentation->GetEndPointProperty()->SetLineWidth(.5);
        lineRepresentation->GetEndPointProperty()->SetOpacity(0.1);

        //lineRepresentation->GetEndPoint2Property()->SetLineWidth(10.);
        lineRepresentation->GetEndPoint2Property()->SetPointSize(20.0);

        lineRepresentation->GetEndPoint2Property()->SetColor(1, 0, 0);


        lineWidget->SetRepresentation(lineRepresentation);
        lineWidget->SetEnabled(0);

 //vtkNew<vtkLineCallback> lineCallback;
        //lineWidget->AddObserver(vtkCommand::InteractionEvent, lineCallback);
        //lineWidget->AddObserver(vtkCommand::PlacePointEvent, lineCallback);



        double p1[3] = { -10000,-10000,0 };
        lineRepresentation->SetPoint1WorldPosition(p1);  //GetPoint1DisplayPosition  GetPoint1WorldPosition
        lineRepresentation->SetPoint2WorldPosition(p1);

        lineRepresentation->GetPoint1WorldPosition(p1);  //GetPoint1DisplayPosition  GetPoint1WorldPosition
        std::cout << "p1:\t" << p1[0] << "\t" << p1[1] << "\t" << p1[2] << "\n";
        lineRepresentation->GetPoint2WorldPosition(p1);
        std::cout << "p2:\t" << p1[0] << "\t" << p1[1] << "\t" << p1[2] << "\n";
        lineWidget->On();

        

        rw->Render();
        rwi->Initialize();
        rwi->Start();
    }

    return 0;
}

 

效果:

您可以使用VTK的线性测量工具来测量三维模型中的长度。以下是一个简单的示例代码,它使用vtkDistanceWidgetvtkDistanceRepresentation来实现线性测量。 ```python import vtk # 读取三维模型 reader = vtk.vtkSTLReader() reader.SetFileName("模型文件路径") reader.Update() # 创建渲染器和RenderWindow renderer = vtk.vtkRenderer() renderWindow = vtk.vtkRenderWindow() renderWindow.AddRenderer(renderer) # 创建交互器和RenderWindowInteractor interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(renderWindow) # 添加三维模型到渲染器中 mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(reader.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) renderer.AddActor(actor) # 创建线性测量工具 widget = vtk.vtkDistanceWidget() widget.SetInteractor(interactor) widget.CreateDefaultRepresentation() rep = widget.GetRepresentation() rep.SetLabelFormat("%-0.3f mm") rep.SetHandleSize(0.01) # 设置测量起点和终点的属性 rep.GetPoint1Representation().SetPointPlacer(None) rep.GetPoint2Representation().SetPointPlacer(None) rep.GetPoint1Representation().SetPickable(1) rep.GetPoint2Representation().SetPickable(1) # 启动交互器 interactor.Initialize() renderWindow.Render() widget.On() interactor.Start() ``` 在这个示例代码中,您需要将“模型文件路径”替换为您的三维模型文件的路径。运行代码后,您可以使用鼠标在三维模型上选择起点和终点,然后线性测量工具将显示测量结果。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值