You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmSubWnd/nmSubWndMain.cpp

2505 lines
73 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "zxLogInstance.h"
#include "ZxBaHelper.h"
#include <QDebug>
#include "ZxResolutionHelper.h"
#include "zxSysUtils.h"
#include "ZxPtyDock.h"
#include "iDockBaseWx.h"
#include "ZxMainWindow.h"
#include "ZxTabWidget.h"
#include "ZxSubAxisX.h"
#include "ZxSubAxisY.h"
#include "ZxPlot.h"
#include "ZxObjCurve.h"
#include "ZxSubTitle.h"
#include "tCurvePlotScene.h"
#include "tCurvePlotView.h"
#include "ZxTableView.h"
#include "ZxTableModel.h"
#include "mModuleDefines.h"
#include "ZxDataWell.h"
#include "ZxDataProject.h"
#include "ZxRstJobWnd.h"
#ifdef QT_DEBUG
#include "ZxDataGaugeP.h"
#endif
#ifdef QT_DEBUG
#include "nmXmlHelper.h"
#endif
#include "nmGuiPlot.h"
#include "nmSubWndMain.h"
#include "nmPlotDialogContext.h"
#include "nmPlotDialogContextProvider.h"
#include "nmWxGridVTKContainerWidget.h"
#include "nmWxSelectWellsDlg.h"
#include "nmWxSelectWellsWidget.h"
#include "nmWxParameterProperty.h"
#include "nmCalculationDllPebiSolverTask.h"
#include "nmCalculationUtils.h"
#include "nmObjPointWell.h"
#include "nmDataAnalyzeManager.h"
#include "nmDataDemo.h"
#include "nmDataLogFile.h"
#include "nmDataMeasure.h"
#include "nmWxParaProperty.h"
#include "nmWxRCDialog.h"
#include "nmWxWellLayerDlg.h"
#include "nmWxGeometryLayerDlg.h"
#include "nmWxReservoirPropertiesDlg.h"
#include "nmWxPostprocessingAnimationWidget.h"
#include "nmWxGeoRefDlg.h"
#include "iSubWndFitting.h"
#include <QVector>
#include "nmSingalCenter.h"
#include "nmWxSelectResultWellsWidget.h"
#include "nmWxResultParameters.h"
#include "nmWxReservoirProperties.h"
#include "nmCalculationPebiGrid.h"
#include "nmDataOutline.h"
#include "nmDataVerticalFracturedWell.h"
#include "nmDataHorizontalFracturedWell.h"
#include "nmDataVerticalWell.h"
#include "ZxDataGaugeP.h"
#include "ZxDataGaugeF.h"
#include "nmWxDFN.h"
#include "nmWxDisplaySettings.h"
#include "nmDataMixedResults.h"
#include "ZxRstWnd.h"
#include <QPointer>
namespace
{
// 保留原来求解器单例的防重入语义全局同一时间只允许一个DLL求解任务运行。
// QPointer会在QObject销毁后自动变空避免保留已经释放的线程指针。
QPointer<nmCalculationDllPebiSolverTask> s_pRunningSolverTask;
}
nmSubWndMain::nmSubWndMain(QWidget *parent, QString sExt) :
iSubWndBaseFit(parent, sExt)
{
m_pWxPlot = NULL;
m_pWxDockParas = NULL;
m_pWxParas = NULL;
m_pWxDockData1 = NULL;
m_pTableView1 = NULL;
m_pWxDockData2 = NULL;
m_pTableView2 = NULL;
#ifdef QT_DEBUG
m_pWxDockTemp = NULL;
m_pListWxTemp = NULL;
#endif
// 为了后续支持多井提供方便
if(m_pDataWell == NULL) {
m_pDataWell = zxCurWell;
}
//m_sMdiWndType = s_MdiType_DataNum;
m_sMdiWndType = s_MdiType_DataAnal;
setWindowTitle(tr("nmSubWndMain"));
m_lockState = false; // 默认为false
m_resultDataDlg = nullptr;
m_openDialogCmdIds.clear();
m_pProgressDlg = nullptr;
m_pSolverTask = nullptr;
m_pFakeProgressTimer = nullptr;
m_nVirtualProgress = 0;
m_nSlowDownCounter = 0;
m_pPlotToolBar = nullptr;
}
nmSubWndMain::~nmSubWndMain()
{
#ifdef QT_DEBUG
// 坚持谁创建谁析构原则,删除(首先需要去除绑定)
if(NULL != m_pWxDockTemp) {
//QObject* pParent = m_pWxDockTemp->parent();
//ZxMainWindow* p = dynamic_cast<ZxMainWindow*>(pParent);
ZxMainWindow* p = m_pMainWindow;
if(NULL != p) {
p->detachOuterDockWx(m_pWxDockTemp);
}
delete m_pWxDockTemp;
m_pWxDockTemp = NULL;
}
#endif
this->setTopDocksVisible(true);
// TODO删除已有在图元的数据对象
//if (m_pWxPlot != nullptr) {
// QVector<nmObjBase*> vecObjs = m_pWxPlot->getAllPlots();
// foreach(nmObjBase* obj, vecObjs) {
// obj->removeData();
// }
//}
if(m_resultDataDlg != nullptr) {
delete m_resultDataDlg;
m_resultDataDlg = nullptr;
}
if (m_pFakeProgressTimer) {
m_pFakeProgressTimer->stop();
// 因为构造时传了 this这里不 delete 也可以,但 disconnect 是安全的
m_pFakeProgressTimer->disconnect();
}
if (m_pProgressDlg) {
delete m_pProgressDlg;
m_pProgressDlg = NULL;
}
if (m_pSolverTask) {
// 窗口销毁时只解除本窗口的回调;若线程仍在运行,让线程自己结束后释放。
disconnect(m_pSolverTask, SIGNAL(sig_calculateDone(bool)), this, SLOT(on_solverTaskFinished(bool)));
if (m_pSolverTask == s_pRunningSolverTask && !m_pSolverTask->isRunning()) {
s_pRunningSolverTask = nullptr;
}
if (!m_pSolverTask->isRunning()) {
m_pSolverTask->deleteLater();
}
m_pSolverTask = nullptr;
}
/*if (m_parameterPropertyWindow != nullptr) {
delete m_parameterPropertyWindow;
m_parameterPropertyWindow = nullptr;
}*/
}
void nmSubWndMain::configWnd(QString sPrevInfo)
{
iSubWndBaseFit::configWnd(sPrevInfo);
if(NULL != m_pMainWindow) {
disconnect(this, SIGNAL(sigAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)), \
m_pMainWindow, SLOT(slotAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)));
connect(this, SIGNAL(sigAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)), \
m_pMainWindow, SLOT(slotAppendDock2Main(iDockBaseWx*, Qt::DockWidgetArea)));
}
initUI();
}
void nmSubWndMain::initUI()
{
// iSubWndBaseAF::initUI();
#ifdef QT_DEBUG
// 示例演示增加Dock并且追加至程序主窗口
initUiTop();
#endif
// 主布局:定义
initUiMain();
// 外围布局DockWx
{
initUiDockWxs();
initUiDockPtys();
}
#ifdef QT_DEBUG
// 示例如何加载xml文件
if(_nmXmlHelper->loadXmlDefines()) {
foreach(nmXmlData* pData, *(_nmXmlHelper->getVecNmXmlDataPtrs())) {
Q_ASSERT(NULL != pData);
qDebug() << QString("%1: %2").arg(pData->m_sName).arg(pData->m_sAlias);
}
}
#endif
}
QWidget* nmSubWndMain::initUiMainWx()
{
QSplitter* pSplitter = new QSplitter(Qt::Vertical);
Q_ASSERT(NULL != pSplitter);
nmGuiPlot* pWxPlot = new nmGuiPlot();
m_pWxPlot = pWxPlot;
// 将绘图对象添加到数据中心
nmDataAnalyzeManager::getCurrentInstance()->setPlot(m_pWxPlot);
{
// 建立信号,以便在此处增加新的工具
connect(pWxPlot, SIGNAL(sigToolbarBuilt(QToolBar*)),
this, SLOT(slotToolbarBuilt(QToolBar*)));
QSize sz = QSize(265, 203);
pWxPlot->initUI("TestGui", sz);
bindChartSignals(pWxPlot);
pSplitter->addWidget(pWxPlot);
}
return pSplitter;
}
void nmSubWndMain::initUiDockWxs()
{
// TODO本Dock的操作
// 基础参数Dock
// {
// m_pWxDockParas = new iDockBaseWx(tr("Parameters"));
// Q_ASSERT (NULL != m_pWxDockParas);
// addDockWidget(Qt::LeftDockWidgetArea, m_pWxDockParas);
// m_pWxParas = new nmWxParaProperty();
// Q_ASSERT (NULL != m_pWxParas);
// m_pWxParas->initUI();
// m_pWxDockParas->setWidget(m_pWxParas);
// m_pWxDockParas->setMinimumWidth(_resoSizeW(200));
// }
// 表格数据Dock
// {
// QStringList listTitles;
// listTitles << tr("Name1");
// iDockBaseWx* pDockWx1 = new iDockBaseWx(tr("Data1"));
// Q_ASSERT (NULL != pDockWx1);
// {
// addDockWidget(Qt::RightDockWidgetArea, pDockWx1);
// m_pWxDockData1 = pDockWx1;
// ZxTableView* pTableView = new ZxTableView();
// Q_ASSERT (NULL != pTableView);
// {
// ZxTableModel* pTableModel = new ZxTableModel(1, 1, listTitles);
// Q_ASSERT (NULL != pTableModel);
// pTableView->setModel(pTableModel);
// pTableView->setMenuMode(ZxTableView::MTM_Edit_Without_Col);
// pTableView->setSelectionBehavior(ZxTableView::SelectRows);
// pTableView->fuzzyUiOfQt5();
// }
// pDockWx1->setWidget(pTableView);
// m_pTableView1 = pTableView;
// }
// iDockBaseWx* pDockWx2 = new iDockBaseWx(tr("Data2"));
// Q_ASSERT (NULL != pDockWx2);
// {
// addDockWidget(Qt::RightDockWidgetArea, pDockWx2);
// tabifyDockWidget(pDockWx1, pDockWx2);
// m_pWxDockData2 = pDockWx2;
// ZxTableView* pTableView = new ZxTableView();
// Q_ASSERT (NULL != pTableView);
// {
// ZxTableModel* pTableModel = new ZxTableModel(1, 1, listTitles);
// Q_ASSERT (NULL != pTableModel);
// pTableView->setModel(pTableModel);
// pTableView->setMenuMode(ZxTableView::MTM_Readonly);
// pTableView->fuzzyUiOfQt5();
// }
// pDockWx2->setWidget(pTableView);
// m_pTableView2 = pTableView;
// }
// }
}
void nmSubWndMain::initUiDockPtys()
{
iSubWndBaseAF::initUiDockPtys();
// 属性Dock
{
Q_ASSERT(NULL != m_pDockPty);
m_pDockPty->setMinimumWidth(_resoSizeW(200));
}
}
#ifdef QT_DEBUG
// 示例演示增加Dock并且追加至程序主窗口
void nmSubWndMain::initUiTop()
{
#if 0
return;
// 隐藏所有Dock
this->setTopDocksVisible(false);
// 创建新的Dock
iDockBaseWx* pDockWx = new iDockBaseWx(tr("TODO:Demo"));
Q_ASSERT(NULL != pDockWx);
// QListWidget* pListWx = new QListWidget();
nmWxTreeWidget* treeWidget = new nmWxTreeWidget(pDockWx, m_pAnalyzeData);
Q_ASSERT(NULL != treeWidget);
pDockWx->setWidget(treeWidget);
// m_pListWxTemp = pListWx;
pDockWx->setMinimumWidth(_resoSizeW(200));
emit sigAppendDock2Main(pDockWx, Qt::LeftDockWidgetArea);
m_pWxDockTemp = pDockWx;
return;
// 基础参数Dock
// {
// iDockBaseWx* pDockWx = new iDockBaseWx(tr("TODO:Demo"));
// Q_ASSERT (NULL != pDockWx);
// QListWidget* pListWx = new QListWidget();
// Q_ASSERT (NULL != pListWx);
// pDockWx->setWidget(pListWx);
// m_pListWxTemp = pListWx;
// pDockWx->setMinimumWidth(_resoSizeW(200));
// emit sigAppendDock2Main(pDockWx, Qt::LeftDockWidgetArea);
// m_pWxDockTemp = pDockWx;
// }
#endif
}
#endif
void nmSubWndMain::bindChartSignals(iGuiPlot* pWxPlot)
{
nmGuiPlot* p = dynamic_cast<nmGuiPlot*>(pWxPlot);
if(NULL != p) {
connect(p, SIGNAL(sigObjSelChanged(ZxObjBase*, bool)), \
this, SLOT(slotObjSelChanged(ZxObjBase*, bool)));
connect(p, SIGNAL(sigObjPtsChanged(ZxObjBase*)),
this, SLOT(slotObjPtsChanged(ZxObjBase*)));
}
iSubWndBaseAF::bindChartSignals(pWxPlot);
}
bool nmSubWndMain::runActionOf(QString sAction)
{
if(iSubWnd::runActionOf(sAction)) {
return true;
}
// 数据加载
QString s = sAction;
if(_isSame(s, "LoadP")) {
return true;
}
return false;
}
bool nmSubWndMain::runCmdBy(QString sName, QString sID)
{
QString s = sName;
int nId = sID.toInt();
// 运行菜单之前,先将所有处于选中状态的图元状态恢复
if(m_pWxPlot != nullptr) {
m_pWxPlot->clearPlotsSelectStates();
}
switch(nId) {
case 5102:
this->geologicalMapImport();
return true;
/*case 5103:
this->geologicalMapHide();
return true;*/
case 5120:
this->drawMeasuringScale();
return true;
case 5103:
this->drawPolygonOutline();
return true;
case 5104:
this->drawSquareOutline();
return true;
case 5105:
this->drawRoundOutline();
return true;
case 5106:
this->drawFault();
return true;
case 5107:
this->selectWell();
return true;
case 5108:
this->drawWell();
return true;
case 5109:
this->drawCrack();
return true;
case 5110:
this->drawRegion();
return true;
case 5111:
this->drawRegionMark();
return true;
case 5112:
this->geoLayering();
return true;
case 5113:
this->reservoirCharacteristics();
return true;
/*case 5114:
this->generationMesh();
return true;
*/
case 5115:
this->solveAndAnalyze();
return true;
case 5117:
this->mergeAnaResultToFitting();
return true;
case 5121:
this->deleteOneObj();
return true;
case 5119:
this->setLocked();
return true;
case 5122:
this->generateDFN();
return true;
case 5123:
this->displaySetting();
return true;
/*
case 5117:
this->initData();
return true;
*/
case 5129:
if(isDialogCmdOpened(5129)) {
return true;
}
this->drawMeasure();
return true;
case 5127:
this->drawGeoRef();
return true;
case 5128:
if(isDialogCmdOpened(5128)) {
return true;
}
this->drawPointerPos();
return true;
}
if(_isSame(s, "RunGrid")) {
if(NULL != m_pWxPlot) {
//m_pWxPlot->refreshGrid(true);
}
return true;
}
return false;
}
bool nmSubWndMain::checkCmdEnable(bool &b, \
QString sName, int nID, \
bool bLicensed)
{
bool b1 = (NULL != zxCurProject);
bool b2 = (NULL != m_pDataWell);
// 判断当前锁定状态
if(m_lockState) {
/*
if(nID >= 5102 && nID <= 5125) {
b = (b1 && b2 && bLicensed && !isReadonly() && NULL != m_pWxPlot);
return true;
}
*/
/*
if ((nID >= 5122 && nID <= 5125) || (nID >= 5112 && nID <= 5119 ))
{
b = true;
return true;
}
*/
/*
if(nID >= 5102 && nID <= 5124) {
b = true;
return true;
}
*/
// 可使用菜单栏
if(sName == "NmMap" || sName == "NmUnlocked" || sName == "NmGeometry" ||
sName == "NmProperties" || sName == "NmDFN" || sName == "NmCaculation" ||
sName == "NmBack" || sName == "NmResult" || sName == "NmGrid" ||
sName == "NmShow" || sName == "NmPrintPreview" || sName == "NmPrint" ||
sName == "VisibleAnalBasic" || sName == "VisibleAnalPVT" || sName == "VisibleAnalDiff" ||
sName == "VisibleAnalPseu" || sName == "nmFitModel" || sName == "NmAnalChange") {
b = true;
return true;
} else {
b = false;
return false;
}
} else {
if((nID >= 5102 && nID <= 5130) /*|| (nID >= 9002 && nID <= 9003) */ || (nID >= 9101 && nID <= 9104) || nID == 3104) {
b = (b1 && b2 && bLicensed && !isReadonly() && NULL != m_pWxPlot);
return true;
}
}
return iSubWndBaseFit::checkCmdEnable(b, sName, nID, bLicensed);
}
void nmSubWndMain::reAdjustToolbar(QToolBar* pToolBar)
{
iSubWndBaseAF::reAdjustToolbar(pToolBar);
m_pPlotToolBar = pToolBar;
// 获取所有动作的列表
// QList<QAction *> actions = m_pPlotToolBar->actions();
// // 隐藏第1个和第2个动作
// if (actions.size() > 0) {
// actions[0]->setVisible(false); // 隐藏第1个动作
// }
// if (actions.size() > 1) {
// actions[1]->setVisible(false); // 隐藏第2个动作
// }
}
void nmSubWndMain::firstLoadAndUpdate()
{
iSubWndBaseAF::firstLoadAndUpdate();
}
void nmSubWndMain::finalDeals()
{
iSubWndBaseAF::finalDeals();
#ifdef QT_DEBUG
updatePlots();
updateDockWxs();
if(m_pWxDockData1 != NULL) {
Q_ASSERT(NULL != m_pWxDockData1);
m_pWxDockData1->raise();
}
#endif
}
void nmSubWndMain::onActivated()
{
#ifdef QT_DEBUG
// 当前窗体激活时可以做些事情比如把隐藏的Dock显示出来
if(NULL != m_pWxDockTemp) {
if(!m_pWxDockTemp->isVisible()) {
m_pWxDockTemp->setVisible(true);
}
}
#endif
}
#ifdef QT_DEBUG
void nmSubWndMain::updatePlots()
{
#if 0
// 里面根据曲线,重新刷了一下坐标轴范围。你屏蔽该函数,即可
// 坐标轴范围会变成背景图的大小
return ;
// 说明:以从当前井获取一条压力数据进行绘图为例
QString sType = iDataModelType::sTypeDataGaugeP;
QString sCodeP = ""; //如果已知压力数据Code可以直接引用
ZxDataGaugeP* pDataObjP = dynamic_cast<ZxDataGaugeP*>(getDataObjOf(sType, sCodeP));
if(NULL == pDataObjP) {
qDebug() << tr("Failed to get data of type '%1'").arg(sType);
return;
}
VecDouble vecX, vecY;
QByteArray ba = pDataObjP->getGaugeDataOf(0);
if(!ZxBaHelper::convertBa2VecXY(vecX, vecY, ba)) {
qDebug() << tr("Failed to get x-y data of dataobj '%1'").arg(pDataObjP->getCode());
return;
}
nmGuiPlot* pWxPlot = m_pWxPlot;
Q_ASSERT(NULL != pWxPlot);
QString sName = tr("CurveName");
ZxObjBase* pObj = pWxPlot->updatePlotObjBy(sName, vecX, vecY, true);
if(NULL != pObj) {
pObj->setLockPos(true); //可以调整属性
// pObj->setReadOnly(true);
pWxPlot->freshAxisScales(true);//刷新坐标轴刻度
// 设置标题+坐标轴等
pWxPlot->setAxisX(tr("Time"), "hr");
pWxPlot->setAxisY(tr("Pressure"), "MPa");
pWxPlot->setAxisXYLog(false, 0);
pWxPlot->setAxisXYLog(false, 1);
pWxPlot->m_pPlot->setLegendVisible(false);
pWxPlot->m_pPlot->getTitle()->setName(tr("Demo"));
}
#endif
}
ZxDataObject* nmSubWndMain::getDataObjOf(QString sType, QString sCode /*= ""*/)
{
ZxDataWell* pDataWell = zxCurWell;
Q_ASSERT(NULL != pDataWell);
ZxDataObject* pDataObj = NULL;
if(!sCode.isEmpty()) {
pDataObj = pDataWell->getChild(sType, sCode);
} else {
ZxDataObjectList vecObjs = pDataWell->getChildren(sType);
if(!vecObjs.isEmpty()) {
pDataObj = vecObjs[0];
}
}
return pDataObj;
}
void nmSubWndMain::updateDockWxs()
{
#if 0
// TODO刷新Dock内容
return;
// 左侧参数窗体
Q_ASSERT(NULL != m_pWxParas);
QStringList listParas;
listParas << "K" << "S" << "rw" << "Miuo" << "Bo" << "phi";
m_pWxParas->refreshUIs(listParas);
// 表格数据1
Q_ASSERT(NULL != m_pTableView1);
ZxTableModel* pTableModel = m_pTableView1->getModel();
Q_ASSERT(NULL != pTableModel);
QStringList listTitles;
listTitles << tr("Col1") << tr("Col2\n(MPa)");
VVecDouble vvec;
{
VecDouble vec;
vec << 0.2 << 3.4;
vvec << vec;
}
{
VecDouble vec;
vec << 5.6 << 0.456;
vvec << vec;
}
pTableModel->setTitles(listTitles);
pTableModel->setData(vvec);
if(NULL != m_pListWxTemp) {
m_pListWxTemp->clear();
for(int i = 0; i < 10; i++) {
QString sItem = tr("Demo Item %1").arg(i + 1);
QListWidgetItem* pItem = new QListWidgetItem(sItem);
Q_ASSERT(NULL != pItem);
pItem->setIcon(zxLoadIcon("Open"));
m_pListWxTemp->addItem(pItem);
}
}
#endif
}
void nmSubWndMain::updateTableByCurve(ZxObjCurve* pObjCurve, ZxTableView* pTableView)
{
Q_ASSERT(NULL != pObjCurve);
Q_ASSERT(NULL != pTableView);
// 刷新表格标题
{
QString sNameX = pObjCurve->getAxisX()->getName();
QString sUnit = pObjCurve->getAxisX()->getUnit();
if(!sUnit.isEmpty()) {
sNameX += QString("\n(%1)").arg(sUnit);
}
QString sNameY = pObjCurve->getAxisY()->getName();
sUnit = pObjCurve->getAxisY()->getUnit();
if(!sUnit.isEmpty()) {
sNameY += QString("\n(%1)").arg(sUnit);
}
QStringList listTitles;
listTitles << sNameX << sNameY;
pTableView->getModel()->setTitles(listTitles);
}
// 刷新表格数据
{
VVecDouble vvec;
QVector<QPointF> vecValues = pObjCurve->getAllValues();
for(int i = 0; i < vecValues.count(); i++) {
VecDouble vec;
vec << vecValues.at(i).x() * 1.0;
vec << vecValues.at(i).y() * 1.0;
vvec << vec;
}
pTableView->getModel()->setData(vvec);
}
}
#endif
void nmSubWndMain::slotObjSelChanged(ZxObjBase* p, bool b)
{
#ifdef QT_DEBUG
// 如果选中了一条曲线则把其数据显示在数据表格2中
ZxObjCurve* pObjCurve = dynamic_cast<ZxObjCurve*>(p);
if(NULL != pObjCurve && b) {
Q_ASSERT(NULL != m_pWxDockData2);
m_pWxDockData2->raise();
updateTableByCurve(pObjCurve, m_pTableView2);
}
#endif
}
void nmSubWndMain::slotObjPtsChanged(ZxObjBase* p)
{
}
void nmSubWndMain::onSerialize(ZxSerializer* ser)
{
iSubWndBaseAF::onSerialize(ser);
if(NULL != m_pWxPlot) {
m_pWxPlot->setModified(false);
}
}
void nmSubWndMain::onDeserialize(ZxSerializer* ser)
{
iSubWndBaseAF::onDeserialize(ser);
if(NULL != m_pWxPlot) {
m_pWxPlot->setModified(false);
}
}
void nmSubWndMain::onDeserialized()
{
if(NULL != m_pWxPlot) {
m_pWxPlot->resetAfterDeserialized();
}
}
//bool nmSubWndMain::loadRss() {
// ZxRstJobWnd* pRstWnd = getRstJobWnd();
// Q_ASSERT(NULL != pRstWnd);
// // 基础信息
// {
// QByteArray v = pRstWnd->getDataInfo();
// IxSerDes* pSerObj = this;
// if(!loadRstInfoFromArr(v, pSerObj)) {
// return false;
// }
// }
// // 图形
// if(NULL != m_pWxPlot) {
// QByteArray v = pRstWnd->getDataInfo1();
// ZxPlot* pPlot = NULL;
// loadOnePlot(pPlot, v);
// if(NULL != pPlot) {
// m_pWxPlot->m_pPlotScene->freshToPlot(pPlot,
// m_pWxPlot->m_pPlotView);
// m_pWxPlot->m_pPlot = m_pWxPlot->m_pPlotScene->m_pPlot;
// pPlot->resetTools(m_pWxPlot->m_pPlotView);
// m_pWxPlot->resetAfterDeserialized();
// }
// m_pWxPlot->runUpdate();
// }
// return true;
//}
//bool nmSubWndMain::saveRss() {
// ZxRstJobWnd* pRstWnd = getRstJobWnd();
// if(NULL == pRstWnd) {
// return false;
// }
// // 基础信息
// {
// QByteArray v;
// IxSerDes* pSerObj = this;
// if(!saveRstInfoToArr(v, pSerObj)) {
// return false;
// }
// pRstWnd->setDataInfo(v);
// }
// // 图形
// if(NULL != m_pWxPlot) {
// ZxPlot* pPlot = m_pWxPlot->m_pPlot;
// {
// QByteArray v1;
// if(saveOnePlot(pPlot, v1)) {
// pRstWnd->setDataInfo1(v1);
// }
// }
// }
// return pRstWnd->save();
//}
bool nmSubWndMain::loadRsts()
{
return true;//
/*
ZxRstWnd* pRstWnd = getRstUtilWnd();
Q_ASSERT (nullptr != pRstWnd);
// 基础信息
if (!loadRstBase(pRstWnd))
{
return false;
}
// 图形
if (nullptr != m_pWxPlot)
{
QByteArray v = QByteArray();
pRstWnd->loadSubPlotContent(v);
ZxPlot* pPlot = nullptr;
loadOnePlotFromBa(pPlot, v);
if (nullptr != pPlot)
{
m_pWxPlot->m_pPlotScene->freshToPlot(pPlot,
m_pWxPlot->m_pPlotView);
m_pWxPlot->m_pPlot = m_pWxPlot->m_pPlotScene->m_pPlot;
pPlot->resetTools(m_pWxPlot->m_pPlotView);
m_pWxPlot->resetAfterDeserialized();
}
m_pWxPlot->runUpdate();
}//*/
}
bool nmSubWndMain::saveRsts()
{
ZxRstWnd* pRstWnd = this->getRstUtilWnd();
if(nullptr == pRstWnd) {
return false;
}
return pRstWnd->save();
// // 基础信息
// if (!saveRstBase(pRstWnd))
// {
// return false;
// }
// // 图形
// if (nullptr != m_pWxPlot)
// {
// ZxPlot* pPlot = m_pWxPlot->m_pPlot;
// {
// QByteArray v1;
// if (saveOnePlotToBa(pPlot, v1))
// {
// pRstWnd->saveSubPlotContent(v1);
// }
// }
// }
//return pRstWnd->save();
}
bool nmSubWndMain::slotSaveAll()
{
ZxRstWnd* pRstWnd = getRstUtilWnd();
Q_ASSERT(NULL != pRstWnd);
if(pRstWnd == NULL) {
return false;
}
return saveRsts();
}
void nmSubWndMain::updateSelectedWells(QList<ZxDataWell *> wellObjList)
{
// if(wellObjList.count() == 0) {
// return;
// }
// setp 1获取现在画布上所有井的 ZxDataWell* 数据指针
QVector<nmObjPointWell*> pWellPlotList = m_pWxPlot->getWellPlots();
// QMap<ZxDataWell*, nmObjPointWell*> 用于快速查找和构建当前画布上的井数据列表
QMap<ZxDataWell*, nmObjPointWell*> pWellDataToPlotMap;
for(int i = 0; i < pWellPlotList.count(); ++i) {
nmObjPointWell* wellPlot = pWellPlotList[i];
ZxDataWell *pWellData = wellPlot->getWellData();
if (pWellData) { // 确保数据不为空
pWellDataToPlotMap.insert(pWellData, wellPlot);
}
}
// 当前在画布上的所有 ZxDataWell* 数据列表 (Key Set)
QList<ZxDataWell*> pWellPlotDataList = pWellDataToPlotMap.keys();
// setp 2找出需要 REMOVE (删除) 的图元
QVector<nmObjPointWell*> vDeleteWellPlotList;
// 遍历所有当前在画布上的井数据
for(int i = 0; i < pWellPlotDataList.count(); ++i) {
ZxDataWell *pWellDataOnPlot = pWellPlotDataList[i];
// 如果该井数据不在用户选中的列表 wellObjList 中,则需要删除
if (!wellObjList.contains(pWellDataOnPlot)) {
// 从 Map 中获取对应的图元对象
vDeleteWellPlotList.append(pWellDataToPlotMap.value(pWellDataOnPlot));
}
}
// setp 3找出需要 ADD (添加) 的井数据
QVector<ZxDataWell*> vAddWellPlotList;
// 遍历所有用户选中的井数据 wellObjList
for(int i = 0; i < wellObjList.count(); ++i) {
ZxDataWell *pWellDataSelected = wellObjList[i];
// 确保井数据有效
if (pWellDataSelected && !pWellPlotDataList.contains(pWellDataSelected)) {
// 如果该井数据不在当前画布上的数据列表中,则需要添加
vAddWellPlotList.append(pWellDataSelected);
}
}
// setp 4执行删除操作
for(int i = 0; i < vDeleteWellPlotList.count(); ++i) {
nmObjPointWell* pWellPlot = vDeleteWellPlotList[i];
// 如果是当前井,不可删除 (保留您的逻辑)
if(pWellPlot->getNmWellData() == nmDataAnalyzeManager::getCurrentInstance()->getCurWellData())
continue;
// 删除对应的参数类
pWellPlot->removeData();
// 实际从画布上删除图元
m_pWxPlot->m_pPlot->removeObjByName(pWellPlot->getName());
}
// setp 5将vAddWellPlotList中的井数据构建图元添加到画布上
for(int i = 0; i < vAddWellPlotList.count(); i++) {
ZxDataWell* wellObj = vAddWellPlotList[i];
QString sName = wellObj->getName();
QVector<QPointF> points;
points.append(QPointF(wellObj->getLocationX(), wellObj->getLocationY()));
// 构建了图元
nmObjPointWell* pWellPlot = NULL;
pWellPlot = (nmObjPointWell*)m_pWxPlot->appendOneObj(NMOT_Point_Well, sName, points);
if(pWellPlot == NULL) {
continue;
}
// 设置图元的井数据
pWellPlot->setWellData(wellObj);
// 移动到正确的位置
pWellPlot->moveToPos(pWellPlot->getPosOf(pWellPlot->getAllPos()));
pWellPlot->afterCreated(); //选择完后初始化参数
}
// 添加完毕后,重新渲染
m_pWxPlot->update();
}
// 地质图导入
void nmSubWndMain::geologicalMapImport()
{
//打开图片选择弹框
//打开文件对话框选择图片文件
//QString filePath = QFileDialog::getOpenFileName(nullptr, "选择图片文件", "", "Images (*.png *.xpm *.jpg)");
//if(!filePath.isEmpty()) {
// // 画布 设置背景,并自适应宽高
// ZxPlot* pPlot = m_pWxPlot->m_pPlot;
// pPlot->setBkImgFile(filePath);
// // QImage* pBkImg = pPlot->getBkImg();
// // Q_ASSERT (NULL != pBkImg);
// // int w = pBkImg->width();
// // int h = pBkImg->height();
// // pPlot->getMainAxisX()->setRangeMinMax(0, w, true);
// // pPlot->getMainAxisY()->setRangeMinMax(0, h, true);
// nmDataLogFile::getInstance()->writeLog(filePath);
//}
QString sFilter =
"PNG Images (*.png);;"
"JPEG Images (*.jpg *.jpeg);;"
"Bitmap Images (*.bmp);;"
"All Files (*)";
QString sFile = QFileDialog::getOpenFileName(
nullptr,
tr("Open File"),
ZxBaseUtil::getLastDir(),
sFilter
);
if(sFile.isEmpty() || !QFile::exists(sFile)) {
return;
}
// 更新最后访问目录
QFileInfo fi(sFile);
ZxBaseUtil::setLastDir(fi.absolutePath());
// 输出文件失败原因
QImageReader reader(sFile);
if(!reader.canRead()) {
// 输出具体错误
qDebug() << "Error Message: " << reader.errorString();
return;
}
if(m_pWxPlot == nullptr || m_pWxPlot->m_pPlot == nullptr) {
return;
}
// 设置背景图片
ZxPlot* pPlot = m_pWxPlot->m_pPlot;
pPlot->setBkImgFile(sFile);
// 检查 ZxPlot 是否成功加载图片
QImage* pBkImg = pPlot->getBkImg();
Q_ASSERT(nullptr != pBkImg);
if(pBkImg == nullptr) {
return;
}
// 将图片信息存储到数据中心
nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance();
if(pManager) {
QImage loadedImage = reader.read(); // 假设已经读取成功
BackgroundImageInfo bgInfo;
bgInfo.bIsVisible = true; // 默认设置为可见
bgInfo.sFilePath = sFile; // 当前背景文件路径
bgInfo.objImage = loadedImage; // 存储QImage对象
pManager->setBackgroundImageInfo(bgInfo); // 设置背景图片信息
}
// 手动调整坐标轴(如果 ZxPlot 未自动调整)
//int w = pBkImg->width();
//int h = pBkImg->height();
//if (w > 0 && h > 0) {
// pPlot->getMainAxisX()->setRangeMinMax(0, w, true);
// pPlot->getMainAxisY()->setRangeMinMax(0, h, true);
//}
}
void nmSubWndMain::drawMeasuringScale()
{
this->triggerToolBarAction(NMOT_Line_MeasuringScale);
}
void nmSubWndMain::geologicalMapHide()
{
}
void nmSubWndMain::setTopDocksVisible(bool visible)
{
// 获取主程序所有 Dock 视图
QList<QDockWidget*> dockWidgets = m_pMainWindow->findChildren<QDockWidget*>();
// 遍历所有 Dock 视图并移除位于左侧的
foreach(QDockWidget* dock, dockWidgets) {
if(visible) {
dock->show();
} else {
dock->hide();
}
}
}
void nmSubWndMain::drawPolygonOutline()
{
// 获取多边形边界的绘制,并模拟触发点击操作
// 目前多边形边界绘制是工具栏的第4个所以用 3
// QList<QAction *> actions = m_pPlotToolBar->actions();
// if (!actions.isEmpty()) {
// QAction *action = actions[3];
// action->trigger();
// }
this->triggerToolBarAction(NMOT_PolygonOutline);
}
void nmSubWndMain::drawSquareOutline()
{
// 获取矩形边界的绘制,并模拟触发点击操作
this->triggerToolBarAction(NMOT_RectOutline);
}
void nmSubWndMain::drawRoundOutline()
{
// 获取矩形边界的绘制,并模拟触发点击操作
this->triggerToolBarAction(NMOT_RoundOutline);
}
void nmSubWndMain::drawFault()
{
this->triggerToolBarAction(NMOT_Line_Fault);
}
void nmSubWndMain::selectWell()
{
if(m_pWxPlot == nullptr || zxCurProject == nullptr) {
return;
}
// 先获取已经添加到的界面中井
QStringList wellPlotNameList = m_pWxPlot->getWellNames();
// 先找到所有的井
int wellCount = zxCurProject->getChildrenCount(iDataModelType::sTypeWell);
ZxDataObjectList wellList = zxCurProject->getChildren(iDataModelType::sTypeWell);
nmDataLogFile::getInstance()->writeLog(QString(" %1 %2").arg(wellCount).arg(wellList.size()));
// 井的名字
QStringList listWellNames;
// 井的code
QList<QVariant> wellCodes;
// 井的名字到井数据指针的Map
QMap<QString, ZxDataWell*> wellNameToObjMap;
// 数据整理
for(int i = 0; i < wellList.size(); i++) {
ZxDataWell* wellObj = (ZxDataWell*)wellList[i];
nmDataLogFile::getInstance()->writeLog(wellObj->getName() + " " + wellObj->getCode());
listWellNames.append(wellObj->getName());
wellCodes.append(wellObj->getCode());
wellNameToObjMap.insert(wellObj->getName(), wellObj);
}
// 展示dialog供选择
nmWxSelectWellsDlg dlg;
nmWxSelectWellsWidget wellListWidget;
wellListWidget.setSelectedItems(wellPlotNameList);
wellListWidget.addItems(listWellNames, wellCodes);
dlg.setWidget(&wellListWidget);
if(dlg.exec() == QDialog::Accepted) {
// 用户点击了"确定"按钮
nmDataLogFile::getInstance()->writeLog(" OK ");
QStringList wellNames = wellListWidget.getItems();
QList<ZxDataWell*> selectWellList;
// 找出新选中的井
for(int i = 0; i < wellNames.count(); i++) {
QString wellName = wellNames[i];
if (!wellName.isEmpty()) { // 确保井名不为空
// 仅将有效的井对象添加到 selectWellList
selectWellList.append(wellNameToObjMap.value(wellName));
}
}
this->updateSelectedWells(selectWellList);
// 更新完成后,通知参数界面刷新
//nmWxParameterProperty::notifyUpdateTable();
nmDataLogFile::getInstance()->writeLog("===" + wellNames.join(";") + "===");
} else {
// 用户点击了"取消"按钮
nmDataLogFile::getInstance()->writeLog(" Cancel ");
}
}
void nmSubWndMain::drawWell()
{
// 获取多边形边界的绘制,并模拟触发点击操作
// 目前多边形边界绘制是工具栏的第4个所以用 3
// QList<QAction *> actions = m_pPlotToolBar->actions();
// if (!actions.isEmpty()) {
// QAction *action = actions[0];
// action->trigger();
// }
this->triggerToolBarAction(NMOT_Point_Well);
nmDataLogFile::getInstance()->writeLog(" in drawWell ");
}
void nmSubWndMain::drawCrack()
{
this->triggerToolBarAction(NMOT_Line_Fracture);
}
void nmSubWndMain::drawRegion()
{
this->triggerToolBarAction(NMOT_Region);
}
void nmSubWndMain::drawRegionMark()
{
this->triggerToolBarAction(NMOT_RegionMark);
}
void nmSubWndMain::drawMeasure()
{
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
QWidget* measureDlg = showMeasureDialog();
if(plot == nullptr || measureDlg == nullptr) {
return;
}
bindMeasureDialog(measureDlg);
plot->setAllPlotObjectsEditable(false);
this->triggerToolBarAction(NMOT_Line_Measure);
}
void nmSubWndMain::drawGeoRef()
{
nmWxGeoRefDlg dlg(nullptr);
dlg.exec();
}
void nmSubWndMain::drawPointerPos()
{
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
if(plot) {
showPointerPosDialog();
}
}
bool nmSubWndMain::isDialogCmdOpened(int nId) const
{
return m_openDialogCmdIds.contains(nId);
}
void nmSubWndMain::markDialogCmdOpened(int nId)
{
if(!m_openDialogCmdIds.contains(nId)) {
m_openDialogCmdIds.append(nId);
}
}
void nmSubWndMain::markDialogCmdClosed(int nId)
{
// 从后向前遍历,避免索引错乱
for (int i = m_openDialogCmdIds.size() - 1; i >= 0; --i) {
if (m_openDialogCmdIds[i] == nId) {
m_openDialogCmdIds.remove(i);
}
}
}
void nmSubWndMain::onDialogCmdDestroyed(QObject* obj)
{
if(obj == nullptr) {
return;
}
bool bOk = false;
int nId = obj->property("dialogCmdId").toInt(&bOk);
if(bOk) {
markDialogCmdClosed(nId);
}
}
void nmSubWndMain::bindDialogCmdDestroyed(QWidget* dialog, int nId)
{
if(dialog == nullptr) {
return;
}
dialog->setProperty("dialogCmdId", nId);
connect(dialog, SIGNAL(destroyed(QObject*)), this, SLOT(onDialogCmdDestroyed(QObject*)));
}
void nmSubWndMain::bindMeasureDialog(QWidget* measureDlg)
{
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
if(plot == nullptr || measureDlg == nullptr) {
return;
}
disconnect(plot, SIGNAL(sigMeasureStarted()), measureDlg, SLOT(resetButtons()));
connect(plot, SIGNAL(sigMeasureStarted()), measureDlg, SLOT(resetButtons()));
disconnect(measureDlg, SIGNAL(needDeleteMeasureObj()), plot, SLOT(finishMeasure()));
connect(measureDlg, SIGNAL(needDeleteMeasureObj()), plot, SLOT(finishMeasure()));
}
QWidget* nmSubWndMain::showMeasureDialog()
{
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
if(plot == nullptr) {
return nullptr;
}
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
if(pDialogProvider == nullptr) {
return nullptr;
}
QWidget* measureDlg = pDialogProvider->createMeasureDialog(plot);
if(measureDlg == nullptr) {
return nullptr;
}
markDialogCmdOpened(5129);
measureDlg->setObjectName("nmMeasureDialog");
measureDlg->setAttribute(Qt::WA_DeleteOnClose, true);
bindDialogCmdDestroyed(measureDlg, 5129);
nmDataMeasure* measureData = nmDataAnalyzeManager::getCurrentInstance()->getMeasureData();
if(measureData != nullptr) {
connect(measureData, SIGNAL(sigMeasureDataChanged()), measureDlg, SLOT(updateDisplay()));
}
measureDlg->show();
return measureDlg;
}
QWidget* nmSubWndMain::showPointerPosDialog()
{
nmGuiPlot* plot = dynamic_cast<nmGuiPlot*>(m_pWxPlot);
if(plot == nullptr) {
return nullptr;
}
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
if(pDialogProvider == nullptr) {
return nullptr;
}
QWidget* pointerPosDlg = pDialogProvider->createPointerPosDialog(plot);
if(pointerPosDlg == nullptr) {
return nullptr;
}
markDialogCmdOpened(5128);
pointerPosDlg->setObjectName("nmPointerPosDialog");
pointerPosDlg->setAttribute(Qt::WA_DeleteOnClose, true);
bindDialogCmdDestroyed(pointerPosDlg, 5128);
plot->bindPointerPosDialog(pointerPosDlg);
pointerPosDlg->show();
return pointerPosDlg;
}
void nmSubWndMain::generationMesh()
{
// // TODO还不支持原型边界
// // 拿到多边形和点的位置信息
// QVector<ZxObjBase*> pObjVec = m_pWxPlot->getObjsByTag("nObjPolygonOutline");
// nmDataLogFile::getInstance()->writeLog(" ---------- " + QString::number(pObjVec.count()));
// QVector<ZxObjBase*> pWellObjVec = m_pWxPlot->getObjsByTag("nObjPointWell");
// nmDataLogFile::getInstance()->writeLog(" ---------- " + QString::number(pWellObjVec.count()));
// // 生成geo文件
// // 调用gmsh生成vtk文件
// // 弹出网格的dialog渲染文件
// if(true) {
// QDialog* dlg = new QDialog;
// QVBoxLayout* layout = new QVBoxLayout;
// dlg->setLayout(layout);
// nmWxGridVTKContainerWidget* gridVTKContainerWidget = new nmWxGridVTKContainerWidget(dlg);
// layout->addWidget(gridVTKContainerWidget);
// dlg->resize(800, 600);
// dlg->show();
// }
}
void nmSubWndMain::solveAndAnalyze()
{
// 关闭查看井数据对话框
if(m_resultDataDlg != nullptr) {
delete m_resultDataDlg;
m_resultDataDlg = nullptr;
}
// 强制清理旧的(以防万一上次没删掉)
if (m_pProgressDlg != nullptr) {
delete m_pProgressDlg;
m_pProgressDlg = nullptr;
}
// 根据当前数据中心的分析切换到对应的流动段分析窗口
ZxMainWindow* pMainWnd1 = const_cast<ZxMainWindow*>(m_pMainWindow);
if(nullptr == pMainWnd1) {
return;
}
ZxTabWidget* pTabWx = pMainWnd1->getCurTabWx();
iSubWndFitting* pSubWndFit = nmDataAnalyzeManager::getCurrentFitting();
Q_ASSERT(pSubWndFit != nullptr);
if(pSubWndFit == nullptr) {
return;
}
pTabWx->setCurrentWidget(pSubWndFit);
// 调用求解器
QString sPostprocessingPath = "";
// 获取计算类型
NM_Grid_Type gridType = nmDataAnalyzeManager::getCurrentInstance()->getGridType();
// PEBI求解直接使用当前后处理目录
if(gridType == NM_Grid_PEBI) {
//sPostprocessingPath = sPostprocessingPath + "/Pebi";
}
// 以前由旧的DLL求解器单例阻止重复启动删掉中间层后在这里保留同样的保护。
if(!s_pRunningSolverTask.isNull() && s_pRunningSolverTask->isRunning()) {
QMessageBox::information(this, tr("solver error"), tr("task is running!"));
return;
}
if(m_pSolverTask != nullptr) {
// 上一次线程已结束但指针还未清空时先交给Qt事件循环安全释放。
m_pSolverTask->deleteLater();
m_pSolverTask = nullptr;
}
// 直接创建真正执行DLL计算的PEBI线程任务替代原来的中间转发层。
m_pSolverTask = new nmCalculationDllPebiSolverTask(sPostprocessingPath);
s_pRunningSolverTask = m_pSolverTask;
connect(m_pSolverTask, SIGNAL(sig_calculateDone(bool)), this, SLOT(on_solverTaskFinished(bool)));
connect(m_pSolverTask, SIGNAL(finished()), m_pSolverTask, SLOT(deleteLater()));
// 1. 创建并配置进度对话框
if (m_pProgressDlg == nullptr)
{
// TODO:关联到父窗口
m_pProgressDlg = new QProgressDialog(tr("Calculating, please wait..."), QString(), 0, 100, getMainWindow());
m_pProgressDlg->setWindowTitle(tr("Solver Progress"));
m_pProgressDlg->setWindowModality(Qt::NonModal); // 模态,锁定父窗口
// 某些系统下,对话框右上角的关闭按钮可能仍存
// 使用 WindowFlags 彻底禁用关闭按钮
m_pProgressDlg->setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
}
m_pProgressDlg->setValue(0);
m_pProgressDlg->show();
m_pProgressDlg->raise(); // 提升层级到最前
m_pProgressDlg->activateWindow(); // 激活窗口焦点
// 2. 初始化模拟进度逻辑
// 每次计算启动前,务必清零
m_nVirtualProgress = 0;
m_nSlowDownCounter = 0;
// 创建定时器 (如果不存在)
if (m_pFakeProgressTimer == nullptr) {
m_pFakeProgressTimer = new QTimer(this);
connect(m_pFakeProgressTimer, SIGNAL(timeout()), this, SLOT(slotUpdateFakeProgress()));
}
// 3. 启动计算并开启模拟进度
m_pSolverTask->start();
m_pFakeProgressTimer->start(500); // 每 500 毫秒增加一次
}
void nmSubWndMain::triggerToolBarAction(int index)
{
// 获取多边形边界的绘制,并模拟触发点击操作
// 目前多边形边界绘制是工具栏的第4个所以用 3
if (m_pPlotToolBar == nullptr) return;
QList<QAction *> actions = m_pPlotToolBar->actions();
if(!actions.isEmpty() && index >= 0 && index < actions.count()) {
QAction *action = actions[index];
action->trigger();
}
}
void nmSubWndMain::mergeAnaResultToFitting()
{
// 渲染数据时弹出查看井数据的对话框
viewWellData();
//QMessageBox::information(this, tr("solver success"), tr("solver succeed!"));
/*if (m_parameterPropertyWindow != nullptr) {
delete m_parameterPropertyWindow;
m_parameterPropertyWindow = nullptr;
}
m_parameterPropertyWindow = new nmWxParameterProperty(this);
m_parameterPropertyWindow->show();*/
ZxMainWindow* pMainWnd1 = const_cast<ZxMainWindow*>(m_pMainWindow);
if(nullptr == pMainWnd1) {
return;
}
iSubWndFitting* pSubWndFit = nmDataAnalyzeManager::getCurrentFitting();
Q_ASSERT(pSubWndFit != nullptr);
if(pSubWndFit == nullptr) {
return;
}
// 历史压力数据
QVector<QVector<double >> vvecHistoryData;
// 双对数数据
QVector<QVector<double >> vvecLogPreData;
// 半对数数据
QVector<QVector<double >> vvecSemiLogPreData;
nmDataAnalyzeManager* pInstance = nmDataAnalyzeManager::getCurrentInstance();
if(pInstance == nullptr) {
return;
}
// 获取参与计算的井
QVector<QPair<NM_WELL_MODEL, QString>> vecWellsOrder = pInstance->getCalculationWells();
// 获取当前查看井的井名
nmDataWellBase* pCurWellData = pInstance->getCurWellData();
QString currentWellName;
if(pCurWellData != nullptr) {
currentWellName = pCurWellData->getWellName();
}
// 判断当前井是否参与计算
if(!pInstance->isContainsWellName(currentWellName)) {
for(int i = 0; i < vecWellsOrder.size(); i++) {
// 跳过裂缝
if(vecWellsOrder[i].first == NM_WELL_MODEL::Unknow_Well) {
continue;
}
// 未参与计算,选择展示第一口计算井的数据
currentWellName = vecWellsOrder[i].second;
break;
}
}
// PEBI结果按井名保存直接读取当前井的三条结果曲线
nmDataWellBase* pWellData = NULL;
if(pInstance->getGridType() == NM_Grid_PEBI) {
pWellData = pInstance->findWellByName(currentWellName);
if(pWellData == NULL) {
return;
}
// 获取该井下存储的三条数据
vvecHistoryData = pWellData->getResultPressure();
vvecLogPreData = pWellData->getResultLogLog();
vvecSemiLogPreData = pWellData->getResultSemiLog();
}
// 半对数
QVector<iCurveDesc> vecHalfLog;
this->inithalfLog(vvecSemiLogPreData, vecHalfLog, false);
FitSubRstTag tag = FSRT_SemiLog; // 半对数
QString errorMessage;
pSubWndFit->adjustFitSubPlotBy(tag, vecHalfLog, true, &errorMessage);
// 双对数
QVector<iCurveDesc> vecLogLog;
this->initloglog(vvecLogPreData, vecLogLog, false);
tag = FSRT_DoubleLog;
pSubWndFit->adjustFitSubPlotBy(tag, vecLogLog, true, &errorMessage);
// 历史压力曲线
QVector<iCurveDesc> vecHistory;
this->initPreHistory(vvecHistoryData, vecHistory, false);
tag = FSRT_Hist;
QString errorMessage4;
pSubWndFit->adjustFitSubPlotBy(tag, vecHistory, true, &errorMessage4);
// 更新结果基础网格,与当前实时生成的网格保持一致
pInstance->setResultBaseGrid(pInstance->getUnstructuredGridCopy());
QWidget* widget1 = pSubWndFit->getFitSubRstWxOf(FSRT_Nm3D, true, &errorMessage);
// 创建 vtkWidget
nmWxPostprocessingAnimationWidget* vtkWidget = nullptr;
if(pInstance->getGridType() == NM_Grid_PEBI) {
vtkWidget = new nmWxPostprocessingAnimationWidget(NULL);
}
if(widget1 == nullptr || vtkWidget == nullptr) {
delete vtkWidget;
return;
}
// 先清理
// 获取当前布局
QLayout* layout1 = widget1->layout();
if(layout1) {
// 移除布局中的所有控件
QLayoutItem* item;
while((item = layout1->takeAt(0))) {
if(item->widget()) {
// 删除控件
delete item->widget();
}
delete item; // 删除布局项
}
// 删除布局
delete layout1;
}
// 确保布局被移除
widget1->setLayout(nullptr);
// 创建一个垂直布局管理器
QVBoxLayout* newLayout1 = new QVBoxLayout(widget1);
// 将现有的控件添加到布局中
newLayout1->addWidget(vtkWidget);
// 设置 widget 的布局
widget1->setLayout(newLayout1);
// 结果参数界面
QWidget* widget2 = pSubWndFit->getFitSubRstWxOf(FSRT_NmRst, true, &errorMessage);
if(widget2 == nullptr) {
return;
}
// 创建结果参数界面
nmWxResultParameters* resultWidget = new nmWxResultParameters;
// 先清理
// 获取当前布局
QLayout* layout2 = widget2->layout();
if(layout2) {
// 移除布局中的所有控件
QLayoutItem* item;
while((item = layout2->takeAt(0))) {
if(item->widget()) {
// 删除控件
delete item->widget();
}
delete item; // 删除布局项
}
// 删除布局
delete layout2;
}
// 确保布局被移除
widget2->setLayout(nullptr);
// 创建一个垂直布局管理器
QVBoxLayout* newLayout2 = new QVBoxLayout(widget2);
// 将现有的控件添加到布局中
newLayout2->addWidget(resultWidget);
// 设置 widget 的布局
widget2->setLayout(newLayout2);
//nmWxResultParameters* resultWidget = new nmWxResultParameters;
//resultWidget->show();
}
bool nmSubWndMain::inithalfLog(QVector<QVector<double >> & vvecLogPreData, QVector<iCurveDesc>& vecDescs, bool isHistoryData)
{
// 半对数压力曲线
iCurveDesc curveDesc;
if(vvecLogPreData.size() != 2) {
vecDescs.append(curveDesc);
return false;
}
// X轴数据
curveDesc.m_vecX = vvecLogPreData[0];
// Y轴数据
curveDesc.m_vecY = vvecLogPreData[1];
curveDesc.m_oCurveType = POT_CurvePressure;
// 判断是历史数据还是计算数据
if(isHistoryData) {
curveDesc.m_sCurveName = s_SemiSouce_Curve;
curveDesc.m_bLineVisible = false; // 关闭线模式可见性
curveDesc.m_bPointVisible = true; // 开启点模式可见性
curveDesc.m_oDot.setColor(Qt::red); // 设置点的颜色
curveDesc.m_oDot.setStyle(ZxDotType::DTS_Cross); // x形状
} else {
curveDesc.m_sCurveName = s_SemiTheorySouce_Curve; // 理论曲线
curveDesc.m_bLineVisible = true; // 开启线模式可见性
curveDesc.m_bPointVisible = false; // 关闭点模式可见性
curveDesc.m_oPen.setColor(Qt::green); // 设置线的颜色
}
// 将 curveDesc 添加到 QVector
vecDescs.append(curveDesc);
return true;
}
bool nmSubWndMain::initloglog(QVector<QVector<double> > &vvecLogPreData, QVector<iCurveDesc>& vecDescs, bool isHistoryData)
{
// 双对数压力曲线
iCurveDesc curveDesc1, curveDesc2;
if(vvecLogPreData.size() != 3) {
vecDescs.append(curveDesc1);
vecDescs.append(curveDesc2);
return false;
}
// 确保每个内部 QVector 都不为空,然后移除其最后一个元素
// 移除 vvecLogPreData[0] (vX) 中的最后一个元素
if(!vvecLogPreData[0].isEmpty()) {
vvecLogPreData[0].remove(vvecLogPreData[0].size() - 1);
} else {
return false;
}
// 移除 vvecLogPreData[1] (vY) 中的最后一个元素
if(!vvecLogPreData[1].isEmpty()) {
vvecLogPreData[1].remove(vvecLogPreData[1].size() - 1);
} else {
return false;
}
// 移除 vvecLogPreData[2] (vZ) 中的最后一个元素
if(!vvecLogPreData[2].isEmpty()) {
vvecLogPreData[2].remove(vvecLogPreData[2].size() - 1);
} else {
return false;
}
// 曲线1
curveDesc1.m_vecX = vvecLogPreData[0];
curveDesc1.m_vecY = vvecLogPreData[1];
// 曲线2
curveDesc2.m_vecX = vvecLogPreData[0];
curveDesc2.m_vecY = vvecLogPreData[2];
curveDesc1.m_oCurveType = POT_CurveDiscrete;
curveDesc2.m_oCurveType = POT_CurveDiscrete;
// 判断是历史数据还是计算数据
if(isHistoryData) {
curveDesc1.m_sCurveName = s_Souce_Curve;
curveDesc2.m_sCurveName = s_Deriv_Curve;
curveDesc1.m_bLineVisible = false; // 关闭线模式可见性
curveDesc1.m_bPointVisible = true; // 开启点模式可见性
curveDesc1.m_oDot.setColor(Qt::green); // 设置点的颜色
curveDesc1.m_oDot.setStyle(ZxDotType::DTS_Cross); // X形状
curveDesc2.m_bLineVisible = false; // 关闭线模式可见性
curveDesc2.m_bPointVisible = true; // 开启点模式可见性
curveDesc2.m_oDot.setColor(Qt::red); // 设置点的颜色
curveDesc2.m_oDot.setStyle(ZxDotType::DTS_Circle); // O形状
curveDesc2.m_oDot.setFilling(false); // 不填充
} else {
curveDesc1.m_sCurveName = s_TheorySouce_Curve;
curveDesc2.m_sCurveName = s_TheoryDeriv_Curve;
curveDesc1.m_bLineVisible = true; // 关闭线模式可见性
curveDesc1.m_bPointVisible = false; // 开启点模式可见性
curveDesc1.m_oPen.setColor(Qt::red); // 设置线的颜色
curveDesc2.m_bLineVisible = true; // 关闭线模式可见性
curveDesc2.m_bPointVisible = false; // 开启点模式可见性
curveDesc2.m_oPen.setColor(Qt::green); // 设置线的颜色
}
// 将 curveDesc 添加到 QVector
vecDescs.append(curveDesc1);
// 将 curveDesc 添加到 QVector
vecDescs.append(curveDesc2);
return true;
}
bool nmSubWndMain::initPreHistory(QVector<QVector<double> > &vvecHistoryData, QVector<iCurveDesc>& vecDescs, bool isHistoryData)
{
// 压力曲线
iCurveDesc curveDesc;
if(vvecHistoryData.size() != 2) {
vecDescs.append(curveDesc);
return false;
}
// X轴数据
curveDesc.m_vecX = vvecHistoryData[0];
// Y轴数据
curveDesc.m_vecY = vvecHistoryData[1];
curveDesc.m_oCurveType = POT_CurvePressure;
// 判断是历史数据还是计算数据
if(isHistoryData) {
curveDesc.m_sCurveName = s_HistorySouce_CurveP;
curveDesc.m_bLineVisible = false; // 关闭线模式可见性
curveDesc.m_bPointVisible = true; // 开启点模式可见性
curveDesc.m_oDot.setColor(Qt::red); // 设置点的颜色
curveDesc.m_oDot.setStyle(ZxDotType::DTS_Plus); // +形状
} else {
curveDesc.m_sCurveName = s_HistoryFit_CurveP;
curveDesc.m_bLineVisible = true; // 关闭线模式可见性
curveDesc.m_bPointVisible = false; // 开启点模式可见性
curveDesc.m_oPen.setColor(Qt::green); // 设置线的颜色
}
// 将 curveDesc 添加到 QVector
vecDescs.append(curveDesc);
return true;
}
bool nmSubWndMain::onConfirmClosing()
{
return iSubWndBaseAF::onConfirmClosing();
}
void nmSubWndMain::reservoirCharacteristics()
{
nmWxReservoirPropertiesDlg dlg;
dlg.exec();
// TODO: 修改完参数应该刷新画布
}
void nmSubWndMain::geoLayering()
{
nmWxGeometryLayerDlg dlg;
if(dlg.exec() == QDialog::Rejected) {
return;
} else {
QVector<nmDataLayer*> layers = dlg.getLayerData();
// 添加到数据中心
nmDataAnalyzeManager::getCurrentInstance()->setLayers(layers);
//for (int i = 0; i < layers.size(); ++i) {
// nmDataLayer* layer = layers[i];
// qDebug() << "Layer" << i + 1 << "Top:" << layer->getTop()
// << "Bottom:" << layer->getBottom()
// << "Thickness:" << layer->getThickness()
// << "IsChecked:" << layer->getIsChecked();
//}
}
}
void nmSubWndMain::on_calculationFinished(NM_Calculation_Result result)
{
// 1. 立即停止模拟定时器(防止它在处理结果时继续触发)
if (m_pFakeProgressTimer) {
m_pFakeProgressTimer->stop();
}
// 2. 强制拉满进度条(给用户一个成功的反馈)
if (m_pProgressDlg) {
m_pProgressDlg->setValue(100);
}
// 3. 处理计算结果
if(result == NM_Calculation_Result_Success) {
// 创建结果对象,显示曲线
nmDataAnalyzeManager::getCurrentInstance()->createMixedResult();
this->mergeAnaResultToFitting();
} else {
// 如果失败,进度条其实没必要拉满了,直接提示错误
QMessageBox::warning(this, tr("solver error"), tr("solver failed!"));
}
// 4. 直接销毁对象并置空
if (m_pProgressDlg != nullptr) {
delete m_pProgressDlg;
m_pProgressDlg = nullptr;
}
}
void nmSubWndMain::on_solverTaskFinished(bool isSuccessed)
{
// 线程完成后清空两个持有点:当前窗口指针和全局运行中指针。
nmCalculationDllPebiSolverTask* pTask = qobject_cast<nmCalculationDllPebiSolverTask*>(sender());
if(pTask == m_pSolverTask) {
m_pSolverTask = nullptr;
}
if(pTask == s_pRunningSolverTask) {
s_pRunningSolverTask = nullptr;
}
// 保持旧流程不变bool结果转换为计算结果枚举再交给原来的统一后处理函数。
NM_Calculation_Result result = isSuccessed ? NM_Calculation_Result_Success : NM_Calculation_Result_Fail;
this->on_calculationFinished(result);
}
void nmSubWndMain::deleteOneObj()
{
this->triggerToolBarAction(NMOT_Delete);
}
void nmSubWndMain::setLocked()
{
if(m_lockState) { // 锁定
m_lockState = false;
int objCount = this->m_pWxPlot->m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = this->m_pWxPlot->m_pPlot->getObjByIndex(i);
if(!_isSame("nObjPointWell", obj->getTagName())) {
obj->setReadOnly(false);
obj->setLockPos(false);
}
}
QStringList nIDs;
nIDs.append("5125");
nIDs.append("5124");
nIDs.append("5123");
nIDs.append("5114");
nIDs.append("5115");
nIDs.append("5116");
nIDs.append("5117");
nIDs.append("5118");
nIDs.append("5119");
nIDs.append("5102");
nIDs.append("5120");
nIDs.append("5103");
nIDs.append("5104");
nIDs.append("5105");
nIDs.append("5106");
nIDs.append("5107");
nIDs.append("5108");
nIDs.append("5109");
nIDs.append("5110");
nIDs.append("5111");
nIDs.append("5121");
nIDs.append("5112");
nIDs.append("5113");
nIDs.append("5122");
nIDs.append("9002");
nIDs.append("9003");
nIDs.append("9101");
nIDs.append("9102");
nIDs.append("9103");
nIDs.append("9104");
nIDs.append("3104");
emit sigFreshRnStates(nIDs);
/*
if (m_pMainWindow != NULL) {
//m_pMainWindow->slotFreshRnStates(nIDs);
}
*/
//m_pMainWindow->getMainRibbon
} else {
m_lockState = true;
int objCount = this->m_pWxPlot->m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = this->m_pWxPlot->m_pPlot->getObjByIndex(i);
if(!_isSame("nObjPointWell", obj->getTagName())) {
obj->setReadOnly(true);
obj->setLockPos(true);
}
}
QStringList nIDs;
nIDs.append("5125");
nIDs.append("5124");
nIDs.append("5123");
nIDs.append("5114");
nIDs.append("5115");
nIDs.append("5116");
nIDs.append("5117");
nIDs.append("5118");
nIDs.append("5119");
nIDs.append("5102");
nIDs.append("5120");
nIDs.append("5103");
nIDs.append("5104");
nIDs.append("5105");
nIDs.append("5106");
nIDs.append("5107");
nIDs.append("5108");
nIDs.append("5109");
nIDs.append("5110");
nIDs.append("5111");
nIDs.append("5121");
nIDs.append("5112");
nIDs.append("5113");
nIDs.append("5122");
//nIDs.append("9002");
//nIDs.append("9003");
nIDs.append("9101");
nIDs.append("9102");
nIDs.append("9103");
nIDs.append("9104");
nIDs.append("3104");
emit sigFreshRnStates(nIDs);
/*
if (m_pMainWindow != NULL) {
m_pMainWindow->slotFreshRnStates(nIDs);
}
*/
/*
emit sigFreshRnStates(nIDs);
if (m_pMainWindow != NULL) {
m_pMainWindow->slotFreshRnStates(nIDs);
}
bool b;
QString sName = "NmUnlocked";
int nID = 5119;
bool bLicensed;
nmSubWndMain::checkCmdEnable(b, sName, nID, bLicensed);
nID = 5125;
sName = "NmPrint";
nmSubWndMain::checkCmdEnable(b, sName, nID, bLicensed);
*/
}
}
nmGuiPlot * nmSubWndMain::getWxPlot() const
{
return m_pWxPlot;
}
void nmSubWndMain::onProgressUpdated(int progress)
{
if (!m_pProgressDlg) {
return;
}
// 1. 处理特殊结束信号
if (progress >= 100 || progress == -1) {
// 停止模拟定时器,防止它继续累加
if (m_pFakeProgressTimer && m_pFakeProgressTimer->isActive()) {
m_pFakeProgressTimer->stop();
}
m_pProgressDlg->setValue(100);
return;
}
// 2. 进度倒退保护
// 如果模拟进度已经跑到了 50%,但某个真实信号传回来 40%
// 为了防止进度条“倒着走”引起用户困惑,只有当前值更大时才更新。
if (progress > m_pProgressDlg->value()) {
m_pProgressDlg->setValue(progress);
// 同步更新模拟变量,防止定时器下次触发时使用旧值
m_nVirtualProgress = progress;
}
}
void nmSubWndMain::viewWellData()
{
// 1.获取当前查看井的井名(默认选中)
nmDataWellBase* pCurWellData = nmDataAnalyzeManager::getCurrentInstance()->getCurWellData();
QString currentWellName;
if(pCurWellData != nullptr) {
currentWellName = pCurWellData->getWellName();
}
// 2.找到计算了的井
QVector<QPair<NM_WELL_MODEL, QString>> vecWellsOrder = nmDataAnalyzeManager::getCurrentInstance()->getCalculationWells();
// 释放内存
if(m_resultDataDlg != nullptr) {
delete m_resultDataDlg;
m_resultDataDlg = nullptr;
}
// 3.创建对话框和井列表控件
m_resultDataDlg = new nmWxSelectResultWellsDlg;
nmWxSelectResultWellsWidget *wellListWidget = new nmWxSelectResultWellsWidget;
// 4.添加所有参与计算的井
for(int i = 0; i < vecWellsOrder.size(); i++) {
// 跳过裂缝
if(vecWellsOrder[i].first == NM_WELL_MODEL::Unknow_Well) {
continue;
}
wellListWidget->addItem(vecWellsOrder[i].second);
}
// 5.设置当前选中的井
if(nmDataAnalyzeManager::getCurrentInstance()->isContainsWellName(currentWellName)) {
// 当前井参与计算,直接选择当前井
wellListWidget->setSelectedItem(currentWellName);
} else {
// 当前井没有参与计算,选择参与计算的第一口井
wellListWidget->setSelectedItem(vecWellsOrder[0].second);
for(int i = 0; i < vecWellsOrder.size(); i++) {
// 跳过裂缝
if(vecWellsOrder[i].first == NM_WELL_MODEL::Unknow_Well) {
continue;
}
wellListWidget->setSelectedItem(vecWellsOrder[i].second);
break;
}
}
// 6.设置控件并连接信号
m_resultDataDlg->setWidget(wellListWidget);
connect(m_resultDataDlg, SIGNAL(wellSelected(QString)), this, SLOT(onWellSelected(QString)));
// 7.显示对话框
m_resultDataDlg->show();
}
void nmSubWndMain::onWellSelected(const QString& wellName)
{
nmDataAnalyzeManager* pInstance = nmDataAnalyzeManager::getCurrentInstance();
if(pInstance == nullptr) {
return;
}
// 更新数据中心的当前查看井数据
nmDataWellBase* pCurWellData = pInstance->getCurWellData();
if(pCurWellData == nullptr)
return;
// 查找切换后的井数据
nmDataWellBase* pWellData = NULL;
pWellData = pInstance->findWellByName(wellName);
if(pWellData == NULL)
return;
if(pCurWellData->getWellName() != wellName) {
// 设置为当前查看井数据
pInstance->setCurWellData(pWellData);
}
// 1.获取流动段分析窗口
iSubWndFitting* pSubWndFit = nmDataAnalyzeManager::getCurrentFitting();
Q_ASSERT(pSubWndFit != nullptr);
if(!pSubWndFit) return;
// 2.根据选择的井名获取计算数据
QVector<QVector<double>> vvecHistoryData;
QVector<QVector<double>> vvecLogPreData;
QVector<QVector<double>> vvecSemiLogPreData;
if(pInstance->getGridType() == NM_Grid_PEBI) {
vvecHistoryData = pWellData->getResultPressure();
vvecLogPreData = pWellData->getResultLogLog();
vvecSemiLogPreData = pWellData->getResultSemiLog();
}
// 调用函数
QVector<QVector<double>> vvecHistoryPressureData; //压力历史数据
QVector<QVector<double>> vvecHistoryLogData; // 历史双对数曲线数据
QVector<QVector<double>> vvecHistorySemiLogData; // 历史半对数曲线数据
pInstance->calculationLogData(pWellData, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
// 删除末尾无效元素
//if (!vvecHistoryLogData.empty() &&
// vvecHistoryLogData.size() >= 3 && // 确保有3个子数组
// !vvecHistoryLogData[0].empty() && // 检查x数组非空
// !vvecHistoryLogData[1].empty() && // 检查y数组非空
// !vvecHistoryLogData[2].empty()) { // 检查z数组非空
// // 同时删除x、y、z的最后一个数据点
// vvecHistoryLogData[0].removeLast(); // 删除最后一个x
// vvecHistoryLogData[1].removeLast(); // 删除最后一个y
// vvecHistoryLogData[2].removeLast(); // 删除最后一个z
//}
// 窗口标识,半对数、双对数、历史压力
FitSubRstTag tag;
// 错误信息
QString errorMessage;
// 3、半对数曲线
QVector<iCurveDesc> vecHistoryHalfLog;
this->inithalfLog(vvecHistorySemiLogData, vecHistoryHalfLog, true);
tag = FSRT_SemiLog;
// 删除原来的线,并将当前查看井的历史半对数曲线渲染出来
pSubWndFit->adjustFitSubPlotBy(tag, vecHistoryHalfLog, true, &errorMessage);
//计算出来的半对数数据,同样需要删除原来的
QVector<iCurveDesc> vecHalfLog;
this->inithalfLog(vvecSemiLogPreData, vecHalfLog, false);
pSubWndFit->adjustFitSubPlotBy(tag, vecHalfLog, true, &errorMessage);
// 双对数
QVector<iCurveDesc> vecHistoryLog;
this->initloglog(vvecHistoryLogData, vecHistoryLog, true);
tag = FSRT_DoubleLog;
// 删除原来的线,并将当前查看井的历史双对数曲线渲染出来
pSubWndFit->adjustFitSubPlotBy(tag, vecHistoryLog, true, &errorMessage);
//计算出来的双对数数据,同样需要删除原来的
QVector<iCurveDesc> vecLogLog;
this->initloglog(vvecLogPreData, vecLogLog, false);
pSubWndFit->adjustFitSubPlotBy(tag, vecLogLog, true, &errorMessage);
// 历史压力曲线
QVector<iCurveDesc> vecHistoryPre;
this->initPreHistory(vvecHistoryPressureData, vecHistoryPre, true);
tag = FSRT_Hist;
// 删除原来的线,并将当前查看井的历史压力曲线渲染出来
pSubWndFit->adjustFitSubPlotBy(tag, vecHistoryPre, true, &errorMessage);
//计算出来的压力数据,同样需要删除原来的
QVector<iCurveDesc> vecHistory;
this->initPreHistory(vvecHistoryData, vecHistory, false);
pSubWndFit->adjustFitSubPlotBy(tag, vecHistory, true, &errorMessage);
}
#include <Windows.h>
//void nmSubWndMain::calculationLogData(
// nmDataWellBase* pWellData,
// QVector<QVector<double>>& vvecHistoryData,
// QVector<QVector<double>>& vvecLogPreData,
// QVector<QVector<double>>& vvecSemiLogPreData)
//{
// // 清空输出参数
// vvecHistoryData.clear();
// vvecLogPreData.clear();
// vvecSemiLogPreData.clear();
//
// if(pWellData == nullptr) {
// return;
// }
//
// // 初始化二维数组结构
// vvecHistoryData.resize(2); // [0]=x, [1]=y
// vvecLogPreData.resize(3); // [0]=x, [1]=y, [2]=z
// vvecSemiLogPreData.resize(2); // [0]=x, [1]=pointData[0]
//
// // 准备压力数据
// QVector<QPointF> vecPressure = pWellData->getPressurePoints();
// std::vector<Point> wellPressureData;
//
// // 填充 wellPressureData 和 vvecHistoryData
// foreach(const QPointF& qpoint, vecPressure) {
// // wellPressureData
// Point pt;
// pt.x = qpoint.x();
// pt.y = qpoint.y();
// pt.z = 0.0;
// wellPressureData.push_back(pt);
//
// // vvecHistoryData
// vvecHistoryData[0].append(qpoint.x()); // x
// vvecHistoryData[1].append(qpoint.y()); // y
// }
//
// // 准备流量段数据
// QVector<QPointF> vecTimeQ = pWellData->getFlowPoints();
// int nTimeNumQ = vecTimeQ.size() - 1;
// std::vector<double> timeQ(nTimeNumQ);
// std::vector<double> q(nTimeNumQ);
//
// for(int i = 0; i < nTimeNumQ; ++i) {
// timeQ[i] = vecTimeQ[i + 1].x();
// q[i] = vecTimeQ[i + 1].y();
// }
//
// // 调用 DLL 计算双对数曲线
// std::vector<Point> logPre;
// int iSectionFlowIndex = pWellData->getIndexF();
//
// HMODULE hMod_solver = LoadLibrary(L"singlePhaseSolverDll.dll");
//
// if(hMod_solver) {
// typedef bool (*PreLog)(const std::vector<Point>&, const int&, double*, double*, int, std::vector<Point>&);
// PreLog preLogFun = (PreLog)GetProcAddress(hMod_solver, "logLogPre");
//
// if(nullptr == preLogFun) {
// FreeLibrary(hMod_solver);
// std::cout << "preLogFun failed!\n";
// return;
// }
//
// preLogFun(wellPressureData, iSectionFlowIndex, timeQ.data(), q.data(), nTimeNumQ, logPre);
//
// // 不添加最后一个元素
// for(uint i = 0; i < logPre.size() - 1; i++) {
// //logFile << logPre[i].x << "\t" << logPre[i].y << "\t" << logPre[i].z << "\t" << std::endl;
// vvecLogPreData[0].append(logPre[i].x); // x
// vvecLogPreData[1].append(logPre[i].y); // y
// vvecLogPreData[2].append(logPre[i].z); // z
// }
//
// // 填充半对数曲线数据 (x, pointData[0])
// foreach(const auto& point, logPre) {
// vvecSemiLogPreData[0].append(point.x); // x
// double y_value = point.pointData.empty() ? 0.0 : point.pointData[0];
// vvecSemiLogPreData[1].append(y_value); // pointData[0] 或默认值
// }
// FreeLibrary(hMod_solver);
// }
//}
void nmSubWndMain::onGenerateButtonClicked()
{
//QString sDir = ZxBaseUtil::getCurWellDirOf("Nm/PreProcessing");
if(nmDataAnalyzeManager::getCurrentInstance()->getGridType() == NM_Grid_PEBI) {
nmCalculationPebiGrid* pPebiGridGeneratorInstance = nmCalculationPebiGrid::getInstance();
if(pPebiGridGeneratorInstance->getGridOutput2().Trinodexy.size() <= 0) {
// 没有可用PEBI网格时才重新生成
if(!pPebiGridGeneratorInstance->meshGenPebi()) {
return;
}
}
// 求解计算
this->solveAndAnalyze();
}
}
void nmSubWndMain::slotUpdateFakeProgress()
{
// --- 1. 安全防御检查 ---
// 如果进度对话框已被销毁(例如计算提前结束或用户关闭),立即停止定时器并退出
// 防止在 delete 对象后发生野指针访问崩溃
if (m_pProgressDlg == nullptr) {
if (m_pFakeProgressTimer) {
m_pFakeProgressTimer->stop();
}
return;
}
// --- 2. 分段模拟进度逻辑 (0% - 99%) ---
// 采用“前快后慢”的心理学策略50% 之后逐级增加阻力,为 DLL 计算留出缓冲时间
if (m_nVirtualProgress < 99) {
// 步进计数器,用于实现非匀速增长
m_nSlowDownCounter++;
if (m_nVirtualProgress < 50) {
// [第一阶段] 0% - 50%: 快速增长
// 每次定时器触发(500ms)即增加 1%,给予用户“响应迅速”的反馈
m_nVirtualProgress += 1;
}
else if (m_nVirtualProgress < 75) {
// [第二阶段] 50% - 75%: 第一次减速
// 每触发 4 次(约 2秒)增加 1%,模拟进入核心计算阶段
if (m_nSlowDownCounter % 4 == 0) {
m_nVirtualProgress += 1;
}
}
else if (m_nVirtualProgress < 90) {
// [第三阶段] 75% - 90%: 第二次减速
// 每触发 8 次(约 4秒)增加 1%,应对较大规模的数据处理
if (m_nSlowDownCounter % 8 == 0) {
m_nVirtualProgress += 1;
}
}
else {
// [第四阶段] 90% - 99%: 深度减速 (极慢)
// 每触发 15 次(约 7.5秒)增加 1%。此时进度条几乎“爬行”,
// 旨在确保在 DLL 返回完成信号前,进度条不会提前撞击 100%
if (m_nSlowDownCounter % 15 == 0) {
m_nVirtualProgress += 1;
}
}
// 统一调用更新接口,同步 UI 显示
this->onProgressUpdated(m_nVirtualProgress);
}
else {
// --- 3. 终点停靠 ---
// 到达 99% 时停止自动增长,死等来自 Solver 线程的真正的 Finished 信号
if (m_pFakeProgressTimer) {
m_pFakeProgressTimer->stop();
}
}
}
void nmSubWndMain::generateDFN()
{
nmWxDFN dfnDialog(nullptr);
dfnDialog.exec();
}
void nmSubWndMain::displaySetting()
{
nmWxDisplaySettings disPlayDlg;
disPlayDlg.exec();
}
void nmSubWndMain::updateMapByDataManager(nmDataAnalyzeManager* pDataManager)
{
// 删除原来的图元信息
if(m_pWxPlot == nullptr) {
return;
}
// 更新对应的Plot成员变量
pDataManager->setPlot(m_pWxPlot);
m_pWxPlot->deleteAllPlotObjs();
// 根据数据中心内容绘制新图元
m_pWxPlot->setPlotsByDataManger(pDataManager);
}