222 lines
6.4 KiB
C++
222 lines
6.4 KiB
C++
#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; }
|
||
|
||
/**
|
||
* @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();
|
||
|
||
/**
|
||
* @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;
|
||
bool m_measureDistanceEnabled;
|
||
QVector<SelectedPointInfo> m_selectedPoints;
|
||
SelectedLineInfo m_selectedLine;
|
||
static const int MAX_SELECTED_POINTS = 2;
|
||
|
||
// 列表高亮点(与选点功能区分)
|
||
bool m_hasListHighlightPoint;
|
||
QVector3D m_listHighlightPoint;
|
||
|
||
int m_colorIndex; // 颜色轮换索引
|
||
static const int COLOR_COUNT = 7; // 可用颜色数量
|
||
};
|
||
|
||
#endif // POINT_CLOUD_GL_WIDGET_H
|