vtkPropPicker无法拾取vtkRenderer中的vtkLineSource的解决方案

本文由Markdown语法编辑器编辑完成。

问题背景:

为了实现类似于一款操作STL等3D对象的软件——Geomagic Studio软件在操作其视野中的3D对象时,可以通过工具->移动->高级对象移动器,调出一个包围该3D对象的坐标轴和沿着这三个轴的三个圆圈。这样,在平移和旋转3D对象对象时便非常直观了。

如下图所示:
这里写图片描述

具体的交互方法为:
(1)平移:当鼠标落在通过3D对象中心的三根红、绿和蓝轴的任何一根上,那么移动鼠标,3D对象便会沿着这条轴所在的方向进行平移;
(2)旋转:当鼠标落在环绕3D对象的三个红、绿和蓝的圆环,则拖动圆环转动,圆环便会沿着它所对应的那根轴进行旋转。

为了在现有的软件中,添加一个类似于该商业软件的这个功能,采用vtk的类可以基本实现。

实现的主要代码如下:

绘制圆环的代码:

double dRadius = 100.0;
double kCenter[3] = {0.0};
double kNormal[3] = {1.0, 0.0, 0.0};
//基于vtkRegularPolygonSource实现圆环的绘制.
vtkSmartPointer<vtkRegularPolygonSource> circleSource = 
        vtkSmartPointer<vtkRegularPolygonSource>::New();
circleSource->GeneratePolygonOff();
    circleSource->SetNumberOfSides(360);
    circleSource->SetRadius(dRadius);
    circleSource->SetCenter(kCenter.X(), kCenter.Y(), kCenter.Z());
    circleSource->SetNormal(kNormal.X(), kNormal.Y(), kNormal.Z());

vtkSmartPointer<vtkPolyDataMapper> mapper = 
        vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(circleSource->GetOutputPort());

actorRotate->SetMapper(mapper);
actorRotate->GetProperty()->SetLineWidth(3);
actorRotate->GetProperty()->SetColor(kColor.X(), kColor.Y(), kColor.Z());
//设置该actor可以被拾取到.
actorRotate->PickableOn();

绘制坐标轴及其在轴的正向增加一个箭头的代码如下:

vtkSmartPointer<vtkLineSource> lineSource = 
        vtkSmartPointer<vtkLineSource>::New();
DxPoint kPoint1 = kCenter.Add(kNormal.Multiply(dRadius * 1.5));
DxPoint kPoint2 = kCenter.Sub(kNormal.Multiply(dRadius * 1.5));

//vtkLineSource是由两个端点确定的一个线段.
lineSource->SetPoint1(kPoint1.X(), kPoint1.Y(),kPoint1.Z());
lineSource->SetPoint2(kPoint2.X(), kPoint2.Y(),kPoint2.Z());

//vtkConeSource是一个可以设置顶点朝向的圆锥体.
vtkSmartPointer<vtkConeSource> coneSource = vtkSmartPointer<vtkConeSource>::New();
    coneSource->SetCenter(kPoint1.X(), kPoint1.Y(), kPoint1.Z());
coneSource->SetHeight(12);
coneSource->SetRadius(6);
//设置这个圆锥的顶点朝向为这条轴的方向向量.
coneSource->SetDirection(kNormal.X(), kNormal.Y(), kNormal.Z());

//通过vtkAppendPolyData可以将两个独立的vtkPolydata合并为一个polydata.
vtkSmartPointer<vtkAppendPolyData> axisWithArrow = vtkSmartPointer<vtkAppendPolyData>::New();   
axisWithArrow->AddInputConnection(coneSource->GetOutputPort());
axisWithArrow->AddInputConnection(lineSource->GetOutputPort());
axisWithArrow->Update();

//通过管道机制,将合并后的polydata输出显示.
vtkSmartPointer<vtkPolyDataMapper> mapper = 
        vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(axisWithArrow->GetOutputPort());

actorPan->SetMapper(mapper);
actorPan->GetProperty()->SetLineWidth(3);
actorPan->GetProperty()->SetColor(kColor.X(), kColor.Y(), kColor.Z());
actorPan->PickableOn();

同样的代码,可以绘制出另外两个方向的坐标轴和其所对应的圆环。绘制完成后的效果图为:
这里写图片描述

解决方案:

绘制完成后,需要处理交互问题。
在通过鼠标对vtkRenderer中的vtkActor进行交互时,首先需要通过鼠标的位置来Pick出其所对应的vtkActor。在vtk中提供了几种不同的Pick类,具体的可以参考该链接。
本项目中之前采用的是vtkPropPick类,该类具有拾取快的特点。
但是也正是因为采用了这个拾取类,导致其无法拾取视野中的vtkLineSoure和vtkRegularPolygonSource这两个类对应的轴和圆环。

通过在Google上查找答案,并实际比较vtk提供的另外的Pick类的效果。发现当采用vtkCellPicker,并且设置一定的Tolerance时,可以完美得实现拾取以上两个对象的目的。

原来的Pick函数为:

vtkSmartPointer<vtkProp3D> PickProp3D(vtkPoint &displayPoint, vtkRenderer renderer)
{
//采用vtkPropPicker来拾取renderer中的actor.
//vtkSmartPointer<vtkPropPicker> picker = //vtkSmartPointer<vtkPropPicker>::New();

//修改后的代码为采用vtkCellPicker,并设置Tolerance来进行拾取.
vtkSmartPointer<vtkCellPicker> picker = vtkSmartPointer<vtkCellPicker>::New();

/*Specify tolerance for performing pick operation.Tolerance is specified as fraction of rendering window size. (Rendering window size is measured across diagonal.)*/
picker->SetTolerance(0.005);

picker->Pick(displayPoint.X(),displayPoint.Y(),displayPoint.Z(), renderer)
return picker->GetProp3D();
}

关于SetTolerance的说明:
Tolerance是设置Pick操作的精度,它的值被设定为RenderWindow窗口大小的百分比,窗口的大小是沿对角线的长度。因此,如果值为0.005,则表示Pick的精度为窗口对角线长度的0.5%。如果对角线长度为100pixel,则拾取的范围为0.5pixel。因此,如果采用vtkCellPicker依然无法获取vtkLineSource的话,可以尝试增大Tolerance的值,以扩大Picker的敏感范围。

参考链接:
1. VTK中提供的拾取类:
http://blog.csdn.net/jane_yuhui/article/details/52189154#comments
http://blog.csdn.net/q1302182594/article/details/45442343
2. Line无法被vtkPropPicker拾取的问题:
http://vtk.1045678.n5.nabble.com/Line-picking-td1253732.html

完。

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

inter_peng

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

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

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

打赏作者

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

抵扣说明:

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

余额充值