feat(nmNum): 增加历史结果图窗口

- 主界面新增敏感性历史图,上方显示压力,下方显示流量。
- 复用求解快照和批次结果,同步 Results 曲线勾选。
- 支持关闭重开,重新求解模型后清除旧图。
feature/Sensitivity-20261012
lvjunjie 1 week ago
parent 924fbd724f
commit 15b684a329

@ -276,6 +276,8 @@ class NM_SUB_WND_EXPORT nmSubWndMain : public iSubWndBaseFit {
bool initloglog(QVector<QVector<double >> & vvecLogPreData, QVector<iCurveDesc>& vecDescs,bool isHistoryData); bool initloglog(QVector<QVector<double >> & vvecLogPreData, QVector<iCurveDesc>& vecDescs,bool isHistoryData);
// 压力历史曲线数据 // 压力历史曲线数据
bool initPreHistory(QVector<QVector<double >> & vvecHistoryData, QVector<iCurveDesc>& vecDescs,bool isHistoryData); bool initPreHistory(QVector<QVector<double >> & vvecHistoryData, QVector<iCurveDesc>& vecDescs,bool isHistoryData);
// 在分析页面内同步敏感性压力/流量历史图。
void updateSensitiveHistoryPlot();
// 根据原始压力数据、计算出半对数、双对数数据 // 根据原始压力数据、计算出半对数、双对数数据
//void calculationLogData(nmDataWellBase* pWellData,QVector<QVector<double>>& vvecHistoryData,QVector<QVector<double>>& vvecLogPreData,QVector<QVector<double>>& vvecSemiLogPreData); //void calculationLogData(nmDataWellBase* pWellData,QVector<QVector<double>>& vvecHistoryData,QVector<QVector<double>>& vvecLogPreData,QVector<QVector<double>>& vvecSemiLogPreData);

@ -65,6 +65,7 @@
#include "iSubWndFitting.h" #include "iSubWndFitting.h"
#include "iGuiPlotPF.h" #include "iGuiPlotPF.h"
#include "iGuiPlotTableHelper.h"
#include "iGuiPlot.h" #include "iGuiPlot.h"
#include "ZxObjCurveFlow.h" #include "ZxObjCurveFlow.h"
#include "iAnalRun.h" #include "iAnalRun.h"
@ -1873,6 +1874,7 @@ void nmSubWndMain::onShowSensitiveResults()
nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data(); nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data();
iSubWndFitting* fitting = m_pResultRefreshFitting.data(); iSubWndFitting* fitting = m_pResultRefreshFitting.data();
if(!manager || !fitting || !manager->getSensitiveData()) return; if(!manager || !fitting || !manager->getSensitiveData()) return;
updateSensitiveHistoryPlot();
QSharedPointer<nmDataSensitive::BatchResult> result = manager->getSensitiveData()->getResults(); QSharedPointer<nmDataSensitive::BatchResult> result = manager->getSensitiveData()->getResults();
iGuiPlot* plot = fitting->getPlotByTag(s_Tag_ChartSensitivity); iGuiPlot* plot = fitting->getPlotByTag(s_Tag_ChartSensitivity);
if(result.isNull()) { if(result.isNull()) {
@ -1987,6 +1989,106 @@ void nmSubWndMain::onShowSensitiveResults()
if(sender() == manager) fitting->setModified(true); if(sender() == manager) fitting->setModified(true);
} }
void nmSubWndMain::updateSensitiveHistoryPlot()
{
// 复用框架的上下压力/流量控件,作为同一分析页面中的独立 MDI 子窗口。
iSubWndFitting* fitting = m_pResultRefreshFitting.data();
nmDataAnalyzeManager* manager = m_pResultRefreshDataManager.data();
if(!fitting || !fitting->m_pMdiArea || !manager || !manager->getSensitiveData()) return;
ZxMdiArea* area = fitting->m_pMdiArea;
QMdiSubWindow* window = area->findChild<QMdiSubWindow*>("nmSensitivityHistory");
const QSharedPointer<nmDataSensitive::BatchResult> batch = manager->getSensitiveData()->getResults();
if(batch.isNull()) {
// 新模型丢弃旧批次时一并销毁窗口,曲线和撤销记录不再残留。
if(window) {
area->removeSubWindow(window);
delete window;
}
return;
}
const bool created = window == nullptr;
if(created) {
// PF 继承对话框,用普通页面承载,关闭子窗口时不进入其对话框关闭流程。
QWidget* page = new QWidget;
QVBoxLayout* layout = new QVBoxLayout(page);
layout->setContentsMargins(0, 0, 0, 0);
iGuiPlotPF* history = new iGuiPlotPF(s_Tag_HIST_PF, true, true, page);
history->setWindowFlags(Qt::Widget);
history->initUI(tr("Sensitivity history plot"));
history->setTableHelperVisible(false);
layout->addWidget(history);
window = area->addSubWindow(page);
window->setObjectName("nmSensitivityHistory");
window->setWindowTitle(tr("Sensitivity history plot"));
window->setAttribute(Qt::WA_DeleteOnClose, false);
}
iGuiPlotPF* history = window->findChild<iGuiPlotPF*>();
QVector<iCurveDesc> curves;
// 基准压力、实测压力和流量均取成功求解快照,未求解的参数或制度编辑不参与绘图。
const QSharedPointer<const nmPebiResultSnapshot> snapshot = manager->getPebiResultSnapshot();
for(int i = 0; !snapshot.isNull() && i < snapshot->getWellCount(); ++i) {
const nmPebiResultWellSnapshot* well = snapshot->getWellAt(i);
if(well->m_sWellCode != batch->m_sWellCode) continue;
QVector<QVector<double> > measured = well->m_oCurves.m_vecHistoryPressure;
QVector<QVector<double> > base = well->m_oCurves.m_vecResultPressure;
if(measured.size() == 2) initPreHistory(measured, curves, true);
if(base.size() == 2) {
initPreHistory(base, curves, false);
curves.last().m_sCurveName = nmWxSensitive::tr("Base model - Pressure");
}
const QVector<double>* rates = resultReferenceRatesOf(well);
if(rates && rates->size() == well->m_vecFlowDurations.size()) {
iCurveDesc flow;
flow.m_oCurveType = POT_CurveFlow;
flow.m_sCurveName = s_HistorySouce_CurveF;
flow.m_bLineVisible = true;
flow.m_bPointVisible = false;
flow.m_oPen.setColor(Qt::red);
// 与普通历史图一致,流量使用段时长并保留框架的首行占位点。
flow.m_vecX = well->m_vecFlowDurations;
flow.m_vecY = *rates;
flow.m_vecX.prepend(0.0);
flow.m_vecY.prepend(0.0);
curves.append(flow);
}
break;
}
for(size_t i = 0; i < batch->m_runs.size(); ++i) {
const nmDataSensitive::RunResult& run = batch->m_runs[i];
if(!run.m_bSucceeded || run.m_bCancelled || !run.m_bVisible || run.m_vecPressure.size() != 2) continue;
QVector<QVector<double> > pressure = run.m_vecPressure;
initPreHistory(pressure, curves, false);
curves.last().m_sCurveName = nmWxSensitive::tr("Run %1 - Pressure").arg(run.m_nRunIndex + 1);
curves.last().m_oPen.setColor(QColor::fromHsv(int((run.m_nRunIndex % 360) * 137 % 360), 190, 190));
}
// 框架不会删除本次未传入的曲线,刷新前清除旧图元,保证 Results 勾选同步生效。
iGuiPlot* plots[] = {history->m_pWxPlotP, history->m_pWxPlotF};
for(int i = 0; i < 2; ++i) {
iGuiPlot* plot = plots[i];
for(int j = plot->m_pPlot->getObjCount() - 1; j >= 0; --j)
if(qobject_cast<ZxObjCurve*>(plot->m_pPlot->getObjByIndex(j))) plot->m_pPlot->removeObjByIndex(j);
plot->clearUndoStack();
plot->setDropEnabled(false);
plot->setAxisXYLog(false, 0);
plot->setAxisXYLog(false, 1);
// PF 的统一分配面向普通历史曲线;多组结果直接交给对应的上下绘图控件。
QVector<iCurveDesc> data;
for(int j = 0; j < curves.size(); ++j)
if((curves[j].m_oCurveType == POT_CurveFlow) == (i == 1)) data.append(curves[j]);
plot->setCurveData(data);
plot->runUpdate();
plot->setReadOnly(true);
plot->freshAxisScales(true, true);
}
const bool restore = window->isHidden();
history->show();
window->widget()->show();
window->show();
// 历史图只显示曲线,隐藏框架默认的空数据表侧栏。
history->m_pTableHelper->hide();
if(created || restore) area->relayoutSubWnds();
}
void nmSubWndMain::startSolverTask() void nmSubWndMain::startSolverTask()
{ {
if(!m_bSolverStartPending) { if(!m_bSolverStartPending) {

Loading…
Cancel
Save