#ifndef MEASUREMENT_WIDGET_H #define MEASUREMENT_WIDGET_H #include #include #include #include #include #include #include class MeasurementWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: enum class DragHandle { None, Head, Tail, Body }; explicit MeasurementWidget(QWidget *parent = nullptr); ~MeasurementWidget() override; bool loadImage(const QString &filePath); void setImage(const QImage &image); bool isCalibrated() const { return m_isCalibrated; } double mmPerPixel() const { return m_mmPerPixel; } double measuredPx() const; double measuredMm() const; void resetLine(); void setLinePoints(const QPointF &head, const QPointF &tail); void setCalibrationMode(bool active); bool isCalibrationMode() const { return m_calibrationMode; } void applyPerspectiveCalibration(double realX, double realY); void cancelCalibrationMode(); void resetCalibration(); bool calibrateWithChessboard(int &innerCornersX, int &innerCornersY, double squareSizeMm); signals: void calibrationUpdated(double mmPerPx); void measurementUpdated(double px, double mm); void imageLoaded(int width, int height); void calibrationProgress(int percent); protected: void initializeGL() override; void resizeGL(int w, int h) override; void paintGL() override; void mousePressEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void wheelEvent(QWheelEvent *event) override; private: QPointF widgetToImageCoords(const QPointF &widgetPos) const; QPointF imageToWidgetCoords(const QPointF &imgPos) const; DragHandle hitTestLine(const QPointF &imgPos, const QPointF &head, const QPointF &tail) const; void drawLineOverlay(QPainter &painter, const QPointF &head, const QPointF &tail, const QColor &color); QImage m_image; QOpenGLTexture *m_texture = nullptr; bool m_textureNeedsUpdate = false; // Single measurement line in image coordinates QPointF m_head; QPointF m_tail; bool m_hasLine = false; // Calibration factor (mm per pixel) double m_mmPerPixel = 0.0; bool m_isCalibrated = false; // Homography matrix for perspective calibration QTransform m_homography; bool m_hasHomography = false; // Lens Calibration Matrix & Coefficients cv::Mat m_cameraMatrix; cv::Mat m_distCoeffs; bool m_hasLensCalibration = false; // Perspective Calibration state bool m_calibrationMode = false; QList m_calibCorners; int m_activeCornerIdx = -1; // Mouse interaction state DragHandle m_activeHandle = DragHandle::None; QPointF m_dragStartImgPos; QPointF m_dragStartHead; QPointF m_dragStartTail; // Viewport transform (zoom & pan) double m_zoomLevel = 1.0; QPointF m_panOffset = QPointF(0, 0); bool m_isPanning = false; QPoint m_lastMousePos; }; #endif // MEASUREMENT_WIDGET_H