#include "nmVTKMeshLayer.h" #include #include #include #include #include #include #include #include #include #include #include #include namespace { // Mapper、Actor 和输入数据都属于 VTK 状态,只允许 GUI 线程修改。 bool isMeshLayerGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); return pApplication == NULL || pApplication->thread() == QThread::currentThread(); } } nmVTKMeshLayer::nmVTKMeshLayer(const QString& sLayerId) : nmVTKRenderLayer(sLayerId), m_pDataSet(NULL), m_pMapper(vtkSmartPointer::New()), m_pActor(vtkSmartPointer::New()), m_pLookupTable(vtkSmartPointer::New()), m_eDisplayMode(DisplayMode_Surface), m_eScalarAssociation(ScalarAssociation_CellData), m_bUsingExplicitScalarRange(false) { Q_ASSERT(isMeshLayerGuiThread()); // 图层独占 Mapper、Actor 和 LookupTable;数据集通过智能指针共享。 m_pLookupTable->SetNumberOfTableValues(256); m_pLookupTable->SetHueRange(0.67, 0.0); m_pLookupTable->Build(); m_pMapper->SetLookupTable(m_pLookupTable); m_pMapper->ScalarVisibilityOff(); m_pActor->SetMapper(m_pMapper); m_pActor->GetProperty()->SetRepresentationToSurface(); m_pActor->GetProperty()->EdgeVisibilityOff(); setRenderProp(m_pActor); } nmVTKMeshLayer::~nmVTKMeshLayer() { Q_ASSERT(isMeshLayerGuiThread()); // 派生成员释放前先解除 Renderer,基类析构中的 detach 仍保持幂等。 detach(); m_pDataSet = NULL; } bool nmVTKMeshLayer::setDataSet(vtkDataSet* pDataSet) { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread()) { return false; } // vtkSmartPointer 仅增加引用计数,不复制点、单元或属性数组。 m_pDataSet = pDataSet; m_pMapper->SetInputData(pDataSet); if(pDataSet == NULL) { clearInvalidScalarState(); return false; } // 更换数据集时保留调用方此前的数组选择;若同名数组存在则恢复其映射方式。 if(!m_aScalarArrayName.isEmpty()) { if(getSelectedScalarArray() == NULL) { clearInvalidScalarState(); return false; } if(m_eScalarAssociation == ScalarAssociation_CellData) { m_pMapper->SetScalarModeToUseCellFieldData(); } else { m_pMapper->SetScalarModeToUsePointFieldData(); } m_pMapper->SelectColorArray(m_aScalarArrayName.constData()); if(!m_bUsingExplicitScalarRange) { if(!applyDataScalarRange()) { clearInvalidScalarState(); return false; } } } return true; } vtkDataSet* nmVTKMeshLayer::getDataSet() const { return m_pDataSet; } void nmVTKMeshLayer::setDisplayMode(DisplayMode eMode) { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || m_pActor == NULL) { return; } // 未识别枚举值按纯表面处理,避免把无效值带入 VTK Property。 m_eDisplayMode = eMode == DisplayMode_SurfaceWithEdges ? DisplayMode_SurfaceWithEdges : DisplayMode_Surface; vtkProperty* pProperty = m_pActor->GetProperty(); pProperty->SetRepresentationToSurface(); pProperty->SetEdgeVisibility( m_eDisplayMode == DisplayMode_SurfaceWithEdges ? 1 : 0); } nmVTKMeshLayer::DisplayMode nmVTKMeshLayer::getDisplayMode() const { return m_eDisplayMode; } bool nmVTKMeshLayer::setOpacity(double dOpacity) { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || !vtkMath::IsFinite(dOpacity) || m_pActor == NULL) { return false; } m_pActor->GetProperty()->SetOpacity(qBound(0.0, dOpacity, 1.0)); return true; } double nmVTKMeshLayer::getOpacity() const { return m_pActor != NULL ? m_pActor->GetProperty()->GetOpacity() : 0.0; } void nmVTKMeshLayer::setScalarVisibility(bool bVisible) { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || m_pMapper == NULL) { return; } m_pMapper->SetScalarVisibility(bVisible ? 1 : 0); } bool nmVTKMeshLayer::isScalarVisible() const { return m_pMapper != NULL && m_pMapper->GetScalarVisibility() != 0; } bool nmVTKMeshLayer::setScalarArray( const QString& sArrayName, ScalarAssociation eAssociation) { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || sArrayName.isEmpty() || m_pDataSet == NULL || m_pMapper == NULL || (eAssociation != ScalarAssociation_CellData && eAssociation != ScalarAssociation_PointData)) { return false; } const QByteArray aArrayName = sArrayName.toUtf8(); vtkDataArray* pArray = eAssociation == ScalarAssociation_CellData ? m_pDataSet->GetCellData()->GetArray(aArrayName.constData()) : m_pDataSet->GetPointData()->GetArray(aArrayName.constData()); if(pArray == NULL) { // 失败时保留原数组选择和原 Mapper 状态。 return false; } double dRange[2] = { 0.0, 0.0 }; if(!m_bUsingExplicitScalarRange) { pArray->GetRange(dRange); if(!vtkMath::IsFinite(dRange[0]) || !vtkMath::IsFinite(dRange[1]) || dRange[0] > dRange[1]) { // 自动范围无效时不提交新数组选择,避免形成半更新状态。 return false; } } m_aScalarArrayName = aArrayName; m_eScalarAssociation = eAssociation; if(eAssociation == ScalarAssociation_CellData) { m_pMapper->SetScalarModeToUseCellFieldData(); } else { m_pMapper->SetScalarModeToUsePointFieldData(); } m_pMapper->SelectColorArray(m_aScalarArrayName.constData()); // 已设置显式范围时不覆盖,否则同步提交已经验证的数据范围。 if(!m_bUsingExplicitScalarRange) { m_pMapper->SetScalarRange(dRange); m_pLookupTable->SetRange(dRange); m_pLookupTable->Build(); } return true; } QString nmVTKMeshLayer::getScalarArrayName() const { return QString::fromUtf8(m_aScalarArrayName.constData()); } nmVTKMeshLayer::ScalarAssociation nmVTKMeshLayer::getScalarAssociation() const { return m_eScalarAssociation; } bool nmVTKMeshLayer::setScalarRange(double dMinimum, double dMaximum) { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || !vtkMath::IsFinite(dMinimum) || !vtkMath::IsFinite(dMaximum) || dMinimum > dMaximum || m_pMapper == NULL || m_pLookupTable == NULL) { return false; } // Mapper 与 LookupTable 使用同一范围,保证几何着色和外接色标一致。 m_pMapper->SetScalarRange(dMinimum, dMaximum); m_pLookupTable->SetRange(dMinimum, dMaximum); m_pLookupTable->Build(); m_bUsingExplicitScalarRange = true; return true; } bool nmVTKMeshLayer::restoreDataScalarRange() { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || !applyDataScalarRange()) { return false; } // 只有成功应用数据范围后才退出显式范围模式。 m_bUsingExplicitScalarRange = false; return true; } bool nmVTKMeshLayer::isUsingExplicitScalarRange() const { return m_bUsingExplicitScalarRange; } vtkDataSetMapper* nmVTKMeshLayer::getMapper() const { return m_pMapper; } vtkActor* nmVTKMeshLayer::getActor() const { return m_pActor; } vtkLookupTable* nmVTKMeshLayer::getLookupTable() const { return m_pLookupTable; } vtkDataArray* nmVTKMeshLayer::getSelectedScalarArray() const { if(m_pDataSet == NULL || m_aScalarArrayName.isEmpty()) { return NULL; } return m_eScalarAssociation == ScalarAssociation_CellData ? m_pDataSet->GetCellData()->GetArray( m_aScalarArrayName.constData()) : m_pDataSet->GetPointData()->GetArray( m_aScalarArrayName.constData()); } bool nmVTKMeshLayer::applyDataScalarRange() { vtkDataArray* pArray = getSelectedScalarArray(); if(pArray == NULL || m_pMapper == NULL || m_pLookupTable == NULL) { return false; } // GetRange 只扫描当前选中的数组;无效或非有限范围不会污染现有颜色表。 double dRange[2] = { 0.0, 0.0 }; pArray->GetRange(dRange); if(!vtkMath::IsFinite(dRange[0]) || !vtkMath::IsFinite(dRange[1]) || dRange[0] > dRange[1]) { return false; } m_pMapper->SetScalarRange(dRange); m_pLookupTable->SetRange(dRange); m_pLookupTable->Build(); return true; } void nmVTKMeshLayer::clearInvalidScalarState() { // 失效选择不能继续驱动几何着色,也不能让外接色标沿用上一数据集范围。 m_aScalarArrayName.clear(); m_eScalarAssociation = ScalarAssociation_CellData; m_bUsingExplicitScalarRange = false; m_pMapper->ScalarVisibilityOff(); m_pMapper->SetScalarModeToDefault(); m_pMapper->SetScalarRange(0.0, 1.0); m_pLookupTable->SetRange(0.0, 1.0); m_pLookupTable->Build(); }