#ifndef NMDATAANALYZEMANAGER_H #define NMDATAANALYZEMANAGER_H #include #include "ZxDataObjectBin.h" #include "nmData_global.h" #include "nmDefines.h" #include "nmDataVerticalWell.h" #include "nmDataHorizontalWell.h" #include "nmDataVerticalFracturedWell.h" #include "nmDataHorizontalFracturedWell.h" #include "nmDataNumericalAnalysisCase.h" #include "nmNumericalResultPersistence.h" #include "nmDataGaugeRecord.h" #include "nmGridDefine.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // 子类别显示信息结构 struct ChildCategoryDisplayInfo { QString name; // 子项名称 bool isChecked; // 子项是否选中 bool isEnabled; // 子项是否启用 (取决于父项的选中状态) }; // 类别显示信息结构 struct CategoryDisplayInfo { bool isRootChecked; // 根节点是否选中 QVector childItems; // 子节点信息列表 }; // 整体 struct DisplaySetting { QString key; CategoryDisplayInfo value; }; // 油藏地图显示信息结构体 struct BackgroundImageInfo { bool bIsVisible; // 是否显示背景图片到地图 QString sFilePath; // 背景图片的文件路径 QImage objImage; // 具体的QImage对象 }; /* 插值测点数据 */ struct NM_DATA_EXPORT nmPropertyInterpolationPointData { nmPropertyInterpolationPointData() : x(0.0), y(0.0), value(0.0) { } nmPropertyInterpolationPointData(double xValue, double yValue, double propertyValue) : x(xValue), y(yValue), value(propertyValue) { } double x; double y; double value; }; /* 一组属性插值数据及其Kriging参数 */ struct NM_DATA_EXPORT nmPropertyInterpolationDataSet { nmPropertyInterpolationDataSet() : property("k"), xDisplayUnit("m"), yDisplayUnit("m"), valueDisplayUnit("mD"), rangeDisplayUnit("m"), useForCalculation(false), showPoints(true), showLabels(true), nugget(0.01), sill(100.0), range(1000.0), model(0) { } QString name; QString property; // 仅记录界面显示单位;坐标、Range及属性值始终按基准单位保存. QString xDisplayUnit; QString yDisplayUnit; QString valueDisplayUnit; QString rangeDisplayUnit; bool useForCalculation; QVector points; bool showPoints; bool showLabels; double nugget; double sill; double range; int model; }; enum NM_SOLVER_MODEL_TYPE { SMT_Oil_ConstPvt = 1, SMT_Oil_VariablePvt = 2, SMT_Water_ConstPvt = 3, SMT_Water_VariablePvt = 4, SMT_Gas_VariablePvt = 5, SMT_Gas_PseudoPressure = 6, SMT_Oil_Gas_TwoPhase = 7, SMT_Oil_Water_TwoPhase = 8, SMT_Gas_Water_TwoPhase = 9, SMT_Oil_Gas_Water_ThreePhase = 10 }; /** @brief 当前 PEBI 接入层已经开放的求解模型范围。 */ inline bool nmIsSupportedPebiSolverModel( NM_SOLVER_MODEL_TYPE eSolverModelType) { switch(eSolverModelType) { case SMT_Oil_ConstPvt: case SMT_Oil_VariablePvt: case SMT_Water_ConstPvt: case SMT_Water_VariablePvt: case SMT_Gas_VariablePvt: case SMT_Gas_PseudoPressure: case SMT_Oil_Water_TwoPhase: return true; default: return false; } } /** @brief 判断求解模型是否包含指定工程井别对应的流量相。 */ inline bool nmSolverModelSupportsWellCategory( NM_SOLVER_MODEL_TYPE eSolverModelType, NM_WELL_CATEGORY eWellCategory) { switch(eSolverModelType) { case SMT_Oil_ConstPvt: case SMT_Oil_VariablePvt: return eWellCategory == NM_WellCategory_Oil; case SMT_Water_ConstPvt: case SMT_Water_VariablePvt: return eWellCategory == NM_WellCategory_Water; case SMT_Gas_VariablePvt: case SMT_Gas_PseudoPressure: return eWellCategory == NM_WellCategory_Gas; case SMT_Oil_Gas_TwoPhase: return eWellCategory == NM_WellCategory_Oil || eWellCategory == NM_WellCategory_Gas; case SMT_Oil_Water_TwoPhase: return eWellCategory == NM_WellCategory_Oil || eWellCategory == NM_WellCategory_Water; case SMT_Gas_Water_TwoPhase: return eWellCategory == NM_WellCategory_Gas || eWellCategory == NM_WellCategory_Water; case SMT_Oil_Gas_Water_ThreePhase: return nmIsValidWellCategory(eWellCategory); default: return false; } } class nmDataWellBase; class ZxDataWell; class nmDataReservoir; class nmDataRegionMark; class nmDataRegion; class nmDataOutline; class nmDataFracture; class nmDataFault; class nmDataAxis; class nmGuiPlot; class nmDataMeasuringScale; class nmDataMeasure; class nmDataPvtParaForPebi; class nmDataMixedResults; class nmDataLayer; class nmDataGeoRef; class nmDataAutomaticFitting; class nmDataDiagnostic; class nmDataForecast; class ZxDataWell; class iSubWndFitting; class nmDataTimeStepSetting; class nmDataSensitive; class nmAttrRegistry; class nmPebiResultSnapshot; struct nmPebiResultWellSnapshot; class NM_DATA_EXPORT nmDataAnalyzeManager : public ZxDataObjectBin { ZX_DECLARE_DYNAMIC Q_OBJECT public: /** @brief PEBI线性求解器类型稳定编码。 */ enum PebiSolverType { PebiSolverCpuAccelerated = 1, PebiSolverOriginal = 2 }; nmDataAnalyzeManager(); // 释放当前流动段分析独占的数据对象 ~nmDataAnalyzeManager(); // 分析窗口和数据管理器的映射关系 static QMap s_mapDataAnalManager; // 当前操作的分析窗体 static iSubWndFitting* s_pCurSubWndFitting; // 根据流动段分析窗口的指针作为唯一标识 static nmDataAnalyzeManager* getInstanceByFitting(iSubWndFitting* pSubWndF); // 流动段分析窗口销毁后,移除并释放对应的数据管理器 static void removeInstanceByFitting(iSubWndFitting* pSubWndF); /** * @brief 根据流动段分析窗口指针(key)查找对应的分析管理器实例(value) * @param pSubWndF 流动段分析窗口指针(作为key) * @return 返回对应的 nmDataAnalyzeManager 实例指针,如果未找到则返回 nullptr */ static nmDataAnalyzeManager* findManagerByFitting(iSubWndFitting* pSubWndF) { return s_mapDataAnalManager.value(pSubWndF, nullptr); } static iSubWndFitting* getCurrentFitting() { return s_pCurSubWndFitting; } static void setCurrentFitting(iSubWndFitting* pSubWndF) { s_pCurSubWndFitting = pSubWndF; } // 获取当前分析窗体下的指针 static nmDataAnalyzeManager* getCurrentInstance(); /** * @brief 枚举工程井下全部压力、流量测量记录并逐条判定可用状态。 * @note 仅当工程井对象为空或井别无效时返回 false;单条记录损坏/为空 * 不影响返回值,只会体现为该记录的 eStatus。 */ static bool readFrameworkWellCurves( ZxDataWell* pWellData, QVector& vecPressureRecords, QVector& vecFlowRecords, NM_WELL_CATEGORY& eWellCategory); /** * @brief 将枚举到的记录列表写入数值井,并优先恢复指定的压力、流量记录。 * @note 找不到任何可用记录时仍会写入列表,只是选中 Code 为空,不阻止建井。 */ static void applyGaugeRecordsToWell( nmDataWellBase* pWellData, const QVector& vecPressureRecords, const QVector& vecFlowRecords, const QString& sPreferredPressureGaugeCode = QString(), const QString& sPreferredFlowGaugeCode = QString(), int nPreferredFlowIndex = 0); // 井的接口 // 添加井 nmDataWellBase* createWell(NM_WELL_MODEL eWellType); nmDataWellBase* changeWellType(nmDataWellBase* pOldWellData, NM_WELL_MODEL eTargetWellType); /** * @brief 判断指定井是否为创建数值分析时绑定的固定主井。 * @note 主井身份只按 PrimaryWellCode 判断,与当前查看井无关。 */ bool isPrimaryWell(const nmDataWellBase* pWellData) const; /** * @brief 判断指定实时井是否允许从当前数值分析中删除。 * @note 只有本管理器拥有且不是固定主井的井才允许删除。 */ bool canRemoveWell(const nmDataWellBase* pWellData) const; /** * @brief 删除一口非主分析井。 * @return 删除成功返回 true;主井、空指针或非本管理器井返回 false。 */ bool removeWell(nmDataWellBase* pWellData); /** @brief 同时移除一口非主分析井的图元和实时数据。 */ void removeWellDataAndPlot(nmDataWellBase* pWellData); /** * @brief 清空所有井数据 * @note 会删除所有井对象并清空数组 */ void clearAllWellData(); // 获取井的数据 QVector getWellDataList() const; // 井副本数据 //QVector getWellDataListCopy() const; // TODO:有问题,不会更新不同类型的井数据 //void updateWellData(const QVector& newData); /** @brief 按稳定 UUID 回写直井数据,并恢复井与最后结果快照的弱关联。 */ void updateVerticalWells(const QVector& wells); /** @brief 按稳定 UUID 回写压裂直井数据,并恢复井与最后结果快照的弱关联。 */ void updateVerticalFracturedWells(const QVector& wells); /** @brief 按稳定 UUID 回写多段压裂水平井数据,并恢复井与最后结果快照的弱关联。 */ void updateHorizontalFracturedWells(const QVector& wells); // 返回分类后的井数据 // 获取所有直井数据 QVector getVerticalWellData() const; // 获取所有垂直裂缝井数据 QVector getVerticalFracturedWellData() const; // 获取所有多段压裂水平井数据 QVector getHorizontalFracturedWellData() const; // 通过井的名称查找井数据 //nmDataWellBase* findWellByName(const QString& wellName) const; nmDataWellBase* findWellByName(QString wellName) const; /** * @brief 通过项目唯一井编码查找井数据。 * @note 数值计算、网格和结果关联必须调用该接口;井名查找只保留给界面显示逻辑。 */ nmDataWellBase* findWellByCode(const QString& sWellCode) const; /** * @brief 通过井对象稳定 UUID 查找当前实时井。 * @note 结果界面用该接口判断快照井是否已删除;井编码或名称不能替代 UUID。 */ nmDataWellBase* findWellByInstanceId( const QString& sWellInstanceId) const; // 初始化测试井数据,即点击数值解的时候,将当前井添加到里面 void initCurWellData(); /** * @brief 按需把项目井加入数值 Map,并复制对应的流量和压力数据。 * @return 已存在或成功创建的数值井;井型不支持时返回空指针。 */ nmDataWellBase* appendWellData(ZxDataWell* pWellData); // 直接添加自定义的井数据 void appendNmWellData(nmDataWellBase* pWellData); /** * @brief 原子替换一口数值井并同步当前井、计算井和属性注册表。 * @param pOldWell 被替换对象,成功后删除。 * @param pNewWell 新对象,必须预先保留与旧井相同的 UUID;成功后由管理器接管所有权。 * @return 替换成功返回true;失败时两个对象所有权均不改变。 */ bool replaceWellData(nmDataWellBase* pOldWell, nmDataWellBase* pNewWell); // 初始化油藏参数 void createReservoir(); // 获取油藏参数 nmDataReservoir* getReservoirData() const; // 返回油藏副本数据 nmDataReservoir getReservoirDataCopy() const; void updateReservoirData(const nmDataReservoir& newData); // 初始化坐标轴参数 nmDataAxis* getAxisData() const; void setAxisData(nmDataAxis* pAxisData); // 从流动段分析窗口获取对应的PVT相关数据 void initPvtParaFromSubFit(); // 初始化区域标记参数 nmDataRegionMark* createRegionMark(); // 获取区域标记数据 QVector getRegionMarkDataList() const; // 移除区域标记数据 bool removeRegionMarkData(nmDataRegionMark* pData); // 返回区域标记副本数据 QVector getRegionMarkDataListCopy() const; void updateRegionMarkData(const QVector& newData); // 初始化边界数据 nmDataOutline* createOutline(); nmDataOutline* getOutlineData(); /** @brief 按当前数值井包围盒及四周 1500m 留量创建一次性默认矩形边界。 */ bool createDefaultOutlineFromWells(); /** @brief 计算当前数值分析全部有效井位置的包围盒。 */ bool calculateNumericalWellBounds(QRectF& oBounds) const; // 移除边界数据 bool removeOutlineData(); // 返回边界副本数据 nmDataOutline getOutlineDataCopy() const; void updateOutlineData(const nmDataOutline& newData); // 初始化复合区数据 nmDataRegion* createRegion(); // 获取复合区数据 QVector getRegionDataList() const; // 移除复合区数据 bool removeRegionData(nmDataRegion* pData); // 返回复合区副本数据 QVector getRegionDataListCopy() const; void updateRegionData(const QVector& newData); // 初始化裂缝数据 nmDataFracture* createFracture(); // 获取所有裂缝数据 QVector getFractureDataList() const; // 获取DNF生成的裂缝数据 QVector getDFNFractureDataList() const; // 移除裂缝数据 bool removeFractureData(nmDataFracture* pData); // 返回裂缝副本数据 QVector getFractureDataListCopy() const; void updateFractureData(const QVector& newData); // 初始化断层数据 nmDataFault* createFault(); // 获取断层数据 QVector getFaultDataList() const; // 移除断层数据 bool removeFaultData(nmDataFault* pData); // 返回断层数据副本 QVector getFaultDataListCopy() const; // 更新断层数据 void updateFaultData(const QVector& newData); // 绘图 nmGuiPlot* getPlot() const; void setPlot(nmGuiPlot* plot); // 更新井图元 void updateWellPlotByDataManager(); // 获取所有可连接的点(Value:实际坐标) QVector getValueAllConnectablePoints(); // 获取所有可连接的点(Pos:屏幕坐标) QVector getPosAllConnectablePoints(); // 根据传入的指针,去掉对应的点的坐标 QVector removePosByObject(QObject* obj); // 比例尺数据对象相关 nmDataMeasuringScale* getMeasuringScaleData(); void setMeasuringScaleData(nmDataMeasuringScale *pMeasuringScaleData); // 测量相关 nmDataMeasure* getMeasureData(); void setMeasureData(nmDataMeasure *pMeasureData); bool removeMeasureData(); // 模型参考点相关 nmDataGeoRef* createGeoRefData(); nmDataGeoRef* getGeoRefData() const; nmDataGeoRef getGeoRefDataCopy() const; void updateGeoRefData(const nmDataGeoRef& newData); // 预测相关 nmDataForecast* createForecastData(); nmDataForecast* getForecastData() const; nmDataForecast getForecastDataCopy() const; void updateForecastData(const nmDataForecast& newData); // 敏感性分析相关 nmDataSensitive* createSensitiveData(); nmDataSensitive* getSensitiveData() const; nmDataSensitive getSensitiveDataCopy() const; void updateSensitiveData(const nmDataSensitive& newData); // 自动拟合相关 nmDataAutomaticFitting* createAutomaticFittingData(); nmDataAutomaticFitting* getAutomaticFittingData() const; nmDataAutomaticFitting getAutomaticFittingDataCopy() const; void updateAutomaticFittingData(const nmDataAutomaticFitting& newData); // 诊断参数相关 nmDataDiagnostic* getDiagnosticData() const; // 应用诊断结果 void applyDiagnosticResults(nmDataDiagnostic* diagnostic, nmDataWellBase* wellData, nmDataReservoir* reservoirData); // 重置功能相关方法 bool resetFromDiagnostic(); // 诊断重置业务逻辑 bool resetFromAnalytical(); // 分析重置业务逻辑 // 网格类型 NM_Grid_Type getGridType(); void setGridType(NM_Grid_Type newGridType); // 求解模型类型 NM_SOLVER_MODEL_TYPE getSolverModelType() const; void setSolverModelType(NM_SOLVER_MODEL_TYPE newSolverModelType); /** @brief 获取PEBI求解器类型,1为CPU加速求解器,2为原求解器。 */ int getPebiSolverType() const; /** @brief 设置PEBI求解器类型。 */ void setPebiSolverType(int nSolverType); /** @brief 获取PEBI求解器的OpenMP线程数。 */ int getPebiOmpThreads() const; /** @brief 设置PEBI求解器的OpenMP线程数。 */ void setPebiOmpThreads(int nOmpThreads); /** @brief 获取PEBI求解器的ILU复用步数。 */ int getPebiIluReuseSteps() const; /** @brief 设置PEBI求解器的ILU复用步数。 */ void setPebiIluReuseSteps(int nIluReuseSteps); // 获取Pebi网格求解数据接口 // 获取压力历史数据 QVector> getPebiSolverHistoryDataByName(const QString& wellName); // 获取压力对数信息 QVector> getPebiSolverLogPreDataByName(const QString& wellName); // 获取压力半对数数据 QVector> getPebiSolverSemiLogPreDataByName(const QString& wellName); // 获取PEBI求解器需要的pvt数据 nmDataPvtParaForPebi* getPebiPvtPara(); // 获取气单相变化 PVT 求解所需的压力/拟压力转换表。 bool getPebiPseudoPressureTable(std::vector& pressure, std::vector& pseudoPressure); // 获取混合结果参数 nmDataMixedResults* getMixedResults(); // 创建混合结果参数对象 nmDataMixedResults* createMixedResult(); // 获取储层数据 nmDataLayer* getLayerData(); // 添加多储层数据 void setLayers(QVector vecLayers); // 获取多储层数据 QVector getLayers(); // 获取储层边界数据 double getMinLayerTop(); double getMaxLayerBottom(); // 在末尾追加一个新的井信息 void appendCalculationWell(const QPair& well); // 在指定位置插入一个新的井信息 void insertCalculationWell(int index, const QPair& well); // 移除指定位置的井信息 bool removeCalculationWell(int index); // 清空容器 void clearCalculationWells(); // 返回井信息的副本 QVector> getCalculationWells() const; // 查询当前计算井中是否有某口井 bool isContainsWellName(const QString& wellName) const; /** @brief 返回当前窗口的数值分析方案,管理器保留对象所有权。 */ nmDataNumericalAnalysisCase* getNumericalAnalysisCase(); /** @brief 返回只读数值分析方案,管理器保留对象所有权。 */ const nmDataNumericalAnalysisCase* getNumericalAnalysisCase() const; /** @brief 后台任务开始使用本管理器;与 endBackgroundUse() 必须成对调用。 */ void beginBackgroundUse(); /** @brief 后台任务结束使用本管理器;最后一个任务退出时唤醒析构等待。 */ void endBackgroundUse(); /** * @brief 初始化固定主分析井 WellCode。 * @note 分析运行期间不允许清空或更换;整体 clear 后可重新初始化。 */ void setPrimaryWellCode(const QString& sWellCode); /** @brief 返回当前主分析井 WellCode。 */ QString getPrimaryWellCode() const; /** @brief 启停手工包含的其他有产量井;不影响 Map 无产量观察井。 */ void setIncludeOtherWells(bool bInclude); /** @brief 返回 Include Other Wells 总开关状态。 */ bool getIncludeOtherWells() const; /** @brief 设置当前方案的 PEBI 网格疏密控制值。 */ void setPebiGridControl(double dGridControl); /** @brief 返回当前方案的 PEBI 网格疏密控制值。 */ double getPebiGridControl() const; /** @brief 保存其他有产量井选择;非法井、主井和无产量井会被过滤。 */ void setIncludedCalculationWells(const QVector& vecWells); /** @brief 返回用户在 Include Other Wells 中保存的有产量井。 */ QVector getIncludedCalculationWells() const; /** @brief 返回真实求解井:主井、全部 Map 无产量井及已包含主动井。 */ QVector getEffectiveCalculationWells() const; /** @brief 从有效求解井集合查询井角色,未参与井按观察井返回。 */ NM_CASE_WELL_MODE getCalculationWellMode(const QString& sWellCode) const; /** @brief 判断井是否属于当前真实求解井集合。 */ bool isWellSelectedForCalculation(const QString& sWellCode) const; /** @brief 清空网格生成器写入的 DLL 井槽位顺序。 */ void clearSolverWellOrder(); /** @brief 向 DLL 井槽位顺序末尾追加一个真实井或裂缝条目。 */ void appendSolverWell(const nmSolverWellRef& oWellRef); /** @brief 在指定 DLL 下标插入井或裂缝条目,并重新编号。 */ void insertSolverWell(int nIndex, const nmSolverWellRef& oWellRef); /** @brief 返回网格确定的 DLL 井槽位顺序,与包含井选择相互独立。 */ QVector getSolverWellOrder() const; /** @brief 整体替换 DLL 井槽位顺序,并由分析方案统一重编号。 */ void setSolverWellOrder(const QVector& vecSolverWellOrder); /** * @brief 按输入版本一次性提交后台生成的井顺序和 VTK 网格。 * @return 输入仍为当前版本且提交成功时返回 true;过期结果不修改现有成果。 */ bool commitPebiGridResult( quint64 nGridInputRevision, const QVector& vecSolverWellOrder, vtkSmartPointer pGrid); /** @brief 主线程登记当前分析正在生成指定输入版本的 PEBI 网格。 */ void beginPebiGridGeneration(quint64 nGridInputRevision); /** @brief 主线程结束当前建网活动,并通知等待同一分析的求解流程。 */ void endPebiGridGeneration(bool bSucceeded); /** @brief 判断当前分析是否仍处于防抖等待、后台建网或待提交阶段。 */ bool isPebiGridGenerationActive() const; /** @brief 将当前输入版本登记为已成功生成网格。 */ void markPebiGridBuilt(); /** @brief 仅在后台划分期间输入未变化时登记网格成功。 */ bool markPebiGridBuiltIfCurrent(quint64 nGridInputRevision); /** @brief 几何或求解井集合变化后,使 PEBI 网格和结果失效。 */ void invalidatePebiGrid(); /** @brief 产量、PVT 等变化后,仅使 PEBI 结果失效。 */ void invalidatePebiResults(); /** @brief 判断当前 PEBI 网格是否与最新输入一致。 */ bool isPebiGridValid() const; /** @brief 判断是否存在一套可保存和查看的 PEBI 结果。 */ bool hasPebiResults() const; /** @brief 返回最后一次成功求解发布的完整只读结果快照。 */ QSharedPointer getPebiResultSnapshot() const; /** @brief 是否已发布完整结果快照。 */ bool hasPebiResultSnapshot() const; /** @brief 快照的网格和求解输入版本是否仍与当前输入一致。 */ bool isPebiResultSnapshotCurrent() const; /** @brief 返回快照查看状态中的当前结果井 UUID。 */ QString getCurrentResultWellInstanceId() const; /** @brief 按快照 UUID 切换结果井,空值表示选择第一口可显示井。 */ bool setCurrentResultWellInstanceId( const QString& sWellInstanceId); /** * @brief 主线程按输入版本一次性发布完整结果快照。 * @note 无论成功或失败都会清空传入候选的可写引用;旧快照仅在成功时替换。 */ bool commitPebiResultSnapshot( QSharedPointer& pCandidate, QString* pError = NULL); /** @brief 清除最后结果快照及其结果井查看状态。 */ void clearPebiResultSnapshot(); // 设置当前查看井 void setCurWellData(nmDataWellBase* wellData); // 获取当前查看井 nmDataWellBase* getCurWellData(); void notifyDataChanged(); /// @brief 对象新增或删除后刷新参数面板,并通知网格更新 void notifyGeometryListChanged(); /// @brief 仅刷新参数面板中的对象名称,避免改名触发网格重建 void notifyParameterObjectNameChanged(); /** * @brief 设置显示设置信息。 * @param displaySettings 包含所有类别显示状态的QVector。 */ void setDisplaySettings(const QVector& displaySettings); /** * @brief 获取当前显示设置信息。 * @return 包含所有类别显示状态的QVector。 */ QVector getDisplaySettings() const; /** * @brief 更新单个类别的显示设置。 * @param categoryName 类别名称。 * @param info 要更新的CategoryDisplayInfo。 * @return 如果找到并更新了指定类别返回true,否则返回false */ bool updateCategoryDisplaySetting(const QString& categoryName, const CategoryDisplayInfo& info); // 初始化默认显示设置 void initDefaultDisplaySettings(); // 用于查找类别 CategoryDisplayInfo* findCategoryDisplayInfo(const QString& categoryName); /** * @brief 向显示设置向量中添加一个子元素。 * @param displaySetting 要添加的DisplaySetting结构。 * @return 添加成功返回true,否则返回false(如已存在相同key) */ bool appendDisplaySetting(const DisplaySetting& displaySetting); /** * @brief 从显示设置向量中删除指定key的子元素。 * @param categoryName 要删除的类别的key。 * @return 删除成功返回true,否则返回false(如未找到) */ bool removeDisplaySetting(const QString& categoryName); /** * @brief 为指定的父类别添加子项 * @param parentCategory 父类别名称(如"Wells", "Faults"等) * @param childNames 要添加的子项名称列表 * @param defaultChecked 子项的默认选中状态 * @return 添加成功返回true,如果父类别不存在则返回false */ bool nmDataAnalyzeManager::addChildItemsToCategory(const QString& parentCategory, const QStringList& childNames, bool defaultChecked); // 刷新当前显示的子节点 void nmDataAnalyzeManager::refreshChildItemsDisplay(); void addWellChildItemsToCategory(const QString& parentCategory); void addFaultChildItemsToCategory(const QString& parentCategory); void addFractureChildItemsToCategory(const QString& parentCategory); void addRegionChildItemsToCategory(const QString& parentCategory); void addRegionMarkChildItemsToCategory(const QString& parentCategory); /** * @brief 设置所有类别的根节点可见性 * @param isVisible true为全部可见,false为全部不可见 */ void setAllCategoriesRootVisibility(bool bIsVisible); // 设置背景图片信息 void setBackgroundImageInfo(const BackgroundImageInfo& info); // 获取背景图片信息 const BackgroundImageInfo& getBackgroundImageInfo() const; /* 获取及设置属性插值数据组 */ QVector getPropertyInterpolationDataSets() const; void setPropertyInterpolationDataSets(const QVector& dataSets); // 统一的读写整个项目数据的方法 // @param filePath JSON文件的路径 // @return 读取成功返回 true,否则返回 false bool ReadProjectData(const QString& filePath); // 统一的写整个项目数据的方法 // @param filePath JSON文件的路径 // @return 写入成功返回 true,否则返回 false bool WriteProjectData( const QString& filePath, const nmNumericalWindowPayloadReferences* pPayloadReferences = NULL); /** * @brief 将本窗口完整写入保存会话指定的 v5 代次目录。 * @note 主 JSON 最后写入,并在返回前校验全部引用文件。 */ bool saveNmResultV3( const QString& sWindowDirectory, nmNumericalFileReference& oMainJsonReference, QString* pError = NULL); /** * @brief 校验一个 v5 窗口主 JSON 明确引用的全部载荷。 * @note 保存会话用它复核从旧根清单保留、但本轮未重写的窗口。 */ static bool validateNmResultV3Window( const QString& sWindowDirectory, const QString& sMainJsonPath, QString* pError = NULL); // 加载本地成果到内存中 // @param sLoadAnalDir 加载的分析目录 // @return 保存成功返回 true,否则返回 false bool loadNmResult(QString sLoadAnalDir); // 辅助函数:确保目录存在,如果不存在则创建 bool ensureDirectoryExists(const QString& dirPath); /** * @brief 判断指定目录是否存在。 * @param sDirPath 要检查的目录路径。 * @return 如果目录存在且可访问,则返回true,否则返回false。 */ static bool isDirExist(const QString& sDirPath) { QFileInfo dirInfo(sDirPath); bool bExists = dirInfo.exists() && dirInfo.isDir(); return bExists; } /** @brief 显式刷新框架井压力和流量;成果加载流程不得调用。 */ bool loadWellPreAndFlow(); // 设置当前分析下的VTK网格对象 void setUnstructuredGrid(vtkSmartPointer grid); // 获取当前分析下的VTK网格对象 vtkSmartPointer getUnstructuredGrid() const; // 清理当前分析下的VTK网格对象 void clearUnstructuredGrid(); // 创建时间步数据 //void createTimeStep(); nmDataTimeStepSetting* createTimeStep(); // 获取时间步数据 nmDataTimeStepSetting* getTimeStep(); void calculationLogData( nmDataWellBase* pWellData, QVector>& vvecHistoryData, QVector>& vvecLogPreData, QVector>& vvecSemiLogPreData); /** @brief 使用同一份 Gauge 输入原子更新井的三组历史曲线及签名。 */ bool updateWellHistoryData(nmDataWellBase* pWellData); // 获取许可证路径 void setLicensePath(const QString& licensePath); QString getLicensePath() const; // 获取属性注册表 nmAttrRegistry* getAttrRegistry() const; /// @brief 同步所有井的参数到 nmAttrRegistry /// @note wellCode + "_W_XX" 作为注册名,使双向绑定链路适用于井参数 /// @note 增量同步:自动清理已删除井的注册,注册新增井的参数 void syncWellAttrs(); /// @brief 按“对象编码 + XML 参数名”注册几何对象参数 void syncGeometryAttrs(); signals: void dataChanged(); /// @brief 井数据准备完成信号 void sigWellAdded(QString wellCode, QString wellName, QStringList baseParas); /// @brief 井删除信号(removeWell 发出) void sigWellRemoved(QString wellCode, QString wellName); /// @brief 参数面板中的对象列表或对象名称发生变化 void sigGeometryListChanged(); /** @brief 当前分析最后一次排队的 PEBI 建网流程已经结束。 */ void sigPebiGridGenerationFinished(quint64 nGridInputRevision, bool bSucceeded); /** @brief 并行结果快照或其结果井选择已经改变。 */ void sigPebiResultSnapshotChanged(); private: /** @brief 按 UUID 给当前实时井统一绑定或解除最后结果快照弱引用。 */ void rebindPebiResultSnapshotToWells(); /** @brief 在候选 Manager 内完整读取并校验一套 v5 成果。 */ bool loadNmResultV3InPlace(const QString& sLoadAnalDir); /** @brief 通过交换所有权一次发布已完整校验的候选项目状态。 */ void swapLoadedProjectState(nmDataAnalyzeManager& oLoadedManager); /** @brief 项目状态替换后用新对象地址重建属性注册表。 */ void rebuildLoadedAttributeRegistry(); /** @brief 创建本数据管理器的成果窗口;只用于读取本成果上下文,不拥有对象。 */ iSubWndFitting* m_pOwnerFitting; /** @brief 保护后台使用计数和析构等待条件。 */ QMutex m_oBackgroundUseMutex; /** @brief DataManager 析构时等待全部后台任务停止访问。 */ QWaitCondition m_oNoBackgroundUseCondition; int m_nBackgroundUseCount; ///< 当前持有 DataManager 使用权的后台任务数量。 /** @brief 仅由主线程维护;覆盖建网防抖、后台计算和结果提交整个阶段。 */ bool m_bPebiGridGenerationActive; quint64 m_nPebiGridGenerationRevision; ///< 当前建网活动对应的输入版本。 // 存储井的数据 QVector m_vWellData; // 断层数据 QVector m_vFaultData; // 裂缝数据 QVector m_vFractureData; // 复合区数据 QVector m_vRegionData; // 区域标记数据 QVector m_vRegionMarkData; // 边界数据 nmDataOutline* m_outlineData; // 坐标轴范围数据 nmDataAxis* m_axisData; // 自动拟合数据 nmDataAutomaticFitting* m_pAutomaticFittingData; // 油藏数据 nmDataReservoir* m_reservoirData; // 存储nmGuiPlot,绘图 nmGuiPlot* m_pNmGuiPlot; // 比例尺信息 nmDataMeasuringScale* m_pMeasuringScaleData; // 测量信息 nmDataMeasure* m_pMeasureData; // 模型参考点信息 nmDataGeoRef* m_pGeoRefData; // 预测信息 nmDataForecast* m_pForecastData; // 敏感性信息 nmDataSensitive* m_pSensitiveData; // 诊断参数 nmDataDiagnostic* m_pDiagnosticData; // 网格类型 NM_Grid_Type m_eGridType; // 求解模型类型 NM_SOLVER_MODEL_TYPE m_eSolverModelType; /** @brief PEBI求解器类型,1为CPU加速求解器,2为原求解器。 */ int m_nPebiSolverType; /** @brief PEBI求解器的OpenMP线程数。 */ int m_nPebiOmpThreads; /** @brief PEBI求解器的ILU复用步数。 */ int m_nPebiIluReuseSteps; // Pvt数据(Pebi) nmDataPvtParaForPebi* m_pebiPvtPara; // 混合结果参数 nmDataMixedResults* m_pMixedResults; // 储层数据 nmDataLayer* m_pLayerData; QVector m_vecLayers; // 通过储层对话框后初始化的数组,临时 // 孔射封堵 //nmDataPerforationClosing* m_pPerCloData; // 当前数值分析方案:保存选井、井角色、当前网格槽位和三个输入版本。 nmDataNumericalAnalysisCase m_oNumericalAnalysisCase; /** @brief 最后一次成功求解发布的完整只读结果。 */ QSharedPointer m_pPebiResultSnapshot; /** @brief 快照查看状态中当前选择的结果井 UUID。 */ QString m_sCurrentResultWellInstanceId; // 当前查看的是哪一口井的数据,也是哪一口测试井 nmDataWellBase* m_pCurDataWell; // 显示设置信息 QVector m_vecDisplaySettings; /* 属性插值数据组 */ QVector m_vecPropertyInterpolationDataSets; // 背景图片信息 BackgroundImageInfo m_backgroundImageInfo; // VTK非结构化网格对象,用于展示网格划分窗体 vtkSmartPointer m_pVtkUnstructuredGrid; // 时间步设置数据 nmDataTimeStepSetting* m_pTimeStep; // 属性注册表(普通指针,手动管理,析构函数末尾 delete) nmAttrRegistry* m_pAttrRegistry; // 许可证路径 QString m_licensePath; public: // 数据是否是从本地加载进来的 bool m_bIsLoadData; }; #endif // NMDATAANALYZEMANAGER_H