#ifndef WELD_OPENGL_WIDGET_H #define WELD_OPENGL_WIDGET_H #include #include #include #include #include #include class WeldOpenGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: enum class DragHandle { None, Head, Tail, Body }; explicit WeldOpenGLWidget(QWidget *parent = nullptr); ~WeldOpenGLWidget() override; bool loadImage(const QString &filePath); void setImage(const QImage &image); void calibrateWithCurrentLine(double knownMm); 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); signals: void calibrationUpdated(double mmPerPx); void measurementUpdated(double px, double mm); void imageLoaded(int width, int height); 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; // 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 // WELD_OPENGL_WIDGET_H