From 77e1cd1512d433e9274adfff1da26ca01fd74a06 Mon Sep 17 00:00:00 2001 From: lh <2334563547@qq.com> Date: Mon, 14 Sep 2026 09:53:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(nmRender):=20=E5=A2=9E=E5=8A=A0=E7=BD=91?= =?UTF-8?q?=E6=A0=BC=E6=96=B9=E5=90=91=E8=BD=B4=E5=B9=B6=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=B8=B2=E6=9F=93=E7=94=9F=E5=91=BD=E5=91=A8=E6=9C=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增容器独占的方向轴控制器并固定主 Renderer - 完善方向轴状态切换、交互限制和幂等解绑 - 接入渲染容器及 qmake 工程并更新开发清单 - 统一 nmRender 和 PEBI 网格预览链的 nullptr 写法与成员命名 --- .../nmNum/nmRender/nmVTKCameraController.h | 6 +- Include/nmNum/nmRender/nmVTKImageExporter.h | 4 +- .../nmNum/nmRender/nmVTKInteractionManager.h | 2 +- .../nmVTKOrientationMarkerController.h | 76 +++++ .../nmRender/nmVTKViewCommandController.h | 2 +- .../nmRender/nmWxVTKRenderContainerWidget.h | 13 +- Include/nmNum/nmSubWnd/nmSubWndGrid.h | 2 +- .../nmSubWxs/nmPebiGridSceneController.h | 2 +- .../nmSubWxs/nmPebiGridViewDataBuilder.h | 2 +- .../nmNum/nmSubWxs/nmWxPebiGridViewWidget.h | 4 +- Src/nmNum/nmRender/nmVTKBoundsGridLayer.cpp | 18 +- Src/nmNum/nmRender/nmVTKCameraController.cpp | 18 +- Src/nmNum/nmRender/nmVTKImageExporter.cpp | 24 +- .../nmRender/nmVTKInteractionManager.cpp | 28 +- Src/nmNum/nmRender/nmVTKMeshLayer.cpp | 32 +-- .../nmVTKOrientationMarkerController.cpp | 263 ++++++++++++++++++ Src/nmNum/nmRender/nmVTKRenderLayer.cpp | 32 +-- Src/nmNum/nmRender/nmVTKScalarBarLayer.cpp | 6 +- Src/nmNum/nmRender/nmVTKScene.cpp | 14 +- .../nmRender/nmVTKViewCommandController.cpp | 18 +- .../nmRender/nmWxVTKRenderContainerWidget.cpp | 155 ++++++----- Src/nmNum/nmSubWnd/nmSubWndGrid.cpp | 32 +-- .../nmSubWxs/nmPebiGridSceneController.cpp | 108 +++---- Src/nmNum/nmSubWxs/nmPebiGridViewData.cpp | 6 +- .../nmSubWxs/nmPebiGridViewDataBuilder.cpp | 30 +- Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp | 52 ++-- Src4/nmNum/nmRender/nmRender.pro | 4 +- 27 files changed, 663 insertions(+), 290 deletions(-) create mode 100644 Include/nmNum/nmRender/nmVTKOrientationMarkerController.h create mode 100644 Src/nmNum/nmRender/nmVTKOrientationMarkerController.cpp diff --git a/Include/nmNum/nmRender/nmVTKCameraController.h b/Include/nmNum/nmRender/nmVTKCameraController.h index 7a13242..0d2a033 100644 --- a/Include/nmNum/nmRender/nmVTKCameraController.h +++ b/Include/nmNum/nmRender/nmVTKCameraController.h @@ -14,12 +14,12 @@ class vtkRenderer; class NM_RENDER_EXPORT nmVTKCameraController { public: - /** @brief 绑定 Renderer 非所有权指针;允许传入 NULL 延后初始化。 */ - explicit nmVTKCameraController(vtkRenderer* pRenderer = NULL); + /** @brief 绑定 Renderer 非所有权指针;允许传入 nullptr 延后初始化。 */ + explicit nmVTKCameraController(vtkRenderer* pRenderer = nullptr); /** @brief 只解除 Renderer 引用,不修改相机和场景。 */ ~nmVTKCameraController(); - /** @brief 切换非所有权 Renderer;传入 NULL 表示解除。 */ + /** @brief 切换非所有权 Renderer;传入 nullptr 表示解除。 */ void setRenderer(vtkRenderer* pRenderer); /** @brief 返回当前 Renderer 非所有权指针。 */ vtkRenderer* getRenderer() const; diff --git a/Include/nmNum/nmRender/nmVTKImageExporter.h b/Include/nmNum/nmRender/nmVTKImageExporter.h index 8a65731..818871c 100644 --- a/Include/nmNum/nmRender/nmVTKImageExporter.h +++ b/Include/nmNum/nmRender/nmVTKImageExporter.h @@ -23,11 +23,11 @@ class NM_RENDER_EXPORT nmVTKImageExporter : public QObject public: /** @brief 创建无绑定 RenderWindow 的图片输出服务。 */ - explicit nmVTKImageExporter(QObject* pParent = NULL); + explicit nmVTKImageExporter(QObject* pParent = nullptr); /** @brief 只解除 RenderWindow 非所有权引用。 */ virtual ~nmVTKImageExporter(); - /** @brief 切换截图来源;传入 NULL 表示解除。 */ + /** @brief 切换截图来源;传入 nullptr 表示解除。 */ void setRenderWindow(vtkRenderWindow* pRenderWindow); /** @brief 返回当前截图来源的非所有权指针。 */ vtkRenderWindow* getRenderWindow() const; diff --git a/Include/nmNum/nmRender/nmVTKInteractionManager.h b/Include/nmNum/nmRender/nmVTKInteractionManager.h index 3e32f15..b02d708 100644 --- a/Include/nmNum/nmRender/nmVTKInteractionManager.h +++ b/Include/nmNum/nmRender/nmVTKInteractionManager.h @@ -40,7 +40,7 @@ public: vtkRenderWindowInteractor* getInteractor() const; /** @brief 返回管理器持有的默认样式非所有权指针。 */ vtkInteractorStyleTrackballCamera* getDefaultStyle() const; - /** @brief 返回当前活动样式的非所有权指针;未安装时返回 NULL。 */ + /** @brief 返回当前活动样式的非所有权指针;未安装时返回 nullptr。 */ vtkInteractorStyle* getActiveStyle() const; private: diff --git a/Include/nmNum/nmRender/nmVTKOrientationMarkerController.h b/Include/nmNum/nmRender/nmVTKOrientationMarkerController.h new file mode 100644 index 0000000..78dc3e1 --- /dev/null +++ b/Include/nmNum/nmRender/nmVTKOrientationMarkerController.h @@ -0,0 +1,76 @@ +#ifndef NMVTKORIENTATIONMARKERCONTROLLER_H +#define NMVTKORIENTATIONMARKERCONTROLLER_H + +#include "nmRender_global.h" + +#include + +class vtkAxesActor; +class vtkOrientationMarkerWidget; +class vtkRenderer; +class vtkRenderWindowInteractor; + +/** + * @brief 管理单个渲染容器左下角的通用空间方向轴。 + * + * 控制器独占 AxesActor 和 OrientationMarkerWidget,不进入业务 Scene, + * 也不主动触发 Render。所有接口必须在 Qt GUI 线程调用。 + */ +class NM_RENDER_EXPORT nmVTKOrientationMarkerController +{ +public: + /** @brief 创建默认开启、默认不可用的方向轴控制器。 */ + nmVTKOrientationMarkerController(); + /** @brief 先禁用并解除所有 VTK 关联,再释放内部对象。 */ + ~nmVTKOrientationMarkerController(); + + /** + * @brief 将方向轴绑定到同一 RenderWindow 的 Interactor 和主 Renderer。 + * + * 重新绑定前会完整解除旧关系。绑定成功但视图尚未 Ready 时返回 true, + * 此时 Marker 仍保持禁用;绑定失败不修改长期显示偏好。 + */ + bool bindInteractor(vtkRenderWindowInteractor* pInteractor, + vtkRenderer* pRenderer); + /** @brief 禁用 Marker,并解除 Actor、Renderer 和 Interactor 的引用关系。 */ + void unbindInteractor(); + + /** @brief 修改长期显示偏好;空、错误和加载状态不会覆盖该偏好。 */ + void setVisible(bool bVisible); + /** @brief 返回长期显示偏好,不代表 Marker 当前一定处于 Enabled 状态。 */ + bool isVisible() const; + + /** @brief 设置当前视图是否处于可显示方向轴的 Ready 状态。 */ + void setViewAvailable(bool bAvailable); + /** @brief 返回当前视图可用状态。 */ + bool isViewAvailable() const; + + /** + * @brief 设置归一化视口;只接受有限且位于 [0, 1] 的有效矩形。 + * @return 参数有效并写入内部 Widget 时返回 true。 + */ + bool setViewport(double dXMinimum, + double dYMinimum, + double dXMaximum, + double dYMaximum); + +private: + Q_DISABLE_COPY(nmVTKOrientationMarkerController) + + /** @brief 按绑定、显示偏好和 Ready 状态统一更新 Marker 的 Enabled 状态。 */ + void updateEnabledState(); + + // 智能指针独占 VTK 对象;MarkerWidget 启用期间还会持有相关 VTK 引用。 + vtkSmartPointer m_pAxesActor; + vtkSmartPointer m_pMarkerWidget; + + // 以下为非所有权访问指针,解绑时必须在释放外部对象前清空。 + vtkRenderWindowInteractor* m_pInteractor; + vtkRenderer* m_pRenderer; + + bool m_bVisible; ///< 用户长期显示偏好,默认开启。 + bool m_bViewAvailable; ///< 当前容器是否处于 Ready 状态。 + double m_dViewport[4]; ///< 归一化方向轴视口。 +}; + +#endif // NMVTKORIENTATIONMARKERCONTROLLER_H diff --git a/Include/nmNum/nmRender/nmVTKViewCommandController.h b/Include/nmNum/nmRender/nmVTKViewCommandController.h index 5bb5c04..d8652fe 100644 --- a/Include/nmNum/nmRender/nmVTKViewCommandController.h +++ b/Include/nmNum/nmRender/nmVTKViewCommandController.h @@ -46,7 +46,7 @@ public: */ explicit nmVTKViewCommandController( nmWxVTKRenderContainerWidget* pContainer, - QObject* pParent = NULL); + QObject* pParent = nullptr); virtual ~nmVTKViewCommandController(); /** @brief 设置当前视图对外提供的命令集合。 */ diff --git a/Include/nmNum/nmRender/nmWxVTKRenderContainerWidget.h b/Include/nmNum/nmRender/nmWxVTKRenderContainerWidget.h index 19edc88..bde540a 100644 --- a/Include/nmNum/nmRender/nmWxVTKRenderContainerWidget.h +++ b/Include/nmNum/nmRender/nmWxVTKRenderContainerWidget.h @@ -17,6 +17,7 @@ class QVTKWidget; class nmVTKCameraController; class nmVTKImageExporter; class nmVTKInteractionManager; +class nmVTKOrientationMarkerController; class nmVTKScene; class vtkRenderer; @@ -27,7 +28,7 @@ class vtkInteractorStyle; /** * @brief 可组合的 Qt + VTK 通用渲染容器。 * - * 容器独占 Renderer、Scene、相机和交互管理器,但不创建任何业务 Actor。 + * 容器独占 Renderer、Scene、相机、交互和方向轴服务,但不创建任何业务 Actor。 * 调用方通过 Scene 组织图层,并在一批修改完成后显式调用 renderView。 */ class NM_RENDER_EXPORT nmWxVTKRenderContainerWidget : public QWidget @@ -35,9 +36,9 @@ class NM_RENDER_EXPORT nmWxVTKRenderContainerWidget : public QWidget Q_OBJECT public: - /** @brief 创建独立的 VTK 显示外壳,并初始化场景、相机和交互服务。 */ - explicit nmWxVTKRenderContainerWidget(QWidget* pParent = NULL); - /** @brief 严格按交互、图层、相机、Renderer 的逆序解除资源。 */ + /** @brief 创建独立的 VTK 显示外壳,并初始化场景、相机、交互和方向轴服务。 */ + explicit nmWxVTKRenderContainerWidget(QWidget* pParent = nullptr); + /** @brief 按命令、方向轴、交互、图层、相机和 Renderer 的顺序解除资源。 */ virtual ~nmWxVTKRenderContainerWidget(); /** @brief 返回 Qt 承载控件;调用方不得删除或重新设置父对象。 */ @@ -55,6 +56,9 @@ public: nmVTKScene* getScene() const; /** @brief 返回当前容器独占的通用命令控制器非所有权指针。 */ nmVTKViewCommandController* getViewCommandController() const; + /** @brief 返回当前容器独占的方向轴控制器非所有权指针。 */ + nmVTKOrientationMarkerController* + getOrientationMarkerController() const; /** @brief 设置工具栏和右键菜单可使用的通用命令集合。 */ void setViewCommandCapabilities( @@ -157,6 +161,7 @@ private: nmVTKInteractionManager* m_pInteractionManager; nmVTKImageExporter* m_pImageExporter; nmVTKViewCommandController* m_pViewCommandController; + nmVTKOrientationMarkerController* m_pOrientationMarkerController; }; #endif // NMWXVTKRENDERCONTAINERWIDGET_H diff --git a/Include/nmNum/nmSubWnd/nmSubWndGrid.h b/Include/nmNum/nmSubWnd/nmSubWndGrid.h index 22454bb..449b154 100644 --- a/Include/nmNum/nmSubWnd/nmSubWndGrid.h +++ b/Include/nmNum/nmSubWnd/nmSubWndGrid.h @@ -75,7 +75,7 @@ class NM_SUB_WND_EXPORT nmSubWndGrid : public iSubWndBaseFit { /** @brief 判断当前任务之后是否仍有防抖或合并后的网格更新。 */ bool hasPendingGridUpdate() const; - QStackedLayout* m_mainLayout; ///< 持有稳定 PEBI 网格视图的主布局。 + QStackedLayout* m_pMainLayout; ///< 持有稳定 PEBI 网格视图的主布局。 nmWxPebiGridViewWidget* m_pGridView; ///< 组合 nmRender 的稳定 PEBI 网格视图。 QTimer* m_pDebounceTimer; ///< 本窗口独立防抖定时器,避免跨窗口刷新。 QPointer m_pDataManager; ///< 窗口所属数据管理器,销毁后自动置空。 diff --git a/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h b/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h index f687041..3f255bc 100644 --- a/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h +++ b/Include/nmNum/nmSubWxs/nmPebiGridSceneController.h @@ -25,7 +25,7 @@ public: /** @brief 共享新网格、更新比例边界并以顶视图重新适配。 */ bool setViewData(const nmPebiGridViewData& oViewData, - QString* pError = NULL); + QString* pError = nullptr); /** @brief 解除网格引用并隐藏图层,不销毁 Scene 或 Renderer。 */ void clear(); diff --git a/Include/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.h b/Include/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.h index d45bf0b..b87187b 100644 --- a/Include/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.h +++ b/Include/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.h @@ -23,7 +23,7 @@ public: */ static bool build(nmDataAnalyzeManager* pDataManager, nmPebiGridViewData* pViewData, - QString* pError = NULL); + QString* pError = nullptr); private: nmPebiGridViewDataBuilder(); diff --git a/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h b/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h index e01f82c..1d4f7cc 100644 --- a/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h +++ b/Include/nmNum/nmSubWxs/nmWxPebiGridViewWidget.h @@ -26,12 +26,12 @@ class NM_SUB_WXS_EXPORT nmWxPebiGridViewWidget : public QWidget Q_OBJECT public: - explicit nmWxPebiGridViewWidget(QWidget* pParent = NULL); + explicit nmWxPebiGridViewWidget(QWidget* pParent = nullptr); virtual ~nmWxPebiGridViewWidget(); /** @brief 装入完整数据并复用现有 Renderer、Scene、图层和工具栏。 */ bool setViewData(const nmPebiGridViewData& oViewData, - QString* pError = NULL); + QString* pError = nullptr); /** @brief 保留当前成功数据,只切换到渲染中状态页。 */ void showLoading(); /** @brief 有旧数据时恢复画面并显示提示,否则显示错误状态页。 */ diff --git a/Src/nmNum/nmRender/nmVTKBoundsGridLayer.cpp b/Src/nmNum/nmRender/nmVTKBoundsGridLayer.cpp index 252fbef..d2d59ac 100644 --- a/Src/nmNum/nmRender/nmVTKBoundsGridLayer.cpp +++ b/Src/nmNum/nmRender/nmVTKBoundsGridLayer.cpp @@ -14,13 +14,13 @@ namespace { bool isBoundsGridGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } bool isValidBounds(const double dBounds[6]) { - if(dBounds == NULL) { + if(dBounds == nullptr) { return false; } for(int nIndex = 0; nIndex < 6; ++nIndex) { @@ -79,22 +79,22 @@ nmVTKBoundsGridLayer::~nmVTKBoundsGridLayer() Q_ASSERT(isBoundsGridGuiThread()); // 先解除 Renderer,再断开 Actor 对当前 Renderer 相机的 VTK 引用。 detach(); - if(m_pActor != NULL) { - m_pActor->SetCamera(NULL); + if(m_pActor != nullptr) { + m_pActor->SetCamera(nullptr); } } void nmVTKBoundsGridLayer::setCamera(vtkCamera* pCamera) { Q_ASSERT(isBoundsGridGuiThread()); - if(isBoundsGridGuiThread() && m_pActor != NULL) { + if(isBoundsGridGuiThread() && m_pActor != nullptr) { m_pActor->SetCamera(pCamera); } } vtkCamera* nmVTKBoundsGridLayer::getCamera() const { - return m_pActor != NULL ? m_pActor->GetCamera() : NULL; + return m_pActor != nullptr ? m_pActor->GetCamera() : nullptr; } void nmVTKBoundsGridLayer::setMode(Mode eMode) @@ -127,7 +127,7 @@ bool nmVTKBoundsGridLayer::setBounds( dZMinimum, dZMaximum }; if(!isBoundsGridGuiThread() || !isValidBounds(dIncomingBounds) || - m_pActor == NULL) { + m_pActor == nullptr) { return false; } @@ -168,7 +168,7 @@ bool nmVTKBoundsGridLayer::setBounds( bool nmVTKBoundsGridLayer::getBounds(double dBounds[6]) const { - if(dBounds == NULL || !m_bHasBounds) { + if(dBounds == nullptr || !m_bHasBounds) { return false; } for(int nIndex = 0; nIndex < 6; ++nIndex) { @@ -184,7 +184,7 @@ vtkCubeAxesActor* nmVTKBoundsGridLayer::getActor() const void nmVTKBoundsGridLayer::applyMode() { - if(m_pActor == NULL) { + if(m_pActor == nullptr) { return; } diff --git a/Src/nmNum/nmRender/nmVTKCameraController.cpp b/Src/nmNum/nmRender/nmVTKCameraController.cpp index 0bef895..eba8ff4 100644 --- a/Src/nmNum/nmRender/nmVTKCameraController.cpp +++ b/Src/nmNum/nmRender/nmVTKCameraController.cpp @@ -13,7 +13,7 @@ namespace { bool isCameraGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } @@ -29,7 +29,7 @@ nmVTKCameraController::~nmVTKCameraController() { Q_ASSERT(isCameraGuiThread()); // Renderer 为非所有权引用,析构只解除关系,不修改相机或场景。 - m_pRenderer = NULL; + m_pRenderer = nullptr; } void nmVTKCameraController::setRenderer(vtkRenderer* pRenderer) @@ -54,7 +54,7 @@ bool nmVTKCameraController::resetCamera() } vtkCamera* pCamera = m_pRenderer->GetActiveCamera(); - if(pCamera == NULL) { + if(pCamera == nullptr) { return false; } // 重置入口恢复默认三维透视投影,再按当前可见边界适配。 @@ -83,7 +83,7 @@ bool nmVTKCameraController::fitView() } vtkCamera* pCamera = m_pRenderer->GetActiveCamera(); - if(pCamera == NULL) { + if(pCamera == nullptr) { return false; } @@ -123,14 +123,14 @@ bool nmVTKCameraController::setRotationCenter( double dZ) { Q_ASSERT(isCameraGuiThread()); - if(!isCameraGuiThread() || m_pRenderer == NULL || + if(!isCameraGuiThread() || m_pRenderer == nullptr || !vtkMath::IsFinite(dX) || !vtkMath::IsFinite(dY) || !vtkMath::IsFinite(dZ)) { return false; } vtkCamera* pCamera = m_pRenderer->GetActiveCamera(); - if(pCamera == NULL) { + if(pCamera == nullptr) { return false; } @@ -163,7 +163,7 @@ bool nmVTKCameraController::resetRotationCenter() bool nmVTKCameraController::getVisibleBounds(double dBounds[6]) const { - if(m_pRenderer == NULL || dBounds == NULL) { + if(m_pRenderer == nullptr || dBounds == nullptr) { return false; } @@ -198,7 +198,7 @@ bool nmVTKCameraController::applyStandardView( } vtkCamera* pCamera = m_pRenderer->GetActiveCamera(); - if(pCamera == NULL) { + if(pCamera == nullptr) { return false; } @@ -245,7 +245,7 @@ bool nmVTKCameraController::zoom(double dFactor) } vtkCamera* pCamera = m_pRenderer->GetActiveCamera(); - if(pCamera == NULL) { + if(pCamera == nullptr) { return false; } diff --git a/Src/nmNum/nmRender/nmVTKImageExporter.cpp b/Src/nmNum/nmRender/nmVTKImageExporter.cpp index 7411c66..cfe165e 100644 --- a/Src/nmNum/nmRender/nmVTKImageExporter.cpp +++ b/Src/nmNum/nmRender/nmVTKImageExporter.cpp @@ -25,7 +25,7 @@ namespace { bool isImageExporterGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } @@ -33,7 +33,7 @@ bool isImageExporterGuiThread() nmVTKImageExporter::nmVTKImageExporter(QObject* pParent) : QObject(pParent), - m_pRenderWindow(NULL) + m_pRenderWindow(nullptr) { Q_ASSERT(isImageExporterGuiThread()); } @@ -42,13 +42,13 @@ nmVTKImageExporter::~nmVTKImageExporter() { Q_ASSERT(isImageExporterGuiThread()); // RenderWindow 由容器中的 QVTKWidget 持有,本服务只解除非所有权引用。 - m_pRenderWindow = NULL; + m_pRenderWindow = nullptr; } void nmVTKImageExporter::setRenderWindow(vtkRenderWindow* pRenderWindow) { Q_ASSERT(isImageExporterGuiThread()); - // 不增加 VTK 引用计数,容器销毁时必须先传入 NULL 解除关系。 + // 不增加 VTK 引用计数,容器销毁时必须先传入 nullptr 解除关系。 if(isImageExporterGuiThread()) { m_pRenderWindow = pRenderWindow; } @@ -62,7 +62,7 @@ vtkRenderWindow* nmVTKImageExporter::getRenderWindow() const QImage nmVTKImageExporter::captureImage() const { Q_ASSERT(isImageExporterGuiThread()); - if(!isImageExporterGuiThread() || m_pRenderWindow == NULL) { + if(!isImageExporterGuiThread() || m_pRenderWindow == nullptr) { return QImage(); } @@ -103,7 +103,7 @@ bool nmVTKImageExporter::copyImageToClipboard() const return false; } const QImage oImage = captureImage(); - if(oImage.isNull() || QApplication::clipboard() == NULL) { + if(oImage.isNull() || QApplication::clipboard() == nullptr) { return false; } QApplication::clipboard()->setImage(oImage); @@ -113,7 +113,7 @@ bool nmVTKImageExporter::copyImageToClipboard() const bool nmVTKImageExporter::printImage(QWidget* pParent) { Q_ASSERT(isImageExporterGuiThread()); - if(!isImageExporterGuiThread() || m_pRenderWindow == NULL) { + if(!isImageExporterGuiThread() || m_pRenderWindow == nullptr) { return false; } @@ -128,7 +128,7 @@ bool nmVTKImageExporter::printImage(QWidget* pParent) bool nmVTKImageExporter::printPreview(QWidget* pParent) { Q_ASSERT(isImageExporterGuiThread()); - if(!isImageExporterGuiThread() || m_pRenderWindow == NULL) { + if(!isImageExporterGuiThread() || m_pRenderWindow == nullptr) { return false; } @@ -149,7 +149,7 @@ void nmVTKImageExporter::renderForPrint(QPrinter* pPrinter) QImage nmVTKImageExporter::createQImage(vtkImageData* pImageData) const { - if(pImageData == NULL || pImageData->GetPointData() == NULL) { + if(pImageData == nullptr || pImageData->GetPointData() == nullptr) { return QImage(); } @@ -157,13 +157,13 @@ QImage nmVTKImageExporter::createQImage(vtkImageData* pImageData) const const int nHeight = pImageData->GetDimensions()[1]; vtkUnsignedCharArray* pScalars = vtkUnsignedCharArray::SafeDownCast( pImageData->GetPointData()->GetScalars()); - if(nWidth <= 0 || nHeight <= 0 || pScalars == NULL) { + if(nWidth <= 0 || nHeight <= 0 || pScalars == nullptr) { return QImage(); } const int nComponents = pScalars->GetNumberOfComponents(); unsigned char* pSource = pScalars->GetPointer(0); - if(nComponents < 1 || nComponents > 4 || pSource == NULL) { + if(nComponents < 1 || nComponents > 4 || pSource == nullptr) { return QImage(); } @@ -189,7 +189,7 @@ QImage nmVTKImageExporter::createQImage(vtkImageData* pImageData) const bool nmVTKImageExporter::paintImage(QPrinter* pPrinter) const { - if(pPrinter == NULL) { + if(pPrinter == nullptr) { return false; } const QImage oImage = captureImage(); diff --git a/Src/nmNum/nmRender/nmVTKInteractionManager.cpp b/Src/nmNum/nmRender/nmVTKInteractionManager.cpp index ca51113..0c4e3bb 100644 --- a/Src/nmNum/nmRender/nmVTKInteractionManager.cpp +++ b/Src/nmNum/nmRender/nmVTKInteractionManager.cpp @@ -13,17 +13,17 @@ namespace { bool isInteractionGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } } nmVTKInteractionManager::nmVTKInteractionManager() - : m_pInteractor(NULL), + : m_pInteractor(nullptr), m_pDefaultStyle( vtkSmartPointer::New()), - m_pActiveStyle(NULL) + m_pActiveStyle(nullptr) { Q_ASSERT(isInteractionGuiThread()); } @@ -33,16 +33,16 @@ nmVTKInteractionManager::~nmVTKInteractionManager() Q_ASSERT(isInteractionGuiThread()); // Interactor 持有 Style 引用,必须先清除绑定再释放智能指针。 unbindInteractor(); - m_pActiveStyle = NULL; - m_pDefaultStyle = NULL; + m_pActiveStyle = nullptr; + m_pDefaultStyle = nullptr; } bool nmVTKInteractionManager::bindInteractor( vtkRenderWindowInteractor* pInteractor) { Q_ASSERT(isInteractionGuiThread()); - if(!isInteractionGuiThread() || pInteractor == NULL || - m_pDefaultStyle == NULL) { + if(!isInteractionGuiThread() || pInteractor == nullptr || + m_pDefaultStyle == nullptr) { return false; } @@ -58,7 +58,7 @@ bool nmVTKInteractionManager::installInteractionStyle( vtkInteractorStyle* pStyle) { Q_ASSERT(isInteractionGuiThread()); - if(!isInteractionGuiThread() || m_pInteractor == NULL || pStyle == NULL) { + if(!isInteractionGuiThread() || m_pInteractor == nullptr || pStyle == nullptr) { return false; } @@ -71,8 +71,8 @@ bool nmVTKInteractionManager::installInteractionStyle( bool nmVTKInteractionManager::restoreDefaultInteraction() { Q_ASSERT(isInteractionGuiThread()); - if(!isInteractionGuiThread() || m_pInteractor == NULL || - m_pDefaultStyle == NULL) { + if(!isInteractionGuiThread() || m_pInteractor == nullptr || + m_pDefaultStyle == nullptr) { return false; } // 后续工具临时替换样式后,可通过本入口回到唯一默认交互模式。 @@ -86,10 +86,10 @@ void nmVTKInteractionManager::clearInteractionStyle() return; } - if(m_pInteractor != NULL) { - m_pInteractor->SetInteractorStyle(NULL); + if(m_pInteractor != nullptr) { + m_pInteractor->SetInteractorStyle(nullptr); } - m_pActiveStyle = NULL; + m_pActiveStyle = nullptr; } void nmVTKInteractionManager::unbindInteractor() @@ -101,7 +101,7 @@ void nmVTKInteractionManager::unbindInteractor() // 本管理器定义单一活动模式边界,解绑时不保留任何旧 Style。 clearInteractionStyle(); - m_pInteractor = NULL; + m_pInteractor = nullptr; } vtkRenderWindowInteractor* nmVTKInteractionManager::getInteractor() const diff --git a/Src/nmNum/nmRender/nmVTKMeshLayer.cpp b/Src/nmNum/nmRender/nmVTKMeshLayer.cpp index 6eed681..d19153c 100644 --- a/Src/nmNum/nmRender/nmVTKMeshLayer.cpp +++ b/Src/nmNum/nmRender/nmVTKMeshLayer.cpp @@ -20,7 +20,7 @@ namespace { bool isMeshLayerGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } @@ -28,7 +28,7 @@ bool isMeshLayerGuiThread() nmVTKMeshLayer::nmVTKMeshLayer(const QString& sLayerId) : nmVTKRenderLayer(sLayerId), - m_pDataSet(NULL), + m_pDataSet(nullptr), m_pMapper(vtkSmartPointer::New()), m_pActor(vtkSmartPointer::New()), m_pLookupTable(vtkSmartPointer::New()), @@ -56,7 +56,7 @@ nmVTKMeshLayer::~nmVTKMeshLayer() Q_ASSERT(isMeshLayerGuiThread()); // 派生成员释放前先解除 Renderer,基类析构中的 detach 仍保持幂等。 detach(); - m_pDataSet = NULL; + m_pDataSet = nullptr; } bool nmVTKMeshLayer::setDataSet(vtkDataSet* pDataSet) @@ -70,14 +70,14 @@ bool nmVTKMeshLayer::setDataSet(vtkDataSet* pDataSet) m_pDataSet = pDataSet; m_pMapper->SetInputData(pDataSet); - if(pDataSet == NULL) { + if(pDataSet == nullptr) { clearInvalidScalarState(); return false; } // 更换数据集时保留调用方此前的数组选择;若同名数组存在则恢复其映射方式。 if(!m_aScalarArrayName.isEmpty()) { - if(getSelectedScalarArray() == NULL) { + if(getSelectedScalarArray() == nullptr) { clearInvalidScalarState(); return false; } @@ -105,7 +105,7 @@ vtkDataSet* nmVTKMeshLayer::getDataSet() const void nmVTKMeshLayer::setDisplayMode(DisplayMode eMode) { Q_ASSERT(isMeshLayerGuiThread()); - if(!isMeshLayerGuiThread() || m_pActor == NULL) { + if(!isMeshLayerGuiThread() || m_pActor == nullptr) { return; } @@ -139,7 +139,7 @@ bool nmVTKMeshLayer::setOpacity(double dOpacity) { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || !vtkMath::IsFinite(dOpacity) || - m_pActor == NULL) { + m_pActor == nullptr) { return false; } m_pActor->GetProperty()->SetOpacity(qBound(0.0, dOpacity, 1.0)); @@ -148,13 +148,13 @@ bool nmVTKMeshLayer::setOpacity(double dOpacity) double nmVTKMeshLayer::getOpacity() const { - return m_pActor != NULL ? m_pActor->GetProperty()->GetOpacity() : 0.0; + return m_pActor != nullptr ? m_pActor->GetProperty()->GetOpacity() : 0.0; } void nmVTKMeshLayer::setScalarVisibility(bool bVisible) { Q_ASSERT(isMeshLayerGuiThread()); - if(!isMeshLayerGuiThread() || m_pMapper == NULL) { + if(!isMeshLayerGuiThread() || m_pMapper == nullptr) { return; } m_pMapper->SetScalarVisibility(bVisible ? 1 : 0); @@ -162,7 +162,7 @@ void nmVTKMeshLayer::setScalarVisibility(bool bVisible) bool nmVTKMeshLayer::isScalarVisible() const { - return m_pMapper != NULL && m_pMapper->GetScalarVisibility() != 0; + return m_pMapper != nullptr && m_pMapper->GetScalarVisibility() != 0; } bool nmVTKMeshLayer::setScalarArray( @@ -171,7 +171,7 @@ bool nmVTKMeshLayer::setScalarArray( { Q_ASSERT(isMeshLayerGuiThread()); if(!isMeshLayerGuiThread() || sArrayName.isEmpty() || - m_pDataSet == NULL || m_pMapper == NULL || + m_pDataSet == nullptr || m_pMapper == nullptr || (eAssociation != ScalarAssociation_CellData && eAssociation != ScalarAssociation_PointData)) { return false; @@ -181,7 +181,7 @@ bool nmVTKMeshLayer::setScalarArray( vtkDataArray* pArray = eAssociation == ScalarAssociation_CellData ? m_pDataSet->GetCellData()->GetArray(aArrayName.constData()) : m_pDataSet->GetPointData()->GetArray(aArrayName.constData()); - if(pArray == NULL) { + if(pArray == nullptr) { // 失败时保留原数组选择和原 Mapper 状态。 return false; } @@ -230,7 +230,7 @@ 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) { + m_pMapper == nullptr || m_pLookupTable == nullptr) { return false; } @@ -275,8 +275,8 @@ vtkLookupTable* nmVTKMeshLayer::getLookupTable() const vtkDataArray* nmVTKMeshLayer::getSelectedScalarArray() const { - if(m_pDataSet == NULL || m_aScalarArrayName.isEmpty()) { - return NULL; + if(m_pDataSet == nullptr || m_aScalarArrayName.isEmpty()) { + return nullptr; } return m_eScalarAssociation == ScalarAssociation_CellData ? m_pDataSet->GetCellData()->GetArray( @@ -288,7 +288,7 @@ vtkDataArray* nmVTKMeshLayer::getSelectedScalarArray() const bool nmVTKMeshLayer::applyDataScalarRange() { vtkDataArray* pArray = getSelectedScalarArray(); - if(pArray == NULL || m_pMapper == NULL || m_pLookupTable == NULL) { + if(pArray == nullptr || m_pMapper == nullptr || m_pLookupTable == nullptr) { return false; } diff --git a/Src/nmNum/nmRender/nmVTKOrientationMarkerController.cpp b/Src/nmNum/nmRender/nmVTKOrientationMarkerController.cpp new file mode 100644 index 0000000..690e899 --- /dev/null +++ b/Src/nmNum/nmRender/nmVTKOrientationMarkerController.cpp @@ -0,0 +1,263 @@ +#include "nmVTKOrientationMarkerController.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace { + +// OrientationMarkerWidget 会维护观察关系和辅助 Renderer,只能在 GUI 线程操作。 +bool isOrientationMarkerGuiThread() +{ + QCoreApplication* pApplication = QCoreApplication::instance(); + return pApplication == nullptr || + pApplication->thread() == QThread::currentThread(); +} + +// 同时设置轴杆、箭头和标签颜色,避免依赖不同 VTK 版本的默认外观。 +void setAxisColor(vtkProperty* pShaftProperty, + vtkProperty* pTipProperty, + vtkCaptionActor2D* pCaptionActor, + double dRed, + double dGreen, + double dBlue) +{ + if(pShaftProperty != nullptr) { + pShaftProperty->SetColor(dRed, dGreen, dBlue); + } + if(pTipProperty != nullptr) { + pTipProperty->SetColor(dRed, dGreen, dBlue); + } + if(pCaptionActor != nullptr && + pCaptionActor->GetCaptionTextProperty() != nullptr) { + pCaptionActor->GetCaptionTextProperty()->SetColor( + dRed, dGreen, dBlue); + } +} + +} + +nmVTKOrientationMarkerController::nmVTKOrientationMarkerController() + : m_pAxesActor(vtkSmartPointer::New()), + m_pMarkerWidget( + vtkSmartPointer::New()), + m_pInteractor(nullptr), + m_pRenderer(nullptr), + m_bVisible(true), + m_bViewAvailable(false) +{ + Q_ASSERT(isOrientationMarkerGuiThread()); + + m_dViewport[0] = 0.015; + m_dViewport[1] = 0.015; + m_dViewport[2] = 0.13; + m_dViewport[3] = 0.13; + + if(m_pAxesActor != nullptr) { + m_pAxesActor->SetXAxisLabelText("X"); + m_pAxesActor->SetYAxisLabelText("Y"); + m_pAxesActor->SetZAxisLabelText("Z"); + setAxisColor(m_pAxesActor->GetXAxisShaftProperty(), + m_pAxesActor->GetXAxisTipProperty(), + m_pAxesActor->GetXAxisCaptionActor2D(), + 1.0, 0.0, 0.0); + setAxisColor(m_pAxesActor->GetYAxisShaftProperty(), + m_pAxesActor->GetYAxisTipProperty(), + m_pAxesActor->GetYAxisCaptionActor2D(), + 0.0, 1.0, 0.0); + setAxisColor(m_pAxesActor->GetZAxisShaftProperty(), + m_pAxesActor->GetZAxisTipProperty(), + m_pAxesActor->GetZAxisCaptionActor2D(), + 0.0, 0.0, 1.0); + } + + if(m_pMarkerWidget != nullptr) { + // 构造阶段尚未绑定 Interactor,只关闭键盘入口并保存默认视口。 + m_pMarkerWidget->KeyPressActivationOff(); + m_pMarkerWidget->SetViewport(m_dViewport); + } +} + +nmVTKOrientationMarkerController::~nmVTKOrientationMarkerController() +{ + Q_ASSERT(isOrientationMarkerGuiThread()); + unbindInteractor(); + m_pMarkerWidget = nullptr; + m_pAxesActor = nullptr; +} + +bool nmVTKOrientationMarkerController::bindInteractor( + vtkRenderWindowInteractor* pInteractor, + vtkRenderer* pRenderer) +{ + Q_ASSERT(isOrientationMarkerGuiThread()); + if(!isOrientationMarkerGuiThread()) { + return false; + } + + // 每次绑定都从干净状态开始,避免 Widget 保留旧窗口的观察关系。 + unbindInteractor(); + + vtkRenderWindow* pRenderWindow = pInteractor != nullptr ? + pInteractor->GetRenderWindow() : nullptr; + if(pInteractor == nullptr || pRenderer == nullptr || + pRenderWindow == nullptr || pRenderer->GetRenderWindow() != pRenderWindow || + m_pAxesActor == nullptr || m_pMarkerWidget == nullptr) { + return false; + } + + m_pInteractor = pInteractor; + m_pRenderer = pRenderer; + + // 显式指定主 Renderer,不能依赖鼠标位置推断多 Renderer 窗口的父相机。 + m_pMarkerWidget->SetOrientationMarker(m_pAxesActor); + m_pMarkerWidget->SetDefaultRenderer(m_pRenderer); + m_pMarkerWidget->SetCurrentRenderer(m_pRenderer); + m_pMarkerWidget->SetInteractor(m_pInteractor); + updateEnabledState(); + + bool bBindingValid = + m_pMarkerWidget->GetInteractor() == m_pInteractor && + m_pMarkerWidget->GetDefaultRenderer() == m_pRenderer && + m_pMarkerWidget->GetOrientationMarker() == + m_pAxesActor.GetPointer(); + if(bBindingValid && m_bVisible && m_bViewAvailable) { + bBindingValid = m_pMarkerWidget->GetEnabled() != 0 && + m_pMarkerWidget->GetInteractive() == 0 && + m_pMarkerWidget->GetCurrentRenderer() == m_pRenderer; + } + if(!bBindingValid) { + unbindInteractor(); + return false; + } + return true; +} + +void nmVTKOrientationMarkerController::unbindInteractor() +{ + Q_ASSERT(isOrientationMarkerGuiThread()); + if(!isOrientationMarkerGuiThread()) { + return; + } + + if(m_pMarkerWidget == nullptr) { + m_pInteractor = nullptr; + m_pRenderer = nullptr; + return; + } + + // 只有已绑定且实际启用时才禁用,重复解绑不会触发 VTK 状态警告。 + if(m_pMarkerWidget->GetInteractor() != nullptr && + m_pMarkerWidget->GetEnabled() != 0) { + m_pMarkerWidget->SetEnabled(0); + } + + // 完整解绑会释放 Widget 持有的 Actor、Renderer 和 Interactor 引用。 + m_pMarkerWidget->SetOrientationMarker(nullptr); + m_pMarkerWidget->SetDefaultRenderer(nullptr); + m_pMarkerWidget->SetCurrentRenderer(nullptr); + m_pMarkerWidget->SetInteractor(nullptr); + m_pInteractor = nullptr; + m_pRenderer = nullptr; +} + +void nmVTKOrientationMarkerController::setVisible(bool bVisible) +{ + Q_ASSERT(isOrientationMarkerGuiThread()); + if(!isOrientationMarkerGuiThread()) { + return; + } + + m_bVisible = bVisible; + updateEnabledState(); +} + +bool nmVTKOrientationMarkerController::isVisible() const +{ + return m_bVisible; +} + +void nmVTKOrientationMarkerController::setViewAvailable(bool bAvailable) +{ + Q_ASSERT(isOrientationMarkerGuiThread()); + if(!isOrientationMarkerGuiThread()) { + return; + } + + m_bViewAvailable = bAvailable; + updateEnabledState(); +} + +bool nmVTKOrientationMarkerController::isViewAvailable() const +{ + return m_bViewAvailable; +} + +bool nmVTKOrientationMarkerController::setViewport( + double dXMinimum, + double dYMinimum, + double dXMaximum, + double dYMaximum) +{ + Q_ASSERT(isOrientationMarkerGuiThread()); + if(!isOrientationMarkerGuiThread() || + !vtkMath::IsFinite(dXMinimum) || + !vtkMath::IsFinite(dYMinimum) || + !vtkMath::IsFinite(dXMaximum) || + !vtkMath::IsFinite(dYMaximum) || + dXMinimum < 0.0 || dYMinimum < 0.0 || + dXMaximum > 1.0 || dYMaximum > 1.0 || + dXMaximum <= dXMinimum || dYMaximum <= dYMinimum || + m_pMarkerWidget == nullptr) { + return false; + } + + m_dViewport[0] = dXMinimum; + m_dViewport[1] = dYMinimum; + m_dViewport[2] = dXMaximum; + m_dViewport[3] = dYMaximum; + m_pMarkerWidget->SetViewport(m_dViewport); + return true; +} + +void nmVTKOrientationMarkerController::updateEnabledState() +{ + if(m_pMarkerWidget == nullptr) { + return; + } + + const bool bShouldEnable = m_pAxesActor != nullptr && + m_pInteractor != nullptr && + m_pRenderer != nullptr && + m_pMarkerWidget->GetInteractor() == m_pInteractor && + m_pMarkerWidget->GetDefaultRenderer() == m_pRenderer && + m_pMarkerWidget->GetOrientationMarker() == + m_pAxesActor.GetPointer() && + m_bVisible && m_bViewAvailable; + if(bShouldEnable) { + // VTK 7.1 禁用 Widget 后会清空 CurrentRenderer,恢复前必须重新指定。 + m_pMarkerWidget->SetCurrentRenderer(m_pRenderer); + m_pMarkerWidget->SetEnabled(1); + if(m_pMarkerWidget->GetEnabled() != 0 && + m_pMarkerWidget->GetInteractive() != 0) { + // Interactive 只有在首次成功启用后设置才会被 VTK 正确接受。 + m_pMarkerWidget->SetInteractive(0); + } + return; + } + + // 临时隐藏只禁用 Widget,保留 Marker、Interactor 和默认 Renderer 绑定。 + if(m_pMarkerWidget->GetInteractor() != nullptr && + m_pMarkerWidget->GetEnabled() != 0) { + m_pMarkerWidget->SetEnabled(0); + } +} diff --git a/Src/nmNum/nmRender/nmVTKRenderLayer.cpp b/Src/nmNum/nmRender/nmVTKRenderLayer.cpp index 53fc3d1..6b1ddbd 100644 --- a/Src/nmNum/nmRender/nmVTKRenderLayer.cpp +++ b/Src/nmNum/nmRender/nmVTKRenderLayer.cpp @@ -12,7 +12,7 @@ namespace { bool isLayerGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } @@ -21,9 +21,9 @@ bool isLayerGuiThread() nmVTKRenderLayer::nmVTKRenderLayer(const QString& sLayerId) : m_sLayerId(sLayerId), m_bVisible(true), - m_pRenderProp(NULL), - m_pRenderer(NULL), - m_pOwningScene(NULL) + m_pRenderProp(nullptr), + m_pRenderer(nullptr), + m_pOwningScene(nullptr) { Q_ASSERT(isLayerGuiThread()); // 稳定 ID 只用于 Scene 查找,不承担可翻译的界面文案。 @@ -32,11 +32,11 @@ nmVTKRenderLayer::nmVTKRenderLayer(const QString& sLayerId) nmVTKRenderLayer::~nmVTKRenderLayer() { Q_ASSERT(isLayerGuiThread()); - Q_ASSERT(m_pOwningScene == NULL); + Q_ASSERT(m_pOwningScene == nullptr); // 主 Prop 由基类智能指针继续持有,因此此时 detach 不依赖派生类成员。 detach(); - m_pRenderProp = NULL; - m_pOwningScene = NULL; + m_pRenderProp = nullptr; + m_pOwningScene = nullptr; } QString nmVTKRenderLayer::getLayerId() const @@ -47,7 +47,7 @@ QString nmVTKRenderLayer::getLayerId() const bool nmVTKRenderLayer::attach(vtkRenderer* pRenderer) { Q_ASSERT(isLayerGuiThread()); - if(!isLayerGuiThread() || pRenderer == NULL || m_pRenderProp == NULL) { + if(!isLayerGuiThread() || pRenderer == nullptr || m_pRenderProp == nullptr) { return false; } if(m_pRenderer == pRenderer) { @@ -66,10 +66,10 @@ bool nmVTKRenderLayer::attach(vtkRenderer* pRenderer) void nmVTKRenderLayer::detach() { Q_ASSERT(isLayerGuiThread()); - if(m_pRenderer != NULL && m_pRenderProp != NULL) { + if(m_pRenderer != nullptr && m_pRenderProp != nullptr) { m_pRenderer->RemoveViewProp(m_pRenderProp); } - m_pRenderer = NULL; + m_pRenderer = nullptr; } void nmVTKRenderLayer::setVisible(bool bVisible) @@ -79,7 +79,7 @@ void nmVTKRenderLayer::setVisible(bool bVisible) return; } m_bVisible = bVisible; - if(m_pRenderProp != NULL) { + if(m_pRenderProp != nullptr) { m_pRenderProp->SetVisibility(bVisible ? 1 : 0); } } @@ -91,13 +91,13 @@ bool nmVTKRenderLayer::isVisible() const bool nmVTKRenderLayer::isAttached() const { - return m_pRenderer != NULL; + return m_pRenderer != nullptr; } bool nmVTKRenderLayer::setRenderProp(vtkProp* pProp) { Q_ASSERT(isLayerGuiThread()); - if(!isLayerGuiThread() || isAttached() || pProp == NULL) { + if(!isLayerGuiThread() || isAttached() || pProp == nullptr) { return false; } // vtkSmartPointer 接管一个 VTK 引用,派生类可继续持有同一对象。 @@ -119,7 +119,7 @@ vtkRenderer* nmVTKRenderLayer::getAttachedRenderer() const bool nmVTKRenderLayer::claimSceneOwnership(nmVTKScene* pScene) { Q_ASSERT(isLayerGuiThread()); - if(!isLayerGuiThread() || pScene == NULL || m_pOwningScene != NULL) { + if(!isLayerGuiThread() || pScene == nullptr || m_pOwningScene != nullptr) { return false; } @@ -131,10 +131,10 @@ bool nmVTKRenderLayer::claimSceneOwnership(nmVTKScene* pScene) bool nmVTKRenderLayer::releaseSceneOwnership(nmVTKScene* pScene) { Q_ASSERT(isLayerGuiThread()); - if(!isLayerGuiThread() || pScene == NULL || m_pOwningScene != pScene) { + if(!isLayerGuiThread() || pScene == nullptr || m_pOwningScene != pScene) { return false; } - m_pOwningScene = NULL; + m_pOwningScene = nullptr; return true; } diff --git a/Src/nmNum/nmRender/nmVTKScalarBarLayer.cpp b/Src/nmNum/nmRender/nmVTKScalarBarLayer.cpp index 914446e..9cec6fc 100644 --- a/Src/nmNum/nmRender/nmVTKScalarBarLayer.cpp +++ b/Src/nmNum/nmRender/nmVTKScalarBarLayer.cpp @@ -14,7 +14,7 @@ namespace { bool isScalarBarGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } @@ -22,7 +22,7 @@ bool isScalarBarGuiThread() nmVTKScalarBarLayer::nmVTKScalarBarLayer(const QString& sLayerId) : nmVTKRenderLayer(sLayerId), - m_pLookupTable(NULL), + m_pLookupTable(nullptr), m_pActor(vtkSmartPointer::New()) { Q_ASSERT(isScalarBarGuiThread()); @@ -35,7 +35,7 @@ nmVTKScalarBarLayer::~nmVTKScalarBarLayer() Q_ASSERT(isScalarBarGuiThread()); // 先移除二维 Prop,再释放对外部 LookupTable 的共享引用。 detach(); - m_pLookupTable = NULL; + m_pLookupTable = nullptr; } void nmVTKScalarBarLayer::setLookupTable(vtkLookupTable* pLookupTable) diff --git a/Src/nmNum/nmRender/nmVTKScene.cpp b/Src/nmNum/nmRender/nmVTKScene.cpp index b28522b..dd8b790 100644 --- a/Src/nmNum/nmRender/nmVTKScene.cpp +++ b/Src/nmNum/nmRender/nmVTKScene.cpp @@ -13,7 +13,7 @@ namespace { bool isSceneGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } @@ -31,13 +31,13 @@ nmVTKScene::~nmVTKScene() Q_ASSERT(isSceneGuiThread()); // 即使在 Release 中违反线程约束,也优先解除 Renderer 对 Prop 的引用。 clearLayers(); - m_pRenderer = NULL; + m_pRenderer = nullptr; } bool nmVTKScene::addLayer(nmVTKRenderLayer* pLayer) { Q_ASSERT(isSceneGuiThread()); - if(!isSceneGuiThread() || pLayer == NULL || m_pRenderer == NULL) { + if(!isSceneGuiThread() || pLayer == nullptr || m_pRenderer == nullptr) { return false; } @@ -66,9 +66,9 @@ nmVTKRenderLayer* nmVTKScene::getLayer(const QString& sLayerId) const { Q_ASSERT(isSceneGuiThread()); if(!isSceneGuiThread()) { - return NULL; + return nullptr; } - return m_mapLayers.value(sLayerId, NULL); + return m_mapLayers.value(sLayerId, nullptr); } bool nmVTKScene::removeLayer(const QString& sLayerId) @@ -79,7 +79,7 @@ bool nmVTKScene::removeLayer(const QString& sLayerId) } nmVTKRenderLayer* pLayer = m_mapLayers.take(sLayerId); - if(pLayer != NULL) { + if(pLayer != nullptr) { // 删除前先从 Renderer 移除 Prop,避免留下悬空引用。 pLayer->detach(); pLayer->releaseSceneOwnership(this); @@ -105,7 +105,7 @@ void nmVTKScene::clearLayers() m_mapLayers.begin(); nmVTKRenderLayer* pLayer = oIterator.value(); m_mapLayers.erase(oIterator); - if(pLayer != NULL) { + if(pLayer != nullptr) { pLayer->detach(); pLayer->releaseSceneOwnership(this); delete pLayer; diff --git a/Src/nmNum/nmRender/nmVTKViewCommandController.cpp b/Src/nmNum/nmRender/nmVTKViewCommandController.cpp index d038ab1..c7524cd 100644 --- a/Src/nmNum/nmRender/nmVTKViewCommandController.cpp +++ b/Src/nmNum/nmRender/nmVTKViewCommandController.cpp @@ -30,7 +30,7 @@ nmVTKViewCommandController::nmVTKViewCommandController( m_bViewAvailable(false) { for(int nIndex = 0; nIndex < ViewCommandCount; ++nIndex) { - m_pActions[nIndex] = NULL; + m_pActions[nIndex] = nullptr; } // QAction 只在构造阶段创建一次,后续所有菜单和工具栏复用这些实例。 @@ -64,7 +64,7 @@ nmVTKViewCommandController::nmVTKViewCommandController( nmVTKViewCommandController::~nmVTKViewCommandController() { // QAction 由 QObject 父子关系释放;这里只解除非所有权容器引用。 - m_pContainer = NULL; + m_pContainer = nullptr; } void nmVTKViewCommandController::setCapabilities(ViewCommands eCommands) @@ -83,12 +83,12 @@ QAction* nmVTKViewCommandController::getAction( ViewCommand eCommand) const { const int nIndex = actionIndex(eCommand); - return nIndex >= 0 ? m_pActions[nIndex] : NULL; + return nIndex >= 0 ? m_pActions[nIndex] : nullptr; } void nmVTKViewCommandController::populateToolBar(QToolBar* pToolBar) const { - if(pToolBar == NULL) { + if(pToolBar == nullptr) { return; } @@ -121,7 +121,7 @@ void nmVTKViewCommandController::populateToolBar(QToolBar* pToolBar) const void nmVTKViewCommandController::populateContextMenu(QMenu* pMenu) const { - if(pMenu == NULL) { + if(pMenu == nullptr) { return; } @@ -202,8 +202,8 @@ QAction* nmVTKViewCommandController::createAction( const char* pSlot) { const int nIndex = actionIndex(eCommand); - if(nIndex < 0 || m_pActions[nIndex] != NULL) { - return NULL; + if(nIndex < 0 || m_pActions[nIndex] != nullptr) { + return nullptr; } QAction* pAction = sIconFile.isEmpty() @@ -211,7 +211,7 @@ QAction* nmVTKViewCommandController::createAction( : new QAction(QIcon(commandIconPath(sIconFile)), sText, this); pAction->setToolTip(sText); pAction->setEnabled(false); - if(m_pContainer != NULL && pSlot != NULL) { + if(m_pContainer != nullptr && pSlot != nullptr) { connect(pAction, SIGNAL(triggered()), m_pContainer, pSlot); } m_pActions[nIndex] = pAction; @@ -260,7 +260,7 @@ void nmVTKViewCommandController::updateActionStates() }; for(int nIndex = 0; nIndex < ViewCommandCount; ++nIndex) { QAction* pAction = m_pActions[nIndex]; - if(pAction != NULL) { + if(pAction != nullptr) { const bool bSupported = supports(eCommands[nIndex]); pAction->setVisible(bSupported); pAction->setEnabled(bSupported && m_bViewAvailable); diff --git a/Src/nmNum/nmRender/nmWxVTKRenderContainerWidget.cpp b/Src/nmNum/nmRender/nmWxVTKRenderContainerWidget.cpp index 0201ed8..fc583fb 100644 --- a/Src/nmNum/nmRender/nmWxVTKRenderContainerWidget.cpp +++ b/Src/nmNum/nmRender/nmWxVTKRenderContainerWidget.cpp @@ -3,6 +3,7 @@ #include "nmVTKCameraController.h" #include "nmVTKImageExporter.h" #include "nmVTKInteractionManager.h" +#include "nmVTKOrientationMarkerController.h" #include "nmVTKScene.h" #include "nmVTKViewCommandController.h" @@ -28,17 +29,18 @@ VTK_MODULE_INIT(vtkInteractionStyle) nmWxVTKRenderContainerWidget::nmWxVTKRenderContainerWidget(QWidget* pParent) : QWidget(pParent), - m_pMainLayout(NULL), - m_pStateStack(NULL), - m_pStatePage(NULL), - m_pStateLabel(NULL), - m_pVtkWidget(NULL), - m_pRenderer(NULL), - m_pScene(NULL), - m_pCameraController(NULL), - m_pInteractionManager(NULL), - m_pImageExporter(NULL), - m_pViewCommandController(NULL) + m_pMainLayout(nullptr), + m_pStateStack(nullptr), + m_pStatePage(nullptr), + m_pStateLabel(nullptr), + m_pVtkWidget(nullptr), + m_pRenderer(nullptr), + m_pScene(nullptr), + m_pCameraController(nullptr), + m_pInteractionManager(nullptr), + m_pImageExporter(nullptr), + m_pViewCommandController(nullptr), + m_pOrientationMarkerController(nullptr) { Q_ASSERT(isGuiThread()); @@ -68,7 +70,7 @@ nmWxVTKRenderContainerWidget::nmWxVTKRenderContainerWidget(QWidget* pParent) vtkRenderWindow* pRenderWindow = getRenderWindow(); vtkRenderWindowInteractor* pInteractor = getInteractor(); m_pRenderer = vtkSmartPointer::New(); - if(pRenderWindow != NULL && m_pRenderer != NULL) { + if(pRenderWindow != nullptr && m_pRenderer != nullptr) { pRenderWindow->AddRenderer(m_pRenderer); m_pRenderer->SetGradientBackground(true); m_pRenderer->SetBackground(0.67, 0.82, 0.94); @@ -103,11 +105,17 @@ nmWxVTKRenderContainerWidget::nmWxVTKRenderContainerWidget(QWidget* pParent) const bool bInteractionReady = m_pInteractionManager->bindInteractor(pInteractor); + // 方向轴是独立辅助 Renderer;绑定失败只隐藏方向轴,不影响主视图初始化。 + m_pOrientationMarkerController = + new nmVTKOrientationMarkerController(); + m_pOrientationMarkerController->bindInteractor( + pInteractor, m_pRenderer); + // 6. 只接管右键菜单,左键、中键和滚轮继续交给 VTK。 m_pVtkWidget->installEventFilter(this); // 7. 基础 VTK 对象完整时进入就绪页,否则保留明确错误状态。 - if(pRenderWindow != NULL && m_pRenderer != NULL && bInteractionReady) { + if(pRenderWindow != nullptr && m_pRenderer != nullptr && bInteractionReady) { showReadyState(); } else { showErrorState(tr("Unable to initialize the render view.")); @@ -119,51 +127,58 @@ nmWxVTKRenderContainerWidget::~nmWxVTKRenderContainerWidget() Q_ASSERT(isGuiThread()); // 1. 先阻止新的右键菜单回调进入销毁中的对象。 - if(m_pVtkWidget != NULL) { + if(m_pVtkWidget != nullptr) { m_pVtkWidget->removeEventFilter(this); } - // 先销毁 QAction,避免后续服务拆除期间再触发容器槽函数。 - if(m_pViewCommandController != NULL) { + // 2. 先销毁 QAction,避免后续服务拆除期间再触发容器槽函数。 + if(m_pViewCommandController != nullptr) { delete m_pViewCommandController; - m_pViewCommandController = NULL; + m_pViewCommandController = nullptr; + } + + // 3. MarkerWidget 持有 Interactor 和辅助 Renderer 引用,必须优先解绑。 + if(m_pOrientationMarkerController != nullptr) { + m_pOrientationMarkerController->unbindInteractor(); + delete m_pOrientationMarkerController; + m_pOrientationMarkerController = nullptr; } - // 图片服务不拥有 RenderWindow,先解除引用再销毁服务。 - if(m_pImageExporter != NULL) { - m_pImageExporter->setRenderWindow(NULL); + // 4. 图片服务不拥有 RenderWindow,先解除引用再销毁服务。 + if(m_pImageExporter != nullptr) { + m_pImageExporter->setRenderWindow(nullptr); delete m_pImageExporter; - m_pImageExporter = NULL; + m_pImageExporter = nullptr; } - // 2. Interactor 必须先释放对默认 Style 的 VTK 引用。 - if(m_pInteractionManager != NULL) { + // 5. Interactor 必须先释放对默认 Style 的 VTK 引用。 + if(m_pInteractionManager != nullptr) { m_pInteractionManager->unbindInteractor(); delete m_pInteractionManager; - m_pInteractionManager = NULL; + m_pInteractionManager = nullptr; } - // 3. Scene 在 Renderer 移除前清空所有 Layer 和 Prop。 - if(m_pScene != NULL) { + // 6. Scene 在 Renderer 移除前清空所有 Layer 和 Prop。 + if(m_pScene != nullptr) { m_pScene->clear(); delete m_pScene; - m_pScene = NULL; + m_pScene = nullptr; } - // 4. 相机控制器仅解除 Renderer 非所有权引用。 - if(m_pCameraController != NULL) { - m_pCameraController->setRenderer(NULL); + // 7. 相机控制器仅解除 Renderer 非所有权引用。 + if(m_pCameraController != nullptr) { + m_pCameraController->setRenderer(nullptr); delete m_pCameraController; - m_pCameraController = NULL; + m_pCameraController = nullptr; } - // 5、6. 最后从 RenderWindow 移除并释放当前实例 Renderer。 + // 8. 最后从 RenderWindow 移除并释放当前实例 Renderer。 vtkRenderWindow* pRenderWindow = getRenderWindow(); - if(pRenderWindow != NULL && m_pRenderer != NULL) { + if(pRenderWindow != nullptr && m_pRenderer != nullptr) { pRenderWindow->RemoveRenderer(m_pRenderer); } - m_pRenderer = NULL; - // 7. QVTKWidget、状态页和布局随后由 Qt 父子关系自动销毁。 + m_pRenderer = nullptr; + // QVTKWidget、状态页和布局随后由 Qt 父子关系自动销毁。 } QVTKWidget* nmWxVTKRenderContainerWidget::getVtkWidget() const @@ -178,14 +193,14 @@ vtkRenderer* nmWxVTKRenderContainerWidget::getRenderer() const vtkRenderWindow* nmWxVTKRenderContainerWidget::getRenderWindow() const { - return m_pVtkWidget != NULL ? m_pVtkWidget->GetRenderWindow() : NULL; + return m_pVtkWidget != nullptr ? m_pVtkWidget->GetRenderWindow() : nullptr; } vtkRenderWindowInteractor* nmWxVTKRenderContainerWidget::getInteractor() const { vtkRenderWindow* pRenderWindow = getRenderWindow(); - return pRenderWindow != NULL ? pRenderWindow->GetInteractor() : NULL; + return pRenderWindow != nullptr ? pRenderWindow->GetInteractor() : nullptr; } nmVTKScene* nmWxVTKRenderContainerWidget::getScene() const @@ -199,10 +214,16 @@ nmWxVTKRenderContainerWidget::getViewCommandController() const return m_pViewCommandController; } +nmVTKOrientationMarkerController* +nmWxVTKRenderContainerWidget::getOrientationMarkerController() const +{ + return m_pOrientationMarkerController; +} + void nmWxVTKRenderContainerWidget::setViewCommandCapabilities( nmVTKViewCommandController::ViewCommands eCommands) { - if(m_pViewCommandController != NULL) { + if(m_pViewCommandController != nullptr) { m_pViewCommandController->setCapabilities(eCommands); } } @@ -211,21 +232,21 @@ bool nmWxVTKRenderContainerWidget::installInteractionStyle( vtkInteractorStyle* pStyle) { Q_ASSERT(isGuiThread()); - return isGuiThread() && m_pInteractionManager != NULL && + return isGuiThread() && m_pInteractionManager != nullptr && m_pInteractionManager->installInteractionStyle(pStyle); } bool nmWxVTKRenderContainerWidget::restoreDefaultInteraction() { Q_ASSERT(isGuiThread()); - return isGuiThread() && m_pInteractionManager != NULL && + return isGuiThread() && m_pInteractionManager != nullptr && m_pInteractionManager->restoreDefaultInteraction(); } void nmWxVTKRenderContainerWidget::clearInteractionStyle() { Q_ASSERT(isGuiThread()); - if(isGuiThread() && m_pInteractionManager != NULL) { + if(isGuiThread() && m_pInteractionManager != nullptr) { m_pInteractionManager->clearInteractionStyle(); } } @@ -235,7 +256,7 @@ void nmWxVTKRenderContainerWidget::renderView() Q_ASSERT(isGuiThread()); vtkRenderWindow* pRenderWindow = getRenderWindow(); // Scene、Layer 和相机均不隐式渲染,批量更新最终汇聚到此入口。 - if(isGuiThread() && pRenderWindow != NULL) { + if(isGuiThread() && pRenderWindow != nullptr) { pRenderWindow->Render(); } } @@ -244,7 +265,7 @@ bool nmWxVTKRenderContainerWidget::fitTopViewWithoutRender() { Q_ASSERT(isGuiThread()); // 相机控制器本身不触发 Render,便于业务图层完成整批更新后只渲染一次。 - return isGuiThread() && m_pCameraController != NULL && + return isGuiThread() && m_pCameraController != nullptr && m_pCameraController->setTopView(); } @@ -256,9 +277,12 @@ void nmWxVTKRenderContainerWidget::showReadyState() } // 状态页与 VTK 页尺寸稳定,切换页面不会重建 RenderWindow 或 Renderer。 m_pStateStack->setCurrentWidget(m_pVtkWidget); - if(m_pViewCommandController != NULL) { + if(m_pViewCommandController != nullptr) { m_pViewCommandController->setViewAvailable(true); } + if(m_pOrientationMarkerController != nullptr) { + m_pOrientationMarkerController->setViewAvailable(true); + } renderView(); } @@ -280,21 +304,21 @@ void nmWxVTKRenderContainerWidget::showRenderingState( void nmWxVTKRenderContainerWidget::zoomIn() { - if(m_pCameraController != NULL && m_pCameraController->zoomIn()) { + if(m_pCameraController != nullptr && m_pCameraController->zoomIn()) { renderView(); } } void nmWxVTKRenderContainerWidget::zoomOut() { - if(m_pCameraController != NULL && m_pCameraController->zoomOut()) { + if(m_pCameraController != nullptr && m_pCameraController->zoomOut()) { renderView(); } } void nmWxVTKRenderContainerWidget::fitView() { - if(m_pCameraController != NULL && m_pCameraController->fitView()) { + if(m_pCameraController != nullptr && m_pCameraController->fitView()) { renderView(); } } @@ -302,35 +326,35 @@ void nmWxVTKRenderContainerWidget::fitView() void nmWxVTKRenderContainerWidget::resetCamera() { // 控制器用返回值表示相机是否确实改变,成功时只提交一次渲染。 - if(m_pCameraController != NULL && m_pCameraController->resetCamera()) { + if(m_pCameraController != nullptr && m_pCameraController->resetCamera()) { renderView(); } } void nmWxVTKRenderContainerWidget::setTopView() { - if(m_pCameraController != NULL && m_pCameraController->setTopView()) { + if(m_pCameraController != nullptr && m_pCameraController->setTopView()) { renderView(); } } void nmWxVTKRenderContainerWidget::setFrontView() { - if(m_pCameraController != NULL && m_pCameraController->setFrontView()) { + if(m_pCameraController != nullptr && m_pCameraController->setFrontView()) { renderView(); } } void nmWxVTKRenderContainerWidget::setRightView() { - if(m_pCameraController != NULL && m_pCameraController->setRightView()) { + if(m_pCameraController != nullptr && m_pCameraController->setRightView()) { renderView(); } } void nmWxVTKRenderContainerWidget::setIsometricView() { - if(m_pCameraController != NULL && + if(m_pCameraController != nullptr && m_pCameraController->setIsometricView()) { renderView(); } @@ -341,7 +365,7 @@ void nmWxVTKRenderContainerWidget::setRotationCenter( double dY, double dZ) { - if(m_pCameraController != NULL && + if(m_pCameraController != nullptr && m_pCameraController->setRotationCenter(dX, dY, dZ)) { renderView(); } @@ -349,7 +373,7 @@ void nmWxVTKRenderContainerWidget::setRotationCenter( void nmWxVTKRenderContainerWidget::resetRotationCenter() { - if(m_pCameraController != NULL && + if(m_pCameraController != nullptr && m_pCameraController->resetRotationCenter()) { renderView(); } @@ -359,13 +383,13 @@ bool nmWxVTKRenderContainerWidget::eventFilter( QObject* pObject, QEvent* pEvent) { - if(pObject == m_pVtkWidget && pEvent != NULL && + if(pObject == m_pVtkWidget && pEvent != nullptr && pEvent->type() == QEvent::MouseButtonPress) { QMouseEvent* pMouseEvent = static_cast(pEvent); if(pMouseEvent->button() == Qt::RightButton) { // 菜单引用命令控制器长期持有的 QAction,不在每次右键时重复创建。 QMenu oMenu(this); - if(m_pViewCommandController != NULL) { + if(m_pViewCommandController != nullptr) { m_pViewCommandController->populateContextMenu(&oMenu); } if(!oMenu.isEmpty()) { @@ -381,7 +405,7 @@ bool nmWxVTKRenderContainerWidget::eventFilter( void nmWxVTKRenderContainerWidget::saveImage() { - if(m_pImageExporter == NULL) { + if(m_pImageExporter == nullptr) { return; } // 实际编码格式由 QImage 按调用方选择的扩展名决定。 @@ -399,7 +423,7 @@ void nmWxVTKRenderContainerWidget::saveImage() void nmWxVTKRenderContainerWidget::copyImage() { - if(m_pImageExporter != NULL && + if(m_pImageExporter != nullptr && !m_pImageExporter->copyImageToClipboard()) { QMessageBox::warning(this, tr("Copy Failed"), @@ -409,14 +433,14 @@ void nmWxVTKRenderContainerWidget::copyImage() void nmWxVTKRenderContainerWidget::printImage() { - if(m_pImageExporter != NULL) { + if(m_pImageExporter != nullptr) { m_pImageExporter->printImage(this); } } void nmWxVTKRenderContainerWidget::printPreview() { - if(m_pImageExporter != NULL) { + if(m_pImageExporter != nullptr) { m_pImageExporter->printPreview(this); } } @@ -426,8 +450,8 @@ void nmWxVTKRenderContainerWidget::showMessageState( const QString& sMessage) { Q_ASSERT(isGuiThread()); - if(!isGuiThread() || m_pStateStack == NULL || - m_pStatePage == NULL || m_pStateLabel == NULL) { + if(!isGuiThread() || m_pStateStack == nullptr || + m_pStatePage == nullptr || m_pStateLabel == nullptr) { return; } @@ -439,14 +463,17 @@ void nmWxVTKRenderContainerWidget::showMessageState( } m_pStateLabel->setText(sMessage); m_pStateStack->setCurrentWidget(m_pStatePage); - if(m_pViewCommandController != NULL) { + if(m_pViewCommandController != nullptr) { m_pViewCommandController->setViewAvailable(false); } + if(m_pOrientationMarkerController != nullptr) { + m_pOrientationMarkerController->setViewAvailable(false); + } } bool nmWxVTKRenderContainerWidget::isGuiThread() const { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } diff --git a/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp b/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp index ea49800..facaadc 100644 --- a/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp +++ b/Src/nmNum/nmSubWnd/nmSubWndGrid.cpp @@ -61,7 +61,7 @@ nmSubWndGrid::nmSubWndGrid(QWidget *parent, bool bGeneratePebiGrid, nmDataAnalyzeManager* pDataManager) : iSubWndBaseFit(parent, sExt), - m_mainLayout(nullptr), + m_pMainLayout(nullptr), m_pGridView(nullptr), m_pDebounceTimer(nullptr), m_pDataManager(nullptr), @@ -116,7 +116,7 @@ void nmSubWndGrid::setDataManager(nmDataAnalyzeManager* pDataManager) } // 构造阶段保留对话框传入的控制参数;窗口创建完成后的分析切换使用新分析自己的值。 - if(m_mainLayout != nullptr && pDataManager != nullptr) { + if(m_pMainLayout != nullptr && pDataManager != nullptr) { m_dPebiGridControl = pDataManager->getPebiGridControl(); } @@ -126,7 +126,7 @@ void nmSubWndGrid::setDataManager(nmDataAnalyzeManager* pDataManager) // 第二步:旧 VTK 页不能作为新分析的失败回退页,否则会继续显示上一分析的网格。 clearGridResultView(); - if(m_mainLayout == nullptr) { + if(m_pMainLayout == nullptr) { return; } @@ -157,7 +157,7 @@ void nmSubWndGrid::configWnd(QString sPrevInfo) { iSubWndBaseFit::configWnd(sPrevInfo); - if(NULL != m_pMainWindow) { + if(nullptr != m_pMainWindow) { disconnect(this, SIGNAL(sigAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)), \ m_pMainWindow, SLOT(slotAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea))); connect(this, SIGNAL(sigAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)), \ @@ -214,16 +214,16 @@ void nmSubWndGrid::initUI() setCentralWidget(mainWidget); - // m_mainLayout 应该直接是 mainWidget 的布局 - m_mainLayout = qobject_cast(mainWidget->layout()); + // m_pMainLayout 应该直接是 mainWidget 的布局 + m_pMainLayout = qobject_cast(mainWidget->layout()); // 通用渲染容器随窗口创建,但没有有效数据时不会创建业务 Mapper 或 Actor。 // 因此空数据、加载和失败都能复用同一状态页,不会落回黑色原生窗口。 m_pGridView = new nmWxPebiGridViewWidget(mainWidget); m_pGridView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_mainLayout->addWidget(m_pGridView); - m_mainLayout->setCurrentWidget(m_pGridView); + m_pMainLayout->addWidget(m_pGridView); + m_pMainLayout->setCurrentWidget(m_pGridView); // 新建成果启动后台划分;加载成果只在已有提交网格时绑定业务图层。 if(m_bGeneratePebiGrid) { @@ -396,18 +396,18 @@ void nmSubWndGrid::onPebiGridTaskFinished() void nmSubWndGrid::showGridLoading() { - if(m_mainLayout == nullptr || m_pGridView == nullptr) { + if(m_pMainLayout == nullptr || m_pGridView == nullptr) { return; } // 已有成功视图时只切换其内部状态页,网格、Scene、Renderer 和相机均保留。 - m_mainLayout->setCurrentWidget(m_pGridView); + m_pMainLayout->setCurrentWidget(m_pGridView); m_pGridView->showLoading(); } void nmSubWndGrid::showGridResult() { - if(m_mainLayout == nullptr || m_pGridView == nullptr) { + if(m_pMainLayout == nullptr || m_pGridView == nullptr) { return; } if(m_pDataManager.isNull()) { @@ -415,18 +415,18 @@ void nmSubWndGrid::showGridResult() return; } - // 网格和井值只在 GUI 线程构建为独立 ViewData;失败时不覆盖已有成功画面。 + // 网格预览数据只在 GUI 线程构建为独立 ViewData;失败时不覆盖已有成功画面。 nmPebiGridViewData oViewData; QString sError; if(!nmPebiGridViewDataBuilder::build( m_pDataManager.data(), &oViewData, &sError)) { - m_mainLayout->setCurrentWidget(m_pGridView); + m_pMainLayout->setCurrentWidget(m_pGridView); m_pGridView->showFailure(sError); return; } // 业务控件在窗口生命周期内只创建一次,后续提交只替换 MeshLayer 输入。 - m_mainLayout->setCurrentWidget(m_pGridView); + m_pMainLayout->setCurrentWidget(m_pGridView); if(!m_pGridView->setViewData(oViewData, &sError)) { m_pGridView->showFailure(sError); } @@ -444,13 +444,13 @@ void nmSubWndGrid::clearGridResultView() void nmSubWndGrid::showGridFailure() { - if(m_mainLayout == nullptr || m_pGridView == nullptr) { + if(m_pMainLayout == nullptr || m_pGridView == nullptr) { return; } // 更新失败但旧网格仍可显示时保留旧成果;首次生成失败时在正常背景上给出 // 明确状态,避免用户把空白或黑屏误认为程序仍在计算。 - m_mainLayout->setCurrentWidget(m_pGridView); + m_pMainLayout->setCurrentWidget(m_pGridView); if(m_pGridView->hasViewData()) { m_pGridView->showFailure(tr( "Grid generation failed. Current view is the last successful grid.")); diff --git a/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp b/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp index ae688e2..e83ed20 100644 --- a/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiGridSceneController.cpp @@ -27,7 +27,7 @@ QString controllerText(const char* pText) bool getFiniteGridBounds(vtkUnstructuredGrid* pGrid, double dBounds[6]) { - if(pGrid == NULL || dBounds == NULL) { + if(pGrid == nullptr || dBounds == nullptr) { return false; } pGrid->GetBounds(dBounds); @@ -52,9 +52,9 @@ public: explicit nmPebiGridSceneControllerPrivate( nmWxVTKRenderContainerWidget* pRenderContainer) : m_pContainer(pRenderContainer), - m_pMeshLayer(NULL), - m_pScalarBarLayer(NULL), - m_pBoundsGridLayer(NULL), + m_pMeshLayer(nullptr), + m_pScalarBarLayer(nullptr), + m_pBoundsGridLayer(nullptr), m_bGridLinesVisible(true), m_bScalarBarVisible(true), m_bBoundsGridVisible(false), @@ -65,15 +65,15 @@ public: bool ensureBaseLayers() { - nmVTKScene* pScene = m_pContainer != NULL - ? m_pContainer->getScene() : NULL; - vtkRenderer* pRenderer = m_pContainer != NULL - ? m_pContainer->getRenderer() : NULL; - if(pScene == NULL || pRenderer == NULL) { + nmVTKScene* pScene = m_pContainer != nullptr + ? m_pContainer->getScene() : nullptr; + vtkRenderer* pRenderer = m_pContainer != nullptr + ? m_pContainer->getRenderer() : nullptr; + if(pScene == nullptr || pRenderer == nullptr) { return false; } - if(m_pMeshLayer == NULL) { + if(m_pMeshLayer == nullptr) { nmVTKMeshLayer* pLayer = new nmVTKMeshLayer("pebi.grid.mesh"); pLayer->setVisible(false); @@ -89,7 +89,7 @@ public: 0.0, 0.0, 0.0); } - if(m_pBoundsGridLayer == NULL) { + if(m_pBoundsGridLayer == nullptr) { nmVTKBoundsGridLayer* pLayer = new nmVTKBoundsGridLayer("pebi.grid.bounds_grid"); pLayer->setMode(nmVTKBoundsGridLayer::Mode_PlanarXY); @@ -106,12 +106,12 @@ public: bool ensureScalarBarLayer() { - if(m_pScalarBarLayer != NULL) { + if(m_pScalarBarLayer != nullptr) { return true; } - nmVTKScene* pScene = m_pContainer != NULL - ? m_pContainer->getScene() : NULL; - if(pScene == NULL || m_pMeshLayer == NULL) { + nmVTKScene* pScene = m_pContainer != nullptr + ? m_pContainer->getScene() : nullptr; + if(pScene == nullptr || m_pMeshLayer == nullptr) { return false; } @@ -132,14 +132,14 @@ public: bool applyProperty(const QString& sPropertyName) { - if(m_pMeshLayer == NULL) { + if(m_pMeshLayer == nullptr) { return false; } if(sPropertyName.isEmpty()) { m_sPropertyName.clear(); m_pMeshLayer->setScalarVisibility(false); - if(m_pScalarBarLayer != NULL) { + if(m_pScalarBarLayer != nullptr) { m_pScalarBarLayer->setVisible(false); } return true; @@ -151,7 +151,7 @@ public: // 无效属性不能沿用上一网格的标量着色或色标范围。 m_sPropertyName.clear(); m_pMeshLayer->setScalarVisibility(false); - if(m_pScalarBarLayer != NULL) { + if(m_pScalarBarLayer != nullptr) { m_pScalarBarLayer->setVisible(false); } return false; @@ -175,8 +175,8 @@ public: const QString& sRequestedProperty, const double dBounds[6]) { - if(m_pMeshLayer == NULL || m_pBoundsGridLayer == NULL || - dBounds == NULL) { + if(m_pMeshLayer == nullptr || m_pBoundsGridLayer == nullptr || + dBounds == nullptr) { return false; } @@ -192,7 +192,7 @@ public: if(!m_pBoundsGridLayer->setBounds( dBounds[0], dBounds[1], dBounds[2], dBounds[3], dBounds[4], dBounds[5])) { - m_pMeshLayer->setDataSet(NULL); + m_pMeshLayer->setDataSet(nullptr); m_pMeshLayer->setVisible(false); m_oViewData.clear(); return false; @@ -208,15 +208,15 @@ public: void releaseGridData() { // 先断开 Mapper 对旧网格的引用,再释放 ViewData 的共享引用。 - if(m_pMeshLayer != NULL) { + if(m_pMeshLayer != nullptr) { m_pMeshLayer->setScalarVisibility(false); - m_pMeshLayer->setDataSet(NULL); + m_pMeshLayer->setDataSet(nullptr); m_pMeshLayer->setVisible(false); } - if(m_pScalarBarLayer != NULL) { + if(m_pScalarBarLayer != nullptr) { m_pScalarBarLayer->setVisible(false); } - if(m_pBoundsGridLayer != NULL) { + if(m_pBoundsGridLayer != nullptr) { m_pBoundsGridLayer->setVisible(false); } m_oViewData.clear(); @@ -246,15 +246,15 @@ nmPebiGridSceneController::nmPebiGridSceneController( nmPebiGridSceneController::~nmPebiGridSceneController() { - if(m_pPrivate != NULL) { + if(m_pPrivate != nullptr) { // Layer 已归 Scene 所有;这里只解除数据和非所有权指针。 m_pPrivate->releaseGridData(); - m_pPrivate->m_pContainer = NULL; - m_pPrivate->m_pMeshLayer = NULL; - m_pPrivate->m_pScalarBarLayer = NULL; - m_pPrivate->m_pBoundsGridLayer = NULL; + m_pPrivate->m_pContainer = nullptr; + m_pPrivate->m_pMeshLayer = nullptr; + m_pPrivate->m_pScalarBarLayer = nullptr; + m_pPrivate->m_pBoundsGridLayer = nullptr; delete m_pPrivate; - m_pPrivate = NULL; + m_pPrivate = nullptr; } } @@ -262,12 +262,12 @@ bool nmPebiGridSceneController::setViewData( const nmPebiGridViewData& oViewData, QString* pError) { - if(pError != NULL) { + if(pError != nullptr) { pError->clear(); } - if(m_pPrivate == NULL || m_pPrivate->m_pContainer == NULL || + if(m_pPrivate == nullptr || m_pPrivate->m_pContainer == nullptr || !oViewData.isValid()) { - if(pError != NULL) { + if(pError != nullptr) { *pError = controllerText("The grid preview data is invalid."); } return false; @@ -275,13 +275,13 @@ bool nmPebiGridSceneController::setViewData( double dBounds[6]; if(!getFiniteGridBounds(oViewData.getGrid(), dBounds)) { - if(pError != NULL) { + if(pError != nullptr) { *pError = controllerText("The grid bounds are invalid."); } return false; } if(!m_pPrivate->ensureBaseLayers()) { - if(pError != NULL) { + if(pError != nullptr) { *pError = controllerText("Unable to create the grid render layers."); } return false; @@ -315,7 +315,7 @@ bool nmPebiGridSceneController::setViewData( sPreviousProperty, dPreviousBounds); } - if(pError != NULL) { + if(pError != nullptr) { *pError = controllerText("Unable to bind the grid render data."); } return false; @@ -329,7 +329,7 @@ bool nmPebiGridSceneController::setViewData( void nmPebiGridSceneController::clear() { - if(m_pPrivate == NULL) { + if(m_pPrivate == nullptr) { return; } m_pPrivate->releaseGridData(); @@ -343,21 +343,21 @@ void nmPebiGridSceneController::clear() void nmPebiGridSceneController::setGridLinesVisible(bool bVisible) { - if(m_pPrivate == NULL) { + if(m_pPrivate == nullptr) { return; } m_pPrivate->m_bGridLinesVisible = bVisible; - if(m_pPrivate->m_pMeshLayer != NULL) { + if(m_pPrivate->m_pMeshLayer != nullptr) { m_pPrivate->m_pMeshLayer->setEdgeVisibility(bVisible); } - if(m_pPrivate->m_bHasData && m_pPrivate->m_pContainer != NULL) { + if(m_pPrivate->m_bHasData && m_pPrivate->m_pContainer != nullptr) { m_pPrivate->m_pContainer->renderView(); } } bool nmPebiGridSceneController::setProperty(const QString& sPropertyName) { - if(m_pPrivate == NULL || !m_pPrivate->m_bHasData) { + if(m_pPrivate == nullptr || !m_pPrivate->m_bHasData) { return false; } const bool bSucceeded = m_pPrivate->applyProperty(sPropertyName); @@ -365,7 +365,7 @@ bool nmPebiGridSceneController::setProperty(const QString& sPropertyName) m_pPrivate->m_bPropertySelectionExplicit = true; m_pPrivate->m_sRequestedPropertyName = bSucceeded ? sPropertyName : QString(); - if(m_pPrivate->m_pContainer != NULL) { + if(m_pPrivate->m_pContainer != nullptr) { m_pPrivate->m_pContainer->renderView(); } return bSucceeded; @@ -373,58 +373,58 @@ bool nmPebiGridSceneController::setProperty(const QString& sPropertyName) void nmPebiGridSceneController::setScalarBarVisible(bool bVisible) { - if(m_pPrivate == NULL) { + if(m_pPrivate == nullptr) { return; } // 无属性时只保存偏好;重新选择 Material 后按该偏好恢复色标。 m_pPrivate->m_bScalarBarVisible = bVisible; - if(m_pPrivate->m_pScalarBarLayer != NULL) { + if(m_pPrivate->m_pScalarBarLayer != nullptr) { m_pPrivate->m_pScalarBarLayer->setVisible( bVisible && m_pPrivate->m_bHasData && !m_pPrivate->m_sPropertyName.isEmpty()); } - if(m_pPrivate->m_bHasData && m_pPrivate->m_pContainer != NULL) { + if(m_pPrivate->m_bHasData && m_pPrivate->m_pContainer != nullptr) { m_pPrivate->m_pContainer->renderView(); } } void nmPebiGridSceneController::setBoundsGridVisible(bool bVisible) { - if(m_pPrivate == NULL) { + if(m_pPrivate == nullptr) { return; } m_pPrivate->m_bBoundsGridVisible = bVisible; - if(m_pPrivate->m_pBoundsGridLayer != NULL) { + if(m_pPrivate->m_pBoundsGridLayer != nullptr) { m_pPrivate->m_pBoundsGridLayer->setVisible( bVisible && m_pPrivate->m_bHasData); } - if(m_pPrivate->m_bHasData && m_pPrivate->m_pContainer != NULL) { + if(m_pPrivate->m_bHasData && m_pPrivate->m_pContainer != nullptr) { m_pPrivate->m_pContainer->renderView(); } } bool nmPebiGridSceneController::hasViewData() const { - return m_pPrivate != NULL && m_pPrivate->m_bHasData; + return m_pPrivate != nullptr && m_pPrivate->m_bHasData; } QString nmPebiGridSceneController::getProperty() const { - return m_pPrivate != NULL + return m_pPrivate != nullptr ? m_pPrivate->m_sPropertyName : QString(); } bool nmPebiGridSceneController::isGridLinesVisible() const { - return m_pPrivate != NULL && m_pPrivate->m_bGridLinesVisible; + return m_pPrivate != nullptr && m_pPrivate->m_bGridLinesVisible; } bool nmPebiGridSceneController::isScalarBarVisible() const { - return m_pPrivate != NULL && m_pPrivate->m_bScalarBarVisible; + return m_pPrivate != nullptr && m_pPrivate->m_bScalarBarVisible; } bool nmPebiGridSceneController::isBoundsGridVisible() const { - return m_pPrivate != NULL && m_pPrivate->m_bBoundsGridVisible; + return m_pPrivate != nullptr && m_pPrivate->m_bBoundsGridVisible; } diff --git a/Src/nmNum/nmSubWxs/nmPebiGridViewData.cpp b/Src/nmNum/nmSubWxs/nmPebiGridViewData.cpp index 2a31228..7eb2a69 100644 --- a/Src/nmNum/nmSubWxs/nmPebiGridViewData.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiGridViewData.cpp @@ -3,7 +3,7 @@ #include nmPebiGridViewData::nmPebiGridViewData() - : m_pGrid(NULL), + : m_pGrid(nullptr), m_eGridType(NM_Grid_UNKNWON), m_nGridInputRevision(0), m_nValidCellCount(0), @@ -14,7 +14,7 @@ nmPebiGridViewData::nmPebiGridViewData() void nmPebiGridViewData::clear() { // 只解除共享的 VTK 引用,不删除 DataManager 持有的实时网格。 - m_pGrid = NULL; + m_pGrid = nullptr; m_eGridType = NM_Grid_UNKNWON; m_nGridInputRevision = 0; m_nValidCellCount = 0; @@ -23,7 +23,7 @@ void nmPebiGridViewData::clear() bool nmPebiGridViewData::isValid() const { - return m_pGrid != NULL && + return m_pGrid != nullptr && m_pGrid->GetNumberOfPoints() > 0 && m_pGrid->GetNumberOfCells() > 0 && m_nValidCellCount > 0; diff --git a/Src/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.cpp b/Src/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.cpp index 2b6cae9..e004762 100644 --- a/Src/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiGridViewDataBuilder.cpp @@ -23,7 +23,7 @@ QString builderText(const char* pText) bool isBuilderGuiThread() { QCoreApplication* pApplication = QCoreApplication::instance(); - return pApplication == NULL || + return pApplication == nullptr || pApplication->thread() == QThread::currentThread(); } @@ -35,37 +35,37 @@ bool nmPebiGridViewDataBuilder::build( QString* pError) { Q_ASSERT(isBuilderGuiThread()); - if(pError != NULL) { + if(pError != nullptr) { pError->clear(); } if(!isBuilderGuiThread()) { - if(pError != NULL) { + if(pError != nullptr) { *pError = builderText( "Grid preview data must be built in the GUI thread."); } return false; } - if(pDataManager == NULL || pViewData == NULL) { - if(pError != NULL) { + if(pDataManager == nullptr || pViewData == nullptr) { + if(pError != nullptr) { *pError = builderText("The grid data source is unavailable."); } return false; } if(pDataManager->thread() != QThread::currentThread()) { - if(pError != NULL) { + if(pError != nullptr) { *pError = builderText( "Grid preview data must be built in the GUI thread."); } return false; } if(!pDataManager->isPebiGridValid()) { - if(pError != NULL) { + if(pError != nullptr) { *pError = builderText("The PEBI grid has not been committed."); } return false; } if(pDataManager->getGridType() != NM_Grid_PEBI) { - if(pError != NULL) { + if(pError != nullptr) { *pError = builderText("The committed grid is not a PEBI grid."); } return false; @@ -73,9 +73,9 @@ bool nmPebiGridViewDataBuilder::build( vtkSmartPointer pGrid = pDataManager->getUnstructuredGrid(); - if(pGrid == NULL || pGrid->GetNumberOfPoints() <= 0 || + if(pGrid == nullptr || pGrid->GetNumberOfPoints() <= 0 || pGrid->GetNumberOfCells() <= 0) { - if(pError != NULL) { + if(pError != nullptr) { *pError = builderText("The committed PEBI grid is empty."); } return false; @@ -83,8 +83,8 @@ bool nmPebiGridViewDataBuilder::build( const nmDataNumericalAnalysisCase* pAnalysisCase = pDataManager->getNumericalAnalysisCase(); - if(pAnalysisCase == NULL) { - if(pError != NULL) { + if(pAnalysisCase == nullptr) { + if(pError != nullptr) { *pError = builderText("The grid version is unavailable."); } return false; @@ -100,9 +100,9 @@ bool nmPebiGridViewDataBuilder::build( // Material 只认可 CellData 中与 VTK 单元一一对应的数组。 vtkCellData* pCellData = pGrid->GetCellData(); - vtkDataArray* pMaterialArray = pCellData != NULL - ? pCellData->GetArray("Material") : NULL; - oCandidate.m_bHasMaterial = pMaterialArray != NULL && + vtkDataArray* pMaterialArray = pCellData != nullptr + ? pCellData->GetArray("Material") : nullptr; + oCandidate.m_bHasMaterial = pMaterialArray != nullptr && pMaterialArray->GetNumberOfTuples() == pGrid->GetNumberOfCells(); *pViewData = oCandidate; diff --git a/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp b/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp index 149f52f..d70516c 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiGridViewWidget.cpp @@ -31,15 +31,15 @@ QString gridViewIconPath(const QString& sFileName) nmWxPebiGridViewWidget::nmWxPebiGridViewWidget(QWidget* pParent) : QWidget(pParent), - m_pRenderContainer(NULL), - m_pSceneController(NULL), - m_pToolBar(NULL), - m_pGridLinesAction(NULL), - m_pScalarBarAction(NULL), - m_pBoundsGridAction(NULL), - m_pPropertyComboBox(NULL), - m_pGridInfoLabel(NULL), - m_pStatusLabel(NULL), + m_pRenderContainer(nullptr), + m_pSceneController(nullptr), + m_pToolBar(nullptr), + m_pGridLinesAction(nullptr), + m_pScalarBarAction(nullptr), + m_pBoundsGridAction(nullptr), + m_pPropertyComboBox(nullptr), + m_pGridInfoLabel(nullptr), + m_pStatusLabel(nullptr), m_bHasViewData(false) { createUi(); @@ -55,7 +55,7 @@ nmWxPebiGridViewWidget::~nmWxPebiGridViewWidget() { // 控制器先解除 Mapper 输入;Scene 和 Layer 随后由容器析构统一清理。 delete m_pSceneController; - m_pSceneController = NULL; + m_pSceneController = nullptr; } void nmWxPebiGridViewWidget::createUi() @@ -111,7 +111,7 @@ void nmWxPebiGridViewWidget::createUi() m_pBoundsGridAction->setToolTip(tr("Coordinate Grid")); m_pBoundsGridAction->setCheckable(true); - if(pCommandController != NULL) { + if(pCommandController != nullptr) { // 网格视图按自身工作流排序,但仍引用命令控制器持有的公共 QAction。 QAction* pZoomOutAction = pCommandController->getAction( nmVTKViewCommandController::ViewCommand_ZoomOut); @@ -123,16 +123,16 @@ void nmWxPebiGridViewWidget::createUi() nmVTKViewCommandController::ViewCommand_Top); QAction* pCopyAction = pCommandController->getAction( nmVTKViewCommandController::ViewCommand_CopyImage); - if(pZoomOutAction != NULL) { + if(pZoomOutAction != nullptr) { m_pToolBar->addAction(pZoomOutAction); } - if(pFitAction != NULL) { + if(pFitAction != nullptr) { m_pToolBar->addAction(pFitAction); } - if(pZoomInAction != NULL) { + if(pZoomInAction != nullptr) { m_pToolBar->addAction(pZoomInAction); } - if(pTopAction != NULL) { + if(pTopAction != nullptr) { m_pToolBar->addAction(pTopAction); } m_pToolBar->addSeparator(); @@ -140,7 +140,7 @@ void nmWxPebiGridViewWidget::createUi() m_pToolBar->addAction(m_pScalarBarAction); m_pToolBar->addAction(m_pBoundsGridAction); m_pToolBar->addSeparator(); - if(pCopyAction != NULL) { + if(pCopyAction != nullptr) { m_pToolBar->addAction(pCopyAction); } } else { @@ -198,8 +198,8 @@ bool nmWxPebiGridViewWidget::setViewData( const nmPebiGridViewData& oViewData, QString* pError) { - if(m_pSceneController == NULL || !oViewData.isValid()) { - if(pError != NULL) { + if(m_pSceneController == nullptr || !oViewData.isValid()) { + if(pError != nullptr) { *pError = tr("The grid preview data is invalid."); } return false; @@ -264,7 +264,7 @@ void nmWxPebiGridViewWidget::showFailure(const QString& sMessage) void nmWxPebiGridViewWidget::clearView() { - if(m_pSceneController != NULL) { + if(m_pSceneController != nullptr) { m_pSceneController->clear(); } m_bHasViewData = false; @@ -304,13 +304,13 @@ void nmWxPebiGridViewWidget::setControlsEnabled(bool bEnabled) m_pGridLinesAction->setEnabled(bEnabled); m_pBoundsGridAction->setEnabled(bEnabled); m_pScalarBarAction->setEnabled( - bEnabled && m_pSceneController != NULL && + bEnabled && m_pSceneController != nullptr && !m_pSceneController->getProperty().isEmpty()); } void nmWxPebiGridViewWidget::updateScalarBarActionState() { - if(m_pSceneController == NULL) { + if(m_pSceneController == nullptr) { return; } const bool bBlocked = m_pScalarBarAction->blockSignals(true); @@ -330,7 +330,7 @@ QString nmWxPebiGridViewWidget::gridTypeText(int nGridType) const void nmWxPebiGridViewWidget::onPropertyChanged(int nIndex) { - if(!m_bHasViewData || nIndex < 0 || m_pSceneController == NULL) { + if(!m_bHasViewData || nIndex < 0 || m_pSceneController == nullptr) { return; } const QString sPropertyName = @@ -345,28 +345,28 @@ void nmWxPebiGridViewWidget::onPropertyChanged(int nIndex) void nmWxPebiGridViewWidget::onGridLinesToggled(bool bVisible) { - if(m_bHasViewData && m_pSceneController != NULL) { + if(m_bHasViewData && m_pSceneController != nullptr) { m_pSceneController->setGridLinesVisible(bVisible); } } void nmWxPebiGridViewWidget::onScalarBarToggled(bool bVisible) { - if(m_bHasViewData && m_pSceneController != NULL) { + if(m_bHasViewData && m_pSceneController != nullptr) { m_pSceneController->setScalarBarVisible(bVisible); } } void nmWxPebiGridViewWidget::onBoundsGridToggled(bool bVisible) { - if(m_bHasViewData && m_pSceneController != NULL) { + if(m_bHasViewData && m_pSceneController != nullptr) { m_pSceneController->setBoundsGridVisible(bVisible); } } void nmWxPebiGridViewWidget::appendContextMenuActions(QMenu* pMenu) { - if(pMenu == NULL) { + if(pMenu == nullptr) { return; } // 右键菜单与工具栏引用同三个业务 QAction,勾选状态不会发生分叉。 diff --git a/Src4/nmNum/nmRender/nmRender.pro b/Src4/nmNum/nmRender/nmRender.pro index babb844..ca70498 100644 --- a/Src4/nmNum/nmRender/nmRender.pro +++ b/Src4/nmNum/nmRender/nmRender.pro @@ -1,4 +1,4 @@ -QT += core gui +QT += core gui # Qt 5 将原 QtGui 中的窗口部件和打印类拆分为独立模块。 greaterThan(QT_MAJOR_VERSION, 4) : QT += widgets printsupport @@ -19,6 +19,7 @@ SOURCES += $${wtSrc}/nmNum/nmRender/nmVTKCameraController.cpp \ $${wtSrc}/nmNum/nmRender/nmVTKBoundsGridLayer.cpp \ $${wtSrc}/nmNum/nmRender/nmVTKImageExporter.cpp \ $${wtSrc}/nmNum/nmRender/nmVTKInteractionManager.cpp \ + $${wtSrc}/nmNum/nmRender/nmVTKOrientationMarkerController.cpp \ $${wtSrc}/nmNum/nmRender/nmVTKMeshLayer.cpp \ $${wtSrc}/nmNum/nmRender/nmVTKRenderLayer.cpp \ $${wtSrc}/nmNum/nmRender/nmVTKScalarBarLayer.cpp \ @@ -31,6 +32,7 @@ HEADERS += $${wtInclude}/nmNum/nmRender/nmRender_global.h \ $${wtInclude}/nmNum/nmRender/nmVTKBoundsGridLayer.h \ $${wtInclude}/nmNum/nmRender/nmVTKImageExporter.h \ $${wtInclude}/nmNum/nmRender/nmVTKInteractionManager.h \ + $${wtInclude}/nmNum/nmRender/nmVTKOrientationMarkerController.h \ $${wtInclude}/nmNum/nmRender/nmVTKMeshLayer.h \ $${wtInclude}/nmNum/nmRender/nmVTKRenderLayer.h \ $${wtInclude}/nmNum/nmRender/nmVTKScalarBarLayer.h \