From 85b1c1173e80ae82a1161b63aa668212cd851ee0 Mon Sep 17 00:00:00 2001 From: lvjunjie Date: Thu, 25 Jun 2026 15:23:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8C=BA=E5=9F=9F=E6=A0=87=E8=AE=B0=E9=87=8D?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Include/nmNum/nmPlot/nmObjRegionMark.h | 27 ++- Include/nmNum/nmPlot/nmPlotGraphicBinder.h | 43 ++++ Src/nmNum/nmData/nmDataRegionMark.cpp | 26 +- Src/nmNum/nmPlot/nmGuiPlot.cpp | 13 +- Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp | 10 + Src/nmNum/nmPlot/nmObjRegion.cpp | 1 + Src/nmNum/nmPlot/nmObjRegionMark.cpp | 192 ++++++--------- Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp | 267 +++++++++++++++++++++ 8 files changed, 449 insertions(+), 130 deletions(-) diff --git a/Include/nmNum/nmPlot/nmObjRegionMark.h b/Include/nmNum/nmPlot/nmObjRegionMark.h index 99fc1cf..a804130 100644 --- a/Include/nmNum/nmPlot/nmObjRegionMark.h +++ b/Include/nmNum/nmPlot/nmObjRegionMark.h @@ -6,7 +6,8 @@ #include "ZxPlot.h" -#include "nmDataRegionMark.h" +class nmPlotGraphicBinder; +class nmDataRegionMark; class NM_PLOT_EXPORT nmObjRegionMark : public nmObjBase { Q_OBJECT @@ -95,8 +96,24 @@ public: void setSelectRegion(bool select); bool getSelectRegion() const; + // 注入 Binder 指针 + void setGraphicBinder(nmPlotGraphicBinder* pBinder) { m_pGraphicBinder = pBinder; } + + // 通过 Binder 查询关联的数据对象(供 nmObjRegion 使用) nmDataRegionMark* getRegionMarkData() const; +signals: + // 储层类型变更 + void sigResevoirTypeChanged(int type); + // 综合压缩系数(Kr)变更 + void sigComKrChanged(double comKr); + // 综合压缩系数(W)变更 + void sigComWChanged(double comW); + // 净毛比变更 + void sigNetToGrossChanged(double netToGross); + // 可见性变更 + void sigRegionMarkVisibleChanged(bool bVisible); + public slots: // 图元状态改变 void onObjVisibleChanged(bool bIsVisible); @@ -107,6 +124,12 @@ private: QColor m_clrBackgrd;//填充颜色 - nmDataRegionMark* m_regionMarkData; + // 本地属性副本(与数据中心同步) + int m_reservoirType; // 0=Homogeneous, 1=Dual porosity + double m_comKr; + double m_comW; + double m_netToGross; + + nmPlotGraphicBinder* m_pGraphicBinder; QPixmap m_icon; }; diff --git a/Include/nmNum/nmPlot/nmPlotGraphicBinder.h b/Include/nmNum/nmPlot/nmPlotGraphicBinder.h index a16de03..a19b3af 100644 --- a/Include/nmNum/nmPlot/nmPlotGraphicBinder.h +++ b/Include/nmNum/nmPlot/nmPlotGraphicBinder.h @@ -18,6 +18,8 @@ class nmObjRectOutline; class nmObjPolygonOutline; class nmDataMeasure; class nmObjLineMeasure; +class nmDataRegionMark; +class nmObjRegionMark; // 图元与数据绑定协调器,由 nmGuiPlot 托管 class NM_PLOT_EXPORT nmPlotGraphicBinder : public QObject @@ -90,6 +92,23 @@ public: // 坐标同步:从数据对象读取起点终点,写回图元(拟合功能修改数据后由 paintBack 调用) void syncMeasurePoints(nmObjLineMeasure* pGraphic); + // ==================== 区域标记图元 ==================== + + // 调用:用户画完区域标记后 + void createRegionMarkForGraphic(nmObjRegionMark* pGraphic); + + // 调用:从文件加载,绑定已有区域标记数据到已有图元 + void bindRegionMarkToGraphic(nmObjRegionMark* pGraphic, nmDataRegionMark* pData); + + // 调用:删除区域标记图元前 + void removeRegionMarkBinding(nmObjRegionMark* pGraphic); + + // 兜底同步:名称、位置,由区域标记图元在 paintBack 中调用 + void syncRegionMarkData(nmObjRegionMark* pGraphic); + + // 查找区域标记图元对应的数据指针 + nmDataRegionMark* getRegionMarkDataFor(nmObjRegionMark* pGraphic); + // 切换分析时更新绑定的 DataManager,并清理旧图元的残留映射 void updateDataMgr(nmDataAnalyzeManager* pDataMgr); @@ -116,6 +135,13 @@ private slots: void onGraphicOutlineFlowTypeChanged(); void onGraphicOutlineVisibleChanged(bool bVisible); + // 区域标记图元信号 → 数据同步 + void onGraphicRegionMarkReservoirTypeChanged(int type); + void onGraphicRegionMarkComKrChanged(double comKr); + void onGraphicRegionMarkComWChanged(double comW); + void onGraphicRegionMarkNetToGrossChanged(double netToGross); + void onGraphicRegionMarkVisibleChanged(bool bVisible); + private: nmDataAnalyzeManager* m_pDataMgr; // 数据中心,不持有,外部注入 @@ -166,4 +192,21 @@ private: // 测量线图元 → 数据 的映射表 QMap m_mapMeasureData; + + // ==================== 区域标记图元 ==================== + + // 区域标记图元 → 数据 的映射表 + QMap m_mapRegionMarkData; + + // 已建立信号连接的区域标记图元集合 + QSet m_setBoundRegionMarkGraphics; + + // 区域标记图元 ←→ 数据 信号连接 + void _connectRegionMark(nmObjRegionMark* pGraphic, nmDataRegionMark* pData); + + // 断开指定区域标记图元与本 Binder 的信号连接 + void _disconnectRegionMark(nmObjRegionMark* pGraphic); + + // 从区域标记数据对象读取值,写入图元本地副本(加载时用) + void _pushRegionMarkDataToGraphic(nmObjRegionMark* pGraphic, nmDataRegionMark* pData); }; diff --git a/Src/nmNum/nmData/nmDataRegionMark.cpp b/Src/nmNum/nmData/nmDataRegionMark.cpp index 2b04c22..36771e8 100644 --- a/Src/nmNum/nmData/nmDataRegionMark.cpp +++ b/Src/nmNum/nmData/nmDataRegionMark.cpp @@ -52,11 +52,15 @@ rapidjson::Value nmDataRegionMark::ToJsonValue(rapidjson::Document::AllocatorTyp rapidjson::Value regionMarkObject(rapidjson::kObjectType); // 序列化名称 - // 将 QString 转换为 UTF-8 编码的 C 字符串,并添加到 JSON 中 - regionMarkObject.AddMember("RegionName", rapidjson::Value(m_sRegionMarkName.toStdString().c_str(), allocator).Move(), allocator); + regionMarkObject.AddMember("RegionMarkName", rapidjson::Value(m_sRegionMarkName.toStdString().c_str(), allocator).Move(), allocator); + + // 序列化位置 (m_ptPos) + rapidjson::Value ptPosObj(rapidjson::kObjectType); + ptPosObj.AddMember("X", m_ptPos.x(), allocator); + ptPosObj.AddMember("Y", m_ptPos.y(), allocator); + regionMarkObject.AddMember("PtPos", ptPosObj, allocator); // 序列化 nmDataAttribute 类型的成员 - // 调用 nmDataAttribute 自身的 ToJsonValue 方法进行递归序列化 regionMarkObject.AddMember("ReservoirType", m_reservoirType.ToJsonValue(allocator), allocator); regionMarkObject.AddMember("ComKr", m_comKr.ToJsonValue(allocator), allocator); regionMarkObject.AddMember("ComW", m_comW.ToJsonValue(allocator), allocator); @@ -65,7 +69,7 @@ rapidjson::Value nmDataRegionMark::ToJsonValue(rapidjson::Document::AllocatorTyp // 序列化图元可见性 (m_bPlotVisible) regionMarkObject.AddMember("PlotVisible", m_bPlotVisible, allocator); - return regionMarkObject; // 返回序列化后的 RapidJSON Value + return regionMarkObject; } // 从 RapidJSON Value 反序列化数据到 nmDataRegionMark @@ -76,8 +80,20 @@ void nmDataRegionMark::FromJsonValue(const rapidjson::Value& jsonValue) m_sRegionMarkName = QString::fromUtf8(jsonValue["RegionMarkName"].GetString()); } + // 反序列化位置 (m_ptPos) + if (jsonValue.HasMember("PtPos") && jsonValue["PtPos"].IsObject()) { + const rapidjson::Value& ptPosObj = jsonValue["PtPos"]; + double x = 0.0, y = 0.0; + if (ptPosObj.HasMember("X") && ptPosObj["X"].IsDouble()) { + x = ptPosObj["X"].GetDouble(); + } + if (ptPosObj.HasMember("Y") && ptPosObj["Y"].IsDouble()) { + y = ptPosObj["Y"].GetDouble(); + } + m_ptPos = QPointF(x, y); + } + // 反序列化 nmDataAttribute 类型的成员 - // 调用 nmDataAttribute 自身的 FromJsonValue 方法进行递归反序列化 if (jsonValue.HasMember("ReservoirType") && jsonValue["ReservoirType"].IsObject()) { m_reservoirType.FromJsonValue(jsonValue["ReservoirType"]); } diff --git a/Src/nmNum/nmPlot/nmGuiPlot.cpp b/Src/nmNum/nmPlot/nmGuiPlot.cpp index 4aa05df..4e046f9 100644 --- a/Src/nmNum/nmPlot/nmGuiPlot.cpp +++ b/Src/nmNum/nmPlot/nmGuiPlot.cpp @@ -43,7 +43,7 @@ #include "nmObjRound.h" #include "nmObjRegion.h" - +#include "nmObjRegionMark.h" #include "nmObjDeleteTool.h" @@ -51,6 +51,7 @@ #include "nmDataFault.h" #include "nmDataFracture.h" #include "nmDataOutline.h" +#include "nmDataRegionMark.h" #include "nmDataAxis.h" #include "nmPlotGraphicBinder.h" @@ -743,10 +744,10 @@ void nmGuiPlot::initRegionMarkObjsFromData(nmDataAnalyzeManager* pDataManager) continue; } - // 6.7 绑定区域标记数据到图元对象上 - //pRegionMarkPlot->set(pDataRegionMark); - - // TODO: 设置区域标记其他属性 + // 6.7 通过 Binder 绑定区域标记数据到图元 + if (m_pGraphicBinder) { + m_pGraphicBinder->bindRegionMarkToGraphic(pRegionMarkPlot, pDataRegionMark); + } } } @@ -1395,6 +1396,8 @@ void nmGuiPlot::slotDeleteOneObj(QString sName, void* obj) m_pGraphicBinder->removeOutlineBinding(nmObj); } else if (nmObjLineMeasure* pMeasure = dynamic_cast(nmObj)) { m_pGraphicBinder->removeMeasureBinding(pMeasure); + } else if (nmObjRegionMark* pRegionMark = dynamic_cast(nmObj)) { + m_pGraphicBinder->removeRegionMarkBinding(pRegionMark); } else { // 其他类型回退到旧方式 nmObj->removeData(); diff --git a/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp b/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp index 3169076..f6e2033 100644 --- a/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp +++ b/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp @@ -37,6 +37,8 @@ #include "nmObjPolygonOutline.h" +#include "nmObjRegionMark.h" + #include "nmObjRegionTool.h" #include "nmObjDeleteTool.h" @@ -390,6 +392,14 @@ void nmGuiPlotCmdHelper::slotObjPtsFinished(QVector& vec) { if (pMeasure && pWxPlot->graphicBinder()) { pWxPlot->graphicBinder()->createMeasureForGraphic(pMeasure); } + } else if (pTool->getNOT() == NMOT_RegionMark) { + // 先执行 afterCreated(图元内部初始化) + pObj->afterCreated(); + // 再通过 Binder 创建数据并建立绑定 + nmObjRegionMark* pRegionMark = dynamic_cast(pObj); + if (pRegionMark && pWxPlot->graphicBinder()) { + pWxPlot->graphicBinder()->createRegionMarkForGraphic(pRegionMark); + } } else { pObj->afterCreated(); } diff --git a/Src/nmNum/nmPlot/nmObjRegion.cpp b/Src/nmNum/nmPlot/nmObjRegion.cpp index 298dc4e..87e167d 100644 --- a/Src/nmNum/nmPlot/nmObjRegion.cpp +++ b/Src/nmNum/nmPlot/nmObjRegion.cpp @@ -13,6 +13,7 @@ #include "ZxPlot.h" #include "nmDataAnalyzeManager.h" +#include "nmDataRegionMark.h" #include diff --git a/Src/nmNum/nmPlot/nmObjRegionMark.cpp b/Src/nmNum/nmPlot/nmObjRegionMark.cpp index e3491af..0fe3495 100644 --- a/Src/nmNum/nmPlot/nmObjRegionMark.cpp +++ b/Src/nmNum/nmPlot/nmObjRegionMark.cpp @@ -16,14 +16,19 @@ #include "ZxBaseUtil.h" #include "ZxPlot.h" -#include "nmDataAnalyzeManager.h" +#include "nmPlotGraphicBinder.h" +#include "nmDataRegionMark.h" ZX_DEFINE_DYNAMIC(nObjRegionMark, nmObjRegionMark) nmObjRegionMark::nmObjRegionMark() : m_bSelectRegion(false) , m_iColorIndex(0) - , m_regionMarkData(nullptr) + , m_reservoirType(0) + , m_comKr(1.0) + , m_comW(1.0) + , m_netToGross(1.0) + , m_pGraphicBinder(nullptr) { m_sObjTag = "nObjRegionMark"; nmObjRegionMark::init("", NULL, NULL); @@ -36,7 +41,11 @@ nmObjRegionMark::nmObjRegionMark(const QString& sName, \ int RegionMarkCount) : m_bSelectRegion(false) , m_iColorIndex(RegionMarkCount) - , m_regionMarkData(nullptr) + , m_reservoirType(0) + , m_comKr(1.0) + , m_comW(1.0) + , m_netToGross(1.0) + , m_pGraphicBinder(nullptr) { m_sObjTag = "nObjRegionMark"; nmObjRegionMark::init(sName, pAxisX, pAxisY); @@ -46,8 +55,6 @@ nmObjRegionMark::nmObjRegionMark(const QString& sName, \ nmObjRegionMark::~nmObjRegionMark() { - // 区域标记数据由DataManager统一释放,图元只保存引用。 - m_regionMarkData = nullptr; } QColor nmObjRegionMark::generateColor(int index) @@ -69,7 +76,7 @@ void nmObjRegionMark::init(const QString& sName, \ m_bSelectRegion = false; - m_regionMarkData = nullptr; + m_pGraphicBinder = nullptr; m_icon = QPixmap(ZxBaseUtil::getDirOf(s_Dir_Res, "Icon") + "Anchor.png"); @@ -89,80 +96,64 @@ void nmObjRegionMark::initTools() void nmObjRegionMark::setResevoirType(int newResevoirType) { - // 从Data中取数据 - nmDataAttribute tempAttr = m_regionMarkData->getReservoirType(); - - if(newResevoirType == 0) { - tempAttr.setValue(tr("Homogeneous")); - } else { - tempAttr.setValue(tr("Dual porosity pseudo steady state")); + if (m_reservoirType != newResevoirType) { + m_reservoirType = newResevoirType; + emit sigResevoirTypeChanged(newResevoirType); } - - m_regionMarkData->setReservoirType(tempAttr); - } int nmObjRegionMark::getResevoirType() { - if(m_regionMarkData->getReservoirType().getValue() == tr("Homogeneous")) - return 0; - else - return 1; + return m_reservoirType; } void nmObjRegionMark::setComKr(double newComkr) { - // 从Data中取数据 - nmDataAttribute tempAttr = m_regionMarkData->getComKr(); - tempAttr.setValue(newComkr); - m_regionMarkData->setComKr(tempAttr); + if (m_comKr != newComkr) { + m_comKr = newComkr; + emit sigComKrChanged(newComkr); + } } double nmObjRegionMark::getComKr() { - return m_regionMarkData->getComKr().getValue().toDouble(); + return m_comKr; } void nmObjRegionMark::setComW(double newComW) { - // 从Data中取数据 - nmDataAttribute tempAttr = m_regionMarkData->getComW(); - tempAttr.setValue(newComW); - m_regionMarkData->setComW(tempAttr); + if (m_comW != newComW) { + m_comW = newComW; + emit sigComWChanged(newComW); + } } double nmObjRegionMark::getComW() { - return m_regionMarkData->getComW().getValue().toDouble(); + return m_comW; } void nmObjRegionMark::setNetToGross(double newNetToGross) { - // 从Data中取数据 - nmDataAttribute tempAttr = m_regionMarkData->getNetToGross(); - tempAttr.setValue(newNetToGross); - m_regionMarkData->setNetToGross(tempAttr); + if (m_netToGross != newNetToGross) { + m_netToGross = newNetToGross; + emit sigNetToGrossChanged(newNetToGross); + } } double nmObjRegionMark::getNetToGross() { - return m_regionMarkData->getNetToGross().getValue().toDouble(); + return m_netToGross; } void nmObjRegionMark::onSerialize(ZxSerializer* ser) { nmObjBase::onSerialize(ser); - int resevoirType; - - if(m_regionMarkData->getReservoirType().getValue() == tr("Homogeneous")) - resevoirType = 0; - else - resevoirType = 1; - ser->write("ResevoirType", resevoirType); - ser->write("dComKr", m_regionMarkData->getComKr().getValue().toDouble()); - ser->write("dComW", m_regionMarkData->getComW().getValue().toDouble()); - ser->write("NetToGross", m_regionMarkData->getNetToGross().getValue().toDouble()); + ser->write("ResevoirType", m_reservoirType); + ser->write("dComKr", m_comKr); + ser->write("dComW", m_comW); + ser->write("NetToGross", m_netToGross); } void nmObjRegionMark::onDeserialize(ZxSerializer* ser) @@ -177,26 +168,20 @@ void nmObjRegionMark::onDeserialize(ZxSerializer* ser) ser->read("dComW", comW); ser->read("NetToGross", netToGross); - this->setResevoirType(resevoirType); - this->setComKr(comKr); - this->setComW(comW); - this->setNetToGross(netToGross); + m_reservoirType = resevoirType; + m_comKr = comKr; + m_comW = comW; + m_netToGross = netToGross; } void nmObjRegionMark::onSaveTempl(ZxSerializer* ser) { nmObjBase::onSaveTempl(ser); - int resevoirType; - - if(m_regionMarkData->getReservoirType().getValue() == tr("Homogeneous")) - resevoirType = 0; - else - resevoirType = 1; - ser->write("ResevoirType", resevoirType); - ser->write("dComKr", m_regionMarkData->getComKr().getValue().toDouble()); - ser->write("dComW", m_regionMarkData->getComW().getValue().toDouble()); - ser->write("NetToGross", m_regionMarkData->getNetToGross().getValue().toDouble()); + ser->write("ResevoirType", m_reservoirType); + ser->write("dComKr", m_comKr); + ser->write("dComW", m_comW); + ser->write("NetToGross", m_netToGross); } void nmObjRegionMark::onLoadTempl(ZxSerializer* ser) @@ -211,10 +196,10 @@ void nmObjRegionMark::onLoadTempl(ZxSerializer* ser) ser->read("dComW", comW); ser->read("NetToGross", netToGross); - this->setResevoirType(resevoirType); - this->setComKr(comKr); - this->setComW(comW); - this->setNetToGross(netToGross); + m_reservoirType = resevoirType; + m_comKr = comKr; + m_comW = comW; + m_netToGross = netToGross; } void nmObjRegionMark::fillPtyPano(IxPtyPano* sheet) @@ -264,7 +249,7 @@ bool nmObjRegionMark::_runHitTest(const QPointF& pt, int& nOption, int& nSubInde QVector pts = getPosOf(m_vecPoints); - // �� + // 点 double r = 3.f; for(int i = 0; i < pts.count(); i++) { @@ -325,13 +310,6 @@ void nmObjRegionMark::paintBack(QPainter* painter, const ZxPaintParam& param) QPointF ptPos = getPosOf(m_vecPoints[0]); painter->save(); - if(m_regionMarkData != nullptr) { - m_regionMarkData->setRegionMarkName(m_sName); - m_regionMarkData->setPtPos(m_vecPoints[0]); - m_regionMarkData->setBackgroundColor(m_clrBackgrd); - m_regionMarkData->setSelectRegion(m_bSelectRegion); - } - ZxPlot* m_pCurPlot = dynamic_cast(this->getParent()); if (m_pCurPlot == nullptr) { painter->restore(); @@ -356,12 +334,13 @@ void nmObjRegionMark::paintBack(QPainter* painter, const ZxPaintParam& param) // 判断 RegionMark 是否在该区域内 if(regionPolygon.containsPoint(ptPos, Qt::OddEvenFill)) { // 判断该区域是否已经被标记 - if(region->getRegionMark() == nullptr && m_regionMarkData != nullptr) { - region->setRegionMark(this); - region->setBackgrdColor(this->m_clrBackgrd); - this->setSelectRegion(true); - // update Data - m_regionMarkData->setSelectRegion(m_bSelectRegion); + if(region->getRegionMark() == nullptr) { + // 仅在 Binder 已绑定时才关联(避免加载数据前 paintBack 误设) + if (m_pGraphicBinder) { + region->setRegionMark(this); + region->setBackgrdColor(this->m_clrBackgrd); + this->setSelectRegion(true); + } } else { // 如果区域已被标记 int index = region->getRegionMark()->getColorIndex(); @@ -371,37 +350,17 @@ void nmObjRegionMark::paintBack(QPainter* painter, const ZxPaintParam& param) region->setRegionMark(this); region->setBackgrdColor(this->m_clrBackgrd); this->setSelectRegion(true); - // updata Data - m_regionMarkData->setSelectRegion(m_bSelectRegion); } } } } } - // 设置字体 - //double r = 8.f; - - //QPointF ptTopLeft = QPointF(ptPos.x() - r, - // ptPos.y() - r); - //QSizeF sz = QSizeF(r * 2.f, r * 2.f); - - //QRectF bound = QRectF(ptTopLeft, sz); - - //QFont ft = qApp->font(); - //ft.setPointSize(8); - //painter->setFont(ft); - //painter->setPen(Qt::black); - //ZxDrawHelper::drawText(painter, - // bound, - // Qt::AlignCenter | Qt::AlignVCenter, - // m_sName); - - ////painter->setPen(QPen(Qt::black, 1.2f)); - ////ZxDrawHelper::drawPlus(painter,ptPos,2.2f,false,Qt::black); - + // 通过 Binder 同步名称、位置、颜色、选中状态到数据(paintBack 兜底同步) + if (m_pGraphicBinder) { + m_pGraphicBinder->syncRegionMarkData(this); + } - //painter->restore(); // 设置字体 QFont ft = qApp->font(); ft.setPointSize(8); @@ -418,7 +377,6 @@ void nmObjRegionMark::paintBack(QPainter* painter, const ZxPaintParam& param) painter->drawPixmap(iconRect, m_icon, m_icon.rect()); // 计算文本的矩形区域,位于图标上方 - // 文本的y坐标是图标顶部减去间距和文本高度(这里使用iconSize作为文本高度) QRectF textRect( ptPos.x() - textWidth / 2, // 文本水平居中于图标 ptPos.y() - iconSize / 2 - spacing - iconSize, // 在图标上方 @@ -466,30 +424,28 @@ void nmObjRegionMark::setBackgrdColor(QColor color) void nmObjRegionMark::afterCreated() { - m_regionMarkData = nmDataAnalyzeManager::getCurrentInstance()->createRegionMark(); - m_regionMarkData->setRegionMarkName(m_sName); - m_regionMarkData->setPtPos(m_vecPoints[0]); - m_regionMarkData->setSelectRegion(m_bSelectRegion); - m_regionMarkData->setBackgroundColor(m_clrBackgrd); -} - -nmDataRegionMark* nmObjRegionMark::getRegionMarkData() const -{ - return m_regionMarkData; + if (m_pGraphicBinder) { + m_pGraphicBinder->createRegionMarkForGraphic(this); + } } void nmObjRegionMark::removeData() { - if(m_regionMarkData) { - // 从数据中心移除该数据 - nmDataAnalyzeManager::getCurrentInstance()->removeRegionMarkData(m_regionMarkData); - m_regionMarkData = nullptr; + if (m_pGraphicBinder) { + m_pGraphicBinder->removeRegionMarkBinding(this); } } void nmObjRegionMark::onObjVisibleChanged(bool bIsVisible) { - if(m_regionMarkData != nullptr) { - m_regionMarkData->setPlotVisible(bIsVisible); + emit sigRegionMarkVisibleChanged(bIsVisible); +} + +// 通过 Binder 查询关联的数据对象(供 nmObjRegion 使用) +nmDataRegionMark* nmObjRegionMark::getRegionMarkData() const +{ + if (m_pGraphicBinder) { + return m_pGraphicBinder->getRegionMarkDataFor(const_cast(this)); } + return nullptr; } diff --git a/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp b/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp index f67ac96..44ac094 100644 --- a/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp +++ b/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp @@ -10,6 +10,8 @@ #include "nmDataOutline.h" #include "nmObjLineMeasure.h" #include "nmDataMeasure.h" +#include "nmObjRegionMark.h" +#include "nmDataRegionMark.h" #include "nmObjBase.h" #include "nmDataAnalyzeManager.h" @@ -101,6 +103,8 @@ void nmPlotGraphicBinder::updateDataMgr(nmDataAnalyzeManager* pDataMgr) m_mapOutlineData.clear(); m_setBoundOutlineGraphics.clear(); m_mapMeasureData.clear(); + m_mapRegionMarkData.clear(); + m_setBoundRegionMarkGraphics.clear(); m_pDataMgr = pDataMgr; } @@ -771,6 +775,8 @@ void nmPlotGraphicBinder::onGraphicOutlineVisibleChanged(bool bVisible) } } +// ==================== 测量线图元 ==================== + // 用户画完测量线后:获取数据对象并建立绑定 void nmPlotGraphicBinder::createMeasureForGraphic(nmObjLineMeasure* pGraphic) { @@ -839,3 +845,264 @@ void nmPlotGraphicBinder::syncMeasurePoints(nmObjLineMeasure* pGraphic) pGraphic->setAllValues(pts); pGraphic->blockSignals(false); } + +// ==================== 区域标记图元 ==================== + +// 用户画完区域标记后:创建数据对象并建立绑定 +void nmPlotGraphicBinder::createRegionMarkForGraphic(nmObjRegionMark* pGraphic) +{ + if (!pGraphic || !m_pDataMgr) { + return; + } + + // 创建数据对象 + nmDataRegionMark* pData = m_pDataMgr->createRegionMark(); + + // 将图元值推入数据 + pData->setRegionMarkName(pGraphic->getName()); + QVector pts = pGraphic->getAllValues(); + if (pts.count() >= 1) { + pData->setPtPos(pts[0]); + } + + // 储层类型:int → 字符串 + nmDataAttribute attr = pData->getReservoirType(); + if (pGraphic->getResevoirType() == 0) { + attr.setValue("Homogeneous"); + } else { + attr.setValue("Dual porosity pseudo steady state"); + } + pData->setReservoirType(attr); + + // 综合压缩系数、净毛比 + nmDataAttribute comKrAttr = pData->getComKr(); + comKrAttr.setValue(pGraphic->getComKr()); + pData->setComKr(comKrAttr); + + nmDataAttribute comWAttr = pData->getComW(); + comWAttr.setValue(pGraphic->getComW()); + pData->setComW(comWAttr); + + nmDataAttribute ntgAttr = pData->getNetToGross(); + ntgAttr.setValue(pGraphic->getNetToGross()); + pData->setNetToGross(ntgAttr); + + // 建立信号连接 + _connectRegionMark(pGraphic, pData); + + m_pDataMgr->notifyDataChanged(); +} + +// 从文件加载:绑定已有区域标记数据到已有图元 +void nmPlotGraphicBinder::bindRegionMarkToGraphic(nmObjRegionMark* pGraphic, nmDataRegionMark* pData) +{ + if (!pGraphic || !pData) { + return; + } + + // 将数据值推到图元本地副本 + _pushRegionMarkDataToGraphic(pGraphic, pData); + + // 建立信号连接 + _connectRegionMark(pGraphic, pData); +} + +// 删除区域标记图元:从数据中心移除数据并断开信号 +void nmPlotGraphicBinder::removeRegionMarkBinding(nmObjRegionMark* pGraphic) +{ + if (!pGraphic) { + return; + } + + _disconnectRegionMark(pGraphic); + + nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr); + if (pData && m_pDataMgr) { + m_pDataMgr->removeRegionMarkData(pData); + } + + m_mapRegionMarkData.remove(pGraphic); +} + +// 兜底同步:名称、位置(由 paintBack 调用) +void nmPlotGraphicBinder::syncRegionMarkData(nmObjRegionMark* pGraphic) +{ + if (!pGraphic) return; + + nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr); + if (!pData) return; + + pData->setRegionMarkName(pGraphic->getName()); + + QVector pts = pGraphic->getAllValues(); + if (pts.count() >= 1) { + pData->setPtPos(pts[0]); + } +} + +// 查找区域标记图元对应的数据指针 +nmDataRegionMark* nmPlotGraphicBinder::getRegionMarkDataFor(nmObjRegionMark* pGraphic) +{ + return m_mapRegionMarkData.value(pGraphic, nullptr); +} + +// 图元信号 → 数据同步 +void nmPlotGraphicBinder::onGraphicRegionMarkReservoirTypeChanged(int type) +{ + nmObjRegionMark* pGraphic = qobject_cast(sender()); + if (!pGraphic) return; + + nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr); + if (!pData) return; + + nmDataAttribute attr = pData->getReservoirType(); + if (type == 0) { + attr.setValue("Homogeneous"); + } else { + attr.setValue("Dual porosity pseudo steady state"); + } + pData->setReservoirType(attr); + + if (m_pDataMgr) { + m_pDataMgr->notifyDataChanged(); + } +} + +void nmPlotGraphicBinder::onGraphicRegionMarkComKrChanged(double comKr) +{ + nmObjRegionMark* pGraphic = qobject_cast(sender()); + if (!pGraphic) return; + + nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr); + if (!pData) return; + + nmDataAttribute attr = pData->getComKr(); + attr.setValue(comKr); + pData->setComKr(attr); + + if (m_pDataMgr) { + m_pDataMgr->notifyDataChanged(); + } +} + +void nmPlotGraphicBinder::onGraphicRegionMarkComWChanged(double comW) +{ + nmObjRegionMark* pGraphic = qobject_cast(sender()); + if (!pGraphic) return; + + nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr); + if (!pData) return; + + nmDataAttribute attr = pData->getComW(); + attr.setValue(comW); + pData->setComW(attr); + + if (m_pDataMgr) { + m_pDataMgr->notifyDataChanged(); + } +} + +void nmPlotGraphicBinder::onGraphicRegionMarkNetToGrossChanged(double netToGross) +{ + nmObjRegionMark* pGraphic = qobject_cast(sender()); + if (!pGraphic) return; + + nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr); + if (!pData) return; + + nmDataAttribute attr = pData->getNetToGross(); + attr.setValue(netToGross); + pData->setNetToGross(attr); + + if (m_pDataMgr) { + m_pDataMgr->notifyDataChanged(); + } +} + +void nmPlotGraphicBinder::onGraphicRegionMarkVisibleChanged(bool bVisible) +{ + nmObjRegionMark* pGraphic = qobject_cast(sender()); + if (!pGraphic) return; + + nmDataRegionMark* pData = m_mapRegionMarkData.value(pGraphic, nullptr); + if (!pData) return; + + pData->setPlotVisible(bVisible); + + if (m_pDataMgr) { + m_pDataMgr->notifyDataChanged(); + } +} + +// 建立信号连接 +void nmPlotGraphicBinder::_connectRegionMark(nmObjRegionMark* pGraphic, nmDataRegionMark* pData) +{ + if (!pGraphic || !pData) return; + + m_mapRegionMarkData[pGraphic] = pData; + pGraphic->setGraphicBinder(this); + + if (m_setBoundRegionMarkGraphics.contains(pGraphic)) { + return; + } + + connect(pGraphic, SIGNAL(sigResevoirTypeChanged(int)), + this, SLOT(onGraphicRegionMarkReservoirTypeChanged(int))); + connect(pGraphic, SIGNAL(sigComKrChanged(double)), + this, SLOT(onGraphicRegionMarkComKrChanged(double))); + connect(pGraphic, SIGNAL(sigComWChanged(double)), + this, SLOT(onGraphicRegionMarkComWChanged(double))); + connect(pGraphic, SIGNAL(sigNetToGrossChanged(double)), + this, SLOT(onGraphicRegionMarkNetToGrossChanged(double))); + connect(pGraphic, SIGNAL(sigRegionMarkVisibleChanged(bool)), + this, SLOT(onGraphicRegionMarkVisibleChanged(bool))); + + m_setBoundRegionMarkGraphics.insert(pGraphic); +} + +// 断开信号连接 +void nmPlotGraphicBinder::_disconnectRegionMark(nmObjRegionMark* pGraphic) +{ + if (!pGraphic) return; + + if (!m_setBoundRegionMarkGraphics.contains(pGraphic)) { + return; + } + + disconnect(pGraphic, SIGNAL(sigResevoirTypeChanged(int)), + this, SLOT(onGraphicRegionMarkReservoirTypeChanged(int))); + disconnect(pGraphic, SIGNAL(sigComKrChanged(double)), + this, SLOT(onGraphicRegionMarkComKrChanged(double))); + disconnect(pGraphic, SIGNAL(sigComWChanged(double)), + this, SLOT(onGraphicRegionMarkComWChanged(double))); + disconnect(pGraphic, SIGNAL(sigNetToGrossChanged(double)), + this, SLOT(onGraphicRegionMarkNetToGrossChanged(double))); + disconnect(pGraphic, SIGNAL(sigRegionMarkVisibleChanged(bool)), + this, SLOT(onGraphicRegionMarkVisibleChanged(bool))); + + m_setBoundRegionMarkGraphics.remove(pGraphic); +} + +// 从数据对象读取值,写入图元本地副本(加载时用) +void nmPlotGraphicBinder::_pushRegionMarkDataToGraphic(nmObjRegionMark* pGraphic, nmDataRegionMark* pData) +{ + pGraphic->blockSignals(true); + + // 储层类型:字符串 → int + if (pData->getReservoirType().getValue() == "Homogeneous") { + pGraphic->setResevoirType(0); + } else { + pGraphic->setResevoirType(1); + } + + pGraphic->setComKr(pData->getComKr().getValue().toDouble()); + pGraphic->setComW(pData->getComW().getValue().toDouble()); + pGraphic->setNetToGross(pData->getNetToGross().getValue().toDouble()); + + // 位置 + QVector pts; + pts << pData->getPtPos(); + pGraphic->setAllValues(pts); + + pGraphic->blockSignals(false); +}