#ifndef NMWXWELLBORETRAJECTORYDISPLAY_H #define NMWXWELLBORETRAJECTORYDISPLAY_H #include #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 #include #include #include #include #include // 基础图元类 // 井筒点 (用于垂直井的俯视图,或井筒在纵截面的中心点) 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 m_handles; // 存储八个手柄的指针 qreal m_handleSize; // 手柄的大小(像素) HandleType m_eCurrentHandle; // 当前正在拖动的手柄类型 QPointF m_lastMouseScenePos; // 记录鼠标在场景坐标系中的位置,用于拖动计算 // 储层边界信息,用于限制裂缝的高度 qreal m_minReservoirTop; qreal m_maxReservoirBottom; }; #include #include "nmDataLayer.h" #include // 绘制具有无限水平宽度感的储层组 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& layers); // 获取上下深度 qreal getMinLayerTop(); qreal getMaxLayerBottom(); protected: QList m_internalLayers; // 存储内部的层数据 // 缓存层数据的最小顶深度和最大底深度 // qreal m_minLayerTop; // qreal m_maxLayerBottom; }; #include #include // 抽象基类,用于组合和管理特定视图下的井筒基本图元 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 m_listPoints; // 井筒点 QList m_listLines; // 井筒线 QList m_listPerforations; // 射孔段 QList m_listLineFractures; // 裂缝[线] QList 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>& 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 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 m_listFractures; // 多段压裂水平井裂缝列表 bool m_bEditMode; // 当前编辑状态 QVector 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 m_listCrossSectionFractures; // 裂缝图元列表 nmWellboreLineGraphicsItem* m_pWellboreLine; // 井筒线图元指针 nmReservoirGraphicsItems* m_pReservoirsItem; // 储层图元指针,用于获取最大底部深度 bool m_bEditMode; // 编辑模式标志 }; #include // QGraphicsView 是显示 QGraphicsScene 的部件 #include // QGraphicsScene 管理图形项 #include // 用于管理 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>& 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>& 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