From dd5ef09c6e3164bd92600a4ec63dde5ae7008b3f Mon Sep 17 00:00:00 2001 From: lvjunjie Date: Thu, 25 Jun 2026 17:02:57 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=8D=E5=90=88=E5=8C=BA=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Include/nmNum/nmData/nmDataRegion.h | 12 ++ Include/nmNum/nmPlot/nmObjRegion.h | 21 ++- Include/nmNum/nmPlot/nmPlotGraphicBinder.h | 40 ++++ Src/nmNum/nmData/nmDataRegion.cpp | 48 +++++ Src/nmNum/nmPlot/nmGuiPlot.cpp | 11 +- Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp | 8 + Src/nmNum/nmPlot/nmObjRegion.cpp | 113 +++++------- Src/nmNum/nmPlot/nmObjRegionTool.cpp | 1 + Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp | 202 +++++++++++++++++++++ 9 files changed, 378 insertions(+), 78 deletions(-) diff --git a/Include/nmNum/nmData/nmDataRegion.h b/Include/nmNum/nmData/nmDataRegion.h index 63a05d9..69144d7 100644 --- a/Include/nmNum/nmData/nmDataRegion.h +++ b/Include/nmNum/nmData/nmDataRegion.h @@ -5,6 +5,8 @@ #include "nmDefines.h" #include "nmDataAttribute.h" +#include + class nmDataRegionMark; class NM_DATA_EXPORT nmDataRegion : public nmDataBase @@ -44,6 +46,12 @@ public: bool getPlotVisible() const; void setPlotVisible(const bool newState); + // 视觉属性:画笔宽度、填充背景色 + double getPenWidth() const; + void setPenWidth(double dWidth); + QColor getBackgrdColor() const; + void setBackgrdColor(const QColor& clr); + private: QString m_sRegionName; // 复合区名称 QVector m_vecPts; // 复合区位置信息 @@ -53,5 +61,9 @@ private: nmDataRegionMark* m_regionMarkData; // 标记区域数据对象 bool m_bPlotVisible; // 图元是否可见 + + // 视觉属性(与图元同步) + double m_dPenWidth; // 画笔宽度 + QColor m_clrBackgrd; // 填充背景色 }; diff --git a/Include/nmNum/nmPlot/nmObjRegion.h b/Include/nmNum/nmPlot/nmObjRegion.h index 18080bf..4234a8c 100644 --- a/Include/nmNum/nmPlot/nmObjRegion.h +++ b/Include/nmNum/nmPlot/nmObjRegion.h @@ -5,7 +5,9 @@ #include "nmPlot_global.h" #include "nmObjRegionMark.h" -#include "nmDataRegion.h" + +class nmDataRegion; +class nmPlotGraphicBinder; // 数值试井绘图对象(区域) class NM_PLOT_EXPORT nmObjRegion : public nmObjBase @@ -78,6 +80,12 @@ public: // 图元状态改变 void onObjVisibleChanged(bool bIsVisible); +signals: + // 流动模型变更 + void sigRegionFlowModelChanged(int model); + // 泄漏系数变更 + void sigRegionLeakageChanged(double leakage); + public: // 填充背景颜色 @@ -92,13 +100,20 @@ public: void setRegionMark(nmObjRegionMark* newRegionMark); nmObjRegionMark* getRegionMark() const; - void setRegionData(nmDataRegion* newRegionData); + // 查找数据指针(通过 Binder) nmDataRegion* getRegionData() const; + void setGraphicBinder(nmPlotGraphicBinder* pBinder) { m_pGraphicBinder = pBinder; } + public: QColor m_clrBackgrd;//填充颜色 nmObjRegionMark* m_regionMark; // 区域标记对象 - nmDataRegion* m_regionData; // 复合区数据对象 +private: + // 本地属性副本(与数据中心同步) + QString m_sFlowModel; // 流动模型:"Leaky" 或 "Composite limit" + double m_dLeakage; // 泄漏系数 + + nmPlotGraphicBinder* m_pGraphicBinder; }; diff --git a/Include/nmNum/nmPlot/nmPlotGraphicBinder.h b/Include/nmNum/nmPlot/nmPlotGraphicBinder.h index a19b3af..ecbf928 100644 --- a/Include/nmNum/nmPlot/nmPlotGraphicBinder.h +++ b/Include/nmNum/nmPlot/nmPlotGraphicBinder.h @@ -20,6 +20,8 @@ class nmDataMeasure; class nmObjLineMeasure; class nmDataRegionMark; class nmObjRegionMark; +class nmDataRegion; +class nmObjRegion; // 图元与数据绑定协调器,由 nmGuiPlot 托管 class NM_PLOT_EXPORT nmPlotGraphicBinder : public QObject @@ -109,6 +111,23 @@ public: // 查找区域标记图元对应的数据指针 nmDataRegionMark* getRegionMarkDataFor(nmObjRegionMark* pGraphic); + // ==================== 复合区图元 ==================== + + // 调用:用户画完复合区后 + void createRegionForGraphic(nmObjRegion* pGraphic); + + // 调用:从文件加载,绑定已有复合区数据到已有图元 + void bindRegionToGraphic(nmObjRegion* pGraphic, nmDataRegion* pData); + + // 调用:删除复合区图元前 + void removeRegionBinding(nmObjRegion* pGraphic); + + // 兜底同步:名称、位置、区域标记关联,由复合区图元在 paintBack 中调用 + void syncRegionData(nmObjRegion* pGraphic); + + // 查找复合区图元对应的数据指针 + nmDataRegion* getRegionDataFor(nmObjRegion* pGraphic); + // 切换分析时更新绑定的 DataManager,并清理旧图元的残留映射 void updateDataMgr(nmDataAnalyzeManager* pDataMgr); @@ -142,6 +161,10 @@ private slots: void onGraphicRegionMarkNetToGrossChanged(double netToGross); void onGraphicRegionMarkVisibleChanged(bool bVisible); + // 复合区图元信号 → 数据同步 + void onGraphicRegionFlowModelChanged(int model); + void onGraphicRegionLeakageChanged(double leakage); + private: nmDataAnalyzeManager* m_pDataMgr; // 数据中心,不持有,外部注入 @@ -209,4 +232,21 @@ private: // 从区域标记数据对象读取值,写入图元本地副本(加载时用) void _pushRegionMarkDataToGraphic(nmObjRegionMark* pGraphic, nmDataRegionMark* pData); + + // ==================== 复合区图元 ==================== + + // 复合区图元 → 数据 的映射表 + QMap m_mapRegionData; + + // 已建立信号连接的复合区图元集合 + QSet m_setBoundRegionGraphics; + + // 复合区图元 ←→ 数据 信号连接 + void _connectRegion(nmObjRegion* pGraphic, nmDataRegion* pData); + + // 断开指定复合区图元与本 Binder 的信号连接 + void _disconnectRegion(nmObjRegion* pGraphic); + + // 从复合区数据对象读取值,写入图元本地副本(加载时用) + void _pushRegionDataToGraphic(nmObjRegion* pGraphic, nmDataRegion* pData); }; diff --git a/Src/nmNum/nmData/nmDataRegion.cpp b/Src/nmNum/nmData/nmDataRegion.cpp index dfa49b1..10e1133 100644 --- a/Src/nmNum/nmData/nmDataRegion.cpp +++ b/Src/nmNum/nmData/nmDataRegion.cpp @@ -8,6 +8,10 @@ nmDataRegion::nmDataRegion(){ // 图元可见性,默认为true m_bPlotVisible = true; + + // 视觉属性默认值(与 nmObjRegion::init 保持一致) + m_dPenWidth = 0.3; + m_clrBackgrd = QColor(0, 0, 0, 0); } nmDataRegion::nmDataRegion(const nmDataRegion& other){ @@ -27,6 +31,9 @@ nmDataRegion& nmDataRegion::operator=(const nmDataRegion& other) { m_regionMarkData = other.m_regionMarkData; m_bPlotVisible = other.m_bPlotVisible; + + m_dPenWidth = other.m_dPenWidth; + m_clrBackgrd = other.m_clrBackgrd; } return *this; } @@ -65,6 +72,15 @@ rapidjson::Value nmDataRegion::ToJsonValue(rapidjson::Document::AllocatorType& a // 序列化图元可见性 (m_bPlotVisible) regionObject.AddMember("PlotVisible", m_bPlotVisible, allocator); + // 序列化视觉属性 + regionObject.AddMember("PenWidth", m_dPenWidth, allocator); + rapidjson::Value clrObj(rapidjson::kObjectType); + clrObj.AddMember("R", m_clrBackgrd.red(), allocator); + clrObj.AddMember("G", m_clrBackgrd.green(), allocator); + clrObj.AddMember("B", m_clrBackgrd.blue(), allocator); + clrObj.AddMember("A", m_clrBackgrd.alpha(), allocator); + regionObject.AddMember("BackgrdColor", clrObj, allocator); + return regionObject; // 返回序列化后的 RapidJSON Value } @@ -103,6 +119,20 @@ void nmDataRegion::FromJsonValue(const rapidjson::Value& jsonValue) if (jsonValue.HasMember("PlotVisible") && jsonValue["PlotVisible"].IsBool()) { m_bPlotVisible = jsonValue["PlotVisible"].GetBool(); } + + // 反序列化视觉属性 + if (jsonValue.HasMember("PenWidth") && jsonValue["PenWidth"].IsDouble()) { + m_dPenWidth = jsonValue["PenWidth"].GetDouble(); + } + if (jsonValue.HasMember("BackgrdColor") && jsonValue["BackgrdColor"].IsObject()) { + const rapidjson::Value& clrObj = jsonValue["BackgrdColor"]; + int r = 0, g = 0, b = 0, a = 0; + if (clrObj.HasMember("R") && clrObj["R"].IsInt()) r = clrObj["R"].GetInt(); + if (clrObj.HasMember("G") && clrObj["G"].IsInt()) g = clrObj["G"].GetInt(); + if (clrObj.HasMember("B") && clrObj["B"].IsInt()) b = clrObj["B"].GetInt(); + if (clrObj.HasMember("A") && clrObj["A"].IsInt()) a = clrObj["A"].GetInt(); + m_clrBackgrd = QColor(r, g, b, a); + } } @@ -164,3 +194,21 @@ bool nmDataRegion::getPlotVisible() const{ void nmDataRegion::setPlotVisible(const bool newState) { m_bPlotVisible = newState; } + +// Getter and Setter for m_dPenWidth +double nmDataRegion::getPenWidth() const { + return m_dPenWidth; +} + +void nmDataRegion::setPenWidth(double dWidth) { + m_dPenWidth = dWidth; +} + +// Getter and Setter for m_clrBackgrd +QColor nmDataRegion::getBackgrdColor() const { + return m_clrBackgrd; +} + +void nmDataRegion::setBackgrdColor(const QColor& clr) { + m_clrBackgrd = clr; +} diff --git a/Src/nmNum/nmPlot/nmGuiPlot.cpp b/Src/nmNum/nmPlot/nmGuiPlot.cpp index 4e046f9..321f6d0 100644 --- a/Src/nmNum/nmPlot/nmGuiPlot.cpp +++ b/Src/nmNum/nmPlot/nmGuiPlot.cpp @@ -52,6 +52,7 @@ #include "nmDataFracture.h" #include "nmDataOutline.h" #include "nmDataRegionMark.h" +#include "nmDataRegion.h" #include "nmDataAxis.h" #include "nmPlotGraphicBinder.h" @@ -700,10 +701,10 @@ void nmGuiPlot::initRegionObjsFromData(nmDataAnalyzeManager* pDataManager) continue; } - // 5.7 绑定区域数据到图元对象上 - pRegionPlot->setRegionData(pDataRegion); - - // TODO: 设置区域其他属性 + // 5.7 通过 Binder 绑定区域数据到图元 + if (m_pGraphicBinder) { + m_pGraphicBinder->bindRegionToGraphic(pRegionPlot, pDataRegion); + } } } @@ -1398,6 +1399,8 @@ void nmGuiPlot::slotDeleteOneObj(QString sName, void* obj) m_pGraphicBinder->removeMeasureBinding(pMeasure); } else if (nmObjRegionMark* pRegionMark = dynamic_cast(nmObj)) { m_pGraphicBinder->removeRegionMarkBinding(pRegionMark); + } else if (nmObjRegion* pRegion = dynamic_cast(nmObj)) { + m_pGraphicBinder->removeRegionBinding(pRegion); } else { // 其他类型回退到旧方式 nmObj->removeData(); diff --git a/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp b/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp index f6e2033..8bec349 100644 --- a/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp +++ b/Src/nmNum/nmPlot/nmGuiPlotCmdHelper.cpp @@ -400,6 +400,14 @@ void nmGuiPlotCmdHelper::slotObjPtsFinished(QVector& vec) { if (pRegionMark && pWxPlot->graphicBinder()) { pWxPlot->graphicBinder()->createRegionMarkForGraphic(pRegionMark); } + } else if (pTool->getNOT() == NMOT_Region) { + // 先执行 afterCreated(图元内部初始化:点排序) + pObj->afterCreated(); + // 再通过 Binder 创建数据并建立绑定 + nmObjRegion* pRegion = dynamic_cast(pObj); + if (pRegion && pWxPlot->graphicBinder()) { + pWxPlot->graphicBinder()->createRegionForGraphic(pRegion); + } } else { pObj->afterCreated(); } diff --git a/Src/nmNum/nmPlot/nmObjRegion.cpp b/Src/nmNum/nmPlot/nmObjRegion.cpp index 87e167d..8b42f58 100644 --- a/Src/nmNum/nmPlot/nmObjRegion.cpp +++ b/Src/nmNum/nmPlot/nmObjRegion.cpp @@ -12,8 +12,8 @@ #include "ZxBaseUtil.h" #include "ZxPlot.h" -#include "nmDataAnalyzeManager.h" -#include "nmDataRegionMark.h" +#include "nmPlotGraphicBinder.h" +#include "nmDataRegion.h" #include @@ -35,9 +35,6 @@ nmObjRegion::nmObjRegion(const QString& sName, \ nmObjRegion::~nmObjRegion() { - // 复合区数据由DataManager统一释放,图元只保存引用。 - m_regionData = nullptr; - if(m_regionMark != nullptr) { m_regionMark = nullptr; } @@ -55,7 +52,9 @@ void nmObjRegion::init(const QString& sName, \ m_clrBackgrd = QColor(0, 0, 0, 0); m_regionMark = nullptr; - m_regionData = nullptr; + m_pGraphicBinder = nullptr; + m_sFlowModel = tr("Leaky"); + m_dLeakage = 1.0; loadTempl(); @@ -206,14 +205,15 @@ void nmObjRegion::onSerialize(ZxSerializer* ser) nmObjBase::onSerialize(ser); int flowModel; - if(m_regionData->getRegionFlowModel().getValue() == tr("Leaky")) + if(m_sFlowModel == tr("Leaky")) flowModel = 0; else flowModel = 1; ser->write("FlowModel", flowModel); - ser->write("Leakage", m_regionData->getRegionFlowModel().getValue().toDouble()); + ser->write("Leakage", m_dLeakage); ser->write("BackgrdColor", m_clrBackgrd); + ser->write("PenWidth", m_oPen.widthF()); } void nmObjRegion::onDeserialize(ZxSerializer* ser) @@ -221,10 +221,14 @@ void nmObjRegion::onDeserialize(ZxSerializer* ser) nmObjBase::onDeserialize(ser); int flowModel; double regionLeakage; + double penWidth; ser->read("FlowModel", flowModel); ser->read("Leakage", regionLeakage); ser->read("BackgrdColor", m_clrBackgrd); + ser->read("PenWidth", penWidth); + m_oPen.setWidthF(penWidth); + this->setRegionFlowModel(flowModel); this->setRegionLeakage(regionLeakage); } @@ -233,14 +237,15 @@ void nmObjRegion::onSaveTempl(ZxSerializer* ser) nmObjBase::onSaveTempl(ser); int flowModel; - if(m_regionData->getRegionFlowModel().getValue() == tr("Leaky")) + if(m_sFlowModel == tr("Leaky")) flowModel = 0; else flowModel = 1; ser->write("FlowModel", flowModel); - ser->write("Leakage", m_regionData->getRegionFlowModel().getValue().toDouble()); + ser->write("Leakage", m_dLeakage); ser->write("BackgrdColor", m_clrBackgrd); + ser->write("PenWidth", m_oPen.widthF()); } void nmObjRegion::onLoadTempl(ZxSerializer* ser) @@ -248,10 +253,14 @@ void nmObjRegion::onLoadTempl(ZxSerializer* ser) nmObjBase::onLoadTempl(ser); int flowModel; double regionLeakage; + double penWidth; ser->read("FlowModel", flowModel); ser->read("Leakage", regionLeakage); ser->read("BackgrdColor", m_clrBackgrd); + ser->read("PenWidth", penWidth); + m_oPen.setWidthF(penWidth); + this->setRegionFlowModel(flowModel); this->setRegionLeakage(regionLeakage); } @@ -280,27 +289,14 @@ void nmObjRegion::paintBack(QPainter* painter, const ZxPaintParam& param) return; } + // 通过 Binder 同步数据到数据中心 + if (m_pGraphicBinder) { + m_pGraphicBinder->syncRegionData(this); + } + painter->save(); QVector pts = getPosOf(m_vecPoints); - if(m_regionData != nullptr) { - m_regionData->setRegionName(m_sName); - m_regionData->setVecPts(m_vecPoints); - - if(m_regionMark == nullptr) { - if(m_regionData->getRegionMarkData() != nullptr) - m_regionData->setRegionMarkData(nullptr); - - } else if(m_regionMark->getRegionMarkData() == nullptr) { - m_regionMark = nullptr; - m_regionData->setRegionMarkData(nullptr); - this->setBackgrdColor(QColor(0, 0, 0, 0)); - } else { - m_regionData->setRegionMarkData(m_regionMark->getRegionMarkData()); - } - - } - // 不选中的状态 if(!pts.empty()) { @@ -315,7 +311,7 @@ void nmObjRegion::paintBack(QPainter* painter, const ZxPaintParam& param) oPath.closeSubpath(); painter->fillPath(oPath, QBrush(m_clrBackgrd)); - // 判断标记区域对象的点是否存在 + // 判断标记区域对象的点是否仍在区域内 if(m_regionMark != nullptr) { QPointF ptPos = getValueOf(m_regionMark->getAllPos()[0]); @@ -324,7 +320,6 @@ void nmObjRegion::paintBack(QPainter* painter, const ZxPaintParam& param) if(!regionPolygon.containsPoint(ptPos, Qt::OddEvenFill)) { this->setBackgrdColor(QColor(0, 0, 0, 0)); m_regionMark->setSelectRegion(false); - m_regionMark->getRegionMarkData()->setSelectRegion(false); m_regionMark = nullptr; } } @@ -386,7 +381,7 @@ void nmObjRegion::paintBack(QPainter* painter, const ZxPaintParam& param) int nmObjRegion::getRegionFlowModel() { - if(m_regionData->getRegionFlowModel().getValue() == tr("Leaky")) + if(m_sFlowModel == tr("Leaky")) return 0; else return 1; @@ -394,29 +389,23 @@ int nmObjRegion::getRegionFlowModel() void nmObjRegion::setRegionFlowModel(int newRegionFlowModel) { - // 从Data中取数据 - nmDataAttribute tempAttr = m_regionData->getRegionFlowModel(); - if(newRegionFlowModel == 0) { - tempAttr.setValue(tr("Leaky")); + m_sFlowModel = tr("Leaky"); } else { - tempAttr.setValue(tr("Composite limit")); + m_sFlowModel = tr("Composite limit"); } - - m_regionData->setRegionFlowModel(tempAttr); + emit sigRegionFlowModelChanged(newRegionFlowModel); } double nmObjRegion::getRegionLeakage() { - return m_regionData->getRegionLeakage().getValue().toDouble(); + return m_dLeakage; } void nmObjRegion::setRegionLeakage(double newRegionLeakage) { - // 从Data中取数据 - nmDataAttribute tempAttr = m_regionData->getRegionLeakage(); - tempAttr.setValue(newRegionLeakage); - m_regionData->setRegionLeakage(tempAttr); + m_dLeakage = newRegionLeakage; + emit sigRegionLeakageChanged(newRegionLeakage); } void nmObjRegion::setRegionMark(nmObjRegionMark* newRegionMark) @@ -429,14 +418,11 @@ nmObjRegionMark* nmObjRegion::getRegionMark() const return m_regionMark; } -void nmObjRegion::setRegionData(nmDataRegion* newRegionData) -{ - m_regionData = newRegionData; -} - nmDataRegion* nmObjRegion::getRegionData() const { - return m_regionData; + if (m_pGraphicBinder) + return m_pGraphicBinder->getRegionDataFor(const_cast(this)); + return nullptr; } //鞋带公式计算多边形有向面积。 @@ -472,38 +458,23 @@ void nmObjRegion::reorderPointsToAntiClockwise() void nmObjRegion::afterCreated() { - m_regionData = nmDataAnalyzeManager::getCurrentInstance()->createRegion(); - // 初始化复合区基础数据 - m_regionData->setRegionName(m_sName); - // 在区域创建完成后,调用重新排序函数确保点的顺序为顺时针 reorderPointsToAntiClockwise(); - m_regionData->setVecPts(m_vecPoints); - - // 判断复合区是否被区域标记 - if(m_regionMark == nullptr) { - if(m_regionData->getRegionMarkData() != nullptr) - m_regionData->setRegionMarkData(nullptr); - - return; - } - - // 添加区域标记对象 - m_regionData->setRegionMarkData(m_regionMark->getRegionMarkData()); } void nmObjRegion::removeData() { - if(m_regionData) { - // 从数据中心移除该数据 - nmDataAnalyzeManager::getCurrentInstance()->removeRegionData(m_regionData); - m_regionData = nullptr; + if (m_pGraphicBinder) { + m_pGraphicBinder->removeRegionBinding(this); } } void nmObjRegion::onObjVisibleChanged(bool bIsVisible) { - if(m_regionData != nullptr) { - m_regionData->setPlotVisible(bIsVisible); + if (m_pGraphicBinder) { + nmDataRegion* pData = m_pGraphicBinder->getRegionDataFor(this); + if (pData) { + pData->setPlotVisible(bIsVisible); + } } } diff --git a/Src/nmNum/nmPlot/nmObjRegionTool.cpp b/Src/nmNum/nmPlot/nmObjRegionTool.cpp index 5dc98c5..846d2a6 100644 --- a/Src/nmNum/nmPlot/nmObjRegionTool.cpp +++ b/Src/nmNum/nmPlot/nmObjRegionTool.cpp @@ -6,6 +6,7 @@ #include "nmObjPointWell.h" #include "nmDataAnalyzeManager.h" +#include "nmDataRegion.h" #include "ZxPlot.h" diff --git a/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp b/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp index 44ac094..f6c89d2 100644 --- a/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp +++ b/Src/nmNum/nmPlot/nmPlotGraphicBinder.cpp @@ -12,6 +12,8 @@ #include "nmDataMeasure.h" #include "nmObjRegionMark.h" #include "nmDataRegionMark.h" +#include "nmObjRegion.h" +#include "nmDataRegion.h" #include "nmObjBase.h" #include "nmDataAnalyzeManager.h" @@ -105,6 +107,8 @@ void nmPlotGraphicBinder::updateDataMgr(nmDataAnalyzeManager* pDataMgr) m_mapMeasureData.clear(); m_mapRegionMarkData.clear(); m_setBoundRegionMarkGraphics.clear(); + m_mapRegionData.clear(); + m_setBoundRegionGraphics.clear(); m_pDataMgr = pDataMgr; } @@ -1106,3 +1110,201 @@ void nmPlotGraphicBinder::_pushRegionMarkDataToGraphic(nmObjRegionMark* pGraphic pGraphic->blockSignals(false); } + +// ==================== 复合区图元 ==================== + +// 用户画完复合区后,创建数据并建立绑定 +void nmPlotGraphicBinder::createRegionForGraphic(nmObjRegion* pGraphic) +{ + if (!pGraphic || !m_pDataMgr) { + return; + } + + // 创建数据对象 + nmDataRegion* pData = m_pDataMgr->createRegion(); + + // 将图元值推入数据 + pData->setRegionName(pGraphic->getName()); + pData->setVecPts(pGraphic->getAllValues()); + + // 流动模型 + nmDataAttribute flowModelAttr = pData->getRegionFlowModel(); + flowModelAttr.setValue(pGraphic->getRegionFlowModel() == 0 ? "Leaky" : "Composite limit"); + pData->setRegionFlowModel(flowModelAttr); + + // 泄漏系数 + nmDataAttribute leakageAttr = pData->getRegionLeakage(); + leakageAttr.setValue(pGraphic->getRegionLeakage()); + pData->setRegionLeakage(leakageAttr); + + // 建立映射 + m_mapRegionData[pGraphic] = pData; + pGraphic->setGraphicBinder(this); + + // 建立信号连接 + _connectRegion(pGraphic, pData); + + m_pDataMgr->notifyDataChanged(); +} + +// 从文件加载:绑定已有数据到已有图元 +void nmPlotGraphicBinder::bindRegionToGraphic(nmObjRegion* pGraphic, nmDataRegion* pData) +{ + if (!pGraphic || !pData) { + return; + } + + m_mapRegionData[pGraphic] = pData; + pGraphic->setGraphicBinder(this); + + _pushRegionDataToGraphic(pGraphic, pData); + _connectRegion(pGraphic, pData); +} + +// 删除复合区图元前,断开信号并清理映射 +void nmPlotGraphicBinder::removeRegionBinding(nmObjRegion* pGraphic) +{ + if (!pGraphic) { + return; + } + + _disconnectRegion(pGraphic); + + nmDataRegion* pData = m_mapRegionData.value(pGraphic, nullptr); + if (pData && m_pDataMgr) { + m_pDataMgr->removeRegionData(pData); + } + + m_mapRegionData.remove(pGraphic); +} + +// 兜底同步:名称、位置、区域标记关联(由 paintBack 调用) +void nmPlotGraphicBinder::syncRegionData(nmObjRegion* pGraphic) +{ + if (!pGraphic) return; + + nmDataRegion* pData = m_mapRegionData.value(pGraphic, nullptr); + if (!pData) return; + + // 兜底同步:名称、位置 + pData->setRegionName(pGraphic->getName()); + pData->setVecPts(pGraphic->getAllValues()); + + // 视觉属性兜底同步:画笔宽度、填充背景色 + QPen pen = pGraphic->getPen(); + if (pData->getPenWidth() != pen.widthF()) { + pData->setPenWidth(pen.widthF()); + } + QColor clr = pGraphic->getBackgrdColor(); + if (pData->getBackgrdColor() != clr) { + pData->setBackgrdColor(clr); + } + + // 区域标记关联 + nmObjRegionMark* pRegionMark = pGraphic->getRegionMark(); + if (pRegionMark) { + nmDataRegionMark* pMarkData = pRegionMark->getRegionMarkData(); + if (pMarkData) { + pData->setRegionMarkData(pMarkData); + } else { + // 区域标记图元存在但数据为空,清除关联 + pGraphic->setRegionMark(nullptr); + pData->setRegionMarkData(nullptr); + pGraphic->setBackgrdColor(QColor(0, 0, 0, 0)); + } + } else { + // 没有区域标记图元,清除数据关联 + if (pData->getRegionMarkData() != nullptr) { + pData->setRegionMarkData(nullptr); + } + } +} + +// 查找复合区图元对应的数据指针 +nmDataRegion* nmPlotGraphicBinder::getRegionDataFor(nmObjRegion* pGraphic) +{ + return m_mapRegionData.value(pGraphic, nullptr); +} + +// 复合区图元信号 → 数据同步 +void nmPlotGraphicBinder::onGraphicRegionFlowModelChanged(int model) +{ + nmObjRegion* pGraphic = dynamic_cast(sender()); + if (!pGraphic) return; + + nmDataRegion* pData = m_mapRegionData.value(pGraphic, nullptr); + if (!pData) return; + + nmDataAttribute attr = pData->getRegionFlowModel(); + if (model == 0) + attr.setValue("Leaky"); + else + attr.setValue("Composite limit"); + pData->setRegionFlowModel(attr); +} + +void nmPlotGraphicBinder::onGraphicRegionLeakageChanged(double leakage) +{ + nmObjRegion* pGraphic = dynamic_cast(sender()); + if (!pGraphic) return; + + nmDataRegion* pData = m_mapRegionData.value(pGraphic, nullptr); + if (!pData) return; + + nmDataAttribute attr = pData->getRegionLeakage(); + attr.setValue(leakage); + pData->setRegionLeakage(attr); +} + +// 建立信号连接 +void nmPlotGraphicBinder::_connectRegion(nmObjRegion* pGraphic, nmDataRegion* pData) +{ + if (!pGraphic || !pData) return; + if (m_setBoundRegionGraphics.contains(pGraphic)) return; + + connect(pGraphic, SIGNAL(sigRegionFlowModelChanged(int)), + this, SLOT(onGraphicRegionFlowModelChanged(int))); + connect(pGraphic, SIGNAL(sigRegionLeakageChanged(double)), + this, SLOT(onGraphicRegionLeakageChanged(double))); + + m_setBoundRegionGraphics.insert(pGraphic); +} + +// 断开信号连接 +void nmPlotGraphicBinder::_disconnectRegion(nmObjRegion* pGraphic) +{ + if (!pGraphic) return; + if (!m_setBoundRegionGraphics.contains(pGraphic)) return; + + disconnect(pGraphic, SIGNAL(sigRegionFlowModelChanged(int)), + this, SLOT(onGraphicRegionFlowModelChanged(int))); + disconnect(pGraphic, SIGNAL(sigRegionLeakageChanged(double)), + this, SLOT(onGraphicRegionLeakageChanged(double))); + + m_setBoundRegionGraphics.remove(pGraphic); +} + +// 从数据对象读取值,写入图元本地副本(加载时用) +void nmPlotGraphicBinder::_pushRegionDataToGraphic(nmObjRegion* pGraphic, nmDataRegion* pData) +{ + if (!pGraphic || !pData) return; + + pGraphic->blockSignals(true); + + // 流动模型:字符串 → int + if (pData->getRegionFlowModel().getValue() == "Leaky") { + pGraphic->setRegionFlowModel(0); + } else { + pGraphic->setRegionFlowModel(1); + } + + pGraphic->setRegionLeakage(pData->getRegionLeakage().getValue().toDouble()); + + // 视觉属性:画笔宽度、填充背景色 + QPen pen = pGraphic->getPen(); + pen.setWidthF(pData->getPenWidth()); + pGraphic->setPen(pen); + pGraphic->setBackgrdColor(pData->getBackgrdColor()); + + pGraphic->blockSignals(false); +} \ No newline at end of file