解耦新建井图元

feature/nm-para-property-20260615
lvjunjie 1 week ago
parent be701c29e2
commit 3df19d5568

@ -3,11 +3,10 @@
#include "nmObjPoint.h"
#include "nmDefines.h"
#include "nmPlot_global.h"
#include "ZxDataWell.h"
#include "ZxObjText.h"
class nmDataWellBase;
class nmPlotGraphicBinder;
class ZxDataWell;
class ZxObjText;
// 数值试井绘图对象(点)
class NM_PLOT_EXPORT nmObjPointWell : public nmObjPoint {
@ -75,13 +74,10 @@ class NM_PLOT_EXPORT nmObjPointWell : public nmObjPoint {
// 删除当前对象里的参数对象
virtual void removeData() override;
// 设置当前井来自数据中心的井数据
void setNmWellData(nmDataWellBase* wellData);
// 获取当前井数据
nmDataWellBase* getNmWellData();
void setGraphicBinder(nmPlotGraphicBinder* pBinder) { m_pGraphicBinder = pBinder; }
nmPlotGraphicBinder* getGraphicBinder() const { return m_pGraphicBinder; }
// 标记井数据已由Binder绑定图元只保留井类型
void markWellDataBound(NM_WELL_MODEL wellType);
public slots:
// 图元状态改变
@ -97,9 +93,6 @@ class NM_PLOT_EXPORT nmObjPointWell : public nmObjPoint {
ZxObjText* m_pNameLabel;
bool m_bSelectWell;
QString m_sWellID;
ZxDataWell* m_pWellData;
nmDataWellBase* m_pNmWellData; // 自定义井数据
nmPlotGraphicBinder* m_pGraphicBinder; // 图元-数据绑定协调器

@ -3,6 +3,9 @@
#include <QObject>
#include <QMap>
#include <QSet>
#include <QPair>
#include <QVector>
#include <QPointF>
#include "nmPlot_global.h"
#include "nmDefines.h"
@ -25,6 +28,8 @@ class nmDataRegion;
class nmObjRegion;
class nmDataWellBase;
class nmObjPointWell;
class ZxDataWell;
class ZxObjText;
// 图元与数据绑定协调器,由 nmGuiPlot 托管
class NM_PLOT_EXPORT nmPlotGraphicBinder : public QObject
@ -148,6 +153,35 @@ public:
// 查找井图元对应的数据指针
nmDataWellBase* getWellDataFor(nmObjPointWell* pGraphic);
// 井图元绘制所需的只读数据快照
struct WellRenderData {
WellRenderData();
bool valid;
NM_WELL_MODEL wellType;
double x;
double y;
double radius;
double wellLength;
double drainAngle;
QVector<QPointF> verticalFracs;
QVector<QPair<QPointF, QPointF>> horizontalFracs;
};
// 判断井图元是否已绑定井数据
bool hasWellDataFor(nmObjPointWell* pGraphic) const;
// 判断井图元是否为当前分析井
bool isCurrentWellGraphic(nmObjPointWell* pGraphic) const;
// 图元移动后,同步井位置及裂缝位置
void syncWellMoveFromGraphic(nmObjPointWell* pGraphic, NM_WELL_MODEL wellType, const QPointF& newLocation);
// 选择已有井后,确保图元已创建并绑定对应的井数据
bool ensureSelectedWellData(nmObjPointWell* pGraphic, NM_WELL_MODEL& wellType);
// 编辑井属性,并将结果同步到框架井数据和数值井数据
bool editWellForGraphic(nmObjPointWell* pGraphic, NM_WELL_MODEL& wellType, ZxObjText* pNameLabel);
// 获取井图元绘制所需的数据快照
WellRenderData getWellRenderData(nmObjPointWell* pGraphic) const;
// 同步井图元可见性到井数据
void setWellVisible(nmObjPointWell* pGraphic, bool bVisible);
// 更新井图元的数据映射(编辑井后更换数据对象时使用)
void updateWellDataMapping(nmObjPointWell* pGraphic, nmDataWellBase* pNewData) { m_mapWellData[pGraphic] = pNewData; }

@ -57,6 +57,8 @@
#include "nmPlotGraphicBinder.h"
#include "ZxDataWell.h"
#include "ZxDataGaugeP.h"
#include "ZxDataGaugeF.h"
@ -900,7 +902,7 @@ void nmGuiPlot::slotDeleteWell(QString wellID)
}
// 当前井作为活动分析井保留,不允许从地图中直接删除
if(obj->getNmWellData() == nmDataAnalyzeManager::getCurrentInstance()->getCurWellData()) {
if(m_pGraphicBinder && m_pGraphicBinder->isCurrentWellGraphic(obj)) {
return;
}
@ -1365,9 +1367,7 @@ void nmGuiPlot::slotDeleteOneObj(QString sName, void* obj)
}
if(nmObjPointWell* pWellObj = dynamic_cast<nmObjPointWell*>(nmObj)) {
nmDataWellBase* pCurWell = nmDataAnalyzeManager::getCurrentInstance()->getCurWellData();
if(pWellObj->getNmWellData() == pCurWell) {
if(m_pGraphicBinder && m_pGraphicBinder->isCurrentWellGraphic(pWellObj)) {
if(pDeleteTool) {
m_pPlot->removeTools(pDeleteTool);
}

@ -10,6 +10,7 @@
#include "ZxPlot.h"
#include "ZxObjText.h"
#include "ZxDataWell.h"
#include "nmObjPointWellTool.h"
#include "nmObjPointWell.h"
@ -17,7 +18,6 @@
#include "nmDataLogFile.h"
#include "iWxWellNew.h"
#include "ZxBaseUtil.h"
#include "ZxDataProject.h"
#include "TreeWxMain.h"
@ -30,16 +30,6 @@
#include "nmPlotGraphicBinder.h"
#include "ZxDataGaugeP.h"
#include "ZxDataGaugeF.h"
#include "nmPlotDialogContext.h"
#include "nmPlotDialogContextProvider.h"
#include "nmDataVerticalFracturedWell.h"
#include "nmDataHorizontalFracturedWell.h"
#include "nmDataVerticalWell.h"
#include "nmDataWellBase.h"
ZX_DEFINE_DYNAMIC(nObjPointWell, nmObjPointWell)
@ -47,8 +37,6 @@ nmObjPointWell::nmObjPointWell()
: nmObjPoint()
, m_pNameLabel(nullptr)
, m_bSelectWell(false)
, m_pWellData(nullptr)
, m_pNmWellData(nullptr)
, m_pGraphicBinder(nullptr)
, m_enumWellType(NM_WELL_MODEL::Vertical_Well)
{
@ -61,8 +49,6 @@ nmObjPointWell::nmObjPointWell(const QString& sName, \
: nmObjPoint(sName, pAxisX, pAxisY)
, m_pNameLabel(nullptr)
, m_bSelectWell(false)
, m_pWellData(nullptr)
, m_pNmWellData(nullptr)
, m_pGraphicBinder(nullptr)
, m_enumWellType(NM_WELL_MODEL::Vertical_Well)
{
@ -71,8 +57,7 @@ nmObjPointWell::nmObjPointWell(const QString& sName, \
nmObjPointWell::~nmObjPointWell()
{
// 井数据由DataManager统一释放图元只保存引用。
m_pNmWellData = nullptr;
// 井数据由 DataManager 和工程树统一管理,图元不持有数据指针。
}
void nmObjPointWell::init(const QString& sName, \
@ -91,7 +76,6 @@ void nmObjPointWell::init(const QString& sName, \
m_vecPoints << QPointF(0.f, 0.f);
loadTempl();
m_pNmWellData = nullptr;
m_pGraphicBinder = nullptr;
// 连接图元可见性信号和槽
@ -110,32 +94,9 @@ bool nmObjPointWell::runMove(const QPointF &pt1, const QPointF &pt2)
nmObjPoint::runMove(pt1, pt2);
// 更新井的位置信息
if(m_pWellData && m_pNmWellData) {
if(m_pGraphicBinder) {
QPointF newLocation = this->getValueOf(pt2);
m_pWellData->setLocationX(newLocation.x());
m_pWellData->setLocationY(newLocation.y());
// 更新井基础信息
nmDataAttribute tempAttr = m_pNmWellData->getX();
tempAttr.setValue(m_pWellData->getLocationX());
m_pNmWellData->setX(tempAttr);
tempAttr = m_pNmWellData->getY();
tempAttr.setValue(m_pWellData->getLocationY());
m_pNmWellData->setY(tempAttr);
tempAttr = m_pNmWellData->getRadius();
tempAttr.setValue(m_pWellData->getWellRadius());
m_pNmWellData->setRadius(tempAttr);
// 对于裂缝类型的井,需要更新裂缝位置
if (m_enumWellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
if (nmDataVerticalFracturedWell* pVFWell = dynamic_cast<nmDataVerticalFracturedWell*>(m_pNmWellData)) {
pVFWell->setFracs();
}
} else if (m_enumWellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
if (nmDataHorizontalFracturedWell* pHFWell = dynamic_cast<nmDataHorizontalFracturedWell*>(m_pNmWellData)) {
pHFWell->setFracs();
}
}
m_pGraphicBinder->syncWellMoveFromGraphic(this, m_enumWellType, newLocation);
}
if (m_pGraphicBinder) {
@ -177,15 +138,12 @@ void nmObjPointWell::onDeserialize(ZxSerializer* ser)
nmObjBase::onDeserialize(ser);
ser->read("NMWellID", m_sWellID);
// 根据wellID获取井的信息
m_pWellData = nullptr;
if (zxCurProject != nullptr) {
m_pWellData = (ZxDataWell*)zxCurProject->getChild(iDataModelType::sTypeWell, m_sWellID);
}
ZxDataWell* pWellData = getWellData();
if(m_pWellData) {
if(pWellData) {
// 设置图元的位置信息将井的坐标设置为plot对象的坐标
m_vecPoints.clear();
m_vecPoints << QPointF(m_pWellData->getLocationX(), m_pWellData->getLocationY());
m_vecPoints << QPointF(pWellData->getLocationX(), pWellData->getLocationY());
return;
}
@ -203,15 +161,12 @@ void nmObjPointWell::onLoadTempl(ZxSerializer* ser)
nmObjBase::onLoadTempl(ser);
ser->read("NMWellID", m_sWellID);
// 根据wellID获取井的信息
m_pWellData = nullptr;
if (zxCurProject != nullptr) {
m_pWellData = (ZxDataWell*)zxCurProject->getChild(iDataModelType::sTypeWell, m_sWellID);
}
ZxDataWell* pWellData = getWellData();
if(m_pWellData) {
if(pWellData) {
// 设置图元的位置信息将井的坐标设置为plot对象的坐标
m_vecPoints.clear();
m_vecPoints << QPointF(m_pWellData->getLocationX(), m_pWellData->getLocationY());
m_vecPoints << QPointF(pWellData->getLocationX(), pWellData->getLocationY());
return;
}
@ -221,11 +176,12 @@ void nmObjPointWell::onLoadTempl(ZxSerializer* ser)
void nmObjPointWell::afterCreated()
{
if(m_pWellData) {
ZxDataWell* pWellData = getWellData();
if(pWellData) {
ZxPlot* pPlot = dynamic_cast<ZxPlot*>(this->getParent());
if(NULL != pPlot) {
QString sName = m_pWellData->getName();
QString sName = pWellData->getName();
this->setName(sName);
ZxObjBase* p = pPlot->addOneObj(POT_Text, sName, false, \
m_pAxisX, m_pAxisY);
@ -254,144 +210,19 @@ void nmObjPointWell::afterCreated()
// 如果是选择的井则不弹出创建的dialog
if(m_bSelectWell) {
// 判断是哪一种井类型,初始化对应的参数
ZxDataWell* pWellData = m_pWellData;
// 选择已有井时通过Binder初始化对应的井数据
if (pWellData == nullptr) {
return;
}
QString wellClass = m_pWellData->getWellClassEn();
// 获取当前井的压力、流量数据
ZxDataObjectList m_listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP);
ZxDataObjectList m_listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF);
ZxDataGaugeP* pGaugeP = nullptr;
ZxDataGaugeF* pGaugeF = nullptr;
// 遍历压力数据列表
for(int i = 0; i < m_listGaugeP.size(); ++i) {
if(pGaugeP = dynamic_cast<ZxDataGaugeP * >(m_listGaugeP[i])) { // 拿到第一条压力数据
break;
}
}
// 遍历流量数据列表
for(int i = 0; i < m_listGaugeF.size(); ++i) {
if(pGaugeF = dynamic_cast<ZxDataGaugeF * >(m_listGaugeF[i])) { // 拿到第一条流量数据
break;
}
}
// 获取的压力、流量数据
QVector<QPointF> vecPtsP, vecPtsF;
vecPtsP.clear();
vecPtsF.clear();
// 临时存储xy坐标
VecDouble vecX, vecY;
if(pGaugeP != nullptr) {
// 获取压力数据
if(pGaugeP->getDataVecXY(vecX, vecY)) {
for(int i = 0; i < vecX.size(); ++i) {
if(i < vecY.size()) {
QPointF pt(vecX[i], vecY[i]);
vecPtsP.append(pt);
}
}
}
}
if(pGaugeF != nullptr) {
vecX.clear();
vecY.clear();
// 获取流量数据
if(pGaugeF->getDataVecXY(vecX, vecY)) {
for(int i = 0; i < vecX.size(); ++i) {
if(i < vecY.size()) {
QPointF pt(vecX[i], vecY[i]);
vecPtsF.append(pt);
}
}
}
}
int nIndexF = -2; //当前井的流动段索引
// 判断是否为当前井
if(m_pWellData != zxCurWell) {
// 更新当前井的流动段的索引,默认为最后一段
nIndexF = vecPtsF.count() - 1;
}
if(ZxBaseUtil::isSameStr(wellClass, "VerticalWell")) {
// 切换当前井类型
m_enumWellType = NM_WELL_MODEL::Vertical_Well;
} else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) {
// 切换当前井类型
m_enumWellType = NM_WELL_MODEL::Vertical_Fractured_Well;
} else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) {
// 切换当前井类型
m_enumWellType = NM_WELL_MODEL::Horizontal_Fractured_Well;
} else {
if (m_pGraphicBinder == nullptr ||
!m_pGraphicBinder->ensureSelectedWellData(this, m_enumWellType)) {
return;
}
// 如果已有井数据(文件加载时通过 bindWellToGraphic 绑定),则跳过创建
if (m_pNmWellData == nullptr) {
m_pNmWellData = m_pGraphicBinder->createWellForGraphic(this, m_enumWellType);
if (m_pNmWellData == nullptr) {
return;
}
m_pNmWellData->setWellName(m_pWellData->getName());
nmDataAttribute tempAttr = m_pNmWellData->getX();
tempAttr.setValue(m_pWellData->getLocationX());
m_pNmWellData->setX(tempAttr);
tempAttr = m_pNmWellData->getY();
tempAttr.setValue(m_pWellData->getLocationY());
m_pNmWellData->setY(tempAttr);
tempAttr = m_pNmWellData->getRadius();
tempAttr.setValue(m_pWellData->getWellRadius());
m_pNmWellData->setRadius(tempAttr);
// 设置井的压力数据、流量数据
m_pNmWellData->setPressurePoints(vecPtsP);
m_pNmWellData->setFlowPoints(vecPtsF);
// 设置井的流动段,默认为最后一段
if(nIndexF >= -1) {
m_pNmWellData->setIndexF(nIndexF);
}
// 对于裂缝类型的井,需要更新裂缝位置
if (m_enumWellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
if (nmDataVerticalFracturedWell* pVFWell = dynamic_cast<nmDataVerticalFracturedWell*>(m_pNmWellData)) {
pVFWell->setFracs();
}
} else if (m_enumWellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
if (nmDataHorizontalFracturedWell* pHFWell = dynamic_cast<nmDataHorizontalFracturedWell*>(m_pNmWellData)) {
pHFWell->setFracs();
}
}
// TODO: 计算井的历史双对数/半对数数据
QVector<QVector<double>> vvecHistoryPressureData;
QVector<QVector<double>> vvecHistoryLogData;
QVector<QVector<double>> vvecHistorySemiLogData;
m_pGraphicBinder->calculateWellLogData(m_pNmWellData, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
// 存储历史数据到井对象
m_pNmWellData->setHistoryPressure(vvecHistoryPressureData);
m_pNmWellData->setHistoryLogLog(vvecHistoryLogData);
m_pNmWellData->setHistorySemiLog(vvecHistorySemiLogData);
}
return;
}
if(m_pWellData == nullptr) {
if(pWellData == nullptr) {
this->createWell();
}
}
@ -400,8 +231,7 @@ void nmObjPointWell::setWellData(ZxDataWell *wellObj)
{
if(wellObj) {
m_bSelectWell = true;
m_pWellData = wellObj;
m_sWellID = m_pWellData->getCode();
m_sWellID = wellObj->getCode();
}
}
@ -428,19 +258,18 @@ void nmObjPointWell::createWell()
pWellDialog->setActionMode(DAM_Edit);
// 初始化UI
pWellDialog->initUI();
// 图元保存井数据
// 图元保存井ID
m_sWellID = pWellData->getCode();
m_pWellData = pWellData;
// 模态展示
if(pWellDialog->exec() == QDialog::Rejected) {
// TODO如果是 选择的井,则直接删除画布上的图元
// TODO如果是 新建的井,删除图元 + 井数据!
// TODO如果是选择的井,则直接删除画布上的图元
// TODO如果是新建的井,删除图元 + 井数据!
nmSingalCenter::getInstance()->emitSigDeleteWell(sCode);
} else {
// 将数据做转换,然后移动到指定的位置
QVector<QPointF> vecPoss;
vecPoss << QPointF(m_pWellData->getLocationX(), m_pWellData->getLocationY());
vecPoss << QPointF(pWellData->getLocationX(), pWellData->getLocationY());
nmDataLogFile::getInstance()->writeLog(" =========== " + QString::number(vecPoss[0].x()) + " " + QString::number(
vecPoss[0].y()));
// 将数据做转换,然后移动到指定的位置
@ -456,84 +285,24 @@ void nmObjPointWell::createWell()
void nmObjPointWell::editWell()
{
// 如果没有层数据,提示用户定义分层信息
if(m_pGraphicBinder && !m_pGraphicBinder->hasLayers()) {
QMessageBox::information(nullptr, tr("error"), tr("please setting layers Data!"));
return;
}
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
if(pDialogProvider == nullptr) {
if (m_pGraphicBinder == nullptr) {
return;
}
nmDataWellBase* pReturnWellData = nullptr;
if(pDialogProvider->editWell(nullptr, m_pWellData, m_pNmWellData, pReturnWellData)) {
// 获取修改后的井数据
if (pReturnWellData == nullptr || m_pWellData == nullptr || m_pNmWellData == nullptr) {
return;
}
// 更新ZxDataWell的数据
m_pWellData->setName(pReturnWellData->getWellName());
this->setName(pReturnWellData->getWellName());
m_pWellData->setLocationX(pReturnWellData->getX().getValue().toDouble());
m_pWellData->setLocationY(pReturnWellData->getY().getValue().toDouble());
m_pWellData->setWellRadius(pReturnWellData->getRadius().getValue().toDouble());
NM_WELL_MODEL eWellType = pReturnWellData->getWellType();
// 修改了井类型,就重新设置
if (eWellType != m_enumWellType)
{
m_enumWellType = eWellType;
QString sWellClass;
if (m_enumWellType == NM_WELL_MODEL::Vertical_Well)
{
sWellClass = "VerticalWell";
} else if(m_enumWellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
sWellClass = "VerticalFracturedWell";
} else if(m_enumWellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
sWellClass = "HorizontalFracturedWell";
}
m_pWellData->setWellClassCn(sWellClass);
}
if (m_pNameLabel != nullptr) {
m_pNameLabel->setText(pReturnWellData->getWellName());
}
// 根据新坐标进行移动
QVector<QPointF> vecPoss;
vecPoss << QPointF(m_pWellData->getLocationX(), m_pWellData->getLocationY());
if(m_pGraphicBinder->editWellForGraphic(this, m_enumWellType, m_pNameLabel)) {
ZxDataWell* pWellData = getWellData();
if (pWellData != nullptr) {
// 根据新坐标进行移动
QVector<QPointF> vecPoss;
vecPoss << QPointF(pWellData->getLocationX(), pWellData->getLocationY());
// 将数据做转换,然后移动到指定的位置
this->setAllPos(vecPoss);
moveToPos(this->getPosOf(this->getAllPos()));
// 判断是不是当前查看的井
nmDataWellBase* pCurWellData = m_pGraphicBinder->getCurrentWellData();
if (pCurWellData != nullptr && pCurWellData->getWellName() == m_pNmWellData->getWellName())
{
// 设置到当前井
m_pGraphicBinder->setCurrentWellData(pReturnWellData);
// 将数据做转换,然后移动到指定的位置
this->setAllPos(vecPoss);
moveToPos(this->getPosOf(this->getAllPos()));
}
// 更新当前井数据,并添加到数据中心
m_pGraphicBinder->removeWellData(m_pNmWellData);
if (m_pNmWellData != nullptr)
{
m_pNmWellData = nullptr;
}
m_pNmWellData = pReturnWellData;
m_pGraphicBinder->appendWellData(m_pNmWellData);
m_pGraphicBinder->updateWellDataMapping(this, m_pNmWellData);
}
if (m_pGraphicBinder) {
m_pGraphicBinder->notifyDataChanged();
}
m_pGraphicBinder->notifyDataChanged();
this->update();
}
@ -541,11 +310,12 @@ void nmObjPointWell::editWell()
QVector<double> nmObjPointWell::getWellInformation()
{
QVector<double> wellInformation;
ZxDataWell* pWellData = getWellData();
if(m_pWellData) {
wellInformation.append(m_pWellData->getLocationX());
wellInformation.append(m_pWellData->getLocationY());
wellInformation.append(m_pWellData->getWellRadius());
if(pWellData) {
wellInformation.append(pWellData->getLocationX());
wellInformation.append(pWellData->getLocationY());
wellInformation.append(pWellData->getWellRadius());
}
return wellInformation;
@ -553,7 +323,10 @@ QVector<double> nmObjPointWell::getWellInformation()
ZxDataWell* nmObjPointWell::getWellData() const
{
return m_pWellData;
if (zxCurProject == nullptr) {
return nullptr;
}
return dynamic_cast<ZxDataWell*>(zxCurProject->getChild(iDataModelType::sTypeWell, m_sWellID));
}
const QString& nmObjPointWell::getWellID() const
@ -575,13 +348,18 @@ void nmObjPointWell::paintBack(QPainter* painter, const ZxPaintParam& param)
}
}
if (m_pWellData == nullptr) {
if (m_pGraphicBinder == nullptr) {
return;
}
nmPlotGraphicBinder::WellRenderData renderData = m_pGraphicBinder->getWellRenderData(this);
if (!renderData.valid) {
return;
}
QString wellClass = m_pWellData->getWellClassEn();
m_enumWellType = renderData.wellType;
if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell") && m_pNmWellData != nullptr) { // 编辑完井之后
if(renderData.wellType == NM_WELL_MODEL::Vertical_Fractured_Well) { // 编辑完井之后
Q_ASSERT(NULL != m_pAxisX);
Q_ASSERT(NULL != m_pAxisY);
@ -592,31 +370,13 @@ void nmObjPointWell::paintBack(QPainter* painter, const ZxPaintParam& param)
painter->save();
double locX = m_pNmWellData->getX().getValue().toDouble();
double locY = m_pNmWellData->getY().getValue().toDouble();
double rad = m_pNmWellData->getRadius().getValue().toDouble();
m_vecPoints[0].setX(locX);
m_vecPoints[0].setY(locY);
m_pWellData->setLocationX(locX);
m_pWellData->setLocationY(locY);
m_pWellData->setWellRadius(rad);
double x = m_pWellData->getLocationX();
double y = m_pWellData->getLocationY();
QPointF point(x, y);
QPointF point(renderData.x, renderData.y);
m_vecPoints[0] = point;
QPointF ptPos = getPosOf(point);
moveToPos(this->getPosOf(m_vecPoints));
nmDataVerticalFracturedWell* pVFWell = dynamic_cast<nmDataVerticalFracturedWell*>(m_pNmWellData);
if (pVFWell == nullptr) {
painter->restore();
return;
}
// 绘制填充
double r = m_oDot.radius();
@ -642,16 +402,15 @@ void nmObjPointWell::paintBack(QPainter* painter, const ZxPaintParam& param)
painter->setPen(fracturePen);
// 绘制裂缝
QVector<QPointF> vecFracs = pVFWell->getFracs();
if (vecFracs.size() == 2) {
QPointF startPos = getPosOf(vecFracs[0]);
QPointF endPos_frac = getPosOf(vecFracs[1]);
if (renderData.verticalFracs.size() == 2) {
QPointF startPos = getPosOf(renderData.verticalFracs[0]);
QPointF endPos_frac = getPosOf(renderData.verticalFracs[1]);
painter->drawLine(startPos, endPos_frac);
}
painter->restore();
} else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell") && m_pNmWellData != nullptr) {
} else if(renderData.wellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
Q_ASSERT(NULL != m_pAxisX);
Q_ASSERT(NULL != m_pAxisY);
@ -662,45 +421,27 @@ void nmObjPointWell::paintBack(QPainter* painter, const ZxPaintParam& param)
painter->save();
double locX = m_pNmWellData->getX().getValue().toDouble();
double locY = m_pNmWellData->getY().getValue().toDouble();
double rad = m_pNmWellData->getRadius().getValue().toDouble();
m_vecPoints[0].setX(locX);
m_vecPoints[0].setY(locY);
m_pWellData->setLocationX(locX);
m_pWellData->setLocationY(locY);
m_pWellData->setWellRadius(rad);
double x = m_pWellData->getLocationX();
double y = m_pWellData->getLocationY();
QPointF point(x, y);
QPointF point(renderData.x, renderData.y);
m_vecPoints[0] = point;
QPointF ptPos = getPosOf(point);
moveToPos(this->getPosOf(m_vecPoints));
nmDataHorizontalFracturedWell* pHFWell = dynamic_cast<nmDataHorizontalFracturedWell*>(m_pNmWellData);
if (pHFWell == nullptr) {
painter->restore();
return;
}
// 获取井长
double wellLength = pHFWell->getWellLength().getValue().toDouble();
double wellLength = renderData.wellLength;
// 获取井的角度
double drainAngle = pHFWell->getDrainAngle().getValue().toDouble();
double drainAngle = renderData.drainAngle;
// 将角度从度转换为弧度
double angleRad = drainAngle * M_PI / 180.0; // M_PI 是 π 的值,表示 180 度
double angleRad = drainAngle * M_PI / 180.0; // M_PI 是π的值,表示 180 度
// 获取裂缝角度(单位:度)
//double fractureAngle = m_HFracturedWell->getFractureAngle().getValue().toDouble();
//double fractureAngleRad = fractureAngle * M_PI / 180.0; // 转换为弧度
// 计算井的终点坐标
double endX = x + wellLength * cos(angleRad);
double endY = y + wellLength * sin(angleRad);
double endX = renderData.x + wellLength * cos(angleRad);
double endY = renderData.y + wellLength * sin(angleRad);
QPointF endPoint(endX, endY);
QPointF endPos = getPosOf(endPoint);
@ -730,16 +471,14 @@ void nmObjPointWell::paintBack(QPainter* painter, const ZxPaintParam& param)
// 井筒
painter->drawLine(ptPos, endPos);
// 获取预先计算好的裂缝坐标
QVector<QPair<QPointF, QPointF>>& vecFracs = pHFWell->getFracs();
// 设置裂缝的画笔
QPen fracturePen(QColor(255, 0, 0));
fracturePen.setWidth(0.3f);
painter->setPen(fracturePen);
// 遍历并绘制所有裂缝
foreach (const auto& frac , vecFracs) {
for(int i = 0; i < renderData.horizontalFracs.size(); ++i) {
const QPair<QPointF, QPointF>& frac = renderData.horizontalFracs.at(i);
// 将世界坐标转换为绘图坐标
QPointF startPos = getPosOf(frac.first);
QPointF endPos_frac = getPosOf(frac.second);
@ -750,20 +489,8 @@ void nmObjPointWell::paintBack(QPainter* painter, const ZxPaintParam& param)
painter->restore();
} else { //其他
if(m_pNmWellData != nullptr) {
double locX = m_pNmWellData->getX().getValue().toDouble();
double locY = m_pNmWellData->getY().getValue().toDouble();
double rad = m_pNmWellData->getRadius().getValue().toDouble();
m_vecPoints[0].setX(locX);
m_vecPoints[0].setY(locY);
m_pWellData->setLocationX(locX);
m_pWellData->setLocationY(locY);
m_pWellData->setWellRadius(rad);
moveToPos(this->getPosOf(m_vecPoints));
}
m_vecPoints[0] = QPointF(renderData.x, renderData.y);
moveToPos(this->getPosOf(m_vecPoints));
nmObjPoint::paintBack(painter, param);
}
@ -774,39 +501,17 @@ void nmObjPointWell::removeData()
if (m_pGraphicBinder) {
m_pGraphicBinder->removeWellBinding(this);
}
m_pNmWellData = nullptr;
}
void nmObjPointWell::setNmWellData(nmDataWellBase* wellData)
void nmObjPointWell::markWellDataBound(NM_WELL_MODEL wellType)
{
// 如果是外界设置了当前图元绑定的井数据则不需要再次在afterCreated()函数中再次设置数据
m_bSelectWell = false;
m_pNmWellData = wellData;
if (m_pWellData) {
QString wellClass = m_pWellData->getWellClassEn();
if(ZxBaseUtil::isSameStr(wellClass, "VerticalWell")) {
m_enumWellType = NM_WELL_MODEL::Vertical_Well;
} else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) {
m_enumWellType = NM_WELL_MODEL::Vertical_Fractured_Well;
} else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) {
m_enumWellType = NM_WELL_MODEL::Horizontal_Fractured_Well;
}
}
}
nmDataWellBase* nmObjPointWell::getNmWellData()
{
return m_pNmWellData;
m_enumWellType = wellType;
}
void nmObjPointWell::onObjVisibleChanged(bool bIsVisible)
{
if (m_pGraphicBinder) {
nmDataWellBase* pData = m_pGraphicBinder->getWellDataFor(this);
if (pData) {
pData->setPlotVisible(bIsVisible);
}
m_pGraphicBinder->setWellVisible(this, bIsVisible);
}
}

@ -18,9 +18,32 @@
#include "nmDataAnalyzeManager.h"
#include "nmObjPointWell.h"
#include "nmDataWellBase.h"
#include "nmDataVerticalFracturedWell.h"
#include "nmDataHorizontalFracturedWell.h"
#include "nmPlotDialogContext.h"
#include "nmPlotDialogContextProvider.h"
#include "ZxDataWell.h"
#include "ZxObjText.h"
#include "ZxDataGaugeP.h"
#include "ZxDataGaugeF.h"
#include "ZxBaseUtil.h"
#include "Defines.h"
#include "iDataTypes.h"
#include "zxSysUtils.h"
#include <QMetaObject>
#include <QMessageBox>
nmPlotGraphicBinder::WellRenderData::WellRenderData()
: valid(false)
, wellType(Vertical_Well)
, x(0.0)
, y(0.0)
, radius(0.0)
, wellLength(0.0)
, drainAngle(0.0)
{
}
nmPlotGraphicBinder::nmPlotGraphicBinder(nmDataAnalyzeManager* pDataMgr, QObject* parent)
: QObject(parent)
, m_pDataMgr(pDataMgr)
@ -1324,8 +1347,10 @@ nmDataWellBase* nmPlotGraphicBinder::createWellForGraphic(nmObjPointWell* pGraph
nmDataWellBase* pData = m_pDataMgr->createWell(wellType);
// 建立图元到数值井数据的映射图元后续只通过Binder访问井数据。
m_mapWellData[pGraphic] = pData;
pGraphic->setGraphicBinder(this);
pGraphic->markWellDataBound(wellType);
_connectWell(pGraphic, pData);
@ -1371,6 +1396,7 @@ void nmPlotGraphicBinder::syncWellData(nmObjPointWell* pGraphic)
nmDataWellBase* pData = m_mapWellData.value(pGraphic, nullptr);
if (!pData) return;
ZxDataWell* pWellData = pGraphic->getWellData();
// 同步名称(用户在属性面板改名后,同步到数据中心和框架数据)
QString sName = pGraphic->getName();
@ -1378,13 +1404,19 @@ void nmPlotGraphicBinder::syncWellData(nmObjPointWell* pGraphic)
if (pData->getWellName() != sName) {
pData->setWellName(sName);
}
ZxDataWell* pWellData = pGraphic->getWellData();
if (pWellData && pWellData->getName() != sName) {
pWellData->setName(sName);
pWellData->save();
}
}
if (pWellData) {
// 数值井数据是分析侧的数据源,这里回写到框架井数据,保证保存工程树时一致。
pWellData->setLocationX(pData->getX().getValue().toDouble());
pWellData->setLocationY(pData->getY().getValue().toDouble());
pWellData->setWellRadius(pData->getRadius().getValue().toDouble());
}
// 同步图元外观属性到井数据(用于保存到 JSON
ZxDot dot = pGraphic->getDot();
pData->setDotStyle(static_cast<int>(dot.style()));
@ -1401,6 +1433,272 @@ nmDataWellBase* nmPlotGraphicBinder::getWellDataFor(nmObjPointWell* pGraphic)
return m_mapWellData.value(pGraphic, nullptr);
}
bool nmPlotGraphicBinder::hasWellDataFor(nmObjPointWell* pGraphic) const
{
return m_mapWellData.value(pGraphic, nullptr) != nullptr;
}
bool nmPlotGraphicBinder::isCurrentWellGraphic(nmObjPointWell* pGraphic) const
{
if (!m_pDataMgr || !pGraphic) return false;
return m_mapWellData.value(pGraphic, nullptr) == m_pDataMgr->getCurWellData();
}
void nmPlotGraphicBinder::syncWellMoveFromGraphic(nmObjPointWell* pGraphic,
NM_WELL_MODEL wellType,
const QPointF& newLocation)
{
if (!pGraphic) return;
ZxDataWell* pWellData = pGraphic->getWellData();
if (!pWellData) return;
nmDataWellBase* pData = m_mapWellData.value(pGraphic, nullptr);
if (!pData) return;
// 图元拖动先更新框架井数据,再同步到数值井数据。
pWellData->setLocationX(newLocation.x());
pWellData->setLocationY(newLocation.y());
nmDataAttribute tempAttr = pData->getX();
tempAttr.setValue(pWellData->getLocationX());
pData->setX(tempAttr);
tempAttr = pData->getY();
tempAttr.setValue(pWellData->getLocationY());
pData->setY(tempAttr);
tempAttr = pData->getRadius();
tempAttr.setValue(pWellData->getWellRadius());
pData->setRadius(tempAttr);
if (wellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
// 裂缝井位置变化后,裂缝端点需要跟着重新计算。
if (nmDataVerticalFracturedWell* pVFWell = dynamic_cast<nmDataVerticalFracturedWell*>(pData)) {
pVFWell->setFracs();
}
} else if (wellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
// 水平裂缝井同样依赖井筒位置重新计算裂缝几何。
if (nmDataHorizontalFracturedWell* pHFWell = dynamic_cast<nmDataHorizontalFracturedWell*>(pData)) {
pHFWell->setFracs();
}
}
}
bool nmPlotGraphicBinder::ensureSelectedWellData(nmObjPointWell* pGraphic,
NM_WELL_MODEL& wellType)
{
if (!pGraphic) return false;
ZxDataWell* pWellData = pGraphic->getWellData();
if (!pWellData) return false;
nmDataWellBase* pData = m_mapWellData.value(pGraphic, nullptr);
if (pData != nullptr) {
// 已经绑定过的图元直接复用数据,避免重复创建数值井对象。
wellType = pData->getWellType();
return true;
}
// 选择井来自工程树,需要先把工程井类型转换成数值井类型。
QString wellClass = pWellData->getWellClassEn();
if(ZxBaseUtil::isSameStr(wellClass, "VerticalWell")) {
wellType = NM_WELL_MODEL::Vertical_Well;
} else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) {
wellType = NM_WELL_MODEL::Vertical_Fractured_Well;
} else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalFracturedWell")) {
wellType = NM_WELL_MODEL::Horizontal_Fractured_Well;
} else {
return false;
}
pData = createWellForGraphic(pGraphic, wellType);
if (pData == nullptr) {
return false;
}
// 重新勾选井时在这里补建nmDataWell并将工程树中的基础属性同步进去。
pData->setWellName(pWellData->getName());
nmDataAttribute tempAttr = pData->getX();
tempAttr.setValue(pWellData->getLocationX());
pData->setX(tempAttr);
tempAttr = pData->getY();
tempAttr.setValue(pWellData->getLocationY());
pData->setY(tempAttr);
tempAttr = pData->getRadius();
tempAttr.setValue(pWellData->getWellRadius());
pData->setRadius(tempAttr);
ZxDataObjectList listGaugeP = pWellData->getChildren(iDataModelType::sTypeDataGaugeP);
ZxDataObjectList listGaugeF = pWellData->getChildren(iDataModelType::sTypeDataGaugeF);
ZxDataGaugeP* pGaugeP = nullptr;
ZxDataGaugeF* pGaugeF = nullptr;
// 从工程树井节点下取第一条压力/流量数据,转换成数值井需要的曲线点。
for(int i = 0; i < listGaugeP.size(); ++i) {
if(pGaugeP = dynamic_cast<ZxDataGaugeP*>(listGaugeP[i])) {
break;
}
}
for(int i = 0; i < listGaugeF.size(); ++i) {
if(pGaugeF = dynamic_cast<ZxDataGaugeF*>(listGaugeF[i])) {
break;
}
}
QVector<QPointF> pressurePoints, flowPoints;
VecDouble vecX, vecY;
if(pGaugeP != nullptr && pGaugeP->getDataVecXY(vecX, vecY)) {
for(int i = 0; i < vecX.size(); ++i) {
if(i < vecY.size()) {
pressurePoints.append(QPointF(vecX[i], vecY[i]));
}
}
}
vecX.clear();
vecY.clear();
if(pGaugeF != nullptr && pGaugeF->getDataVecXY(vecX, vecY)) {
for(int i = 0; i < vecX.size(); ++i) {
if(i < vecY.size()) {
flowPoints.append(QPointF(vecX[i], vecY[i]));
}
}
}
int indexF = -2;
if(pWellData != zxCurWell) {
// 非当前查看井默认使用最后一段流量段。
indexF = flowPoints.count() - 1;
}
pData->setPressurePoints(pressurePoints);
pData->setFlowPoints(flowPoints);
if(indexF >= -1) {
pData->setIndexF(indexF);
}
if (wellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
if (nmDataVerticalFracturedWell* pVFWell = dynamic_cast<nmDataVerticalFracturedWell*>(pData)) {
pVFWell->setFracs();
}
} else if (wellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
if (nmDataHorizontalFracturedWell* pHFWell = dynamic_cast<nmDataHorizontalFracturedWell*>(pData)) {
pHFWell->setFracs();
}
}
QVector<QVector<double>> vvecHistoryPressureData;
QVector<QVector<double>> vvecHistoryLogData;
QVector<QVector<double>> vvecHistorySemiLogData;
// 初始化历史压力、双对数和半对数数据,保证重新显示后可直接分析。
calculateWellLogData(pData, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
pData->setHistoryPressure(vvecHistoryPressureData);
pData->setHistoryLogLog(vvecHistoryLogData);
pData->setHistorySemiLog(vvecHistorySemiLogData);
return true;
}
bool nmPlotGraphicBinder::editWellForGraphic(nmObjPointWell* pGraphic,
NM_WELL_MODEL& wellType,
ZxObjText* pNameLabel)
{
if (!pGraphic) return false;
ZxDataWell* pWellData = pGraphic->getWellData();
if (!pWellData) return false;
if(!hasLayers()) {
QMessageBox::information(nullptr, tr("error"), tr("please setting layers Data!"));
return false;
}
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
if(pDialogProvider == nullptr) {
return false;
}
nmDataWellBase* pOldData = m_mapWellData.value(pGraphic, nullptr);
nmDataWellBase* pReturnWellData = nullptr;
// 编辑弹窗同时依赖框架井数据和数值井数据由Binder集中传入图元不持有数据指针。
if(!pDialogProvider->editWell(nullptr, pWellData, pOldData, pReturnWellData)) {
return false;
}
if (pReturnWellData == nullptr || pOldData == nullptr) {
return false;
}
pWellData->setName(pReturnWellData->getWellName());
pGraphic->setName(pReturnWellData->getWellName());
pWellData->setLocationX(pReturnWellData->getX().getValue().toDouble());
pWellData->setLocationY(pReturnWellData->getY().getValue().toDouble());
pWellData->setWellRadius(pReturnWellData->getRadius().getValue().toDouble());
NM_WELL_MODEL eWellType = pReturnWellData->getWellType();
if (eWellType != wellType) {
wellType = eWellType;
QString sWellClass;
if (wellType == NM_WELL_MODEL::Vertical_Well) {
sWellClass = "VerticalWell";
} else if(wellType == NM_WELL_MODEL::Vertical_Fractured_Well) {
sWellClass = "VerticalFracturedWell";
} else if(wellType == NM_WELL_MODEL::Horizontal_Fractured_Well) {
sWellClass = "HorizontalFracturedWell";
}
pWellData->setWellClassCn(sWellClass);
}
if (pNameLabel != nullptr) {
pNameLabel->setText(pReturnWellData->getWellName());
}
nmDataWellBase* pCurWellData = getCurrentWellData();
if (pCurWellData != nullptr && pCurWellData->getWellName() == pOldData->getWellName()) {
// 如果编辑的是当前分析井需要同步替换DataManager中的当前井指针。
setCurrentWellData(pReturnWellData);
}
// 编辑返回的是新的数值井数据对象,旧对象移除后重建映射。
removeWellData(pOldData);
appendWellData(pReturnWellData);
updateWellDataMapping(pGraphic, pReturnWellData);
return true;
}
nmPlotGraphicBinder::WellRenderData nmPlotGraphicBinder::getWellRenderData(nmObjPointWell* pGraphic) const
{
WellRenderData renderData;
nmDataWellBase* pData = m_mapWellData.value(pGraphic, nullptr);
if (!pData) {
return renderData;
}
// 图元绘制阶段只读取快照不直接持有nmDataWell指针。
renderData.valid = true;
renderData.wellType = pData->getWellType();
renderData.x = pData->getX().getValue().toDouble();
renderData.y = pData->getY().getValue().toDouble();
renderData.radius = pData->getRadius().getValue().toDouble();
if (nmDataVerticalFracturedWell* pVFWell = dynamic_cast<nmDataVerticalFracturedWell*>(pData)) {
// 裂缝几何由数据对象预先计算,图元只负责坐标转换和绘制。
renderData.verticalFracs = pVFWell->getFracs();
} else if (nmDataHorizontalFracturedWell* pHFWell = dynamic_cast<nmDataHorizontalFracturedWell*>(pData)) {
// 水平井绘制需要井长、角度和多段裂缝几何。
renderData.wellLength = pHFWell->getWellLength().getValue().toDouble();
renderData.drainAngle = pHFWell->getDrainAngle().getValue().toDouble();
renderData.horizontalFracs = pHFWell->getFracs();
}
return renderData;
}
void nmPlotGraphicBinder::setWellVisible(nmObjPointWell* pGraphic, bool bVisible)
{
nmDataWellBase* pData = m_mapWellData.value(pGraphic, nullptr);
if (pData) {
pData->setPlotVisible(bVisible);
}
}
void nmPlotGraphicBinder::calculateWellLogData(nmDataWellBase* pWellData,
QVector<QVector<double>>& pressure,
QVector<QVector<double>>& logLog,
@ -1471,7 +1769,7 @@ void nmPlotGraphicBinder::_pushWellDataToGraphic(nmObjPointWell* pGraphic, nmDat
pGraphic->blockSignals(true);
pGraphic->setNmWellData(pData);
pGraphic->markWellDataBound(pData->getWellType());
// 从井数据恢复图元外观属性(加载时从 JSON 恢复的属性设置到图元)
ZxDot dot = pGraphic->getDot();

@ -1020,7 +1020,7 @@ void nmSubWndMain::updateSelectedWells(QList<ZxDataWell *> wellObjList)
for(int i = 0; i < vDeleteWellPlotList.count(); ++i) {
nmObjPointWell* pWellPlot = vDeleteWellPlotList[i];
// 如果是当前井,不可删除 (保留您的逻辑)
if(pWellPlot->getNmWellData() == nmDataAnalyzeManager::getCurrentInstance()->getCurWellData())
if(m_pWxPlot->graphicBinder() && m_pWxPlot->graphicBinder()->isCurrentWellGraphic(pWellPlot))
continue;
// 删除对应的参数类
@ -1043,6 +1043,10 @@ void nmSubWndMain::updateSelectedWells(QList<ZxDataWell *> wellObjList)
if(pWellPlot == NULL) {
continue;
}
// 选择已有井重新生成图元时先恢复Binder后续afterCreated才能建立井数据绑定
if(m_pWxPlot->graphicBinder()) {
pWellPlot->setGraphicBinder(m_pWxPlot->graphicBinder());
}
// 设置图元的井数据
pWellPlot->setWellData(wellObj);
// 移动到正确的位置

Loading…
Cancel
Save