From 01ccc2b88c6cc23830646daa92ad661062cce18e Mon Sep 17 00:00:00 2001 From: lh <2334563547@qq.com> Date: Fri, 18 Sep 2026 11:27:09 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BC=98=E5=8C=96=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E8=A7=86=E5=9B=BE=E4=BA=95=E5=90=8D=E4=B8=8E=E5=BC=95=E7=BA=BF?= =?UTF-8?q?=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除独立井位标记及其显示开关 - 使用逐井文字 Actor 和引线 Actor 锚定真实井位 - 井名按钮统一控制文字与引线显隐 - 调整字体、屏幕偏移、阴影和引线样式 - 将井名与引线置于前景层,改善密集网格下的可读性 - 保持井标注候选构造和事务提交机制 - 清理井位标记翻译并更新中文语言包 --- Bin/Config/Lang/cn/nmNum_cn.qm | Bin 147692 -> 147619 bytes Bin/Config/Lang/cn/nmNum_cn.ts | 1 - .../nmSubWxs/nmPebiResultSceneController.h | 8 +- .../nmPebiResultWellAnnotationLayer.h | 18 +- .../nmNum/nmSubWxs/nmWxPebiResultViewWidget.h | 5 +- .../nmSubWxs/nmPebiResultSceneController.cpp | 28 --- .../nmPebiResultWellAnnotationLayer.cpp | 217 ++++++++---------- .../nmSubWxs/nmWxPebiResultViewWidget.cpp | 24 +- 8 files changed, 113 insertions(+), 188 deletions(-) diff --git a/Bin/Config/Lang/cn/nmNum_cn.qm b/Bin/Config/Lang/cn/nmNum_cn.qm index 2413b6b4a989d1abe29b924d1e93872b3e3fedeb..127e75bc8a376bcb6cbecdf162b7f09ce529fd31 100644 GIT binary patch delta 3183 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 delta 3282 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 diff --git a/Bin/Config/Lang/cn/nmNum_cn.ts b/Bin/Config/Lang/cn/nmNum_cn.ts index 442701b8..a95c6a41 100644 --- a/Bin/Config/Lang/cn/nmNum_cn.ts +++ b/Bin/Config/Lang/cn/nmNum_cn.ts @@ -2888,7 +2888,6 @@ Reason: %1 No result data.暂无结果数据。 Color Scale色标 Scale Grid比例网格 - Well Markers井位标记 Well Names井名 Unable to display the latest result.无法显示最新结果。 Unable to display the latest result: %1无法显示最新结果:%1 diff --git a/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h b/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h index 9b8b0c90..44514aa0 100644 --- a/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h +++ b/Include/nmNum/nmSubWxs/nmPebiResultSceneController.h @@ -69,9 +69,7 @@ public: void setScalarBarVisible(bool bVisible); /** @brief 设置平面比例网格显隐;偏好跨快照保留。 */ void setScaleGridVisible(bool bVisible); - /** @brief 设置二维井位标记显隐;偏好跨快照保留。 */ - void setWellMarkersVisible(bool bVisible); - /** @brief 设置二维井名显隐;偏好跨快照保留。 */ + /** @brief 设置二维井名及其引线显隐;偏好跨快照保留。 */ void setWellNamesVisible(bool bVisible); /** @brief 返回当前是否持有可用快照且稳定结果图层仍完整。 */ @@ -111,9 +109,7 @@ public: bool isScalarBarVisible() const; /** @brief 返回比例网格显示偏好,不要求当前存在快照。 */ bool isScaleGridVisible() const; - /** @brief 返回二维井位标记显示偏好。 */ - bool areWellMarkersVisible() const; - /** @brief 返回二维井名显示偏好。 */ + /** @brief 返回二维井名及其引线显示偏好。 */ bool areWellNamesVisible() const; private: diff --git a/Include/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.h b/Include/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.h index 395d4d1e..6697b229 100644 --- a/Include/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.h +++ b/Include/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.h @@ -12,7 +12,7 @@ class nmPebiResultSnapshot; class vtkPropAssembly; /** - * @brief 显示快照中全部二维井位和井名的业务图层。 + * @brief 显示快照中全部二维井名和引线的业务图层。 * * 图层只读取快照冻结的 XY 和井名,不访问 DataManager,不伪造井深或轨迹。 * 稳定根 Assembly 始终挂在 Scene 中;新快照通过候选子 Assembly 无失败交换。 @@ -27,7 +27,7 @@ public: virtual ~nmPebiResultWellAnnotationLayer(); /** - * @brief 在未挂载候选对象中构造快照全部井位和井名。 + * @brief 在未挂载候选对象中构造快照全部井名和二维引线。 * @note 失败时活动子 Assembly 完全不变;再次准备会丢弃旧候选。 */ bool prepareCandidate( @@ -45,11 +45,8 @@ public: /** @brief 返回活动快照是否已有完整井标注子树。 */ bool hasActiveAnnotations() const; - /** @brief 独立设置约 9px 的二维井位标记显隐。 */ - void setWellMarkersVisible(bool bVisible); - /** @brief 独立设置约 12px 的二维井名显隐。 */ + /** @brief 统一设置二维井名及其引线显隐。 */ void setWellNamesVisible(bool bVisible); - bool areWellMarkersVisible() const; bool areWellNamesVisible() const; private: @@ -57,13 +54,10 @@ private: vtkSmartPointer m_pRootAssembly; ///< Scene 挂载的稳定根。 vtkSmartPointer m_pActiveSnapshotAssembly; ///< 当前快照子树。 - vtkSmartPointer m_pActiveMarkerGroup; ///< 当前井位组。 - vtkSmartPointer m_pActiveNameGroup; ///< 当前井名组。 + vtkSmartPointer m_pActiveAnnotationGroup; ///< 当前井名与引线组。 vtkSmartPointer m_pCandidateSnapshotAssembly; ///< 待提交子树。 - vtkSmartPointer m_pCandidateMarkerGroup; ///< 候选井位组。 - vtkSmartPointer m_pCandidateNameGroup; ///< 候选井名组。 - bool m_bWellMarkersVisible; ///< 跨快照保留的井位显隐偏好。 - bool m_bWellNamesVisible; ///< 跨快照保留的井名显隐偏好。 + vtkSmartPointer m_pCandidateAnnotationGroup; ///< 候选井名与引线组。 + bool m_bWellNamesVisible; ///< 跨快照保留的文字与引线显隐偏好。 }; #endif // NMPEBIRESULTWELLANNOTATIONLAYER_H diff --git a/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h b/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h index 9f91683a..7a13f51a 100644 --- a/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h +++ b/Include/nmNum/nmSubWxs/nmWxPebiResultViewWidget.h @@ -67,8 +67,6 @@ private slots: void onScalarBarToggled(bool bVisible); /** @brief 切换比例网格显隐。 */ void onScaleGridToggled(bool bVisible); - /** @brief 切换二维井位标记显隐。 */ - void onWellMarkersToggled(bool bVisible); /** @brief 切换二维井名显隐。 */ void onWellNamesToggled(bool bVisible); @@ -86,7 +84,7 @@ private: const QSharedPointer& pSnapshot, const QString& sSnapshotId, bool bCurrent); - /** @brief 从 SceneController 镜像四个业务 QAction 的勾选和可用状态。 */ + /** @brief 从 SceneController 镜像三个业务 QAction 的勾选和可用状态。 */ void synchronizeBusinessActions(); /** @brief 根据“绑定失败、过期、操作错误”的固定优先级刷新提示栏。 */ void refreshStatusBar(); @@ -102,7 +100,6 @@ private: QAction* m_pScalarBarAction; ///< 色标显隐动作。 QAction* m_pScaleGridAction; ///< 比例网格显隐动作。 - QAction* m_pWellMarkersAction; ///< 二维井位标记显隐动作。 QAction* m_pWellNamesAction; ///< 二维井名显隐动作。 /** @brief Manager 最近一次通知后观察到的快照强引用。 */ diff --git a/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp b/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp index ce449b68..4ae6c258 100644 --- a/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiResultSceneController.cpp @@ -403,7 +403,6 @@ public: m_bHasBounds(false), m_bScalarBarVisible(true), m_bScaleGridVisible(false), - m_bWellMarkersVisible(true), m_bWellNamesVisible(true) { m_dBusinessRange[0] = 0.0; @@ -598,7 +597,6 @@ public: new nmPebiResultWellAnnotationLayer( QString::fromLatin1(RESULT_WELLS_LAYER_ID)); pLayer->setVisible(false); - pLayer->setWellMarkersVisible(m_bWellMarkersVisible); pLayer->setWellNamesVisible(m_bWellNamesVisible); if(!pScene->addLayer(pLayer)) { delete pLayer; @@ -723,7 +721,6 @@ public: bHasData && m_bScaleGridVisible); } if(m_pWellLayer != nullptr) { - m_pWellLayer->setWellMarkersVisible(m_bWellMarkersVisible); m_pWellLayer->setWellNamesVisible(m_bWellNamesVisible); m_pWellLayer->setVisible(bHasData); } @@ -883,7 +880,6 @@ public: bool m_bHasBounds; bool m_bScalarBarVisible; bool m_bScaleGridVisible; - bool m_bWellMarkersVisible; bool m_bWellNamesVisible; }; @@ -1348,25 +1344,6 @@ void nmPebiResultSceneController::setScaleGridVisible(bool bVisible) } } -void nmPebiResultSceneController::setWellMarkersVisible(bool bVisible) -{ - Q_ASSERT(isResultSceneGuiThread()); - if(!isResultSceneGuiThread() || m_pPrivate == nullptr) { - return; - } - m_pPrivate->discardActiveDataIfLayersLost(); - if(m_pPrivate->m_bWellMarkersVisible == bVisible) { - return; - } - m_pPrivate->m_bWellMarkersVisible = bVisible; - if(m_pPrivate->m_pWellLayer != nullptr) { - m_pPrivate->m_pWellLayer->setWellMarkersVisible(bVisible); - } - if(hasSnapshot()) { - m_pPrivate->m_pContainer->renderView(); - } -} - void nmPebiResultSceneController::setWellNamesVisible(bool bVisible) { Q_ASSERT(isResultSceneGuiThread()); @@ -1506,11 +1483,6 @@ bool nmPebiResultSceneController::isScaleGridVisible() const return m_pPrivate != nullptr && m_pPrivate->m_bScaleGridVisible; } -bool nmPebiResultSceneController::areWellMarkersVisible() const -{ - return m_pPrivate != nullptr && m_pPrivate->m_bWellMarkersVisible; -} - bool nmPebiResultSceneController::areWellNamesVisible() const { return m_pPrivate != nullptr && m_pPrivate->m_bWellNamesVisible; diff --git a/Src/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.cpp b/Src/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.cpp index fec1d8d2..1ed074f8 100644 --- a/Src/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.cpp +++ b/Src/nmNum/nmSubWxs/nmPebiResultWellAnnotationLayer.cpp @@ -2,22 +2,18 @@ #include "nmPebiResultSnapshot.h" +#include #include #include #include #include -#include #include -#include +#include #include -#include -#include -#include -#include #include #include -#include +#include #include namespace { @@ -29,6 +25,17 @@ bool isWellAnnotationGuiThread() pApplication->thread() == QThread::currentThread(); } +// Saphir 风格标注使用固定像素偏移,缩放相机时文字和引线长度保持不变。 +const int WELL_NAME_FONT_SIZE = 16; +const int WELL_NAME_OFFSET_X = 18; +const int WELL_NAME_OFFSET_Y = 40; +const int WELL_LEADER_OFFSET_X = 14; +const int WELL_LEADER_OFFSET_Y = 36; + +const double WELL_LEADER_RED = 140.0 / 255.0; +const double WELL_LEADER_GREEN = 87.0 / 255.0; +const double WELL_LEADER_BLUE = 59.0 / 255.0; + } nmPebiResultWellAnnotationLayer::nmPebiResultWellAnnotationLayer( @@ -36,12 +43,9 @@ nmPebiResultWellAnnotationLayer::nmPebiResultWellAnnotationLayer( : nmVTKRenderLayer(sLayerId), m_pRootAssembly(vtkSmartPointer::New()), m_pActiveSnapshotAssembly(nullptr), - m_pActiveMarkerGroup(nullptr), - m_pActiveNameGroup(nullptr), + m_pActiveAnnotationGroup(nullptr), m_pCandidateSnapshotAssembly(nullptr), - m_pCandidateMarkerGroup(nullptr), - m_pCandidateNameGroup(nullptr), - m_bWellMarkersVisible(true), + m_pCandidateAnnotationGroup(nullptr), m_bWellNamesVisible(true) { Q_ASSERT(isWellAnnotationGuiThread()); @@ -67,16 +71,6 @@ bool nmPebiResultWellAnnotationLayer::prepareCandidate( return false; } - vtkSmartPointer pMarkerPoints = - vtkSmartPointer::New(); - vtkSmartPointer pMarkerVertices = - vtkSmartPointer::New(); - vtkSmartPointer pNamePoints = - vtkSmartPointer::New(); - vtkSmartPointer pWellNames = - vtkSmartPointer::New(); - pWellNames->SetName("WellName"); - QSet setWellIds; for(int nIndex = 0; nIndex < pSnapshot->getWellCount(); ++nIndex) { const nmPebiResultWellSnapshot* pWell = pSnapshot->getWellAt(nIndex); @@ -89,90 +83,103 @@ bool nmPebiResultWellAnnotationLayer::prepareCandidate( return false; } setWellIds.insert(pWell->m_sWellInstanceId); - - // 保持快照存储顺序;二维 Overlay 不向业务位置写入虚构 Z 值。 - const vtkIdType nPointId = pMarkerPoints->InsertNextPoint( - pWell->m_oLocation.x(), pWell->m_oLocation.y(), 0.0); - pMarkerVertices->InsertNextCell(1); - pMarkerVertices->InsertCellPoint(nPointId); - pNamePoints->InsertNextPoint( - pWell->m_oLocation.x(), pWell->m_oLocation.y(), 0.0); - const QByteArray aWellName = pWell->m_sWellName.toUtf8(); - pWellNames->InsertNextValue(aWellName.constData()); } vtkSmartPointer pSnapshotAssembly = vtkSmartPointer::New(); - vtkSmartPointer pMarkerGroup = - vtkSmartPointer::New(); - vtkSmartPointer pNameGroup = + vtkSmartPointer pAnnotationGroup = vtkSmartPointer::New(); if(pSnapshot->getWellCount() > 0) { - vtkSmartPointer pMarkerData = - vtkSmartPointer::New(); - pMarkerData->SetPoints(pMarkerPoints); - pMarkerData->SetVerts(pMarkerVertices); - - vtkSmartPointer pWorldCoordinate = - vtkSmartPointer::New(); - pWorldCoordinate->SetCoordinateSystemToWorld(); - vtkSmartPointer pMarkerMapper = - vtkSmartPointer::New(); - pMarkerMapper->SetInputData(pMarkerData); - pMarkerMapper->SetTransformCoordinate(pWorldCoordinate); - pMarkerMapper->ScalarVisibilityOff(); - - vtkSmartPointer pMarkerActor = - vtkSmartPointer::New(); - pMarkerActor->SetMapper(pMarkerMapper); - pMarkerActor->GetProperty()->SetColor(0.12, 0.12, 0.12); - pMarkerActor->GetProperty()->SetPointSize(9.0); - pMarkerGroup->AddPart(pMarkerActor); - - vtkSmartPointer pNameData = - vtkSmartPointer::New(); - pNameData->SetPoints(pNamePoints); - pNameData->GetPointData()->AddArray(pWellNames); - vtkSmartPointer pNameMapper = - vtkSmartPointer::New(); - pNameMapper->SetInputData(pNameData); - pNameMapper->SetLabelModeToLabelFieldData(); - pNameMapper->SetFieldDataName("WellName"); - pNameMapper->SetLabelFormat("%s"); - pNameMapper->GetLabelTextProperty()->SetFontSize(12); - pNameMapper->GetLabelTextProperty()->SetColor(0.10, 0.10, 0.10); - pNameMapper->GetLabelTextProperty()->BoldOff(); - pNameMapper->GetLabelTextProperty()->ItalicOff(); - pNameMapper->GetLabelTextProperty()->ShadowOff(); - pNameMapper->GetLabelTextProperty()->SetJustificationToLeft(); - pNameMapper->GetLabelTextProperty()->SetVerticalJustificationToBottom(); - - vtkSmartPointer pNameActor = - vtkSmartPointer::New(); - pNameActor->SetMapper(pNameMapper); - // Actor2D 的显示坐标偏移固定为像素,不随相机缩放改变。 - pNameActor->SetDisplayPosition(7, 6); - pNameGroup->AddPart(pNameActor); + for(int nIndex = 0; nIndex < pSnapshot->getWellCount(); ++nIndex) { + const nmPebiResultWellSnapshot* pWell = + pSnapshot->getWellAt(nIndex); + vtkSmartPointer pWorldAnchor = + vtkSmartPointer::New(); + // Z=0 仅表示冻结 XY 所在平面,不表示井深、井斜或井轨迹。 + pWorldAnchor->SetCoordinateSystemToWorld(); + pWorldAnchor->SetValue( + pWell->m_oLocation.x(), + pWell->m_oLocation.y(), 0.0); + + vtkSmartPointer pWellAnnotation = + vtkSmartPointer::New(); + vtkSmartPointer pLeader = + vtkSmartPointer::New(); + + // 引线两个端点都引用同一 World 锚点,只叠加固定 Display 像素偏移。 + vtkCoordinate* pStartCoordinate = + pLeader->GetPositionCoordinate(); + pStartCoordinate->SetCoordinateSystemToDisplay(); + pStartCoordinate->SetReferenceCoordinate(pWorldAnchor); + pStartCoordinate->SetValue(0.0, 0.0, 0.0); + vtkCoordinate* pEndCoordinate = + pLeader->GetPosition2Coordinate(); + pEndCoordinate->SetCoordinateSystemToDisplay(); + pEndCoordinate->SetReferenceCoordinate(pWorldAnchor); + pEndCoordinate->SetValue( + WELL_LEADER_OFFSET_X, WELL_LEADER_OFFSET_Y, 0.0); + + pLeader->AutoLabelOff(); + pLeader->SetLabel(""); + pLeader->SetArrowPlacementToNone(); + pLeader->SetRadius(0.0); + pLeader->GetProperty()->SetColor( + WELL_LEADER_RED, + WELL_LEADER_GREEN, + WELL_LEADER_BLUE); + pLeader->GetProperty()->SetLineWidth(1.0); + // 二维引线始终绘制在三维网格前方,避免被致密单元边线遮挡。 + pLeader->GetProperty()->SetDisplayLocationToForeground(); + pWellAnnotation->AddPart(pLeader); + + vtkSmartPointer pNameMapper = + vtkSmartPointer::New(); + const QByteArray aWellName = pWell->m_sWellName.toUtf8(); + pNameMapper->SetInput(aWellName.constData()); + vtkTextProperty* pTextProperty = + pNameMapper->GetTextProperty(); + pTextProperty->SetFontFamilyToArial(); + pTextProperty->SetFontSize(WELL_NAME_FONT_SIZE); + pTextProperty->SetColor(1.0, 1.0, 0.0); + pTextProperty->BoldOff(); + pTextProperty->ItalicOff(); + pTextProperty->ShadowOn(); + pTextProperty->SetShadowOffset(1, -1); + pTextProperty->SetJustificationToLeft(); + pTextProperty->SetVerticalJustificationToBottom(); + + vtkSmartPointer pNameActor = + vtkSmartPointer::New(); + pNameActor->SetMapper(pNameMapper); + // 井名与引线使用相同的前景层级,保证顶视图下仍清晰可读。 + pNameActor->GetProperty()->SetDisplayLocationToForeground(); + vtkCoordinate* pNameCoordinate = + pNameActor->GetPositionCoordinate(); + pNameCoordinate->SetCoordinateSystemToDisplay(); + pNameCoordinate->SetReferenceCoordinate(pWorldAnchor); + pNameCoordinate->SetValue( + WELL_NAME_OFFSET_X, WELL_NAME_OFFSET_Y, 0.0); + pWellAnnotation->AddPart(pNameActor); + + // 每口井的文字与引线形成一个不可拆分的候选注记单元。 + pAnnotationGroup->AddPart(pWellAnnotation); + } } - pMarkerGroup->SetVisibility(m_bWellMarkersVisible ? 1 : 0); - pNameGroup->SetVisibility(m_bWellNamesVisible ? 1 : 0); - pSnapshotAssembly->AddPart(pMarkerGroup); - pSnapshotAssembly->AddPart(pNameGroup); + pAnnotationGroup->SetVisibility(m_bWellNamesVisible ? 1 : 0); + pSnapshotAssembly->AddPart(pAnnotationGroup); // 所有校验和 VTK 对象构造成功后才记录候选;活动子树仍未触碰。 m_pCandidateSnapshotAssembly = pSnapshotAssembly; - m_pCandidateMarkerGroup = pMarkerGroup; - m_pCandidateNameGroup = pNameGroup; + m_pCandidateAnnotationGroup = pAnnotationGroup; return true; } void nmPebiResultWellAnnotationLayer::discardCandidate() { Q_ASSERT(isWellAnnotationGuiThread()); - m_pCandidateNameGroup = nullptr; - m_pCandidateMarkerGroup = nullptr; + m_pCandidateAnnotationGroup = nullptr; m_pCandidateSnapshotAssembly = nullptr; } @@ -185,8 +192,7 @@ void nmPebiResultWellAnnotationLayer::commitCandidate() m_pRootAssembly->RemovePart(m_pActiveSnapshotAssembly); } m_pActiveSnapshotAssembly = m_pCandidateSnapshotAssembly; - m_pActiveMarkerGroup = m_pCandidateMarkerGroup; - m_pActiveNameGroup = m_pCandidateNameGroup; + m_pActiveAnnotationGroup = m_pCandidateAnnotationGroup; m_pRootAssembly->AddPart(m_pActiveSnapshotAssembly); discardCandidate(); } @@ -199,8 +205,7 @@ void nmPebiResultWellAnnotationLayer::clear() m_pActiveSnapshotAssembly != nullptr) { m_pRootAssembly->RemovePart(m_pActiveSnapshotAssembly); } - m_pActiveNameGroup = nullptr; - m_pActiveMarkerGroup = nullptr; + m_pActiveAnnotationGroup = nullptr; m_pActiveSnapshotAssembly = nullptr; } @@ -209,21 +214,6 @@ bool nmPebiResultWellAnnotationLayer::hasActiveAnnotations() const return m_pActiveSnapshotAssembly != nullptr; } -void nmPebiResultWellAnnotationLayer::setWellMarkersVisible(bool bVisible) -{ - Q_ASSERT(isWellAnnotationGuiThread()); - if(!isWellAnnotationGuiThread()) { - return; - } - m_bWellMarkersVisible = bVisible; - if(m_pActiveMarkerGroup != nullptr) { - m_pActiveMarkerGroup->SetVisibility(bVisible ? 1 : 0); - } - if(m_pCandidateMarkerGroup != nullptr) { - m_pCandidateMarkerGroup->SetVisibility(bVisible ? 1 : 0); - } -} - void nmPebiResultWellAnnotationLayer::setWellNamesVisible(bool bVisible) { Q_ASSERT(isWellAnnotationGuiThread()); @@ -231,19 +221,14 @@ void nmPebiResultWellAnnotationLayer::setWellNamesVisible(bool bVisible) return; } m_bWellNamesVisible = bVisible; - if(m_pActiveNameGroup != nullptr) { - m_pActiveNameGroup->SetVisibility(bVisible ? 1 : 0); + if(m_pActiveAnnotationGroup != nullptr) { + m_pActiveAnnotationGroup->SetVisibility(bVisible ? 1 : 0); } - if(m_pCandidateNameGroup != nullptr) { - m_pCandidateNameGroup->SetVisibility(bVisible ? 1 : 0); + if(m_pCandidateAnnotationGroup != nullptr) { + m_pCandidateAnnotationGroup->SetVisibility(bVisible ? 1 : 0); } } -bool nmPebiResultWellAnnotationLayer::areWellMarkersVisible() const -{ - return m_bWellMarkersVisible; -} - bool nmPebiResultWellAnnotationLayer::areWellNamesVisible() const { return m_bWellNamesVisible; diff --git a/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp b/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp index 80482dbc..b8aca4ac 100644 --- a/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp +++ b/Src/nmNum/nmSubWxs/nmWxPebiResultViewWidget.cpp @@ -58,7 +58,6 @@ nmWxPebiResultViewWidget::nmWxPebiResultViewWidget( m_pStatusLabel(nullptr), m_pScalarBarAction(nullptr), m_pScaleGridAction(nullptr), - m_pWellMarkersAction(nullptr), m_pWellNamesAction(nullptr), m_bObservedSnapshotCurrent(false), m_bObservedStateValid(false), @@ -173,7 +172,6 @@ void nmWxPebiResultViewWidget::appendContextMenuActions(QMenu* pMenu) } pMenu->addAction(m_pScalarBarAction); pMenu->addAction(m_pScaleGridAction); - pMenu->addAction(m_pWellMarkersAction); pMenu->addAction(m_pWellNamesAction); } @@ -213,13 +211,6 @@ void nmWxPebiResultViewWidget::onScaleGridToggled(bool bVisible) } } -void nmWxPebiResultViewWidget::onWellMarkersToggled(bool bVisible) -{ - if(m_pSceneController != nullptr && m_pSceneController->hasSnapshot()) { - m_pSceneController->setWellMarkersVisible(bVisible); - } -} - void nmWxPebiResultViewWidget::onWellNamesToggled(bool bVisible) { if(m_pSceneController != nullptr && m_pSceneController->hasSnapshot()) { @@ -269,18 +260,14 @@ void nmWxPebiResultViewWidget::createUi() m_pScaleGridAction = new QAction( QIcon(resultViewIconPath("NmScaleGrid.png")), tr("Scale Grid"), this); - m_pWellMarkersAction = new QAction( - QIcon(resultViewIconPath("NmWell.png")), - tr("Well Markers"), this); m_pWellNamesAction = new QAction( QIcon(resultViewIconPath("NmShow.png")), tr("Well Names"), this); QAction* const pBusinessActions[] = { - m_pScalarBarAction, m_pScaleGridAction, - m_pWellMarkersAction, m_pWellNamesAction + m_pScalarBarAction, m_pScaleGridAction, m_pWellNamesAction }; - for(int nIndex = 0; nIndex < 4; ++nIndex) { + for(int nIndex = 0; nIndex < 3; ++nIndex) { pBusinessActions[nIndex]->setCheckable(true); pBusinessActions[nIndex]->setToolTip( pBusinessActions[nIndex]->text()); @@ -312,7 +299,7 @@ void nmWxPebiResultViewWidget::createUi() if(pFrontAction != nullptr) m_pToolBar->addAction(pFrontAction); if(pPickCenterAction != nullptr) m_pToolBar->addAction(pPickCenterAction); m_pToolBar->addSeparator(); - for(int nIndex = 0; nIndex < 4; ++nIndex) { + for(int nIndex = 0; nIndex < 3; ++nIndex) { m_pToolBar->addAction(pBusinessActions[nIndex]); } m_pToolBar->addSeparator(); @@ -323,8 +310,6 @@ void nmWxPebiResultViewWidget::createUi() this, SLOT(onScalarBarToggled(bool))); connect(m_pScaleGridAction, SIGNAL(toggled(bool)), this, SLOT(onScaleGridToggled(bool))); - connect(m_pWellMarkersAction, SIGNAL(toggled(bool)), - this, SLOT(onWellMarkersToggled(bool))); connect(m_pWellNamesAction, SIGNAL(toggled(bool)), this, SLOT(onWellNamesToggled(bool))); connect(m_pRenderContainer, SIGNAL(contextMenuAboutToShow(QMenu*)), @@ -484,15 +469,12 @@ void nmWxPebiResultViewWidget::synchronizeBusinessActions() m_pScalarBarAction, m_pSceneController->isScalarBarVisible()); setActionCheckedWithoutSignal( m_pScaleGridAction, m_pSceneController->isScaleGridVisible()); - setActionCheckedWithoutSignal( - m_pWellMarkersAction, m_pSceneController->areWellMarkersVisible()); setActionCheckedWithoutSignal( m_pWellNamesAction, m_pSceneController->areWellNamesVisible()); const bool bEnabled = m_pSceneController->hasSnapshot(); m_pScalarBarAction->setEnabled(bEnabled); m_pScaleGridAction->setEnabled(bEnabled); - m_pWellMarkersAction->setEnabled(bEnabled); m_pWellNamesAction->setEnabled(bEnabled); }