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/Include/nmNum/nmSubWxs/nmWxWellboreTrajectoryDispl...

1020 lines
41 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.

#ifndef NMWXWELLBORETRAJECTORYDISPLAY_H
#define NMWXWELLBORETRAJECTORYDISPLAY_H
#include <QWidget>
#include "nmSubWxs_global.h"
#include "nmDefines.h"
class nmDataWellBase;
class QButtonGroup;
class QRadioButton;
class QToolBar;
class QStackedWidget;
class QGroupBox;
class QLabel;
class QMouseEvent;
class QWheelEvent;
#include <QGraphicsRectItem>
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
#include <QGraphicsPathItem>
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
// 基础图元类
// 井筒点 (用于垂直井的俯视图,或井筒在纵截面的中心点)
class nmWellborePointGraphicsItem : public QObject, public QGraphicsEllipseItem
{
Q_OBJECT
public:
explicit nmWellborePointGraphicsItem(QGraphicsItem *parent = nullptr);
// 可添加设置特定属性的方法,如颜色、大小等
void setStyle(const QPen& pen, const QBrush& brush);
signals:
// 井点中心位置变化信号,移动时实时发出
void sigPositionChanging(const QPointF& newCenterScenePos);
// 拖动结束信号 (仅在鼠标释放时发出)
void sigDragFinished(const QPointF& finalCenterScenePos);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
bool m_bIsDragging; // 标记是否正在拖动
QPointF m_dragStartPos; // 记录鼠标按下时的场景坐标
QPointF m_originalPos; // 记录拖动开始时图元的原始位置(左上角)
};
// 井筒线 (用于水平井的俯视图,或纵截面视图的井筒段)
class nmWellboreLineGraphicsItem : public QObject, public QGraphicsLineItem
{
Q_OBJECT
public:
explicit nmWellboreLineGraphicsItem(QGraphicsItem *parent = nullptr);
// 可添加设置特定属性的方法
void setStyle(const QPen& pen);
};
enum PerforationHandleType {
StartHandle, // 起点手柄类型
EndHandle // 终点手柄类型
};
// 射孔手柄类
class nmPerforationHandleItem : public QGraphicsRectItem
{
public:
// 构造函数:需要手柄类型和父级图形项
explicit nmPerforationHandleItem(PerforationHandleType type, QGraphicsItem *parent = nullptr);
protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
QRectF boundingRect() const override;
private:
PerforationHandleType m_handleType; // 存储手柄的类型
};
// 定义射孔段的当前交互模式
enum PerforationInteractionMode {
Normal, // 正常模式,无特殊交互(鼠标未按下或未拖动)
ResizeStart, // 调整起点MD (用户正在拖动射孔的起点手柄)
ResizeEnd, // 调整终点MD (用户正在拖动射孔的终点手柄)
MoveItem // 移动整个射孔项 (用户正在拖动射孔本体以整体移动)
};
class nmDataPerforation;
// 射孔
class nmPerforationGraphicsItem : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
explicit nmPerforationGraphicsItem(nmDataPerforation *pPerData, NM_WELL_MODEL wellType, double wellboreStartAbsoluteMd, double totalWellboreMdLength, QGraphicsItem *parent = nullptr);
~nmPerforationGraphicsItem();
// 启用/禁用编辑模式:在编辑模式下,手柄可见且可拖动
void setEditMode(bool enable);
// 更新图形项(包括射孔本体和手柄)的位置和大小。
// 这个函数是响应数据模型变化的最终更新,它会读取 Model 的真实数据进行渲染。
void updateGraphics();
// 获取关联的射孔段数据
nmDataPerforation* getPerforationData();
// 当井筒视觉或MD信息变化时更新射孔段内部存储的井筒相关数据
void updateWellboreVisuals(const QPointF& wellboreStartScene, const QPointF& wellboreEndScene, double wellboreStartAbsoluteMd, double totalWellboreMdLength);
// 根据裂缝临时位置进行裁剪,实时预览
void updateGraphicsForPreview(qreal fractureTopMD, qreal fractureBottomMD);
// 根据MD值获取井筒上的场景点
QPointF getScenePointFromMd(double md) const;
// 根据场景中的点,找到井筒上最近的点,并返回对应的 MD 值
double getMdFromScenePointOnWellbore(const QPointF& scenePoint) const;
// 获取被裁剪后的MD范围
double getCroppedMdStart();
double getCroppedMdEnd();
// 用于在井身拖动时,根据新井身长度进行实时预览,目前是多段压裂水平井需要
void updateVisualsForWellboreDrag(const QPointF& wellboreStartScene, const QPointF& wellboreEndScene,
double wellboreStartAbsoluteMd, double originalWellboreLength,
double newWellboreLength);
signals:
// 射孔段拖动结束后请求更新数据模型MD位置
void sigRequestPerforationMdUpdate(nmDataPerforation* pPerforationData, double proposedMdStart, double proposedMdEnd);
protected:
// 重写包围盒计算,需要包含射孔本体和手柄的区域,确保全部被绘制和点击检测到
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QRectF boundingRect() const override;
// 重写鼠标事件,用于处理用户交互(按下、移动、释放)
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
nmDataPerforation* m_pPerforationData; // 关联的射孔段数据
bool m_bEditable; // 是否处于编辑状态
PerforationInteractionMode m_eCurrentInteractionMode; // 当前交互模式
QPointF m_lastMouseScenePos; // 鼠标按下时的场景坐标 (用于拖动计算)
double m_initialMdStart; // 拖动开始时的射孔起点MD
double m_initialMdEnd; // 拖动开始时的射孔终点MD
bool m_isDragging; // 标志:当前是否处于拖动操作中 (鼠标按下并移动)
double m_tempDragMdStart; // 拖动过程中视图临时显示的起点MD (只用于局部渲染)
double m_tempDragMdEnd; // 拖动过程中视图临时显示的终点MD (只用于局部渲染)
// 射孔和手柄的样式和尺寸
double m_dPerWidth; // 射孔的视觉宽度
QPen m_handlePen; // 手柄的边框画笔
QBrush m_handleBrush; // 手柄的填充画刷
qreal m_handleSize; // 手柄的尺寸 (正方形的边长)
QPointF m_wellboreStartScenePoint; // 井筒在场景中的起始点
QPointF m_wellboreEndScenePoint; // 井筒在场景中的结束点
double m_wellboreStartAbsoluteMd; // 井筒的绝对MD起始值
double m_totalWellboreMdLength; // 井筒的总MD长度
NM_WELL_MODEL m_eWellType; // 井筒类型
QLineF m_wellboreVisualLine; // 存储井筒的视觉线段
// 射孔手柄 QGraphicsRectItem 成员
nmPerforationHandleItem* m_pStartHandle; // 指向起点手柄的指针
nmPerforationHandleItem* m_pEndHandle; // 指向终点手柄的指针
// 存储被裁剪后的 MD 范围
double m_dCroppedMdStart;
double m_dCroppedMdEnd;
// 私有辅助函数:更新射孔本体和手柄的几何形状
// 这个函数现在必须接受两个MD值参数用于绘制
void updatePerforationAndHandleGeometry(double mdStartToRender, double mdEndToRender);
};
// 裂缝手柄类[线]
class nmFractureLineHandleItem : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
explicit nmFractureLineHandleItem(QGraphicsItem *parent = nullptr);
// 信号:通知父项或控制器手柄位置发生变化
// 参数可以包括手柄自身指针和新的局部位置
signals:
void handlePositionChanged(nmFractureLineHandleItem* handle, QPointF newPos, bool IsDragging);
protected:
// 重写鼠标事件
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QRectF boundingRect() const override;
private:
QPointF m_lastMousePos; // 记录上次鼠标位置,用于计算移动增量
bool m_bIsDragging; // 标志:是否正在拖动
};
// 针对多段压裂水平井的多段裂缝图元
class nmHorizontalFractureGraphicsItem : public QObject, public QGraphicsLineItem
{
Q_OBJECT
signals:
// 信号通知父项nmHorizontalFracturedWellTopViewItem裂缝半长发生变化
// newHalfLength: 新的裂缝半长
// isDragging: 是否正在拖动
// fractureIndex: 当前是哪条裂缝(在父列表中)的索引,用于数据模型更新
void fractureHalfLengthChanged(double newHalfLength, bool isDragging, int fractureIndex);
public:
explicit nmHorizontalFractureGraphicsItem(int index, QGraphicsItem *parent = nullptr);
void setStyle(const QPen& pen);
// 更新裂缝线和手柄的位置
void updateFractureLineAndHandles(const QPointF& p1, const QPointF& p2);
// 设置井筒的场景坐标信息和方向向量
void setWellboreInfo(const QPointF& wellboreStartScene, const QPointF& wellboreEndScene);
// 设置编辑模式,控制手柄可见性
void setEditMode(bool enable);
// 获取当前裂缝在父类列表中的索引
int getFractureIndex() const { return m_fractureIndex; }
private slots:
// 接收手柄的信号
void onHandlePositionChanged(nmFractureLineHandleItem* handle, QPointF newHandlePosInParent, bool isDragging);
private:
nmFractureLineHandleItem* m_pHandle1;
nmFractureLineHandleItem* m_pHandle2;
bool m_bEditMode;
int m_fractureIndex; // 当前裂缝在 nmHorizontalFracturedWellTopViewItem 中的索引
QPointF m_wellboreStartScene; // 井筒起始点 (场景坐标)
QPointF m_wellboreEndScene; // 井筒结束点 (场景坐标)
QPointF m_wellboreDirection; // 井筒方向向量 (归一化,场景坐标)
};
class nmDataVerticalFracturedWell;
// 裂缝 (通常是直线)
class nmFractureLineGraphicsItem : public QObject, public QGraphicsLineItem
{
Q_OBJECT
public:
explicit nmFractureLineGraphicsItem(QGraphicsItem *parent = nullptr);
// 可添加设置特定属性的方法
void setStyle(const QPen& pen);
// 设置为编辑模式
void setEditMode(bool enable);
signals:
// 拖拽结束后,发送裂缝几何位置
void sigFractureGeometryChanged(double newHalfLength, double newAngle);
private slots: // 用于接收手柄的信号
void onHandlePositionChanged(nmFractureLineHandleItem* handle, QPointF newPos, bool isDragging);
private:
// 创建矩形手柄
void createHandles();
// 更新手柄位置
void updateHandlesPosition();
// 更新裂缝位置
void updateFractureFromHandle(nmFractureLineHandleItem* draggedHandle, const QPointF& newHandleScenePos, bool isDragging);
private:
bool m_bEditMode; // 表示当前是否处于编辑模式
// 裂缝手柄
nmFractureLineHandleItem* m_pHandle1;
nmFractureLineHandleItem* m_pHandle2;
};
// 枚举手柄的类型,用于父项判断如何缩放
enum HandleType {
NoHandle, // 没有拖动手柄
TopLeftHandle, // 左上角手柄
TopMiddleHandle, // 顶边中点手柄
TopRightHandle, // 右上角手柄
MiddleLeftHandle, // 左边中点手柄
MiddleRightHandle, // 右边中点手柄
BottomLeftHandle, // 左下角手柄
BottomMiddleHandle, // 底边中点手柄
BottomRightHandle // 右下角手柄
};
// nmFractureHandleItem 类继承自 QObject 和 QGraphicsRectItem
// 代表裂缝矩形上的一个可拖动的手柄
class nmFractureRectHandleItem : public QObject, public QGraphicsRectItem {
Q_OBJECT
public:
// 构造函数,需要手柄类型和父项
explicit nmFractureRectHandleItem(HandleType type, QGraphicsItem *parent = nullptr);
~nmFractureRectHandleItem();
// 获取手柄类型
HandleType getHandleType();
signals:
// 信号:手柄开始拖动时发出
void handlePressed(HandleType type, QPointF scenePos);
// 信号:手柄正在拖动时发出
void handleMoved(HandleType type, QPointF scenePos);
// 信号:手柄释放时发出
void handleReleased(HandleType type, QPointF scenePos);
protected:
// 重写鼠标事件处理函数,用于捕获手柄的交互
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
QRectF boundingRect() const override;
private:
HandleType m_eHandleType; // 当前手柄的类型
QPointF m_lastMouseScenePos; // 记录鼠标在场景坐标系中的位置,用于计算位移
};
// 绘制截面下的裂缝[矩形]
class nmFractureRectGraphicsItem : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit nmFractureRectGraphicsItem(nmDataVerticalFracturedWell* pDataWell, QGraphicsItem *parent = nullptr);
~nmFractureRectGraphicsItem();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
// 设置编辑模式的公共接口
void setEditMode(bool bEdit);
signals:
// 携带裂缝新的顶部和底部MD
void sigRequestFractureRectUpdate(qreal newTopMD, qreal newBottomMD);
// 拖动过程中实时发送
void sigFractureGeometryChanged(qreal fractureTopMD, qreal fractureBottomMD);
private slots:
// 槽函数响应手柄nmFractureHandleItem发出的信号
void onHandlePressed(HandleType type, QPointF scenePos);
void onHandleMoved(HandleType type, QPointF scenePos);
void onHandleReleased(HandleType type, QPointF scenePos);
private:
void updateFractureGeometry(); // 根据数据更新裂缝矩形的位置和大小
void updateHandlePositions(); // 更新所有手柄的位置,使其与裂缝矩形对齐
void createHandles(); // 创建并初始化八个手柄子项
void destroyHandles(); // 销毁所有手柄子项
private:
nmDataVerticalFracturedWell* m_pDataWell; // 指向裂缝数据模型的指针
bool m_bEditMode; // 是否处于编辑模式
QRectF m_fractureRect; // 裂缝矩形的当前几何信息(本地坐标系)
// 用于手柄的成员变量
QVector<nmFractureRectHandleItem *> m_handles; // 存储八个手柄的指针
qreal m_handleSize; // 手柄的大小(像素)
HandleType m_eCurrentHandle; // 当前正在拖动的手柄类型
QPointF m_lastMouseScenePos; // 记录鼠标在场景坐标系中的位置,用于拖动计算
// 储层边界信息,用于限制裂缝的高度
qreal m_minReservoirTop;
qreal m_maxReservoirBottom;
};
#include <QList>
#include "nmDataLayer.h"
#include <QVector>
// 绘制具有无限水平宽度感的储层组
class nmReservoirGraphicsItems : public QObject, public QGraphicsItem
{
Q_OBJECT
public:
explicit nmReservoirGraphicsItems(QGraphicsItem *parent = nullptr);
~nmReservoirGraphicsItems();
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); // Qt 4 兼容的 nullptr 替代
void setReservoirLayers(const QVector<nmDataLayer*>& layers);
// 获取上下深度
qreal getMinLayerTop();
qreal getMaxLayerBottom();
protected:
QList<nmDataLayer*> m_internalLayers; // 存储内部的层数据
// 缓存层数据的最小顶深度和最大底深度
// qreal m_minLayerTop;
// qreal m_maxLayerBottom;
};
#include <QGraphicsItemGroup>
#include <QGraphicsScene>
// 抽象基类,用于组合和管理特定视图下的井筒基本图元
class nmAbstractWellboreVisual : public QObject, public QGraphicsItemGroup
{
Q_OBJECT
public:
explicit nmAbstractWellboreVisual(QGraphicsItem *parent = nullptr);
virtual ~nmAbstractWellboreVisual();
// 核心虚函数:根据几何数据来创建和更新内部的基本图形项
virtual void updateGeometryVisuals(nmDataWellBase *pDataWell) = 0;
// 获取当前渲染的井数据实例
nmDataWellBase* getWellData();
// 删除指定的射孔图形项并从内部列表中移除
void removePerforationVisual(nmPerforationGraphicsItem* itemToRemove);
// 清空所有射孔段图元
void clearAllPerforationItems();
protected:
// 清除所有子项的通用方法
void clearAllChildItems();
// 用于管理和追踪创建的基本图元,以便在更新时可以清除旧的
QList<nmWellborePointGraphicsItem*> m_listPoints; // 井筒点
QList<nmWellboreLineGraphicsItem*> m_listLines; // 井筒线
QList<nmPerforationGraphicsItem*> m_listPerforations; // 射孔段
QList<nmFractureLineGraphicsItem*> m_listLineFractures; // 裂缝[线]
QList<nmFractureRectGraphicsItem*> m_listRectFractures; // 裂缝[矩形]
// 添加基础图元
void addPoint(nmWellborePointGraphicsItem* item);
void addLine(nmWellboreLineGraphicsItem* item);
void addPerforation(nmPerforationGraphicsItem* item);
void addFractureLine(nmFractureLineGraphicsItem* item);
void addFractureRect(nmFractureRectGraphicsItem* item);
// 指向数据模型的指针不拥有其内存因此使用const
nmDataWellBase *m_pDataWell;
};
// 垂直井 - 俯视图
class nmVerticalWellTopViewItem : public nmAbstractWellboreVisual
{
Q_OBJECT
public:
explicit nmVerticalWellTopViewItem(QGraphicsItem *parent = nullptr);
// 根据几何数据更新图元的可视化表示
void updateGeometryVisuals(nmDataWellBase *pDataWell) override;
void setEditMode(bool enabled); // 编辑模式控制
QPointF getWellPointPosition() const; // 获取当前绿点位置
signals:
// 井点被拖动结束后的信号
void sigWellborePointDragFinished(const QPointF& newScenePos);
private slots:
// 接收井点位置变化的信号,更新虚线连接
void slotUpdateDashLine(const QPointF& newPos);
// 接收井点拖动完成的信号,并转发给控制器
void slotWellborePointDragFinished(const QPointF& finalCenterScenePos);
private:
nmWellborePointGraphicsItem* m_pWellPoint; // 绿色可移动点
nmWellborePointGraphicsItem* m_pOriginalPoint; // 红色固定点(编辑时创建)
QGraphicsLineItem* m_pDashLine; // 虚线连接
};
// 垂直井 - 纵截面视图 (组合图元)
class nmVerticalWellCrossSectionItem : public nmAbstractWellboreVisual
{
Q_OBJECT
public:
explicit nmVerticalWellCrossSectionItem(QGraphicsItem *parent = nullptr);
// 根据几何数据更新图元的可视化表示
void updateGeometryVisuals(nmDataWellBase *pDataWell) override;
// 射孔段编辑状态控制
void setPerforationEditMode(bool enabled);
signals:
// 射孔被拖动结束后的信号,转发给主视图
void sigPerforationDragFinished(nmDataPerforation* pPerforationData, double proposedMdStart, double proposedMdEnd);
};
// 垂直裂缝井 - 俯视图
class nmVerticalFracturedWellTopViewItem : public nmAbstractWellboreVisual
{
Q_OBJECT
public:
explicit nmVerticalFracturedWellTopViewItem(QGraphicsItem *parent = nullptr);
// 根据几何数据更新图元的可视化表示
void updateGeometryVisuals(nmDataWellBase *pDataWell) override;
void setEditMode(bool enabled); // 编辑模式控制
signals:
// 拖拽结束后,发送裂缝几何位置
void sigFracturePosChanged(double newHalfLength, double newAngle);
private:
nmFractureLineGraphicsItem* m_pFracture; // 裂缝
};
// 垂直裂缝井 - 纵截面视图 (组合图元)
class nmVerticalFracturedWellCrossSectionItem : public nmAbstractWellboreVisual
{
Q_OBJECT
public:
explicit nmVerticalFracturedWellCrossSectionItem(QGraphicsItem *parent = nullptr);
// 根据几何数据更新图元的可视化表示
void updateGeometryVisuals(nmDataWellBase *pDataWell) override;
// 设置裂缝编辑模式
void setFractureEditMode(bool enabled);
// 射孔段编辑状态控制
void setPerforationEditMode(bool enabled);
// 获取矩形裂缝MD位置
QRectF getFractureMD();
signals:
// 射孔被拖动结束后的信号,转发给主视图
void sigPerforationDragFinished(nmDataPerforation* pPerforationData, double proposedMdStart, double proposedMdEnd);
// 将裂缝的垂直范围变化请求转发给控制器
void sigRequestFractureRectUpdate(qreal fractureTopMD, qreal fractureBottomMD);
// 拖动裂缝结束后,将更新后的射孔数据传递给控制器
// QMap<数据指针, <起始MD, 结束MD>>
void sigFractureDragFinished(const QMap<nmDataPerforation*, QPair<double, double>>& updatedPerforations);
public slots:
// 响应裂缝垂直范围变化的槽函数,用于动态更新和约束射孔段
void slotFractureConstraintChanged(qreal fractureTopMD, qreal fractureBottomMD);
// 拖动裂缝结束后,调用此槽函数收集数据并发出信号
void slotFractureDragFinished(qreal fractureTopMD, qreal fractureBottomMD);
private:
// 增量更新射孔图元显示
void updatePerforationChildGraphics();
private:
nmFractureRectGraphicsItem* m_pRectFracture;
// 存储 nmDataPerforation 对象与 nmPerforationGraphicsItem 的映射
QMap<nmDataPerforation*, nmPerforationGraphicsItem*> m_mapPerforationItem;
};
// 井筒末端拖动手柄
class nmWellboreEndHandleGraphicsItem : public QObject, public QGraphicsRectItem
{
Q_OBJECT
signals:
// 信号:通知父项或其他控制器手柄在场景中的新位置
void handlePositionChanged(QPointF newScenePos, bool isDragging);
public:
explicit nmWellboreEndHandleGraphicsItem(QGraphicsItem *parent = nullptr);
protected:
// 重写鼠标事件以实现拖动功能
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
private:
QPointF m_lastMouseScenePos; // 记录上次鼠标位置,用于计算移动增量
};
class nmDataHorizontalFracturedWell;
// 多段压裂水平井 - 俯视图
class nmHorizontalFracturedWellTopViewItem : public nmAbstractWellboreVisual
{
Q_OBJECT
public:
explicit nmHorizontalFracturedWellTopViewItem(QGraphicsItem *parent = nullptr);
// 根据几何数据更新图元的可视化表示
void updateGeometryVisuals(nmDataWellBase *pDataWell) override;
void setEditMode(bool enabled); // 编辑模式控制
// 射孔段编辑状态控制
void setPerforationEditMode(bool enabled);
// 获取井筒线
QLineF getWellboreLine();
signals:
// 射孔被拖动结束后的信号,转发给主视图
void sigPerforationDragFinished(nmDataPerforation* pPerforationData, double proposedMdStart, double proposedMdEnd);
// 将裂缝半长变化转发给控制器
void sigFractureHalfLengthChanged(double newHalfLength);
// 井身终点位置发生变化,转发给控制器
void sigWellboreDragFinished(QPointF newScenePos);
private slots:
// 接收井筒末端拖动手柄的位置变化信号
void onEndHandleMoved(QPointF newScenePos, bool isDragging);
// 接收单个裂缝图元发出的半长变化信号
void onSingleFractureHalfLengthChanged(double newHalfLength, bool isDragging, int fractureIndex);
private:
nmWellboreLineGraphicsItem* m_pWellboreLine; // 用于表示井筒的线段
nmWellboreEndHandleGraphicsItem* m_pEndHandle; // 用于表示井筒末端的拖动手柄
QList<nmHorizontalFractureGraphicsItem*> m_listFractures; // 多段压裂水平井裂缝列表
bool m_bEditMode; // 当前编辑状态
QVector<double> m_vecFractureMds; // 缓存裂缝的MD值
};
// 多段压裂水平井裂缝纵截面图元
class nmCrossSectionFractureItem : public QObject, public QGraphicsLineItem
{
Q_OBJECT
public:
explicit nmCrossSectionFractureItem(int fractureIndex, QGraphicsItem *parent = nullptr);
~nmCrossSectionFractureItem();
// 更新裂缝视觉:新增 min/max 储层深度作为约束参数
void updateFractureVisuals(double fractureXPosition, double midPointY, double fractureHeight,
double minReservoirDepth, double maxReservoirDepth);
// 设置编辑模式,控制把手可见性及拖动能力,同时禁用不必要的视觉效果
void setEditMode(bool enable);
signals:
// 同时传递裂缝高度和中点Y坐标
void fractureGeometryChanged(double newHeight, double newMidPointY, bool isDragging, int fractureIndex);
protected:
// 覆盖鼠标事件以启用图元整体拖动
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
// 如果需要更精细控制 ItemIsSelectable 后的选中框,可以重写 paint
// void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
private slots:
// 槽函数:响应把手位置变化(用于调整高度)
void onHandlePositionChanged(nmFractureLineHandleItem* handle, QPointF newHandlePosInParent, bool isDragging);
private:
nmFractureLineHandleItem* m_pTopHandle; // 垂直裂缝的顶部把手
nmFractureLineHandleItem* m_pBottomHandle; // 垂直裂缝的底部把手
bool m_bEditMode; // 当前编辑模式状态
int m_fractureIndex; // 裂缝的索引,用于识别
// 存储当前裂缝的几何信息,方便内部计算和信号发出
double m_currentFractureXPosition; // 裂缝的X坐标 (MD)
double m_currentFractureMidPointY; // 裂缝中心点的Y坐标 (深度)
double m_currentFractureHeight; // 裂缝的总高度
// 储层深度限制
double m_minReservoirDepth;
double m_maxReservoirDepth;
QPointF m_lastMousePos; // 存储上次鼠标位置,用于拖动计算
bool m_isDraggingBody; // 标志位,指示是否正在拖动裂缝本体
};
// 多段压裂水平井 - 纵截面视图 (组合图元)
class nmHorizontalFracturedWellCrossSectionItem : public nmAbstractWellboreVisual
{
Q_OBJECT
public:
explicit nmHorizontalFracturedWellCrossSectionItem(QGraphicsItem *parent = nullptr);
// 根据几何数据更新图元的可视化表示
void updateGeometryVisuals(nmDataWellBase *pDataWell) override;
// 设置编辑模式
void setEditMode(bool enabled);
signals:
// 转发裂缝的高度和中点高度给控制器
void sigFractureGeometryChanged(double newHeight, double newMidPointY);
private slots:
// 接收更新后的裂缝几何位置
void onSingleFractureGeometryChanged(double newHeight, double newMidPointY, bool isDragging, int fractureIndex);
private:
nmDataHorizontalFracturedWell *m_pHFWellData; // 指向水平压裂井数据的特定指针
QList<nmCrossSectionFractureItem*> m_listCrossSectionFractures; // 裂缝图元列表
nmWellboreLineGraphicsItem* m_pWellboreLine; // 井筒线图元指针
nmReservoirGraphicsItems* m_pReservoirsItem; // 储层图元指针,用于获取最大底部深度
bool m_bEditMode; // 编辑模式标志
};
#include <QGraphicsView> // QGraphicsView 是显示 QGraphicsScene 的部件
#include <QGraphicsScene> // QGraphicsScene 管理图形项
#include <QSharedPointer> // 用于管理 WellboreGeometry 的生命周期
class nmDefine;
// 抽象井筒视图基类
// 提供了所有井筒视图的通用功能和接口
class nmAbstractWellboreView : public QGraphicsView
{
Q_OBJECT // 启用Qt的元对象系统
public:
explicit nmAbstractWellboreView(QWidget *parent = nullptr); // 构造函数
virtual ~nmAbstractWellboreView(); // 虚析构函数
// 更新视图的核心方法,根据传入的几何数据模型来更新显示
// 纯虚函数,由子类实现具体视图的更新逻辑
virtual void updateView(nmDataWellBase* geometry) = 0;
// 缩放视图
void zoomIn();
void zoomOut();
// 重置视图变换,纯虚函数,需要子类自己实现
virtual void resetViewTransform() = 0;
signals:
// 添加射孔信号,发送给主视图,发送信号时需要根据井类型+视角共同决定传入哪些参数
void sigRequestAddPerforation(const QPointF& scenePos,
double fractureTopMd = -1.0,
double fractureBottomMd = -1.0,
const QLineF& wellboreVisualLine = QLineF());
// 请求控制器删除射孔的信号
// 参数是待删除射孔的数据指针
void sigRequestDeletePerforation(nmDataPerforation* pPerforationData);
// 当鼠标在视图上移动时发出的信号,提供转换后的场景坐标
void mouseCoordinatesChanged(double x, double y);
void mouseEnteredView(); // 鼠标进入视图区域时发射
void mouseLeftView(); // 鼠标离开视图区域时发射
protected:
// 重写鼠标移动事件以发出坐标信号
void mouseMoveEvent(QMouseEvent *event) override;
// 重写鼠标进入/离开事件以控制鼠标坐标标签
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
// 重写滚轮事件以实现缩放
void wheelEvent(QWheelEvent *event) override;
protected:
QGraphicsScene *m_scene; // 视图所关联的图形场景
nmAbstractWellboreVisual *m_currentWellboreVisual; // 当前场景中显示的井筒组合图元
// 设置场景(在构造函数中调用)
void setupScene();
// 清理旧的井筒图元并准备场景以显示新的图元
void clearAndPrepareScene();
// 工厂方法:根据井类型创建特定视图下的组合图元实例
// 纯虚函数,由子类实现
virtual nmAbstractWellboreVisual* createWellboreVisual(NM_WELL_MODEL type) = 0;
};
// === 内部定义的井筒轨迹俯视图类 ===
class nmWxWellboreTopView : public nmAbstractWellboreView
{
Q_OBJECT
public:
explicit nmWxWellboreTopView(QWidget *parent = nullptr);
// 重写基类的更新视图方法,实现俯视图的更新逻辑
void updateView(nmDataWellBase* geometry) override;
// 传递编辑状态
void setEditMode(bool enabled);
// 传递射孔段编辑状态
void setPerForationEditMode(bool enabled);
// 设置添加射孔段模式
void setAddPerforationMode(bool enable);
// 设置删除模式
void setPerforationDeleteMode(bool enabled);
// 重置视图变换
void resetViewTransform() override;
signals:
// 井筒点在俯视图中被拖拽 (只在拖动结束后发射,转发给主视图)
void sigWellborePointMovedInTopView(const QPointF& newScenePos);
// 射孔在俯视图中被拖拽 (只在拖动结束后发射,转发给控制器)
void sigPerforationDragInTopView(nmDataPerforation* pPerforationData, double proposedMdStart, double proposedMdEnd);
// 拖拽结束后,发送裂缝几何位置
void sigFracturePosChangedInTopView(double newHalfLength, double newAngle);
// 将裂缝半长变化转发给控制器
void sigFractureHalfLengthChanged(double newHalfLength);
// 井身终点位置发生变化,转发给控制器
void sigWellboreDragFinished(QPointF newScenePos);
protected:
// 重写工厂方法,根据井类型创建适合俯视图的组合图元
nmAbstractWellboreVisual* createWellboreVisual(NM_WELL_MODEL type) override;
void mousePressEvent(QMouseEvent *event) override; // 重写鼠标按下事件
private:
bool m_bIsInAddPerforationMode; // 视图内部的添加模式状态
bool m_bIsInDeletePerforationMode; // 删除射孔模式标志
};
// === 内部定义的井筒轨迹纵截面视图类 ===
class nmWxWellboreCrossSectionView : public nmAbstractWellboreView
{
Q_OBJECT
public:
explicit nmWxWellboreCrossSectionView(QWidget *parent = nullptr);
// 重写基类的更新视图方法,实现纵截面视图的更新逻辑
void updateView(nmDataWellBase* geometry) override;
// 传递射孔段编辑状态
void setPerForationEditMode(bool enabled);
// 设置添加射孔段模式
void setAddPerforationMode(bool enable);
// 设置删除模式
void setPerforationDeleteMode(bool enabled);
// 重置视图变换
void resetViewTransform() override;
// 设置裂缝编辑模式
void setFractureEditMode(bool enabled);
signals:
// 射孔在截面图中被拖拽 (只在拖动结束后发射,转发给控制器)
void sigPerforationDragInCrossView(nmDataPerforation* pPerforationData, double proposedMdStart, double proposedMdEnd);
// 将裂缝的垂直范围变化请求转发给控制器
void sigRequestFractureRectUpdate(qreal fractureTopMD, qreal fractureBottomMD);
// 拖动裂缝结束后,将更新后的射孔数据传递给控制器
// QMap<数据指针, <起始MD, 结束MD>>
void sigFractureDragFinished(const QMap<nmDataPerforation*, QPair<double, double>>& updatedPerforations);
// 转发裂缝的高度和中点高度给控制器(多段压裂水平井)
void sigFractureGeometryChanged(double newHeight, double newMidPointY);
protected:
// 重写工厂方法,根据井类型创建适合纵截面视图的组合图元
nmAbstractWellboreVisual* createWellboreVisual(NM_WELL_MODEL type) override;
void mousePressEvent(QMouseEvent *event) override; // 重写鼠标按下事件
void resizeEvent(QResizeEvent *event) override;
private:
bool m_bIsInAddPerforationMode; // 视图内部的添加模式状态
bool m_bIsInDeletePerforationMode; // 删除射孔模式标志
bool m_isInitialFitDone; // 用于确保初始缩放只执行一次
};
// === 内部定义的井筒轨迹3D视图类 ===
class nmWxWellbore3DView : public QWidget
{
Q_OBJECT
public:
explicit nmWxWellbore3DView(QWidget *parent = nullptr);
// 这里可以添加3D View特有的方法和成员
};
// 井筒轨迹显示视图
class NM_SUB_WXS_EXPORT nmWxWellboreTrajectoryDisplay : public QWidget
{
Q_OBJECT
public:
explicit nmWxWellboreTrajectoryDisplay(QWidget *parent = nullptr);
~nmWxWellboreTrajectoryDisplay();
// 设置当前要显示的井数据
void setCurrentWellboreData(nmDataWellBase* pWellData);
// 对当前可见视图设置模式和更新UI
void setEditWellMode(bool enabled); // 用于井筒轨迹编辑模式
void setPerforationEditMode(bool enabled); // 射孔编辑模式
void setAddPerforationMode(bool enabled); // 添加射孔模式
void setDeletePerforationMode(bool enabled); // 删除射孔模式
void setSnapPerforationMode(bool enabled); // 对齐/吸附模式
signals:
// 由视图发出的信号,通知控制器用户请求了某个操作
// 控制器会根据当前状态决定是否激活该模式,并管理模式的互斥性
void requestedEditWellMode(int nCurrentViewId); // 请求编辑井筒/裂缝模式
void requestedEditPerforationsMode(int nCurrentViewId); // 请求编辑射孔模式
void requestedNewPerforationMode(int nCurrentViewId); // 请求添加射孔模式
void requestedDeletePerforationMode(int nCurrentViewId); // 请求删除射孔模式
void requestedSnapPerforationMode(int nCurrentViewId); // 请求吸附射孔模式
// 清理当前视图状态
void sigClearViewStates();
// 通知控制器当前视图已切换
void currentViewChanged(int newViewId);
// 井筒点移动信号 (从俯视图转发而来,发送给控制器)
void sigWellboreTrajectoryPointMoved(const QPointF& newScenePos);
// 射孔段拖动完成信号 (从截面图转发而来,发送给控制器)
void sigPerforationDragFinished(nmDataPerforation* pPerforationData, double proposedMdStart, double proposedMdEnd);
// 在添加射孔模式下,将点击的场景坐标发送给控制器
void sigTryAddNewPerforation(const QPointF& scenePos,
double fractureTopMd = -1.0,
double fractureBottomMd = -1.0,
const QLineF& wellboreVisualLine = QLineF());
// 将待删除的射孔数据发送给控制器
void sigTryDeletePerforation(nmDataPerforation* pPerforationData);
// 拖拽结束后,发送裂缝几何位置
void sigFractureGeometryDragFinished(double newHalfLength, double newAngle);
// 将裂缝的垂直范围变化请求转发给控制器
void sigRequestFractureRectUpdate(qreal fractureTopMD, qreal fractureBottomMD);
// 拖动裂缝结束后,将更新后的射孔数据传递给控制器
// QMap<数据指针, <起始MD, 结束MD>>
void sigFractureDragFinished(const QMap<nmDataPerforation*, QPair<double, double>>& updatedPerforations);
// 将裂缝半长变化转发给控制器
void sigFractureHalfLengthChanged(double newHalfLength);
// 井身终点位置发生变化,转发给控制器
void sigWellboreDragFinished(QPointF newScenePos);
// 转发裂缝的高度和中点高度给控制器(多段压裂水平井)
void sigFractureGeometryChanged(double newHeight, double newMidPointY);
private:
// 私有函数
void initUI();
void createViewOptions();
void createToolBar();
void createViewWidgets();
void connectSignalsSlots();
// 更新工具栏要显示什么
void updateToolBarForCurrentView(int viewIndex);
private slots:
void onViewRadioButtonToggled(int id);
void onZoomOutClicked(); // 缩小
void onHomeViewClicked(); // 复位/恢复
void onZoomInClicked(); // 放大
void onXYClicked(); // 坐标显示
void onEditWellClicked(); // 编辑井筒轨迹(发出请求)
void onLoadClicked(); // 加载
void onEditPerforationsClicked(); // 编辑射孔(发出请求)
void onNewPerforationClicked(); // 添加射孔段(发出请求)
void onDeletePerforationClicked(); // 删除射孔段(发出请求)
void onSnapPerforationClicked(); // 对齐/吸附(发出请求)
// 响应数据模型变化,更新所有视图
void onWellboreDataChanged();
// 接收来自 QGraphicsView 的鼠标坐标信号
void onMouseMovedOnPlot(double x, double y);
void onMouseEnteredAnyView(); // 新增槽函数:鼠标进入任一视图
void onMouseLeftAnyView(); // 新增槽函数:鼠标离开任一视图
public:
// 刷新纵截面视图
void updataCrossSectionView();
private:
// 成员变量
QGroupBox *m_pViewGroupBox;
QButtonGroup *m_pViewButtonGroup;
QRadioButton *m_pTopViewRadio;
QRadioButton *m_pCrossSectionRadio;
QRadioButton *m_p3DViewRadio;
QToolBar *m_pToolBar;
QAction *m_pZoomOutAction; // 缩小
QAction *m_pHomeViewAction; // 复位/恢复
QAction *m_pZoomInAction; // 放大
QAction *m_pXYAction; // 坐标显示
QAction *m_pEditWellAction; // 编辑井筒轨迹
QAction *m_pLoadAction; // 加载
QAction *m_pEditPerforationsAction; // 编辑射孔
QAction *m_pNewPerforationAction; // 添加射孔段
QAction *m_pDeletePerforationAction; // 删除射孔段
QAction *m_pSnapPerforationAction; // 对齐/吸附
QStackedWidget *m_pStackedWidget;
nmWxWellboreTopView *m_pTopViewWidget; // 顶部视图
nmWxWellboreCrossSectionView *m_pCrossSectionViewWidget; // 纵截面视图
nmWxWellbore3DView *m_p3DViewWidget; // 3D视图
// 当前渲染的井数据对象
nmDataWellBase* m_pDataWell;
// 用于显示鼠标坐标的标签
QLabel* m_pMouseCoordLabel;
// 是否启用该标签
bool m_bMouseLabelEnabled;
};
#endif // NMWXWELLBORETRAJECTORYDISPLAY_H