#ifndef NMVTKMESHLAYER_H #define NMVTKMESHLAYER_H #include "nmVTKRenderLayer.h" #include #include class vtkActor; class vtkAlgorithmOutput; class vtkDataArray; class vtkDataSet; class vtkDataSetMapper; class vtkLookupTable; /** * @brief 通用数据集表面图层,不包含任何业务属性名称。 * * 图层共享输入数据集的 VTK 引用,独占 Mapper、Actor 和 LookupTable。 * 所有修改只更新管线状态,不主动触发 Render。 */ class NM_RENDER_EXPORT nmVTKMeshLayer : public nmVTKRenderLayer { public: enum DisplayMode { DisplayMode_Surface = 0, ///< 只显示填充表面。 DisplayMode_SurfaceWithEdges ///< 同时显示表面和单元边线。 }; enum ScalarAssociation { ScalarAssociation_CellData = 0, ///< 从 CellData 选择标量数组。 ScalarAssociation_PointData ///< 从 PointData 选择标量数组。 }; /** @brief 创建空数据图层并建立默认表面渲染管线。 */ explicit nmVTKMeshLayer(const QString& sLayerId); /** @brief 先解除 Renderer,再释放共享数据引用。 */ virtual ~nmVTKMeshLayer(); /** * @brief 共享传入数据集的 VTK 引用,不执行 DeepCopy。 * @return 数据集非空且原标量选择在新数据集中仍有效时返回 true;失败时 * 保留原输入、标量选择和 Mapper 状态。传入 nullptr 会清除输入。 */ bool setDataSet(vtkDataSet* pDataSet); /** * @brief 连接通用 VTK 管线输出,不取得 Producer 所有权。 * @return 输出为数据集且原标量选择仍有效时返回 true;失败时保留原输入。 */ bool setInputConnection(vtkAlgorithmOutput* pInputConnection); /** * @brief 原子提交管线输出、标量数组和显式显示范围。 * * 候选输出、数组、数据范围和显示范围会在 Mapper 改动前完整验证; * 返回 false 时原输入、数组选择、范围和 LookupTable 均保持不变。 */ bool setInputConnection(vtkAlgorithmOutput* pInputConnection, const QString& sArrayName, ScalarAssociation eAssociation, double dMinimum, double dMaximum); /** * @brief 原子提交管线输入、标量数组和完整候选颜色表。 * @note 候选 LookupTable 必须已包含范围、色带、比例和越界颜色;失败时 * 原输入、Mapper 和活动 LookupTable 均保持不变。 */ bool setInputConnection(vtkAlgorithmOutput* pInputConnection, const QString& sArrayName, ScalarAssociation eAssociation, vtkLookupTable* pCandidateLookupTable); /** @brief 解除直接数据或管线连接,并清除当前标量选择。 */ void clearInput(); /** @brief 返回当前直接数据或管线输出数据集的非所有权指针。 */ vtkDataSet* getDataSet() const; /** @brief 设置表面或表面加边线显示模式。 */ void setDisplayMode(DisplayMode eMode); /** @brief 返回当前显示模式。 */ DisplayMode getDisplayMode() const; /** @brief 直接控制表面边线,供不暴露双显示模式的组合视图使用。 */ void setEdgeVisibility(bool bVisible); bool isEdgeVisible() const; /** @return 透明度为有限数时返回 true,并限制到 [0, 1]。 */ bool setOpacity(double dOpacity); /** @brief 返回 Actor 当前透明度。 */ double getOpacity() const; /** @brief 打开或关闭 Mapper 的标量着色。 */ void setScalarVisibility(bool bVisible); /** @brief 返回 Mapper 当前是否启用标量着色。 */ bool isScalarVisible() const; /** * @brief 选择 CellData 或 PointData 数组作为标量来源。 * @return 数据集和指定数组存在,且自动范围有效时返回 true;失败时保留 * 原数组选择和 Mapper 状态。 */ bool setScalarArray(const QString& sArrayName, ScalarAssociation eAssociation); /** * @brief 原子提交当前输入的标量数组和显式显示范围。 * @return 数组和两个范围均有效时返回 true;失败时保留原 Mapper 状态。 */ bool setScalarArray(const QString& sArrayName, ScalarAssociation eAssociation, double dMinimum, double dMaximum); /** * @brief 原子提交当前输入的标量数组和完整候选颜色表。 * @return 数组和候选颜色表全部有效时返回 true;失败不修改活动状态。 */ bool setScalarArray(const QString& sArrayName, ScalarAssociation eAssociation, vtkLookupTable* pCandidateLookupTable); /** @brief 返回当前选中的数组名称。 */ QString getScalarArrayName() const; /** @brief 返回当前数组来自 CellData 还是 PointData。 */ ScalarAssociation getScalarAssociation() const; /** @brief 设置显式标量范围;不读取数据集。 */ bool setScalarRange(double dMinimum, double dMaximum); /** @brief 从当前选中数组恢复数据范围。 */ bool restoreDataScalarRange(); /** @brief 返回当前范围是否由调用方显式指定。 */ bool isUsingExplicitScalarRange() const; /** * @brief 原子替换当前标量数组使用的完整颜色表。 * @note 成功后 Mapper 与外部 ScalarBar 可以共享同一对象;不主动 Render。 */ bool setLookupTable(vtkLookupTable* pCandidateLookupTable); /** 以下访问函数均返回图层持有对象的非所有权指针。 */ vtkDataSetMapper* getMapper() const; vtkActor* getActor() const; vtkLookupTable* getLookupTable() const; private: Q_DISABLE_COPY(nmVTKMeshLayer) /** @brief 解析直接输入或当前管线输出;按需先更新上游 Producer。 */ vtkDataSet* getInputDataSet(bool bUpdatePipeline) const; /** @brief 在不修改 Mapper 的前提下校验候选数据及保留的标量选择。 */ bool validateInputDataSet(vtkDataSet* pDataSet, double dScalarRange[2]) const; /** @brief 查询指定关联中的数组,并验证其实际数据范围为有限值。 */ vtkDataArray* validateScalarArray(vtkDataSet* pDataSet, const QByteArray& aArrayName, ScalarAssociation eAssociation, double dDataRange[2]) const; /** @brief 校验候选颜色表的表项、有限范围及 Log10 正下限。 */ bool validateLookupTable(vtkLookupTable* pLookupTable, double dRange[2]) const; /** @brief 提交已经完整验证的数组选择和范围;本函数内部没有失败分支。 */ void applyExplicitScalarState(const QByteArray& aArrayName, ScalarAssociation eAssociation, double dMinimum, double dMaximum); /** @brief 提交已验证的数组选择和候选颜色表;内部没有失败分支。 */ void applyLookupTableScalarState(const QByteArray& aArrayName, ScalarAssociation eAssociation, vtkLookupTable* pLookupTable, const double dRange[2]); /** @brief 对新输入重新应用已经验证的标量模式、名称和自动范围。 */ void applyRetainedScalarState(const double dScalarRange[2]); /** @brief 从当前数据集解析已记录的数组选择。 */ vtkDataArray* getSelectedScalarArray() const; /** @brief 校验数组范围并同步到 Mapper 和 LookupTable。 */ bool applyDataScalarRange(); /** @brief 清除失效数组选择、关闭标量着色并恢复默认范围。 */ void clearInvalidScalarState(); vtkSmartPointer m_pDataSet; ///< 共享输入数据,不执行深拷贝。 vtkSmartPointer m_pInputConnection; ///< 共享管线输出端口。 vtkSmartPointer m_pMapper; ///< 图层独占的映射器。 vtkSmartPointer m_pActor; ///< 图层主 Prop,由基类同步持有。 vtkSmartPointer m_pLookupTable; ///< 图层独占的颜色表。 DisplayMode m_eDisplayMode; ScalarAssociation m_eScalarAssociation; QByteArray m_aScalarArrayName; ///< 供 VTK 7.1 接口使用的 UTF-8 数组名。 bool m_bUsingExplicitScalarRange; ///< 为 true 时更换数据不覆盖调用方范围。 }; #endif // NMVTKMESHLAYER_H