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/nmPlot/nmGuiPlot.cpp

2075 lines
65 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 "ZxBaseUtil.h"
#include "zxLogInstance.h"
#include <QDebug>
#include "ZxSubAxisX.h"
#include "ZxSubAxisY.h"
#include "ZxSubTitle.h"
#include "ZxPlot.h"
#include "ZxObjCurve.h"
#include "nmPlotScene.h"
#include "nmPlotView.h"
#include "nmObjPoint.h"
#include "nmObjLine.h"
#include "nmObjPolygon.h"
#include "nmObjPolygonOutline.h"
#include "nmObjLineCrack.h"
#include "nmObjLineFault.h"
#include "nmObjLineMeasuringScale.h"
#include "nmObjPointWell.h"
#include "nmObjLineMeasure.h"
#include "nmGuiPlotCmdHelper.h"
#include "nmGuiPlot.h"
#include "nmPlotDialogContext.h"
#include "nmPlotDialogContextProvider.h"
#include "nmDataLogFile.h"
#include "nmDataMeasure.h"
#include "nmSingalCenter.h"
#include "ZxDataProject.h"
#include "TreeWxMain.h"
#include "Defines.h"
#include "zxSysUtils.h"
#include "nmObjRectOutline.h"
#include "nmObjRect.h"
#include "nmObjRoundOutline.h"
#include "nmObjRound.h"
#include "nmObjRegion.h"
#include "nmObjRegionMark.h"
#include "nmObjDeleteTool.h"
#include "nmDataAnalyzeManager.h"
#include "nmDataFault.h"
#include "nmDataFracture.h"
#include "nmDataOutline.h"
#include "nmDataRegionMark.h"
#include "nmDataRegion.h"
#include "nmDataAxis.h"
#include "nmPlotGraphicBinder.h"
#include "ZxDataWell.h"
#include "ZxDataGaugeP.h"
#include "ZxDataGaugeF.h"
#include <QMessageBox>
#include <QResizeEvent>
#include <QTimer>
#include <QWidget>
namespace {
void includeMapPoint(const QPointF& oPoint,
bool& bHasBounds,
double& dMinX,
double& dMaxX,
double& dMinY,
double& dMaxY)
{
if(!qIsFinite(oPoint.x()) || !qIsFinite(oPoint.y())) {
return;
}
if(!bHasBounds) {
dMinX = dMaxX = oPoint.x();
dMinY = dMaxY = oPoint.y();
bHasBounds = true;
return;
}
dMinX = qMin(dMinX, oPoint.x());
dMaxX = qMax(dMaxX, oPoint.x());
dMinY = qMin(dMinY, oPoint.y());
dMaxY = qMax(dMaxY, oPoint.y());
}
void includeMapPoints(const QVector<QPointF>& vecPoints,
bool& bHasBounds,
double& dMinX,
double& dMaxX,
double& dMinY,
double& dMaxY)
{
foreach(const QPointF& oPoint, vecPoints) {
includeMapPoint(oPoint, bHasBounds,
dMinX, dMaxX, dMinY, dMaxY);
}
}
}
nmGuiPlot::nmGuiPlot(bool bUseBtns, QWidget *parent) :
iGuiPlot(bUseBtns, parent),
m_pGraphicBinder(NULL),
m_pDataManager(nmDataAnalyzeManager::getCurrentInstance()),
m_bApplyingAxisRange(false),
m_bAxisInitializationPending(false)
{
m_bUseBtns = bUseBtns;
if(NULL != m_pCmdHelper) {
delete m_pCmdHelper;
m_pCmdHelper = NULL;
}
m_pCmdHelper = new nmGuiPlotCmdHelper(this);
Q_ASSERT(NULL != m_pCmdHelper);
connect(m_pCmdHelper, SIGNAL(sigMeasureStarted()), this, SIGNAL(sigMeasureStarted()));
m_sChartCmdType = "NmDemo2DType";
setWindowTitle(tr("nmGuiPlot"));
m_iRegionMarkCount = 0;
m_pGraphicBinder = new nmPlotGraphicBinder(m_pDataManager, this);
}
nmGuiPlot::~nmGuiPlot()
{
}
void nmGuiPlot::initUI(QString sTitle,
QSize szDefault /*= QSize(265, 203)*/)
{
iGuiPlot::initUI(sTitle, szDefault);
}
void nmGuiPlot::initSheets()
{
// iGuiPlot::initSheets();
}
void nmGuiPlot::initMainLayout()
{
iGuiPlot::initMainLayout();
}
QWidget* nmGuiPlot::initChartLayout(QString sTitle, QSize szDefault)
{
return iGuiPlot::initChartLayout(sTitle, szDefault);
}
void nmGuiPlot::initChartView(QString sTitle, QSize szDefault)
{
// iGuiPlot::initChartView(sTitle, szDefault);
m_pPlotView = new nmPlotView();
Q_ASSERT(NULL != m_pPlotView);
m_pPlotScene = new nmPlotScene();
Q_ASSERT(NULL != m_pPlotScene);
m_pPlotView->setScene(m_pPlotScene);
m_pPlotScene->init(m_pPlotView, sTitle, szDefault);
//m_pPlotView->setSimpleMode(true);
m_pPlot = m_pPlotScene->m_pPlot;
m_pPlotView->setMargins(0, 0, 0, 0);
m_pPlotView->setZoomMode(ZxRenderView::eZoomFitWindow, true);
connectSignals();
initDefultGeoObj();
}
void nmGuiPlot::connectSignals()
{
iGuiPlot::connectSignals();
// your owns
if(NULL != m_pPlot) {
// disconnect(m_pPlot, SIGNAL(sigUpdate()), \
// m_pPlotView->viewport(), SLOT(update()));
// connect(m_pPlot, SIGNAL(sigUpdate()), \
// m_pPlotView->viewport(), SLOT(update()));
}
nmSingalCenter* sCenter = nmSingalCenter::getInstance();
connect(sCenter, SIGNAL(sigDeleteWell(QString)), this, SLOT(slotDeleteWell(QString)));
connect(sCenter, SIGNAL(sigMeasuringScale(QPointF, QPointF, void*)), this, SLOT(slotMeasuringScale(QPointF, QPointF, void*)));
connect(sCenter, SIGNAL(sigDeleteOneObj(QString, void*)), this, SLOT(slotDeleteOneObj(QString, void*)));
}
void nmGuiPlot::runUpdate()
{
// iGuiPlot::updatePlots();
if(NULL != m_pPlot) {
}
}
bool nmGuiPlot::runAction(QString sAction)
{
Q_ASSERT(NULL != m_pCmdHelper);
return m_pCmdHelper->runAction(sAction);
}
void nmGuiPlot::cancelActiveTools()
{
nmGuiPlotCmdHelper* helper = dynamic_cast<nmGuiPlotCmdHelper*>(m_pCmdHelper);
if(helper != NULL) {
helper->cancelActiveTools();
}
}
void nmGuiPlot::initDefultGeoObj()
{
nmDataAnalyzeManager* pDataManager = dataManager();
if(pDataManager == nullptr) {
return;
}
nmDataAxis* pAxisData = pDataManager->getAxisData();
if(pAxisData == nullptr) {
pAxisData = new nmDataAxis;
// 将 pAxisData 存入数据中心
pDataManager->setAxisData(pAxisData);
}
// 获取井数据,来自数据中心
QVector<nmDataWellBase*> vecWellDatas = pDataManager->getWellDataList();
// 数据中心没有一口井数据,添加默认井数据
if(vecWellDatas.isEmpty()) {
// 获取当前默认井数据
ZxDataWell* pWellData = zxCurWell;
if(pWellData == nullptr) {
this->setPlotsByDataManger(pDataManager);
return;
}
// 判断是哪一种井类型,初始化对应的参数
QString wellClass = pWellData->getWellClassEn();
const NM_WELL_CATEGORY eWellCategory =
static_cast<NM_WELL_CATEGORY>(
pWellData->getWellTypeIndex());
if(!nmIsValidWellCategory(eWellCategory)) {
this->setPlotsByDataManger(pDataManager);
return;
}
// 获取当前井的压力、流量数据
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, 0)) {
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, static_cast<int>(eWellCategory))) {
for(int i = 0; i < vecX.size(); ++i) {
if(i < vecY.size()) {
QPointF pt(vecX[i], vecY[i]);
vecPtsF.append(pt);
}
}
}
}
// 历史数据
QVector<QVector<double>> vvecHistoryPressureData;
QVector<QVector<double>> vvecHistoryLogData;
QVector<QVector<double>> vvecHistorySemiLogData;
if(ZxBaseUtil::isSameStr(wellClass, "VerticalWell")) {
// 初始化直井默认参数
nmDataWellBase* pWell = pDataManager->createWell(NM_WELL_MODEL::Vertical_Well);
nmDataVerticalWell* m_VerticalWell = dynamic_cast<nmDataVerticalWell*>(pWell);
if(m_VerticalWell == nullptr) {
this->setPlotsByDataManger(pDataManager);
return;
}
m_VerticalWell->setWellName(pWellData->getName());
m_VerticalWell->setWellCode(pWellData->getCode());
m_VerticalWell->setWellCategory(eWellCategory);
nmDataAttribute tempAttr = m_VerticalWell->getX();
tempAttr.setValue(pWellData->getLocationX());
m_VerticalWell->setX(tempAttr);
tempAttr = m_VerticalWell->getY();
tempAttr.setValue(pWellData->getLocationY());
m_VerticalWell->setY(tempAttr);
tempAttr = m_VerticalWell->getRadius();
tempAttr.setValue(pWellData->getWellRadius());
m_VerticalWell->setRadius(tempAttr);
// 设置井的压力数据、流量数据
m_VerticalWell->setPressurePoints(vecPtsP);
m_VerticalWell->setFlowPoints(vecPtsF);
// TODO: 计算井的历史双对数/半对数数据
pDataManager->calculationLogData(m_VerticalWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
// 存储历史数据到井对象
m_VerticalWell->setHistoryPressure(vvecHistoryPressureData);
m_VerticalWell->setHistoryLogLog(vvecHistoryLogData);
m_VerticalWell->setHistorySemiLog(vvecHistorySemiLogData);
// 设置为当前查看的井
pDataManager->setCurWellData(m_VerticalWell);
} else if(ZxBaseUtil::isSameStr(wellClass, "VerticalFracturedWell")) {
// 初始化垂直裂缝井默认参数
nmDataWellBase* pWell = pDataManager->createWell(NM_WELL_MODEL::Vertical_Fractured_Well);
nmDataVerticalFracturedWell* m_VFracturedWell = dynamic_cast<nmDataVerticalFracturedWell*>(pWell);
if(m_VFracturedWell == nullptr) {
this->setPlotsByDataManger(pDataManager);
return;
}
m_VFracturedWell->setWellName(pWellData->getName());
m_VFracturedWell->setWellCode(pWellData->getCode());
m_VFracturedWell->setWellCategory(eWellCategory);
nmDataAttribute tempAttr = m_VFracturedWell->getX();
tempAttr.setValue(pWellData->getLocationX());
m_VFracturedWell->setX(tempAttr);
tempAttr = m_VFracturedWell->getY();
tempAttr.setValue(pWellData->getLocationY());
m_VFracturedWell->setY(tempAttr);
tempAttr = m_VFracturedWell->getRadius();
tempAttr.setValue(pWellData->getWellRadius());
m_VFracturedWell->setRadius(tempAttr);
// 设置井的压力数据、流量数据
m_VFracturedWell->setPressurePoints(vecPtsP);
m_VFracturedWell->setFlowPoints(vecPtsF);
// TODO: 计算井的历史双对数/半对数数据
pDataManager->calculationLogData(m_VFracturedWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
// 存储历史数据到井对象
m_VFracturedWell->setHistoryPressure(vvecHistoryPressureData);
m_VFracturedWell->setHistoryLogLog(vvecHistoryLogData);
m_VFracturedWell->setHistorySemiLog(vvecHistorySemiLogData);
// 更新裂缝位置信息
m_VFracturedWell->setFracs();
// 设置为当前查看的井
pDataManager->setCurWellData(m_VFracturedWell);
} else if(ZxBaseUtil::isSameStr(wellClass, "HorizontalMultiFracturedWell")) {
// 初始化多段压裂水平井默认参数
nmDataWellBase* pWell = pDataManager->createWell(NM_WELL_MODEL::Horizontal_Fractured_Well);
nmDataHorizontalFracturedWell* m_HFracturedWell = dynamic_cast<nmDataHorizontalFracturedWell*>(pWell);
if(m_HFracturedWell == nullptr) {
this->setPlotsByDataManger(pDataManager);
return;
}
m_HFracturedWell->setWellName(pWellData->getName());
m_HFracturedWell->setWellCode(pWellData->getCode());
m_HFracturedWell->setWellCategory(eWellCategory);
nmDataAttribute tempAttr = m_HFracturedWell->getX();
tempAttr.setValue(pWellData->getLocationX());
m_HFracturedWell->setX(tempAttr);
tempAttr = m_HFracturedWell->getY();
tempAttr.setValue(pWellData->getLocationY());
m_HFracturedWell->setY(tempAttr);
tempAttr = m_HFracturedWell->getRadius();
tempAttr.setValue(pWellData->getWellRadius());
m_HFracturedWell->setRadius(tempAttr);
// 设置井的压力数据、流量数据
m_HFracturedWell->setPressurePoints(vecPtsP);
m_HFracturedWell->setFlowPoints(vecPtsF);
// TODO: 计算井的历史双对数/半对数数据
pDataManager->calculationLogData(m_HFracturedWell, vvecHistoryPressureData, vvecHistoryLogData, vvecHistorySemiLogData);
// 存储历史数据到井对象
m_HFracturedWell->setHistoryPressure(vvecHistoryPressureData);
m_HFracturedWell->setHistoryLogLog(vvecHistoryLogData);
m_HFracturedWell->setHistorySemiLog(vvecHistorySemiLogData);
// 计算裂缝数据
m_HFracturedWell->setFracs();
// 设置为当前查看的井
pDataManager->setCurWellData(m_HFracturedWell);
}
// 重新获取添加后的井数据
pDataManager->appendNmWellData(pDataManager->getCurWellData());
vecWellDatas = pDataManager->getWellDataList();
}
// 极端兼容入口没有预先建立边界时,也按当前井位置创建一次性默认边界。
if(pDataManager->getOutlineData() == nullptr) {
pDataManager->createDefaultOutlineFromWells();
}
// 根据数据中心的数据渲染所有的图元,上面只是为了保证打开时有一口井和边界
this->setPlotsByDataManger(pDataManager);
}
void nmGuiPlot::initAxisFromData(nmDataAnalyzeManager* pDataManager)
{
Q_ASSERT(nullptr != pDataManager);
// 0.坐标轴
// 0.1 获取坐标轴数据,来自数据中心
nmDataAxis* pAxisData = pDataManager->getAxisData();
Q_ASSERT(nullptr != pAxisData);
// 0.2 获取 X 最大值
nmDataAttribute xMaxAttr = pAxisData->getXMax();
double xMaxValue = xMaxAttr.getValue().toDouble();
// 0.3 获取 Y 最大值
nmDataAttribute yMaxAttr = pAxisData->getYMax();
double yMaxValue = yMaxAttr.getValue().toDouble();
// 0.4 获取 X 最小值
nmDataAttribute xMinAttr = pAxisData->getXMin();
double xMinValue = xMinAttr.getValue().toDouble();
// 0.5 获取 Y 最小值
nmDataAttribute yMinAttr = pAxisData->getYMin();
double yMinValue = yMinAttr.getValue().toDouble();
if(qIsFinite(xMinValue) && qIsFinite(xMaxValue) &&
qIsFinite(yMinValue) && qIsFinite(yMaxValue) &&
xMaxValue > xMinValue && yMaxValue > yMinValue) {
applyAxisRange(xMinValue, xMaxValue, yMinValue, yMaxValue);
} else {
pAxisData->setInitialViewFitted(false);
}
connect(m_pPlot->getMainAxisX(), SIGNAL(sigRangeChanged(double, double, bool, bool)),
this, SLOT(onRangeXChanged(double, double, bool, bool)),
Qt::UniqueConnection);
connect(m_pPlot->getMainAxisY(), SIGNAL(sigRangeChanged(double, double, bool, bool)),
this, SLOT(onRangeYChanged(double, double, bool, bool)),
Qt::UniqueConnection);
}
void nmGuiPlot::initBoundaryObjFromData(nmDataAnalyzeManager* pDataManager)
{
Q_ASSERT(nullptr != pDataManager);
if(pDataManager == nullptr || m_pPlot == nullptr) {
return;
}
// 1.边界
// 1.1 获取边界数据,来自数据中心
nmDataOutline* pOutlineData = pDataManager->getOutlineData();
Q_ASSERT(nullptr != pOutlineData);
if(pOutlineData == nullptr) {
return;
}
// 1.2 获取边界位置
QVector<QPointF> vecOutlinePoints = pOutlineData->getOutlinePoints();
// 1.3 获取边界名称
QString sOutlineName = pOutlineData->getName();
// 1.4 转换坐标
QVector<QPointF> vecConvertPoints = m_pPlot->getPosForValue(vecOutlinePoints);
// 1.5 根据边界类型绘制不同类型的边界
if(pOutlineData->getOutlineType() == NM_Data_Outline_Type::NM_Rect_Outline_Type) {
// 矩形边界
// 将当前矩形边界对象添加到地图
nmObjRectOutline* pRectOutlinePlot = (nmObjRectOutline*)appendOneObj(NMOT_RectOutline, sOutlineName, vecConvertPoints);
if(pRectOutlinePlot == nullptr) {
return;
}
// 通过 Binder 绑定边界数据到图元对象
m_pGraphicBinder->bindOutlineToGraphic(pRectOutlinePlot, pOutlineData);
} else if(pOutlineData->getOutlineType() == NM_Data_Outline_Type::NM_Round_Outline_Type) {
// 圆形边界
// 将当前多边形边界对象添加到地图
nmObjRoundOutline* pPRoundOutlinePlot = (nmObjRoundOutline*)appendOneObj(NMOT_RoundOutline, sOutlineName, vecConvertPoints);
if(pPRoundOutlinePlot == nullptr) {
return;
}
// 通过 Binder 绑定边界数据到图元对象
m_pGraphicBinder->bindOutlineToGraphic(pPRoundOutlinePlot, pOutlineData);
} else if(pOutlineData->getOutlineType() == NM_Data_Outline_Type::NM_Polygon_Outline_Type) {
// 多边形边界
// 将当前多边形边界对象添加到地图
nmObjPolygonOutline* pPolygonOutlinePlot = (nmObjPolygonOutline*)appendOneObj(NMOT_PolygonOutline, sOutlineName, vecConvertPoints);
if(pPolygonOutlinePlot == nullptr) {
return;
}
// 通过 Binder 绑定边界数据到图元对象
m_pGraphicBinder->bindOutlineToGraphic(pPolygonOutlinePlot, pOutlineData);
}
}
void nmGuiPlot::initWellObjsFromData(nmDataAnalyzeManager* pDataManager)
{
Q_ASSERT(nullptr != pDataManager);
if(pDataManager == nullptr || m_pPlot == nullptr) {
return;
}
// 2.井
// 2.1 获取井数据,来自数据中心
QVector<nmDataWellBase*> vecWellDatas = pDataManager->getWellDataList();
// 2.2 编辑井数组,获取具体的井数据
for(int i = 0; i < vecWellDatas.size(); i++) {
nmDataWellBase* pWellData = vecWellDatas[i];
Q_ASSERT(nullptr != pWellData);
if(pWellData == nullptr) {
continue;
}
// 2.3 获取当前井坐标
QPointF ptWell(pWellData->getX().getValue().toDouble(), pWellData->getY().getValue().toDouble());
QVector<QPointF> vecPtWell;
vecPtWell.append(ptWell);
// 2.4 获取井名
QString sCurWellName = pWellData->getWellName();
// 2.5 构建井图元
nmObjPointWell* pWellPlot = (nmObjPointWell*)appendOneObj(NMOT_Point_Well, sCurWellName, vecPtWell);
if(pWellPlot == nullptr || zxCurProject == nullptr) {
continue;
}
// 2.6 获取当前工区的所有井
ZxDataObjectList wellList = zxCurProject->getChildren(iDataModelType::sTypeWell);
// 2.7 遍历找到与当前井数据一致的井
for(int i = 0; i < wellList.size(); i++) {
ZxDataWell* pWellObj = (ZxDataWell*)wellList[i];
if(pWellObj == nullptr) {
continue;
}
if(_isSame(pWellObj->getName(), sCurWellName)) {
// 设置图元的井数据
pWellPlot->setWellData(pWellObj);
}
}
// 2.8 移动到正确的位置
pWellPlot->moveToPos(pWellPlot->getPosOf(pWellPlot->getAllPos()));
// 2.9 通过 Binder 绑定井数据(推值 + 建立信号连接)
if (m_pGraphicBinder) {
m_pGraphicBinder->bindWellToGraphic(pWellPlot, pWellData);
}
pWellPlot->afterCreated();
}
}
void nmGuiPlot::initFaultObjsFromData(nmDataAnalyzeManager* pDataManager)
{
Q_ASSERT(nullptr != pDataManager);
if(pDataManager == nullptr || m_pPlot == nullptr) {
return;
}
// 3.断层
// 3.1 获取断层数据,来自数据中心
QVector<nmDataFault*> vecFaultData = pDataManager->getFaultDataList();
// 3.2 遍历断层数组的数据
for(int i = 0; i < vecFaultData.size(); i++) {
nmDataFault* pDataFault = vecFaultData[i];
Q_ASSERT(nullptr != pDataFault);
if(pDataFault == nullptr) {
continue;
}
// 3.3 获取断层位置
QVector<QPointF> vecFaultPoints = pDataFault->getFaultPoints();
// 3.4 获取断层名称
QString sFaultName = pDataFault->getFaultName();
// 3.5 转换坐标
QVector<QPointF> vecConvertPoints = m_pPlot->getPosForValue(vecFaultPoints);
// 3.6 将当前断层对象添加到地图
nmObjLineFault* pFaultPlot = (nmObjLineFault*)appendOneObj(NMOT_Line_Fault, sFaultName, vecConvertPoints);
if(pFaultPlot == nullptr) {
continue;
}
// 3.7 通过 Binder 绑定数据(推值 + 建立信号连接)
m_pGraphicBinder->bindFaultToGraphic(pFaultPlot, pDataFault);
// TODO: 设置断层其他属性
}
}
void nmGuiPlot::initFractureObjsFromData(nmDataAnalyzeManager* pDataManager)
{
Q_ASSERT(nullptr != pDataManager);
if(pDataManager == nullptr || m_pPlot == nullptr) {
return;
}
// 4.裂缝
// 4.1 获取裂缝数据,来自数据中心
QVector<nmDataFracture*> vecFractureData = pDataManager->getFractureDataList();
// 4.2 遍历裂缝数组的数据
for(int i = 0; i < vecFractureData.size(); i++) {
nmDataFracture* pDataFracture = vecFractureData[i];
Q_ASSERT(nullptr != pDataFracture);
if(pDataFracture == nullptr) {
continue;
}
// 4.3 获取裂缝位置
QVector<QPointF> vecFracturePoints = pDataFracture->getFracturePoints();
// 4.4 获取裂缝名称
QString sFractureName = pDataFracture->getFractureName();
// 4.5 转换坐标
QVector<QPointF> vecConvertPoints = m_pPlot->getPosForValue(vecFracturePoints);
// 4.6 将当前裂缝对象添加到地图
nmObjLineCrack* pFracturePlot = (nmObjLineCrack*)appendOneObj(NMOT_Line_Fracture, sFractureName, vecConvertPoints);
if(pFracturePlot == nullptr) {
continue;
}
// 4.7 通过 Binder 绑定数据(推值 + 建立信号连接)
m_pGraphicBinder->bindCrackToGraphic(pFracturePlot, pDataFracture);
// TODO: 设置裂缝其他属性
}
}
void nmGuiPlot::initRegionObjsFromData(nmDataAnalyzeManager* pDataManager)
{
Q_ASSERT(nullptr != pDataManager);
if(pDataManager == nullptr || m_pPlot == nullptr) {
return;
}
// 5.区域
// 5.1 获取区域数据,来自数据中心
QVector<nmDataRegion*> vecRegionData = pDataManager->getRegionDataList();
// 5.2 遍历区域数组的数据
for(int i = 0; i < vecRegionData.size(); i++) {
nmDataRegion* pDataRegion = vecRegionData[i];
Q_ASSERT(nullptr != pDataRegion);
if(pDataRegion == nullptr) {
continue;
}
// 5.3 获取区域位置
QVector<QPointF> vecRegionPoints = pDataRegion->getVecPts();
// 5.4 获取区域名称
QString sRegionName = pDataRegion->getRegoinName();
// 5.5 转换坐标
QVector<QPointF> vecConvertPoints = m_pPlot->getPosForValue(vecRegionPoints);
// 5.6 将当前区域对象添加到地图
nmObjRegion* pRegionPlot = (nmObjRegion*)appendOneObj(NMOT_Region, sRegionName, vecConvertPoints);
if(pRegionPlot == nullptr) {
continue;
}
// 5.7 通过 Binder 绑定区域数据到图元
if (m_pGraphicBinder) {
m_pGraphicBinder->bindRegionToGraphic(pRegionPlot, pDataRegion);
}
}
}
void nmGuiPlot::initRegionMarkObjsFromData(nmDataAnalyzeManager* pDataManager)
{
Q_ASSERT(nullptr != pDataManager);
if(pDataManager == nullptr || m_pPlot == nullptr) {
return;
}
// 6.区域标记
// 6.1 获取区域标记数据,来自数据中心
QVector<nmDataRegionMark*> vecRegionMarkData = pDataManager->getRegionMarkDataList();
// 6.2 遍历区域标记数组的数据
for(int i = 0; i < vecRegionMarkData.size(); i++) {
nmDataRegionMark* pDataRegionMark = vecRegionMarkData[i];
Q_ASSERT(nullptr != pDataRegionMark);
if(pDataRegionMark == nullptr) {
continue;
}
// 6.3 获取区域标记位置
QPointF ptRegionMark = pDataRegionMark->getPtPos();
QVector<QPointF> vecPtRegionMark;
vecPtRegionMark.append(ptRegionMark);
// 6.4 获取区域标记名称
QString sRegionMarkName = pDataRegionMark->getRegionMarkName();
// 6.5 转换坐标
QVector<QPointF> vecConvertPoints = m_pPlot->getPosForValue(vecPtRegionMark);
// 6.6 将当前区域标记对象添加到地图
nmObjRegionMark* pRegionMarkPlot = (nmObjRegionMark*)appendOneObj(NMOT_RegionMark, sRegionMarkName, vecConvertPoints);
if(pRegionMarkPlot == nullptr) {
continue;
}
// 6.7 通过 Binder 绑定区域标记数据到图元
if (m_pGraphicBinder) {
m_pGraphicBinder->bindRegionMarkToGraphic(pRegionMarkPlot, pDataRegionMark);
}
}
}
void nmGuiPlot::deleteAllPlotObjs()
{
if(m_pPlot == nullptr) {
return;
}
// 这里只清理显示对象不能调用removeData()删除DataManager中的业务数据。
// 先解除全部绑定再倒序删除图元避免重名对象残留或Binder保存悬空指针。
if(m_pGraphicBinder != nullptr) {
m_pGraphicBinder->updateDataMgr(dataManager());
}
for(int nIndex = m_pPlot->getObjCount() - 1; nIndex >= 0; --nIndex) {
m_pPlot->removeObjByIndex(nIndex);
}
}
nmObjBase* nmGuiPlot::appendOneObj(NM_Obj_Type o, QString& sName, QVector<QPointF>& vec)
{
nmObjBase* pObj = _createOneObj(o, sName);
if(NULL == pObj) {
return NULL;
}
pObj->setAllPos(vec);
//pObj->select(true);
//pObj->dealSelChanged(true);
pObj->update();
// 当对象创建完成之后进行的操作如改变按钮Check的状态
//emit sigObjCompleted(pObj); //通常有Plot触发而非iGuiPlot
// 所以直接用 slotObjCompleted
slotObjCompleted(pObj);
setModified(true);
return pObj;
}
nmObjBase* nmGuiPlot::_createOneObj(NM_Obj_Type o, QString& sName)
{
Q_ASSERT(NULL != m_pPlot);
// 确保名称不重复
QStringList listOlds;
for(int i = 0; i < m_pPlot->getObjCount(); i++) {
listOlds << m_pPlot->getObjByIndex(i)->getName();
}
sName = ZxBaseUtil::getNextOneName(listOlds, sName);
// 创建,此处代码为了简洁,作了非规范性书写
nmObjBase* pObj = NULL;
if(o == NMOT_Point) {
pObj = new nmObjPoint(sName, NULL, NULL);
} else if(o == NMOT_Point_Well) {
pObj = new nmObjPointWell(sName, NULL, NULL);
} else if(o == NMOT_Line) {
pObj = new nmObjLine(sName, NULL, NULL);
} else if(o == NMOT_Polygon) {
pObj = new nmObjPolygon(sName, NULL, NULL);
} else if(o == NMOT_PolygonOutline) {
pObj = new nmObjPolygonOutline(sName, NULL, NULL);
} else if(o == NMOT_Rect) { //矩形
pObj = new nmObjRect(sName, NULL, NULL);
} else if(o == NMOT_RectOutline) { //矩形边界
pObj = new nmObjRectOutline(sName, NULL, NULL);
} else if(o == NMOT_Round) { //圆形
pObj = new nmObjRound(sName, NULL, NULL);
} else if(o == NMOT_RoundOutline) { //圆形边界
pObj = new nmObjRoundOutline(sName, NULL, NULL);
} else if(o == NMOT_Line_Fracture) {
pObj = new nmObjLineCrack(sName, NULL, NULL);
} else if(o == NMOT_Line_Fault) {
pObj = new nmObjLineFault(sName, NULL, NULL);
} else if(o == NMOT_Region) {
pObj = new nmObjRegion(sName, NULL, NULL);
} else if(o == NMOT_Line_MeasuringScale) {
pObj = new nmObjLineMeasuringScale(sName, NULL, NULL);
} else if(o == NMOT_Line_Measure) {
pObj = new nmObjLineMeasure(sName, NULL, NULL);
} else if(o == NMOT_RegionMark) {
pObj = new nmObjRegionMark(sName, NULL, NULL, m_iRegionMarkCount);
m_iRegionMarkCount++;
} else {
qDebug() << tr("Type '%1' not supported.").arg((int)o);
nmDataLogFile::getInstance()->writeLog(tr("Type '%1' not supported.").arg((int)o));
return NULL;
}
Q_ASSERT(NULL != pObj);
bindObjSignals(pObj);
m_pPlot->addOneObj(pObj);
// 将边界置于最底层
if(o == NMOT_RectOutline || o == NMOT_PolygonOutline || o == NMOT_RoundOutline) {
//m_pPlot->sendToBack(pObj);
}
return pObj;
}
void nmGuiPlot::bindObjSignals(ZxObjBase* pObj)
{
Q_ASSERT(NULL != pObj);
disconnect(pObj, SIGNAL(sigObjSelectionChanged(bool)), \
this, SLOT(slotObjSelChanged(bool)));
disconnect(pObj, SIGNAL(sigPtsChanged()), \
this, SLOT(slotObjPtsChanged()));
connect(pObj, SIGNAL(sigObjSelectionChanged(bool)), \
this, SLOT(slotObjSelChanged(bool)));
connect(pObj, SIGNAL(sigPtsChanged()), \
this, SLOT(slotObjPtsChanged()));
}
// Obj选择状态改变
void nmGuiPlot::slotObjSelChanged(bool b)
{
ZxObjBase* p = dynamic_cast<ZxObjBase*>(sender());
if(NULL != p) {
emit sigObjSelChanged(p, b);
}
}
// Obj数据发生了改变
void nmGuiPlot::slotObjPtsChanged()
{
ZxObjBase* p = dynamic_cast<ZxObjBase*>(sender());
if(NULL != p) {
emit sigObjPtsChanged(p);
}
}
void nmGuiPlot::slotDeleteWell(QString wellID)
{
nmDataLogFile::getInstance()->writeLog(wellID + " ========");
// 找到要删除的图片
nmObjPointWell* obj = (nmObjPointWell*)this->getWellObjById(wellID);
if(obj == nullptr || m_pPlot == nullptr) {
return;
}
// 创建分析时绑定的主井是流动段及数值输入基准,不能从数值 Map 单独删除。
if(m_pGraphicBinder && m_pGraphicBinder->isPrimaryWellGraphic(obj)) {
QMessageBox::information(this,
tr("Cannot Delete Well"),
tr("The primary analysis well cannot be deleted."));
return;
}
// // 创建一个QTimer对象
// QTimer* timer = new QTimer();
// // 创建一个要执行的单次任务
// QObject::connect(timer, &QTimer::timeout, []() {
// // 这里是你想要延迟执行的代码
// qDebug() << "任务执行了!";
// });
// // 设置延迟时间(单位毫秒)
// int delay = 2000; // 例如2000毫秒2秒
// timer->setSingleShot(true); // 设置为单次触发
// timer->start(delay); // 开始计时时间到后执行timeout信号关联的任务
// 删除结构树里的对象
if(zxCurProject != nullptr && obj->getWellData() != nullptr) {
zxCurProject->removeChild(obj->getWellData());
}
// 删除图元
m_pPlot->removeObjByName(obj->getName());
}
void nmGuiPlot::onSerialize(ZxSerializer* ser)
{
iGuiPlot::onSerialize(ser);
}
void nmGuiPlot::onDeserialize(ZxSerializer* ser)
{
iGuiPlot::onDeserialize(ser);
}
void nmGuiPlot::resetAfterDeserialized()
{
iGuiPlot::resetAfterDeserialized();
if(NULL == m_pPlot) {
return;
}
connectSignals();
slotChangeSizeWithChangedXY();
setModified(false);
for(int i = 0; i < m_pPlot->getObjCount(); i++) {
nmObjBase* pObj = (nmObjBase*)m_pPlot->getObjByIndex(i);
if(NULL != pObj) {
// 建立信号
bindObjSignals(pObj);
}
}
}
QVector<ZxObjBase*> nmGuiPlot::getObjsByTag(QString objTag)
{
QVector<ZxObjBase*> pObjVec;
if(m_pPlot == nullptr) {
return pObjVec;
}
int objCount = m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = m_pPlot->getObjByIndex(i);
if(obj != nullptr && _isSame(objTag, obj->getTagName())) {
pObjVec.append(obj);
}
}
return pObjVec;
}
ZxObjBase* nmGuiPlot::getWellObjById(QString id)
{
int objCount = m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = m_pPlot->getObjByIndex(i);
nmDataLogFile::getInstance()->writeLog(QString::fromStdString(obj->getTagName()) + " ======");
if(_isSame("nObjPointWell", obj->getTagName())) {
nmObjPointWell* pWellPlot = dynamic_cast<nmObjPointWell*>(obj);
if(pWellPlot == nullptr) {
continue;
}
if(_isSame(id, pWellPlot->getWellID())) {
return pWellPlot;
}
}
}
return NULL;
}
QVector<QPointF> nmGuiPlot::getOutlinePoints()
{
QVector<QPointF> pointList;
// 获取边界的所有点
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjPolygonOutline");
// 如果是多边形边界
if(objList.count() > 0) {
ZxObjBase* outlineObj = objList[0];
return outlineObj->getValueOf(outlineObj->getAllPos());
}
// 获取边界的所有点
objList = this->getObjsByTag("nObjRectOutline");
// 如果是多边形边界
if(objList.count() > 0) {
ZxObjBase* outlineObj = objList[0];
return outlineObj->getValueOf(outlineObj->getAllPos());
}
// TODO,需要支持圆形边界
return pointList;
}
QVector<QVector<double >> nmGuiPlot::getWellsInformation()
{
QVector<QVector<double >> wellsList;
// 获取边界的所有点
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjPointWell");
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
nmObjPointWell* pWell = (nmObjPointWell*)objList[i];
QVector<double> wellInfo = pWell->getWellInformation();
if(wellInfo.count() == 3) {
wellsList.append(wellInfo);
}
}
}
return wellsList;
}
QVector<QVector<QPointF> > nmGuiPlot::getCracksInformation()
{
QVector<QVector<QPointF >> vCracks;
// 获取裂缝的所有点
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjLineFracture");
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
nmObjLineCrack* pCrack = (nmObjLineCrack*)objList[i];
vCracks.append(pCrack->getValueOf(pCrack->getAllPos()));
}
}
return vCracks;
}
QVector<QVector<QPointF> > nmGuiPlot::getFaultsInformation()
{
QVector<QVector<QPointF >> vFaults;
// 获取裂缝的所有点
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjLineFault");
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
nmObjLineFault* pFault = (nmObjLineFault*)objList[i];
vFaults.append(pFault->getValueOf(pFault->getAllPos()));
}
}
return vFaults;
}
QVector<QVector<QPointF>> nmGuiPlot::getRegionsInformation()
{
QVector<QVector<QPointF >> vRegions;
// 获取裂缝的所有点
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjRegion");
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
nmObjRegion* pRegion = (nmObjRegion*)objList[i];
QVector<QPointF> vPos = pRegion->getAllPos();
for(size_t j = 0; j < vPos.size(); j++) {
QPointF& p = vPos[j];
qDebug() << QString("%1,%2").arg(p.x()).arg(p.y());
}
vRegions.append(pRegion->getValueOf(pRegion->getAllPos()));
}
}
return vRegions;
}
QVector<nmObjPointWell*> nmGuiPlot::getWellPlots()
{
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjPointWell");
QVector<nmObjPointWell*> wellPlots;
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
wellPlots.append((nmObjPointWell*) objList[i]);
}
}
return wellPlots;
}
QVector<ZxDataWell*> nmGuiPlot::getWellDatas()
{
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjPointWell");
QVector<ZxDataWell*> wellDatas;
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
wellDatas.append(((nmObjPointWell*) objList[i])->getWellData());
}
}
return wellDatas;
}
QStringList nmGuiPlot::getWellNames()
{
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjPointWell");
QStringList wellNames;
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
wellNames.append(((nmObjPointWell*) objList[i])->getWellData()->getName());
}
}
return wellNames;
}
QVector<nmObjBase*> nmGuiPlot::getAllPlots()
{
QVector<nmObjBase*> pObjVec;
int objCount = m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = m_pPlot->getObjByIndex(i);
pObjVec.append(static_cast<nmObjBase*>(obj));
}
return pObjVec;
}
void nmGuiPlot::paintEvent(QPaintEvent* e)
{
iGuiPlot::paintEvent(e);
}
#ifdef QT_DEBUG
ZxObjBase* nmGuiPlot::updatePlotObjBy(QString sName, \
VecDouble& vecX, VecDouble& vecY, \
bool bPressureLike /*= true*/, \
bool bUseY2 /*= false*/, \
bool bClearAll /*= false*/)
{
if(vecX.count() < 2 || vecX.count() != vecY.count()) {
return NULL;
}
ZxPlot* pPlot = m_pPlot;
Q_ASSERT(NULL != pPlot);
// 移除先前图上已经有的曲线
int n = pPlot->getObjCount();
for(int i = n - 1; i >= 0; i--) {
ZxObjBase* pObj = pPlot->getObjByIndex(i);
if(NULL == pObj) {
continue;
}
if(bClearAll) {
pPlot->removeObjByIndex(i);
} else if(_isSame(sName, pObj->getName())) {
pPlot->removeObjByIndex(i);
break;
}
}
ZxObjCurve* pObj = NULL;
if(bPressureLike) {
pObj = appendSeriesP(vecX, vecY, sName, bUseY2);
} else {
pObj = appendSeriesF(vecX, vecY, sName, bUseY2);
}
if(NULL != pObj) {
setPenAndDot(pObj, !bPressureLike, !bPressureLike);
bindObjSignals(pObj);
}
return pObj;
}
#endif
void nmGuiPlot::slotMeasuringScale(QPointF pStart, QPointF pEnd, void* obj)
{
// 弹出dialog1、显示 X、Y坐标2、设置长度和单位
double dLength = 0;
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
if(pDialogProvider != nullptr && pDialogProvider->execMeasuringScaleDialog(pStart, pEnd, &dLength)) {
if(m_pPlot == nullptr) {
return;
}
ZxSubAxisX* pAxisX = m_pPlot->getMainAxisX();
ZxSubAxisY* pAxisY = m_pPlot->getMainAxisY();
if(pAxisX == nullptr || pAxisY == nullptr) {
return;
}
// 计算原始长度
double dOriLength = sqrt((pStart.x() - pEnd.x()) * (pStart.x() - pEnd.x()) + (pStart.y() - pEnd.y()) *
(pStart.y() - pEnd.y()));
qDebug() << dOriLength;
qDebug() << dLength;
// 根据比例来进行调整整个画布的尺寸
// 先获取当前的X 和 Y的尺寸
double dXMin = pAxisX->getRangeMin();
double dXMax = pAxisX->getRangeMax();
double dYMin = pAxisY->getRangeMin();
double dYMax = pAxisY->getRangeMax();
// 根据给的参数进行比例的计算
double dScale = dLength / dOriLength;
double dXRangeScaled = (dXMax - dXMin) * dScale;
double dYRangeScaled = (dYMax - dYMin) * dScale;
double dXMaxScaled = dXRangeScaled - dXMin;
double dYMaxScaled = dYRangeScaled - dYMin;
// 根据比例计算得到新的X和Y
// 设置新的X 和 Y
// 设置默认的X和Y坐标
//m_pPlot->getMainAxisX()->setRangeMin(0);
m_pPlot->getMainAxisX()->setRangeMax(dXMaxScaled);
//m_pPlot->getMainAxisY()->setRangeMin(0);
m_pPlot->getMainAxisY()->setRangeMax(dYMaxScaled);
}
// 将比例尺对象删除
nmObjLineMeasuringScale* pScaleObj = (nmObjLineMeasuringScale*)obj;
//pScaleObj->getAllValues()
Q_ASSERT(nullptr != obj);
// 删除图元
m_pPlot->removeObjByName(pScaleObj->getName());
}
void nmGuiPlot::deleteMeasureObjects()
{
QVector<ZxObjBase*> measureObjs = getObjsByTag("nObjLineMeasure");
for(int i = 0; i < measureObjs.count(); i++) {
if(measureObjs[i] != nullptr) {
nmObjLineMeasure* pMeasure = dynamic_cast<nmObjLineMeasure*>(measureObjs[i]);
if(pMeasure) {
pMeasure->removeData();
}
m_pPlot->removeObjByName(measureObjs[i]->getName());
}
}
// 清空数据对象
nmDataAnalyzeManager::getCurrentInstance()->removeMeasureData();
// 恢复画布可编辑状态
setAllPlotObjectsEditable(true);
}
void nmGuiPlot::clearPreviousMeasure()
{
QVector<ZxObjBase*> measureObjs = getObjsByTag("nObjLineMeasure");
for(int i = 0; i < measureObjs.count(); i++) {
if(measureObjs[i] != nullptr) {
nmObjLineMeasure* pMeasure = dynamic_cast<nmObjLineMeasure*>(measureObjs[i]);
if(pMeasure) {
pMeasure->removeData();
}
m_pPlot->removeObjByName(measureObjs[i]->getName());
}
}
nmDataMeasure* data = nmDataAnalyzeManager::getCurrentInstance()->getMeasureData();
if(data) {
data->setStartPoint(QPointF(0, 0));
data->setEndPoint(QPointF(0, 0));
data->setCurrentPoint(QPointF(0, 0));
nmDataAttribute lenAttr = data->getLength();
lenAttr.setValue(0.0);
data->setLength(lenAttr);
}
}
void nmGuiPlot::setAllPlotObjectsEditable(bool editable)
{
if(m_pPlot == nullptr) {
return;
}
int objCount = m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = m_pPlot->getObjByIndex(i);
if(obj == nullptr) {
continue;
}
obj->setReadOnly(!editable);
obj->setLockPos(!editable);
}
}
void nmGuiPlot::bindPointerPosDialog(QWidget* pointerPosDlg)
{
if(pointerPosDlg == nullptr || m_pPlotView == nullptr) {
return;
}
disconnect(m_pPlotView, SIGNAL(sigPointerPos(double, double)), pointerPosDlg, SLOT(setPointerPos(double, double)));
connect(m_pPlotView, SIGNAL(sigPointerPos(double, double)), pointerPosDlg, SLOT(setPointerPos(double, double)));
}
void nmGuiPlot::slotDeleteOneObj(QString sName, void* obj)
{
if(m_pPlot == nullptr) {
return;
}
if(sName != NULL) {
// 删除前先校验目标对象。
// 如果目标不存在,或目标井是固定主分析井,则结束删除工具并直接返回。
// 预检必须发生在确认对话框和图元删除前,避免数据层拒绝后只剩半套状态。
nmObjDeleteTool* pDeleteTool = static_cast<nmObjDeleteTool*>(obj);
nmObjBase* nmObj = dynamic_cast<nmObjBase*>(m_pPlot->getObjByName(sName));
if(nmObj == nullptr) {
if(pDeleteTool) {
m_pPlot->removeTools(pDeleteTool);
}
return;
}
if(nmObjPointWell* pWellObj = dynamic_cast<nmObjPointWell*>(nmObj)) {
if(m_pGraphicBinder && m_pGraphicBinder->isPrimaryWellGraphic(pWellObj)) {
if(pDeleteTool) {
m_pPlot->removeTools(pDeleteTool);
}
QMessageBox::information(
this,
tr("Cannot Delete Well"),
tr("The primary analysis well cannot be deleted."));
return;
}
}
nmPlotDialogContextProvider* pDialogProvider = nmPlotDialogContext::provider();
if(pDialogProvider != nullptr && pDialogProvider->confirmDeleteObject()) {
nmObjDeleteTool* pDeleteTool = static_cast<nmObjDeleteTool*>(obj);
if(pDeleteTool) { // 确保 obj 不是空指针
m_pPlot->removeTools(pDeleteTool);
//ZxObjBase* obj = m_pPlot->getObjByName(sName);
nmObjBase* nmObj = dynamic_cast<nmObjBase*>(m_pPlot->getObjByName(sName));
if(nmObj) {
m_pPlot->removeObjByName(sName);
// 先通过 Binder 清理数据绑定(如果是断层/裂缝/边界等 Binder 管理的类型)
if (nmObjLineFault* pFault = dynamic_cast<nmObjLineFault*>(nmObj)) {
m_pGraphicBinder->removeFaultBinding(pFault);
} else if (nmObjLineCrack* pCrack = dynamic_cast<nmObjLineCrack*>(nmObj)) {
m_pGraphicBinder->removeCrackBinding(pCrack);
} else if (dynamic_cast<nmObjRoundOutline*>(nmObj) ||
dynamic_cast<nmObjRectOutline*>(nmObj) ||
dynamic_cast<nmObjPolygonOutline*>(nmObj)) {
m_pGraphicBinder->removeOutlineBinding(nmObj);
} else if (nmObjLineMeasure* pMeasure = dynamic_cast<nmObjLineMeasure*>(nmObj)) {
m_pGraphicBinder->removeMeasureBinding(pMeasure);
} else if (nmObjRegionMark* pRegionMark = dynamic_cast<nmObjRegionMark*>(nmObj)) {
m_pGraphicBinder->removeRegionMarkBinding(pRegionMark);
} else if (nmObjRegion* pRegion = dynamic_cast<nmObjRegion*>(nmObj)) {
m_pGraphicBinder->removeRegionBinding(pRegion);
} else {
// 其他类型回退到旧方式
nmObj->removeData();
}
}
}
} else {
nmObjDeleteTool* pDeleteTool = static_cast<nmObjDeleteTool*>(obj);
if(pDeleteTool) { // 确保 obj 不是空指针
m_pPlot->removeTools(pDeleteTool);
}
}
}
}
void nmGuiPlot::clearPlotsSelectStates()
{
// 获取所有图元
QVector<nmObjBase*> vecObjs = this->getAllPlots();
// 遍历所有图元对象,如果为选中状态,则恢复为未选中
foreach(nmObjBase* obj, vecObjs) {
if(obj->isSelected()) {
obj->setSelected(false);
}
}
}
void nmGuiPlot::deleteAllDFNPlots()
{
QVector<ZxObjBase*> objList = this->getObjsByTag("nObjLineFracture");
if(objList.count() > 0) {
for(int i = 0; i < objList.count() ; i++) {
nmObjLineCrack* pCrack = (nmObjLineCrack*)objList[i];
if(pCrack == nullptr || m_pGraphicBinder == nullptr) {
continue;
}
nmDataFracture* pData = m_pGraphicBinder->getCrackDataFor(pCrack);
if(pData == nullptr) {
continue;
}
if(pData->getFractureType().getValue() == tr("DFN")) {
// 通过 Binder 清理数据绑定
m_pGraphicBinder->removeCrackBinding(pCrack);
// 删除DFN图元
m_pPlot->removeObjByName(pCrack->getName());
}
}
}
}
nmDataAnalyzeManager* nmGuiPlot::dataManager() const
{
return m_pDataManager != nullptr
? m_pDataManager
: nmDataAnalyzeManager::getCurrentInstance();
}
bool nmGuiPlot::calculateVisibleContentBounds(QRectF& oBounds) const
{
nmDataAnalyzeManager* pDataManager = dataManager();
if(pDataManager == nullptr) {
return false;
}
bool bHasBounds = false;
double dMinX = 0.0;
double dMaxX = 0.0;
double dMinY = 0.0;
double dMaxY = 0.0;
nmDataOutline* pOutlineData = pDataManager->getOutlineData();
if(pOutlineData != nullptr && pOutlineData->getPlotVisible()) {
if(pOutlineData->getOutlineType() == NM_Round_Outline_Type) {
const QPointF oCenter = pOutlineData->getCenter();
const double dRadius = qAbs(pOutlineData->getRadius());
includeMapPoint(QPointF(oCenter.x() - dRadius,
oCenter.y() - dRadius),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
includeMapPoint(QPointF(oCenter.x() + dRadius,
oCenter.y() + dRadius),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
} else {
includeMapPoints(pOutlineData->getOutlinePoints(),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
}
}
const QVector<nmDataWellBase*> vecWells = pDataManager->getWellDataList();
foreach(nmDataWellBase* pWellData, vecWells) {
if(pWellData != nullptr && pWellData->getPlotVisible()) {
includeMapPoint(QPointF(
pWellData->getX().getValue().toDouble(),
pWellData->getY().getValue().toDouble()),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
}
}
const QVector<nmDataFault*> vecFaults = pDataManager->getFaultDataList();
foreach(nmDataFault* pFaultData, vecFaults) {
if(pFaultData != nullptr && pFaultData->getPlotVisible()) {
includeMapPoints(pFaultData->getFaultPoints(),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
}
}
const QVector<nmDataFracture*> vecFractures =
pDataManager->getFractureDataList();
foreach(nmDataFracture* pFractureData, vecFractures) {
if(pFractureData != nullptr && pFractureData->getPlotVisible()) {
includeMapPoints(pFractureData->getFracturePoints(),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
}
}
const QVector<nmDataRegion*> vecRegions = pDataManager->getRegionDataList();
foreach(nmDataRegion* pRegionData, vecRegions) {
if(pRegionData != nullptr && pRegionData->getPlotVisible()) {
includeMapPoints(pRegionData->getVecPts(),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
}
}
const QVector<nmDataRegionMark*> vecRegionMarks =
pDataManager->getRegionMarkDataList();
foreach(nmDataRegionMark* pRegionMarkData, vecRegionMarks) {
if(pRegionMarkData != nullptr && pRegionMarkData->getPlotVisible()) {
includeMapPoint(pRegionMarkData->getPtPos(),
bHasBounds, dMinX, dMaxX, dMinY, dMaxY);
}
}
if(!bHasBounds) {
return false;
}
oBounds = QRectF(QPointF(dMinX, dMinY),
QPointF(dMaxX, dMaxY)).normalized();
return true;
}
void nmGuiPlot::applyAxisRange(double dXMin, double dXMax,
double dYMin, double dYMax)
{
if(m_pPlot == nullptr ||
!qIsFinite(dXMin) || !qIsFinite(dXMax) ||
!qIsFinite(dYMin) || !qIsFinite(dYMax) ||
dXMax <= dXMin || dYMax <= dYMin) {
return;
}
const bool bOldApplying = m_bApplyingAxisRange;
m_bApplyingAxisRange = true;
m_pPlot->getMainAxisX()->setRangeMinMax(dXMin, dXMax, true, false);
m_pPlot->getMainAxisY()->setRangeMinMax(dYMin, dYMax, true, false);
nmDataAnalyzeManager* pDataManager = dataManager();
nmDataAxis* pAxisData = pDataManager != nullptr
? pDataManager->getAxisData() : nullptr;
if(pAxisData != nullptr) {
pAxisData->getXMin().setValue(dXMin);
pAxisData->getXMax().setValue(dXMax);
pAxisData->getYMin().setValue(dYMin);
pAxisData->getYMax().setValue(dYMax);
}
m_bApplyingAxisRange = bOldApplying;
}
bool nmGuiPlot::fitInitialAxisToContent()
{
if(m_pPlot == nullptr) {
return false;
}
QRectF oBounds;
if(!calculateVisibleContentBounds(oBounds)) {
return false;
}
QRectF oPlotRect = m_pPlot->getInnerRectF();
if(oPlotRect.width() <= 0.0 || oPlotRect.height() <= 0.0) {
return false;
}
double dCenterX = (oBounds.left() + oBounds.right()) * 0.5;
double dCenterY = (oBounds.top() + oBounds.bottom()) * 0.5;
double dRangeX = oBounds.width();
double dRangeY = oBounds.height();
// 退化为点或直线时补足基础跨度,避免产生零范围坐标轴。
if(dRangeX <= 0.0) {
dRangeX = 1500.0;
}
if(dRangeY <= 0.0) {
dRangeY = 1500.0;
}
// 内容四周各增加最大边长的 5%,边界本身不因此发生变化。
const double dPadding = qMax(dRangeX, dRangeY) * 0.05;
dRangeX += dPadding * 2.0;
dRangeY += dPadding * 2.0;
const double dViewRatio = oPlotRect.width() / oPlotRect.height();
const double dContentRatio = dRangeX / dRangeY;
if(dContentRatio < dViewRatio) {
dRangeX = dRangeY * dViewRatio;
} else {
dRangeY = dRangeX / dViewRatio;
}
applyAxisRange(dCenterX - dRangeX * 0.5,
dCenterX + dRangeX * 0.5,
dCenterY - dRangeY * 0.5,
dCenterY + dRangeY * 0.5);
return true;
}
void nmGuiPlot::scheduleInitialAxisView()
{
if(m_bAxisInitializationPending) {
return;
}
m_bAxisInitializationPending = true;
QTimer::singleShot(0, this, SLOT(initializeAxisView()));
}
void nmGuiPlot::initializeAxisView()
{
m_bAxisInitializationPending = false;
nmDataAnalyzeManager* pDataManager = dataManager();
nmDataAxis* pAxisData = pDataManager != nullptr
? pDataManager->getAxisData() : nullptr;
if(pAxisData == nullptr || pAxisData->isInitialViewFitted()) {
return;
}
// 只有真实绘图区和图元均准备好后才封闭初始化,失败时等待下一次显示尺寸变化。
if(fitInitialAxisToContent()) {
pAxisData->setInitialViewFitted(true);
}
}
void nmGuiPlot::resizeEvent(QResizeEvent* pEvent)
{
nmDataAnalyzeManager* pDataManager = dataManager();
nmDataAxis* pAxisData = pDataManager != nullptr
? pDataManager->getAxisData() : nullptr;
const bool bWaitingForInitialView =
pAxisData != nullptr && !pAxisData->isInitialViewFitted();
const bool bOldApplying = m_bApplyingAxisRange;
if(bWaitingForInitialView) {
// 布局阶段可能触发轴信号,不能把它误认为用户已经设置了范围。
m_bApplyingAxisRange = true;
}
iGuiPlot::resizeEvent(pEvent);
m_bApplyingAxisRange = bOldApplying;
if(bWaitingForInitialView) {
scheduleInitialAxisView();
}
}
void nmGuiPlot::onRangeXChanged(double dMin, double dMax, bool bRecalTicks, bool bAdjustRectZoomRatio)
{
nmDataAnalyzeManager* pDataManager = dataManager();
nmDataAxis* pAxisData = pDataManager != nullptr
? pDataManager->getAxisData() : nullptr;
if(pAxisData == nullptr) {
return;
}
// 获取 X 最大值
pAxisData->getXMax().setValue(dMax);
// 获取 X 最小值
pAxisData->getXMin().setValue(dMin);
if(!m_bApplyingAxisRange) {
// 任一用户轴操作都终止首次初始化,后续范围完全由用户控制。
pAxisData->setInitialViewFitted(true);
}
}
void nmGuiPlot::onRangeYChanged(double dMin, double dMax, bool bRecalTicks, bool bAdjustRectZoomRatio)
{
nmDataAnalyzeManager* pDataManager = dataManager();
nmDataAxis* pAxisData = pDataManager != nullptr
? pDataManager->getAxisData() : nullptr;
if(pAxisData == nullptr) {
return;
}
// 获取 Y 最大值
pAxisData->getYMax().setValue(dMax);
// 获取 Y 最小值
pAxisData->getYMin().setValue(dMin);
if(!m_bApplyingAxisRange) {
pAxisData->setInitialViewFitted(true);
}
}
// ============================== 可见性设置方法实现 ==============================
void nmGuiPlot::setContourVisibility(bool bIsVisible)
{
// 边界图元对象
QVector<ZxObjBase*> vecPlotObjs;
// 1、从数据中心获取当前边界类型
nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance();
if(pManager == nullptr || pManager->getOutlineData() == nullptr) {
return;
}
NM_Data_Outline_Type eOutlineType = pManager->getOutlineData()->getOutlineType();
// 2、根据边界类型设置是否可见
if(eOutlineType == NM_Data_Outline_Type::NM_Rect_Outline_Type) {
vecPlotObjs = this->getObjsByTag("nObjRectOutline");
if(vecPlotObjs.count() > 0) {
for(int i = 0; i < vecPlotObjs.count() ; i++) {
nmObjRectOutline* pOutline = (nmObjRectOutline*)vecPlotObjs[i];
if(pOutline != nullptr) {
pOutline->setVisible(bIsVisible);
}
}
}
} else if(eOutlineType == NM_Data_Outline_Type::NM_Polygon_Outline_Type) {
vecPlotObjs = this->getObjsByTag("nObjPolygonOutline");
if(vecPlotObjs.count() > 0) {
for(int i = 0; i < vecPlotObjs.count() ; i++) {
nmObjPolygonOutline* pOutline = (nmObjPolygonOutline*)vecPlotObjs[i];
if(pOutline != nullptr) {
pOutline->setVisible(bIsVisible);
}
}
}
} else if(eOutlineType == NM_Data_Outline_Type::NM_Round_Outline_Type) {
vecPlotObjs = this->getObjsByTag("nObjRoundOutline");
if(vecPlotObjs.count() > 0) {
for(int i = 0; i < vecPlotObjs.count() ; i++) {
nmObjRoundOutline* pOutline = (nmObjRoundOutline*)vecPlotObjs[i];
if(pOutline != nullptr) {
pOutline->setVisible(bIsVisible);
}
}
}
}
}
void nmGuiPlot::setImagesVisibility(bool bIsVisible)
{
// TODO:
// 从数据中心获取背景图片信息
nmDataAnalyzeManager* pManager = nmDataAnalyzeManager::getCurrentInstance();
if(pManager) {
BackgroundImageInfo currentInfo = pManager->getBackgroundImageInfo();
currentInfo.bIsVisible = bIsVisible; // 更新可见性状态
pManager->setBackgroundImageInfo(currentInfo); // 更新数据中心
if(bIsVisible) {
// 重新设置背景
m_pPlot->setBkImgFile(currentInfo.sFilePath);
} else {
// 设置空地址作为背景图片,即不可见
m_pPlot->setBkImgFile("");
}
}
}
/**
* @brief 设置所有井的可见性
*/
void nmGuiPlot::setAllWellsVisible(bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjPointWell");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjPointWell* pWell = static_cast<nmObjPointWell*>(vecPlotObjs.at(i));
pWell->setVisible(bIsVisible);
}
}
/**
* @brief 设置单个井的可见性
*/
void nmGuiPlot::setWellVisible(QString sObjName, bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjPointWell");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjPointWell* pWell = static_cast<nmObjPointWell*>(vecPlotObjs.at(i));
if(pWell->getName() == sObjName) {
pWell->setVisible(bIsVisible);
break;
}
}
}
/**
* @brief 设置所有断层的可见性
*/
void nmGuiPlot::setAllFaultsVisible(bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjLineFault");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjLineFault* pFault = static_cast<nmObjLineFault*>(vecPlotObjs.at(i));
pFault->setVisible(bIsVisible);
}
}
/**
* @brief 设置单个断层的可见性
*/
void nmGuiPlot::setFaultVisible(QString sObjName, bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjLineFault");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjLineFault* pFault = static_cast<nmObjLineFault*>(vecPlotObjs.at(i));
if(pFault->getName() == sObjName) {
pFault->setVisible(bIsVisible);
break;
}
}
}
/**
* @brief 设置所有裂缝的可见性
*/
void nmGuiPlot::setAllFracturesVisible(bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjLineFracture");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjLineCrack* pFracture = static_cast<nmObjLineCrack*>(vecPlotObjs.at(i));
pFracture->setVisible(bIsVisible);
}
}
/**
* @brief 设置单个裂缝的可见性
*/
void nmGuiPlot::setFractureVisible(QString sObjName, bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjLineFracture");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjLineCrack* pFracture = static_cast<nmObjLineCrack*>(vecPlotObjs.at(i));
if(pFracture->getName() == sObjName) {
pFracture->setVisible(bIsVisible);
break;
}
}
}
/**
* @brief 设置所有区域的可见性
*/
void nmGuiPlot::setAllRegionsVisible(bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjRegion");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjRegion* pRegion = static_cast<nmObjRegion*>(vecPlotObjs.at(i));
pRegion->setVisible(bIsVisible);
}
}
/**
* @brief 设置单个区域的可见性
*/
void nmGuiPlot::setRegionVisible(QString sObjName, bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjRegion");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjRegion* pRegion = static_cast<nmObjRegion*>(vecPlotObjs.at(i));
if(pRegion->getName() == sObjName) {
pRegion->setVisible(bIsVisible);
break;
}
}
}
/**
* @brief 设置所有区域标记的可见性
*/
void nmGuiPlot::setAllRegionMarksVisible(bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjRegionMark");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjRegionMark* pRegionMark = static_cast<nmObjRegionMark*>(vecPlotObjs.at(i));
pRegionMark->setVisible(bIsVisible);
}
}
/**
* @brief 设置单个区域标记的可见性
*/
void nmGuiPlot::setRegionMarkVisible(QString sObjName, bool bIsVisible)
{
QVector<ZxObjBase*> vecPlotObjs = this->getObjsByTag("nObjRegionMark");
for(int i = 0; i < vecPlotObjs.count(); ++i) {
nmObjRegionMark* pRegionMark = static_cast<nmObjRegionMark*>(vecPlotObjs.at(i));
if(pRegionMark->getName() == sObjName) {
pRegionMark->setVisible(bIsVisible);
break;
}
}
}
void nmGuiPlot::finishMeasure()
{
nmGuiPlotCmdHelper* helper = dynamic_cast<nmGuiPlotCmdHelper*>(m_pCmdHelper);
if(helper != nullptr) {
helper->finishMeasure();
}
}
bool nmGuiPlot::setPlotsByDataManger(nmDataAnalyzeManager* pDataManager)
{
if(pDataManager == nullptr || m_pPlot == nullptr) {
return false;
}
// 本函数按DataManager完整重建Map重复调用也只能保留一套图元。
// 清理过程不删除业务数据,因此同一分析刷新和跨分析切换可使用同一路径。
deleteAllPlotObjs();
if(m_pGraphicBinder != nullptr) {
m_pGraphicBinder->updateDataMgr(pDataManager);
}
m_pDataManager = pDataManager;
nmDataAxis* pAxisData = pDataManager->getAxisData();
const bool bWaitingForInitialView =
pAxisData != nullptr && !pAxisData->isInitialViewFitted();
const bool bOldApplying = m_bApplyingAxisRange;
if(bWaitingForInitialView) {
// 图元创建过程可能发出轴范围信号,首次适配完成前统一按内部更新处理。
m_bApplyingAxisRange = true;
}
// 0.坐标轴
this->initAxisFromData(pDataManager);
// 1.边界
this->initBoundaryObjFromData(pDataManager);
// 2.井
this->initWellObjsFromData(pDataManager);
// 3.断层
this->initFaultObjsFromData(pDataManager);
// 4.裂缝
this->initFractureObjsFromData(pDataManager);
// 5.区域
this->initRegionObjsFromData(pDataManager);
// 6.区域标记
this->initRegionMarkObjsFromData(pDataManager);
m_bApplyingAxisRange = bOldApplying;
if(pAxisData != nullptr && !pAxisData->isInitialViewFitted()) {
// 等本轮布局和坐标轴内边距稳定后只初始化一次。
scheduleInitialAxisView();
}
return true;
}
void nmGuiPlot::removeWellPlotByData(nmDataWellBase* pData)
{
if(pData != nullptr) {
// 移除井图元
int objCount = m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = m_pPlot->getObjByIndex(i);
if(_isSame(obj->getName(), pData->getWellName())) {
// 删除图元
m_pPlot->removeObjByName(obj->getName());
break;
}
}
}
}
void nmGuiPlot::removeAllWellPlot()
{
// 移除所有井图元
int objCount = m_pPlot->getObjCount();
for(int i = 0; i < objCount; i++) {
ZxObjBase* obj = m_pPlot->getObjByIndex(i);
if(_isSame("nObjPointWell", obj->getTagName())) {
// 删除井图元
m_pPlot->removeObjByName(obj->getName());
}
}
}