网站如何做下载链接,企业官方网站如何做蓝v认证,おっさんとわたし天堂,时尚网站策划鼠标拾取对象是很多软件的基本功能。FastCAE的拾取比较简单#xff0c;是通过VTK实现的。 对几何而言#xff0c;拾取类型切换在工具栏上#xff0c;单击后再来单击视图区对象进行拾取#xff0c;拾取后的对象会高亮显示。效果如下图#xff1a;
一、拾取对象
拾取对象… 鼠标拾取对象是很多软件的基本功能。FastCAE的拾取比较简单是通过VTK实现的。 对几何而言拾取类型切换在工具栏上单击后再来单击视图区对象进行拾取拾取后的对象会高亮显示。效果如下图
一、拾取对象
拾取对象是在PropPickerInteractionStyle类实现的该类是vtkInteractorStyleRubberBandPick的子类重写原来的鼠标处理函数。当鼠标左键按下会触发以下代码
void PropPickerInteractionStyle::clickSelectGeometry(bool preSelect)
{int *clickPos this-GetInteractor()-GetEventPosition(); // 获取鼠标点击位置int success -1, index -1;vtkActor *actor nullptr;if (_selectModel GeometryPoint || _selectModel GeometryWinPoint) // 几何点{vtkSmartPointervtkPointPicker picker vtkSmartPointervtkPointPicker::New();success picker-Pick(clickPos[0], clickPos[1], 0, this-GetDefaultRenderer());if (0 ! success){index picker-GetPointId(); // 点的idactor picker-GetActor(); // 点对应的Actor}}else{vtkSmartPointervtkCellPicker picker vtkSmartPointervtkCellPicker::New();if (_selectModel GeometryCurve || _selectModel GeometryWinCurve)picker-SetTolerance(0.0025);success picker-Pick(clickPos[0], clickPos[1], 0, this-GetDefaultRenderer());if (0 ! success){index picker-GetCellId(); // cell的idactor picker-GetActor(); // 对应的actor}}emit selectGeometry(preSelect, actor, index);
}这段代码就是鼠标拾取对象的核心逻辑。其实现是借助了VTK提供的vtkPointPicker、vtkCellPicker。其中当拾取模式是点的时候使用vtkPointPicker如果拾取成功返回点的id及对应的Actor一个Actor可能包含多个点。当拾取模式是线、面、体的时候使用vtkCellPicker成功则返回对应cell id及Actor一个Actor可能包含多个cell。注意当拾取线的时候需要提高拾取Tolerance不然线很难拾取到。
另外要注意的是当拾取线的时候面Actor是拾取不到的同样当拾取面的时候线Actor也是拾取不到。这是通过在用户切换选择模式的时候设置面或边Actor是否可以拾取实现的。核心代码在GeometryViewProvider类中如下
void GeometryViewProvider::setGeoSelectMode(int m)
{_viewData-updateGraphOption();ModuleBase::SelectModel selectType (ModuleBase::SelectModel)m;QListGeoViewObj viewObjs _geoViewHash.values();vtkActor *actor nullptr;for (GeoViewObj vobj : viewObjs){actor vobj._faceObj.first;if (actor ! nullptr)actor-SetPickable(false);actor vobj._edgeObj.first;if (actor ! nullptr)actor-SetPickable(false);actor vobj._pointObj.first;if (actor ! nullptr)actor-SetPickable(false);switch (selectType){case ModuleBase::GeometryBody:case ModuleBase::GeometrySurface:case ModuleBase::GeometryWinBody:case ModuleBase::GeometryWinSurface:actor vobj._faceObj.first;if (actor ! nullptr)actor-SetPickable(true);break;case ModuleBase::GeometryWinCurve:case ModuleBase::GeometryCurve:actor vobj._edgeObj.first;if (actor ! nullptr)actor-SetPickable(true);break;case ModuleBase::GeometryWinPoint:case ModuleBase::GeometryPoint:actor vobj._pointObj.first;if (actor ! nullptr)actor-SetPickable(true);break;default:break;}}
}这个代码相对比较简单不再分析。
二、从信号到槽函数
拾取对象之后会发出emit selectGeometry信号参数中带有Actor及cell或点的id。这个信号是QT框架提供的编程机制。其对应的槽函数在如下图中能找到
三、高亮拾取对象
高亮拾取对象处理过程代码如下
void GeometryViewProvider::selectGeometry(bool pre, vtkActor *ac, int index)
{if (ac nullptr || index 0) // 无效拾取{_viewData-preHighLight(nullptr);_preWindow-reRender();return;}ModuleBase::SelectModel selectMod _preWindow-getSelectModel(); // 选择模式vtkDataSet *dataSet ac-GetMapper()-GetInputAsDataSet(); // 获取Actor的多边形数据集vtkPolyDatavtkPolyData *poly vtkPolyData::SafeDownCast(dataSet);if (poly nullptr)return;GeometryViewObject *vobj nullptr;switch (selectMod){case ModuleBase::GeometryWinBody:case ModuleBase::GeometryBody:vobj _viewData-getSolidViewObj(poly, index);break;case ModuleBase::GeometryWinSurface:case ModuleBase::GeometrySurface:vobj _viewData-getFaceViewObj(poly, index); // 输入多边形数据cell idbreak;case ModuleBase::GeometryWinCurve:case ModuleBase::GeometryCurve:vobj _viewData-getEdgeViewObj(poly, index);break;case ModuleBase::GeometryWinPoint:case ModuleBase::GeometryPoint:vobj _viewData-getPointViewObj(poly, index);break;default:break;}if (vobj nullptr)return;if (pre)_viewData-preHighLight(vobj); // 设置预高亮else{vobj-highLight(); // 高亮对象_viewData-preHighLight(nullptr);emit geoShapeSelected(vobj-getGeometySet(), vobj-getIndex());}_preWindow-reRender();
}同样这里也只分析面的高亮其他的高亮逻辑类似。高亮处理的时候直接先根据Actor获取了其vtkPolyData数据集找到哪个面需要高亮最后更改其颜色。如何根据cell id找到这个面需要理解其数据结构才能看懂其逻辑。对于面的数据结构这篇文章【FastCAE源码阅读3】几何模型显示从OCC对象到VTK对象有详细描述。其核心原理是查找cell id落在哪个面包含的cell区间上确定高亮哪个面。最后调用_preWindow-reRender()重新绘制整个场景。