2026-01-16 01:04:43 +08:00
|
|
|
|
#ifndef POINT_CLOUD_GL_WIDGET_H
|
|
|
|
|
|
#define POINT_CLOUD_GL_WIDGET_H
|
|
|
|
|
|
|
|
|
|
|
|
#include <QOpenGLWidget>
|
|
|
|
|
|
#include <QOpenGLFunctions>
|
|
|
|
|
|
#include <QMatrix4x4>
|
|
|
|
|
|
#include <QVector3D>
|
|
|
|
|
|
#include <QMouseEvent>
|
|
|
|
|
|
#include <QWheelEvent>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
|
|
#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<SelectedPointInfo> 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; }
|
|
|
|
|
|
|
2026-01-17 12:29:57 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置是否启用测距功能
|
|
|
|
|
|
*/
|
|
|
|
|
|
void setMeasureDistanceEnabled(bool enabled) { m_measureDistanceEnabled = enabled; }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取测距功能是否启用
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool isMeasureDistanceEnabled() const { return m_measureDistanceEnabled; }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取选中线上的所有点坐标
|
|
|
|
|
|
* @return 点坐标列表,每个元素为 (x, y, z)
|
|
|
|
|
|
*/
|
|
|
|
|
|
QVector<QVector3D> getSelectedLinePoints() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置列表高亮点(与选点功能区分)
|
|
|
|
|
|
* @param point 点坐标,如果为空则清除高亮
|
|
|
|
|
|
*/
|
|
|
|
|
|
void setListHighlightPoint(const QVector3D& point);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 清除列表高亮点
|
|
|
|
|
|
*/
|
|
|
|
|
|
void clearListHighlightPoint();
|
|
|
|
|
|
|
2026-01-16 01:04:43 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @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<float> vertices;
|
|
|
|
|
|
std::vector<float> colors;
|
|
|
|
|
|
std::vector<int> lineIndices; // 每个点所属的线索引
|
|
|
|
|
|
std::vector<int> originalIndices; // 每个显示点在原始点云中的索引(用于计算原始index)
|
|
|
|
|
|
bool hasColor;
|
|
|
|
|
|
bool hasLineInfo; // 是否有线信息
|
|
|
|
|
|
QString name;
|
|
|
|
|
|
int colorIndex; // 点云颜色索引
|
|
|
|
|
|
int totalLines; // 总线数
|
|
|
|
|
|
int pointsPerLine; // 每线点数(网格化点云)
|
|
|
|
|
|
};
|
|
|
|
|
|
std::vector<PointCloudData> 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;
|
2026-01-17 12:29:57 +08:00
|
|
|
|
bool m_measureDistanceEnabled;
|
2026-01-16 01:04:43 +08:00
|
|
|
|
QVector<SelectedPointInfo> m_selectedPoints;
|
|
|
|
|
|
SelectedLineInfo m_selectedLine;
|
|
|
|
|
|
static const int MAX_SELECTED_POINTS = 2;
|
|
|
|
|
|
|
2026-01-17 12:29:57 +08:00
|
|
|
|
// 列表高亮点(与选点功能区分)
|
|
|
|
|
|
bool m_hasListHighlightPoint;
|
|
|
|
|
|
QVector3D m_listHighlightPoint;
|
|
|
|
|
|
|
2026-01-16 01:04:43 +08:00
|
|
|
|
int m_colorIndex; // 颜色轮换索引
|
|
|
|
|
|
static const int COLOR_COUNT = 7; // 可用颜色数量
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#endif // POINT_CLOUD_GL_WIDGET_H
|