VTK三维坐标点拾取

0 前言

    VTK可以借助vtkPointPicker或者vtkCellPicker进行三维坐标拾取,其官方例程序参见annotatePick.pyQtVTKRenderWindows.cxx

    QtVTKRenderWindows.cxx例子中说明,如果将vtkCellPickervtkImagePlaneWidget结合使用时,只需要使用vtkImagePlaneWidgetSetPicker()将它们两者绑定即可实现坐标点的拾取和显示;然而,如果想在三维重建时,实现目标的三维坐标拾取,可不那么简单。下面是VTK6.2.0的使用文档中对含有SetPicker()函数的类的总结:

SetPicker() : vtkRenderWindowInteractor , vtkBalloonWidget , vtkImagePlaneWidget

    由上面的总结可见,只有3个类是含有SetPicker()函数的,也就是说只有3个类可以与vtkCellPicker绑定。在三维重建效果显示时,通常使用的是第1个:vtkRenderWindowInteractor

    将vtkCellPickervtkRenderWindowInteractor通过SetPicker()绑定之后,并非就万事大吉。这时候还不能触发三维坐标点的采集。此外,就算继续设定vtkCellPicker的事件处理函数,也还不行。

    那么,要怎样才能触发vtkCellPicker的采集呢?答案是必须调用其Pick()函数,而且是调用一次,就触发一次!下面将用一个实例说明。

1 vtkCellPicker的创建并且与Interactor绑定

// Cell Picker
    m_pvtkCellPicker =
      vtkSmartPointer< vtkCellPicker >::New();
    m_pvtkCellPicker->SetTolerance( 0.005 );

    vtkSmartPointer < vtkCallbackCommand > callback_picker = vtkSmartPointer < vtkCallbackCommand >::New();
    callback_picker->SetCallback( handle_cell_picker );
    callback_picker->SetClientData( this );
    m_pvtkCellPicker->AddObserver( vtkCommand::EndPickEvent, callback_picker );
    this->ui->qvtkWidget3D->GetInteractor()->SetPicker( m_pvtkCellPicker );

2 vtkCellPicker回调函数

static void handle_cell_picker(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata)
{
    QString hints;
    double selPt[3];
    double normal[3];
    //float pixelValue = 0;

    RSAMeasurement3D *parent=  (RSAMeasurement3D *)clientdata;

    if ( !parent )
        return;

    if ( !parent->m_bHasRendered3D ) {
        parent->m_pvtkTextActor->VisibilityOff();
        return;
    }

    if ( Qt::Unchecked == parent->ui->enablePickerCheckBox->checkState() ) {
       // parent->m_pvtkTextActor->VisibilityOff();
        return;
    }

    if ( parent->m_pvtkCellPicker->GetCellId() < 0)
        return;

    parent->m_pvtkCellPicker->GetPickPosition( selPt );

    parent->m_pvtkTextActor->VisibilityOn();
    parent->m_pvtkConeActor->SetPosition( selPt );
}

3 触发坐标点采集

    我们的设想是,点击以下鼠标,采集一次坐标。首先要设置Interactor的单击处理回调函数:

    vtkSmartPointer < vtkCallbackCommand > callback_interactor =
            vtkSmartPointer < vtkCallbackCommand >::New();
    callback_interactor->SetCallback( handle_interactor_event );
    callback_interactor->SetClientData( this );
    this->ui->qvtkWidget3D->GetInteractor()->AddObserver(
                vtkCommand::LeftButtonPressEvent, callback_interactor );

    在回调函数里面,触发坐标采集

static void handle_interactor_event(vtkObject *caller, unsigned long eid, void *clientdata, void *calldata)
{

    //qDebug() << "left button release";

    RSAMeasurement3D *parent=  (RSAMeasurement3D *)clientdata;

    if ( !parent )
        return;

    int *pick = parent->ui->qvtkWidget3D->GetInteractor()->GetEventPosition();

    parent->m_pvtkCellPicker->Pick(
            (double)pick[0],
            (double)pick[1],
            0.0,
            parent->m_pvtkRenderer3D );
}

参考资料

[1]VTK拾取三维空间细胞(vtkcell)坐标参数 

[2]vtk捡选实例

[3]vtk坐标系统 

[4]VTK拾取相关的类(转)

[5]用vtk在屏幕中选一个点,并加上标记

[6][vtkusers] vtkCellPicker failing to pick vtkPolyLine (using Python and wx)

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论
VTK(Visualization Toolkit)是一个用于可视化和图形处理的开源软件库。它提供了广泛的功能,包括三维可视化、体绘制、图形处理、图像处理、科学可视化等。在VTK中,可以使用标记来标记三维场景中的特定位置。而平面映射则是将三维场景中的物体投影到二维平面上,以便于展示和处理。 下面是VTK中实现三维标记平面映射的步骤: 1. 创建一个VTK Renderer和RenderWindow对象,用于显示场景。 2. 创建一个VTK PolyData对象,用于存储标记的位置和属性。 3. 创建一个VTK PolyDataMapper对象,将PolyData对象映射到场景中。 4. 创建一个VTK Actor对象,将Mapper对象添加到Actor中。 5. 将Actor对象添加到Renderer中。 6. 创建一个VTK Plane对象,用于进行平面映射。 7. 创建一个VTK ProjectPoints对象,将标记投影到平面上。 8. 将投影结果添加到PolyData对象中。 9. 更新RenderWindow对象,显示投影结果。 下面是实现代码示例: ```python import vtk # create a renderer and render window renderer = vtk.vtkRenderer() render_window = vtk.vtkRenderWindow() render_window.AddRenderer(renderer) # create polydata object to store marker points polydata = vtk.vtkPolyData() # create mapper object to map polydata to scene mapper = vtk.vtkPolyDataMapper() mapper.SetInputData(polydata) # create actor object to add mapper to renderer actor = vtk.vtkActor() actor.SetMapper(mapper) renderer.AddActor(actor) # create plane object for projection plane = vtk.vtkPlane() # create project points object for projection project_points = vtk.vtkProjectPoints() project_points.SetInputData(polydata) project_points.SetPlane(plane) project_points.Update() # add projection result to polydata polydata.SetPoints(project_points.GetOutput().GetPoints()) # update render window to show projection result render_window.Render() ``` 以上代码演示了如何创建一个VTK场景,并将标记投影到平面上以显示投影结果。根据需要,可以调整代码以适应不同的应用场景。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OneSea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值