#ifndef POINT_CLOUD_GL_WIDGET_H #define POINT_CLOUD_GL_WIDGET_H #include #include #include #include #include #include #include #include "PointCloudConverter.h" /** * @brief 点云显示颜色枚举 */ enum class PointCloudColor { White, Red, Green, Blue, Yellow, Cyan, Magenta, Original }; /** * @brief 选中的点信息 */ struct SelectedPointInfo { bool valid; size_t index; float x, y, z; int cloudIndex; int lineIndex; // 所属线索引 int pointIndexInLine; // 点在线中的索引 SelectedPointInfo() : valid(false), index(0), x(0), y(0), z(0), cloudIndex(-1), lineIndex(-1), pointIndexInLine(-1) {} }; /** * @brief 选线模式 */ enum class LineSelectMode { Vertical, // 纵向选线(同一条扫描线) Horizontal // 横向选线(所有线的相同索引点) }; /** * @brief 选中的线信息 */ struct SelectedLineInfo { bool valid; int cloudIndex; // 点云索引 int lineIndex; // 线索引(纵向选线时使用) int pointIndex; // 点索引(横向选线时使用) int pointCount; // 该线上的点数 LineSelectMode mode; // 选线模式 SelectedLineInfo() : valid(false), cloudIndex(-1), lineIndex(-1), pointIndex(-1), pointCount(0), mode(LineSelectMode::Vertical) {} }; /** * @brief 点云 OpenGL 渲染控件 */ class PointCloudGLWidget : public QOpenGLWidget, protected QOpenGLFunctions { Q_OBJECT public: explicit PointCloudGLWidget(QWidget* parent = nullptr); ~PointCloudGLWidget() override; void addPointCloud(const PointCloudXYZ& cloud, const QString& name = ""); void addPointCloud(const PointCloudXYZRGB& cloud, const QString& name = ""); void clearPointClouds(); void setPointCloudColor(PointCloudColor color); void setPointSize(float size); void resetView(); QVector getSelectedPoints() const { return m_selectedPoints; } SelectedLineInfo getSelectedLine() const { return m_selectedLine; } void clearSelectedPoints(); void clearSelectedLine(); float calculateDistance(const SelectedPointInfo& p1, const SelectedPointInfo& p2); /** * @brief 通过线索引选择线(纵向) */ bool selectLineByIndex(int lineIndex); /** * @brief 通过点索引选择横向线(所有线的相同索引点) */ bool selectHorizontalLineByIndex(int pointIndex); /** * @brief 设置选线模式 */ void setLineSelectMode(LineSelectMode mode) { m_lineSelectMode = mode; } /** * @brief 获取第一个点云的数据(用于旋转和保存) */ bool getFirstCloudData(PointCloudXYZ& cloud) const; /** * @brief 替换第一个点云(用于显示旋转后的数据) */ void replaceFirstCloud(const PointCloudXYZ& cloud, const QString& name); /** * @brief 获取点云数量 */ size_t getCloudCount() const { return m_pointClouds.size(); } signals: void pointSelected(const SelectedPointInfo& point); void twoPointsSelected(const SelectedPointInfo& p1, const SelectedPointInfo& p2, float distance); void lineSelected(const SelectedLineInfo& line); 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: void computeBoundingBox(); void setCurrentColor(PointCloudColor color); void setColorByIndex(int colorIndex); // 根据索引设置颜色 SelectedPointInfo pickPoint(int screenX, int screenY); void drawSelectedPoints(); void drawMeasurementLine(); void drawAxis(); void drawSelectedLine(); // 绘制选中的线 struct PointCloudData { std::vector vertices; std::vector colors; std::vector lineIndices; // 每个点所属的线索引 std::vector originalIndices; // 每个显示点在原始点云中的索引(用于计算原始index) bool hasColor; bool hasLineInfo; // 是否有线信息 QString name; int colorIndex; // 点云颜色索引 int totalLines; // 总线数 int pointsPerLine; // 每线点数(网格化点云) }; std::vector m_pointClouds; QMatrix4x4 m_projection; QMatrix4x4 m_view; QMatrix4x4 m_model; float m_distance; float m_rotationX; float m_rotationY; QVector3D m_center; QVector3D m_pan; QVector3D m_minBound; QVector3D m_maxBound; QPoint m_lastMousePos; bool m_leftButtonPressed; bool m_rightButtonPressed; bool m_middleButtonPressed; PointCloudColor m_currentColor; float m_pointSize; LineSelectMode m_lineSelectMode; QVector m_selectedPoints; SelectedLineInfo m_selectedLine; static const int MAX_SELECTED_POINTS = 2; int m_colorIndex; // 颜色轮换索引 static const int COLOR_COUNT = 7; // 可用颜色数量 }; #endif // POINT_CLOUD_GL_WIDGET_H