#ifndef NMWXCHARTWIDGET_H #define NMWXCHARTWIDGET_H #include #include #include #include #include "nmDataPerforation.h" class QPainter; class QMouseEvent; class QPaintEvent; class nmWxChartWidget : public QWidget { Q_OBJECT public: explicit nmWxChartWidget(QWidget *parent = 0); virtual ~nmWxChartWidget(); protected: virtual void paintEvent(QPaintEvent *event); virtual void mousePressEvent(QMouseEvent *event); virtual void mouseMoveEvent(QMouseEvent *event); virtual void mouseReleaseEvent(QMouseEvent *event); public: // 设置skin值 void setSkinValues(double bValue, double kValue); // 设置和获取线条位置 void setLinePositions(double x1, double y1, double x2, double y2); void getLinePositions(double& x1, double& y1, double& x2, double& y2) const; // 获取计算出的skin值 double getSkin0Value() const; double getDSkinDqValue() const; bool getLassoMode() const; void setLassoMode(bool enabled); // 重置线条到初始位置 void resetLinesToInitialPositions(); // 新增:设置流动段数据和流量数据 void setFlowSegmentData(const nmDataPerforation& perforationData); void setFlowData(const QVector& flowData); void setRawFlowData(const QVector& rawFlowData); void setSnapToRateChanges(bool snapToRateChanges); // 新增:更新×标记点数据 void updateCrossMarkPoints(); // 重置所有×标记点 void resetAllCrossMarks(); void updateCrossMarkPointsData(); // 只更新现有×标记点的数据 void regenerateCrossMarkPoints(); // 完全重新生成×标记点 // 计算方法 void calculateAverageValue(); bool shouldShowAverageLine(); void calculateDataRange(); // 动态计算坐标范围 signals: void skinValuesChanged(double skin0Value, double dSkinDqValue); void crossMarksFiltered(); // 当×标记被过滤后发出的信号 void lassoOperationCompleted(); // 新增:套索操作完成信号 private: // 绘制方法 void drawGrid(QPainter &painter); void drawAxes(QPainter &painter); void drawLine(QPainter &painter); void drawPoints(QPainter &painter); void drawAverageLine(QPainter &painter); // 绘制skin0线 void drawCrossMarks(QPainter &painter); // 新增:绘制×标记 // 坐标转换 QPointF dataToScreen(const QPointF &dataPoint); QPointF screenToData(const QPointF &screenPoint); // 交互相关 int findNearestPoint(const QPointF &screenPos); bool isNearLine(const QPointF &screenPos); // 辅助方法 void setLinePositionsFromSkinValues(double skin0Value, double dSkinDqValue); double getAverageFlowRateForSegment(double segmentStartTime, double segmentEndTime) const; // 最小二乘法拟合×标记点,返回拟合是否成功 bool fitLineToPoints(); // 计算拟合直线的参数 y = ax + b void calculateLinearRegression(const QVector& points, double& slope, double& intercept); // 根据拟合结果设置红色线的端点位置 void setFittedLinePositions(double slope, double intercept); // 套索相关方法 bool isPointInPolygon(const QPointF& point, const QPolygonF& polygon); void deleteSelectedCrossMarks(); void drawLasso(QPainter& painter); void clearLassoSelection(); void exitLassoMode(); // 常量定义 static const double POINT_RADIUS; static const double POINT_CLICK_RADIUS; static const double LINE_CLICK_DISTANCE; static const double CROSS_MARK_SIZE; // 新增:×标记大小 QVector linePoints; // 红线端点 QVector initialPositions; // 初始位置(现在动态计算) QVector crossMarkPoints; // 新增:×标记点位置 QVector crossMarkSegmentIndices; // 新增:×标记对应的段索引 QRectF dataRect; QRectF chartRect; bool isDragging; bool isDraggingLine; int dragPointIndex; QPointF lastMousePos; QPointF dragOffset; bool showAverageLine; // 是否显示skin0线 double averageValue; // skin0值(y轴截距) double dSkinDqValue; // 斜率 double selectionRangeX1; // 选择范围的左端点x值 double selectionRangeX2; // 选择范围的右端点x值 // 数据源 nmDataPerforation m_perforationData; QVector m_flowData; // 流量数据 QVector m_rawFlowData; bool m_snapToRateChanges; // 保存对齐到流量段的状态 // 套索选择相关 bool m_lassoMode; // 是否处于套索模式 bool m_lassoDrawing; // 是否正在绘制套索 QPolygonF m_lassoPath; // 套索路径 QVector m_selectedCrossMarkIndices; // 选中的×标记索引 bool m_hasPerformedInitialFit; // 是否已经进行过初始拟合 }; #endif // NMWXCHARTWIDGET_H